diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d1571a..cb971fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,9 +20,14 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install pytest pytest-cov coveralls + python -m pip install pytest pytest-cov coveralls ruff pip install -r requirements.txt + - name: Check code style + run: | + ruff format --check . + ruff check . + - name: Test with pytest run: | pytest --cov-report term-missing:skip-covered --cov=geodepy geodepy/tests/ diff --git a/Standalone/AG2020_SubGridExtract.py b/Standalone/AG2020_SubGridExtract.py index a6a1252..75a5321 100644 --- a/Standalone/AG2020_SubGridExtract.py +++ b/Standalone/AG2020_SubGridExtract.py @@ -4,6 +4,7 @@ @author: u84157 """ + # Example input # North Latitude (S): 10 # South Latitude (S): 25 @@ -12,25 +13,33 @@ # Directory and file name of AUSGeoid2020 grid: C:\AusGeoidExtract\AUSGeoid2020_20170908_win.dat # Output Directory and file name of sub-grid: C:\AusGeoidExtract\AUSGeoid2020_20170908_win_SUBGRID.dat # Get user to input the extents of the file they wish to extract -Latmin = input('North Latitude (S): ') -Latmax = input('South Latitude (S): ') -Longmin = input('West Longitude (E): ') -Longmax = input('East Longitude (E): ') +Latmin = input("North Latitude (S): ") +Latmax = input("South Latitude (S): ") +Longmin = input("West Longitude (E): ") +Longmax = input("East Longitude (E): ") # Get user to specify input/out files -filename = input('Directory and file name of AUSGeoid2020 grid: ') +filename = input("Directory and file name of AUSGeoid2020 grid: ") f = open(filename) linestr = f.readline() -filenameout = input('Output Directory and file name of sub-grid: ') +filenameout = input("Output Directory and file name of sub-grid: ") fout = open(filenameout, "w") fout.writelines(linestr) # Run through each line of the input file and extract the relevant lines print("Running") for linestr in f.readlines(): - Latk = float(linestr[14:16])+float(linestr[17:19])/60+float(linestr[17:19])/3600 - Longk = float(linestr[28:31])+float(linestr[32:35])/60+float(linestr[36:41])/3600 + Latk = ( + float(linestr[14:16]) + + float(linestr[17:19]) / 60 + + float(linestr[17:19]) / 3600 + ) + Longk = ( + float(linestr[28:31]) + + float(linestr[32:35]) / 60 + + float(linestr[36:41]) / 3600 + ) if Latk >= Latmin and Latk <= Latmax and Longk >= Longmin and Longk <= Longmax: fout.writelines(linestr) # Close the files f.close fout.close -print("Done :)") \ No newline at end of file +print("Done :)") diff --git a/Standalone/mga2gda.py b/Standalone/mga2gda.py index 1f1f8bd..af6688b 100644 --- a/Standalone/mga2gda.py +++ b/Standalone/mga2gda.py @@ -7,104 +7,81 @@ # Author: Josh Batchelor - -from decimal import * -from math import sqrt, log, degrees, sin, cos, sinh, cosh, atan -import os import argparse import csv +import os +from decimal import * +from math import atan, cos, cosh, degrees, log, sin, sinh, sqrt # Universal Transverse Mercator Projection Parameters -proj = [6378137, Decimal('298.25722210088'), 500000, - 10000000, Decimal('0.9996'), 6, -177] +proj = [ + 6378137, + Decimal("298.25722210088"), + 500000, + 10000000, + Decimal("0.9996"), + 6, + -177, +] # Ellipsoidal Constants f = 1 / proj[1] semi_maj = proj[0] semi_min = float(semi_maj * (1 - f)) ecc1sq = float(f * (2 - f)) -ecc2sq = float(ecc1sq/(1 - ecc1sq)) +ecc2sq = float(ecc1sq / (1 - ecc1sq)) ecc1 = sqrt(ecc1sq) n = f / (2 - f) n = float(n) -n2 = n ** 2 +n2 = n**2 # Rectifying Radius (Horner Form) -A = proj[0] / (1 + n) * ((n2 * - (n2 * - (n2 * - (25 * n2 + 64) - + 256) - + 4096) - + 16384) - / 16384.) +A1 = n2 * (25 * n2 + 64) + 256 +A2 = n2 * A1 + 4096 +A3 = n2 * A2 + 16384 +A = proj[0] / (1 + n) * (A3 / 16384.0) # Beta Coefficients (Horner Form) -b2 = ((n * - (n * - (n * - (n * - (n * - (n * - ((37845269 - 31777436 * n) - 43097152) - + 42865200) - + 752640) - - 104428800) - + 180633600) - - 135475200)) - / 270950400.) - -b4 = ((n ** 2 * - (n * - (n * - (n * - (n * - ((-24749483 * n - 14930208) * n + 100683990) - - 152616960) - + 105719040) - - 23224320) - - 7257600)) - / 348364800.) - -b6 = ((n ** 3 * - (n * - (n * - (n * - (n * - (232468668 * n - 101880889) - - 39205760) - + 29795040) - + 28131840) - - 22619520)) - / 638668800.) - -b8 = ((n ** 4 * - (n * - (n * - ((-324154477 * n - 1433121792) * n + 876745056) - + 167270400) - - 208945440)) - / 7664025600.) - -b10 = ((n ** 5 * - (n * - (n * - (312227409 - 457888660 * n) - + 67920528) - - 70779852)) - / 2490808320.) - -b12 = ((n ** 6 * - (n * - (19841813847 * n + 3665348512) - - 3758062126)) - / 116237721600.) - -b14 = ((n ** 7 * - (1989295244 * n - 1979471673)) - / 49816166400.) - -b16 = ((-191773887257 * n ** 8) / 3719607091200.) +b2a = (37845269 - 31777436 * n) - 43097152 +b2b = n * b2a + 42865200 +b2c = n * b2b + 752640 +b2d = n * b2c - 104428800 +b2e = n * b2d + 180633600 +b2f = n * b2e - 135475200 +b2 = n * b2f / 270950400.0 + +b4a = (-24749483 * n - 14930208) * n + 100683990 +b4b = n * b4a - 152616960 +b4c = n * b4b + 105719040 +b4d = n * b4c - 23224320 +b4e = n * b4d - 7257600 +b4 = n**2 * b4e / 348364800.0 + +b6a = 232468668 * n - 101880889 +b6b = n * b6a - 39205760 +b6c = n * b6b + 29795040 +b6d = n * b6c + 28131840 +b6e = n * b6d - 22619520 +b6 = n**3 * b6e / 638668800.0 + +b8a = (-324154477 * n - 1433121792) * n + 876745056 +b8b = n * b8a + 167270400 +b8c = n * b8b - 208945440 +b8 = n**4 * b8c / 7664025600.0 + +b10a = 312227409 - 457888660 * n +b10b = n * b10a + 67920528 +b10c = n * b10b - 70779852 +b10 = n**5 * b10c / 2490808320.0 + +b12a = 19841813847 * n + 3665348512 +b12b = n * b12a - 3758062126 +b12 = n**6 * b12b / 116237721600.0 + +b14a = 1989295244 * n - 1979471673 +b14 = n**7 * b14a / 49816166400.0 + +b16 = (-191773887257 * n**8) / 3719607091200.0 def dd2dms(dd): @@ -154,16 +131,23 @@ def grid2geo(zone, easting, northing): # Finding t using Newtons Method def sigma(t): sigma = sinh( - ecc1 * 0.5 * log((1 + ((ecc1 * t) / (sqrt(1 + t ** 2)))) / (1 - ((ecc1 * t) / (sqrt(1 + t ** 2)))))) + ecc1 + * 0.5 + * log( + (1 + ((ecc1 * t) / (sqrt(1 + t**2)))) + / (1 - ((ecc1 * t) / (sqrt(1 + t**2)))) + ) + ) return sigma def ftn(t): - ftn = t * sqrt(1 + (sigma(t)) ** 2) - sigma(t) * sqrt(1 + t ** 2) - t1 + ftn = t * sqrt(1 + (sigma(t)) ** 2) - sigma(t) * sqrt(1 + t**2) - t1 return ftn def f1tn(t): - f1tn = (sqrt(1 + (sigma(t)) ** 2) * sqrt(1 + t ** 2) - sigma(t) * t) * ( - ((1 - float(ecc1sq)) * sqrt(1 + t ** 2)) / (1 + (1 - float(ecc1sq)) * t ** 2)) + f1tn = (sqrt(1 + (sigma(t)) ** 2) * sqrt(1 + t**2) - sigma(t) * t) * ( + ((1 - float(ecc1sq)) * sqrt(1 + t**2)) / (1 + (1 - float(ecc1sq)) * t**2) + ) return f1tn t2 = t1 - (ftn(t1)) / (f1tn(t1)) @@ -196,9 +180,9 @@ def grid2geoio(fn): 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', newline='') + fn_part = os.path.splitext(fn) + fn_out = fn_part[0] + "_out" + fn_part[1] + outfile = open(fn_out, "w", newline="") # Write Output outfilewriter = csv.writer(outfile) # outfilewriter.writerow(['Pt', 'Latitude', 'Longitude']) @@ -216,15 +200,17 @@ def grid2geoio(fn): # Close Files outfile.close() csvfile.close() - return 'Output saved as ' + str(fn_out) + return "Output saved as " + str(fn_out) if __name__ == "__main__": - parser = argparse.ArgumentParser(description='Batch Converter of Map Grid of Australia grid co-ordinates to ' - 'Geodetic Datum of Australia geographic co-ordinates. Files must ' - 'be .csv and of the format Pt ID, Zone, Easting, Northing with no ' - 'header line.') - parser.add_argument('f', metavar='--file', type=str, help='Input Filename') + parser = argparse.ArgumentParser( + description="Batch Converter of Map Grid of Australia grid co-ordinates to " + "Geodetic Datum of Australia geographic co-ordinates. Files must " + "be .csv and of the format Pt ID, Zone, Easting, Northing with no " + "header line." + ) + parser.add_argument("f", metavar="--file", type=str, help="Input Filename") args = parser.parse_args() fn = args.f diff --git a/api/app.py b/api/app.py index 70f72ba..a1d6243 100644 --- a/api/app.py +++ b/api/app.py @@ -1,82 +1,81 @@ -from flask import Flask -from flask import jsonify -from flask import request -from flask import url_for -from geodepy.geodesy import vincdir -from geodepy.geodesy import vincinv -from geodepy.convert import hp2dec -from geodepy.convert import dec2hp +from flask import Flask, jsonify, request, url_for +from geodepy.convert import dec2hp, hp2dec +from geodepy.geodesy import vincdir, vincinv app = Flask(__name__) angle_type_to_dd = { - 'dd': lambda x: x, - 'dms': hp2dec, + "dd": lambda x: x, + "dms": hp2dec, } dd_to_angle_type = { - 'dd': lambda x: x, - 'dms': dec2hp, + "dd": lambda x: x, + "dms": dec2hp, } -@app.route('/') +@app.route("/") def list_routes(): - return str(tuple(url_for(rule.endpoint) for rule in - app.url_map.iter_rules() if rule.endpoint != 'static')) + return str( + tuple( + url_for(rule.endpoint) + for rule in app.url_map.iter_rules() + if rule.endpoint != "static" + ) + ) -@app.route('/vincinv') +@app.route("/vincinv") def handle_vincinv(): - from_angle_type = request.args.get('from_angle_type', default='dd') - to_angle_type = request.args.get('to_angle_type', default='dd') - lat1 = request.args.get('lat1', type=float) - lon1 = request.args.get('lon1', type=float) - lat2 = request.args.get('lat2', type=float) - lon2 = request.args.get('lon2', type=float) + from_angle_type = request.args.get("from_angle_type", default="dd") + to_angle_type = request.args.get("to_angle_type", default="dd") + lat1 = request.args.get("lat1", type=float) + lon1 = request.args.get("lon1", type=float) + lat2 = request.args.get("lat2", type=float) + lon2 = request.args.get("lon2", type=float) dd = angle_type_to_dd[from_angle_type] lat1_dd, lon1_dd, lat2_dd, lon2_dd = dd(lat1), dd(lon1), dd(lat2), dd(lon2) - ell_dist, azimuth1to2_dd, azimuth2to1_dd = vincinv(lat1_dd, lon1_dd, - lat2_dd, lon2_dd) + ell_dist, azimuth1to2_dd, azimuth2to1_dd = vincinv( + lat1_dd, lon1_dd, lat2_dd, lon2_dd + ) angle = dd_to_angle_type[to_angle_type] azimuth1to2, azimuth2to1 = angle(azimuth1to2_dd), angle(azimuth2to1_dd) - return jsonify({ - 'ell_dist': ell_dist, - 'azimuth1to2': azimuth1to2, - 'azimuth2to1': azimuth2to1 - }), 200 + return jsonify( + {"ell_dist": ell_dist, "azimuth1to2": azimuth1to2, "azimuth2to1": azimuth2to1} + ), 200 -@app.route('/vincdir') +@app.route("/vincdir") def handle_vincdir(): - from_angle_type = request.args.get('from_angle_type', default='dd') - to_angle_type = request.args.get('to_angle_type', default='dd') - lat1 = request.args.get('lat1', type=float) - lon1 = request.args.get('lon1', type=float) - azimuth1to2 = request.args.get('azimuth1to2', type=float) - ell_dist = request.args.get('ell_dist', type=float) + from_angle_type = request.args.get("from_angle_type", default="dd") + to_angle_type = request.args.get("to_angle_type", default="dd") + lat1 = request.args.get("lat1", type=float) + lon1 = request.args.get("lon1", type=float) + azimuth1to2 = request.args.get("azimuth1to2", type=float) + ell_dist = request.args.get("ell_dist", type=float) dd = angle_type_to_dd[from_angle_type] lat1_dd, lon1_dd, azimuth1to2_dd = dd(lat1), dd(lon1), dd(azimuth1to2) - lat2_dd, lon2_dd, azimuth2to1_dd = vincdir(lat1_dd, lon1_dd, - azimuth1to2_dd, ell_dist) + lat2_dd, lon2_dd, azimuth2to1_dd = vincdir( + lat1_dd, lon1_dd, azimuth1to2_dd, ell_dist + ) angle_type = dd_to_angle_type[to_angle_type] - lat2, lon2, azimuth2to1 = angle_type(lat2_dd), angle_type(lon2_dd),\ - angle_type(azimuth2to1_dd) + lat2, lon2, azimuth2to1 = ( + angle_type(lat2_dd), + angle_type(lon2_dd), + angle_type(azimuth2to1_dd), + ) - return jsonify({ - 'lat2': lat2, - 'lon2': lon2, - 'azimuth2to1': azimuth2to1 - }), 200 + return jsonify({"lat2": lat2, "lon2": lon2, "azimuth2to1": azimuth2to1}), 200 -if __name__ == '__main__': +if __name__ == "__main__": app.run() diff --git a/api/test_app.py b/api/test_app.py index c85bad0..5b63dcc 100644 --- a/api/test_app.py +++ b/api/test_app.py @@ -1,43 +1,42 @@ +import json import unittest + from api.app import app -import json class TestAPI(unittest.TestCase): def test_vincinv(self): query = { - 'lat1': -37.57037203, - 'lon1': 144.25295244, - 'lat2': -37.39101561, - 'lon2': 143.5535383, - 'from_angle_type': 'dms', - 'to_angle_type': 'dms' + "lat1": -37.57037203, + "lon1": 144.25295244, + "lat2": -37.39101561, + "lon2": 143.5535383, + "from_angle_type": "dms", + "to_angle_type": "dms", } expected_response = { - 'ell_dist': 54972.289, - 'azimuth1to2': 306.52053231124, - 'azimuth2to1': 127.10250207968 + "ell_dist": 54972.289, + "azimuth1to2": 306.52053231124, + "azimuth2to1": 127.10250207968, } - response = app.test_client().get('/vincinv', query_string=query) + response = app.test_client().get("/vincinv", query_string=query) self.assertEqual(json.loads(response.data), expected_response) def test_vincdir(self): query = { - 'lat1': -37.57037203, - 'lon1': 144.25295244, - 'azimuth1to2': 306.520537, - 'ell_dist': 54972.271, - 'from_angle_type': 'dms', - 'to_angle_type': 'dms' + "lat1": -37.57037203, + "lon1": 144.25295244, + "azimuth1to2": 306.520537, + "ell_dist": 54972.271, + "from_angle_type": "dms", + "to_angle_type": "dms", } expected_response = { - 'lat2': -37.3910156124268, - 'lon2': 143.5535383883988, - 'azimuth2to1': 127.10250671432 + "lat2": -37.3910156124268, + "lon2": 143.5535383883988, + "azimuth2to1": 127.10250671432, } - response = app.test_client().get('/vincdir', query_string=query) + response = app.test_client().get("/vincdir", query_string=query) self.assertEqual(json.loads(response.data), expected_response) - - diff --git a/docs/community/contributing.rst b/docs/community/contributing.rst index 8e53c49..5bc8606 100644 --- a/docs/community/contributing.rst +++ b/docs/community/contributing.rst @@ -17,9 +17,15 @@ Please read it to understand the expectations for behavior when contributing to Coding Style Guide ------------------ -GeodePy uses `Black `_ to keep coding style consistent while still being accessable to all. -Black uses `PEP 8 `_ coding style, an industry standard for python code. Before -any commits to GeodePy ensure Black has been used. +GeodePy uses `Ruff `_ to keep Python formatting and import ordering consistent. Ruff is +configured in ``pyproject.toml`` and is checked in continuous integration. + +Before committing Python changes, run: + +.. code:: bash + + ruff format . + ruff check . .. _code: @@ -31,7 +37,7 @@ When contributing code please follow these steps: 1. Fork the repository on `GitHub `_. 2. Run tests on current code to ensure it works on your system (See :ref:`Testing `) 3. Create tests that demonstrate your bug or feature. -4. Make changes, ensuring coding sytle guide is abided by. +4. Make changes, ensuring the coding style guide is followed. 5. Run all tests again including one added and ensure all tests pass. 6. Send a Github Pull Request to the repository's **master** branch @@ -59,4 +65,4 @@ Feature Requests ---------------- If you believe a feature is missing, feel free to raise a feature request. Keep in mind that being an open source project requested features may -or may not be implemented. If there is a feature you really need consider creating it yourself and :ref:`submitting the code `. \ No newline at end of file +or may not be implemented. If there is a feature you really need consider creating it yourself and :ref:`submitting the code `. diff --git a/docs/conf.py b/docs/conf.py index 97e241e..7e04c55 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -14,23 +14,28 @@ # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information -project = 'GeodePy' -copyright = '2025, Geoscience Australia' -author = 'Geoscience Australia' -release = '0.6.0' +project = "GeodePy" +copyright = "2025, Geoscience Australia" +author = "Geoscience Australia" +release = "0.6.0" # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration -extensions = ["sphinx.ext.autodoc", "sphinx.ext.napoleon", "sphinx.ext.viewcode",'sphinx_copybutton'] +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.napoleon", + "sphinx.ext.viewcode", + "sphinx_copybutton", +] -templates_path = ['_templates'] -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +templates_path = ["_templates"] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] html_sidebars = { "**": [ - "sidebar/brand.html", # Logo - "sidebar/extra.html", # Custom tagline + badge + "sidebar/brand.html", # Logo + "sidebar/extra.html", # Custom tagline + badge "sidebar/scroll-start.html", "sidebar/search.html", "sidebar/navigation.html", @@ -38,13 +43,13 @@ ] } -autoclass_content = 'both' +autoclass_content = "both" # -- Options for HTML output ------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output -html_theme = 'furo' -html_static_path = ['_static'] +html_theme = "furo" +html_static_path = ["_static"] html_theme_options = { "light_logo": "geodepy-logo-light.png", "dark_logo": "geodepy-logo-dark.png", @@ -52,15 +57,17 @@ } html_css_files = [ - 'custom.css', + "custom.css", ] html_js_files = [ - 'custom.js', + "custom.js", ] -html_favicon = '_static/favicon.ico' +html_favicon = "_static/favicon.ico" em_dash_char = chr(8212) -html_title = "GeodePy: Geodesy in Python " + em_dash_char+ " v" + release + " Documentation" +html_title = ( + "GeodePy: Geodesy in Python " + em_dash_char + " v" + release + " Documentation" +) ogp_site_name = "GeodePy: Geodesy in Python" html_extra_path = ["_static/robots.txt", "_static/sitemap.xml"] -autodoc_mock_imports = ["osgeo","gdal","GDAL"] \ No newline at end of file +autodoc_mock_imports = ["osgeo", "gdal", "GDAL"] diff --git a/geodepy/angles.py b/geodepy/angles.py index 96532e3..4c6b83e 100644 --- a/geodepy/angles.py +++ b/geodepy/angles.py @@ -59,20 +59,20 @@ def __add__(self, other): try: return DECAngle(self.dec() + other.dec()) except AttributeError: - raise TypeError("Can only add Angle objects with .dec() method " "together") + raise TypeError("Can only add Angle objects with .dec() method together") def __radd__(self, other): try: return DECAngle(other.dec() + self.dec()) except AttributeError: - raise TypeError("Can only add Angle objects with .dec() method " "together") + raise TypeError("Can only add Angle objects with .dec() method together") def __sub__(self, other): try: return DECAngle(self.dec() - other.dec()) except AttributeError: raise TypeError( - "Can only subtract Angle objects with .dec() method" " together" + "Can only subtract Angle objects with .dec() method together" ) def __rsub__(self, other): @@ -80,7 +80,7 @@ def __rsub__(self, other): return DECAngle(other.dec() - self.dec()) except AttributeError: raise TypeError( - "Can only subtract Angle objects with .dec() method" " together" + "Can only subtract Angle objects with .dec() method together" ) def __mul__(self, other): @@ -88,7 +88,7 @@ def __mul__(self, other): return DECAngle(self.dec() * other) except TypeError: raise TypeError( - "Multiply only defined between DECAngle Object " "and Int or Float" + "Multiply only defined between DECAngle Object and Int or Float" ) def __rmul__(self, other): @@ -96,7 +96,7 @@ def __rmul__(self, other): return DECAngle(other * self.dec()) except TypeError: raise TypeError( - "Multiply only defined between DECAngle Object " "and Int or Float" + "Multiply only defined between DECAngle Object and Int or Float" ) def __truediv__(self, other): @@ -104,7 +104,7 @@ def __truediv__(self, other): return DECAngle(self.dec() / other) except TypeError: raise TypeError( - "Division only defined between DECAngle Object " "and Int or Float" + "Division only defined between DECAngle Object and Int or Float" ) def __abs__(self): @@ -245,20 +245,20 @@ def __add__(self, other): try: return HPAngle(dec2hp(self.dec() + other.dec())) except AttributeError: - raise TypeError("Can only add Angle objects with .dec() method " "together") + raise TypeError("Can only add Angle objects with .dec() method together") def __radd__(self, other): try: return HPAngle(dec2hp(other.dec() + self.dec())) except AttributeError: - raise TypeError("Can only add Angle objects with .dec() method " "together") + raise TypeError("Can only add Angle objects with .dec() method together") def __sub__(self, other): try: return HPAngle(dec2hp(self.dec() - other.dec())) except AttributeError: raise TypeError( - "Can only subtract Angle objects with .dec() method" " together" + "Can only subtract Angle objects with .dec() method together" ) def __rsub__(self, other): @@ -266,7 +266,7 @@ def __rsub__(self, other): return HPAngle(dec2hp(other.dec() - self.dec())) except AttributeError: raise TypeError( - "Can only subtract Angle objects with .dec() method" " together" + "Can only subtract Angle objects with .dec() method together" ) def __mul__(self, other): @@ -274,7 +274,7 @@ def __mul__(self, other): return HPAngle(dec2hp(self.dec() * other)) except TypeError: raise TypeError( - "Multiply only defined between Angle objects and " "Int or Float" + "Multiply only defined between Angle objects and Int or Float" ) def __rmul__(self, other): @@ -282,7 +282,7 @@ def __rmul__(self, other): return HPAngle(dec2hp(other * self.dec())) except TypeError: raise TypeError( - "Multiply only defined between Angle objects and " "Int or Float" + "Multiply only defined between Angle objects and Int or Float" ) def __truediv__(self, other): @@ -290,7 +290,7 @@ def __truediv__(self, other): return HPAngle(dec2hp(self.dec() / other)) except TypeError: raise TypeError( - "Division only defined between HPAngle objects " "and Int or Float" + "Division only defined between HPAngle objects and Int or Float" ) def __abs__(self): @@ -420,20 +420,20 @@ def __add__(self, other): try: return GONAngle(dec2gon(self.dec() + other.dec())) except AttributeError: - raise TypeError("Can only add Angle objects with .dec() method " "together") + raise TypeError("Can only add Angle objects with .dec() method together") def __radd__(self, other): try: return GONAngle(dec2gon(other.dec() + self.dec())) except AttributeError: - raise TypeError("Can only add Angle objects with .dec() method " "together") + raise TypeError("Can only add Angle objects with .dec() method together") def __sub__(self, other): try: return GONAngle(dec2gon(self.dec() - other.dec())) except AttributeError: raise TypeError( - "Can only subtract Angle objects with .dec() method" " together" + "Can only subtract Angle objects with .dec() method together" ) def __rsub__(self, other): @@ -441,7 +441,7 @@ def __rsub__(self, other): return GONAngle(dec2gon(other.dec() - self.dec())) except AttributeError: raise TypeError( - "Can only subtract Angle objects with .dec() method" " together" + "Can only subtract Angle objects with .dec() method together" ) def __mul__(self, other): @@ -449,7 +449,7 @@ def __mul__(self, other): return GONAngle(dec2gon(self.dec() * other)) except TypeError: raise TypeError( - "Multiply only defined between Angle objects and " "Int or Float" + "Multiply only defined between Angle objects and Int or Float" ) def __rmul__(self, other): @@ -457,7 +457,7 @@ def __rmul__(self, other): return GONAngle(dec2gon(other * self.dec())) except TypeError: raise TypeError( - "Multiply only defined between Angle objects and " "Int or Float" + "Multiply only defined between Angle objects and Int or Float" ) def __truediv__(self, other): @@ -465,7 +465,7 @@ def __truediv__(self, other): return GONAngle(dec2gon(self.dec() / other)) except TypeError: raise TypeError( - "Division only defined between HPAngle objects " "and Int or Float" + "Division only defined between HPAngle objects and Int or Float" ) def __abs__(self): @@ -634,20 +634,20 @@ def __add__(self, other): try: return dec2dms(self.dec() + other.dec()) except AttributeError: - raise TypeError("Can only add Angle objects with .dec() method " "together") + raise TypeError("Can only add Angle objects with .dec() method together") def __radd__(self, other): try: return dec2dms(other.dec() + self.dec()) except AttributeError: - raise TypeError("Can only add Angle objects with .dec() method " "together") + raise TypeError("Can only add Angle objects with .dec() method together") def __sub__(self, other): try: return dec2dms(self.dec() - other.dec()) except AttributeError: raise TypeError( - "Can only subtract Angle objects with .dec() method" " together" + "Can only subtract Angle objects with .dec() method together" ) def __rsub__(self, other): @@ -655,7 +655,7 @@ def __rsub__(self, other): return dec2dms(other.dec() - self.dec()) except AttributeError: raise TypeError( - "Can only subtract Angle objects with .dec() method" " together" + "Can only subtract Angle objects with .dec() method together" ) def __mul__(self, other): @@ -663,7 +663,7 @@ def __mul__(self, other): return dec2dms(self.dec() * other) except TypeError: raise TypeError( - "Multiply only defined between DMSAngle Object " "and Int or Float" + "Multiply only defined between DMSAngle Object and Int or Float" ) def __rmul__(self, other): @@ -671,7 +671,7 @@ def __rmul__(self, other): return dec2dms(other * self.dec()) except TypeError: raise TypeError( - "Multiply only defined between DMSAngle Object " "and Int or Float" + "Multiply only defined between DMSAngle Object and Int or Float" ) def __truediv__(self, other): @@ -679,7 +679,7 @@ def __truediv__(self, other): return dec2dms(self.dec() / other) except TypeError: raise TypeError( - "Division only defined between DMSAngle Object " "and Int or Float" + "Division only defined between DMSAngle Object and Int or Float" ) def __abs__(self): @@ -855,20 +855,20 @@ def __add__(self, other): try: return dec2ddm(self.dec() + other.dec()) except AttributeError: - raise TypeError("Can only add Angle objects with .dec() method " "together") + raise TypeError("Can only add Angle objects with .dec() method together") def __radd__(self, other): try: return dec2ddm(other.dec() + self.dec()) except AttributeError: - raise TypeError("Can only add Angle objects with .dec() method " "together") + raise TypeError("Can only add Angle objects with .dec() method together") def __sub__(self, other): try: return dec2ddm(self.dec() - other.dec()) except AttributeError: raise TypeError( - "Can only subtract Angle objects with .dec() method" " together" + "Can only subtract Angle objects with .dec() method together" ) def __rsub__(self, other): @@ -876,7 +876,7 @@ def __rsub__(self, other): return dec2ddm(other.dec() - self.dec()) except AttributeError: raise TypeError( - "Can only subtract Angle objects with .dec() method" " together" + "Can only subtract Angle objects with .dec() method together" ) def __mul__(self, other): @@ -884,7 +884,7 @@ def __mul__(self, other): return dec2ddm(self.dec() * other) except TypeError: raise TypeError( - "Multiply only defined between DMSAngle Object " "and Int or Float" + "Multiply only defined between DMSAngle Object and Int or Float" ) def __rmul__(self, other): @@ -892,7 +892,7 @@ def __rmul__(self, other): return dec2ddm(other * self.dec()) except TypeError: raise TypeError( - "Multiply only defined between DMSAngle Object " "and Int or Float" + "Multiply only defined between DMSAngle Object and Int or Float" ) def __truediv__(self, other): @@ -900,7 +900,7 @@ def __truediv__(self, other): return dec2ddm(self.dec() / other) except TypeError: raise TypeError( - "Division only defined between DMSAngle Object " "and Int or Float" + "Division only defined between DMSAngle Object and Int or Float" ) def __abs__(self): @@ -1146,13 +1146,11 @@ def hp2dec(hp): hp = float(hp) hp_deg_str, hp_mmss_str = f"{hp:.13f}".split(".") if int(hp_mmss_str[0]) > 5: - raise ValueError( - f"Invalid HP Notation: 1st decimal place greater " f"than 5: {hp}" - ) + raise ValueError(f"Invalid HP Notation: 1st decimal place greater than 5: {hp}") if len(hp_mmss_str) > 2: if int(hp_mmss_str[2]) > 5: raise ValueError( - f"Invalid HP Notation: 3rd decimal place greater " f"than 5: {hp}" + f"Invalid HP Notation: 3rd decimal place greater than 5: {hp}" ) # parse string to avoid precision problems with floating point ops and base 10 numbers deg = abs(int(hp_deg_str)) diff --git a/geodepy/constants.py b/geodepy/constants.py index bf2bf75..b504ec4 100644 --- a/geodepy/constants.py +++ b/geodepy/constants.py @@ -5,8 +5,8 @@ Constants Module """ -from math import sqrt from datetime import date +from math import sqrt c_vac = 299792.458 k_0 = 0.9996 @@ -15,13 +15,13 @@ # Ellipsoid constants class Ellipsoid(object): def __init__(self, semimaj, inversef): - ''' + """ Ellipsoid Parameters :param semimaj: Semi-major axis (m) :param inversef: Inverse flattening - ''' + """ self.semimaj = semimaj self.inversef = inversef self.f = 1 / self.inversef @@ -84,7 +84,6 @@ def __init__(self, falseeast, falsenorth, cmscale, zonewidth, initialcm): # Helmert 14 parameter transformation class Transformation(object): def __init__( - self, from_datum, to_datum, @@ -309,7 +308,7 @@ def __init__( sd_d_ry=None, sd_d_rz=None, ): - ''' + """ Transformation Standard Deviation Parameters :param sd_tx: one-sigma uncertainty of tx (m) @@ -327,7 +326,7 @@ def __init__( :param sd_d_ry: one-sigma uncertainty of d_ry (arcsec/yr) :param sd_d_rz: one-sigma uncertainty of d_rz (arcsec/yr) - ''' + """ self.sd_tx = sd_tx # one-sigma uncertainty of tx (m) self.sd_ty = sd_ty # one-sigma uncertainty of ty (m) self.sd_tz = sd_tz # one-sigma uncertainty of tz (m) @@ -362,13 +361,13 @@ def iers2trans( d_rx, d_ry, d_rz, - tf_sd=None + tf_sd=None, ): """ Used to convert IERS transformation parameters into GeodePy Transformation class parameters. Note: All rotation and delta rotation terms have the sign change applied. - + :param itrf_from: ITRF realization transforming from :param itrf_to: ITRF realization transforming to :param ref_epoch: Reference epoch (YYYY.DOY) @@ -407,9 +406,10 @@ class parameters. round(-d_rx / 1000, 8), round(-d_ry / 1000, 8), round(-d_rz / 1000, 8), - tf_sd=tf_sd + tf_sd=tf_sd, ) + def iers2transSD( sd_tx=None, sd_ty=None, @@ -430,7 +430,7 @@ def iers2transSD( Used to convert IERS transformation standard deviation parameters into GeodePy TransformationSD class parameters. Note: All rotation and delta rotation terms have the sign change applied. - + :param sd_tx: one-sigma uncertainty of tx (mm) :param sd_ty: one-sigma uncertainty of ty (mm) :param sd_tz: one-sigma uncertainty of tz (mm) @@ -964,7 +964,7 @@ class parameters. sd_d_sc=0.03, sd_d_rx=0.007, sd_d_ry=0.006, - sd_d_rz=0.007 + sd_d_rz=0.007, ) itrf2020_to_itrf2014 = iers2trans( @@ -985,7 +985,7 @@ class parameters. d_rx=0.0, d_ry=0.0, d_rz=0.0, - tf_sd=itrf2020_to_itrf2014_sd + tf_sd=itrf2020_to_itrf2014_sd, ) itrf2020_to_itrf2008 = iers2trans( @@ -1266,7 +1266,7 @@ class parameters. sd_d_sc=0.02, sd_d_rx=0.006, sd_d_ry=0.006, - sd_d_rz=0.006 + sd_d_rz=0.006, ) itrf2014_to_itrf2008 = iers2trans( @@ -1287,7 +1287,7 @@ class parameters. d_rx=0, d_ry=0, d_rz=0, - tf_sd=itrf2014_to_itrf2008_sd + tf_sd=itrf2014_to_itrf2008_sd, ) itrf2014_to_itrf2005 = iers2trans( @@ -1547,7 +1547,7 @@ class parameters. sd_d_sc=0.03, sd_d_rx=0.008, sd_d_ry=0.008, - sd_d_rz=0.008 + sd_d_rz=0.008, ) itrf2008_to_itrf2005 = iers2trans( @@ -1568,7 +1568,7 @@ class parameters. d_rx=0, d_ry=0, d_rz=0, - tf_sd=itrf2008_to_itrf2005_sd + tf_sd=itrf2008_to_itrf2005_sd, ) itrf2008_to_itrf2000 = iers2trans( @@ -1808,7 +1808,7 @@ class parameters. sd_d_sc=0.05, sd_d_rx=0.012, sd_d_ry=0.012, - sd_d_rz=0.012 + sd_d_rz=0.012, ) itrf2005_to_itrf2000 = iers2trans( @@ -1829,7 +1829,7 @@ class parameters. d_rx=0, d_ry=0, d_rz=0, - tf_sd=itrf2005_to_itrf2000_sd + tf_sd=itrf2005_to_itrf2000_sd, ) itrf2005_to_itrf97 = iers2trans( @@ -2045,7 +2045,7 @@ class parameters. sd_d_sc=0.05, sd_d_rx=0.012, sd_d_ry=0.012, - sd_d_rz=0.014 + sd_d_rz=0.014, ) itrf2000_to_itrf97 = iers2trans( @@ -2066,7 +2066,7 @@ class parameters. d_rx=0, d_ry=0, d_rz=0.02, - tf_sd=itrf2000_to_itrf97_sd + tf_sd=itrf2000_to_itrf97_sd, ) itrf2000_to_itrf96 = iers2trans( @@ -2409,7 +2409,7 @@ class parameters. itrf91_to_itrf97 = -itrf97_to_itrf91 itrf90_to_itrf97 = -itrf97_to_itrf90 itrf89_to_itrf97 = -itrf97_to_itrf89 -itrf88_to_itrf97 = -itrf97_to_itrf88 +itrf88_to_itrf97 = -itrf97_to_itrf88 # itrf96 # Ref: https://itrf.ign.fr/en/solutions/transformations @@ -2560,7 +2560,7 @@ class parameters. itrf91_to_itrf96 = -itrf96_to_itrf91 itrf90_to_itrf96 = -itrf96_to_itrf90 itrf89_to_itrf96 = -itrf96_to_itrf89 -itrf88_to_itrf96 = -itrf96_to_itrf88 +itrf88_to_itrf96 = -itrf96_to_itrf88 # ITRF94 parameters # Ref: https://itrf.ign.fr/en/solutions/transformations @@ -2690,7 +2690,7 @@ class parameters. itrf91_to_itrf94 = -itrf94_to_itrf91 itrf90_to_itrf94 = -itrf94_to_itrf90 itrf89_to_itrf94 = -itrf94_to_itrf89 -itrf88_to_itrf94 = -itrf94_to_itrf88 +itrf88_to_itrf94 = -itrf94_to_itrf88 # ITRF93 paramters # Ref: https://itrf.ign.fr/en/solutions/transformations @@ -2799,7 +2799,7 @@ class parameters. itrf91_to_itrf93 = -itrf93_to_itrf91 itrf90_to_itrf93 = -itrf93_to_itrf90 itrf89_to_itrf93 = -itrf93_to_itrf89 -itrf88_to_itrf93 = -itrf93_to_itrf88 +itrf88_to_itrf93 = -itrf93_to_itrf88 # ITRF92 paramters # Ref: https://itrf.ign.fr/en/solutions/transformations @@ -3002,7 +3002,7 @@ class parameters. itrf89_to_itrf90 = -itrf90_to_itrf89 itrf88_to_itrf90 = -itrf90_to_itrf88 -#ITRF89 Paramters +# ITRF89 Paramters # Ref: https://itrf.ign.fr/en/solutions/transformations itrf89_to_itrf88 = iers2trans( @@ -3044,7 +3044,7 @@ class parameters. sd_d_sc=0.04, sd_d_rx=0.01, sd_d_ry=0.01, - sd_d_rz=0.01 + sd_d_rz=0.01, ) wgs84g1762_to_wgs84g2296_sd = iers2transSD( @@ -3061,7 +3061,7 @@ class parameters. sd_d_sc=0.09, sd_d_rx=0.02, sd_d_ry=0.03, - sd_d_rz=0.02 + sd_d_rz=0.02, ) wgs84g2296_to_itrf2020_sd = TransformationSD( @@ -3078,7 +3078,7 @@ class parameters. sd_d_sc=0.0, sd_d_rx=0.0, sd_d_ry=0.0, - sd_d_rz=0.0 + sd_d_rz=0.0, ) wgs84g2296_to_itrf2020 = Transformation( @@ -3099,7 +3099,7 @@ class parameters. d_rx=0.0, d_ry=0.0, d_rz=0.0, - tf_sd=wgs84g2296_to_itrf2020_sd + tf_sd=wgs84g2296_to_itrf2020_sd, ) wgs84g2139_to_wgs84g2296 = iers2trans( @@ -3120,7 +3120,7 @@ class parameters. d_rx=0.0, d_ry=-0.02, d_rz=-0.02, - tf_sd=wgs84g2139_to_wgs84g2296_sd + tf_sd=wgs84g2139_to_wgs84g2296_sd, ) wgs84g1762_to_wgs84g2296 = iers2trans( @@ -3141,14 +3141,14 @@ class parameters. d_rx=0.0, d_ry=-0.02, d_rz=0.01, - tf_sd=wgs84g1762_to_wgs84g2296_sd + tf_sd=wgs84g1762_to_wgs84g2296_sd, ) itrf2020_to_wgs84g2296 = -wgs84g2296_to_itrf2020 wgs84g2296_to_wgs84g2139 = -wgs84g2139_to_wgs84g2296 wgs84g2296_to_wgs84g1762 = -wgs84g1762_to_wgs84g2296 -#WGS84 (G2139) paramters +# WGS84 (G2139) paramters # https://www.unoosa.org/documents/pdf/icg/2023/ICG-17/icg17_wgd_02_02.pdf wgs84g2139_to_itrf2014_sd = TransformationSD( @@ -3165,7 +3165,7 @@ class parameters. sd_d_sc=0.0, sd_d_rx=0.0, sd_d_ry=0.0, - sd_d_rz=0.0 + sd_d_rz=0.0, ) wgs84g2139_to_itrf2014 = Transformation( @@ -3186,12 +3186,12 @@ class parameters. d_rx=0.0, d_ry=0.0, d_rz=0.0, - tf_sd=wgs84g2139_to_itrf2014_sd + tf_sd=wgs84g2139_to_itrf2014_sd, ) itrf2014_to_wgs84g2139 = -wgs84g2139_to_itrf2014 -#WGS84 (G1762) parameters +# WGS84 (G1762) parameters # https://www.unoosa.org/documents/pdf/icg/2023/ICG-17/icg17_wgd_02_02.pdf wgs84g1762_to_itrf2008_sd = TransformationSD( @@ -3208,7 +3208,7 @@ class parameters. sd_d_sc=0.0, sd_d_rx=0.0, sd_d_ry=0.0, - sd_d_rz=0.0 + sd_d_rz=0.0, ) wgs84g1762_to_itrf2008 = Transformation( @@ -3229,12 +3229,12 @@ class parameters. d_rx=0.0, d_ry=0.0, d_rz=0.0, - tf_sd=wgs84g1762_to_itrf2008_sd + tf_sd=wgs84g1762_to_itrf2008_sd, ) itrf2008_to_wgs84g1762 = -wgs84g1762_to_itrf2008 -#WGS84 (G1674) parameters +# WGS84 (G1674) parameters # https://www.unoosa.org/documents/pdf/icg/2023/ICG-17/icg17_wgd_02_02.pdf and # Kelly and Dennis, 2022 @@ -3252,7 +3252,7 @@ class parameters. sd_d_sc=0.0, sd_d_rx=0.0, sd_d_ry=0.0, - sd_d_rz=0.0 + sd_d_rz=0.0, ) wgs84g1674_to_wgs84g1762_sd = TransformationSD( @@ -3269,7 +3269,7 @@ class parameters. sd_d_sc=0.0, sd_d_rx=0.0, sd_d_ry=0.0, - sd_d_rz=0.0 + sd_d_rz=0.0, ) itrf2005_to_wgs84g1674 = iers2trans( @@ -3290,7 +3290,7 @@ class parameters. d_rx=0.0, d_ry=0.0, d_rz=0.0, - tf_sd=wgs84g1674_to_itrf2005_sd + tf_sd=wgs84g1674_to_itrf2005_sd, ) wgs84g1674_to_wgs84g1762 = iers2trans( @@ -3311,13 +3311,13 @@ class parameters. d_rx=0.0, d_ry=0.0, d_rz=0.0, - tf_sd=wgs84g1674_to_itrf2005_sd + tf_sd=wgs84g1674_to_itrf2005_sd, ) wgs84g1674_to_itrf2005 = -itrf2005_to_wgs84g1674 wgs84g1762_to_wgs84g1674 = -wgs84g1674_to_wgs84g1762 -#WGS84 (G1150) parameters +# WGS84 (G1150) parameters # https://www.unoosa.org/documents/pdf/icg/2023/ICG-17/icg17_wgd_02_02.pdf wgs84g1150_to_itrf2000_sd = TransformationSD( @@ -3334,10 +3334,10 @@ class parameters. sd_d_sc=0.0, sd_d_rx=0.0, sd_d_ry=0.0, - sd_d_rz=0.0 + sd_d_rz=0.0, ) -#From Kelly and Dennis (2022) +# From Kelly and Dennis (2022) wgs84g1150_to_itrf2000 = iers2trans( itrf_from="WGS84 (G1150)", @@ -3357,12 +3357,12 @@ class parameters. d_rx=0.0, d_ry=0.0, d_rz=0.0, - tf_sd=wgs84g1150_to_itrf2000_sd + tf_sd=wgs84g1150_to_itrf2000_sd, ) itrf2000_to_wgs84g1150 = -wgs84g1150_to_itrf2000 -#WGS84 (G873) parameters +# WGS84 (G873) parameters # https://www.unoosa.org/documents/pdf/icg/2023/ICG-17/icg17_wgd_02_02.pdf wgs84g873_to_itrf94_sd = TransformationSD( @@ -3379,7 +3379,7 @@ class parameters. sd_d_sc=0.0, sd_d_rx=0.0, sd_d_ry=0.0, - sd_d_rz=0.0 + sd_d_rz=0.0, ) wgs84g873_to_itrf96_sd = TransformationSD( @@ -3396,7 +3396,7 @@ class parameters. sd_d_sc=0.0, sd_d_rx=0.0, sd_d_ry=0.0, - sd_d_rz=0.0 + sd_d_rz=0.0, ) wgs84g873_to_itrf97_sd = TransformationSD( @@ -3413,7 +3413,7 @@ class parameters. sd_d_sc=0.0, sd_d_rx=0.0, sd_d_ry=0.0, - sd_d_rz=0.0 + sd_d_rz=0.0, ) wgs84g873_to_itrf94 = Transformation( @@ -3434,7 +3434,7 @@ class parameters. d_rx=0.0, d_ry=0.0, d_rz=0.0, - tf_sd=wgs84g873_to_itrf94_sd + tf_sd=wgs84g873_to_itrf94_sd, ) wgs84g873_to_itrf96 = Transformation( @@ -3455,7 +3455,7 @@ class parameters. d_rx=0.0, d_ry=0.0, d_rz=0.0, - tf_sd=wgs84g873_to_itrf94_sd + tf_sd=wgs84g873_to_itrf94_sd, ) wgs84g873_to_itrf97 = Transformation( @@ -3476,14 +3476,14 @@ class parameters. d_rx=0.0, d_ry=0.0, d_rz=0.0, - tf_sd=wgs84g873_to_itrf94_sd + tf_sd=wgs84g873_to_itrf94_sd, ) itrf94_to_wgs84g873 = -wgs84g873_to_itrf94 itrf96_to_wgs84g873 = -wgs84g873_to_itrf96 itrf97_to_wgs84g873 = -wgs84g873_to_itrf97 -#WGS84 (G730) parameters +# WGS84 (G730) parameters # https://www.unoosa.org/documents/pdf/icg/2023/ICG-17/icg17_wgd_02_02.pdf wgs84g730_to_itrf91_sd = TransformationSD( @@ -3500,7 +3500,7 @@ class parameters. sd_d_sc=0.0, sd_d_rx=0.0, sd_d_ry=0.0, - sd_d_rz=0.0 + sd_d_rz=0.0, ) wgs84g730_to_itrf91 = Transformation( @@ -3521,12 +3521,12 @@ class parameters. d_rx=0.0, d_ry=0.0, d_rz=0.0, - tf_sd=wgs84g730_to_itrf91_sd + tf_sd=wgs84g730_to_itrf91_sd, ) itrf91_to_wgs84g730 = -wgs84g730_to_itrf91 -#WGS84 (Transit) parameters +# WGS84 (Transit) parameters # Kelly and Dennis (2022) wgs84trans_to_itrf90_sd = TransformationSD( @@ -3543,7 +3543,7 @@ class parameters. sd_d_sc=0.0, sd_d_rx=0.0, sd_d_ry=0.0, - sd_d_rz=0.0 + sd_d_rz=0.0, ) wgs84trans_to_itrf90 = iers2trans( @@ -3584,7 +3584,7 @@ class parameters. sd_d_sc=0.0, sd_d_rx=0.0, sd_d_ry=0.0, - sd_d_rz=0.0 + sd_d_rz=0.0, ) wgs84ensemble_to_itrf2014 = Transformation( @@ -3605,7 +3605,7 @@ class parameters. d_rx=0.0, d_ry=0.0, d_rz=0.0, - tf_sd=wgs84ensemble_to_itrf2014_sd + tf_sd=wgs84ensemble_to_itrf2014_sd, ) itrf2014_to_wgs84ensemble = -wgs84ensemble_to_itrf2014 diff --git a/geodepy/convert.py b/geodepy/convert.py index 30ffd63..23b89d6 100644 --- a/geodepy/convert.py +++ b/geodepy/convert.py @@ -5,40 +5,41 @@ Convert Module """ -from math import sin, cos, atan2, radians, degrees, sqrt, cosh, sinh, tan, atan, log import datetime import warnings -from geodepy.constants import utm, isg, grs80, ans +from math import atan, atan2, cos, cosh, degrees, log, radians, sin, sinh, sqrt, tan + from geodepy.angles import ( + DDMAngle, DECAngle, - HPAngle, - GONAngle, DMSAngle, - DDMAngle, - dec2hp, - dec2hpa, + GONAngle, + HPAngle, + angular_typecheck, + dd2sec, + dec2ddm, + dec2dms, dec2gon, dec2gona, - dec2dms, - dec2ddm, - hp2dec, - hp2deca, - hp2gon, - hp2gona, - hp2dms, - hp2ddm, - hp2rad, - hp2dec_v, + dec2hp, + dec2hpa, + gon2ddm, gon2dec, gon2deca, + gon2dms, gon2hp, gon2hpa, - gon2dms, - gon2ddm, gon2rad, - dd2sec, - angular_typecheck, + hp2ddm, + hp2dec, + hp2dec_v, + hp2deca, + hp2dms, + hp2gon, + hp2gona, + hp2rad, ) +from geodepy.constants import ans, grs80, isg, utm def polar2rect(r, theta): @@ -65,7 +66,7 @@ def rect2polar(x, y): :param x: Rectangular Coordinate X :param y: Rectangular Coordinate Y - :return: + :return: - Radius - Angle (decimal degrees) """ @@ -208,78 +209,44 @@ def beta_coeff(ellipsoid): :rtype: tuple """ nval = ellipsoid.n - b2 = ( - nval - * ( - nval - * ( - nval - * ( - nval - * ( - nval - * (nval * ((37845269 - 31777436 * nval) - 43097152) + 42865200) - + 752640 - ) - - 104428800 - ) - + 180633600 - ) - - 135475200 - ) - ) / 270950400.0 - - b4 = ( - nval**2 - * ( - nval - * ( - nval - * ( - nval - * ( - nval * ((-24749483 * nval - 14930208) * nval + 100683990) - - 152616960 - ) - + 105719040 - ) - - 23224320 - ) - - 7257600 - ) - ) / 348364800.0 - - b6 = ( - nval**3 - * ( - nval - * ( - nval - * (nval * (nval * (232468668 * nval - 101880889) - 39205760) + 29795040) - + 28131840 - ) - - 22619520 - ) - ) / 638668800.0 - - b8 = ( - nval**4 - * ( - nval - * (nval * ((-324154477 * nval - 1433121792) * nval + 876745056) + 167270400) - - 208945440 - ) - ) / 7664025600.0 - - b10 = ( - nval**5 * (nval * (nval * (312227409 - 457888660 * nval) + 67920528) - 70779852) - ) / 2490808320.0 - - b12 = ( - nval**6 * (nval * (19841813847 * nval + 3665348512) - 3758062126) - ) / 116237721600.0 - - b14 = (nval**7 * (1989295244 * nval - 1979471673)) / 49816166400.0 + b2a = (37845269 - 31777436 * nval) - 43097152 + b2b = nval * b2a + 42865200 + b2c = nval * b2b + 752640 + b2d = nval * b2c - 104428800 + b2e = nval * b2d + 180633600 + b2f = nval * b2e - 135475200 + b2 = nval * b2f / 270950400.0 + + b4a = (-24749483 * nval - 14930208) * nval + 100683990 + b4b = nval * b4a - 152616960 + b4c = nval * b4b + 105719040 + b4d = nval * b4c - 23224320 + b4e = nval * b4d - 7257600 + b4 = nval**2 * b4e / 348364800.0 + + b6a = 232468668 * nval - 101880889 + b6b = nval * b6a - 39205760 + b6c = nval * b6b + 29795040 + b6d = nval * b6c + 28131840 + b6e = nval * b6d - 22619520 + b6 = nval**3 * b6e / 638668800.0 + + b8a = (-324154477 * nval - 1433121792) * nval + 876745056 + b8b = nval * b8a + 167270400 + b8c = nval * b8b - 208945440 + b8 = nval**4 * b8c / 7664025600.0 + + b10a = 312227409 - 457888660 * nval + b10b = nval * b10a + 67920528 + b10c = nval * b10b - 70779852 + b10 = nval**5 * b10c / 2490808320.0 + + b12a = 19841813847 * nval + 3665348512 + b12b = nval * b12a - 3758062126 + b12 = nval**6 * b12b / 116237721600.0 + + b14a = 1989295244 * nval - 1979471673 + b14 = nval**7 * b14a / 49816166400.0 b16 = (-191773887257 * nval**8) / 3719607091200.0 return b2, b4, b6, b8, b10, b12, b14, b16 @@ -489,9 +456,7 @@ def grid2geo(zone, east, north, hemisphere="south", ellipsoid=grs80, prj=utm): raise ValueError("Invalid Zone - Zones from 1 to 60") if east < -2830000 or east > 3830000: - raise ValueError( - "Invalid Easting - Must be within" "3330km of Central Meridian" - ) + raise ValueError("Invalid Easting - Must be within3330km of Central Meridian") if north < 0 or north > 10000000: raise ValueError("Invalid Northing - Must be between 0 and 10,000,000m") @@ -554,9 +519,7 @@ def ftn(tn, ecc1): def f1tn(tn, ecc1, ecc1sq): return ( sqrt(1 + (sigma(tn, ecc1)) ** 2) * sqrt(1 + tn**2) - sigma(tn, ecc1) * tn - ) * ( - ((1 - float(ecc1sq)) * sqrt(1 + t**2)) / (1 + (1 - float(ecc1sq)) * t**2) - ) + ) * (((1 - float(ecc1sq)) * sqrt(1 + t**2)) / (1 + (1 - float(ecc1sq)) * t**2)) diff = 1 t = t1 diff --git a/geodepy/coord.py b/geodepy/coord.py index 1463e64..4bd6559 100644 --- a/geodepy/coord.py +++ b/geodepy/coord.py @@ -5,20 +5,20 @@ Coordinate Module """ -from geodepy.constants import Projection, utm, grs80 from geodepy.angles import ( + DDMAngle, DECAngle, - HPAngle, - GONAngle, DMSAngle, - DDMAngle, - dec2hpa, - dec2gona, - dec2dms, - dec2ddm, + GONAngle, + HPAngle, angular_typecheck, + dec2ddm, + dec2dms, + dec2gona, + dec2hpa, ) -from geodepy.convert import xyz2llh, llh2xyz, grid2geo, geo2grid +from geodepy.constants import Projection, grs80, utm +from geodepy.convert import geo2grid, grid2geo, llh2xyz, xyz2llh class CoordCart(object): @@ -500,7 +500,7 @@ def cart(self, ellipsoid=grs80): Convert coordinates to Cartesian Note: If no ellipsoid height set, uses 0m. No N Value output - + :param ellipsoid: geodepy.constants.Ellipsoid Object (default: grs80) :return: Cartesian Coordinate :rtype: CoordCart diff --git a/geodepy/geodesy.py b/geodepy/geodesy.py index 237f73a..0c0102d 100644 --- a/geodepy/geodesy.py +++ b/geodepy/geodesy.py @@ -5,10 +5,12 @@ Geodesy Module """ -from math import degrees, radians, sqrt, sin, cos, tan, asin, acos, atan, atan2 +from math import acos, asin, atan, atan2, cos, degrees, radians, sin, sqrt, tan + import numpy as np + from geodepy.constants import grs80, utm -from geodepy.convert import geo2grid, grid2geo, angular_typecheck +from geodepy.convert import angular_typecheck, geo2grid, grid2geo from geodepy.statistics import rotation_matrix from geodepy.survey import radiations @@ -65,7 +67,7 @@ def vincdir(lat1, lon1, azimuth1to2, ell_dist, ellipsoid=grs80): :type azimuth1to2: float (decimal degrees), DMSAngle or DDMAngle :param ell_dist: Ellipsoidal Distance between Points 1 and 2 (metres) :param ellipsoid: Ellipsoid Object - :return: + :return: - lat2 - Latitude of Point 2 (Decimal Degrees), - lon2 - Longitude of Point 2 (Decimal Degrees), - azimuth2to1 - Azimuth from Point 2 to 1 (Decimal Degrees) @@ -112,7 +114,6 @@ def vincdir(lat1, lon1, azimuth1to2, ell_dist, ellipsoid=grs80): # or after 1000 iterations have been completed two_sigma_m = 0 for i in range(1000): - # Eq. 95 two_sigma_m = 2 * sigma1 + sigma @@ -207,7 +208,7 @@ def vincinv(lat1, lon1, lat2, lon2, ellipsoid=grs80): - ell_dist - Ellipsoidal Distance between Points 1 and 2 (m), - azimuth1to2 - Azimuth from Point 1 to 2 (Decimal Degrees), - azimuth2to1 - Azimuth from Point 2 to 1 (Decimal Degrees) - + """ # Convert Angles to Decimal Degrees (if required) @@ -239,7 +240,6 @@ def vincinv(lat1, lon1, lat2, lon2, ellipsoid=grs80): sigma = 0 cos_two_sigma_m = 0 for i in range(1000): - # Eq. 74 sin_sigma = sqrt( (cos(u2) * sin(lon)) ** 2 @@ -364,7 +364,7 @@ def vincdir_utm( :param grid_dist: UTM Grid Distance between Points 1 and 2 (m) :param hemisphere: String - 'North' or 'South'(default) :param ellipsoid: Ellipsoid Object (default: GRS80) - :return: + :return: - zone2 - Point 2 Zone Number - 1 to 60 - east2 - Point 2 Easting (m, within 3330km of Central Meridian) - north2 - Point 2 Northing (m, 0 to 10,000,000m) @@ -421,7 +421,7 @@ def vincinv_utm( :param north2: Point 2 Northing (m, 0 to 10,000,000m) :param hemisphere: String - 'North' or 'South'(default) :param ellipsoid: Ellipsoid Object (default: GRS80) - :return: + :return: - grid_dist - UTM Grid Distance between Points 1 and 2 (m), - grid1to2 - Grid Bearing from Point 1 to 2 (decimal degrees), - grid2to1 - Grid Bearing from Point 2 to 1 (decimal degrees) @@ -516,7 +516,7 @@ def nu(lat, ellipsoid=grs80): """ Return the radius of curvature of the ellipsoid in the prime vertical plane (nu) at a given latitude - + :param lat: latitude in decimal degrees :param ellipsoid: Ellipsoid Object :return: nu at specified latitude diff --git a/geodepy/gnss.py b/geodepy/gnss.py index 65903a8..2c5f703 100644 --- a/geodepy/gnss.py +++ b/geodepy/gnss.py @@ -55,12 +55,14 @@ """ +import re from datetime import datetime + import numpy as np import pandas as pd -from numpy import zeros, delete +from numpy import delete, zeros + from geodepy.angles import DMSAngle -import re def list_sinex_blocks(file): @@ -320,12 +322,12 @@ def read_sinex_matrix(file): :param file: the input SINEX file :return: Sinex matrix as list of lists """ - ''' + """ ToDo: 1. The above order is only valid if the matrix is upper triangle. If it is lower triangle, then the covar_xy is actually the var_y. Will need to fix this when time permits. - ''' + """ # Read in the codes (station names) and solutions, and check for velocities data = read_sinex_estimate(file) code = [] @@ -1198,7 +1200,6 @@ def dataframe2matrix_snx_vcv(df, numPar=3): j = 0 r = 0 while r < len(df.code): - # variances Q[i + 0, j + 0] = df.xx[r] Q[i + 1, j + 1] = df.yy[r] @@ -1241,9 +1242,7 @@ def dataframe2matrix_solution_matrix_estimate(df, tri="L"): Q = np.zeros((n, n)) if triangle == "L": - for i in range(len(df.row)): - # Get matrix indices row = int(df.row[i]) - 1 col = int(df.col[i]) - 1 @@ -1264,15 +1263,12 @@ def dataframe2matrix_solution_matrix_estimate(df, tri="L"): Q[col + 2, row] = q3 if triangle == "U": - for i in range(len(df.row)): - # Get matrix indices row = int(df.row[i]) - 1 col = int(df.col[i]) - 1 if df.col[i] < n - 1: - # Fill PARA2+0 q1 = df.q1[i] Q[row, col] = q1 @@ -1289,7 +1285,6 @@ def dataframe2matrix_solution_matrix_estimate(df, tri="L"): Q[col + 2, row] = q3 if df.col[i] == n - 1: - # Fill PARA2+0 q1 = df.q1[i] Q[row, col] = q1 @@ -1301,7 +1296,6 @@ def dataframe2matrix_solution_matrix_estimate(df, tri="L"): Q[col + 1, row] = q2 if df.col[i] == n: - # Fill PARA2+0 q1 = df.q1[i] Q[row, col] = q1 @@ -1329,7 +1323,6 @@ def matrix2dataframe_solution_matrix_estimate(m, tri="L"): n = np.shape(Q)[0] if triangle == "L": - # Make upper triangle NaNs Q[np.triu_indices(n, 1)] = np.nan @@ -1352,7 +1345,6 @@ def matrix2dataframe_solution_matrix_estimate(m, tri="L"): i += 1 if triangle == "U": - # Make lower triangle NaNs Q[np.tril_indices(n, -1)] = np.nan @@ -1488,7 +1480,6 @@ def writeSINEX( # Open File with open(fp, "w") as f: - # Header if header == None: pass @@ -1670,7 +1661,6 @@ def remove_stns_sinex(sinex, sites): # Open the output file with open("output.snx", "w") as out: - # Get header line and update the creation time and the number of # parameter estimates. Write the updated header line to the new file header = read_sinex_header_line(sinex) @@ -1851,7 +1841,6 @@ def remove_velocity_sinex(sinex): # Open the output file with open("output.snx", "w") as out: - # With header line: # - update the creation time # - update number of parameter estimates @@ -1982,13 +1971,13 @@ def remove_velocity_sinex(sinex): j = 0 while i < len(Q): while j <= i: - out.write(f" {i+1:5d} {j+1:5d} {Q[i,j]:21.14E} ") + out.write(f" {i + 1:5d} {j + 1:5d} {Q[i, j]:21.14E} ") j += 1 if j <= i: - out.write(f"{Q[i,j]:21.14E} ") + out.write(f"{Q[i, j]:21.14E} ") j += 1 if j <= i: - out.write(f"{Q[i,j]:21.14E}") + out.write(f"{Q[i, j]:21.14E}") j += 1 out.write(" \n") j = 0 @@ -1999,13 +1988,13 @@ def remove_velocity_sinex(sinex): for i in range(len(Q)): j = i while j < len(Q): - out.write(f" {i+1:5d} {j+1:5d} {Q[i,j]:21.14E} ") + out.write(f" {i + 1:5d} {j + 1:5d} {Q[i, j]:21.14E} ") j += 1 if j < len(Q): - out.write(f"{Q[i,j]:21.14E} ") + out.write(f"{Q[i, j]:21.14E} ") j += 1 if j < len(Q): - out.write(f"{Q[i,j]:21.14E}") + out.write(f"{Q[i, j]:21.14E}") j += 1 out.write(" \n") # Write out end of block line, and delete large variables @@ -2030,7 +2019,6 @@ def remove_matrixzeros_sinex(sinex): # Open the output file with open("output.snx", "w") as out: - # With header line: # - update the creation time # - then write to file diff --git a/geodepy/height.py b/geodepy/height.py index c5856c7..9bb8af4 100644 --- a/geodepy/height.py +++ b/geodepy/height.py @@ -7,19 +7,21 @@ # These allow direct access remotely using "gdal" # ___________________________________________________________________________# # Import dependencies -import geodepy.constants as cons -import geodepy.geodesy as gg -from osgeo import gdal +import math as m + import numpy as np +from osgeo import gdal from scipy.interpolate import griddata -import math as m + +import geodepy.constants as cons +import geodepy.geodesy as gg # ___________________________________________________________________________# # Interpolation functions def interp_file(Lat, Long, file): """ - Interpolates files at specific Latitude and Longitude. Uses files found in + Interpolates files at specific Latitude and Longitude. Uses files found in geodepy.constants and vsicurl to access only part of file. :param Lat: Latitude in decimal degrees @@ -98,7 +100,7 @@ def AHD_to_AVWS(Lat, Long, AHD_H): :param Long: Longitude in decimal degrees :param AHD_H: AHD height (m) :return: AVWS height (m) - """ + """ # Convert to GPS GPS_H = AHD_H + interp_file(Lat, Long, cons.file_AG2020) # AUSGEOID2020 file # Convert to AVWS @@ -146,7 +148,7 @@ def AVWS_to_AHD(Lat, Long, AVWS_H): :param Long: Longitude in decimal degrees :param AVWS_H: AVWS height (m) :return: AHD height (m) - """ + """ # Convert to GPS GPS_H = AVWS_H + interp_file(Lat, Long, cons.file_AVWS) # AVWS file # Convert to AHD @@ -178,7 +180,7 @@ def GPS_to_AUSGeoid98(Lat, Long, GPS_H): :param Long: Longitude in decimal degrees :param GPS_H: Ellipsoidal height (m) :return: AHD using AUSGeoid98 (m) - """ + """ N = interp_file(Lat, Long, cons.file_AG98) # AUSGEOID98 file AHD_H = GPS_H - N return [AHD_H] @@ -192,7 +194,7 @@ def AUSGeoid98_to_GPS(Lat, Long, AHD_H): :param Long: Longitude in decimal degrees :param AHD_H: height using AUSGEOID98 (m) :return: Ellipsoidal height (m) - """ + """ N = interp_file(Lat, Long, cons.file_AG98) # AUSGEOID98 file GPS_H = AHD_H + N return [GPS_H] @@ -206,7 +208,7 @@ def GPS_to_AUSGeoid09(Lat, Long, GPS_H): :param Long: Longitude in decimal degrees :param AHD_H: ellipsoidal height (m) :return: AHD using AUSGeoid09 (m) - """ + """ N = interp_file(Lat, Long, cons.file_AG09) # AUSGEOID09 file AHD_H = GPS_H - N return [AHD_H] @@ -220,7 +222,7 @@ def AUSGeoid09_to_GPS(Lat, Long, AHD_H): :param Long: Longitude in decimal degrees :param AHD_H: AHD using AUSGEOID98 (m) :return: Ellipsoidal height (m) - """ + """ N = interp_file(Lat, Long, cons.file_AG09) # AUSGEOID09 file GPS_H = AHD_H + N return [GPS_H] @@ -334,7 +336,7 @@ def normal_grav(Lat, h): def mean_surface_grav(Lat_A, Long_A, H_A, Lat_B, Long_B, H_B): """ - Mean surface gravity between two points. Uses anomalies, normal theoretical + Mean surface gravity between two points. Uses anomalies, normal theoretical gravity and the Bouguer slab correction. :param Lat_A: Latitude of point A in decimal degrees diff --git a/geodepy/inputoutput.py b/geodepy/inputoutput.py index 52daaf5..bc353c5 100644 --- a/geodepy/inputoutput.py +++ b/geodepy/inputoutput.py @@ -1,11 +1,13 @@ __all__ = ["grid2geoio", "geo2gridio", "gdatrans7"] -import geodepy.convert -import pandas as pd import tkinter as ttk -import geodepy.transform as tf -import geodepy.convert as cv + +import pandas as pd + import geodepy.constants as cs +import geodepy.convert +import geodepy.convert as cv +import geodepy.transform as tf """ The inputoutput module acts as the backend for the GUI and manages the calls @@ -18,16 +20,16 @@ def grid2geoio(fn, fn_out, easting, northing, utmzone, geotypeout): """ - The CSV data must have headers. + The CSV data must have headers. - :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 + :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 - :return: Data is output to the fn_out location as a CSV. + :return: Data 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 @@ -115,17 +117,17 @@ def geo2gridio(fn, fn_out, latitude, longitude, geotypein): def gdatrans7(fn, fn_out, latitude, longitude, ellht, gdageotypein, direction): """ - The CSV data must have headers. + The CSV data must have headers. - :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. + :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. - :return: Data is output to the fn_out location as a CSV. + :return: Data 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 diff --git a/geodepy/ntv2reader.py b/geodepy/ntv2reader.py index 2ae9bf7..ba53173 100644 --- a/geodepy/ntv2reader.py +++ b/geodepy/ntv2reader.py @@ -8,6 +8,7 @@ import struct from datetime import datetime as dt + import numpy as np @@ -27,7 +28,7 @@ def __init__( minor_t, file_path, ): - ''' + """ NTv2 Grid Parameters :param num_orec: Number of header identifiers @@ -43,7 +44,7 @@ def __init__( :param minor_t: semi minor of to system :param file_path: full path to ntv2 gsb file - ''' + """ self.num_orec = num_orec # Number of header identifiers self.num_srec = num_srec # Number of sub-header idents self.num_file = num_file # Number of subgrids in file @@ -74,7 +75,7 @@ def __init__( long_inc, gs_count, ): - ''' + """ Sub Grid Parameters :param sub_name: subgrid name @@ -89,7 +90,7 @@ def __init__( :param long_inc: longitude increment :param gs_count: total nodes in subgrid - ''' + """ self.sub_name = sub_name # subgrid name self.parent = parent # parent name self.created = created # date created @@ -666,7 +667,7 @@ def read_ntv2_file(ntv2_gsb_file): def interpolate_ntv2(grid_object, lat, lon, method="bicubic"): """ Function to interpolate Ntv2Grid objects - + :param grid_object: Ntv2Grid object :param lat: latitude (decimal degrees) :param lon: longitude (decimal degrees) @@ -719,7 +720,6 @@ def interpolate_ntv2(grid_object, lat, lon, method="bicubic"): with open(grid_object.file_path, "rb") as f: for sg in grid_object.subgrids.values(): - skip_bytes += 176 # subgrid header length if sg.sub_name == in_grid.sub_name: if method == "bilinear": diff --git a/geodepy/statistics.py b/geodepy/statistics.py index 054ac5c..09d2429 100644 --- a/geodepy/statistics.py +++ b/geodepy/statistics.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 -from math import radians, sin, cos, sqrt, atan2, degrees +from math import atan2, cos, degrees, radians, sin, sqrt + import numpy as np @@ -119,7 +120,7 @@ def error_ellipse(vcv): def relative_error(lat, lon, var1, var2, cov12): """ Function to compute relative error between two 3D stations: - + * 2D relative error ellipse [semi-major axis, semi-minor axis, bearing] * 1D relative 'up' error @@ -196,7 +197,7 @@ def k_val95(dof): 120, returns k value of 1.96 and for DOF below 1, returns k value for DOF = 1. Coverage Factor produced using following scipy stats: - .. code:: python + .. code:: python stats.t.ppf(1-0.025,dof) diff --git a/geodepy/survey.py b/geodepy/survey.py index 120bd01..33b95c9 100644 --- a/geodepy/survey.py +++ b/geodepy/survey.py @@ -5,9 +5,10 @@ Survey Module """ -from math import sqrt, sin, cos, atan, radians, degrees, exp +from math import atan, cos, degrees, exp, radians, sin, sqrt from statistics import mean, stdev -from geodepy.convert import rect2polar, polar2rect + +from geodepy.convert import polar2rect, rect2polar def first_vel_params(wavelength, frequency, n_REF=None, unit_length=None): @@ -158,7 +159,7 @@ def precise_inst_ht(vert_list, spacing, offset): Uses a set of Vertical Angle Observations taken to a levelling staff at regular intervals to determine the height of the instrument above a reference mark - + :param vert_list: List of Vertical (Zenith) Angle Observations (minimum of 3) in Decimal Degrees format :param spacing: Distance in metres between each vertical angle observation :param offset: Lowest observed height above reference mark @@ -221,7 +222,7 @@ def va_conv(zenith_angle, slope_dist, height_inst=0, height_tgt=0): :param height_inst: Height of Instrument. Optional - Default Value of 0m :param height_tgt: Height of Target. Optional - Default Value of 0m - :return: + :return: - vert_angle_pt - Vertical Angle between Ground Points, expressed in decimal degrees - slope_dist_pt - Slope Distance between Ground Points in metres - hz_dist - Horizontal Distance @@ -385,7 +386,7 @@ def phase_refractivity(LAMDA, TC, P, PV, XC=420): :param P: pressure (hPa) :param PV: partial water vapour pressure (Pa) :param XC: carbon dioxide content (ppm) - + :return: NPROPP_1 - phase refractivity = (NPROPphase-1)10E8 """ @@ -519,7 +520,7 @@ def group_refractivity(LAMDA, TC, P, PV, XC=420): :param P: pressure (hPa) :param PV: partial water vapour pressure (Pa) :param XC: carbon dioxide content (ppm) - + :return: NPROPG_1 - group refractivity = (NPROPgroup-1)10E8 """ @@ -653,7 +654,7 @@ def humidity2part_water_vapour_press(H, TC): :param H: humidity (%) :param TC: temperature (degrees Celcius) - + :return: PV - partial water vapour pressure (Pa) """ diff --git a/geodepy/tests/test_angles.py b/geodepy/tests/test_angles.py index afce1e6..f9f3b1e 100644 --- a/geodepy/tests/test_angles.py +++ b/geodepy/tests/test_angles.py @@ -1,35 +1,35 @@ -import unittest import os -from math import radians, pi +import unittest +from math import pi, radians from geodepy.angles import ( + DDMAngle, DECAngle, - HPAngle, - GONAngle, DMSAngle, - DDMAngle, - dec2hp, - dec2hpa, + GONAngle, + HPAngle, + angular_typecheck, + dd2sec, + dec2ddm, + dec2dms, dec2gon, dec2gona, - dec2dms, - dec2ddm, - hp2dec, - hp2deca, - hp2gon, - hp2gona, - hp2dms, - hp2ddm, - hp2rad, + dec2hp, + dec2hpa, + gon2ddm, gon2dec, gon2deca, + gon2dms, gon2hp, gon2hpa, - gon2dms, - gon2ddm, gon2rad, - dd2sec, - angular_typecheck, + hp2ddm, + hp2dec, + hp2deca, + hp2dms, + hp2gon, + hp2gona, + hp2rad, ) rad_exs = [ @@ -134,7 +134,7 @@ def setUp(self): for sec in range(60): if sec: hp_minus = float( - f"{deg:4d}.{min:02d}{sec-1:02d}" + "9" * (dec_places - 4) + f"{deg:4d}.{min:02d}{sec - 1:02d}" + "9" * (dec_places - 4) ) dec_minus = deg + (min / 60.0 + (sec - error) / 3600.0) gon_minus = 400.0 / 360.0 * dec_minus diff --git a/geodepy/tests/test_convert.py b/geodepy/tests/test_convert.py index 3455728..9d58161 100644 --- a/geodepy/tests/test_convert.py +++ b/geodepy/tests/test_convert.py @@ -1,27 +1,29 @@ +import datetime import os import unittest -import datetime + import numpy as np -from geodepy.fileio import read_dnacoord -from geodepy.constants import grs80, ans, isg + +from geodepy.constants import ans, grs80, isg from geodepy.convert import ( - dec2hp, - hp2dec, - DMSAngle, DDMAngle, - dec2dms, - dec2ddm, - hp2dms, - hp2ddm, - dd2sec, - yyyydoy_to_date, + DMSAngle, date_to_yyyydoy, + dd2sec, + dec2ddm, + dec2dms, + dec2hp, + geo2grid, grid2geo, + hp2ddm, + hp2dec, hp2dec_v, - geo2grid, + hp2dms, llh2xyz, xyz2llh, + yyyydoy_to_date, ) +from geodepy.fileio import read_dnacoord class TestConvert(unittest.TestCase): diff --git a/geodepy/tests/test_coord.py b/geodepy/tests/test_coord.py index 64e14c1..7b22fd0 100644 --- a/geodepy/tests/test_coord.py +++ b/geodepy/tests/test_coord.py @@ -1,6 +1,7 @@ import unittest -from geodepy.angles import DMSAngle, DECAngle -from geodepy.constants import utm, grs80 + +from geodepy.angles import DECAngle, DMSAngle +from geodepy.constants import grs80, utm from geodepy.coord import CoordCart, CoordGeo, CoordTM cart_ex1 = CoordCart(-4052052.7379, 4212835.9897, -2545104.5898, 14.269) @@ -47,9 +48,7 @@ def test_CoordCart(self): # Test Overloads self.assertEqual( repr(cart_ex1), - "CoordCart: X: -4052052.7379 " - "Y: 4212835.9897 Z: -2545104.5898 " - "NVal: 14.269", + "CoordCart: X: -4052052.7379 Y: 4212835.9897 Z: -2545104.5898 NVal: 14.269", ) self.assertEqual(cart_ex1, cart_ex1) diff --git a/geodepy/tests/test_geodesy.py b/geodepy/tests/test_geodesy.py index bf96c81..52e4a5f 100644 --- a/geodepy/tests/test_geodesy.py +++ b/geodepy/tests/test_geodesy.py @@ -1,17 +1,19 @@ -import unittest import os.path +import unittest + import numpy as np import numpy.lib.recfunctions as rfn + from geodepy.convert import ( - hp2dec, + DMSAngle, dec2hp, - rect2polar, - polar2rect, grid2geo, + hp2dec, llh2xyz, - DMSAngle, + polar2rect, + rect2polar, ) -from geodepy.geodesy import vincinv, vincdir, vincinv_utm, vincdir_utm, enu2xyz, xyz2enu +from geodepy.geodesy import enu2xyz, vincdir, vincdir_utm, vincinv, vincinv_utm, xyz2enu class TestGeodesy(unittest.TestCase): diff --git a/geodepy/tests/test_statistics.py b/geodepy/tests/test_statistics.py index 561b347..ffc17db 100644 --- a/geodepy/tests/test_statistics.py +++ b/geodepy/tests/test_statistics.py @@ -1,7 +1,9 @@ import unittest -from geodepy import statistics + import numpy as np +from geodepy import statistics + lat = 19.4792453 lon = 70.69315634 vcv = np.array([[1.44, -1.32, 1.32], [-1.32, 1.22, -1.20], [1.32, -1.20, 1.20]]) diff --git a/geodepy/tests/test_survey.py b/geodepy/tests/test_survey.py index 9a5349c..52ccb13 100644 --- a/geodepy/tests/test_survey.py +++ b/geodepy/tests/test_survey.py @@ -1,13 +1,14 @@ import unittest + from geodepy.convert import DMSAngle from geodepy.survey import ( - first_vel_params, first_vel_corrn, + first_vel_params, + joins, mets_partial_differentials, precise_inst_ht, - va_conv, radiations, - joins, + va_conv, ) diff --git a/geodepy/tests/test_transform.py b/geodepy/tests/test_transform.py index 01a56ec..0b00108 100644 --- a/geodepy/tests/test_transform.py +++ b/geodepy/tests/test_transform.py @@ -1,17 +1,17 @@ import unittest +from datetime import date +from geodepy.constants import gda94_to_gda2020, itrf2014_to_gda2020 from geodepy.transform import ( + atrf2014_to_gda2020, conform7, conform14, plate_motion_transformation, - atrf2014_to_gda2020, - transform_gda2020_to_atrf2014, transform_atrf2014_to_gda2020, + transform_gda2020_to_atrf2014, transform_mga94_to_mga2020, transform_mga2020_to_mga94, ) -from geodepy.constants import itrf2014_to_gda2020, gda94_to_gda2020 -from datetime import date class TestTransforms(unittest.TestCase): @@ -51,10 +51,10 @@ def test_plate_motion_transformation(self): alic_atrf14at2018 = (-4052052.6588, 4212835.9938, -2545104.6946) alic_atrf14at2025 = (-4052052.9336, 4212835.9577, -2545104.3168) alic_atrf14at2025_comp = plate_motion_transformation( - *alic_atrf14at2018, date(2018,1,1), date(2025,1,1),itrf2014_to_gda2020 + *alic_atrf14at2018, date(2018, 1, 1), date(2025, 1, 1), itrf2014_to_gda2020 ) alic_atrf14at2018_comp = plate_motion_transformation( - *alic_atrf14at2025, date(2025,1,1), date(2018,1,1), itrf2014_to_gda2020 + *alic_atrf14at2025, date(2025, 1, 1), date(2018, 1, 1), itrf2014_to_gda2020 ) assert abs(alic_atrf14at2018_comp[0] - alic_atrf14at2018[0]) < 5e-5 assert abs(alic_atrf14at2018_comp[1] - alic_atrf14at2018[1]) < 5e-5 diff --git a/geodepy/transform.py b/geodepy/transform.py index 536f261..bb67274 100644 --- a/geodepy/transform.py +++ b/geodepy/transform.py @@ -13,16 +13,18 @@ import datetime from math import radians + import numpy as np + from geodepy.constants import ( Transformation, TransformationSD, atrf2014_to_gda2020, gda94_to_gda2020, ) -from geodepy.statistics import vcv_local2cart, vcv_cart2local -from geodepy.convert import hp2dec, geo2grid, grid2geo, xyz2llh, llh2xyz +from geodepy.convert import geo2grid, grid2geo, hp2dec, llh2xyz, xyz2llh from geodepy.ntv2reader import NTv2Grid, interpolate_ntv2 +from geodepy.statistics import vcv_cart2local, vcv_local2cart def conform7(x, y, z, trans, vcv=None): @@ -146,6 +148,7 @@ def conform14(x, y, z, to_epoch, trans, vcv=None): xtrans, ytrans, ztrans, trans_vcv = conform7(x, y, z, timetrans, vcv=vcv) return xtrans, ytrans, ztrans, trans_vcv + def plate_motion_transformation(x, y, z, from_epoch, to_epoch, plate_motion, vcv=None): """ Preforms plate motion transformations using a helmert 14 conformal transformation. @@ -166,10 +169,10 @@ def plate_motion_transformation(x, y, z, from_epoch, to_epoch, plate_motion, vcv if type(plate_motion) != Transformation: raise ValueError("plate_motion must be a Transformation Object") - #calculate number of years to be moved - timediff= to_epoch - from_epoch + # calculate number of years to be moved + timediff = to_epoch - from_epoch - #calculate epoch needed for plate motion + # calculate epoch needed for plate motion change_epoch = plate_motion.ref_epoch - timediff # Calculate 7 Parameters from 14 Parameter Transformation Object @@ -179,6 +182,7 @@ def plate_motion_transformation(x, y, z, from_epoch, to_epoch, plate_motion, vcv xtrans, ytrans, ztrans, trans_vcv = conform7(x, y, z, timetrans, vcv=vcv) return xtrans, ytrans, ztrans, trans_vcv + def transform_mga94_to_mga2020(zone, east, north, ell_ht=False, vcv=None): """ Performs conformal transformation of Map Grid of Australia 1994 to Map Grid of Australia 2020 Coordinates @@ -273,7 +277,7 @@ def transform_gda2020_to_atrf2014(x, y, z, epoch_to, vcv=None): def ntv2_2d(ntv2_grid, lat, lon, forward_tf=True, method="bicubic"): """ Performs a 2D transformation based on ntv2 grid shifts. - + :param ntv2_grid: Ntv2Grid object (create with read_ntv2_file() function in geodepy.ntv2reader module) :param lat: latitude in decimal degrees :param lon: longitude in decimal degrees diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..d8cd911 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,18 @@ +[tool.ruff] +line-length = 88 +extend-exclude = [ + "docs/_build", + "docs/tutorials/juypter notebooks", +] + +[tool.ruff.lint] +select = [ + "E9", + "F63", + "F7", + "F82", + "I", +] + +[tool.ruff.lint.isort] +known-first-party = ["geodepy"] diff --git a/setup.py b/setup.py index 9ee90c3..0b59330 100644 --- a/setup.py +++ b/setup.py @@ -1,12 +1,14 @@ from setuptools import setup -setup(name='geodepy', - version='0.7.0', - description='GA Geodesy Package', - long_description='A toolkit for Geodesy and Surveying in Python', - url='https://github.com/GeoscienceAustralia/GeodePy', - author='Geoscience Australia', - author_email='geodesy@ga.gov.au', - license='Apache License 2.0', - packages=['geodepy'], - install_requires=['numpy', 'scipy']) +setup( + name="geodepy", + version="0.7.0", + description="GA Geodesy Package", + long_description="A toolkit for Geodesy and Surveying in Python", + url="https://github.com/GeoscienceAustralia/GeodePy", + author="Geoscience Australia", + author_email="geodesy@ga.gov.au", + license="Apache License 2.0", + packages=["geodepy"], + install_requires=["numpy", "scipy"], +)