diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 0000000..f9780a8
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,22 @@
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required
+version: 2
+
+# Set the OS, Python version, and other tools you might need
+build:
+  os: ubuntu-24.04
+  tools:
+    python: "3.13"
+
+# Build documentation in the "docs/" directory with Sphinx
+sphinx:
+   configuration: docs/conf.py
+
+# Optionally, but recommended,
+# declare the Python requirements required to build your documentation
+# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
+python:
+  install:
+    - requirements: docs/requirements.txt
\ No newline at end of file
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000..d4bb2cb
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS    ?=
+SPHINXBUILD   ?= sphinx-build
+SOURCEDIR     = .
+BUILDDIR      = _build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/docs/_static/custom.css b/docs/_static/custom.css
new file mode 100644
index 0000000..a0ba58f
--- /dev/null
+++ b/docs/_static/custom.css
@@ -0,0 +1,32 @@
+a {
+    color: #00718e;
+}
+
+a .sidebar-navigation{
+    color: #00718e;
+}
+
+.sidebar-tree a {
+    color: #00718e !important; /* Sidebar links */
+}
+
+.sidebar-tree svg {
+    color: #00718e !important; /* Normal arrow color */
+}
+
+/* Hide the TOC caption heading on the index page */
+.toctree-wrapper > p.caption {
+    display: none;
+}
+
+/* Style the custom TOC expander arrows */
+.toctree-expander {
+    color: #00718e; /* Your preferred color */
+}
+
+/* Optional: Hover effect */
+.toctree-expander:hover {
+    color: #005f73;
+}
+
+
diff --git a/docs/_static/custom.js b/docs/_static/custom.js
new file mode 100644
index 0000000..d4df3ba
--- /dev/null
+++ b/docs/_static/custom.js
@@ -0,0 +1,29 @@
+document.addEventListener("DOMContentLoaded", function () {
+    document.querySelectorAll(".collapsible-toc li").forEach(function (item) {
+        const sublist = item.querySelector("ul");
+        const link = item.querySelector("a");
+        if (sublist && link) {
+            const toggle = document.createElement("span");
+            toggle.innerHTML = `
+                <svg class="toctree-expander" viewBox="0 0 24 24" width="16" height="16" stroke="currentColor" fill="none" stroke-width="2">
+                    <polyline points="6 9 12 15 18 9"></polyline>
+                </svg>
+            `;
+            toggle.style.cursor = "pointer";
+            toggle.style.marginLeft = "8px";
+
+            toggle.addEventListener("click", function () {
+                if (sublist.style.display === "none") {
+                    sublist.style.display = "block";
+                    toggle.querySelector("polyline").setAttribute("points", "6 15 12 9 18 15");
+                } else {
+                    sublist.style.display = "none";
+                    toggle.querySelector("polyline").setAttribute("points", "6 9 12 15 18 9");
+                }
+            });
+
+            sublist.style.display = "none";
+            link.insertAdjacentElement("afterend", toggle);
+        }
+    });
+});
diff --git a/docs/_static/geodepy-logo-dark.png b/docs/_static/geodepy-logo-dark.png
new file mode 100644
index 0000000..c5d37fe
Binary files /dev/null and b/docs/_static/geodepy-logo-dark.png differ
diff --git a/docs/_static/geodepy-logo-light.png b/docs/_static/geodepy-logo-light.png
new file mode 100644
index 0000000..c9c321f
Binary files /dev/null and b/docs/_static/geodepy-logo-light.png differ
diff --git a/docs/_static/geodepy-logo.png b/docs/_static/geodepy-logo.png
new file mode 100644
index 0000000..5224e81
Binary files /dev/null and b/docs/_static/geodepy-logo.png differ
diff --git a/docs/_templates/sidebar/extra.html b/docs/_templates/sidebar/extra.html
new file mode 100644
index 0000000..2b8a70d
--- /dev/null
+++ b/docs/_templates/sidebar/extra.html
@@ -0,0 +1,6 @@
+<div class="sidebar-extra" style="text-align:left; margin-top:0px; margin-bottom:5px ;">
+    <p style="font-size:14px; margin-bottom:10px;">GeodePy is a package of tools for manipulating goespatial datasets using Python.</p>
+    <a href="https://github.com/GeoscienceAustralia/GeodePy" target="_blank">
+    <img src="https://img.shields.io/badge/GitHub-GeodePy-blue?logo=github" alt="GitHub Badge" />
+    </a>
+</div>
diff --git a/docs/community/authors.rst b/docs/community/authors.rst
new file mode 100644
index 0000000..124da09
--- /dev/null
+++ b/docs/community/authors.rst
@@ -0,0 +1,12 @@
+Authors
+=======
+
+GeodePy is developed and maintained by the Geoscience Australia National Geodesy Team. Over time, many contributors have helped improve the package.
+
+* **Craig Harrison** - Project Management - `harry093 <https://github.com/harry093>`_
+* **Josh Batchelor** - Initial Work, Geodesy and Surveying - `BatchelorJ <https://github.com/BatchelorJ>`_
+* **Jonathan Mettes** - Testing, Integration and Development - `jmettes <https://github.com/jmettes>`_
+* **Jack McCubbine** - Height Module - `JackMcCubbineGA <https://github.com/JackMcCubbineGA>`_
+* **Kyran Cook** - Documentation and Uplift - `KyranCookGA <https://github.com/KyranCookGA>`_
+
+See also the list of `contributors <https://github.com/GeoscienceAustralia/geodepy/graphs/contributors>`_ who have participated in this project.
\ No newline at end of file
diff --git a/docs/community/contributing.rst b/docs/community/contributing.rst
new file mode 100644
index 0000000..bf8e9d4
--- /dev/null
+++ b/docs/community/contributing.rst
@@ -0,0 +1,11 @@
+Contributing
+==================
+
+We welcome contributions from the community to help improve GeodePy! Whether you're fixing bugs, adding new features, or enhancing documentation, your input is valuable. Open source projects live and die based on the support they recieve.
+
+This document outlines some of the guidlines and advice for contributing to GeodePy.
+
+Code of Conduct
+----------------
+
+By participating in this project, you agree to abide by the `Python Software Foundation Code of Conduct <https://policies.python.org/python.org/code-of-conduct/>`_. Please read it to understand the expectations for behavior when contributing to this project.
\ No newline at end of file
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..333d706
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,59 @@
+# Configuration file for the Sphinx documentation builder.
+#
+# For the full list of built-in configuration values, see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+
+import os
+import sys
+
+# Add the path to your local source code
+sys.path.insert(0, os.path.abspath(".."))  # Adjust to your directory
+
+
+# -- 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'
+
+# -- General configuration ---------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
+
+extensions = ["sphinx.ext.autodoc", "sphinx.ext.napoleon", "sphinx.ext.viewcode"]
+
+templates_path = ['_templates']
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+
+html_sidebars = {
+    "**": [
+        "sidebar/brand.html",      # Logo
+        "sidebar/extra.html",      # Custom tagline + badge
+        "sidebar/scroll-start.html",
+        "sidebar/search.html",
+        "sidebar/navigation.html",
+        "sidebar/scroll-end.html",
+    ]
+}
+
+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_options = {
+    "light_logo": "geodepy-logo-light.png",
+    "dark_logo": "geodepy-logo-dark.png",
+    "sidebar_hide_name": True,
+}
+
+html_css_files = [
+    'custom.css',
+]
+html_js_files = [
+    'custom.js',
+]
\ No newline at end of file
diff --git a/docs/features/angles.rst b/docs/features/angles.rst
new file mode 100644
index 0000000..dd8123e
--- /dev/null
+++ b/docs/features/angles.rst
@@ -0,0 +1,148 @@
+.. _features/angles:
+ 
+Angles
+======
+
+Angle Types
+-----------
+
+GeodePy supports Angular Notation in 9 different formats
+
++------------------------+--------------------------------------------------------------+
+| ABRV                   | FORMAT (type)                                                |
++========================+==============================================================+
+| rad                    | Radians (stored as float)                                    |
++------------------------+--------------------------------------------------------------+
+| dec                    | Decimal Degrees (stored as float)                            |
++------------------------+--------------------------------------------------------------+
+| :ref:`dec <DECAngle>`  | Decimal Degrees (via DECAngle class)                         |
++------------------------+--------------------------------------------------------------+
+| hp                     | Hewlett Packard (HP) Notation (stored as float)              |
++------------------------+--------------------------------------------------------------+
+| :ref:`hpa <HPAngle>`   | Hewlett Packard (HP) Notation (via HPAngle class)            |
++------------------------+--------------------------------------------------------------+
+| gon                    | Gradians (stored as float)                                   |
++------------------------+--------------------------------------------------------------+
+| :ref:`gona <GONAngle>` | Gradians (via GONAngle class)                                |
++------------------------+--------------------------------------------------------------+
+| :ref:`dms <DMSAngle>`  | Degrees, Minutes and Seconds Notation (via DMSAngle class)   |
++------------------------+--------------------------------------------------------------+
+| :ref:`ddm <DDMAngle>`  | Degrees and Decimal Minutes Notation (via DDMAngle class)    |
++------------------------+--------------------------------------------------------------+
+
+Conversion between all formats is supported as shown below:
+
+* Radians to/from Decimal Degrees via builtin math.radians and math.degrees
+
+* Formats as floats to all other types via functions in the form abrv2abrv
+  
+  e.g. gon2hpa()
+
+* DECAngle, HPAngle, GONAngle, DMSAngle and DDMAngle class objects via methods in
+  the form CLASS.abrv()
+  
+  e.g. HPAngle(value).dec()
+
+All **angle classes** can be seen below:
+
+.. _DECAngle:
+
+.. autoclass:: geodepy.angles.DECAngle
+    :members:
+
+.. _HPAngle:
+
+.. autoclass:: geodepy.angles.HPAngle
+    :members:
+
+.. _GONAngle:
+
+.. autoclass:: geodepy.angles.GONAngle
+    :members:
+
+.. _DMSAngle:
+
+.. autoclass:: geodepy.angles.DMSAngle
+    :members:
+
+.. _DDMAngle:
+
+.. autoclass:: geodepy.angles.DDMAngle
+    :members:
+
+.. _converstions:
+
+-------------------
+
+Angle Conversions
+-----------------
+
+All conversion functions can be seen below.
+
+For converting **decimal degree** to other formats:
+
+.. autofunction:: geodepy.angles.dec2hp
+
+.. autofunction:: geodepy.angles.dec2hpa
+
+.. autofunction:: geodepy.angles.dec2gon
+
+.. autofunction:: geodepy.angles.dec2gona
+
+.. autofunction:: geodepy.angles.dec2dms
+
+.. autofunction:: geodepy.angles.dec2ddm
+
+-------------------
+
+For converting **Hewlett Packard** to other formats:
+
+
+.. autofunction:: geodepy.angles.hp2dec
+
+.. autofunction:: geodepy.angles.hp2deca
+
+.. autofunction:: geodepy.angles.hp2rad
+
+.. autofunction:: geodepy.angles.hp2gon
+
+.. autofunction:: geodepy.angles.hp2gona
+
+.. autofunction:: geodepy.angles.hp2dms
+
+.. autofunction:: geodepy.angles.hp2ddm
+
+-------------------
+
+For converting **Gradians** to other formats:
+
+.. autofunction:: geodepy.angles.gon2dec
+
+.. autofunction:: geodepy.angles.gon2deca
+
+.. autofunction:: geodepy.angles.gon2hp
+
+.. autofunction:: geodepy.angles.gon2hpa
+
+.. autofunction:: geodepy.angles.gon2rad
+
+.. autofunction:: geodepy.angles.gon2dms
+
+.. autofunction:: geodepy.angles.gon2ddm
+
+-------------------
+
+Other Converstion Functions:
+
+.. autofunction:: geodepy.angles.dd2sec
+
+..
+
+  .. autofunction:: geodepy.angles.dec2hp_v
+
+  .. autofunction:: geodepy.angles.hp2dec_v
+
+Angle Type Checking
+-------------------
+
+.. autofunction:: geodepy.angles.angular_typecheck
diff --git a/docs/features/constants.rst b/docs/features/constants.rst
new file mode 100644
index 0000000..b332113
--- /dev/null
+++ b/docs/features/constants.rst
@@ -0,0 +1,143 @@
+.. _features/constants:
+
+Constants
+=========
+
+This module contains constants commonly used in geodetic calculations, including ellipsoids, projections and transformations.
+
+Classes
+--------
+
+GeodePy provides four classes for handling commonly used geodetic constants. These include a class for ellipsoids, projections, tranformations and tranformations sigmas.
+These classes can be used to create objects that store the relevant parameters for each type of constant, and provide methods for accessing and manipulating these parameters.
+
+
+.. autoclass:: geodepy.constants.Ellipsoid
+    :members:
+
+.. autoclass:: geodepy.constants.Projection
+    :members:   
+
+.. autoclass:: geodepy.constants.Transformation
+    :members:
+
+    .. automethod:: __neg__
+    .. automethod:: __add__
+
+.. autoclass:: geodepy.constants.TransformationSD   
+    :members:
+
+Predefined Constants
+----------------------
+
+GeodePy also includes a set of predefined constants for commonly used ellipsoids, projections and transformations. These can be seen below.
+
+Ellipsoid
+^^^^^^^^^
+
+For :class:`~geodepy.constants.Ellipsoid`:
+
++-----------------------------+---------------------+-------------------------------------------------------------+
+| Name                        | Type                | Description                                                 |
++=============================+=====================+=============================================================+
+| grs80                       | Ellipsoid           | Geodetic Reference System 1980                              |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| wgs84                       | Ellipsoid           | World Geodetic System 1984                                  |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| ans                         | Ellipsoid           | Australian National Spheroid                                |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| intl24                      | Ellipsoid           | International (Hayford) 1924                                |
++-----------------------------+---------------------+-------------------------------------------------------------+
+
+Projection
+^^^^^^^^^^
+
+For :class:`~geodepy.constants.Projection`:
+
++-----------------------------+---------------------+-------------------------------------------------------------+
+| Name                        | Type                | Description                                                 |
++=============================+=====================+=============================================================+
+| utm                         | Projection          | Universal Transverse Mercator projection                    |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| isg                         | Projection          | Integrated Survey Grid (NSW, AGD66)                         |
++-----------------------------+---------------------+-------------------------------------------------------------+
+
+Transformation
+^^^^^^^^^^^^^^
+
+For :class:`~geodepy.constants.Transformation`:
+
++-----------------------------+---------------------+-------------------------------------------------------------+
+| Name                        | Type                | Description                                                 |
++=============================+=====================+=============================================================+
+| gda94_to_gda2020            | Transformation      | GDA94 to GDA2020 (national)                                 |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf2014_to_gda2020         | Transformation      | ITRF2014 to GDA2020                                         |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| atrf2014_to_gda2020         | Transformation      | ATRF2014 to GDA2020                                         |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf2008_to_gda94           | Transformation      | ITRF2008 to GDA94                                           |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf2005_to_gda94           | Transformation      | ITRF2005 to GDA94                                           |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf2000_to_gda94           | Transformation      | ITRF2000 to GDA94                                           |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf97_to_gda94             | Transformation      | ITRF97 to GDA94                                             |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf96_to_gda94             | Transformation      | ITRF96 to GDA94                                             |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| agd84_to_gda94              | Transformation      | AGD84 to GDA94                                              |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| agd66_to_gda94              | Transformation      | AGD66 to GDA94                                              |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| agd66_to_gda94_act          | Transformation      | AGD66 to GDA94 (ACT region)                                 |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| agd66_to_gda94_tas          | Transformation      | AGD66 to GDA94 (Tasmania region)                            |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| agd66_to_gda94_vicnsw       | Transformation      | AGD66 to GDA94 (Vic/NSW region)                             |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| agd66_to_gda94_nt           | Transformation      | AGD66 to GDA94 (NT region)                                  |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf2020_to_itrf2014        | Transformation      | ITRF2020 to ITRF2014                                        |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf2020_to_itrf2014_vel    | Transformation      | ITRF2020 to ITRF2014 (velocity only)                        |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf2020_to_itrf2008        | Transformation      | ITRF2020 to ITRF2008                                        |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf2020_to_itrf2005        | Transformation      | ITRF2020 to ITRF2005                                        |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf2020_to_itrf2000        | Transformation      | ITRF2020 to ITRF2000                                        |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf2020_to_itrf97          | Transformation      | ITRF2020 to ITRF97                                          |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf2020_to_itrf96          | Transformation      | ITRF2020 to ITRF96                                          |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf2020_to_itrf94          | Transformation      | ITRF2020 to ITRF94                                          |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf2020_to_itrf93          | Transformation      | ITRF2020 to ITRF93                                          |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf2020_to_itrf92          | Transformation      | ITRF2020 to ITRF92                                          |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf2020_to_itrf91          | Transformation      | ITRF2020 to ITRF91                                          |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf2020_to_itrf90          | Transformation      | ITRF2020 to ITRF90                                          |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf2020_to_itrf89          | Transformation      | ITRF2020 to ITRF89                                          |
++-----------------------------+---------------------+-------------------------------------------------------------+
+| itrf2020_to_itrf88          | Transformation      | ITRF2020 to ITRF88                                          |
++-----------------------------+---------------------+-------------------------------------------------------------+
+
+
+All other combinations of ITRF transofmrations are available.
+
+IERS to GeodePy Transformation
+------------------------------
+
+GeeodePy also includes a function for converting from IERS transfomration parameters to a GeodePy Transformation object.
+
+.. autofunction:: geodepy.constants.iers2trans
+
+Height
+---------
+
+The module also contains locations for files commonly used in height converstions that will be used in the :ref:`height <features/height>` module.
\ No newline at end of file
diff --git a/docs/features/convert.rst b/docs/features/convert.rst
new file mode 100644
index 0000000..4824b0d
--- /dev/null
+++ b/docs/features/convert.rst
@@ -0,0 +1,30 @@
+.. _features/convert:
+
+Converting
+===========
+
+This module contains functions for converting between different coordinate types. Each of the functions can be seen below.
+
+.. autofunction:: geodepy.convert.polar2rect
+
+.. autofunction:: geodepy.convert.rect2polar
+
+.. autofunction:: geodepy.convert.rect_radius
+
+.. autofunction:: geodepy.convert.alpha_coeff
+
+.. autofunction:: geodepy.convert.beta_coeff
+
+.. autofunction:: geodepy.convert.psfandgridconv
+
+.. autofunction:: geodepy.convert.geo2grid
+
+.. autofunction:: geodepy.convert.grid2geo
+
+.. autofunction:: geodepy.convert.xyz2llh
+
+.. autofunction:: geodepy.convert.llh2xyz
+
+.. autofunction:: geodepy.convert.date_to_yyyydoy
+
+.. autofunction:: geodepy.convert.yyyydoy_to_date  
\ No newline at end of file
diff --git a/docs/features/coord.rst b/docs/features/coord.rst
new file mode 100644
index 0000000..9bfb112
--- /dev/null
+++ b/docs/features/coord.rst
@@ -0,0 +1,15 @@
+.. _features/coord:
+
+Coordinates
+===========
+
+This module contains classes for coordinates and functions for converting between different coordinate types.
+
+.. autoclass:: geodepy.coord.CoordCart
+    :members:
+
+.. autoclass:: geodepy.coord.CoordGeo
+    :members:
+
+.. autoclass:: geodepy.coord.CoordTM
+    :members:
diff --git a/docs/features/geodesy.rst b/docs/features/geodesy.rst
new file mode 100644
index 0000000..b37aa29
--- /dev/null
+++ b/docs/features/geodesy.rst
@@ -0,0 +1,34 @@
+.. _features/geodesy:
+
+Geodesy
+=========
+
+This module includes functions for geodetic calculations.
+
+Convertions
+------------
+
+.. autofunction:: geodepy.geodesy.enu2xyz
+
+.. autofunction:: geodepy.geodesy.xyz2enu
+
+Vincenty
+--------
+
+.. autofunction:: geodepy.geodesy.vincdir
+
+.. autofunction:: geodepy.geodesy.vincinv
+
+.. autofunction:: geodepy.geodesy.vincdir_utm
+
+.. autofunction:: geodepy.geodesy.vincinv_utm
+
+Other Geodetic Functions
+--------------------------
+
+.. autofunction:: geodepy.geodesy.line_sf
+
+.. autofunction:: geodepy.geodesy.rho
+
+.. autofunction:: geodepy.geodesy.nu
+
diff --git a/docs/features/gnss.rst b/docs/features/gnss.rst
new file mode 100644
index 0000000..0321c00
--- /dev/null
+++ b/docs/features/gnss.rst
@@ -0,0 +1,60 @@
+.. _features/gnss:
+
+Sinex
+=====
+
+This module includes functions for dealing with sinex files.
+
+Reading Sinex Files
+----------------------
+
+.. autofunction:: geodepy.gnss.list_sinex_blocks
+.. autofunction:: geodepy.gnss.read_sinex_comments
+.. autofunction:: geodepy.gnss.read_sinex_header_line
+.. autofunction:: geodepy.gnss.read_sinex_custom
+.. autofunction:: geodepy.gnss.read_sinex_estimate
+.. autofunction:: geodepy.gnss.read_sinex_matrix
+.. autofunction:: geodepy.gnss.read_sinex_sites
+.. autofunction:: geodepy.gnss.read_disconts
+.. autofunction:: geodepy.gnss.read_solution_epochs
+.. autofunction:: geodepy.gnss.read_sinex_header_block
+.. autofunction:: geodepy.gnss.read_sinex_file_reference_block
+.. autofunction:: geodepy.gnss.read_sinex_input_acknowledgments_block
+.. autofunction:: geodepy.gnss.read_sinex_solution_statistics_block
+.. autofunction:: geodepy.gnss.read_sinex_site_receiver_block
+.. autofunction:: geodepy.gnss.read_sinex_site_antenna_block
+.. autofunction:: geodepy.gnss.read_sinex_site_gps_phase_center_block
+.. autofunction:: geodepy.gnss.read_sinex_site_eccentricity_block
+.. autofunction:: geodepy.gnss.read_sinex_site_id_block
+.. autofunction:: geodepy.gnss.read_sinex_solution_epochs_block
+.. autofunction:: geodepy.gnss.read_sinex_solution_estimate_block
+.. autofunction:: geodepy.gnss.read_sinex_solution_apriori_block
+.. autofunction:: geodepy.gnss.read_sinex_solution_matrix_estimate_block
+.. autofunction:: geodepy.gnss.read_sinex_solution_matrix_apriori_block
+
+Converting Sinex Data to DataFrames
+------------------------------------
+
+.. autofunction:: geodepy.gnss.matrix2dataframe_solution_matrix_estimate
+.. autofunction:: geodepy.gnss.sinex2dataframe_solution_estimate
+.. autofunction:: geodepy.gnss.sinex2dataframe_solution_apriori
+.. autofunction:: geodepy.gnss.sinex2dataframe_solution_matrix_estimate
+
+Writing Sinex Files
+--------------------
+
+.. autofunction:: geodepy.gnss.print_sinex_comments
+.. autofunction:: geodepy.gnss.set_creation_time
+.. autofunction:: geodepy.gnss.dataframe2sinex_solution_estimate
+.. autofunction:: geodepy.gnss.dataframe2sinex_solution_apriori
+.. autofunction:: geodepy.gnss.dataframe2matrix_snx_vcv
+.. autofunction:: geodepy.gnss.dataframe2matrix_solution_matrix_estimate
+.. autofunction:: geodepy.gnss.dataframe2sinex_solution_matrix_estimate
+.. autofunction:: geodepy.gnss.writeSINEX
+
+Specific Sinex Functions
+--------------------------
+
+.. autofunction:: geodepy.gnss.remove_stns_sinex
+.. autofunction:: geodepy.gnss.remove_velocity_sinex
+.. autofunction:: geodepy.gnss.remove_matrixzeros_sinex
\ No newline at end of file
diff --git a/docs/features/height.rst b/docs/features/height.rst
new file mode 100644
index 0000000..25fc175
--- /dev/null
+++ b/docs/features/height.rst
@@ -0,0 +1,4 @@
+.. _features/height:  
+
+Vertical Datums
+=================
\ No newline at end of file
diff --git a/docs/features/index.rst b/docs/features/index.rst
new file mode 100644
index 0000000..31c2e95
--- /dev/null
+++ b/docs/features/index.rst
@@ -0,0 +1,24 @@
+.. _features/index:
+
+Features
+========
+
+This section provides an overview of all features available in GeodePy, split into their respective modules.
+
+.. container:: collapsible-toc
+
+   .. toctree::
+      :maxdepth: 2
+
+      angles
+      constants
+      convert
+      coord
+      geodesy
+      gnss
+      height
+      inputoutput
+      ntv2reader
+      statistics
+      survey
+      transform
\ No newline at end of file
diff --git a/docs/features/inputoutput.rst b/docs/features/inputoutput.rst
new file mode 100644
index 0000000..8586ef7
--- /dev/null
+++ b/docs/features/inputoutput.rst
@@ -0,0 +1,18 @@
+.. _features/inputoutput:
+
+Input and Output
+================
+
+This module has functions that operate as a backend for a GUI. The functions have been rewritten from the transform module using pandas.
+
+Converting
+-----------------------
+
+.. autofunction:: geodepy.inputoutput.grid2geoio
+.. autofunction:: geodepy.inputoutput.geo2gridio
+
+
+Transformations
+----------------
+
+.. autofunction:: geodepy.inputoutput.gdatrans7
diff --git a/docs/features/ntv2reader.rst b/docs/features/ntv2reader.rst
new file mode 100644
index 0000000..5caae8c
--- /dev/null
+++ b/docs/features/ntv2reader.rst
@@ -0,0 +1,26 @@
+.. _features/ntv2reader:
+
+NTV2 Reader
+===============
+
+Tihs module provides functionality to read and utilize NTV2 grid files for coordinate transformations.
+It has been adapted from Jaimie Dodd's ntv2reader.py
+
+Classes
+-------
+
+.. autoclass:: geodepy.ntv2reader.NTv2Grid
+   :members:
+
+.. autoclass:: geodepy.ntv2reader.SubGrid
+   :members:
+
+Functions
+---------
+
+.. autofunction:: geodepy.ntv2reader.read_ntv2_file
+.. autofunction:: geodepy.ntv2reader.interpolate_ntv2
+.. autofunction:: geodepy.ntv2reader.read_node
+.. autofunction:: geodepy.ntv2reader.bilinear_interpolation
+.. autofunction:: geodepy.ntv2reader.bicubic_interpolation
+
diff --git a/docs/features/statistics.rst b/docs/features/statistics.rst
new file mode 100644
index 0000000..6eb6471
--- /dev/null
+++ b/docs/features/statistics.rst
@@ -0,0 +1,26 @@
+.. _features/statistics:
+
+Statistics
+==========
+
+This module looks at calculating error, VCV matrix transformations, and rotation matrices.
+
+Error
+------
+
+.. autofunction:: geodepy.statistics.error_ellipse
+
+.. autofunction:: geodepy.statistics.relative_error
+.. autofunction:: geodepy.statistics.circ_hz_pu
+.. autofunction:: geodepy.statistics.k_val95
+
+VCV Matrix Transformations
+-------------------------------
+
+.. autofunction:: geodepy.statistics.vcv_cart2local
+.. autofunction:: geodepy.statistics.vcv_local2cart
+
+Rotation Matrix
+---------------
+
+.. autofunction:: geodepy.statistics.rotation_matrix
\ No newline at end of file
diff --git a/docs/features/survey.rst b/docs/features/survey.rst
new file mode 100644
index 0000000..87a5bd9
--- /dev/null
+++ b/docs/features/survey.rst
@@ -0,0 +1,26 @@
+.. _features/survey:
+
+Surveying Calculations
+=======================
+
+This module provides various surveying calculation functions commonly used in geodetic and surveying applications.
+
+EDM Corrections
+-----------------
+
+.. autofunction:: geodepy.survey.va_conv
+.. autofunction:: geodepy.survey.first_vel_params
+.. autofunction:: geodepy.survey.part_h2o_vap_press
+.. autofunction:: geodepy.survey.first_vel_corrn
+.. autofunction:: geodepy.survey.mets_partial_differentials
+.. autofunction:: geodepy.survey.refractivity_constants
+.. autofunction:: geodepy.survey.phase_refractivity
+.. autofunction:: geodepy.survey.group_refractivity
+.. autofunction:: geodepy.survey.humidity2part_water_vapour_press
+
+
+Angle Calculations
+------------------
+
+.. autofunction:: geodepy.survey.joins
+.. autofunction:: geodepy.survey.radiations
\ No newline at end of file
diff --git a/docs/features/transform.rst b/docs/features/transform.rst
new file mode 100644
index 0000000..1be51df
--- /dev/null
+++ b/docs/features/transform.rst
@@ -0,0 +1,27 @@
+.. _features/transform:
+
+Transforming
+=================
+
+This module provides functions for transforming coordinates between different geodetic datums. It includes methods for performing Helmert transformations, functions for various 
+common geodetic transformations and support for NTv2 2D grid-based transformations.
+
+Helmert Transformations
+-----------------------
+
+.. autofunction:: geodepy.transform.conform7
+
+.. autofunction:: geodepy.transform.conform14
+
+Common Geodetic Transformations
+--------------------------------
+
+.. autofunction:: geodepy.transform.transform_mga94_to_mga2020
+.. autofunction:: geodepy.transform.transform_mga2020_to_mga94
+.. autofunction:: geodepy.transform.transform_atrf2014_to_gda2020
+.. autofunction:: geodepy.transform.transform_gda2020_to_atrf2014
+
+NTv2 Transformations
+----------------------
+
+.. autofunction:: geodepy.transform.ntv2_2d
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..d627943
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,69 @@
+.. GeodePy documentation master file, created by
+   sphinx-quickstart on Wed Nov  5 03:43:35 2025.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+GeodePy: Geodesy in Python
+======================================================
+
+Release v0.6.0
+
+.. image:: https://static.pepy.tech/personalized-badge/geodepy?period=total&units=INTERNATIONAL_SYSTEM&left_color=GREY&right_color=BLUE&left_text=downloads
+    :target: https://pepy.tech/project/geodepy
+    :alt: Total Downloads Badge
+
+.. image:: https://img.shields.io/badge/license-Apache_2.0-green
+    :target: https://opensource.org/licenses/Apache-2.0
+    :alt: License Badge
+
+.. image:: https://img.shields.io/badge/PyPi-GeodePy-yellow
+    :target: https://pypi.org/project/geodepy/
+    :alt: Pypi Badge
+
+.. image:: https://img.shields.io/badge/Paper-GDA2020_Technical_Manual-556472
+    :target: https://www.anzlic.gov.au/ICSM
+    :alt: Paper Badge
+
+**GeodePy** is a package of tools for manipulating geospatial datasets using Python.
+
+-------------------
+
+Features
+--------
+
+GeodePy includes a variety of :ref:`features <features/index>` for geodesy and geospatial data manipulation, including:
+
+* :ref:`Converting <features/convert>` between coordinate types
+* :ref:`Transforming <features/transform>` between datums
+* Calculating :ref:`geodetic <features/geodesy>` distances and bearings
+* Working with :ref:`geoid <features/height>` models
+* :ref:`Surveying <features/survey>` calculations
+* Various classes for :ref:`angles <features/angles>` , :ref:`corrdinates <features/coord>`, and :ref:`datums <features/constants>`
+* :ref:`Statistics <features/statistics>`
+* And more!
+
+User Guide
+--------------
+
+This section contains the user guide for GeodePy, including installation, instructions, features and tutorials.
+
+.. toctree::
+   :maxdepth: 2
+   :caption: User Guide
+
+   installation
+   quickstart
+   features/index
+   tutorials/index
+
+Community Guide
+---------------
+
+This section contains information for contributors to the GeodePy project.
+
+.. toctree::
+   :maxdepth: 3
+   :caption: Community Guide
+
+   community/contributing
+   community/authors
diff --git a/docs/installation.rst b/docs/installation.rst
new file mode 100644
index 0000000..cf7b10d
--- /dev/null
+++ b/docs/installation.rst
@@ -0,0 +1,33 @@
+.. _installation:
+
+Installation
+============
+
+This section contains instructions for installing GeodePy.
+
+Installing via pip
+--------------------
+The recommended way to install GeodePy is via pip. You can do this by running the following command in your terminal:
+
+.. code:: bash
+    
+    pip install geodepy
+
+
+Installing from source
+----------------------
+If you prefer to install GeodePy from source, you can clone the repository from GitHub and install it manually. Here are the steps:
+
+.. code:: bash
+
+   git clone https://github.com/GeoscienceAustralia/GeodePy.git
+
+.. _updating:
+
+Updating GeodePy
+-----------------
+To update GeodePy to the latest version, you can use pip with the --upgrade flag:
+
+.. code:: bash
+
+    pip install --upgrade geodepy   
diff --git a/docs/make.bat b/docs/make.bat
new file mode 100644
index 0000000..32bb245
--- /dev/null
+++ b/docs/make.bat
@@ -0,0 +1,35 @@
+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+	set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=.
+set BUILDDIR=_build
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+	echo.
+	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+	echo.installed, then set the SPHINXBUILD environment variable to point
+	echo.to the full path of the 'sphinx-build' executable. Alternatively you
+	echo.may add the Sphinx directory to PATH.
+	echo.
+	echo.If you don't have Sphinx installed, grab it from
+	echo.https://www.sphinx-doc.org/
+	exit /b 1
+)
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+
+:end
+popd
diff --git a/docs/quickstart.rst b/docs/quickstart.rst
new file mode 100644
index 0000000..183c55a
--- /dev/null
+++ b/docs/quickstart.rst
@@ -0,0 +1,52 @@
+Quickstart
+==========
+
+Ready to get started? This page gives a good introduction to using GeodePy.
+
+First, ensure that:
+
+* GeodePy is :ref:`installed <installation>`
+* GeodePy is :ref:`up-to-date <updating>`
+
+Let's get started with a simple example.
+
+Transforming from MGA94 to MGA2020
+-----------------------------------
+
+Begin by importing GeodePy:
+
+.. code:: python
+
+    import geodepy.transform as tr   
+
+Next, define some coordinate values in MGA94:
+
+.. code:: python
+
+    zone_94 = 55
+    east_94 = 696053.3373
+    north_94 = 6086610.1338
+
+Now, transform this coordinate to MGA2020:
+
+.. code:: python
+
+    (zone_20, east_20, north_20, _, _) = tr.transform_mga94_to_mga2020(
+        zone_94,
+        east_94,
+        north_94
+    )
+
+Finally, print the transformed coordinate:
+
+.. code:: python
+
+    print(zone_20, east_20, north_20)
+
+This will output the latitude, longitude, and height of the coordinate in MGA2020.
+
+.. code::
+
+    >> 55 696053.872 6086611.549
+
+For more detailed examples and tutorials, please refer to the :ref:`features <features/index>` and :ref:`tutorial <tutorials/index>` section.
\ No newline at end of file
diff --git a/docs/requirements.txt b/docs/requirements.txt
new file mode 100644
index 0000000..6e377ee
--- /dev/null
+++ b/docs/requirements.txt
@@ -0,0 +1,2 @@
+furo
+pandas
\ No newline at end of file
diff --git a/docs/tutorials/anglestut.rst b/docs/tutorials/anglestut.rst
new file mode 100644
index 0000000..142b5c9
--- /dev/null
+++ b/docs/tutorials/anglestut.rst
@@ -0,0 +1,44 @@
+.. _tutorials/angles:
+
+Angle Classes and Converstions
+=================================
+
+GeodePy has 5 main angle classes to represent angles in different formats. These will be explored here along with how to convert between these types.
+
+Creating Angle Class
+--------------------
+
+First import GeodePy
+
+.. code:: python
+
+    import geodepy.angles as angles  
+
+In this example a DMS angle will be created. This object can be initalised by including the degrees, minutes and seconds as arguments.
+
+.. code:: python
+
+    angle1 = angles.DMSAngle(30, 5, 42)
+    print(angle1)
+
+    >> 30 5 42
+
+The methods within the class can be used to convert the angle into different types. This is seen below:
+
+.. code:: python
+
+    print(angle1.ddm())
+    print(angle1.dec())
+    print(angle1.gona())
+    print(angle1.hpa())
+    print(angle1.rad())
+
+    >>30 5.7
+    >>30.095
+    >>33.4388888889
+    >>30.0542
+    >>0.5252568383876934
+
+This can be completed with any of the 5 angle classes within GeodePy. To complete math on the angle classes the following can be completed.
+
+
diff --git a/docs/tutorials/convert.rst b/docs/tutorials/convert.rst
new file mode 100644
index 0000000..b4520b6
--- /dev/null
+++ b/docs/tutorials/convert.rst
@@ -0,0 +1,2 @@
+Converting
+===========
\ No newline at end of file
diff --git a/docs/tutorials/coordtut.rst b/docs/tutorials/coordtut.rst
new file mode 100644
index 0000000..bebea49
--- /dev/null
+++ b/docs/tutorials/coordtut.rst
@@ -0,0 +1,4 @@
+.. _tutorials/coord:
+
+Coordinate Classes and Conversions
+=============================================
\ No newline at end of file
diff --git a/docs/tutorials/index.rst b/docs/tutorials/index.rst
new file mode 100644
index 0000000..e8f8c53
--- /dev/null
+++ b/docs/tutorials/index.rst
@@ -0,0 +1,13 @@
+.. _tutorials/index:
+
+Tutorials
+===========
+
+.. toctree::
+   :maxdepth: 2
+
+   anglestut
+   coordtut
+   vincenty
+   convert
+   transform
\ No newline at end of file
diff --git a/docs/tutorials/transform.rst b/docs/tutorials/transform.rst
new file mode 100644
index 0000000..490b660
--- /dev/null
+++ b/docs/tutorials/transform.rst
@@ -0,0 +1,2 @@
+Transforming
+=================
\ No newline at end of file
diff --git a/docs/tutorials/vincenty.rst b/docs/tutorials/vincenty.rst
new file mode 100644
index 0000000..7d3e3f7
--- /dev/null
+++ b/docs/tutorials/vincenty.rst
@@ -0,0 +1,4 @@
+.. _tutorials/vincenty:
+
+Vincenty Formula
+================
\ No newline at end of file
diff --git a/geodepy/angles.py b/geodepy/angles.py
index 87f93ef..96532e3 100644
--- a/geodepy/angles.py
+++ b/geodepy/angles.py
@@ -37,11 +37,13 @@
 class DECAngle(float):
     """
     Class for working with angles in Decimal Degrees
+
     Note: GeodePy also supports working with angles in Decimal Degrees as floats
     """
 
     def __init__(self, dec_angle=0.0):
         """
+
         :param dec_angle: float Decimal Degrees angle
         """
         super().__init__()
@@ -49,58 +51,61 @@ def __init__(self, dec_angle=0.0):
 
     def __repr__(self):
         if self.dec_angle >= 0:
-            return '{DECAngle: +' + str(self.dec_angle) + '}'
+            return "{DECAngle: +" + str(self.dec_angle) + "}"
         else:  # negative
-            return '{DECAngle: ' + str(self.dec_angle) + '}'
+            return "{DECAngle: " + str(self.dec_angle) + "}"
 
     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')
+            raise TypeError(
+                "Can only subtract Angle objects with .dec() method" " together"
+            )
 
     def __rsub__(self, other):
         try:
             return DECAngle(other.dec() - self.dec())
         except AttributeError:
-            raise TypeError('Can only subtract Angle objects with .dec() method'
-                            ' together')
+            raise TypeError(
+                "Can only subtract Angle objects with .dec() method" " together"
+            )
 
     def __mul__(self, other):
         try:
             return DECAngle(self.dec() * other)
         except TypeError:
-            raise TypeError('Multiply only defined between DECAngle Object '
-                            'and Int or Float')
+            raise TypeError(
+                "Multiply only defined between DECAngle Object " "and Int or Float"
+            )
 
     def __rmul__(self, other):
         try:
             return DECAngle(other * self.dec())
         except TypeError:
-            raise TypeError('Multiply only defined between DECAngle Object '
-                            'and Int or Float')
+            raise TypeError(
+                "Multiply only defined between DECAngle Object " "and Int or Float"
+            )
 
     def __truediv__(self, other):
         try:
             return DECAngle(self.dec() / other)
         except TypeError:
-            raise TypeError('Division only defined between DECAngle Object '
-                            'and Int or Float')
+            raise TypeError(
+                "Division only defined between DECAngle Object " "and Int or Float"
+            )
 
     def __abs__(self):
         return DECAngle(abs(self.dec_angle))
@@ -135,6 +140,7 @@ def __round__(self, n=None):
     def rad(self):
         """
         Convert to radians
+
         :return: radians
         :rtype: float
         """
@@ -143,6 +149,7 @@ def rad(self):
     def dec(self):
         """
         Convert to Decimal Degrees (float)
+
         :return: Decimal Degrees
         :rtype: float
         """
@@ -151,6 +158,7 @@ def dec(self):
     def hp(self):
         """
         Convert to HP Notation
+
         :return: HP Notation (DDD.MMSSSS)
         :rtype: float
         """
@@ -159,6 +167,7 @@ def hp(self):
     def hpa(self):
         """
         Convert to HP Notation (class)
+
         :return: HP Notation (DDD.MMSSSS)
         :rtype: HPAngle
         """
@@ -167,6 +176,7 @@ def hpa(self):
     def gon(self):
         """
         Convert to Gradians (float)
+
         :return: Gradians
         :rtype: float
         """
@@ -175,6 +185,7 @@ def gon(self):
     def gona(self):
         """
         Convert to Gradians (class)
+
         :return: Gradians
         :rtype: GONAngle
         """
@@ -183,6 +194,7 @@ def gona(self):
     def dms(self):
         """
         Convert to Degrees, Minutes, Seconds Object
+
         :return: Degrees, Minutes, Seconds Object
         :rtype: DMSAngle
         """
@@ -191,6 +203,7 @@ def dms(self):
     def ddm(self):
         """
         Convert to Degrees, Decimal Minutes Object
+
         :return: Degrees, Decimal Minutes Object
         :rtype: DDMAngle
         """
@@ -200,77 +213,85 @@ def ddm(self):
 class HPAngle(object):
     """
     Class for working with angles in Hewlett-Packard (HP) format
+
     Note: GeodePy also supports working with angles in HP format as floats
     """
+
     def __init__(self, hp_angle=0.0):
         """
         :param hp_angle: float HP angle
         """
         self.hp_angle = float(hp_angle)
-        hp_dec_str = f'{self.hp_angle:.17f}'.split('.')[1]
+        hp_dec_str = f"{self.hp_angle:.17f}".split(".")[1]
         if int(hp_dec_str[0]) > 5:
-            raise ValueError(f'Invalid HP Notation: 1st decimal place greater '
-                             f'than 5: {self.hp_angle}')
+            raise ValueError(
+                f"Invalid HP Notation: 1st decimal place greater "
+                f"than 5: {self.hp_angle}"
+            )
         if len(hp_dec_str) > 2:
             if int(hp_dec_str[2]) > 5:
                 raise ValueError(
-                    f'Invalid HP Notation: 3rd decimal place greater '
-                    f'than 5: {self.hp_angle}')
+                    f"Invalid HP Notation: 3rd decimal place greater "
+                    f"than 5: {self.hp_angle}"
+                )
 
     def __repr__(self):
         if self.hp_angle >= 0:
-            return '{HPAngle: +' + str(self.hp_angle) + '}'
+            return "{HPAngle: +" + str(self.hp_angle) + "}"
         else:  # negative
-            return '{HPAngle: ' + str(self.hp_angle) + '}'
+            return "{HPAngle: " + str(self.hp_angle) + "}"
 
     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')
+            raise TypeError(
+                "Can only subtract Angle objects with .dec() method" " together"
+            )
 
     def __rsub__(self, other):
         try:
             return HPAngle(dec2hp(other.dec() - self.dec()))
         except AttributeError:
-            raise TypeError('Can only subtract Angle objects with .dec() method'
-                            ' together')
+            raise TypeError(
+                "Can only subtract Angle objects with .dec() method" " together"
+            )
 
     def __mul__(self, other):
         try:
             return HPAngle(dec2hp(self.dec() * other))
         except TypeError:
-            raise TypeError('Multiply only defined between Angle objects and '
-                            'Int or Float')
+            raise TypeError(
+                "Multiply only defined between Angle objects and " "Int or Float"
+            )
 
     def __rmul__(self, other):
         try:
             return HPAngle(dec2hp(other * self.dec()))
         except TypeError:
-            raise TypeError('Multiply only defined between Angle objects and '
-                            'Int or Float')
+            raise TypeError(
+                "Multiply only defined between Angle objects and " "Int or Float"
+            )
 
     def __truediv__(self, other):
         try:
             return HPAngle(dec2hp(self.dec() / other))
         except TypeError:
-            raise TypeError('Division only defined between HPAngle objects '
-                            'and Int or Float')
+            raise TypeError(
+                "Division only defined between HPAngle objects " "and Int or Float"
+            )
 
     def __abs__(self):
         return HPAngle(abs(self.hp_angle))
@@ -305,6 +326,7 @@ def __round__(self, n=None):
     def rad(self):
         """
         Convert to Radians
+
         :return: Radians
         :rtype: float
         """
@@ -313,6 +335,7 @@ def rad(self):
     def dec(self):
         """
         Convert to Decimal Degrees (float)
+
         :return: Decimal Degrees
         :rtype: float
         """
@@ -321,6 +344,7 @@ def dec(self):
     def deca(self):
         """
         Convert to Decimal Degrees (class)
+
         :return: Decimal Degrees
         :rtype: DECAngle
         """
@@ -329,6 +353,7 @@ def deca(self):
     def hp(self):
         """
         Convert to HP Notation (float)
+
         :return: HP Notation (DDD.MMSSSS)
         :rtype: float
         """
@@ -337,6 +362,7 @@ def hp(self):
     def gon(self):
         """
         Convert to Gradians (float)
+
         :return: Gradians
         :rtype: float
         """
@@ -345,6 +371,7 @@ def gon(self):
     def gona(self):
         """
         Convert to Gradians (class)
+
         :return: Gradians
         :rtype: GONAngle
         """
@@ -353,6 +380,7 @@ def gona(self):
     def dms(self):
         """
         Convert to Degrees, Minutes, Seconds Object
+
         :return: Degrees, Minutes, Seconds Object
         :rtype: DMSAngle
         """
@@ -361,6 +389,7 @@ def dms(self):
     def ddm(self):
         """
         Convert to Degrees, Decimal Minutes Object
+
         :return: Degrees, Decimal Minutes Object
         :rtype: DDMAngle
         """
@@ -370,8 +399,10 @@ def ddm(self):
 class GONAngle(object):
     """
     Class for working with angles in Gradians (90 degrees == 100 Gradians)
+
     Note: GeodePy also supports working with angles in Gradians as floats
     """
+
     def __init__(self, gon_angle=0.0):
         """
         :param gon_angle: float Gradian angle
@@ -381,58 +412,61 @@ def __init__(self, gon_angle=0.0):
 
     def __repr__(self):
         if self.gon_angle >= 0:
-            return '{GONAngle: +' + str(self.gon_angle) + '}'
+            return "{GONAngle: +" + str(self.gon_angle) + "}"
         else:  # negative
-            return '{GONAngle: ' + str(self.gon_angle) + '}'
+            return "{GONAngle: " + str(self.gon_angle) + "}"
 
     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')
+            raise TypeError(
+                "Can only subtract Angle objects with .dec() method" " together"
+            )
 
     def __rsub__(self, other):
         try:
             return GONAngle(dec2gon(other.dec() - self.dec()))
         except AttributeError:
-            raise TypeError('Can only subtract Angle objects with .dec() method'
-                            ' together')
+            raise TypeError(
+                "Can only subtract Angle objects with .dec() method" " together"
+            )
 
     def __mul__(self, other):
         try:
             return GONAngle(dec2gon(self.dec() * other))
         except TypeError:
-            raise TypeError('Multiply only defined between Angle objects and '
-                            'Int or Float')
+            raise TypeError(
+                "Multiply only defined between Angle objects and " "Int or Float"
+            )
 
     def __rmul__(self, other):
         try:
             return GONAngle(dec2gon(other * self.dec()))
         except TypeError:
-            raise TypeError('Multiply only defined between Angle objects and '
-                            'Int or Float')
+            raise TypeError(
+                "Multiply only defined between Angle objects and " "Int or Float"
+            )
 
     def __truediv__(self, other):
         try:
             return GONAngle(dec2gon(self.dec() / other))
         except TypeError:
-            raise TypeError('Division only defined between HPAngle objects '
-                            'and Int or Float')
+            raise TypeError(
+                "Division only defined between HPAngle objects " "and Int or Float"
+            )
 
     def __abs__(self):
         return GONAngle(abs(self.gon_angle))
@@ -467,6 +501,7 @@ def __round__(self, n=None):
     def rad(self):
         """
         Convert to Radians
+
         :return: Radians
         :rtype: float
         """
@@ -475,6 +510,7 @@ def rad(self):
     def dec(self):
         """
         Convert to Decimal Degrees (float)
+
         :return: Decimal Degrees
         :rtype: float
         """
@@ -483,6 +519,7 @@ def dec(self):
     def deca(self):
         """
         Convert to Decimal Degrees (class)
+
         :return: Decimal Degrees
         :rtype: DECAngle
         """
@@ -491,6 +528,7 @@ def deca(self):
     def hp(self):
         """
         Convert to HP Notation (float)
+
         :return: HP Notation (DDD.MMSSSS)
         :rtype: float
         """
@@ -499,6 +537,7 @@ def hp(self):
     def hpa(self):
         """
         Convert to HP Notation (class)
+
         :return: HP Notation (DDD.MMSSSS)
         :rtype: HPAngle
         """
@@ -507,6 +546,7 @@ def hpa(self):
     def gon(self):
         """
         Convert to Gradians (float)
+
         :return: Gradians
         :rtype: float
         """
@@ -515,6 +555,7 @@ def gon(self):
     def dms(self):
         """
         Convert to Degrees, Minutes, Seconds Object
+
         :return: Degrees, Minutes, Seconds Object
         :rtype: DMSAngle
         """
@@ -523,6 +564,7 @@ def dms(self):
     def ddm(self):
         """
         Convert to Degrees, Decimal Minutes Object
+
         :return: Degrees, Decimal Minutes Object
         :rtype: DDMAngle
         """
@@ -533,8 +575,10 @@ class DMSAngle(object):
     """
     Class for working with angles in Degrees, Minutes and Seconds format
     """
+
     def __init__(self, degree, minute=0, second=0.0, positive=None):
         """
+
         :param degree: Angle: whole degrees component (floats truncated)
                        Alt: formatted string '±DDD MM SS.SSS'
         :type degree: float | str
@@ -544,9 +588,10 @@ def __init__(self, degree, minute=0, second=0.0, positive=None):
         :type second: float
         :param positive: Optional. True is positive, False is negative. Evaluated from deg/min/sec where None
         :type positive: bool
+
         """
         # evaluate sign
-        if positive is False or str(degree)[0] == '-':
+        if positive is False or str(degree)[0] == "-":
             self.positive = False
         else:
             self.positive = True
@@ -571,60 +616,71 @@ def __init__(self, degree, minute=0, second=0.0, positive=None):
 
     def __repr__(self):
         if self.positive:
-            signsymbol = '+'
+            signsymbol = "+"
         else:
-            signsymbol = '-'
-        return '{DMSAngle: ' + signsymbol + str(self.degree) + 'd ' +\
-               str(self.minute) + 'm ' + str(self.second) + 's}'
+            signsymbol = "-"
+        return (
+            "{DMSAngle: "
+            + signsymbol
+            + str(self.degree)
+            + "d "
+            + str(self.minute)
+            + "m "
+            + str(self.second)
+            + "s}"
+        )
 
     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')
+            raise TypeError(
+                "Can only subtract Angle objects with .dec() method" " together"
+            )
 
     def __rsub__(self, other):
         try:
             return dec2dms(other.dec() - self.dec())
         except AttributeError:
-            raise TypeError('Can only subtract Angle objects with .dec() method'
-                            ' together')
+            raise TypeError(
+                "Can only subtract Angle objects with .dec() method" " together"
+            )
 
     def __mul__(self, other):
         try:
             return dec2dms(self.dec() * other)
         except TypeError:
-            raise TypeError('Multiply only defined between DMSAngle Object '
-                            'and Int or Float')
+            raise TypeError(
+                "Multiply only defined between DMSAngle Object " "and Int or Float"
+            )
 
     def __rmul__(self, other):
         try:
             return dec2dms(other * self.dec())
         except TypeError:
-            raise TypeError('Multiply only defined between DMSAngle Object '
-                            'and Int or Float')
+            raise TypeError(
+                "Multiply only defined between DMSAngle Object " "and Int or Float"
+            )
 
     def __truediv__(self, other):
         try:
             return dec2dms(self.dec() / other)
         except TypeError:
-            raise TypeError('Division only defined between DMSAngle Object '
-                            'and Int or Float')
+            raise TypeError(
+                "Division only defined between DMSAngle Object " "and Int or Float"
+            )
 
     def __abs__(self):
         return DMSAngle(self.degree, self.minute, self.second)
@@ -649,11 +705,11 @@ def __gt__(self, other):
 
     def __str__(self):
         if self.positive:
-            return (str(self.degree) + ' ' + str(self.minute) + ' '
-                    + str(self.second))
+            return str(self.degree) + " " + str(self.minute) + " " + str(self.second)
         else:
-            return ('-' + str(self.degree) + ' ' + str(self.minute) + ' '
-                    + str(self.second))
+            return (
+                "-" + str(self.degree) + " " + str(self.minute) + " " + str(self.second)
+            )
 
     def __round__(self, n=None):
         if self.positive:
@@ -667,6 +723,7 @@ def __mod__(self, other):
     def rad(self):
         """
         Convert to Radians
+
         :return: Radians
         :rtype: float
         """
@@ -675,6 +732,7 @@ def rad(self):
     def dec(self):
         """
         Convert to Decimal Degrees (float)
+
         :return: Decimal Degrees
         :rtype: float
         """
@@ -686,6 +744,7 @@ def dec(self):
     def deca(self):
         """
         Convert to Decimal Degrees (class)
+
         :return: Decimal Degrees
         :rtype: DECAngle
         """
@@ -694,6 +753,7 @@ def deca(self):
     def hp(self):
         """
         Convert to HP Notation (float)
+
         :return: HP Notation (DDD.MMSSSS)
         :rtype: float
         """
@@ -705,6 +765,7 @@ def hp(self):
     def hpa(self):
         """
         Convert to HP Notation (class)
+
         :return: HP Notation (DDD.MMSSSS)
         :rtype: HPAngle
         """
@@ -713,6 +774,7 @@ def hpa(self):
     def gon(self):
         """
         Convert to Gradians (float)
+
         :return: Gradians
         :rtype: float
         """
@@ -721,6 +783,7 @@ def gon(self):
     def gona(self):
         """
         Convert to Gradians (class)
+
         :return: Gradians
         :rtype: GONAngle
         """
@@ -729,19 +792,21 @@ def gona(self):
     def ddm(self):
         """
         Convert to Degrees, Decimal Minutes Object
+
         :return: Degrees, Decimal Minutes Object
         :rtype: DDMAngle
         """
         if self.positive:
-            return DDMAngle(self.degree, self.minute + (self.second/60))
+            return DDMAngle(self.degree, self.minute + (self.second / 60))
         else:
-            return -DDMAngle(self.degree, self.minute + (self.second/60))
+            return -DDMAngle(self.degree, self.minute + (self.second / 60))
 
 
 class DDMAngle(object):
     """
     Class for working with angles in Degrees, Decimal Minutes format
     """
+
     def __init__(self, degree, minute=0.0, positive=None):
         """
         :param degree: Angle: whole degrees component (floats truncated)
@@ -753,7 +818,7 @@ def __init__(self, degree, minute=0.0, positive=None):
         """
 
         # evaluate sign
-        if positive is False or str(degree)[0] == '-':
+        if positive is False or str(degree)[0] == "-":
             self.positive = False
         else:
             self.positive = True
@@ -765,7 +830,7 @@ def __init__(self, degree, minute=0.0, positive=None):
 
         # Convert formatted string 'DDD MM.MMMM' to DDMAngle
         if type(degree) == str:
-            str_pts = degree.split(' ')
+            str_pts = degree.split(" ")
             degree = int(str_pts[0])
             minute = float(str_pts[1])
 
@@ -774,60 +839,69 @@ def __init__(self, degree, minute=0.0, positive=None):
 
     def __repr__(self):
         if self.positive:
-            signsymbol = '+'
+            signsymbol = "+"
         else:
-            signsymbol = '-'
-        return '{DDMAngle: ' + signsymbol + str(self.degree) + 'd ' + \
-               str(self.minute) + 'm}'
+            signsymbol = "-"
+        return (
+            "{DDMAngle: "
+            + signsymbol
+            + str(self.degree)
+            + "d "
+            + str(self.minute)
+            + "m}"
+        )
 
     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')
+            raise TypeError(
+                "Can only subtract Angle objects with .dec() method" " together"
+            )
 
     def __rsub__(self, other):
         try:
             return dec2ddm(other.dec() - self.dec())
         except AttributeError:
-            raise TypeError('Can only subtract Angle objects with .dec() method'
-                            ' together')
+            raise TypeError(
+                "Can only subtract Angle objects with .dec() method" " together"
+            )
 
     def __mul__(self, other):
         try:
             return dec2ddm(self.dec() * other)
         except TypeError:
-            raise TypeError('Multiply only defined between DMSAngle Object '
-                            'and Int or Float')
+            raise TypeError(
+                "Multiply only defined between DMSAngle Object " "and Int or Float"
+            )
 
     def __rmul__(self, other):
         try:
             return dec2ddm(other * self.dec())
         except TypeError:
-            raise TypeError('Multiply only defined between DMSAngle Object '
-                            'and Int or Float')
+            raise TypeError(
+                "Multiply only defined between DMSAngle Object " "and Int or Float"
+            )
 
     def __truediv__(self, other):
         try:
             return dec2ddm(self.dec() / other)
         except TypeError:
-            raise TypeError('Division only defined between DMSAngle Object '
-                            'and Int or Float')
+            raise TypeError(
+                "Division only defined between DMSAngle Object " "and Int or Float"
+            )
 
     def __abs__(self):
         return DDMAngle(self.degree, self.minute)
@@ -852,9 +926,9 @@ def __gt__(self, other):
 
     def __str__(self):
         if self.positive:
-            return str(self.degree) + ' ' + str(self.minute)
+            return str(self.degree) + " " + str(self.minute)
         else:
-            return '-' + str(self.degree) + ' ' + str(self.minute)
+            return "-" + str(self.degree) + " " + str(self.minute)
 
     def __round__(self, n=None):
         if self.positive:
@@ -865,10 +939,10 @@ def __round__(self, n=None):
     def __mod__(self, other):
         return dec2ddm(self.dec() % other)
 
-
     def rad(self):
         """
         Convert to Radians
+
         :return: Radians
         :rtype: float
         """
@@ -877,6 +951,7 @@ def rad(self):
     def dec(self):
         """
         Convert to Decimal Degrees (float)
+
         :return: Decimal Degrees
         :rtype: float
         """
@@ -888,6 +963,7 @@ def dec(self):
     def deca(self):
         """
         Convert to Decimal Degrees (class)
+
         :return: Decimal Degrees
         :rtype: DECAngle
         """
@@ -896,6 +972,7 @@ def deca(self):
     def hp(self):
         """
         Convert to HP Notation (float)
+
         :return: HP Notation (DDD.MMSSSS)
         :rtype: float
         """
@@ -908,6 +985,7 @@ def hp(self):
     def hpa(self):
         """
         Convert to HP Notation (class)
+
         :return: HP Notation (DDD.MMSSSS)
         :rtype: HPAngle
         """
@@ -916,6 +994,7 @@ def hpa(self):
     def gon(self):
         """
         Convert to Gradians (float)
+
         :return: Gradians
         :rtype: float
         """
@@ -924,6 +1003,7 @@ def gon(self):
     def gona(self):
         """
         Convert to Gradians (class)
+
         :return: Gradians
         :rtype: GONAngle
         """
@@ -932,6 +1012,7 @@ def gona(self):
     def dms(self):
         """
         Convert to Degrees, Minutes, Seconds Object
+
         :return: Degrees, Minutes, Seconds Object
         :rtype: DMSAngle
         """
@@ -944,6 +1025,7 @@ def dms(self):
 
 # Functions converting from Decimal Degrees (float) to other formats
 
+
 def dec2hp(dec):
     """
     Converts Decimal Degrees to HP Notation (float)
@@ -951,33 +1033,34 @@ def dec2hp(dec):
     :type dec: float
     :return: HP Notation (DDD.MMSSSS)
     :rtype: float
-    """      
+    """
     minute, second = divmod(abs(dec) * 3600, 60)
     degree, minute = divmod(minute, 60)
 
     # floating point precision is 13 places for the variable 'dec' where values
     # are between 256 and 512 degrees. Precision improves for smaller angles.
-    # In calculating the variable 'second' the precision is degraded by a factor of 3600 
+    # In calculating the variable 'second' the precision is degraded by a factor of 3600
     # Therefore 'second' should be rounded to 9 DP and tested for carry.
     if round(second, 9) == 60:
         second = 0
         minute += 1
-    
+
     # to avoid precision issues with floating point operations
     # a string will be built to represent a sexagesimal number and then converted to float
-    degree = f'{int(degree)}'
-    minute = f'{int(minute):02}'
-    second = f'{second:012.9f}'.rstrip('0').replace('.', '')
-    
-    hp_string = f'{degree}.{minute}{second}'
+    degree = f"{int(degree)}"
+    minute = f"{int(minute):02}"
+    second = f"{second:012.9f}".rstrip("0").replace(".", "")
+
+    hp_string = f"{degree}.{minute}{second}"
     hp = float(hp_string)
-     
+
     return hp if dec >= 0 else -hp
 
 
 def dec2hpa(dec):
     """
     Converts Decimal Degrees to HP Angle Object
+
     :param dec: Decimal Degrees
     :type dec: float
     :return: HP Angle Object (DDD.MMSSSS)
@@ -989,17 +1072,19 @@ def dec2hpa(dec):
 def dec2gon(dec):
     """
     Converts Decimal Degrees to Gradians
+
     :param dec: Decimal Degrees
     :type dec: float
     :return: Gradians
     :rtype: float
     """
-    return 10/9 * dec
+    return 10 / 9 * dec
 
 
 def dec2gona(dec):
     """
     Converts Decimal Degrees to Gradians (class)
+
     :param dec: Decimal Degrees
     :type dec: float
     :return: Gradians
@@ -1011,6 +1096,7 @@ def dec2gona(dec):
 def dec2dms(dec):
     """
     Converts Decimal Degrees to Degrees, Minutes, Seconds Object
+
     :param dec: Decimal Degrees
     :type dec: float
     :return: Degrees, Minutes, Seconds Object
@@ -1018,13 +1104,17 @@ def dec2dms(dec):
     """
     minute, second = divmod(abs(dec) * 3600, 60)
     degree, minute = divmod(minute, 60)
-    return (DMSAngle(degree, minute, second, positive=True) if dec >= 0
-            else DMSAngle(degree, minute, second, positive=False))
+    return (
+        DMSAngle(degree, minute, second, positive=True)
+        if dec >= 0
+        else DMSAngle(degree, minute, second, positive=False)
+    )
 
 
 def dec2ddm(dec):
     """
     Converts Decimal Degrees to Degrees, Decimal Minutes Object
+
     :param dec: Decimal Degrees
     :type dec: float
     :return: Degrees, Decimal Minutes Object
@@ -1033,14 +1123,20 @@ def dec2ddm(dec):
     minute, second = divmod(abs(dec) * 3600, 60)
     degree, minute = divmod(minute, 60)
     minute = minute + (second / 60)
-    return DDMAngle(degree, minute, positive=True) if dec >= 0 else DDMAngle(degree, minute, positive=False)
+    return (
+        DDMAngle(degree, minute, positive=True)
+        if dec >= 0
+        else DDMAngle(degree, minute, positive=False)
+    )
 
 
 # Functions converting from Hewlett-Packard (HP) format to other formats
 
+
 def hp2dec(hp):
     """
     Converts HP Notation to Decimal Degrees
+
     :param hp: HP Notation (DDD.MMSSSS)
     :type hp: float
     :return: Decimal Degrees
@@ -1048,18 +1144,20 @@ def hp2dec(hp):
     """
     # Check if 1st and 3rd decimal place greater than 5 (invalid HP Notation)
     hp = float(hp)
-    hp_deg_str, hp_mmss_str = f'{hp:.13f}'.split('.')
+    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 " f"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}')
+            raise ValueError(
+                f"Invalid HP Notation: 3rd decimal place greater " f"than 5: {hp}"
+            )
     # parse string to avoid precision problems with floating point ops and base 10 numbers
     deg = abs(int(hp_deg_str))
     min = int(hp_mmss_str[:2])
-    sec = float(hp_mmss_str[2:4] + '.' + hp_mmss_str[4:])
+    sec = float(hp_mmss_str[2:4] + "." + hp_mmss_str[4:])
     dec = sec / 3600 + min / 60 + deg
 
     return dec if hp >= 0 else -dec
@@ -1068,6 +1166,7 @@ def hp2dec(hp):
 def hp2deca(hp):
     """
     Converts HP Notation to DECAngle Object
+
     :param hp: HP Notation (DDD.MMSSSS)
     :type hp: float
     :return: Decimal Degrees Object
@@ -1079,6 +1178,7 @@ def hp2deca(hp):
 def hp2rad(hp):
     """
     Converts HP Notation to radians
+
     :param hp: HP Notation (DDD.MMSSSS)
     :type hp: float
     :return: radians
@@ -1090,6 +1190,7 @@ def hp2rad(hp):
 def hp2gon(hp):
     """
     Converts HP Notation to Gradians
+
     :param hp: HP Notation (DDD.MMSSSS)
     :type hp: float
     :return: Gradians
@@ -1101,6 +1202,7 @@ def hp2gon(hp):
 def hp2gona(hp):
     """
     Converts HP Notation to Gradians (class)
+
     :param hp: HP Notation (DDD.MMSSSS)
     :type hp: float
     :return: Gradians
@@ -1112,6 +1214,7 @@ def hp2gona(hp):
 def hp2dms(hp):
     """
     Converts HP Notation to Degrees, Minutes, Seconds Object
+
     :param hp: HP Notation (DDD.MMSSSS)
     :type hp: float
     :return: Degrees, Minutes, Seconds Object
@@ -1119,13 +1222,17 @@ def hp2dms(hp):
     """
     degmin, second = divmod(abs(hp) * 1000, 10)
     degree, minute = divmod(degmin, 100)
-    return (DMSAngle(degree, minute, second * 10, positive=True) if hp >= 0
-            else DMSAngle(degree, minute, second * 10, positive=False))
+    return (
+        DMSAngle(degree, minute, second * 10, positive=True)
+        if hp >= 0
+        else DMSAngle(degree, minute, second * 10, positive=False)
+    )
 
 
 def hp2ddm(hp):
     """
     Converts HP Notation to Degrees, Decimal Minutes Object
+
     :param hp: HP Notation (DDD.MMSSSS)
     :type hp: float
     :return: Degrees, Decimal Minutes Object
@@ -1134,25 +1241,32 @@ def hp2ddm(hp):
     degmin, second = divmod(abs(hp) * 1000, 10)
     degree, minute = divmod(degmin, 100)
     minute = minute + (second / 6)
-    return DDMAngle(degree, minute, positive=True) if hp >= 0 else DDMAngle(degree, minute, positive=False)
+    return (
+        DDMAngle(degree, minute, positive=True)
+        if hp >= 0
+        else DDMAngle(degree, minute, positive=False)
+    )
 
 
 # Functions converting from Gradians format to other formats
 
+
 def gon2dec(gon):
     """
     Converts Gradians to Decimal Degrees
+
     :param gon: Gradians
     :type gon: float
     :return: Decimal Degrees
     :rtype: float
     """
-    return 9/10 * gon
+    return 9 / 10 * gon
 
 
 def gon2deca(gon):
     """
     Converts Gradians to DECAngle Object
+
     :param gon: Gradians
     :type gon: float
     :return: Decimal Degrees Object
@@ -1164,6 +1278,7 @@ def gon2deca(gon):
 def gon2hp(gon):
     """
     Converts Gradians to HP Notation (float)
+
     :param gon: Gradians
     :type gon: float
     :return: HP Notation (DDD.MMSSSS)
@@ -1175,6 +1290,7 @@ def gon2hp(gon):
 def gon2hpa(gon):
     """
     Converts Gradians to HP Angle Object
+
     :param gon: Gradians
     :type gon: float
     :return: HP Angle Object (DDD.MMSSSS)
@@ -1186,6 +1302,7 @@ def gon2hpa(gon):
 def gon2rad(gon):
     """
     Converts Gradians to radians
+
     :param gon: Gradians
     :type gon: float
     :return: Radians
@@ -1197,6 +1314,7 @@ def gon2rad(gon):
 def gon2dms(gon):
     """
     Converts Gradians to Degrees, Minutes, Seconds Object
+
     :param gon: Gradians
     :type gon: float
     :return: Degrees, Minutes, Seconds Object
@@ -1208,6 +1326,7 @@ def gon2dms(gon):
 def gon2ddm(gon):
     """
     Converts Gradians to Degrees, Decimal Minutes Object
+
     :param gon: Gradians
     :type gon: float
     :return: Degrees, Decimal Minutes Object
@@ -1218,9 +1337,11 @@ def gon2ddm(gon):
 
 # Miscellaneous other useful functions
 
+
 def dd2sec(dd):
     """
     Converts angle in decimal degrees to angle in seconds
+
     :param dd: Decimal Degrees
     :return: Seconds
     """
@@ -1247,7 +1368,14 @@ def hp2dec_v(hp):
 
 
 def angular_typecheck(angle):
-    # Converts Angle Objects to Decimal Degrees (float) for computations
+    """
+    Converts Angle Objects to Decimal Degrees (float) for computations or returns
+    float input as-is.
+
+    :param angle: Angle Object or float
+    :return: Decimal Degrees
+    :rtype: float
+    """
     supported_types = [DMSAngle, DDMAngle, DECAngle, HPAngle, GONAngle]
     if type(angle) in supported_types:
         return angle.dec()
diff --git a/geodepy/constants.py b/geodepy/constants.py
index bc6e536..bb9cf34 100644
--- a/geodepy/constants.py
+++ b/geodepy/constants.py
@@ -15,6 +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
@@ -23,8 +30,8 @@ def __init__(self, semimaj, inversef):
         self.ecc2sq = float(self.ecc1sq / (1 - self.ecc1sq))
         self.ecc1 = sqrt(self.ecc1sq)
         self.n = float(self.f / (2 - self.f))
-        self.n2 = self.n ** 2
-        self.meanradius = (2 * self.semimaj + self.semimin)/3
+        self.n2 = self.n**2
+        self.meanradius = (2 * self.semimaj + self.semimin) / 3
 
 
 # Geodetic Reference System 1980
@@ -52,6 +59,7 @@ class Projection(object):
     def __init__(self, falseeast, falsenorth, cmscale, zonewidth, initialcm):
         """
         Transverse Mercator Projection Parameters
+
         :param falseeast: Easting (m) assigned to Central Meridian
         :param falsenorth: Northing (m) assigned to Equator
         :param cmscale: Central Meridian Scale Factor (unitless, 1 is no scale)
@@ -75,48 +83,125 @@ def __init__(self, falseeast, falsenorth, cmscale, zonewidth, initialcm):
 
 # Helmert 14 parameter transformation
 class Transformation(object):
-    def __init__(self, from_datum, to_datum, ref_epoch,
-                 tx, ty, tz, sc, rx, ry, rz,
-                 d_tx=0.0, d_ty=0.0, d_tz=0.0, d_sc=0.0,
-                 d_rx=0.0, d_ry=0.0, d_rz=0.0, tf_sd=None):
-        self.from_datum = from_datum   # Datum transforming from
-        self.to_datum = to_datum       # Datum transforming to
-        self.ref_epoch = ref_epoch     # Ref. epoch (datetime.date object)
-        self.tx = tx                   # Translation in X (m)
-        self.ty = ty                   # Translation in Y (m)
-        self.tz = tz                   # Translation in Z (m)
-        self.sc = sc                   # Scale factor (ppm)
-        self.rx = rx                   # Rotation about X (arcsec)
-        self.ry = ry                   # Rotation about Y (arcsec)
-        self.rz = rz                   # Rotation about Z (arcsec)
-        self.d_tx = d_tx               # Translation rate of change in X (m/yr)
-        self.d_ty = d_ty               # Translation rate of change in Y (m/yr)
-        self.d_tz = d_tz               # Translation rate of change in Z (m/yr)
-        self.d_sc = d_sc               # Scale factor rate of change (ppm/yr)
-        self.d_rx = d_rx               # Rot rate of change about X (arcsec/yr)
-        self.d_ry = d_ry               # Rot rate of change about Y (arcsec/yr)
-        self.d_rz = d_rz               # Rot rate of change about Z (arcsec/yr)
-        self.tf_sd = tf_sd             # TransformationSD object
+    def __init__(
+        
+        self,
+        from_datum,
+        to_datum,
+        ref_epoch,
+        tx,
+        ty,
+        tz,
+        sc,
+        rx,
+        ry,
+        rz,
+        d_tx=0.0,
+        d_ty=0.0,
+        d_tz=0.0,
+        d_sc=0.0,
+        d_rx=0.0,
+        d_ry=0.0,
+        d_rz=0.0,
+        tf_sd=None,
+    ):
+        """
+        Transformation Parameters
+
+        :param from_datum: Datum transforming from
+        :param to_datum: Datum transforming to
+        :param ref_epoch: Ref. epoch
+        :type ref_epoch: datetime.date
+        :param tx: Translation in X (m)
+        :param ty: Translation in Y (m)
+        :param tz: Translation in Z (m)
+        :param sc: Scale factor (ppm)
+        :param rx: Rotation about X (arcsec)
+        :param ry: Rotation about Y (arcsec)
+        :param rz: Rotation about Z (arcsec)
+        :param d_tx: Translation rate of change in X (m/yr)
+        :param d_ty: Translation rate of change in Y (m/yr)
+        :param d_tz: Translation rate of change in Z (m/yr)
+        :param d_sc: Scale factor rate of change (ppm/yr)
+        :param d_rx: Rotate rate of change about X (arcsec/yr)
+        :param d_ry: Rotate rate of change about Y (arcsec/yr)
+        :param d_rz: Rotate rate of change about Z (arcsec/yr)
+        :param tf_sd: TransformationSD object
+        :type tf_sd: TransformationSD
+        """
+        self.from_datum = from_datum  # Datum transforming from
+        self.to_datum = to_datum  # Datum transforming to
+        self.ref_epoch = ref_epoch  # Ref. epoch (datetime.date object)
+        self.tx = tx  # Translation in X (m)
+        self.ty = ty  # Translation in Y (m)
+        self.tz = tz  # Translation in Z (m)
+        self.sc = sc  # Scale factor (ppm)
+        self.rx = rx  # Rotation about X (arcsec)
+        self.ry = ry  # Rotation about Y (arcsec)
+        self.rz = rz  # Rotation about Z (arcsec)
+        self.d_tx = d_tx  # Translation rate of change in X (m/yr)
+        self.d_ty = d_ty  # Translation rate of change in Y (m/yr)
+        self.d_tz = d_tz  # Translation rate of change in Z (m/yr)
+        self.d_sc = d_sc  # Scale factor rate of change (ppm/yr)
+        self.d_rx = d_rx  # Rot rate of change about X (arcsec/yr)
+        self.d_ry = d_ry  # Rot rate of change about Y (arcsec/yr)
+        self.d_rz = d_rz  # Rot rate of change about Z (arcsec/yr)
+        self.tf_sd = tf_sd  # TransformationSD object
 
     def __repr__(self):
-        return ('Transformation: '
-                + 'From ' + repr(self.from_datum) +
-                ' to ' + repr(self.to_datum) + '\n'
-                + 'Reference Epoch: ' + repr(self.ref_epoch) + '\n'
-                + '  tx: ' + repr(self.tx) + 'm + ' + repr(self.d_tx) +
-                'm/yr' + '\n'
-                + '  ty: ' + repr(self.ty) + 'm + ' + repr(self.d_ty) +
-                'm/yr' + '\n'
-                + '  tz: ' + repr(self.tz) + 'm + ' + repr(self.d_tz) +
-                'm/yr' + '\n'
-                + '  sc: ' + repr(self.sc) + 'ppm + ' + repr(self.d_sc) +
-                'ppm/yr' + '\n'
-                + '  rx: ' + repr(self.rx) + '\" + ' + repr(self.d_rx) +
-                '\"/yr' + '\n'
-                + '  ry: ' + repr(self.ry) + '\" + ' + repr(self.d_ry) +
-                '\"/yr' + '\n'
-                + '  rz: ' + repr(self.rz) + '\" + ' + repr(self.d_rz) +
-                '\"/yr' + '\n')
+        return (
+            "Transformation: "
+            + "From "
+            + repr(self.from_datum)
+            + " to "
+            + repr(self.to_datum)
+            + "\n"
+            + "Reference Epoch: "
+            + repr(self.ref_epoch)
+            + "\n"
+            + "  tx: "
+            + repr(self.tx)
+            + "m + "
+            + repr(self.d_tx)
+            + "m/yr"
+            + "\n"
+            + "  ty: "
+            + repr(self.ty)
+            + "m + "
+            + repr(self.d_ty)
+            + "m/yr"
+            + "\n"
+            + "  tz: "
+            + repr(self.tz)
+            + "m + "
+            + repr(self.d_tz)
+            + "m/yr"
+            + "\n"
+            + "  sc: "
+            + repr(self.sc)
+            + "ppm + "
+            + repr(self.d_sc)
+            + "ppm/yr"
+            + "\n"
+            + "  rx: "
+            + repr(self.rx)
+            + '" + '
+            + repr(self.d_rx)
+            + '"/yr'
+            + "\n"
+            + "  ry: "
+            + repr(self.ry)
+            + '" + '
+            + repr(self.d_ry)
+            + '"/yr'
+            + "\n"
+            + "  rz: "
+            + repr(self.rz)
+            + '" + '
+            + repr(self.d_rz)
+            + '"/yr'
+            + "\n"
+        )
 
     def __neg__(self):
         """
@@ -126,17 +211,26 @@ def __neg__(self):
 
         :return: reversed direction transformation object
         """
-        return Transformation(self.to_datum,
-                              self.from_datum,
-                              self.ref_epoch,
-                              -self.tx, -self.ty, -self.tz,
-                              -self.sc,
-                              -self.rx, -self.ry, -self.rz,
-                              -self.d_tx, -self.d_ty, -self.d_tz,
-                              -self.d_sc,
-                              -self.d_rx, -self.d_ry, -self.d_rz,
-                              tf_sd=self.tf_sd
-                              )
+        return Transformation(
+            self.to_datum,
+            self.from_datum,
+            self.ref_epoch,
+            -self.tx,
+            -self.ty,
+            -self.tz,
+            -self.sc,
+            -self.rx,
+            -self.ry,
+            -self.rz,
+            -self.d_tx,
+            -self.d_ty,
+            -self.d_tz,
+            -self.d_sc,
+            -self.d_rx,
+            -self.d_ry,
+            -self.d_rz,
+            tf_sd=self.tf_sd,
+        )
 
     def __add__(self, other):
         """
@@ -145,70 +239,135 @@ def __add__(self, other):
 
         :param other: datetime.date object
         :return: transformation object with parameters and ref epoch moved to
-        the specified date
+                 the specified date
         """
         if type(other) == date:
-            timediff = (other - self.ref_epoch).days/365.25
+            timediff = (other - self.ref_epoch).days / 365.25
 
             if type(self.tf_sd) == TransformationSD:
-                self.tf_sd.sd_tx = (self.tf_sd.sd_tx**2 + (self.tf_sd.sd_d_tx * timediff)**2) ** 0.5
-                self.tf_sd.sd_ty = (self.tf_sd.sd_ty**2 + (self.tf_sd.sd_d_ty * timediff)**2) ** 0.5
-                self.tf_sd.sd_tz = (self.tf_sd.sd_tz**2 + (self.tf_sd.sd_d_tz * timediff)**2) ** 0.5
-                self.tf_sd.sd_sc = (self.tf_sd.sd_sc**2 + (self.tf_sd.sd_d_sc * timediff)**2) ** 0.5
-                self.tf_sd.sd_rx = (self.tf_sd.sd_rx**2 + (self.tf_sd.sd_d_rx * timediff)**2) ** 0.5
-                self.tf_sd.sd_ry = (self.tf_sd.sd_ry**2 + (self.tf_sd.sd_d_ry * timediff)**2) ** 0.5
-                self.tf_sd.sd_rz = (self.tf_sd.sd_rz**2 + (self.tf_sd.sd_d_rz * timediff)**2) ** 0.5
-
-            return Transformation(self.to_datum,
-                                  self.from_datum,
-                                  other,
-                                  round(self.tx + (self.d_tx * timediff), 8),
-                                  round(self.ty + (self.d_ty * timediff), 8),
-                                  round(self.tz + (self.d_tz * timediff), 8),
-                                  round(self.sc + (self.d_sc * timediff), 8),
-                                  round(self.rx + (self.d_rx * timediff), 8),
-                                  round(self.ry + (self.d_ry * timediff), 8),
-                                  round(self.rz + (self.d_rz * timediff), 8),
-                                  self.d_tx,
-                                  self.d_ty,
-                                  self.d_tz,
-                                  self.d_sc,
-                                  self.d_rx,
-                                  self.d_ry,
-                                  self.d_rz,
-                                  self.tf_sd
-                                  )
+                self.tf_sd.sd_tx = (
+                    self.tf_sd.sd_tx**2 + (self.tf_sd.sd_d_tx * timediff) ** 2
+                ) ** 0.5
+                self.tf_sd.sd_ty = (
+                    self.tf_sd.sd_ty**2 + (self.tf_sd.sd_d_ty * timediff) ** 2
+                ) ** 0.5
+                self.tf_sd.sd_tz = (
+                    self.tf_sd.sd_tz**2 + (self.tf_sd.sd_d_tz * timediff) ** 2
+                ) ** 0.5
+                self.tf_sd.sd_sc = (
+                    self.tf_sd.sd_sc**2 + (self.tf_sd.sd_d_sc * timediff) ** 2
+                ) ** 0.5
+                self.tf_sd.sd_rx = (
+                    self.tf_sd.sd_rx**2 + (self.tf_sd.sd_d_rx * timediff) ** 2
+                ) ** 0.5
+                self.tf_sd.sd_ry = (
+                    self.tf_sd.sd_ry**2 + (self.tf_sd.sd_d_ry * timediff) ** 2
+                ) ** 0.5
+                self.tf_sd.sd_rz = (
+                    self.tf_sd.sd_rz**2 + (self.tf_sd.sd_d_rz * timediff) ** 2
+                ) ** 0.5
+
+            return Transformation(
+                self.to_datum,
+                self.from_datum,
+                other,
+                round(self.tx + (self.d_tx * timediff), 8),
+                round(self.ty + (self.d_ty * timediff), 8),
+                round(self.tz + (self.d_tz * timediff), 8),
+                round(self.sc + (self.d_sc * timediff), 8),
+                round(self.rx + (self.d_rx * timediff), 8),
+                round(self.ry + (self.d_ry * timediff), 8),
+                round(self.rz + (self.d_rz * timediff), 8),
+                self.d_tx,
+                self.d_ty,
+                self.d_tz,
+                self.d_sc,
+                self.d_rx,
+                self.d_ry,
+                self.d_rz,
+                self.tf_sd,
+            )
         else:
-            ValueError('supports adding datetime.date objects only')
+            ValueError("supports adding datetime.date objects only")
 
 
 class TransformationSD(object):
-    def __init__(self, sd_tx=None, sd_ty=None, sd_tz=None, sd_sc=None,
-                 sd_rx=None, sd_ry=None, sd_rz=None,
-                 sd_d_tx=None, sd_d_ty=None, sd_d_tz=None, sd_d_sc=None,
-                 sd_d_rx=None, sd_d_ry=None, sd_d_rz=None):
-        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)
-        self.sd_sc = sd_sc         # one-sigma uncertainty of sc (ppm)
-        self.sd_rx = sd_rx         # one-sigma uncertainty of rx (arcsec/yr)
-        self.sd_ry = sd_ry         # one-sigma uncertainty of ry (arcsec/yr)
-        self.sd_rz = sd_rz         # one-sigma uncertainty of rz (arcsec/yr)
-        self.sd_d_tx = sd_d_tx     # one-sigma uncertainty of d_tx (m/yr)
-        self.sd_d_ty = sd_d_ty     # one-sigma uncertainty of d_ty (m/yr)
-        self.sd_d_tz = sd_d_tz     # one-sigma uncertainty of d_tz (m/yr)
-        self.sd_d_sc = sd_d_sc     # one-sigma uncertainty of d_sc (ppm/yr)
-        self.sd_d_rx = sd_d_rx     # one-sigma uncertainty of d_rx (arcsec/yr)
-        self.sd_d_ry = sd_d_ry     # one-sigma uncertainty of d_ry (arcsec/yr)
-        self.sd_d_rz = sd_d_rz     # one-sigma uncertainty of d_rz (arcsec/yr)
-
-
-def iers2trans(itrf_from, itrf_to, ref_epoch, tx, ty, tz, sc, rx, ry, rz,
-               d_tx, d_ty, d_tz, d_sc, d_rx, d_ry, d_rz):
+    def __init__(
+        self,
+        sd_tx=None,
+        sd_ty=None,
+        sd_tz=None,
+        sd_sc=None,
+        sd_rx=None,
+        sd_ry=None,
+        sd_rz=None,
+        sd_d_tx=None,
+        sd_d_ty=None,
+        sd_d_tz=None,
+        sd_d_sc=None,
+        sd_d_rx=None,
+        sd_d_ry=None,
+        sd_d_rz=None,
+    ):
+        '''
+        Transformation Standard Deviation Parameters
+
+        :param sd_tx: one-sigma uncertainty of tx (m)
+        :param sd_ty: one-sigma uncertainty of ty (m)
+        :param sd_tz: one-sigma uncertainty of tz (m)
+        :param sd_sc: one-sigma uncertainty of sc (ppm)
+        :param sd_rx: one-sigma uncertainty of rx (arcsec/yr)
+        :param sd_ry: one-sigma uncertainty of ry (arcsec/yr)
+        :param sd_rz: one-sigma uncertainty of rz (arcsec/yr)
+        :param sd_d_tx: one-sigma uncertainty of d_tx (m/yr)
+        :param sd_d_ty: one-sigma uncertainty of d_ty (m/yr)
+        :param sd_d_tz: one-sigma uncertainty of d_tz (m/yr)
+        :param sd_d_sc: one-sigma uncertainty of d_sc (ppm/yr)
+        :param sd_d_rx: one-sigma uncertainty of d_rx (arcsec/yr)
+        :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)
+        self.sd_sc = sd_sc  # one-sigma uncertainty of sc (ppm)
+        self.sd_rx = sd_rx  # one-sigma uncertainty of rx (arcsec/yr)
+        self.sd_ry = sd_ry  # one-sigma uncertainty of ry (arcsec/yr)
+        self.sd_rz = sd_rz  # one-sigma uncertainty of rz (arcsec/yr)
+        self.sd_d_tx = sd_d_tx  # one-sigma uncertainty of d_tx (m/yr)
+        self.sd_d_ty = sd_d_ty  # one-sigma uncertainty of d_ty (m/yr)
+        self.sd_d_tz = sd_d_tz  # one-sigma uncertainty of d_tz (m/yr)
+        self.sd_d_sc = sd_d_sc  # one-sigma uncertainty of d_sc (ppm/yr)
+        self.sd_d_rx = sd_d_rx  # one-sigma uncertainty of d_rx (arcsec/yr)
+        self.sd_d_ry = sd_d_ry  # one-sigma uncertainty of d_ry (arcsec/yr)
+        self.sd_d_rz = sd_d_rz  # one-sigma uncertainty of d_rz (arcsec/yr)
+
+
+def iers2trans(
+    itrf_from,
+    itrf_to,
+    ref_epoch,
+    tx,
+    ty,
+    tz,
+    sc,
+    rx,
+    ry,
+    rz,
+    d_tx,
+    d_ty,
+    d_tz,
+    d_sc,
+    d_rx,
+    d_ry,
+    d_rz,
+):
     """
     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)
@@ -228,14 +387,25 @@ class parameters.
     :param d_rz: Rate of change in Rotation about X (milliarcsec/yr)
     :return: Transformation object following the Australian convention
     """
-    return Transformation(itrf_from, itrf_to, ref_epoch,
-                          round(tx / 1000, 8), round(ty / 1000, 8),
-                          round(tz / 1000, 8), round(sc / 1000, 8),
-                          round(-rx / 1000, 8), round(-ry / 1000, 8),
-                          round(-rz / 1000, 8), round(d_tx / 1000, 8),
-                          round(d_ty / 1000, 8), round(d_tz / 1000, 8),
-                          round(d_sc / 1000, 8), round(-d_rx / 1000, 8),
-                          round(-d_ry / 1000, 8), round(-d_rz / 1000, 8))
+    return Transformation(
+        itrf_from,
+        itrf_to,
+        ref_epoch,
+        round(tx / 1000, 8),
+        round(ty / 1000, 8),
+        round(tz / 1000, 8),
+        round(sc / 1000, 8),
+        round(-rx / 1000, 8),
+        round(-ry / 1000, 8),
+        round(-rz / 1000, 8),
+        round(d_tx / 1000, 8),
+        round(d_ty / 1000, 8),
+        round(d_tz / 1000, 8),
+        round(d_sc / 1000, 8),
+        round(-d_rx / 1000, 8),
+        round(-d_ry / 1000, 8),
+        round(-d_rz / 1000, 8),
+    )
 
 
 """
@@ -271,16 +441,28 @@ class parameters.
 # Ref: https://www.icsm.gov.au/gda2020-and-gda94-technical-manuals
 
 gda94_to_gda2020_sd = TransformationSD(
-    sd_tx=0.0007, sd_ty=0.0006, sd_tz=0.0007,
+    sd_tx=0.0007,
+    sd_ty=0.0006,
+    sd_tz=0.0007,
     sd_sc=0.00010,
-    sd_rx=0.000011, sd_ry=0.000010, sd_rz=0.000011,)
+    sd_rx=0.000011,
+    sd_ry=0.000010,
+    sd_rz=0.000011,
+)
 
 gda94_to_gda2020 = Transformation(
-    from_datum='GDA94', to_datum='GDA2020', ref_epoch=0,
-    tx=0.06155, ty=-0.01087, tz=-0.04019,
+    from_datum="GDA94",
+    to_datum="GDA2020",
+    ref_epoch=0,
+    tx=0.06155,
+    ty=-0.01087,
+    tz=-0.04019,
     sc=-0.009994,
-    rx=-0.0394924, ry=-0.0327221, rz=-0.0328979,
-    tf_sd=gda94_to_gda2020_sd)
+    rx=-0.0394924,
+    ry=-0.0327221,
+    rz=-0.0328979,
+    tf_sd=gda94_to_gda2020_sd,
+)
 
 gda2020_to_gda94 = -gda94_to_gda2020
 
@@ -293,19 +475,42 @@ class parameters.
 # Ref: https://www.legislation.gov.au/Details/F2017L01352
 
 itrf2014_to_gda2020_sd = TransformationSD(
-    sd_tx=0.00, sd_ty=0.00, sd_tz=0.00,
+    sd_tx=0.00,
+    sd_ty=0.00,
+    sd_tz=0.00,
     sd_sc=0.00,
-    sd_rx=0.00, sd_ry=0.00, sd_rz=0.00,
-    sd_d_tx=0.00, sd_d_ty=0.00, sd_d_tz=0.00,
+    sd_rx=0.00,
+    sd_ry=0.00,
+    sd_rz=0.00,
+    sd_d_tx=0.00,
+    sd_d_ty=0.00,
+    sd_d_tz=0.00,
     sd_d_sc=0.00,
-    sd_d_rx=0.00000417, sd_d_ry=0.00000401, sd_d_rz=0.00000370)
+    sd_d_rx=0.00000417,
+    sd_d_ry=0.00000401,
+    sd_d_rz=0.00000370,
+)
 
 itrf2014_to_gda2020 = Transformation(
-    from_datum='ITRF2014', to_datum='GDA2020', ref_epoch=date(2020, 1, 1),
-    tx=0, ty=0, tz=0, sc=0, rx=0, ry=0, rz=0,
-    d_tx=0, d_ty=0, d_tz=0, d_sc=0,
-    d_rx=0.00150379, d_ry=0.00118346, d_rz=0.00120716,
-    tf_sd=itrf2014_to_gda2020_sd)
+    from_datum="ITRF2014",
+    to_datum="GDA2020",
+    ref_epoch=date(2020, 1, 1),
+    tx=0,
+    ty=0,
+    tz=0,
+    sc=0,
+    rx=0,
+    ry=0,
+    rz=0,
+    d_tx=0,
+    d_ty=0,
+    d_tz=0,
+    d_sc=0,
+    d_rx=0.00150379,
+    d_ry=0.00118346,
+    d_rz=0.00120716,
+    tf_sd=itrf2014_to_gda2020_sd,
+)
 
 gda2020_to_itrf2014 = -itrf2014_to_gda2020
 
@@ -315,19 +520,42 @@ class parameters.
 # Ref: https://www.icsm.gov.au/australian-terrestrial-reference-frame
 
 atrf2014_to_gda2020_sd = TransformationSD(
-    sd_tx=0.00, sd_ty=0.00, sd_tz=0.00,
+    sd_tx=0.00,
+    sd_ty=0.00,
+    sd_tz=0.00,
     sd_sc=0.00,
-    sd_rx=0.00, sd_ry=0.00, sd_rz=0.00,
-    sd_d_tx=0.00, sd_d_ty=0.00, sd_d_tz=0.00,
+    sd_rx=0.00,
+    sd_ry=0.00,
+    sd_rz=0.00,
+    sd_d_tx=0.00,
+    sd_d_ty=0.00,
+    sd_d_tz=0.00,
     sd_d_sc=0.00,
-    sd_d_rx=0.00000417, sd_d_ry=0.00000401, sd_d_rz=0.00000370)
+    sd_d_rx=0.00000417,
+    sd_d_ry=0.00000401,
+    sd_d_rz=0.00000370,
+)
 
 atrf2014_to_gda2020 = Transformation(
-    from_datum='ATRF2014', to_datum='GDA2020', ref_epoch=date(2020, 1, 1),
-    tx=0, ty=0, tz=0, sc=0, rx=0, ry=0, rz=0,
-    d_tx=0, d_ty=0, d_tz=0, d_sc=0,
-    d_rx=0.00150379, d_ry=0.00118346, d_rz=0.00120716,
-    tf_sd=atrf2014_to_gda2020_sd)
+    from_datum="ATRF2014",
+    to_datum="GDA2020",
+    ref_epoch=date(2020, 1, 1),
+    tx=0,
+    ty=0,
+    tz=0,
+    sc=0,
+    rx=0,
+    ry=0,
+    rz=0,
+    d_tx=0,
+    d_ty=0,
+    d_tz=0,
+    d_sc=0,
+    d_rx=0.00150379,
+    d_ry=0.00118346,
+    d_rz=0.00120716,
+    tf_sd=atrf2014_to_gda2020_sd,
+)
 
 
 # GDA94 to ITRF transformation parameters [Dawson and Woods (2010)]
@@ -336,131 +564,273 @@ class parameters.
 
 # Transformation Standard Deviations
 itrf2008_to_gda94_sd = TransformationSD(
-    sd_tx=0.00091, sd_ty=0.00078, sd_tz=0.00106,
+    sd_tx=0.00091,
+    sd_ty=0.00078,
+    sd_tz=0.00106,
     sd_sc=0.000126,
-    sd_rx=0.0000221, sd_ry=0.0000236, sd_rz=0.0000194,
-    sd_d_tx=0.00008, sd_d_ty=0.00007, sd_d_tz=0.00011,
+    sd_rx=0.0000221,
+    sd_ry=0.0000236,
+    sd_rz=0.0000194,
+    sd_d_tx=0.00008,
+    sd_d_ty=0.00007,
+    sd_d_tz=0.00011,
     sd_d_sc=0.000013,
-    sd_d_rx=0.0000028, sd_d_ry=0.0000030, sd_d_rz=0.0000023)
+    sd_d_rx=0.0000028,
+    sd_d_ry=0.0000030,
+    sd_d_rz=0.0000023,
+)
 
 itrf2005_to_gda94_sd = TransformationSD(
-    sd_tx=0.00256, sd_ty=0.00187, sd_tz=0.00337,
+    sd_tx=0.00256,
+    sd_ty=0.00187,
+    sd_tz=0.00337,
     sd_sc=0.000227,
-    sd_rx=0.0000883, sd_ry=0.0000972, sd_rz=0.0000600,
-    sd_d_tx=0.00028, sd_d_ty=0.00020, sd_d_tz=0.00036,
+    sd_rx=0.0000883,
+    sd_ry=0.0000972,
+    sd_rz=0.0000600,
+    sd_d_tx=0.00028,
+    sd_d_ty=0.00020,
+    sd_d_tz=0.00036,
     sd_d_sc=0.000022,
-    sd_d_rx=0.0000096, sd_d_ry=0.0000106, sd_d_rz=0.0000070)
+    sd_d_rx=0.0000096,
+    sd_d_ry=0.0000106,
+    sd_d_rz=0.0000070,
+)
 
 itrf2000_to_gda94_sd = TransformationSD(
-    sd_tx=0.00874, sd_ty=0.00412, sd_tz=0.01105,
+    sd_tx=0.00874,
+    sd_ty=0.00412,
+    sd_tz=0.01105,
     sd_sc=0.000423,
-    sd_rx=0.0002852, sd_ry=0.0003602, sd_rz=0.0001567,
-    sd_d_tx=0.00166, sd_d_ty=0.00083, sd_d_tz=0.00209,
+    sd_rx=0.0002852,
+    sd_ry=0.0003602,
+    sd_rz=0.0001567,
+    sd_d_tx=0.00166,
+    sd_d_ty=0.00083,
+    sd_d_tz=0.00209,
     sd_d_sc=0.000076,
-    sd_d_rx=0.0000537, sd_d_ry=0.0000677, sd_d_rz=0.0000317)
+    sd_d_rx=0.0000537,
+    sd_d_ry=0.0000677,
+    sd_d_rz=0.0000317,
+)
 
 itrf97_to_gda94_sd = TransformationSD(
-    sd_tx=0.01107, sd_ty=0.00574, sd_tz=0.01427,
+    sd_tx=0.01107,
+    sd_ty=0.00574,
+    sd_tz=0.01427,
     sd_sc=0.000425,
-    sd_rx=0.0003757, sd_ry=0.0004642, sd_rz=0.0001955,
-    sd_d_tx=0.00276, sd_d_ty=0.00136, sd_d_tz=0.00371,
+    sd_rx=0.0003757,
+    sd_ry=0.0004642,
+    sd_rz=0.0001955,
+    sd_d_tx=0.00276,
+    sd_d_ty=0.00136,
+    sd_d_tz=0.00371,
     sd_d_sc=0.000101,
-    sd_d_rx=0.0000967, sd_d_ry=0.0001196, sd_d_rz=0.0000453)
+    sd_d_rx=0.0000967,
+    sd_d_ry=0.0001196,
+    sd_d_rz=0.0000453,
+)
 
 itrf96_to_gda94_sd = TransformationSD(
-    sd_tx=0.02033, sd_ty=0.01059, sd_tz=0.02866,
+    sd_tx=0.02033,
+    sd_ty=0.01059,
+    sd_tz=0.02866,
     sd_sc=0.000653,
-    sd_rx=0.0007627, sd_ry=0.0009049, sd_rz=0.0003225,
-    sd_d_tx=0.00753, sd_d_ty=0.00391, sd_d_tz=0.01074,
+    sd_rx=0.0007627,
+    sd_ry=0.0009049,
+    sd_rz=0.0003225,
+    sd_d_tx=0.00753,
+    sd_d_ty=0.00391,
+    sd_d_tz=0.01074,
     sd_d_sc=0.000228,
-    sd_d_rx=0.0002850, sd_d_ry=0.0003382, sd_d_rz=0.0001169)
+    sd_d_rx=0.0002850,
+    sd_d_ry=0.0003382,
+    sd_d_rz=0.0001169,
+)
 
 # Transformations
 itrf2008_to_gda94 = Transformation(
-    from_datum='ITRF2008', to_datum='GDA94', ref_epoch=date(1994, 1, 1),
-    tx=-0.08468, ty=-0.01942, tz=0.03201,
+    from_datum="ITRF2008",
+    to_datum="GDA94",
+    ref_epoch=date(1994, 1, 1),
+    tx=-0.08468,
+    ty=-0.01942,
+    tz=0.03201,
     sc=0.00971,
-    rx=-0.0004254, ry=0.0022578, rz=0.0024015,
-    d_tx=0.00142, d_ty=0.00134, d_tz=0.00090,
+    rx=-0.0004254,
+    ry=0.0022578,
+    rz=0.0024015,
+    d_tx=0.00142,
+    d_ty=0.00134,
+    d_tz=0.00090,
     d_sc=0.000109,
-    d_rx=0.0015461, d_ry=0.0011820, d_rz=0.0011551,
-    tf_sd=itrf2008_to_gda94_sd)
+    d_rx=0.0015461,
+    d_ry=0.0011820,
+    d_rz=0.0011551,
+    tf_sd=itrf2008_to_gda94_sd,
+)
 
 itrf2005_to_gda94 = Transformation(
-    from_datum='ITRF2005', to_datum='GDA94', ref_epoch=date(1994, 1, 1),
-    tx=-0.07973, ty=-0.00686, tz=0.03803,
+    from_datum="ITRF2005",
+    to_datum="GDA94",
+    ref_epoch=date(1994, 1, 1),
+    tx=-0.07973,
+    ty=-0.00686,
+    tz=0.03803,
     sc=0.006636,
-    rx=-0.0000351, ry=0.0021211, rz=0.0021411,
-    d_tx=0.00225, d_ty=-0.00062, d_tz=-0.00056,
+    rx=-0.0000351,
+    ry=0.0021211,
+    rz=0.0021411,
+    d_tx=0.00225,
+    d_ty=-0.00062,
+    d_tz=-0.00056,
     d_sc=0.000294,
-    d_rx=0.0014707, d_ry=0.0011443, d_rz=0.0011701,
-    tf_sd=itrf2005_to_gda94_sd)
+    d_rx=0.0014707,
+    d_ry=0.0011443,
+    d_rz=0.0011701,
+    tf_sd=itrf2005_to_gda94_sd,
+)
 
 itrf2000_to_gda94 = Transformation(
-    from_datum='ITRF2000', to_datum='GDA94', ref_epoch=date(1994, 1, 1),
-    tx=-0.04591, ty=-0.02985, tz=-0.02037,
+    from_datum="ITRF2000",
+    to_datum="GDA94",
+    ref_epoch=date(1994, 1, 1),
+    tx=-0.04591,
+    ty=-0.02985,
+    tz=-0.02037,
     sc=0.00707,
-    rx=-0.0016705, ry=0.0004594, rz=0.0019356,
-    d_tx=-0.00466, d_ty=0.00355, d_tz=0.01124,
+    rx=-0.0016705,
+    ry=0.0004594,
+    rz=0.0019356,
+    d_tx=-0.00466,
+    d_ty=0.00355,
+    d_tz=0.01124,
     d_sc=0.000249,
-    d_rx=0.0017454, d_ry=0.0014868, d_rz=0.001224,
-    tf_sd=itrf2000_to_gda94_sd)
+    d_rx=0.0017454,
+    d_ry=0.0014868,
+    d_rz=0.001224,
+    tf_sd=itrf2000_to_gda94_sd,
+)
 
 itrf97_to_gda94 = Transformation(
-    from_datum='ITRF97', to_datum='GDA94', ref_epoch=date(1994, 1, 1),
-    tx=-0.01463, ty=-0.02762, tz=-0.02532,
+    from_datum="ITRF97",
+    to_datum="GDA94",
+    ref_epoch=date(1994, 1, 1),
+    tx=-0.01463,
+    ty=-0.02762,
+    tz=-0.02532,
     sc=0.006695,
-    rx=-0.0017893, ry=-0.0006047, rz=0.0009962,
-    d_tx=-0.00860, d_ty=0.00036, d_tz=0.01125,
+    rx=-0.0017893,
+    ry=-0.0006047,
+    rz=0.0009962,
+    d_tx=-0.00860,
+    d_ty=0.00036,
+    d_tz=0.01125,
     d_sc=0.000007,
-    d_rx=0.0016394, d_ry=0.0015198, d_rz=0.0013801,
-    tf_sd=itrf97_to_gda94_sd)
+    d_rx=0.0016394,
+    d_ry=0.0015198,
+    d_rz=0.0013801,
+    tf_sd=itrf97_to_gda94_sd,
+)
 
 itrf96_to_gda94 = Transformation(
-    from_datum='ITRF96', to_datum='GDA94', ref_epoch=date(1994, 1, 1),
-    tx=0.02454, ty=-0.03643, tz=-0.06812,
+    from_datum="ITRF96",
+    to_datum="GDA94",
+    ref_epoch=date(1994, 1, 1),
+    tx=0.02454,
+    ty=-0.03643,
+    tz=-0.06812,
     sc=0.006901,
-    rx=-0.0027359, ry=-0.0020431, rz=0.0003731,
-    d_tx=-0.02180, d_ty=0.00471, d_tz=0.02627,
+    rx=-0.0027359,
+    ry=-0.0020431,
+    rz=0.0003731,
+    d_tx=-0.02180,
+    d_ty=0.00471,
+    d_tz=0.02627,
     d_sc=0.000388,
-    d_rx=0.0020203, d_ry=0.0021735, d_rz=0.0016290,
-    tf_sd=itrf96_to_gda94_sd)
+    d_rx=0.0020203,
+    d_ry=0.0021735,
+    d_rz=0.0016290,
+    tf_sd=itrf96_to_gda94_sd,
+)
 
 agd84_to_gda94 = Transformation(
-    from_datum='AGD84', to_datum='GDA94', ref_epoch=0,
-    tx=-117.763, ty=-51.510, tz=139.061,
+    from_datum="AGD84",
+    to_datum="GDA94",
+    ref_epoch=0,
+    tx=-117.763,
+    ty=-51.510,
+    tz=139.061,
     sc=-0.191,
-    rx=-0.292, ry=-0.443, rz=-0.277)
+    rx=-0.292,
+    ry=-0.443,
+    rz=-0.277,
+)
 
 agd66_to_gda94 = Transformation(
-    from_datum='AGD66', to_datum='GDA94', ref_epoch=0,
-    tx=-117.808, ty=-51.536, tz=137.784,
+    from_datum="AGD66",
+    to_datum="GDA94",
+    ref_epoch=0,
+    tx=-117.808,
+    ty=-51.536,
+    tz=137.784,
     sc=-0.290,
-    rx=-0.303, ry=-0.446, rz=-0.234)
+    rx=-0.303,
+    ry=-0.446,
+    rz=-0.234,
+)
 
 agd66_to_gda94_act = Transformation(
-    from_datum='AGD66', to_datum='GDA94', ref_epoch=0,
-    tx=-129.193, ty=-41.212, tz=130.730,
+    from_datum="AGD66",
+    to_datum="GDA94",
+    ref_epoch=0,
+    tx=-129.193,
+    ty=-41.212,
+    tz=130.730,
     sc=-2.955,
-    rx=-0.246, ry=-0.374, rz=-0.329)
+    rx=-0.246,
+    ry=-0.374,
+    rz=-0.329,
+)
 
 agd66_to_gda94_tas = Transformation(
-    from_datum='AGD66', to_datum='GDA94', ref_epoch=0,
-    tx=-120.271, ty=-64.543, tz=161.632,
+    from_datum="AGD66",
+    to_datum="GDA94",
+    ref_epoch=0,
+    tx=-120.271,
+    ty=-64.543,
+    tz=161.632,
     sc=2.499,
-    rx=-0.217, ry=0.067, rz=0.129)
+    rx=-0.217,
+    ry=0.067,
+    rz=0.129,
+)
 
 agd66_to_gda94_vicnsw = Transformation(
-    from_datum='AGD66', to_datum='GDA94', ref_epoch=0,
-    tx=-119.353, ty=-48.301, tz=139.484,
+    from_datum="AGD66",
+    to_datum="GDA94",
+    ref_epoch=0,
+    tx=-119.353,
+    ty=-48.301,
+    tz=139.484,
     sc=-0.613,
-    rx=-0.415, ry=-0.260, rz=-0.437)
+    rx=-0.415,
+    ry=-0.260,
+    rz=-0.437,
+)
 
 agd66_to_gda94_nt = Transformation(
-    from_datum='AGD66', to_datum='GDA94', ref_epoch=0,
-    tx=-124.133, ty=-42.003, tz=137.400,
+    from_datum="AGD66",
+    to_datum="GDA94",
+    ref_epoch=0,
+    tx=-124.133,
+    ty=-42.003,
+    tz=137.400,
     sc=-1.854,
-    rx=0.008, ry=-0.557, rz=-0.178)
+    rx=0.008,
+    ry=-0.557,
+    rz=-0.178,
+)
 
 gda94_to_itrf2008 = -itrf2008_to_gda94
 gda94_to_itrf2005 = -itrf2005_to_gda94
@@ -481,131 +851,285 @@ class parameters.
 # Ref: https://itrf.ign.fr/docs/solutions/itrf2020/Transfo-ITRF2020_TRFs.txt
 
 itrf2020_to_itrf2014_vel = iers2trans(
-    itrf_from='ITRF2020', itrf_to='ITRF2014', ref_epoch=date(2015, 1, 1),
-    tx=0.0, ty=-0.1, tz=0.2,
+    itrf_from="ITRF2020",
+    itrf_to="ITRF2014",
+    ref_epoch=date(2015, 1, 1),
+    tx=0.0,
+    ty=-0.1,
+    tz=0.2,
     sc=-0.42,
-    rx=0.0, ry=0.0, rz=0.0,
-    d_tx=0.0, d_ty=0.0, d_tz=0.0,
+    rx=0.0,
+    ry=0.0,
+    rz=0.0,
+    d_tx=0.0,
+    d_ty=0.0,
+    d_tz=0.0,
     d_sc=0.0,
-    d_rx=0.0, d_ry=0.0, d_rz=0.0)
+    d_rx=0.0,
+    d_ry=0.0,
+    d_rz=0.0,
+)
 
 itrf2020_to_itrf2014 = iers2trans(
-    itrf_from='ITRF2020', itrf_to='ITRF2014', ref_epoch=date(2015, 1, 1),
-    tx=-1.4, ty=-0.9, tz=1.4,
+    itrf_from="ITRF2020",
+    itrf_to="ITRF2014",
+    ref_epoch=date(2015, 1, 1),
+    tx=-1.4,
+    ty=-0.9,
+    tz=1.4,
     sc=-0.42,
-    rx=0.0, ry=0.0, rz=0.0,
-    d_tx=0.0, d_ty=-0.1, d_tz=0.2,
+    rx=0.0,
+    ry=0.0,
+    rz=0.0,
+    d_tx=0.0,
+    d_ty=-0.1,
+    d_tz=0.2,
     d_sc=0.0,
-    d_rx=0.0, d_ry=0.0, d_rz=0.0)
+    d_rx=0.0,
+    d_ry=0.0,
+    d_rz=0.0,
+)
 
 itrf2020_to_itrf2008 = iers2trans(
-    itrf_from='ITRF2020', itrf_to='ITRF2008', ref_epoch=date(2015, 1, 1),
-    tx=0.2, ty=1.0, tz=3.3,
+    itrf_from="ITRF2020",
+    itrf_to="ITRF2008",
+    ref_epoch=date(2015, 1, 1),
+    tx=0.2,
+    ty=1.0,
+    tz=3.3,
     sc=-0.29,
-    rx=0.0, ry=0.0, rz=0.0,
-    d_tx=0.0, d_ty=-0.1, d_tz=0.1,
+    rx=0.0,
+    ry=0.0,
+    rz=0.0,
+    d_tx=0.0,
+    d_ty=-0.1,
+    d_tz=0.1,
     d_sc=0.03,
-    d_rx=0.0, d_ry=0.0, d_rz=0.0)
+    d_rx=0.0,
+    d_ry=0.0,
+    d_rz=0.0,
+)
 
 itrf2020_to_itrf2005 = iers2trans(
-    itrf_from='ITRF2020', itrf_to='ITRF2005', ref_epoch=date(2015, 1, 1),
-    tx=2.7, ty=0.1, tz=-1.4,
+    itrf_from="ITRF2020",
+    itrf_to="ITRF2005",
+    ref_epoch=date(2015, 1, 1),
+    tx=2.7,
+    ty=0.1,
+    tz=-1.4,
     sc=0.65,
-    rx=0.0, ry=0.0, rz=0.0,
-    d_tx=0.3, d_ty=-0.1, d_tz=0.1,
+    rx=0.0,
+    ry=0.0,
+    rz=0.0,
+    d_tx=0.3,
+    d_ty=-0.1,
+    d_tz=0.1,
     d_sc=0.03,
-    d_rx=0.0, d_ry=0.0, d_rz=0.0)
+    d_rx=0.0,
+    d_ry=0.0,
+    d_rz=0.0,
+)
 
 itrf2020_to_itrf2000 = iers2trans(
-    itrf_from='ITRF2020', itrf_to='ITRF2000', ref_epoch=date(2015, 1, 1),
-    tx=-0.2, ty=0.8, tz=-34.2,
+    itrf_from="ITRF2020",
+    itrf_to="ITRF2000",
+    ref_epoch=date(2015, 1, 1),
+    tx=-0.2,
+    ty=0.8,
+    tz=-34.2,
     sc=2.25,
-    rx=0.0, ry=0.0, rz=0.0,
-    d_tx=0.1, d_ty=0.0, d_tz=-1.7,
+    rx=0.0,
+    ry=0.0,
+    rz=0.0,
+    d_tx=0.1,
+    d_ty=0.0,
+    d_tz=-1.7,
     d_sc=0.11,
-    d_rx=0.0, d_ry=0.0, d_rz=0.0)
+    d_rx=0.0,
+    d_ry=0.0,
+    d_rz=0.0,
+)
 
 itrf2020_to_itrf97 = iers2trans(
-    itrf_from='ITRF2020', itrf_to='ITRF97', ref_epoch=date(2015, 1, 1),
-    tx=6.5, ty=-3.9, tz=-77.9,
+    itrf_from="ITRF2020",
+    itrf_to="ITRF97",
+    ref_epoch=date(2015, 1, 1),
+    tx=6.5,
+    ty=-3.9,
+    tz=-77.9,
     sc=3.98,
-    rx=0.0, ry=0.0, rz=0.36,
-    d_tx=0.1, d_ty=-0.6, d_tz=-3.1,
+    rx=0.0,
+    ry=0.0,
+    rz=0.36,
+    d_tx=0.1,
+    d_ty=-0.6,
+    d_tz=-3.1,
     d_sc=0.12,
-    d_rx=0.0, d_ry=0.0, d_rz=0.02)
+    d_rx=0.0,
+    d_ry=0.0,
+    d_rz=0.02,
+)
 
 itrf2020_to_itrf96 = iers2trans(
-    itrf_from='ITRF2020', itrf_to='ITRF96', ref_epoch=date(2015, 1, 1),
-    tx=6.5, ty=-3.9, tz=-77.9,
+    itrf_from="ITRF2020",
+    itrf_to="ITRF96",
+    ref_epoch=date(2015, 1, 1),
+    tx=6.5,
+    ty=-3.9,
+    tz=-77.9,
     sc=3.98,
-    rx=0.0, ry=0.0, rz=0.36,
-    d_tx=0.1, d_ty=-0.6, d_tz=-3.1,
+    rx=0.0,
+    ry=0.0,
+    rz=0.36,
+    d_tx=0.1,
+    d_ty=-0.6,
+    d_tz=-3.1,
     d_sc=0.12,
-    d_rx=0.0, d_ry=0.0, d_rz=0.02)
+    d_rx=0.0,
+    d_ry=0.0,
+    d_rz=0.02,
+)
 
 itrf2020_to_itrf94 = iers2trans(
-    itrf_from='ITRF2020', itrf_to='ITRF94', ref_epoch=date(2015, 1, 1),
-    tx=6.5, ty=-3.9, tz=-77.9,
+    itrf_from="ITRF2020",
+    itrf_to="ITRF94",
+    ref_epoch=date(2015, 1, 1),
+    tx=6.5,
+    ty=-3.9,
+    tz=-77.9,
     sc=3.98,
-    rx=0.0, ry=0.0, rz=0.36,
-    d_tx=0.1, d_ty=-0.6, d_tz=-3.1,
+    rx=0.0,
+    ry=0.0,
+    rz=0.36,
+    d_tx=0.1,
+    d_ty=-0.6,
+    d_tz=-3.1,
     d_sc=0.12,
-    d_rx=0.0, d_ry=0.0, d_rz=0.02)
+    d_rx=0.0,
+    d_ry=0.0,
+    d_rz=0.02,
+)
 
 itrf2020_to_itrf93 = iers2trans(
-    itrf_from='ITRF2020', itrf_to='ITRF93', ref_epoch=date(2015, 1, 1),
-    tx=-65.8, ty=1.9, tz=-71.3,
+    itrf_from="ITRF2020",
+    itrf_to="ITRF93",
+    ref_epoch=date(2015, 1, 1),
+    tx=-65.8,
+    ty=1.9,
+    tz=-71.3,
     sc=4.47,
-    rx=-3.36, ry=-4.33, rz=0.75,
-    d_tx=-2.8, d_ty=-0.2, d_tz=-2.3,
+    rx=-3.36,
+    ry=-4.33,
+    rz=0.75,
+    d_tx=-2.8,
+    d_ty=-0.2,
+    d_tz=-2.3,
     d_sc=0.12,
-    d_rx=-0.11, d_ry=-0.19, d_rz=0.07)
+    d_rx=-0.11,
+    d_ry=-0.19,
+    d_rz=0.07,
+)
 
 itrf2020_to_itrf92 = iers2trans(
-    itrf_from='ITRF2020', itrf_to='ITRF92', ref_epoch=date(2015, 1, 1),
-    tx=14.5, ty=-1.9, tz=-85.9,
+    itrf_from="ITRF2020",
+    itrf_to="ITRF92",
+    ref_epoch=date(2015, 1, 1),
+    tx=14.5,
+    ty=-1.9,
+    tz=-85.9,
     sc=3.27,
-    rx=0.0, ry=0.0, rz=0.36,
-    d_tx=0.1, d_ty=-0.6, d_tz=-3.1,
+    rx=0.0,
+    ry=0.0,
+    rz=0.36,
+    d_tx=0.1,
+    d_ty=-0.6,
+    d_tz=-3.1,
     d_sc=0.12,
-    d_rx=0.0, d_ry=0.0, d_rz=0.02)
+    d_rx=0.0,
+    d_ry=0.0,
+    d_rz=0.02,
+)
 
 itrf2020_to_itrf91 = iers2trans(
-    itrf_from='ITRF2020', itrf_to='ITRF91', ref_epoch=date(2015, 1, 1),
-    tx=26.5, ty=12.1, tz=-91.9,
+    itrf_from="ITRF2020",
+    itrf_to="ITRF91",
+    ref_epoch=date(2015, 1, 1),
+    tx=26.5,
+    ty=12.1,
+    tz=-91.9,
     sc=4.67,
-    rx=0.0, ry=0.0, rz=0.36,
-    d_tx=0.1, d_ty=-0.6, d_tz=-3.1,
+    rx=0.0,
+    ry=0.0,
+    rz=0.36,
+    d_tx=0.1,
+    d_ty=-0.6,
+    d_tz=-3.1,
     d_sc=0.12,
-    d_rx=0.0, d_ry=0.0, d_rz=0.02)
+    d_rx=0.0,
+    d_ry=0.0,
+    d_rz=0.02,
+)
 
 itrf2020_to_itrf90 = iers2trans(
-    itrf_from='ITRF2020', itrf_to='ITRF90', ref_epoch=date(2015, 1, 1),
-    tx=24.5, ty=8.1, tz=-107.9,
+    itrf_from="ITRF2020",
+    itrf_to="ITRF90",
+    ref_epoch=date(2015, 1, 1),
+    tx=24.5,
+    ty=8.1,
+    tz=-107.9,
     sc=4.97,
-    rx=0.0, ry=0.0, rz=0.36,
-    d_tx=0.1, d_ty=-0.6, d_tz=-3.1,
+    rx=0.0,
+    ry=0.0,
+    rz=0.36,
+    d_tx=0.1,
+    d_ty=-0.6,
+    d_tz=-3.1,
     d_sc=0.12,
-    d_rx=0.0, d_ry=0.0, d_rz=0.02)
+    d_rx=0.0,
+    d_ry=0.0,
+    d_rz=0.02,
+)
 
 itrf2020_to_itrf89 = iers2trans(
-    itrf_from='ITRF2020', itrf_to='ITRF89', ref_epoch=date(2015, 1, 1),
-    tx=29.5, ty=32.1, tz=-145.9,
+    itrf_from="ITRF2020",
+    itrf_to="ITRF89",
+    ref_epoch=date(2015, 1, 1),
+    tx=29.5,
+    ty=32.1,
+    tz=-145.9,
     sc=8.37,
-    rx=0.0, ry=0.0, rz=0.36,
-    d_tx=0.1, d_ty=-0.6, d_tz=-3.1,
+    rx=0.0,
+    ry=0.0,
+    rz=0.36,
+    d_tx=0.1,
+    d_ty=-0.6,
+    d_tz=-3.1,
     d_sc=0.12,
-    d_rx=0.0, d_ry=0.0, d_rz=0.02)
+    d_rx=0.0,
+    d_ry=0.0,
+    d_rz=0.02,
+)
 
 itrf2020_to_itrf88 = iers2trans(
-    itrf_from='ITRF2020', itrf_to='ITRF88', ref_epoch=date(2015, 1, 1),
-    tx=24.5, ty=-3.9, tz=-169.9,
+    itrf_from="ITRF2020",
+    itrf_to="ITRF88",
+    ref_epoch=date(2015, 1, 1),
+    tx=24.5,
+    ty=-3.9,
+    tz=-169.9,
     sc=11.47,
-    rx=0.1, ry=0.0, rz=0.36,
-    d_tx=0.1, d_ty=-0.6, d_tz=-3.1,
+    rx=0.1,
+    ry=0.0,
+    rz=0.36,
+    d_tx=0.1,
+    d_ty=-0.6,
+    d_tz=-3.1,
     d_sc=0.12,
-    d_rx=0.0, d_ry=0.0, d_rz=0.02)
-    
+    d_rx=0.0,
+    d_ry=0.0,
+    d_rz=0.02,
+)
+
 itrf2014_to_itrf2020 = -itrf2020_to_itrf2014
 itrf2008_to_itrf2020 = -itrf2020_to_itrf2008
 itrf2005_to_itrf2020 = -itrf2020_to_itrf2005
@@ -619,7 +1143,7 @@ class parameters.
 itrf90_to_itrf2020 = -itrf2020_to_itrf90
 itrf89_to_itrf2020 = -itrf2020_to_itrf89
 itrf88_to_itrf2020 = -itrf2020_to_itrf88
-    
+
 
 # ITRF2014 parameters
 # Note: These parameter definitions use the units, rotation and delta-rotation
@@ -630,112 +1154,244 @@ class parameters.
 # Ref: http://itrf.ign.fr/doc_ITRF/Transfo-ITRF2014_ITRFs.txt
 
 itrf2014_to_itrf2008 = iers2trans(
-    itrf_from='ITRF2014', itrf_to='ITRF2008', ref_epoch=date(2010, 1, 1),
-    tx=1.6, ty=1.9, tz=2.4,
+    itrf_from="ITRF2014",
+    itrf_to="ITRF2008",
+    ref_epoch=date(2010, 1, 1),
+    tx=1.6,
+    ty=1.9,
+    tz=2.4,
     sc=-0.02,
-    rx=0, ry=0, rz=0,
-    d_tx=0.0, d_ty=0.0, d_tz=-0.1,
+    rx=0,
+    ry=0,
+    rz=0,
+    d_tx=0.0,
+    d_ty=0.0,
+    d_tz=-0.1,
     d_sc=0.03,
-    d_rx=0, d_ry=0, d_rz=0)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0,
+)
 
 itrf2014_to_itrf2005 = iers2trans(
-    itrf_from='ITRF2014', itrf_to='ITRF2005', ref_epoch=date(2010, 1, 1),
-    tx=2.6, ty=1.0, tz=-2.3,
+    itrf_from="ITRF2014",
+    itrf_to="ITRF2005",
+    ref_epoch=date(2010, 1, 1),
+    tx=2.6,
+    ty=1.0,
+    tz=-2.3,
     sc=0.92,
-    rx=0, ry=0, rz=0,
-    d_tx=0.3, d_ty=0.0, d_tz=-0.1,
+    rx=0,
+    ry=0,
+    rz=0,
+    d_tx=0.3,
+    d_ty=0.0,
+    d_tz=-0.1,
     d_sc=0.03,
-    d_rx=0, d_ry=0, d_rz=0)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0,
+)
 
 itrf2014_to_itrf2000 = iers2trans(
-    itrf_from='ITRF2014', itrf_to='ITRF2000', ref_epoch=date(2010, 1, 1),
-    tx=0.7, ty=1.2, tz=-26.1,
+    itrf_from="ITRF2014",
+    itrf_to="ITRF2000",
+    ref_epoch=date(2010, 1, 1),
+    tx=0.7,
+    ty=1.2,
+    tz=-26.1,
     sc=2.12,
-    rx=0, ry=0, rz=0,
-    d_tx=0.1, d_ty=0.1, d_tz=-1.9,
+    rx=0,
+    ry=0,
+    rz=0,
+    d_tx=0.1,
+    d_ty=0.1,
+    d_tz=-1.9,
     d_sc=0.11,
-    d_rx=0, d_ry=0, d_rz=0)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0,
+)
 
 itrf2014_to_itrf97 = iers2trans(
-    itrf_from='ITRF2014', itrf_to='ITRF97', ref_epoch=date(2010, 1, 1),
-    tx=7.4, ty=-0.5, tz=-62.8,
+    itrf_from="ITRF2014",
+    itrf_to="ITRF97",
+    ref_epoch=date(2010, 1, 1),
+    tx=7.4,
+    ty=-0.5,
+    tz=-62.8,
     sc=3.80,
-    rx=0, ry=0, rz=0.26,
-    d_tx=0.1, d_ty=-0.5, d_tz=-3.3,
+    rx=0,
+    ry=0,
+    rz=0.26,
+    d_tx=0.1,
+    d_ty=-0.5,
+    d_tz=-3.3,
     d_sc=0.12,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2014_to_itrf96 = iers2trans(
-    itrf_from='ITRF2014', itrf_to='ITRF96', ref_epoch=date(2010, 1, 1),
-    tx=7.4, ty=-0.5, tz=-62.8,
+    itrf_from="ITRF2014",
+    itrf_to="ITRF96",
+    ref_epoch=date(2010, 1, 1),
+    tx=7.4,
+    ty=-0.5,
+    tz=-62.8,
     sc=3.80,
-    rx=0, ry=0, rz=0.26,
-    d_tx=0.1, d_ty=-0.5, d_tz=-3.3,
+    rx=0,
+    ry=0,
+    rz=0.26,
+    d_tx=0.1,
+    d_ty=-0.5,
+    d_tz=-3.3,
     d_sc=0.12,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2014_to_itrf94 = iers2trans(
-    itrf_from='ITRF2014', itrf_to='ITRF94', ref_epoch=date(2010, 1, 1),
-    tx=7.4, ty=-0.5, tz=-62.8,
+    itrf_from="ITRF2014",
+    itrf_to="ITRF94",
+    ref_epoch=date(2010, 1, 1),
+    tx=7.4,
+    ty=-0.5,
+    tz=-62.8,
     sc=3.80,
-    rx=0, ry=0, rz=0.26,
-    d_tx=0.1, d_ty=-0.5, d_tz=-3.3,
+    rx=0,
+    ry=0,
+    rz=0.26,
+    d_tx=0.1,
+    d_ty=-0.5,
+    d_tz=-3.3,
     d_sc=0.12,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2014_to_itrf93 = iers2trans(
-    itrf_from='ITRF2014', itrf_to='ITRF93', ref_epoch=date(2010, 1, 1),
-    tx=-50.4, ty=3.3, tz=-60.2,
+    itrf_from="ITRF2014",
+    itrf_to="ITRF93",
+    ref_epoch=date(2010, 1, 1),
+    tx=-50.4,
+    ty=3.3,
+    tz=-60.2,
     sc=4.29,
-    rx=-2.81, ry=-3.38, rz=0.40,
-    d_tx=-2.8, d_ty=-0.1, d_tz=-2.5,
+    rx=-2.81,
+    ry=-3.38,
+    rz=0.40,
+    d_tx=-2.8,
+    d_ty=-0.1,
+    d_tz=-2.5,
     d_sc=0.12,
-    d_rx=-0.11, d_ry=-0.19, d_rz=0.07)
+    d_rx=-0.11,
+    d_ry=-0.19,
+    d_rz=0.07,
+)
 
 itrf2014_to_itrf92 = iers2trans(
-    itrf_from='ITRF2014', itrf_to='ITRF92', ref_epoch=date(2010, 1, 1),
-    tx=15.4, ty=1.5, tz=-70.8,
+    itrf_from="ITRF2014",
+    itrf_to="ITRF92",
+    ref_epoch=date(2010, 1, 1),
+    tx=15.4,
+    ty=1.5,
+    tz=-70.8,
     sc=3.09,
-    rx=0, ry=0, rz=0.26,
-    d_tx=0.1, d_ty=-0.5, d_tz=-3.3,
+    rx=0,
+    ry=0,
+    rz=0.26,
+    d_tx=0.1,
+    d_ty=-0.5,
+    d_tz=-3.3,
     d_sc=0.12,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2014_to_itrf91 = iers2trans(
-    itrf_from='ITRF2014', itrf_to='ITRF91', ref_epoch=date(2010, 1, 1),
-    tx=27.4, ty=15.5, tz=-76.8,
+    itrf_from="ITRF2014",
+    itrf_to="ITRF91",
+    ref_epoch=date(2010, 1, 1),
+    tx=27.4,
+    ty=15.5,
+    tz=-76.8,
     sc=4.49,
-    rx=0, ry=0, rz=0.26,
-    d_tx=0.1, d_ty=-0.5, d_tz=-3.3,
+    rx=0,
+    ry=0,
+    rz=0.26,
+    d_tx=0.1,
+    d_ty=-0.5,
+    d_tz=-3.3,
     d_sc=0.12,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2014_to_itrf90 = iers2trans(
-    itrf_from='ITRF2014', itrf_to='ITRF90', ref_epoch=date(2010, 1, 1),
-    tx=25.4, ty=11.5, tz=-92.8,
+    itrf_from="ITRF2014",
+    itrf_to="ITRF90",
+    ref_epoch=date(2010, 1, 1),
+    tx=25.4,
+    ty=11.5,
+    tz=-92.8,
     sc=4.79,
-    rx=0, ry=0, rz=0.26,
-    d_tx=0.1, d_ty=-0.5, d_tz=-3.3,
+    rx=0,
+    ry=0,
+    rz=0.26,
+    d_tx=0.1,
+    d_ty=-0.5,
+    d_tz=-3.3,
     d_sc=0.12,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2014_to_itrf89 = iers2trans(
-    itrf_from='ITRF2014', itrf_to='ITRF89', ref_epoch=date(2010, 1, 1),
-    tx=30.4, ty=35.5, tz=-130.8,
+    itrf_from="ITRF2014",
+    itrf_to="ITRF89",
+    ref_epoch=date(2010, 1, 1),
+    tx=30.4,
+    ty=35.5,
+    tz=-130.8,
     sc=8.19,
-    rx=0, ry=0, rz=0.26,
-    d_tx=0.1, d_ty=-0.5, d_tz=-3.3,
+    rx=0,
+    ry=0,
+    rz=0.26,
+    d_tx=0.1,
+    d_ty=-0.5,
+    d_tz=-3.3,
     d_sc=0.12,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2014_to_itrf88 = iers2trans(
-    itrf_from='ITRF2014', itrf_to='ITRF88', ref_epoch=date(2010, 1, 1),
-    tx=25.4, ty=-0.5, tz=-154.8,
+    itrf_from="ITRF2014",
+    itrf_to="ITRF88",
+    ref_epoch=date(2010, 1, 1),
+    tx=25.4,
+    ty=-0.5,
+    tz=-154.8,
     sc=11.29,
-    rx=0.1, ry=0, rz=0.26,
-    d_tx=0.1, d_ty=-0.5, d_tz=-3.3,
+    rx=0.1,
+    ry=0,
+    rz=0.26,
+    d_tx=0.1,
+    d_ty=-0.5,
+    d_tz=-3.3,
     d_sc=0.12,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2008_to_itrf2014 = -itrf2014_to_itrf2008
 itrf2005_to_itrf2014 = -itrf2014_to_itrf2005
@@ -760,103 +1416,224 @@ class parameters.
 # Ref: http://itrf.ign.fr/doc_ITRF/Transfo-ITRF2008_ITRFs.txt
 
 itrf2008_to_itrf2005 = iers2trans(
-    itrf_from='ITRF2008', itrf_to='ITRF2005', ref_epoch=date(2000, 1, 1),
-    tx=-2.0, ty=-0.9, tz=-4.7,
+    itrf_from="ITRF2008",
+    itrf_to="ITRF2005",
+    ref_epoch=date(2000, 1, 1),
+    tx=-2.0,
+    ty=-0.9,
+    tz=-4.7,
     sc=0.94,
-    rx=0, ry=0, rz=0,
-    d_tx=0.3, d_ty=0.0, d_tz=0.0,
+    rx=0,
+    ry=0,
+    rz=0,
+    d_tx=0.3,
+    d_ty=0.0,
+    d_tz=0.0,
     d_sc=0.0,
-    d_rx=0, d_ry=0, d_rz=0)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0,
+)
 
 itrf2008_to_itrf2000 = iers2trans(
-    itrf_from='ITRF2008', itrf_to='ITRF2000', ref_epoch=date(2000, 1, 1),
-    tx=-1.9, ty=-1.7, tz=-10.5,
+    itrf_from="ITRF2008",
+    itrf_to="ITRF2000",
+    ref_epoch=date(2000, 1, 1),
+    tx=-1.9,
+    ty=-1.7,
+    tz=-10.5,
     sc=1.34,
-    rx=0, ry=0, rz=0,
-    d_tx=0.1, d_ty=0.1, d_tz=-1.8,
+    rx=0,
+    ry=0,
+    rz=0,
+    d_tx=0.1,
+    d_ty=0.1,
+    d_tz=-1.8,
     d_sc=0.08,
-    d_rx=0, d_ry=0, d_rz=0)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0,
+)
 
 itrf2008_to_itrf97 = iers2trans(
-    itrf_from='ITRF2008', itrf_to='ITRF97', ref_epoch=date(2000, 1, 1),
-    tx=4.8, ty=2.6, tz=-33.2,
+    itrf_from="ITRF2008",
+    itrf_to="ITRF97",
+    ref_epoch=date(2000, 1, 1),
+    tx=4.8,
+    ty=2.6,
+    tz=-33.2,
     sc=2.92,
-    rx=0, ry=0, rz=0.06,
-    d_tx=0.1, d_ty=-0.5, d_tz=-3.2,
+    rx=0,
+    ry=0,
+    rz=0.06,
+    d_tx=0.1,
+    d_ty=-0.5,
+    d_tz=-3.2,
     d_sc=0.09,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2008_to_itrf96 = iers2trans(
-    itrf_from='ITRF2008', itrf_to='ITRF96', ref_epoch=date(2000, 1, 1),
-    tx=4.8, ty=2.6, tz=-33.2,
+    itrf_from="ITRF2008",
+    itrf_to="ITRF96",
+    ref_epoch=date(2000, 1, 1),
+    tx=4.8,
+    ty=2.6,
+    tz=-33.2,
     sc=2.92,
-    rx=0, ry=0, rz=0.06,
-    d_tx=0.1, d_ty=-0.5, d_tz=-3.2,
+    rx=0,
+    ry=0,
+    rz=0.06,
+    d_tx=0.1,
+    d_ty=-0.5,
+    d_tz=-3.2,
     d_sc=0.09,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2008_to_itrf94 = iers2trans(
-    itrf_from='ITRF2008', itrf_to='ITRF94', ref_epoch=date(2000, 1, 1),
-    tx=4.8, ty=2.6, tz=-33.2,
+    itrf_from="ITRF2008",
+    itrf_to="ITRF94",
+    ref_epoch=date(2000, 1, 1),
+    tx=4.8,
+    ty=2.6,
+    tz=-33.2,
     sc=2.92,
-    rx=0, ry=0, rz=0.06,
-    d_tx=0.1, d_ty=-0.5, d_tz=-3.2,
+    rx=0,
+    ry=0,
+    rz=0.06,
+    d_tx=0.1,
+    d_ty=-0.5,
+    d_tz=-3.2,
     d_sc=0.09,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2008_to_itrf93 = iers2trans(
-    itrf_from='ITRF2008', itrf_to='ITRF93', ref_epoch=date(2000, 1, 1),
-    tx=4-24.0, ty=2.4, tz=-38.6,
+    itrf_from="ITRF2008",
+    itrf_to="ITRF93",
+    ref_epoch=date(2000, 1, 1),
+    tx=4 - 24.0,
+    ty=2.4,
+    tz=-38.6,
     sc=3.41,
-    rx=-1.71, ry=-1.48, rz=-0.30,
-    d_tx=-2.8, d_ty=-0.1, d_tz=-2.4,
+    rx=-1.71,
+    ry=-1.48,
+    rz=-0.30,
+    d_tx=-2.8,
+    d_ty=-0.1,
+    d_tz=-2.4,
     d_sc=0.09,
-    d_rx=-0.11, d_ry=-0.19, d_rz=0.07)
+    d_rx=-0.11,
+    d_ry=-0.19,
+    d_rz=0.07,
+)
 
 itrf2008_to_itrf92 = iers2trans(
-    itrf_from='ITRF2008', itrf_to='ITRF92', ref_epoch=date(2000, 1, 1),
-    tx=12.8, ty=4.6, tz=-41.2,
+    itrf_from="ITRF2008",
+    itrf_to="ITRF92",
+    ref_epoch=date(2000, 1, 1),
+    tx=12.8,
+    ty=4.6,
+    tz=-41.2,
     sc=2.21,
-    rx=0, ry=0, rz=0.06,
-    d_tx=0.1, d_ty=-0.5, d_tz=-3.2,
+    rx=0,
+    ry=0,
+    rz=0.06,
+    d_tx=0.1,
+    d_ty=-0.5,
+    d_tz=-3.2,
     d_sc=0.09,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2008_to_itrf91 = iers2trans(
-    itrf_from='ITRF2008', itrf_to='ITRF91', ref_epoch=date(2000, 1, 1),
-    tx=24.8, ty=18.6, tz=-47.2,
+    itrf_from="ITRF2008",
+    itrf_to="ITRF91",
+    ref_epoch=date(2000, 1, 1),
+    tx=24.8,
+    ty=18.6,
+    tz=-47.2,
     sc=3.61,
-    rx=0, ry=0, rz=0.06,
-    d_tx=0.1, d_ty=-0.5, d_tz=-3.2,
+    rx=0,
+    ry=0,
+    rz=0.06,
+    d_tx=0.1,
+    d_ty=-0.5,
+    d_tz=-3.2,
     d_sc=0.09,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2008_to_itrf90 = iers2trans(
-    itrf_from='ITRF2008', itrf_to='ITRF90', ref_epoch=date(2000, 1, 1),
-    tx=22.8, ty=14.6, tz=-63.2,
+    itrf_from="ITRF2008",
+    itrf_to="ITRF90",
+    ref_epoch=date(2000, 1, 1),
+    tx=22.8,
+    ty=14.6,
+    tz=-63.2,
     sc=3.91,
-    rx=0, ry=0, rz=0.06,
-    d_tx=0.1, d_ty=-0.5, d_tz=-3.2,
+    rx=0,
+    ry=0,
+    rz=0.06,
+    d_tx=0.1,
+    d_ty=-0.5,
+    d_tz=-3.2,
     d_sc=0.09,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2008_to_itrf89 = iers2trans(
-    itrf_from='ITRF2008', itrf_to='ITRF89', ref_epoch=date(2000, 1, 1),
-    tx=27.8, ty=38.6, tz=-101.2,
+    itrf_from="ITRF2008",
+    itrf_to="ITRF89",
+    ref_epoch=date(2000, 1, 1),
+    tx=27.8,
+    ty=38.6,
+    tz=-101.2,
     sc=7.31,
-    rx=0, ry=0, rz=0.06,
-    d_tx=0.1, d_ty=-0.5, d_tz=-3.2,
+    rx=0,
+    ry=0,
+    rz=0.06,
+    d_tx=0.1,
+    d_ty=-0.5,
+    d_tz=-3.2,
     d_sc=0.09,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2008_to_itrf88 = iers2trans(
-    itrf_from='ITRF2008', itrf_to='ITRF88', ref_epoch=date(2000, 1, 1),
-    tx=22.8, ty=2.6, tz=-125.2,
+    itrf_from="ITRF2008",
+    itrf_to="ITRF88",
+    ref_epoch=date(2000, 1, 1),
+    tx=22.8,
+    ty=2.6,
+    tz=-125.2,
     sc=10.41,
-    rx=0.10, ry=0, rz=0.06,
-    d_tx=0.1, d_ty=-0.5, d_tz=-3.2,
+    rx=0.10,
+    ry=0,
+    rz=0.06,
+    d_tx=0.1,
+    d_ty=-0.5,
+    d_tz=-3.2,
     d_sc=0.09,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2005_to_itrf2008 = -itrf2008_to_itrf2005
 itrf2000_to_itrf2008 = -itrf2008_to_itrf2000
@@ -880,13 +1657,24 @@ class parameters.
 # Ref: http://itrf.ensg.ign.fr/ITRF_solutions/2005/tp_05-00.php
 
 itrf2005_to_itrf2000 = iers2trans(
-    itrf_from='ITRF2005', itrf_to='ITRF2000', ref_epoch=date(2000, 1, 1),
-    tx=0.1, ty=-0.8, tz=-5.8,
+    itrf_from="ITRF2005",
+    itrf_to="ITRF2000",
+    ref_epoch=date(2000, 1, 1),
+    tx=0.1,
+    ty=-0.8,
+    tz=-5.8,
     sc=0.40,
-    rx=0, ry=0, rz=0,
-    d_tx=-0.2, d_ty=0.1, d_tz=-1.8,
+    rx=0,
+    ry=0,
+    rz=0,
+    d_tx=-0.2,
+    d_ty=0.1,
+    d_tz=-1.8,
     d_sc=0.08,
-    d_rx=0, d_ry=0, d_rz=0)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0,
+)
 
 itrf2000_to_itrf2005 = -itrf2005_to_itrf2000
 
@@ -897,85 +1685,184 @@ class parameters.
 # NOTE: All translations and rates of translation shown below have been
 # converted to millimetres.
 itrf2000_to_itrf97 = iers2trans(
-    itrf_from='ITRF2000', itrf_to='ITRF97', ref_epoch=date(1997, 1, 1),
-    tx=6.7, ty=6.1, tz=-18.5,
+    itrf_from="ITRF2000",
+    itrf_to="ITRF97",
+    ref_epoch=date(1997, 1, 1),
+    tx=6.7,
+    ty=6.1,
+    tz=-18.5,
     sc=1.55,
-    rx=0, ry=0, rz=0,
-    d_tx=0.0, d_ty=-0.6, d_tz=-1.4,
+    rx=0,
+    ry=0,
+    rz=0,
+    d_tx=0.0,
+    d_ty=-0.6,
+    d_tz=-1.4,
     d_sc=0.01,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2000_to_itrf96 = iers2trans(
-    itrf_from='ITRF2000', itrf_to='ITRF96', ref_epoch=date(1997, 1, 1),
-    tx=6.7, ty=6.1, tz=-18.5,
+    itrf_from="ITRF2000",
+    itrf_to="ITRF96",
+    ref_epoch=date(1997, 1, 1),
+    tx=6.7,
+    ty=6.1,
+    tz=-18.5,
     sc=1.55,
-    rx=0, ry=0, rz=0,
-    d_tx=0.0, d_ty=-0.6, d_tz=-1.4,
+    rx=0,
+    ry=0,
+    rz=0,
+    d_tx=0.0,
+    d_ty=-0.6,
+    d_tz=-1.4,
     d_sc=0.01,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2000_to_itrf94 = iers2trans(
-    itrf_from='ITRF2000', itrf_to='ITRF94', ref_epoch=date(1997, 1, 1),
-    tx=6.7, ty=6.1, tz=-18.5,
+    itrf_from="ITRF2000",
+    itrf_to="ITRF94",
+    ref_epoch=date(1997, 1, 1),
+    tx=6.7,
+    ty=6.1,
+    tz=-18.5,
     sc=1.55,
-    rx=0, ry=0, rz=0,
-    d_tx=0.0, d_ty=-0.6, d_tz=-1.4,
+    rx=0,
+    ry=0,
+    rz=0,
+    d_tx=0.0,
+    d_ty=-0.6,
+    d_tz=-1.4,
     d_sc=0.01,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2000_to_itrf93 = iers2trans(
-    itrf_from='ITRF2000', itrf_to='ITRF93', ref_epoch=date(1988, 1, 1),
-    tx=12.7, ty=6.5, tz=-20.9,
+    itrf_from="ITRF2000",
+    itrf_to="ITRF93",
+    ref_epoch=date(1988, 1, 1),
+    tx=12.7,
+    ty=6.5,
+    tz=-20.9,
     sc=1.95,
-    rx=-0.39, ry=0.80, rz=-1.14,
-    d_tx=-2.9, d_ty=-0.2, d_tz=-0.6,
+    rx=-0.39,
+    ry=0.80,
+    rz=-1.14,
+    d_tx=-2.9,
+    d_ty=-0.2,
+    d_tz=-0.6,
     d_sc=0.01,
-    d_rx=-0.11, d_ry=-0.19, d_rz=0.07)
+    d_rx=-0.11,
+    d_ry=-0.19,
+    d_rz=0.07,
+)
 
 itrf2000_to_itrf92 = iers2trans(
-    itrf_from='ITRF2000', itrf_to='ITRF92', ref_epoch=date(1988, 1, 1),
-    tx=14.7, ty=13.5, tz=-13.9,
+    itrf_from="ITRF2000",
+    itrf_to="ITRF92",
+    ref_epoch=date(1988, 1, 1),
+    tx=14.7,
+    ty=13.5,
+    tz=-13.9,
     sc=0.75,
-    rx=0, ry=0, rz=-0.18,
-    d_tx=0.0, d_ty=-0.6, d_tz=-1.4,
+    rx=0,
+    ry=0,
+    rz=-0.18,
+    d_tx=0.0,
+    d_ty=-0.6,
+    d_tz=-1.4,
     d_sc=0.01,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2000_to_itrf91 = iers2trans(
-    itrf_from='ITRF2000', itrf_to='ITRF91', ref_epoch=date(1988, 1, 1),
-    tx=26.7, ty=27.5, tz=-19.9,
+    itrf_from="ITRF2000",
+    itrf_to="ITRF91",
+    ref_epoch=date(1988, 1, 1),
+    tx=26.7,
+    ty=27.5,
+    tz=-19.9,
     sc=2.15,
-    rx=0, ry=0, rz=-0.18,
-    d_tx=0.0, d_ty=-0.6, d_tz=-1.4,
+    rx=0,
+    ry=0,
+    rz=-0.18,
+    d_tx=0.0,
+    d_ty=-0.6,
+    d_tz=-1.4,
     d_sc=0.01,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2000_to_itrf90 = iers2trans(
-    itrf_from='ITRF2000', itrf_to='ITRF90', ref_epoch=date(1988, 1, 1),
-    tx=24.7, ty=23.5, tz=-35.9,
+    itrf_from="ITRF2000",
+    itrf_to="ITRF90",
+    ref_epoch=date(1988, 1, 1),
+    tx=24.7,
+    ty=23.5,
+    tz=-35.9,
     sc=2.45,
-    rx=0, ry=0, rz=-0.18,
-    d_tx=0.0, d_ty=-0.6, d_tz=-1.4,
+    rx=0,
+    ry=0,
+    rz=-0.18,
+    d_tx=0.0,
+    d_ty=-0.6,
+    d_tz=-1.4,
     d_sc=0.01,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2000_to_itrf89 = iers2trans(
-    itrf_from='ITRF2000', itrf_to='ITRF89', ref_epoch=date(1988, 1, 1),
-    tx=29.7, ty=47.5, tz=-73.9,
+    itrf_from="ITRF2000",
+    itrf_to="ITRF89",
+    ref_epoch=date(1988, 1, 1),
+    tx=29.7,
+    ty=47.5,
+    tz=-73.9,
     sc=5.85,
-    rx=0, ry=0, rz=-0.18,
-    d_tx=0.0, d_ty=-0.6, d_tz=-1.4,
+    rx=0,
+    ry=0,
+    rz=-0.18,
+    d_tx=0.0,
+    d_ty=-0.6,
+    d_tz=-1.4,
     d_sc=0.01,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf2000_to_itrf88 = iers2trans(
-    itrf_from='ITRF2000', itrf_to='ITRF88', ref_epoch=date(1988, 1, 1),
-    tx=24.7, ty=11.5, tz=-97.9,
+    itrf_from="ITRF2000",
+    itrf_to="ITRF88",
+    ref_epoch=date(1988, 1, 1),
+    tx=24.7,
+    ty=11.5,
+    tz=-97.9,
     sc=8.95,
-    rx=0.10, ry=0, rz=-0.18,
-    d_tx=0.0, d_ty=-0.6, d_tz=-1.4,
+    rx=0.10,
+    ry=0,
+    rz=-0.18,
+    d_tx=0.0,
+    d_ty=-0.6,
+    d_tz=-1.4,
     d_sc=0.01,
-    d_rx=0, d_ry=0, d_rz=0.02)
+    d_rx=0,
+    d_ry=0,
+    d_rz=0.02,
+)
 
 itrf97_to_itrf2000 = -itrf2000_to_itrf97
 itrf96_to_itrf2000 = -itrf2000_to_itrf96
@@ -989,20 +1876,20 @@ class parameters.
 
 
 # The locations of files used in the height module
-aws_server = '/vsicurl/https://geoid.s3-ap-southeast-2.amazonaws.com/'
-file_DOV_PV = aws_server + 'AGQG/DOV_PV.tif'
-file_DOV_PM = aws_server + 'AGQG/DOV_PM.tif'
-file_AG2020 = aws_server + 'AUSGeoid/AUSGeoid2020_RELEASEV20170908.tif'
-file_AG2020_STD = aws_server + 'AUSGeoid/AUSGeoid2020_RELEASEV20170908_err.tif'
-file_AVWS = aws_server + 'AGQG/AGQG_20201120.tif'
-file_AVWS_STD = aws_server + 'AGQG/AGQG_uncertainty_20201120.tif'
-file_GRAV_BA = aws_server + 'AGQG/Bouguer_Grav_RELEASE20191107.tif'
-file_AG98=aws_server+'AUSGeoid/AUSGeoid98.tif'
-file_AG09=aws_server+'AUSGeoid/AUSGeoid09_V1.01.tif'
-file_AG98_DOV_PV=aws_server+'AUSGeoid/AUSGeoid98_DOV_PV.tif'
-file_AG98_DOV_PM=aws_server+'AUSGeoid/AUSGeoid98_DOV_PM.tif'
-file_AG09_DOV_PV=aws_server+'AUSGeoid/AUSGeoid09_DOV_PV_V1.01.tif'
-file_AG09_DOV_PM=aws_server+'AUSGeoid/AUSGeoid09_DOV_PM_V1.01.tif'
+aws_server = "/vsicurl/https://geoid.s3-ap-southeast-2.amazonaws.com/"
+file_DOV_PV = aws_server + "AGQG/DOV_PV.tif"
+file_DOV_PM = aws_server + "AGQG/DOV_PM.tif"
+file_AG2020 = aws_server + "AUSGeoid/AUSGeoid2020_RELEASEV20170908.tif"
+file_AG2020_STD = aws_server + "AUSGeoid/AUSGeoid2020_RELEASEV20170908_err.tif"
+file_AVWS = aws_server + "AGQG/AGQG_20201120.tif"
+file_AVWS_STD = aws_server + "AGQG/AGQG_uncertainty_20201120.tif"
+file_GRAV_BA = aws_server + "AGQG/Bouguer_Grav_RELEASE20191107.tif"
+file_AG98 = aws_server + "AUSGeoid/AUSGeoid98.tif"
+file_AG09 = aws_server + "AUSGeoid/AUSGeoid09_V1.01.tif"
+file_AG98_DOV_PV = aws_server + "AUSGeoid/AUSGeoid98_DOV_PV.tif"
+file_AG98_DOV_PM = aws_server + "AUSGeoid/AUSGeoid98_DOV_PM.tif"
+file_AG09_DOV_PV = aws_server + "AUSGeoid/AUSGeoid09_DOV_PV_V1.01.tif"
+file_AG09_DOV_PM = aws_server + "AUSGeoid/AUSGeoid09_DOV_PM_V1.01.tif"
 
 
 # GRS80 normal gravity flattening [Moritz, 2000 Section 4]
diff --git a/geodepy/convert.py b/geodepy/convert.py
index 040e12f..30ffd63 100644
--- a/geodepy/convert.py
+++ b/geodepy/convert.py
@@ -5,30 +5,51 @@
 Convert Module
 """
 
-from math import (sin, cos, atan2, radians, degrees,
-                  sqrt, cosh, sinh, tan, atan, log)
+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 geodepy.angles import (DECAngle, HPAngle, GONAngle, DMSAngle, DDMAngle,
-                            dec2hp, dec2hpa, dec2gon, dec2gona,
-                            dec2dms, dec2ddm,
-                            hp2dec, hp2deca, hp2gon, hp2gona,
-                            hp2dms, hp2ddm, hp2rad, hp2dec_v,
-                            gon2dec, gon2deca, gon2hp, gon2hpa,
-                            gon2dms, gon2ddm, gon2rad,
-                            dd2sec, angular_typecheck)
+from geodepy.angles import (
+    DECAngle,
+    HPAngle,
+    GONAngle,
+    DMSAngle,
+    DDMAngle,
+    dec2hp,
+    dec2hpa,
+    dec2gon,
+    dec2gona,
+    dec2dms,
+    dec2ddm,
+    hp2dec,
+    hp2deca,
+    hp2gon,
+    hp2gona,
+    hp2dms,
+    hp2ddm,
+    hp2rad,
+    hp2dec_v,
+    gon2dec,
+    gon2deca,
+    gon2hp,
+    gon2hpa,
+    gon2dms,
+    gon2ddm,
+    gon2rad,
+    dd2sec,
+    angular_typecheck,
+)
 
 
 def polar2rect(r, theta):
     """
     Converts point in polar coordinates to corresponding rectangular coordinates
-    Theta is degrees and is measured clockwise from the positive y axis
-    (i.e. north)
+
     :param r: Radius
-    :param theta: Angle (decimal degrees)
+    :param theta: Angle (decimal degrees) from postive y axis (north)
     :type theta: Float (decimal degrees), DMSAngle or DDMAngle
     :return: Rectangular Coordinates X, Y
+
     """
     theta = angular_typecheck(theta)
     x = r * sin(radians(theta))
@@ -41,13 +62,14 @@ def rect2polar(x, y):
     Converts point in rectangular coordinates to corresponding polar coordinates
     Angular component of polar coordinates (theta) is in decimal degrees and
     is measured clockwise from the positive y axis (i.e. north)
+
     :param x: Rectangular Coordinate X
     :param y: Rectangular Coordinate Y
-    :return r: Radius
-    :return theta: Angle (decimal degrees)
-    :rtype theta: float (decimal degrees)
+    :return: 
+        - Radius
+        - Angle (decimal degrees)
     """
-    r = sqrt(x ** 2 + y ** 2)
+    r = sqrt(x**2 + y**2)
     theta = atan2(x, y)
     if theta < 0:
         theta = degrees(theta) + 360
@@ -60,101 +82,118 @@ def rect_radius(ellipsoid):
     """
     Computes the Rectifying Radius of an Ellipsoid with specified Inverse
     Flattening (See Ref 2 Equation 3)
+
     :param ellipsoid: Ellipsoid Object
     :type ellipsoid: Ellipsoid
     :return: Ellipsoid Rectifying Radius
     """
-    nval = (1 / float(ellipsoid.inversef)) /\
-           (2 - (1 / float(ellipsoid.inversef)))
+    nval = (1 / float(ellipsoid.inversef)) / (2 - (1 / float(ellipsoid.inversef)))
     nval2 = nval**2
-    return (ellipsoid.semimaj / (1 + nval) * ((nval2 *
-                                              (nval2 *
-                                               (nval2 *
-                                                (25 * nval2 + 64)
-                                                + 256)
-                                               + 4096)
-                                              + 16384)
-                                              / 16384.))
+    return (
+        ellipsoid.semimaj
+        / (1 + nval)
+        * (
+            (nval2 * (nval2 * (nval2 * (25 * nval2 + 64) + 256) + 4096) + 16384)
+            / 16384.0
+        )
+    )
 
 
 def alpha_coeff(ellipsoid):
     """
     Computes the set of Alpha coefficients of an Ellipsoid with specified
     Inverse Flattening (See Ref 2 Equation 5)
+
     :param ellipsoid: Ellipsoid Object
     :type ellipsoid: Ellipsoid
     :return: Alpha coefficients a2, a4 ... a16
     :rtype: tuple
     """
     nval = ellipsoid.n
-    a2 = ((nval *
-           (nval *
-            (nval *
-             (nval *
-              (nval *
-               (nval *
-                ((37884525 - 75900428 * nval)
-                 * nval + 42422016)
-                - 89611200)
-               + 46287360)
-              + 63504000)
-             - 135475200)
-            + 101606400))
-          / 203212800.)
-
-    a4 = ((nval ** 2 *
-           (nval *
-            (nval *
-             (nval *
-              (nval *
-               (nval *
-                (148003883 * nval + 83274912)
-                - 178508970)
-               + 77690880)
-              + 67374720)
-             - 104509440)
-            + 47174400))
-          / 174182400.)
-
-    a6 = ((nval ** 3 *
-           (nval *
-            (nval *
-             (nval *
-              (nval *
-               (318729724 * nval - 738126169)
-               + 294981280)
-              + 178924680)
-             - 234938880)
-            + 81164160))
-          / 319334400.)
-
-    a8 = ((nval ** 4 *
-           (nval *
-            (nval *
-             ((14967552000 - 40176129013 * nval) * nval + 6971354016)
-             - 8165836800)
-            + 2355138720))
-          / 7664025600.)
-
-    a10 = ((nval ** 5 *
-            (nval *
-             (nval *
-              (10421654396 * nval + 3997835751)
-              - 4266773472)
-             + 1072709352))
-           / 2490808320.)
-
-    a12 = ((nval ** 6 *
-            (nval *
-             (175214326799 * nval - 171950693600)
-             + 38652967262))
-           / 58118860800.)
-
-    a14 = ((nval ** 7 *
-            (13700311101 - 67039739596 * nval))
-           / 12454041600.)
-
-    a16 = (1424729850961 * nval ** 8) / 743921418240.
+    a2 = (
+        nval
+        * (
+            nval
+            * (
+                nval
+                * (
+                    nval
+                    * (
+                        nval
+                        * (
+                            nval * ((37884525 - 75900428 * nval) * nval + 42422016)
+                            - 89611200
+                        )
+                        + 46287360
+                    )
+                    + 63504000
+                )
+                - 135475200
+            )
+            + 101606400
+        )
+    ) / 203212800.0
+
+    a4 = (
+        nval**2
+        * (
+            nval
+            * (
+                nval
+                * (
+                    nval
+                    * (
+                        nval * (nval * (148003883 * nval + 83274912) - 178508970)
+                        + 77690880
+                    )
+                    + 67374720
+                )
+                - 104509440
+            )
+            + 47174400
+        )
+    ) / 174182400.0
+
+    a6 = (
+        nval**3
+        * (
+            nval
+            * (
+                nval
+                * (
+                    nval * (nval * (318729724 * nval - 738126169) + 294981280)
+                    + 178924680
+                )
+                - 234938880
+            )
+            + 81164160
+        )
+    ) / 319334400.0
+
+    a8 = (
+        nval**4
+        * (
+            nval
+            * (
+                nval * ((14967552000 - 40176129013 * nval) * nval + 6971354016)
+                - 8165836800
+            )
+            + 2355138720
+        )
+    ) / 7664025600.0
+
+    a10 = (
+        nval**5
+        * (nval * (nval * (10421654396 * nval + 3997835751) - 4266773472) + 1072709352)
+    ) / 2490808320.0
+
+    a12 = (
+        nval**6 * (nval * (175214326799 * nval - 171950693600) + 38652967262)
+    ) / 58118860800.0
+
+    a14 = (nval**7 * (13700311101 - 67039739596 * nval)) / 12454041600.0
+
+    a16 = (1424729850961 * nval**8) / 743921418240.0
     return a2, a4, a6, a8, a10, a12, a14, a16
 
 
@@ -162,77 +201,87 @@ def beta_coeff(ellipsoid):
     """
     Computes the set of Beta coefficients of an Ellipsoid with specified
     Inverse Flattening (See Ref 2 Equation 23)
+
     :param ellipsoid: Ellipsoid Object
     :type ellipsoid: Ellipsoid
     :return: Alpha coefficients a2, a4 ... a16
     :rtype: tuple
     """
     nval = ellipsoid.n
-    b2 = ((nval *
-           (nval *
-            (nval *
-             (nval *
-              (nval *
-               (nval *
-                ((37845269 - 31777436 * nval) - 43097152)
-                + 42865200)
-               + 752640)
-              - 104428800)
-             + 180633600)
-            - 135475200))
-          / 270950400.)
-
-    b4 = ((nval ** 2 *
-           (nval *
-            (nval *
-             (nval *
-              (nval *
-               ((-24749483 * nval - 14930208) * nval + 100683990)
-               - 152616960)
-              + 105719040)
-             - 23224320)
-            - 7257600))
-          / 348364800.)
-
-    b6 = ((nval ** 3 *
-           (nval *
-            (nval *
-             (nval *
-              (nval *
-               (232468668 * nval - 101880889)
-               - 39205760)
-              + 29795040)
-             + 28131840)
-            - 22619520))
-          / 638668800.)
-
-    b8 = ((nval ** 4 *
-           (nval *
-            (nval *
-             ((-324154477 * nval - 1433121792) * nval + 876745056)
-             + 167270400)
-            - 208945440))
-          / 7664025600.)
-
-    b10 = ((nval ** 5 *
-            (nval *
-             (nval *
-              (312227409 - 457888660 * nval)
-              + 67920528)
-             - 70779852))
-           / 2490808320.)
-
-    b12 = ((nval ** 6 *
-            (nval *
-             (19841813847 * nval + 3665348512)
-             - 3758062126))
-           / 116237721600.)
-
-    b14 = ((nval ** 7 *
-            (1989295244 * nval - 1979471673))
-           / 49816166400.)
-
-    b16 = ((-191773887257 * nval ** 8) / 3719607091200.)
+    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
+
+    b16 = (-191773887257 * nval**8) / 3719607091200.0
     return b2, b4, b6, b8, b10, b12, b14, b16
 
 
@@ -240,6 +289,7 @@ def psfandgridconv(xi1, eta1, lat, lon, cm, conf_lat, ellipsoid=grs80, prj=utm):
     """
     Calculates Point Scale Factor and Grid Convergence. Used in convert.geo2grid
     and convert.grid2geo
+
     :param xi1: Transverse Mercator Ratio Xi
     :param eta1: Transverse Mercator Ratio Eta
     :param lat: Latitude
@@ -263,20 +313,24 @@ def psfandgridconv(xi1, eta1, lat, lon, cm, conf_lat, ellipsoid=grs80, prj=utm):
     p = 1
     q = 0
     for r in range(1, 9):
-        p += 2*r * a[r-1] * cos(2*r * xi1) * cosh(2*r * eta1)
-        q += 2*r * a[r-1] * sin(2*r * xi1) * sinh(2*r * eta1)
+        p += 2 * r * a[r - 1] * cos(2 * r * xi1) * cosh(2 * r * eta1)
+        q += 2 * r * a[r - 1] * sin(2 * r * xi1) * sinh(2 * r * eta1)
     q = -q
-    psf = (float(prj.cmscale)
-           * (A / ellipsoid.semimaj)
-           * sqrt(q**2 + p**2)
-           * ((sqrt(1 + (tan(lat)**2))
-               * sqrt(1 - ellipsoid.ecc1sq * (sin(lat)**2)))
-              / sqrt((tan(conf_lat)**2) + (cos(long_diff)**2))))
+    psf = (
+        float(prj.cmscale)
+        * (A / ellipsoid.semimaj)
+        * sqrt(q**2 + p**2)
+        * (
+            (sqrt(1 + (tan(lat) ** 2)) * sqrt(1 - ellipsoid.ecc1sq * (sin(lat) ** 2)))
+            / sqrt((tan(conf_lat) ** 2) + (cos(long_diff) ** 2))
+        )
+    )
 
     # Grid Convergence
-    grid_conv = degrees(atan(abs(q / p))
-                        + atan(abs(tan(conf_lat) * tan(long_diff))
-                               / sqrt(1 + tan(conf_lat)**2)))
+    grid_conv = degrees(
+        atan(abs(q / p))
+        + atan(abs(tan(conf_lat) * tan(long_diff)) / sqrt(1 + tan(conf_lat) ** 2))
+    )
     if cm > lon and lat < 0:
         grid_conv = -grid_conv
     elif cm < lon and lat > 0:
@@ -292,12 +346,13 @@ def geo2grid(lat, lon, zone=0, ellipsoid=grs80, prj=utm):
     Scale Factor and Grid Convergence. Default Projection is Universal
     Transverse Mercator Projection using
     GRS80 Ellipsoid parameters.
+
     :param lat: Latitude
     :type lat: Float (Decimal Degrees), DMSAngle or DDMAngle
     :param lon: Longitude
     :type lon: Float (Decimal Degrees, DMSAngle or DDMAngle
     :param zone: Optional Zone Number - Only required if calculating grid
-                                        co-ordinate outside zone boundaries
+                 co-ordinate outside zone boundaries
     :param ellipsoid: Ellipsoid Object
     :type ellipsoid: Ellipsoid
     :return: hemisphere, zone, east (m), north (m), Point Scale Factor,
@@ -312,19 +367,24 @@ def geo2grid(lat, lon, zone=0, ellipsoid=grs80, prj=utm):
     zone = int(zone)
     if prj == isg:
         if zone not in (0, 541, 542, 543, 551, 552, 553, 561, 562, 563, 572):
-            raise ValueError('Invalid Zone - Choose from 541, 542, 543, 551, 552, 553, 561, 562, 563, 572')
+            raise ValueError(
+                "Invalid Zone - Choose from 541, 542, 543, 551, 552, 553, 561, 562, 563, 572"
+            )
     else:
         if zone < 0 or zone > 60:
-                raise ValueError('Invalid Zone - Zones from 1 to 60')
+            raise ValueError("Invalid Zone - Zones from 1 to 60")
 
     if lat < -80 or lat > 84:
-        raise ValueError('Invalid Latitude - Latitudes from -80 to +84')
+        raise ValueError("Invalid Latitude - Latitudes from -80 to +84")
 
     if lon < -180 or lon > 180:
-        raise ValueError('Invalid Longitude - Longitudes from -180 to +180')
+        raise ValueError("Invalid Longitude - Longitudes from -180 to +180")
 
     if prj == isg and ellipsoid != ans:
-        warnings.warn(message='ISG projection should be used with ANS ellipsoid', category=UserWarning)
+        warnings.warn(
+            message="ISG projection should be used with ANS ellipsoid",
+            category=UserWarning,
+        )
 
     A = rect_radius(ellipsoid)
     a = alpha_coeff(ellipsoid)
@@ -332,23 +392,31 @@ def geo2grid(lat, lon, zone=0, ellipsoid=grs80, prj=utm):
     # Calculate Zone
     if zone == 0:
         if prj == isg:
-            amgzone = (float(lon) - (prj.initialcm - (4.5 * prj.zonewidth))) / (prj.zonewidth * 3)
+            amgzone = (float(lon) - (prj.initialcm - (4.5 * prj.zonewidth))) / (
+                prj.zonewidth * 3
+            )
             subzone = int((amgzone - int(amgzone)) * 3 + 1)
             amgzone = int(amgzone)
-            zone = int(f'{amgzone}{subzone}')
+            zone = int(f"{amgzone}{subzone}")
         else:
-            zone = int((float(lon) - (prj.initialcm - (1.5 * prj.zonewidth))) / prj.zonewidth)
+            zone = int(
+                (float(lon) - (prj.initialcm - (1.5 * prj.zonewidth))) / prj.zonewidth
+            )
     if prj == isg:
         amgzone = int(str(zone)[:2])
         subzone = int(str(zone)[2])
-        cm = float((amgzone - 1) * prj.zonewidth * 3 + prj.initialcm + (subzone - 2) * prj.zonewidth)
+        cm = float(
+            (amgzone - 1) * prj.zonewidth * 3
+            + prj.initialcm
+            + (subzone - 2) * prj.zonewidth
+        )
     else:
         cm = float(zone * prj.zonewidth + prj.initialcm - prj.zonewidth)
 
     # Conformal Latitude
     sigx = (ellipsoid.ecc1 * tan(lat)) / sqrt(1 + (tan(lat) ** 2))
     sig = sinh(ellipsoid.ecc1 * (0.5 * log((1 + sigx) / (1 - sigx))))
-    conf_lat = tan(lat) * sqrt(1 + sig ** 2) - sig * sqrt(1 + (tan(lat) ** 2))
+    conf_lat = tan(lat) * sqrt(1 + sig**2) - sig * sqrt(1 + (tan(lat) ** 2))
     conf_lat = atan(conf_lat)
 
     # Longitude Difference
@@ -356,14 +424,14 @@ def geo2grid(lat, lon, zone=0, ellipsoid=grs80, prj=utm):
     # Gauss-Schreiber Ratios
     xi1 = atan(tan(conf_lat) / cos(long_diff))
     eta1x = sin(long_diff) / (sqrt(tan(conf_lat) ** 2 + cos(long_diff) ** 2))
-    eta1 = log(eta1x + sqrt(1 + eta1x ** 2))
+    eta1 = log(eta1x + sqrt(1 + eta1x**2))
 
     # Transverse Mercator Ratios
     eta = eta1
     xi = xi1
     for r in range(1, 9):
-        eta += a[r-1] * cos(2*r * xi1) * sinh(2*r * eta1)
-        xi += a[r-1] * sin(2*r * xi1) * cosh(2*r * eta1)
+        eta += a[r - 1] * cos(2 * r * xi1) * sinh(2 * r * eta1)
+        xi += a[r - 1] * sin(2 * r * xi1) * cosh(2 * r * eta1)
 
     # Transverse Mercator Co-ordinates
     x = A * eta
@@ -372,28 +440,33 @@ def geo2grid(lat, lon, zone=0, ellipsoid=grs80, prj=utm):
     # Hemisphere-dependent UTM Projection Co-ordinates
     east = prj.cmscale * x + prj.falseeast
     if y < 0:
-        hemisphere = 'South'
+        hemisphere = "South"
         north = prj.cmscale * y + prj.falsenorth
     else:
-        hemisphere = 'North'
+        hemisphere = "North"
         falsenorth = 0
         north = prj.cmscale * y + falsenorth
 
     # Point Scale Factor and Grid Convergence
     psf, grid_conv = psfandgridconv(xi1, eta1, degrees(lat), lon, cm, conf_lat)
 
-    return (hemisphere, zone,
-            round(float(east), 4),
-            round(float(north), 4),
-            round(psf, 8), grid_conv)
+    return (
+        hemisphere,
+        zone,
+        round(float(east), 4),
+        round(float(north), 4),
+        round(psf, 8),
+        grid_conv,
+    )
 
 
-def grid2geo(zone, east, north, hemisphere='south', ellipsoid=grs80, prj=utm):
+def grid2geo(zone, east, north, hemisphere="south", ellipsoid=grs80, prj=utm):
     """
     Takes a Transverse Mercator grid co-ordinate (Zone, Easting, Northing,
     Hemisphere) and returns its corresponding Geographic Latitude and Longitude,
     Point Scale Factor and Grid Convergence. Default Projection is Universal
     Transverse Mercator Projection using GRS80 Ellipsoid parameters.
+
     :param zone: Zone Number - 1 to 60
     :param east: Easting (m, within 3330km of Central Meridian)
     :param north: Northing (m, 0 to 10,000,000m)
@@ -408,30 +481,36 @@ def grid2geo(zone, east, north, hemisphere='south', ellipsoid=grs80, prj=utm):
     zone = int(zone)
     if prj == isg:
         if zone not in (541, 542, 543, 551, 552, 553, 561, 562, 563, 572):
-            raise ValueError('Invalid Zone - Choose from 541, 542, 543, 551, 552, 553, 561, 562, 563, 572')
+            raise ValueError(
+                "Invalid Zone - Choose from 541, 542, 543, 551, 552, 553, 561, 562, 563, 572"
+            )
     else:
         if zone < 0 or zone > 60:
-            raise ValueError('Invalid Zone - Zones from 1 to 60')
+            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 within" "3330km of Central Meridian"
+        )
 
     if north < 0 or north > 10000000:
-        raise ValueError('Invalid Northing - Must be between 0 and 10,000,000m')
+        raise ValueError("Invalid Northing - Must be between 0 and 10,000,000m")
 
     h = hemisphere.lower()
-    if h != 'north' and h != 'south':
-        raise ValueError('Invalid Hemisphere - String, either North or South')
+    if h != "north" and h != "south":
+        raise ValueError("Invalid Hemisphere - String, either North or South")
 
     if prj == isg and ellipsoid != ans:
-        warnings.warn(message='ISG projection should be used with ANS ellipsoid', category=UserWarning)
+        warnings.warn(
+            message="ISG projection should be used with ANS ellipsoid",
+            category=UserWarning,
+        )
 
     A = rect_radius(ellipsoid)
     b = beta_coeff(ellipsoid)
     # Transverse Mercator Co-ordinates
     x = (east - float(prj.falseeast)) / float(prj.cmscale)
-    if hemisphere.lower() == 'north':
+    if hemisphere.lower() == "north":
         y = -(north / float(prj.cmscale))
         hemisign = -1
     else:
@@ -446,8 +525,8 @@ def grid2geo(zone, east, north, hemisphere='south', ellipsoid=grs80, prj=utm):
     eta1 = eta
     xi1 = xi
     for r in range(1, 9):
-        eta1 += b[r-1] * cos(2*r * xi) * sinh(2*r * eta)
-        xi1 += b[r-1] * sin(2*r * xi) * cosh(2*r * eta)
+        eta1 += b[r - 1] * cos(2 * r * xi) * sinh(2 * r * eta)
+        xi1 += b[r - 1] * sin(2 * r * xi) * cosh(2 * r * eta)
 
     # Conformal Latitude
     conf_lat = (sin(xi1)) / (sqrt((sinh(eta1)) ** 2 + (cos(xi1)) ** 2))
@@ -456,20 +535,28 @@ def grid2geo(zone, east, north, hemisphere='south', ellipsoid=grs80, prj=utm):
 
     # Finding t using Newtons Method
     def sigma(tn, ecc1):
-        return (sinh(ecc1
-                     * 0.5
-                     * log((1 + ((ecc1 * tn) / (sqrt(1 + tn ** 2))))
-                           / (1 - ((ecc1 * tn) / (sqrt(1 + tn ** 2)))))))
+        return sinh(
+            ecc1
+            * 0.5
+            * log(
+                (1 + ((ecc1 * tn) / (sqrt(1 + tn**2))))
+                / (1 - ((ecc1 * tn) / (sqrt(1 + tn**2))))
+            )
+        )
 
     def ftn(tn, ecc1):
-        return (t * sqrt(1 + (sigma(tn, ecc1)) ** 2) -
-                sigma(tn, ecc1) * sqrt(1 + tn ** 2) - t1)
+        return (
+            t * sqrt(1 + (sigma(tn, ecc1)) ** 2)
+            - sigma(tn, ecc1) * sqrt(1 + tn**2)
+            - t1
+        )
 
     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)))
+        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)
+        )
 
     diff = 1
     t = t1
@@ -477,8 +564,7 @@ def f1tn(tn, ecc1, ecc1sq):
     while diff > 1e-15 and itercount < 100:
         itercount += 1
         t_before = t
-        t = t - (ftn(t, ellipsoid.ecc1)
-                 / f1tn(t, ellipsoid.ecc1, ellipsoid.ecc1sq))
+        t = t - (ftn(t, ellipsoid.ecc1) / f1tn(t, ellipsoid.ecc1, ellipsoid.ecc1sq))
         diff = abs(t - t_before)
     lat = degrees(atan(t))
 
@@ -486,7 +572,11 @@ def f1tn(tn, ecc1, ecc1sq):
     if prj == isg:
         amgzone = int(str(zone)[:2])
         subzone = int(str(zone)[2])
-        cm = float((amgzone - 1) * prj.zonewidth * 3 + prj.initialcm + (subzone - 2) * prj.zonewidth)
+        cm = float(
+            (amgzone - 1) * prj.zonewidth * 3
+            + prj.initialcm
+            + (subzone - 2) * prj.zonewidth
+        )
     else:
         cm = float((zone * prj.zonewidth) + prj.initialcm - prj.zonewidth)
     long_diff = degrees(atan(sinh(eta1) / cos(xi1)))
@@ -495,37 +585,41 @@ def f1tn(tn, ecc1, ecc1sq):
     # Point Scale Factor and Grid Convergence
     psf, grid_conv = psfandgridconv(xi1, eta1, lat, long, cm, conf_lat)
 
-    return (hemisign * round(lat, 11),
-            round(long, 11), round(psf, 8),
-            hemisign * grid_conv)
+    return (
+        hemisign * round(lat, 11),
+        round(long, 11),
+        round(psf, 8),
+        hemisign * grid_conv,
+    )
 
 
 def xyz2llh(x, y, z, ellipsoid=grs80):
     """
     Converts Cartesian X, Y, Z coordinate to Geographic Latitude, Longitude and
     Ellipsoid Height. Default Ellipsoid parameters used are GRS80.
+
     :param x: Cartesian X Coordinate (metres)
     :param y: Cartesian Y Coordinate (metres)
     :param z: Cartesian Z Coordinate (metres)
     :param ellipsoid: Ellipsoid Object
     :type ellipsoid: Ellipsoid
     :return: Geographic Latitude (Decimal Degrees), Longitude (Decimal Degrees)
-    and Ellipsoid Height (metres)
+             and Ellipsoid Height (metres)
     :rtype: tuple
     """
     # Calculate Longitude
     long = atan2(y, x)
     # Calculate Latitude
     p = sqrt(x**2 + y**2)
-    latinit = atan((z*(1+ellipsoid.ecc2sq))/p)
+    latinit = atan((z * (1 + ellipsoid.ecc2sq)) / p)
     lat = latinit
     itercheck = 1
     while abs(itercheck) > 1e-10:
-        nu = ellipsoid.semimaj/(sqrt(1 - ellipsoid.ecc1sq * (sin(lat))**2))
-        itercheck = lat - atan((z + nu * ellipsoid.ecc1sq * sin(lat))/p)
-        lat = atan((z + nu * ellipsoid.ecc1sq * sin(lat))/p)
-    nu = ellipsoid.semimaj/(sqrt(1 - ellipsoid.ecc1sq * (sin(lat))**2))
-    ellht = p/(cos(lat)) - nu
+        nu = ellipsoid.semimaj / (sqrt(1 - ellipsoid.ecc1sq * (sin(lat)) ** 2))
+        itercheck = lat - atan((z + nu * ellipsoid.ecc1sq * sin(lat)) / p)
+        lat = atan((z + nu * ellipsoid.ecc1sq * sin(lat)) / p)
+    nu = ellipsoid.semimaj / (sqrt(1 - ellipsoid.ecc1sq * (sin(lat)) ** 2))
+    ellht = p / (cos(lat)) - nu
     # Convert Latitude and Longitude to Degrees
     lat = degrees(lat)
     long = degrees(long)
@@ -536,6 +630,7 @@ def llh2xyz(lat, lon, ellht=0, ellipsoid=grs80):
     """
     Converts Geographic Latitude, Longitude and Ellipsoid Height to Cartesian
     X, Y and Z Coordinates. Default Ellipsoid parameters used are GRS80.
+
     :param lat: Geographic Latitude
     :type lat: Float (Decimal Degrees), DMSAngle or DDMAngle
     :param lon: Geographic Longitude
@@ -553,7 +648,7 @@ def llh2xyz(lat, lon, ellht=0, ellipsoid=grs80):
     if lat == 0:
         nu = grs80.semimaj
     else:
-        nu = ellipsoid.semimaj/(sqrt(1 - ellipsoid.ecc1sq * (sin(lat)**2)))
+        nu = ellipsoid.semimaj / (sqrt(1 - ellipsoid.ecc1sq * (sin(lat) ** 2)))
     # Calculate x, y, z
     x = (nu + ellht) * cos(lat) * cos(lon)
     y = (nu + ellht) * cos(lat) * sin(lon)
@@ -566,16 +661,18 @@ def date_to_yyyydoy(date):
     Convert a datetime.date object to a string in the form 'yyyy.doy',
     where yyyy is the 4 character year number and doy is the 3 character
     day of year
+
     :param date: datetime.date object
     :type date: datetime.date
     :return: string with date in the form 'yyyy.doy'
     :rtype: str
     """
     try:
-        return (str(date.timetuple().tm_year) + '.' +
-                str(date.timetuple().tm_yday).zfill(3))
+        return (
+            str(date.timetuple().tm_year) + "." + str(date.timetuple().tm_yday).zfill(3)
+        )
     except AttributeError:
-        raise AttributeError('Invalid date: date must be datetime.date object')
+        raise AttributeError("Invalid date: date must be datetime.date object")
 
 
 def yyyydoy_to_date(yyyydoy):
@@ -583,20 +680,21 @@ def yyyydoy_to_date(yyyydoy):
     Convert a string in the form of either 'yyyydoy' or 'yyyy.doy' to a
     datetime.date object, where yyyy is the 4 character year number and doy
     is the 3 character day of year
+
     :param yyyydoy: string with date in the form 'yyyy.doy' or 'yyyydoy'
     :return: datetime.date object
     :rtype: datetime.date
     """
     try:
-        if '.' in yyyydoy:
+        if "." in yyyydoy:
             if len(yyyydoy) != 8:
-                raise ValueError('Invalid string: must be yyyydoy or yyyy.doy')
-            yyyy, doy = yyyydoy.split('.')
+                raise ValueError("Invalid string: must be yyyydoy or yyyy.doy")
+            yyyy, doy = yyyydoy.split(".")
         else:
             if len(yyyydoy) != 7:
-                raise ValueError('Invalid string: must be yyyydoy or yyyy.doy')
+                raise ValueError("Invalid string: must be yyyydoy or yyyy.doy")
             yyyy = yyyydoy[0:4]
             doy = yyyydoy[4:7]
         return datetime.date(int(yyyy), 1, 1) + datetime.timedelta(int(doy) - 1)
     except ValueError:
-        raise ValueError('Invalid string: must be yyyydoy or yyyy.doy')
+        raise ValueError("Invalid string: must be yyyydoy or yyyy.doy")
diff --git a/geodepy/coord.py b/geodepy/coord.py
index 6540bb1..1463e64 100644
--- a/geodepy/coord.py
+++ b/geodepy/coord.py
@@ -6,33 +6,44 @@
 """
 
 from geodepy.constants import Projection, utm, grs80
-from geodepy.angles import (DECAngle, HPAngle, GONAngle, DMSAngle, DDMAngle,
-                            dec2hpa, dec2gona, dec2dms, dec2ddm,
-                            angular_typecheck)
+from geodepy.angles import (
+    DECAngle,
+    HPAngle,
+    GONAngle,
+    DMSAngle,
+    DDMAngle,
+    dec2hpa,
+    dec2gona,
+    dec2dms,
+    dec2ddm,
+    angular_typecheck,
+)
 from geodepy.convert import xyz2llh, llh2xyz, grid2geo, geo2grid
 
 
 class CoordCart(object):
     """
     Cartesian Coordinate Class
+
     Used for working with coordinates representing points in a 3 dimensional
     earth-centred earth-fixed system. N Value (optional) is the distance (m)
     at the coordinate that a reference surface (typically a geoid) is above
-    or below an ellipsoid
+    or below an ellipsoid.
     """
+
     def __init__(self, xaxis, yaxis, zaxis, nval=None):
         """
         :param xaxis: Distance (m) along X Axis (positive when passing through
-        intersection of equator and prime meridian)
+                      intersection of equator and prime meridian)
         :type xaxis: float
         :param yaxis: Distance (m) along Y Axis (positive when passing through
-        intersection of equator and 90 degrees east longitude)
+                      intersection of equator and 90 degrees east longitude)
         :type yaxis: float
         :param zaxis: Distance (m) along Z Axis (positive when passing through
-        north pole)
+                      north pole)
         :type zaxis: float
         :param nval: Distance (m) between a reference surface (typically a
-        geoid) and an ellipsoid (positive when surface is above ellipsoid)
+                     geoid) and an ellipsoid (positive when surface is above ellipsoid)
         :type nval: float
         """
         self.xaxis = float(xaxis)
@@ -44,36 +55,46 @@ def __init__(self, xaxis, yaxis, zaxis, nval=None):
             self.nval = float(nval)
 
     def __repr__(self):
-        return (f'CoordCart: X: {self.xaxis} Y: {self.yaxis} Z: {self.zaxis} '
-                f'NVal: {self.nval}')
+        return (
+            f"CoordCart: X: {self.xaxis} Y: {self.yaxis} Z: {self.zaxis} "
+            f"NVal: {self.nval}"
+        )
 
     def __eq__(self, other):
         if isinstance(other, CoordCart):
             return vars(self) == vars(other)
         else:
-            raise ValueError(f"Can't compare {self} to {other}. If other object"
-                             f" is coord, convert to CoordCart first.")
+            raise ValueError(
+                f"Can't compare {self} to {other}. If other object"
+                f" is coord, convert to CoordCart first."
+            )
 
     def __round__(self, n=None):
         if self.nval is None:
-            return CoordCart(round(self.xaxis, n), round(self.yaxis, n),
-                             round(self.zaxis, n))
+            return CoordCart(
+                round(self.xaxis, n), round(self.yaxis, n), round(self.zaxis, n)
+            )
         else:
-            return CoordCart(round(self.xaxis, n), round(self.yaxis, n),
-                             round(self.zaxis, n), round(self.nval, n))
+            return CoordCart(
+                round(self.xaxis, n),
+                round(self.yaxis, n),
+                round(self.zaxis, n),
+                round(self.nval, n),
+            )
 
     def geo(self, ellipsoid=grs80, notation=DECAngle):
         """
         Convert coordinates to Geographic
+
         Note: If no N Value, no Orthometric Height set.
+
         :param ellipsoid: geodepy.constants.Ellipsoid Object (default: grs80)
         :param notation: Latitude and Longitude Angle Notation format
         :type notation: geodepy.angle class or float
         :return: Geographic Coordinate
         :rtype: CoordGeo
         """
-        lat, lon, ell_ht = xyz2llh(self.xaxis, self.yaxis,
-                                   self.zaxis, ellipsoid)
+        lat, lon, ell_ht = xyz2llh(self.xaxis, self.yaxis, self.zaxis, ellipsoid)
         if notation is DECAngle:
             lat = DECAngle(lat)
             lon = DECAngle(lon)
@@ -92,20 +113,22 @@ def geo(self, ellipsoid=grs80, notation=DECAngle):
         elif notation is float:
             pass  # geodepy.convert.grid2geo returns float dec degrees
         else:
-            raise ValueError(f'CoordCart.geo() notation requires class float or'
-                             f' class from geodepy.angles module. '
-                             f'Supplied: {notation}')
+            raise ValueError(
+                f"CoordCart.geo() notation requires class float or"
+                f" class from geodepy.angles module. "
+                f"Supplied: {notation}"
+            )
         if self.nval is None:
             return CoordGeo(lat, lon, ell_ht)
         else:
-            return CoordGeo(lat, lon, ell_ht,
-                            ell_ht - self.nval)
+            return CoordGeo(lat, lon, ell_ht, ell_ht - self.nval)
 
     # TODO: Add functionality to utilise different TM projections
 
     def tm(self, ellipsoid=grs80, projection=utm):
         """
         Convert coordinates to Transverse Mercator
+
         :param ellipsoid: geodepy.constants.Ellipsoid Object (default: grs80)
         :param projection: geodepy.constants.Projection Object (default: utm)
         :return: Transverse Mercator Projection Coordinate
@@ -117,18 +140,20 @@ def tm(self, ellipsoid=grs80, projection=utm):
 class CoordGeo(object):
     """
     Geographic Coordinate Class
+
     Used for working with coordinates representing points in an ellipsoidal
     system with ellipsoid heights (m) relative to the surface of the ellipsoid.
     Orthometric heights (m) are relative to a different reference surface
     (typically a geoid).
     """
+
     def __init__(self, lat, lon, ell_ht=None, orth_ht=None):
         """
         :param lat: Geographic Latitude (angle between +90 and -90 degrees,
-        positive values are north of equator)
+                    positive values are north of equator)
         :type lat: float (decimal degrees) or any Angle object in geodepy.angles
         :param lon: Geographic Longitude (angle between +180 and -180 degrees,
-        positive values are east of central meridian)
+                    positive values are east of central meridian)
         :type lon: float (decimal degrees) or any Angle object in geodepy.angles
         :param ell_ht: Ellipsoid Height (m, positive is outside ellipsoid)
         :type ell_ht: float
@@ -138,14 +163,18 @@ def __init__(self, lat, lon, ell_ht=None, orth_ht=None):
         # Check latitude and longitude are supported types, both same type
         type_list = [float, DECAngle, HPAngle, GONAngle, DMSAngle, DDMAngle]
         if not all(x in type_list for x in [type(lat), type(lon)]):
-            raise TypeError(f'CoordGeo Latitude and Longitude must be type: '
-                            f'float (decimal degrees) or geodepy.angles class '
-                            f'Lat: {type(lat)}, Lon: {type(lon)}')
+            raise TypeError(
+                f"CoordGeo Latitude and Longitude must be type: "
+                f"float (decimal degrees) or geodepy.angles class "
+                f"Lat: {type(lat)}, Lon: {type(lon)}"
+            )
         if type(lat) != type(lon):
-            raise TypeError(f'CoordGeo Latitude and Longitude must have the '
-                            f'same notation type: float (decimal degrees) or '
-                            f'geodepy.angles class. Lat: {type(lat)}, '
-                            f'Lon: {type(lon)}')
+            raise TypeError(
+                f"CoordGeo Latitude and Longitude must have the "
+                f"same notation type: float (decimal degrees) or "
+                f"geodepy.angles class. Lat: {type(lat)}, "
+                f"Lon: {type(lon)}"
+            )
         self.lat = lat
         self.lon = lon
         if ell_ht is None:
@@ -158,28 +187,38 @@ def __init__(self, lat, lon, ell_ht=None, orth_ht=None):
             self.orth_ht = float(orth_ht)
 
     def __repr__(self):
-        return (f'CoordGeo: Lat: {self.lat} Lon: {self.lon} '
-                f'Ell_Ht: {self.ell_ht} Orth_Ht: {self.orth_ht}')
+        return (
+            f"CoordGeo: Lat: {self.lat} Lon: {self.lon} "
+            f"Ell_Ht: {self.ell_ht} Orth_Ht: {self.orth_ht}"
+        )
 
     def __eq__(self, other):
         if isinstance(other, CoordGeo):
             return vars(self) == vars(other)
         else:
-            raise ValueError(f"Can't compare {self} to {other}. If other object"
-                             f" is coord, convert to CoordGeo first.")
+            raise ValueError(
+                f"Can't compare {self} to {other}. If other object"
+                f" is coord, convert to CoordGeo first."
+            )
 
     def __round__(self, n=None):
         if self.ell_ht is None and self.orth_ht is None:
             return CoordGeo(round(self.lat, n), round(self.lon, n))
         elif self.ell_ht is None:
-            return CoordGeo(round(self.lat, n), round(self.lon, n),
-                            None, round(self.orth_ht, n))
+            return CoordGeo(
+                round(self.lat, n), round(self.lon, n), None, round(self.orth_ht, n)
+            )
         elif self.orth_ht is None:
-            return CoordGeo(round(self.lat, n), round(self.lon, n),
-                            round(self.ell_ht, n), None)
+            return CoordGeo(
+                round(self.lat, n), round(self.lon, n), round(self.ell_ht, n), None
+            )
         else:
-            return CoordGeo(round(self.lat, n), round(self.lon, n),
-                            round(self.ell_ht, n), round(self.orth_ht, n))
+            return CoordGeo(
+                round(self.lat, n),
+                round(self.lon, n),
+                round(self.ell_ht, n),
+                round(self.orth_ht, n),
+            )
 
     def notation(self, notation):
         if type(self.lat) == float:  # Decimal Degrees (float)
@@ -203,11 +242,11 @@ def notation(self, notation):
                 new_lon = dec2ddm(self.lon)
             else:
                 raise ValueError(
-                    f'CoordGeo.notation() notation requires class float or '
-                    f'class from geodepy.angles module. '
-                    f'Supplied: {notation}')
-        elif type(self.lat) in [DECAngle, HPAngle, GONAngle,
-                                DMSAngle, DDMAngle]:
+                    f"CoordGeo.notation() notation requires class float or "
+                    f"class from geodepy.angles module. "
+                    f"Supplied: {notation}"
+                )
+        elif type(self.lat) in [DECAngle, HPAngle, GONAngle, DMSAngle, DDMAngle]:
             # Use methods to convert from geodepy.angles classes
             if notation == float:
                 new_lat = self.lat.dec()
@@ -229,15 +268,18 @@ def notation(self, notation):
                 new_lon = self.lon.ddm()
             else:
                 raise ValueError(
-                    f'CoordGeo.notation() notation requires class float or '
-                    f'class from geodepy.angles module. '
-                    f'Supplied: {notation}')
+                    f"CoordGeo.notation() notation requires class float or "
+                    f"class from geodepy.angles module. "
+                    f"Supplied: {notation}"
+                )
         return CoordGeo(new_lat, new_lon, self.ell_ht, self.orth_ht)
 
     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
@@ -257,27 +299,29 @@ def cart(self, ellipsoid=grs80):
     def tm(self, ellipsoid=grs80, projection=utm):
         """
         Convert coordinates to Universal Transverse Mercator Projection
+
         Note: Heights are not used in calculation
+
         :param ellipsoid: geodepy.constants.Ellipsoid Object (default: grs80)
         :param projection: geodepy.constants.Projection Object (default: utm)
         :return: Transverse Mercator Projection Coordinate
         :rtype: CoordTM
         """
-        hemi, zone, east, north, psf, gc = geo2grid(self.lat, self.lon,
-                                                    0, ellipsoid)
-        if hemi == 'North':
+        hemi, zone, east, north, psf, gc = geo2grid(self.lat, self.lon, 0, ellipsoid)
+        if hemi == "North":
             hemi_north = True
         else:  # hemi == 'South'
             hemi_north = False
 
-        return CoordTM(zone, east, north,
-                       self.ell_ht, self.orth_ht,
-                       hemi_north, projection)
+        return CoordTM(
+            zone, east, north, self.ell_ht, self.orth_ht, hemi_north, projection
+        )
 
 
 class CoordTM(object):
     """
     Transverse Mercator Coordinate Class
+
     Used for working with coordinates representing points in a Transverse
     Mercator projected planar system. Coordinates are related to an ellipsoid
     via a projection (default is Universal Transverse Mercator, see
@@ -285,8 +329,17 @@ class CoordTM(object):
     are relative to the surface of the ellipsoid. Orthometric heights (m) are
     relative to a different reference surface (typically a geoid).
     """
-    def __init__(self, zone, east, north, ell_ht=None, orth_ht=None,
-                 hemi_north=False, projection=utm):
+
+    def __init__(
+        self,
+        zone,
+        east,
+        north,
+        ell_ht=None,
+        orth_ht=None,
+        hemi_north=False,
+        projection=utm,
+    ):
         """
         :param zone: Transverse Mercator Zone Number - 1 to 60
         :type zone: int
@@ -299,12 +352,12 @@ def __init__(self, zone, east, north, ell_ht=None, orth_ht=None,
         :param orth_ht: Orthometric Height (m)
         :type orth_ht: float
         :param hemi_north: True if coordinate in Northern Hemisphere, False if
-        coordinate in Southern Hemisphere (default)
+                           coordinate in Southern Hemisphere (default)
         :type hemi_north: bool
         :param projection: Information defining relationship between projected
-        coordinate and the ellipsoid
+                           coordinate and the ellipsoid
         :type projection: geodepy.constants.Projection object
-        (default: geodepy.constants.utm)
+                          (default: geodepy.constants.utm)
         """
         self.zone = int(zone)
         self.east = float(east)
@@ -320,50 +373,84 @@ def __init__(self, zone, east, north, ell_ht=None, orth_ht=None,
         if isinstance(hemi_north, bool):
             self.hemi_north = hemi_north
         else:
-            raise TypeError(f'CoordTM: invalid hemi_north, must be bool (True '
-                            f'for Northern Hemisphere, False for Southern). '
-                            f'hemi_north entered: {hemi_north}')
+            raise TypeError(
+                f"CoordTM: invalid hemi_north, must be bool (True "
+                f"for Northern Hemisphere, False for Southern). "
+                f"hemi_north entered: {hemi_north}"
+            )
         if isinstance(projection, Projection):
             self.projection = projection
         else:
-            raise TypeError(f'CoordTM: invalid projection, must be geodepy.'
-                            f'constants.Projection object (default is geodepy.'
-                            f'constants.utm. projection entered: {projection}')
+            raise TypeError(
+                f"CoordTM: invalid projection, must be geodepy."
+                f"constants.Projection object (default is geodepy."
+                f"constants.utm. projection entered: {projection}"
+            )
 
     def __repr__(self):
         if self.hemi_north:
-            return (f'CoordTM: Zone: {self.zone} East: {self.east} '
-                    f'North: {self.north} Ell_Ht: {self.ell_ht} '
-                    f'Orth_Ht: {self.orth_ht} Hemisphere: North')
+            return (
+                f"CoordTM: Zone: {self.zone} East: {self.east} "
+                f"North: {self.north} Ell_Ht: {self.ell_ht} "
+                f"Orth_Ht: {self.orth_ht} Hemisphere: North"
+            )
         else:  # not self.hemi_north
-            return (f'CoordTM: Zone: {self.zone} East: {self.east} '
-                    f'North: {self.north} Ell_Ht: {self.ell_ht} '
-                    f'Orth_Ht: {self.orth_ht} Hemisphere: South')
+            return (
+                f"CoordTM: Zone: {self.zone} East: {self.east} "
+                f"North: {self.north} Ell_Ht: {self.ell_ht} "
+                f"Orth_Ht: {self.orth_ht} Hemisphere: South"
+            )
 
     def __eq__(self, other):
         if isinstance(other, CoordTM):
             return vars(self) == vars(other)
         else:
-            raise ValueError(f"Can't compare {self} to {other}. If other object"
-                             f" is coord, convert to CoordTM first.")
+            raise ValueError(
+                f"Can't compare {self} to {other}. If other object"
+                f" is coord, convert to CoordTM first."
+            )
 
     def __round__(self, n=None):
         if self.ell_ht is None and self.orth_ht is None:
-            return CoordTM(self.zone, round(self.east, n), round(self.north, n),
-                           None, None,
-                           self.hemi_north, self.projection)
+            return CoordTM(
+                self.zone,
+                round(self.east, n),
+                round(self.north, n),
+                None,
+                None,
+                self.hemi_north,
+                self.projection,
+            )
         elif self.ell_ht is None:
-            return CoordTM(self.zone, round(self.east, n), round(self.north, n),
-                           None, round(self.orth_ht, n),
-                           self.hemi_north, self.projection)
+            return CoordTM(
+                self.zone,
+                round(self.east, n),
+                round(self.north, n),
+                None,
+                round(self.orth_ht, n),
+                self.hemi_north,
+                self.projection,
+            )
         elif self.orth_ht is None:
-            return CoordTM(self.zone, round(self.east, n), round(self.north, n),
-                           round(self.ell_ht, n), None,
-                           self.hemi_north, self.projection)
+            return CoordTM(
+                self.zone,
+                round(self.east, n),
+                round(self.north, n),
+                round(self.ell_ht, n),
+                None,
+                self.hemi_north,
+                self.projection,
+            )
         else:
-            return CoordTM(self.zone, round(self.east, n), round(self.north, n),
-                           round(self.ell_ht, n), round(self.orth_ht, n),
-                           self.hemi_north, self.projection)
+            return CoordTM(
+                self.zone,
+                round(self.east, n),
+                round(self.north, n),
+                round(self.ell_ht, n),
+                round(self.orth_ht, n),
+                self.hemi_north,
+                self.projection,
+            )
 
     def geo(self, ellipsoid=grs80, notation=DECAngle):
         """
@@ -371,14 +458,16 @@ def geo(self, ellipsoid=grs80, notation=DECAngle):
         :param ellipsoid: geodepy.constants.Ellipsoid Object (default: grs80)
         :param notation: Latitude and Longitude Angle Notation format
         :type notation: geodepy.angle class or float
-        :return:
+        :return: Geographic Coordinate
+        :rtype: CoordGeo
         """
         if self.hemi_north:
-            hemi_str = 'north'
+            hemi_str = "north"
         else:
-            hemi_str = 'south'
-        lat, lon, psf, grid_conv = grid2geo(self.zone, self.east, self.north,
-                                            hemi_str, ellipsoid)
+            hemi_str = "south"
+        lat, lon, psf, grid_conv = grid2geo(
+            self.zone, self.east, self.north, hemi_str, ellipsoid
+        )
         if notation is DECAngle:
             lat = DECAngle(lat)
             lon = DECAngle(lon)
@@ -397,9 +486,11 @@ def geo(self, ellipsoid=grs80, notation=DECAngle):
         elif notation is float:
             pass  # geodepy.convert.grid2geo returns float dec degrees
         else:
-            raise ValueError(f'CoordTM.geo() notation requires class float or '
-                             f'class from geodepy.angles module. '
-                             f'Supplied: {notation}')
+            raise ValueError(
+                f"CoordTM.geo() notation requires class float or "
+                f"class from geodepy.angles module. "
+                f"Supplied: {notation}"
+            )
         return CoordGeo(lat, lon, self.ell_ht, self.orth_ht)
 
     # TODO: Add functionality to utilise different TM projections
@@ -407,7 +498,9 @@ def geo(self, ellipsoid=grs80, notation=DECAngle):
     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/fileio.py b/geodepy/fileio.py
index 8a0c4f2..8e7d63a 100644
--- a/geodepy/fileio.py
+++ b/geodepy/fileio.py
@@ -9,8 +9,25 @@
 
 
 class DNACoord(object):
-    def __init__(self, pointid, const, easting, northing, zone, lat,
-                 long, ortho_ht, ell_ht, x, y, z, x_sd, y_sd, z_sd, desc):
+    def __init__(
+        self,
+        pointid,
+        const,
+        easting,
+        northing,
+        zone,
+        lat,
+        long,
+        ortho_ht,
+        ell_ht,
+        x,
+        y,
+        z,
+        x_sd,
+        y_sd,
+        z_sd,
+        desc,
+    ):
         self.pointid = pointid
         self.const = const
         self.easting = easting
@@ -35,7 +52,7 @@ def converthptodd(self):
 
 def read_dnacoord(fn):
     coord_list = []
-    with open(fn, 'r') as file:
+    with open(fn, "r") as file:
         dnadata = file.readlines()
         for line in dnadata:
             pointid = line[0:20]
@@ -54,8 +71,23 @@ def read_dnacoord(fn):
             y_sd = float(line[172:181])
             z_sd = float(line[182:191])
             desc = line[192:-1]
-            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())
+            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
diff --git a/geodepy/geodesy.py b/geodepy/geodesy.py
index b20b891..237f73a 100644
--- a/geodepy/geodesy.py
+++ b/geodepy/geodesy.py
@@ -16,6 +16,7 @@
 def enu2xyz(lat, lon, east, north, up):
     """Convert a column vector in the local reference frame to a column vector
     in the Cartesian reference frame.
+
     :param lat: latitude in decimal degrees
     :param lon: longitude in decimal degrees
     :param east: in metres
@@ -35,6 +36,7 @@ def enu2xyz(lat, lon, east, north, up):
 def xyz2enu(lat, lon, x, y, z):
     """Convert a column vector in the Cartesian reference frame to a column
     vector in the local reference frame.
+
     :param lat: latitude in decimal degrees
     :param lon: longitude in decimal degrees
     :param x: in metres
@@ -54,6 +56,7 @@ def xyz2enu(lat, lon, x, y, z):
 def vincdir(lat1, lon1, azimuth1to2, ell_dist, ellipsoid=grs80):
     """
     Vincenty's Direct Formula
+
     :param lat1: Latitude of Point 1 (decimal degrees)
     :type lat1: float (decimal degrees), DMSAngle or DDMAngle
     :param lon1: Longitude of Point 1 (decimal degrees)
@@ -62,11 +65,11 @@ 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: lat2: Latitude of Point 2 (Decimal Degrees),
-             lon2: Longitude of Point 2 (Decimal Degrees),
-             azimuth2to1: Azimuth from Point 2 to 1 (Decimal Degrees)
+    :return: 
+        - lat2 - Latitude of Point 2 (Decimal Degrees),
+        - lon2 - Longitude of Point 2 (Decimal Degrees),
+        - azimuth2to1 - Azimuth from Point 2 to 1 (Decimal Degrees)
 
-    Code review: 14-08-2018 Craig Harrison
     """
 
     # Convert Angles to Decimal Degrees (if required)
@@ -86,17 +89,21 @@ def vincdir(lat1, lon1, azimuth1to2, ell_dist, ellipsoid=grs80):
     alpha = asin(cos(u1) * sin(azimuth1to2))
 
     # Eq. 91
-    u_squared = cos(alpha)**2 \
-        * (ellipsoid.semimaj**2 - ellipsoid.semimin**2) \
+    u_squared = (
+        cos(alpha) ** 2
+        * (ellipsoid.semimaj**2 - ellipsoid.semimin**2)
         / ellipsoid.semimin**2
+    )
 
     # Eq. 92
-    a = 1 + (u_squared / 16384) \
-        * (4096 + u_squared * (-768 + u_squared * (320 - 175 * u_squared)))
+    a = 1 + (u_squared / 16384) * (
+        4096 + u_squared * (-768 + u_squared * (320 - 175 * u_squared))
+    )
 
     # Eq. 93
-    b = (u_squared / 1024) \
-        * (256 + u_squared * (-128 + u_squared * (74 - 47 * u_squared)))
+    b = (u_squared / 1024) * (
+        256 + u_squared * (-128 + u_squared * (74 - 47 * u_squared))
+    )
 
     # Eq. 94
     sigma = ell_dist / (ellipsoid.semimin * a)
@@ -107,15 +114,24 @@ def vincdir(lat1, lon1, azimuth1to2, ell_dist, ellipsoid=grs80):
     for i in range(1000):
 
         # Eq. 95
-        two_sigma_m = 2*sigma1 + sigma
+        two_sigma_m = 2 * sigma1 + sigma
 
         # Eq. 96
-        delta_sigma = b * sin(sigma) * (cos(two_sigma_m) + (b/4)
-                                        * (cos(sigma)
-                                           * (-1 + 2 * cos(two_sigma_m)**2)
-                                           - (b/6) * cos(two_sigma_m)
-                                           * (-3 + 4 * sin(sigma)**2)
-                                           * (-3 + 4 * cos(two_sigma_m)**2)))
+        delta_sigma = (
+            b
+            * sin(sigma)
+            * (
+                cos(two_sigma_m)
+                + (b / 4)
+                * (
+                    cos(sigma) * (-1 + 2 * cos(two_sigma_m) ** 2)
+                    - (b / 6)
+                    * cos(two_sigma_m)
+                    * (-3 + 4 * sin(sigma) ** 2)
+                    * (-3 + 4 * cos(two_sigma_m) ** 2)
+                )
+            )
+        )
         new_sigma = (ell_dist / (ellipsoid.semimin * a)) + delta_sigma
         sigma_change = new_sigma - sigma
         sigma = new_sigma
@@ -125,32 +141,51 @@ def vincdir(lat1, lon1, azimuth1to2, ell_dist, ellipsoid=grs80):
 
     # Calculate the Latitude of Point 2
     # Eq. 98
-    lat2 = atan2(sin(u1)*cos(sigma) + cos(u1)*sin(sigma)*cos(azimuth1to2),
-                 (1 - ellipsoid.f)
-                 * sqrt(sin(alpha)**2 + (sin(u1)*sin(sigma)
-                        - cos(u1)*cos(sigma)*cos(azimuth1to2))**2))
+    lat2 = atan2(
+        sin(u1) * cos(sigma) + cos(u1) * sin(sigma) * cos(azimuth1to2),
+        (1 - ellipsoid.f)
+        * sqrt(
+            sin(alpha) ** 2
+            + (sin(u1) * sin(sigma) - cos(u1) * cos(sigma) * cos(azimuth1to2)) ** 2
+        ),
+    )
     lat2 = degrees(lat2)
 
     # Calculate the Longitude of Point 2
     # Eq. 99
-    lon = atan2(sin(sigma)*sin(azimuth1to2),
-                cos(u1)*cos(sigma) - sin(u1)*sin(sigma)*cos(azimuth1to2))
+    lon = atan2(
+        sin(sigma) * sin(azimuth1to2),
+        cos(u1) * cos(sigma) - sin(u1) * sin(sigma) * cos(azimuth1to2),
+    )
 
     # Eq. 100
-    c = (ellipsoid.f/16)*cos(alpha)**2 \
-        * (4 + ellipsoid.f*(4 - 3*cos(alpha)**2))
+    c = (
+        (ellipsoid.f / 16)
+        * cos(alpha) ** 2
+        * (4 + ellipsoid.f * (4 - 3 * cos(alpha) ** 2))
+    )
 
     # Eq. 101
-    omega = lon - (1-c)*ellipsoid.f*sin(alpha) \
-        * (sigma + c*sin(sigma)*(cos(two_sigma_m) + c*cos(sigma)
-                                 * (-1 + 2*cos(two_sigma_m)**2)))
+    omega = lon - (1 - c) * ellipsoid.f * sin(alpha) * (
+        sigma
+        + c
+        * sin(sigma)
+        * (cos(two_sigma_m) + c * cos(sigma) * (-1 + 2 * cos(two_sigma_m) ** 2))
+    )
 
     # Eq. 102
     lon2 = float(lon1) + degrees(omega)
 
     # Calculate the Reverse Azimuth
-    azimuth2to1 = degrees(atan2(sin(alpha), -sin(u1)*sin(sigma)
-                          + cos(u1)*cos(sigma)*cos(azimuth1to2))) + 180
+    azimuth2to1 = (
+        degrees(
+            atan2(
+                sin(alpha),
+                -sin(u1) * sin(sigma) + cos(u1) * cos(sigma) * cos(azimuth1to2),
+            )
+        )
+        + 180
+    )
 
     return round(lat2, 11), round(lon2, 11), round(azimuth2to1, 9)
 
@@ -158,6 +193,7 @@ def vincdir(lat1, lon1, azimuth1to2, ell_dist, ellipsoid=grs80):
 def vincinv(lat1, lon1, lat2, lon2, ellipsoid=grs80):
     """
     Vincenty's Inverse Formula
+
     :param lat1: Latitude of Point 1 (decimal degrees)
     :type lat1: float (decimal degrees), DMSAngle or DDMAngle
     :param lon1: Longitude of Point 1 (decimal degrees)
@@ -167,10 +203,11 @@ def vincinv(lat1, lon1, lat2, lon2, ellipsoid=grs80):
     :param lon2: Longitude of Point 2 (decimal degrees)
     :type lon2: float (decimal degrees), DMSAngle or DDMAngle
     :param ellipsoid: Ellipsoid Object
-    :return: 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)
-    Code review: 14-08-2018 Craig Harrison
+    :return:
+        - 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)
@@ -204,29 +241,37 @@ def vincinv(lat1, lon1, lat2, lon2, ellipsoid=grs80):
     for i in range(1000):
 
         # Eq. 74
-        sin_sigma = sqrt((cos(u2)*sin(lon))**2
-                         + (cos(u1)*sin(u2) - sin(u1)*cos(u2)*cos(lon))**2)
+        sin_sigma = sqrt(
+            (cos(u2) * sin(lon)) ** 2
+            + (cos(u1) * sin(u2) - sin(u1) * cos(u2) * cos(lon)) ** 2
+        )
 
         # Eq. 75
-        cos_sigma = sin(u1)*sin(u2) + cos(u1)*cos(u2)*cos(lon)
+        cos_sigma = sin(u1) * sin(u2) + cos(u1) * cos(u2) * cos(lon)
 
         # Eq. 76
         sigma = atan2(sin_sigma, cos_sigma)
 
         # Eq. 77
-        alpha = asin((cos(u1)*cos(u2)*sin(lon)) / sin_sigma)
+        alpha = asin((cos(u1) * cos(u2) * sin(lon)) / sin_sigma)
 
         # Eq. 78
-        cos_two_sigma_m = cos(sigma) - (2*sin(u1)*sin(u2) / cos(alpha)**2)
+        cos_two_sigma_m = cos(sigma) - (2 * sin(u1) * sin(u2) / cos(alpha) ** 2)
 
         # Eq. 79
-        c = (ellipsoid.f / 16) * cos(alpha)**2 * (4 + ellipsoid.f
-                                                  * (4 - 3*cos(alpha)**2))
+        c = (
+            (ellipsoid.f / 16)
+            * cos(alpha) ** 2
+            * (4 + ellipsoid.f * (4 - 3 * cos(alpha) ** 2))
+        )
 
         # Eq. 80
-        new_lon = omega + (1 - c) * ellipsoid.f * sin(alpha) * (sigma + c*sin(sigma)
-                                                                * (cos_two_sigma_m + c * cos(sigma)
-                                                                   * (-1 + 2*(cos_two_sigma_m**2))))
+        new_lon = omega + (1 - c) * ellipsoid.f * sin(alpha) * (
+            sigma
+            + c
+            * sin(sigma)
+            * (cos_two_sigma_m + c * cos(sigma) * (-1 + 2 * (cos_two_sigma_m**2)))
+        )
 
         delta_lon = new_lon - lon
         lon = new_lon
@@ -235,61 +280,83 @@ def vincinv(lat1, lon1, lat2, lon2, ellipsoid=grs80):
             break
 
     # Eq. 81
-    u_squared = cos(alpha)**2 \
-        * (ellipsoid.semimaj**2 - ellipsoid.semimin**2) \
+    u_squared = (
+        cos(alpha) ** 2
+        * (ellipsoid.semimaj**2 - ellipsoid.semimin**2)
         / ellipsoid.semimin**2
+    )
 
     # Eq. 82
-    a = 1 + (u_squared / 16384) \
-        * (4096 + u_squared * (-768 + u_squared * (320 - 175 * u_squared)))
+    a = 1 + (u_squared / 16384) * (
+        4096 + u_squared * (-768 + u_squared * (320 - 175 * u_squared))
+    )
 
     # Eq. 83
-    b = (u_squared / 1024) \
-        * (256 + u_squared * (-128 + u_squared * (74 - 47 * u_squared)))
+    b = (u_squared / 1024) * (
+        256 + u_squared * (-128 + u_squared * (74 - 47 * u_squared))
+    )
 
     # Eq. 84
-    delta_sigma = b*sin(sigma) * (cos_two_sigma_m + (b / 4)
-                                  * (cos(sigma) * (-1 + 2*cos_two_sigma_m**2)
-                                  - (b / 6)*cos_two_sigma_m
-                                  * (-3 + 4*sin(sigma)**2)
-                                  * (-3 + 4*cos_two_sigma_m**2)))
+    delta_sigma = (
+        b
+        * sin(sigma)
+        * (
+            cos_two_sigma_m
+            + (b / 4)
+            * (
+                cos(sigma) * (-1 + 2 * cos_two_sigma_m**2)
+                - (b / 6)
+                * cos_two_sigma_m
+                * (-3 + 4 * sin(sigma) ** 2)
+                * (-3 + 4 * cos_two_sigma_m**2)
+            )
+        )
+    )
 
     # Calculate the ellipsoidal distance
     # Eq. 85
-    ell_dist = ellipsoid.semimin*a * (sigma - delta_sigma)
+    ell_dist = ellipsoid.semimin * a * (sigma - delta_sigma)
 
     # Calculate the azimuth from point 1 to point 2
-    azimuth1to2 = degrees(atan2((cos(u2)*sin(lon)),
-                                (cos(u1)*sin(u2)
-                                 - sin(u1)*cos(u2)*cos(lon))))
+    azimuth1to2 = degrees(
+        atan2((cos(u2) * sin(lon)), (cos(u1) * sin(u2) - sin(u1) * cos(u2) * cos(lon)))
+    )
 
     if azimuth1to2 < 0:
         azimuth1to2 = azimuth1to2 + 360
 
     # Calculate the azimuth from point 2 to point 1
-    azimuth2to1 = degrees(atan2(cos(u1)*sin(lon),
-                                (-sin(u1)*cos(u2)
-                                 + cos(u1)*sin(u2)*cos(lon)))) + 180
+    azimuth2to1 = (
+        degrees(
+            atan2(
+                cos(u1) * sin(lon), (-sin(u1) * cos(u2) + cos(u1) * sin(u2) * cos(lon))
+            )
+        )
+        + 180
+    )
 
     # Meridian Critical Case Tests
-    #if lon1 == lon2 and lat1 > lat2:
+    # if lon1 == lon2 and lat1 > lat2:
     #    azimuth1to2 = 180
     #    azimuth2to1 = 0
-    #elif lon1 == lon2 and lat1 < lat2:
+    # elif lon1 == lon2 and lat1 < lat2:
     #    azimuth1to2 = 0
     #    azimuth2to1 = 180
 
     return round(ell_dist, 3), round(azimuth1to2, 9), round(azimuth2to1, 9)
 
 
-def vincdir_utm(zone1, east1, north1, grid1to2, grid_dist,
-                hemisphere='south', ellipsoid=grs80):
+def vincdir_utm(
+    zone1, east1, north1, grid1to2, grid_dist, hemisphere="south", ellipsoid=grs80
+):
     """
     Perform Vincenty's Direct Computation using UTM Grid Coordinates, a
     grid bearing and grid distance.
+
     Note: Point 2 UTM Coordinates use the Zone specified for Point 1, even if
     Point 2 would typically be computed in a different zone. This keeps the grid
     bearings and line scale factor all relative to the same UTM Zone.
+
     :param zone1: Point 1 Zone Number - 1 to 60
     :param east1: Point 1 Easting (m, within 3330km of Central Meridian)
     :param north1: Point 1 Northing (m, 0 to 10,000,000m)
@@ -297,25 +364,24 @@ def vincdir_utm(zone1, east1, north1, grid1to2, grid_dist,
     :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: 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)
-             grid2to1: Grid Bearing from Point 2 to 1 (decimal degrees)
-             lsf: Line Scale Factor (for Point 1 Zone)
+    :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)
+        - grid2to1 - Grid Bearing from Point 2 to 1 (decimal degrees)
+        - lsf -  Line Scale Factor (for Point 1 Zone)
     """
     # Convert angle to decimal degrees (if required)
     grid1to2 = angular_typecheck(grid1to2)
 
     # Convert UTM Coords to Geographic
-    lat1, lon1, psf1, gridconv1 = grid2geo(zone1, east1, north1,
-                                           hemisphere, ellipsoid)
+    lat1, lon1, psf1, gridconv1 = grid2geo(zone1, east1, north1, hemisphere, ellipsoid)
 
     # Convert Grid Bearing to Geodetic Azimuth
     az1to2 = grid1to2 - gridconv1
 
     # Estimate Line Scale Factor (LSF)
-    zone2, east2, north2 = (zone1, *radiations(east1, north1,
-                                               grid1to2, grid_dist))
+    zone2, east2, north2 = (zone1, *radiations(east1, north1, grid1to2, grid_dist))
     lsf = line_sf(zone1, east1, north1, zone2, east2, north2)
 
     # Iteratively estimate Pt 2 Coordinates, refining LSF each time
@@ -323,31 +389,30 @@ def vincdir_utm(zone1, east1, north1, grid1to2, grid_dist,
     max_iter = 10
     while lsf_diff > 1e-9:
         lsf_previous = lsf
-        lat2, lon2, az2to1 = vincdir(lat1, lon1, az1to2,
-                                     grid_dist / lsf, ellipsoid)
-        (hemisphere2, zone2, east2,
-         north2, psf2, gridconv2) = geo2grid(lat2, lon2,
-                                             zone1, ellipsoid)
-        lsf = line_sf(zone1, east1, north1,
-                      zone2, east2, north2,
-                      hemisphere, ellipsoid)
+        lat2, lon2, az2to1 = vincdir(lat1, lon1, az1to2, grid_dist / lsf, ellipsoid)
+        (hemisphere2, zone2, east2, north2, psf2, gridconv2) = geo2grid(
+            lat2, lon2, zone1, ellipsoid
+        )
+        lsf = line_sf(zone1, east1, north1, zone2, east2, north2, hemisphere, ellipsoid)
         lsf_diff = abs(lsf_previous - lsf)
 
     # Compute Grid Bearing for Station 2
-    lat2, lon2, psf2, gridconv2 = grid2geo(zone2, east2, north2,
-                                           hemisphere, ellipsoid)
+    lat2, lon2, psf2, gridconv2 = grid2geo(zone2, east2, north2, hemisphere, ellipsoid)
     grid2to1 = az2to1 + gridconv2
 
     return zone2, east2, north2, grid2to1, lsf
 
 
-def vincinv_utm(zone1, east1, north1, zone2, east2, north2,
-                hemisphere='south', ellipsoid=grs80):
+def vincinv_utm(
+    zone1, east1, north1, zone2, east2, north2, hemisphere="south", ellipsoid=grs80
+):
     """
-    Perform Vincentys Inverse Computation using UTM Grid Coordinates
+    Perform Vincentys Inverse Computation using UTM Grid Coordinates.
+
     Note: Where coordinates from different zones are used, UTM Grid Distance
     is relative to Point 1's Zone. Grid Bearings of Points 1 and 2 are
     relative to each of their respective Zones.
+
     :param zone1: Point 1 Zone Number - 1 to 60
     :param east1: Point 1 Easting (m, within 3330km of Central Meridian)
     :param north1: Point 1 Northing (m, 0 to 10,000,000m)
@@ -356,20 +421,19 @@ def vincinv_utm(zone1, east1, north1, zone2, east2, north2,
     :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: 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)
-             lsf: Line Scale Factor (for Point 1 Zone)
+    :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)
+        - lsf - Line Scale Factor (for Point 1 Zone)
     """
     # Convert utm to geographic
     pt1 = grid2geo(zone1, east1, north1, hemisphere, ellipsoid)
     pt2 = grid2geo(zone2, east2, north2, hemisphere, ellipsoid)
-    ell_dist, az1to2, az2to1 = vincinv(pt1[0], pt1[1],
-                                       pt2[0], pt2[1], ellipsoid)
+    ell_dist, az1to2, az2to1 = vincinv(pt1[0], pt1[1], pt2[0], pt2[1], ellipsoid)
 
     # Compute Grid Distance using Line Scale Factor
-    lsf = line_sf(zone1, east1, north1,
-                  zone2, east2, north2, hemisphere, ellipsoid)
+    lsf = line_sf(zone1, east1, north1, zone2, east2, north2, hemisphere, ellipsoid)
     grid_dist = ell_dist * lsf
 
     # Compute Grid Bearings using Grid Convergence
@@ -379,13 +443,24 @@ def vincinv_utm(zone1, east1, north1, zone2, east2, north2,
     return grid_dist, grid1to2, grid2to1, lsf
 
 
-def line_sf(zone1, east1, north1, zone2, east2, north2,
-            hemisphere='south', ellipsoid=grs80, projection=utm):
+def line_sf(
+    zone1,
+    east1,
+    north1,
+    zone2,
+    east2,
+    north2,
+    hemisphere="south",
+    ellipsoid=grs80,
+    projection=utm,
+):
     """
-    Computes Line Scale Factor for a pair of Transverse Mercator Coordinates
+    Computes Line Scale Factor for a pair of Transverse Mercator Coordinates.
+
     Ref: Deakin 2010, Traverse Computations on the Ellipsoid and on the
     Universal Transverse Mercator Projection, pp 35
     http://www.mygeodesy.id.au/documents/Trav_Comp_V2.1.pdf
+
     :param zone1: Station 1 Zone Number - 1 to 60
     :param east1: Station 1 Easting (m, within 3330km of Central Meridian)
     :param north1: Station 1 Northing (m, 0 to 10,000,000m)
@@ -396,7 +471,7 @@ def line_sf(zone1, east1, north1, zone2, east2, north2,
     :param ellipsoid: Ellipsoid Object (default GRS80)
     :param projection: Projection Object (default Universal Transverse Mercator)
     :return: Line Scale Factor (relative to Zone 1 if different zones
-    are entered)
+             are entered)
     """
     # Re-project cross-zone coordinate to same UTM zone
     if zone1 != zone2:
@@ -417,13 +492,9 @@ def line_sf(zone1, east1, north1, zone2, east2, north2,
     lat_mean = (lat1 + lat2) / 2
 
     # Compute Line Scale Factor (Deakin 2010 Eq. 13)
-    r_sq_m = (rho(lat_mean, ellipsoid) *
-              nu(lat_mean, ellipsoid) *
-              projection.cmscale ** 2)
-    k1 = ((eastofcm1 ** 2 + eastofcm1 * eastofcm2 + eastofcm2 ** 2) /
-          (6 * r_sq_m))
-    k2 = ((eastofcm1 ** 2 + eastofcm1 * eastofcm2 + eastofcm2 ** 2) /
-          (36 * r_sq_m))
+    r_sq_m = rho(lat_mean, ellipsoid) * nu(lat_mean, ellipsoid) * projection.cmscale**2
+    k1 = (eastofcm1**2 + eastofcm1 * eastofcm2 + eastofcm2**2) / (6 * r_sq_m)
+    k2 = (eastofcm1**2 + eastofcm1 * eastofcm2 + eastofcm2**2) / (36 * r_sq_m)
     return projection.cmscale * (1 + k1 * (1 + k2))
 
 
@@ -431,21 +502,23 @@ def rho(lat, ellipsoid=grs80):
     """
     Return the radius of curvature of the ellipsoid in the meridian plane
     (rho) at a given latitude
+
     :param lat: latitude in decimal degrees
     :param ellipsoid: Ellipsoid Object
     :return: rho at specified latitude
     """
-    return ((ellipsoid.semimaj * (1 - ellipsoid.ecc1sq)) /
-            (1 - ellipsoid.ecc1sq * (sin(radians(lat)) ** 2)) ** 1.5)
+    return (ellipsoid.semimaj * (1 - ellipsoid.ecc1sq)) / (
+        1 - ellipsoid.ecc1sq * (sin(radians(lat)) ** 2)
+    ) ** 1.5
 
 
 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
     """
-    return (ellipsoid.semimaj /
-            sqrt(1 - ellipsoid.ecc1sq * (sin(radians(lat)) ** 2)))
+    return ellipsoid.semimaj / sqrt(1 - ellipsoid.ecc1sq * (sin(radians(lat)) ** 2))
diff --git a/geodepy/gnss.py b/geodepy/gnss.py
index 3d19547..b99e5fa 100644
--- a/geodepy/gnss.py
+++ b/geodepy/gnss.py
@@ -12,10 +12,10 @@
     - remove_velocity_sinex()
     - remove_matrixzeros_sinex()
 
-General functions for reading from SINEX: 
+General functions for reading from SINEX:
 
     - list_sinex_blocks()
-    - read_sinex_comments() 
+    - read_sinex_comments()
     - read_sinex_header_line()
     - read_sinex_custom()
     - read_sinex_estimate()
@@ -43,7 +43,7 @@
     - sinex2dataframe_solution_matrix_estimate()
 
 General functions for writing to SINEX:
-    
+
     - print_sinex_comments()
     - set_creation_time()
     - dataframe2sinex_solution_estimate()
@@ -52,7 +52,7 @@
     - dataframe2matrix_solution_matrix_estimate()
     - dataframe2sinex_solution_matrix_estimate()
     - writeSINEX()
-    
+
 """
 
 from datetime import datetime
@@ -64,20 +64,22 @@
 
 
 def list_sinex_blocks(file):
-    """This script lists the blocks in a SINEX file
+    """
+    This script lists the blocks in a SINEX file
 
     :param str file: the input SINEX file
     """
     blocks = []
     with open(file) as f:
         for line in f.readlines():
-            if line.startswith('+'):
-                col = line.split(' ')
-                block = col[0].replace('+', '')
+            if line.startswith("+"):
+                col = line.split(" ")
+                block = col[0].replace("+", "")
                 blocks.append(block.strip())
     for block in blocks:
         print(block)
 
+
 def print_sinex_comments(file):
     """This script prints comments in a SINEX file.
 
@@ -86,13 +88,14 @@ def print_sinex_comments(file):
     go = False
     with open(file) as f:
         for line in f.readlines():
-            if line.startswith('+FILE/COMMENT'):
+            if line.startswith("+FILE/COMMENT"):
                 go = True
             if go:
                 print(line.strip())
-            if line.startswith('-FILE/COMMENT'):
+            if line.startswith("-FILE/COMMENT"):
                 go = False
 
+
 def read_sinex_comments(file):
     """This function reads comments in a SINEX file.
 
@@ -104,17 +107,21 @@ def read_sinex_comments(file):
     go = False
     with open(file) as f:
         for line in f.readlines():
-            if line.startswith('+FILE/COMMENT'):
+            if line.startswith("+FILE/COMMENT"):
                 go = True
             if go:
                 comments.append(line.strip())
-            if line.startswith('-FILE/COMMENT'):
+            if line.startswith("-FILE/COMMENT"):
                 go = False
 
-        comments.insert(-1,f"* File created by Geodepy.gnss.py at {datetime.now().strftime('%d-%m-%Y, %H:%M')}")
+        comments.insert(
+            -1,
+            f"* File created by Geodepy.gnss.py at {datetime.now().strftime('%d-%m-%Y, %H:%M')}",
+        )
 
     return comments
 
+
 def set_creation_time():
     """This function sets the creation time, in format YY:DDD:SSSSS, for use
     in the SINEX header line
@@ -126,15 +133,17 @@ def set_creation_time():
     time_tup = now.timetuple()
     year = str(time_tup.tm_year)[2:]
     doy = time_tup.tm_yday
-    doy = '{:03d}'.format(doy)
-    seconds = (now - now.replace(hour=0, minute=0, second=0, microsecond=0))\
-        .total_seconds()
-    #seconds = '{:.0f}'.format(seconds)
-    seconds = '{:05.0f}'.format(seconds)
-    creation_time = year + ':' + doy + ':' + seconds
+    doy = "{:03d}".format(doy)
+    seconds = (
+        now - now.replace(hour=0, minute=0, second=0, microsecond=0)
+    ).total_seconds()
+    # seconds = '{:.0f}'.format(seconds)
+    seconds = "{:05.0f}".format(seconds)
+    creation_time = year + ":" + doy + ":" + seconds
 
     return creation_time
 
+
 def read_sinex_header_line(file):
     """This function reads the header line of a SINEX file into a string
 
@@ -147,13 +156,14 @@ def read_sinex_header_line(file):
 
     return header_line
 
+
 def read_sinex_custom(fp, start_line, end_line):
-    """Read custom line range from SINEX. Useful for 
-    SINEX with irregular formatting or block that has 
+    """Read custom line range from SINEX. Useful for
+    SINEX with irregular formatting or block that has
     not been accounted for.
 
     :param str fp: Path to SINEX file.
-    :param int start_line:   Beginning line number. 
+    :param int start_line:   Beginning line number.
     :param int end_line:     Finishing line number.
     :return list custom:  List of string(s).
     """
@@ -165,31 +175,31 @@ def read_sinex_custom(fp, start_line, end_line):
     custom = []
 
     with open(fp) as f:
-        for line in f.readlines()[i-1:j]:
-             custom.append(line.strip())
+        for line in f.readlines()[i - 1 : j]:
+            custom.append(line.strip())
 
     # Return
     return custom
 
+
 def read_sinex_estimate(file):
     """This function reads in the SOLUTION/ESTIMATE block of a SINEX file. It
     returns estimate, a list of tuples:
 
-    estimate = [(code, soln, refEpoch, staX, staY, staZ, staX_sd, staY_sd,
-                 staZ_sd[, velX, velY, velZ, velX_sd, velY_sd, velZ_sd])...]
+    estimate = [(code, soln, refEpoch, staX, staY, staZ, staX_sd, staY_sd, staZ_sd[, velX, velY, velZ, velX_sd, velY_sd, velZ_sd])...]
 
     where:
         * code is the stations's 4-character ID
         * soln is the segment of the stations's time series
         * refEpoch is the epoch of the solution in the form YY:DOY:SSSSS (YY
-            is the two digit year, DOY is day of year, and SSSSS is the time of
-            day in seconds
+          is the two digit year, DOY is day of year, and SSSSS is the time of
+          day in seconds
         * sta[XYZ] is the station coordinates in the Cartesian reference frame
         * sta[XYZ]_sd is the standard deviation of the station coordinates in
-            the Cartesian reference frame
+          the Cartesian reference frame
         * vel[XYZ] is the station velocity in the Cartesian reference frame
         * vel[XYZ]_sd is the standard deviation of the station velocity in the
-            Cartesian reference frame
+          Cartesian reference frame
 
     Velocities are not included in all SINEX files and so are only returned if
     present.
@@ -203,77 +213,90 @@ def read_sinex_estimate(file):
     estimate = []
     velocities = False
     go = False
-    code = ''
-    soln = ''
-    epoch = ''
-    stax = ''
-    stay = ''
-    staz = ''
-    stax_sd = ''
-    stay_sd = ''
-    staz_sd = ''
-    velx = ''
-    vely = ''
-    velz = ''
-    velx_sd = ''
-    vely_sd = ''
-    velz_sd = ''
+    code = ""
+    soln = ""
+    epoch = ""
+    stax = ""
+    stay = ""
+    staz = ""
+    stax_sd = ""
+    stay_sd = ""
+    staz_sd = ""
+    velx = ""
+    vely = ""
+    velz = ""
+    velx_sd = ""
+    vely_sd = ""
+    velz_sd = ""
 
     # Read the SOLUTION/ESTIMATE block into a list and determine if there is
     # any velocity information
     with open(file) as f:
         for line in f:
-            if line[:18] == '-SOLUTION/ESTIMATE':
+            if line[:18] == "-SOLUTION/ESTIMATE":
                 break
-            if go and line[:11] == '*INDEX TYPE':
+            if go and line[:11] == "*INDEX TYPE":
                 pass
             elif go:
-                if line[7:10] == 'VEL':
+                if line[7:10] == "VEL":
                     velocities = True
                 lines.append(line)
-            if line[:18] == '+SOLUTION/ESTIMATE':
+            if line[:18] == "+SOLUTION/ESTIMATE":
                 go = True
 
     for line in lines:
         typ = line[7:11]
-        if typ == 'STAX':
+        if typ == "STAX":
             code = line[14:18]
             soln = line[23:26].lstrip()
             epoch = line[27:39]
             stax = float(line[47:68])
             stax_sd = float(line[69:80])
-        elif typ == 'STAY':
+        elif typ == "STAY":
             stay = float(line[47:68])
             stay_sd = float(line[69:80])
-        elif typ == 'STAZ':
+        elif typ == "STAZ":
             staz = float(line[47:68])
             staz_sd = float(line[69:80])
             if not velocities:
-                info = (code, soln, epoch, stax, stay, staz, stax_sd, stay_sd,
-                        staz_sd)
+                info = (code, soln, epoch, stax, stay, staz, stax_sd, stay_sd, staz_sd)
                 estimate.append(info)
-        elif typ == 'VELX':
+        elif typ == "VELX":
             velx = float(line[47:68])
             velx_sd = float(line[69:80])
-        elif typ == 'VELY':
+        elif typ == "VELY":
             vely = float(line[47:68])
             vely_sd = float(line[69:80])
-        elif typ == 'VELZ':
+        elif typ == "VELZ":
             velz = float(line[47:68])
             velz_sd = float(line[69:80])
-            info = (code, soln, epoch, stax, stay, staz, stax_sd, stay_sd,
-                    staz_sd, velx, vely, velz, velx_sd, vely_sd, velz_sd)
+            info = (
+                code,
+                soln,
+                epoch,
+                stax,
+                stay,
+                staz,
+                stax_sd,
+                stay_sd,
+                staz_sd,
+                velx,
+                vely,
+                velz,
+                velx_sd,
+                vely_sd,
+                velz_sd,
+            )
             estimate.append(info)
 
     return estimate
 
+
 def read_sinex_matrix(file):
     """This function reads in the SOLUTION/MATRIX_ESTIMATE block of a SINEX
     file. It returns matrix, a list of tuples:
 
-    matrix = [(code, soln, var_x, covar_xy, covar_xz, var_y, covar_yz,
-            var_z[, var_v_x, covar_v_xy, covar_v_xz, var_v_y, covar_v_yz,
-            var_v_z])...]
+    matrix = [(code, soln, var_x, covar_xy, covar_xz, var_y, covar_yz, var_z[, var_v_x, covar_v_xy, covar_v_xz, var_v_y, covar_v_yz, var_v_z])...]
 
     where:
         * code is the stations's 4-character ID
@@ -294,15 +317,15 @@ def read_sinex_matrix(file):
     Velocities are not included in all SINEX files and so their VCV information
     is only returned if they are present.
 
-    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.
-
     :param file: the input SINEX file
     :return: matrix
     """
-
+    '''
+    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 = []
@@ -321,14 +344,14 @@ def read_sinex_matrix(file):
     go = False
     with open(file) as f:
         for line in f:
-            if line[:25] == '-SOLUTION/MATRIX_ESTIMATE':
+            if line[:25] == "-SOLUTION/MATRIX_ESTIMATE":
                 break
-            if go and line[:12] == '*PARA1 PARA2':
+            if go and line[:12] == "*PARA1 PARA2":
                 pass
             elif go:
                 lines.append(line)
-            if line[:25] == '+SOLUTION/MATRIX_ESTIMATE':
-                if line[26] == 'L':
+            if line[:25] == "+SOLUTION/MATRIX_ESTIMATE":
+                if line[26] == "L":
                     lower_triangular = True
                 go = True
 
@@ -346,54 +369,73 @@ def read_sinex_matrix(file):
     if velocities:
         if lower_triangular:
             for i in range(len(code)):
-                info = (code[i], soln[i], element[6 * i][6 * i],
-                        element[6 * i + 1][6 * i],
-                        element[6 * i + 1][6 * i + 1],
-                        element[6 * i + 2][6 * i],
-                        element[6 * i + 2][6 * i + 1],
-                        element[6 * i + 2][6 * i + 2],
-                        element[6 * i + 3][6 * i + 3],
-                        element[6 * i + 4][6 * i + 3],
-                        element[6 * i + 4][6 * i + 4],
-                        element[6 * i + 5][6 * i + 3],
-                        element[6 * i + 5][6 * i + 4],
-                        element[6 * i + 5][6 * i + 5])
+                info = (
+                    code[i],
+                    soln[i],
+                    element[6 * i][6 * i],
+                    element[6 * i + 1][6 * i],
+                    element[6 * i + 1][6 * i + 1],
+                    element[6 * i + 2][6 * i],
+                    element[6 * i + 2][6 * i + 1],
+                    element[6 * i + 2][6 * i + 2],
+                    element[6 * i + 3][6 * i + 3],
+                    element[6 * i + 4][6 * i + 3],
+                    element[6 * i + 4][6 * i + 4],
+                    element[6 * i + 5][6 * i + 3],
+                    element[6 * i + 5][6 * i + 4],
+                    element[6 * i + 5][6 * i + 5],
+                )
                 matrix.append(info)
         else:
             for i in range(len(code)):
-                info = (code[i], soln[i], element[6 * i][6 * i],
-                        element[6 * i][6 * i + 1], element[6 * i][6 * i + 2],
-                        element[6 * i + 1][6 * i + 1],
-                        element[6 * i + 1][6 * i + 2],
-                        element[6 * i + 2][6 * i + 2],
-                        element[6 * i + 3][6 * i + 3],
-                        element[6 * i + 3][6 * i + 4],
-                        element[6 * i + 3][6 * i + 5],
-                        element[6 * i + 4][6 * i + 4],
-                        element[6 * i + 4][6 * i + 5],
-                        element[6 * i + 5][6 * i + 5])
+                info = (
+                    code[i],
+                    soln[i],
+                    element[6 * i][6 * i],
+                    element[6 * i][6 * i + 1],
+                    element[6 * i][6 * i + 2],
+                    element[6 * i + 1][6 * i + 1],
+                    element[6 * i + 1][6 * i + 2],
+                    element[6 * i + 2][6 * i + 2],
+                    element[6 * i + 3][6 * i + 3],
+                    element[6 * i + 3][6 * i + 4],
+                    element[6 * i + 3][6 * i + 5],
+                    element[6 * i + 4][6 * i + 4],
+                    element[6 * i + 4][6 * i + 5],
+                    element[6 * i + 5][6 * i + 5],
+                )
                 matrix.append(info)
     else:
         if lower_triangular:
             for i in range(len(code)):
-                info = (code[i], soln[i], element[3 * i][3 * i],
-                        element[3 * i + 1][3 * i],
-                        element[3 * i + 1][3 * i + 1],
-                        element[3 * i + 2][3 * i],
-                        element[3 * i + 2][3 * i + 1],
-                        element[3 * i + 2][3 * i + 2])
+                info = (
+                    code[i],
+                    soln[i],
+                    element[3 * i][3 * i],
+                    element[3 * i + 1][3 * i],
+                    element[3 * i + 1][3 * i + 1],
+                    element[3 * i + 2][3 * i],
+                    element[3 * i + 2][3 * i + 1],
+                    element[3 * i + 2][3 * i + 2],
+                )
                 matrix.append(info)
         else:
             for i in range(len(code)):
-                info = (code[i], soln[i], element[3 * i][3 * i],
-                        element[3 * i][3 * i + 1], element[3 * i][3 * i + 2],
-                        element[3 * i + 1][3 * i + 1],
-                        element[3 * i + 1][3 * i + 2],
-                        element[3 * i + 2][3 * i + 2])
+                info = (
+                    code[i],
+                    soln[i],
+                    element[3 * i][3 * i],
+                    element[3 * i][3 * i + 1],
+                    element[3 * i][3 * i + 2],
+                    element[3 * i + 1][3 * i + 1],
+                    element[3 * i + 1][3 * i + 2],
+                    element[3 * i + 2][3 * i + 2],
+                )
                 matrix.append(info)
 
     return matrix
 
+
 def read_sinex_sites(file):
     """This function reads in the SITE/ID block of a SINEX file. It returns
     sites, a list of tuples:
@@ -419,13 +461,13 @@ def read_sinex_sites(file):
     go = False
     with open(file) as f:
         for line in f:
-            if line[:8] == '-SITE/ID':
+            if line[:8] == "-SITE/ID":
                 break
-            if go and line[:8] == '*CODE PT':
+            if go and line[:8] == "*CODE PT":
                 pass
             elif go:
                 lines.append(line)
-            if line[:8] == '+SITE/ID':
+            if line[:8] == "+SITE/ID":
                 go = True
     sites = []
     for line in lines:
@@ -442,6 +484,7 @@ def read_sinex_sites(file):
 
     return sites
 
+
 def read_disconts(file):
     """This function reads in the SOLUTION/DISCONTINUITY block of a
     SINEX file. It returns disconts , a list of tuples:
@@ -456,7 +499,7 @@ def read_disconts(file):
         * start is the start time for the point code in YY:DOY:SECOD
         * end is the end time for the point code in YY:DOY:SECOD
         * type is the type of discontinuity; P for position or V for
-            velocity
+          velocity
 
     I could not find the format description for this block.
 
@@ -469,11 +512,11 @@ def read_disconts(file):
     go = False
     with open(file) as f:
         for line in f:
-            if line[:23] == '-SOLUTION/DISCONTINUITY':
+            if line[:23] == "-SOLUTION/DISCONTINUITY":
                 break
             elif go:
                 lines.append(line)
-            if line[:23] == '+SOLUTION/DISCONTINUITY':
+            if line[:23] == "+SOLUTION/DISCONTINUITY":
                 go = True
     disconts = []
     for line in lines:
@@ -489,6 +532,7 @@ def read_disconts(file):
 
     return disconts
 
+
 def read_solution_epochs(file):
     """This function reads in the SOLUTION/EPOCHS block of a SINEX file.
     It returns epochs, a list of tuples:
@@ -513,13 +557,13 @@ def read_solution_epochs(file):
     go = False
     with open(file) as f:
         for line in f:
-            if line[:16] == '-SOLUTION/EPOCHS':
+            if line[:16] == "-SOLUTION/EPOCHS":
                 break
-            if go and line[:8] == '*Code PT':
+            if go and line[:8] == "*Code PT":
                 pass
             elif go:
                 lines.append(line)
-            if line[:16] == '+SOLUTION/EPOCHS':
+            if line[:16] == "+SOLUTION/EPOCHS":
                 go = True
     epochs = []
     # Parse each line, create a tuple and add it to the list
@@ -536,341 +580,371 @@ def read_solution_epochs(file):
 
     return epochs
 
+
 def read_sinex_header_block(sinex):
-    """This function reads in the header block information 
+    """
+    This function reads in the header block information
     of a SINEX file (All lines before the SITE/ID block).
 
-        :param str sinex: input SINEX file
-        return: block
-        """
+    :param str sinex: input SINEX file
+    :return: block
+    """
 
     block = []
-    with open(sinex, 'r') as f:
+    with open(sinex, "r") as f:
         next(f)
         line = f.readline()
         while line:
             block.append(line.rstrip())
             line = f.readline()
-            if line.startswith('+SITE/ID'):
+            if line.startswith("+SITE/ID"):
                 break
 
     return block
 
+
 def read_sinex_file_reference_block(sinex):
-    """This function reads in the +FILE/REFERENCE block 
+    """
+    This function reads in the +FILE/REFERENCE block
     of a SINEX file.
 
-        :param str sinex: input SINEX file
-        return: block
-        """
+    :param str sinex: input SINEX file
+    :return: block
+    """
 
     block = []
     go = False
-    with open(sinex, 'r') as f:
+    with open(sinex, "r") as f:
         line = f.readline()
         while line:
-            if line.startswith('+FILE/REFERENCE'):
+            if line.startswith("+FILE/REFERENCE"):
                 go = True
             if go:
                 block.append(line.rstrip())
-            if line.startswith('-FILE/REFERENCE'):
+            if line.startswith("-FILE/REFERENCE"):
                 break
             line = f.readline()
-            
+
     return block
 
+
 def read_sinex_input_acknowledgments_block(sinex):
-    """This function reads in the +INPUT/ACKNOWLEDGMENTS 
+    """
+    This function reads in the +INPUT/ACKNOWLEDGMENTS
     block of a SINEX file.
 
-        :param str sinex: input SINEX file
-        return: block
-        """
+    :param str sinex: input SINEX file
+    :return: block
+    """
 
     block = []
     go = False
-    with open(sinex, 'r') as f:
+    with open(sinex, "r") as f:
         line = f.readline()
         while line:
-            if line.startswith('+INPUT/ACKNOWLEDGMENTS'):
+            if line.startswith("+INPUT/ACKNOWLEDGMENTS"):
                 go = True
             if go:
                 block.append(line.rstrip())
-            if line.startswith('-INPUT/ACKNOWLEDGMENTS'):
+            if line.startswith("-INPUT/ACKNOWLEDGMENTS"):
                 break
             line = f.readline()
 
     return block
 
+
 def read_sinex_solution_statistics_block(sinex):
-    """This function reads in the +SOLUTION/STATISTICS
+    """
+    This function reads in the +SOLUTION/STATISTICS
     block of a SINEX file.
 
-        :param str sinex: input SINEX file
-        return: block
-        """
+    :param str sinex: input SINEX file
+    :return: block
+    """
 
     block = []
     go = False
-    with open(sinex, 'r') as f:
+    with open(sinex, "r") as f:
         line = f.readline()
         while line:
-            if line.startswith('+SOLUTION/STATISTICS'):
+            if line.startswith("+SOLUTION/STATISTICS"):
                 go = True
             if go:
                 block.append(line.rstrip())
-            if line.startswith('-SOLUTION/STATISTICS'):
+            if line.startswith("-SOLUTION/STATISTICS"):
                 break
             line = f.readline()
 
     return block
 
+
 def read_sinex_site_receiver_block(sinex):
-    """This function reads in the +SITE/RECEIVER
+    """
+    This function reads in the +SITE/RECEIVER
     block of a SINEX file.
 
-        :param str sinex: input SINEX file
-        return: block
-        """
+    :param str sinex: input SINEX file
+    :return: block
+    """
 
     block = []
     go = False
-    with open(sinex, 'r') as f:
+    with open(sinex, "r") as f:
         line = f.readline()
         while line:
-            if line.startswith('+SITE/RECEIVER'):
+            if line.startswith("+SITE/RECEIVER"):
                 go = True
             if go:
                 block.append(line.rstrip())
-            if line.startswith('-SITE/RECEIVER'):
+            if line.startswith("-SITE/RECEIVER"):
                 break
             line = f.readline()
-            
+
     return block
 
+
 def read_sinex_site_antenna_block(sinex):
-    """This function reads in the +SITE/ANTENNA
+    """
+    This function reads in the +SITE/ANTENNA
     block of a SINEX file.
 
-        :param str sinex: input SINEX file
-        return: block
-        """
+    :param str sinex: input SINEX file
+    :return: block
+    """
 
     block = []
     go = False
-    with open(sinex, 'r') as f:
+    with open(sinex, "r") as f:
         line = f.readline()
         while line:
-            if line.startswith('+SITE/ANTENNA'):
+            if line.startswith("+SITE/ANTENNA"):
                 go = True
             if go:
                 block.append(line.rstrip())
-            if line.startswith('-SITE/ANTENNA'):
+            if line.startswith("-SITE/ANTENNA"):
                 break
             line = f.readline()
-            
+
     return block
 
+
 def read_sinex_site_gps_phase_center_block(sinex):
-    """This function reads in the +SITE/GPS_PHASE_CENTER
+    """
+    This function reads in the +SITE/GPS_PHASE_CENTER
     block of a SINEX file.
 
-        :param str sinex: input SINEX file
-        return: block
-        """
+    :param str sinex: input SINEX file
+    :return: block
+    """
 
     block = []
     go = False
-    with open(sinex, 'r') as f:
+    with open(sinex, "r") as f:
         line = f.readline()
         while line:
-            if line.startswith('+SITE/GPS_PHASE_CENTER'):
+            if line.startswith("+SITE/GPS_PHASE_CENTER"):
                 go = True
             if go:
                 block.append(line.rstrip())
-            if line.startswith('-SITE/GPS_PHASE_CENTER'):
+            if line.startswith("-SITE/GPS_PHASE_CENTER"):
                 break
             line = f.readline()
-            
+
     return block
 
+
 def read_sinex_site_eccentricity_block(sinex):
-    """This function reads in the +SITE/ECCENTRICITY
+    """
+    This function reads in the +SITE/ECCENTRICITY
     block of a SINEX file.
 
-        :param str sinex: input SINEX file
-        return: block
-        """
+    :param str sinex: input SINEX file
+    :return: block
+    """
 
     block = []
     go = False
-    with open(sinex, 'r') as f:
+    with open(sinex, "r") as f:
         line = f.readline()
         while line:
-            if line.startswith('+SITE/ECCENTRICITY'):
+            if line.startswith("+SITE/ECCENTRICITY"):
                 go = True
             if go:
                 block.append(line.rstrip())
-            if line.startswith('-SITE/ECCENTRICITY'):
+            if line.startswith("-SITE/ECCENTRICITY"):
                 break
             line = f.readline()
-            
+
     return block
 
+
 def read_sinex_site_id_block(sinex):
-    """This function reads in the SITE/ID block of a SINEX file
+    """
+    This function reads in the SITE/ID block of a SINEX file
     into list of strings.
 
     :param str sinex: input SINEX file
-    return: block
+    :return: block
     """
 
     block = []
     go = False
-    with open(sinex, 'r') as f:
+    with open(sinex, "r") as f:
         line = f.readline()
         while line:
-            if line.startswith('+SITE/ID'):
+            if line.startswith("+SITE/ID"):
                 go = True
             if go:
                 block.append(line.rstrip())
-            if line.startswith('-SITE/ID'):
+            if line.startswith("-SITE/ID"):
                 break
             line = f.readline()
 
     return block
 
+
 def read_sinex_solution_epochs_block(sinex):
-    """This function reads in the SOLUTION/EPOCHS block of a SINEX file
+    """
+    This function reads in the SOLUTION/EPOCHS block of a SINEX file
     into list of strings.
 
     :param str sinex: input SINEX file
-    return: block
+    :return: block
     """
 
     block = []
     go = False
-    with open(sinex, 'r') as f:
+    with open(sinex, "r") as f:
         line = f.readline()
         while line:
-            if line.startswith('+SOLUTION/EPOCHS'):
+            if line.startswith("+SOLUTION/EPOCHS"):
                 go = True
             if go:
                 block.append(line.rstrip())
-            if line.startswith('-SOLUTION/EPOCHS'):
+            if line.startswith("-SOLUTION/EPOCHS"):
                 break
             line = f.readline()
     return block
 
+
 def read_sinex_solution_estimate_block(sinex):
-    """This function reads in the SOLUTION/ESTIMATE block of a SINEX
+    """
+    This function reads in the SOLUTION/ESTIMATE block of a SINEX
     file into list of strings.
 
     :param str sinex: input SINEX file
-    return: block
+    :return: block
     """
 
     block = []
     go = False
-    with open(sinex, 'r') as f:
+    with open(sinex, "r") as f:
         line = f.readline()
         while line:
-            if line.startswith('+SOLUTION/ESTIMATE'):
+            if line.startswith("+SOLUTION/ESTIMATE"):
                 go = True
             if go:
                 block.append(line.rstrip())
-            if line.startswith('-SOLUTION/ESTIMATE'):
+            if line.startswith("-SOLUTION/ESTIMATE"):
                 break
             line = f.readline()
     return block
 
+
 def read_sinex_solution_apriori_block(sinex):
-    """This function reads in the +SOLUTION/APRIORI
+    """
+    This function reads in the +SOLUTION/APRIORI
     block of a SINEX file.
 
-        :param str sinex: input SINEX file
-        return: block
-        """
+    :param str sinex: input SINEX file
+    :return: block
+    """
 
     block = []
     go = False
-    with open(sinex, 'r') as f:
+    with open(sinex, "r") as f:
         line = f.readline()
         while line:
-            if line.startswith('+SOLUTION/APRIORI'):
+            if line.startswith("+SOLUTION/APRIORI"):
                 go = True
             if go:
                 block.append(line.rstrip())
-            if line.startswith('-SOLUTION/APRIORI'):
+            if line.startswith("-SOLUTION/APRIORI"):
                 break
             line = f.readline()
-            
+
     return block
 
+
 def read_sinex_solution_matrix_estimate_block(sinex):
-    """This function reads in the SOLUTION/MATRIX_ESTIMATE block of a SINEX
+    """
+    This function reads in the SOLUTION/MATRIX_ESTIMATE block of a SINEX
     file into list of strings.
 
     :param str sinex: input SINEX file
-    return: block
+    :return: block
     """
 
     block = []
     go = False
-    with open(sinex, 'r') as f:
+    with open(sinex, "r") as f:
         line = f.readline()
         while line:
-            if line.startswith('+SOLUTION/MATRIX_ESTIMATE'):
+            if line.startswith("+SOLUTION/MATRIX_ESTIMATE"):
                 go = True
             if go:
                 block.append(line.rstrip())
-            if line.startswith('-SOLUTION/MATRIX_ESTIMATE'):
+            if line.startswith("-SOLUTION/MATRIX_ESTIMATE"):
                 break
             line = f.readline()
 
     return block
 
+
 def read_sinex_solution_matrix_apriori_block(sinex):
-    """This function reads in the SOLUTION/MATRIX_APRIORI block 
+    """
+    This function reads in the SOLUTION/MATRIX_APRIORI block
     of a SINEX file into list of strings.
 
     :param str sinex: input SINEX file
-    return: block
+    :return: block
     """
 
     block = []
     go = False
-    with open(sinex, 'r') as f:
+    with open(sinex, "r") as f:
         line = f.readline()
         while line:
-            if line.startswith('+SOLUTION/MATRIX_APRIORI'):
+            if line.startswith("+SOLUTION/MATRIX_APRIORI"):
                 go = True
             if go:
                 block.append(line.rstrip())
-            if line.startswith('-SOLUTION/MATRIX_APRIORI'):
+            if line.startswith("-SOLUTION/MATRIX_APRIORI"):
                 break
             line = f.readline()
-            
+
     return block
 
+
 def sinex2dataframe_solution_estimate(fp):
-    """This function reads in a SINEX file and returns 
-    a dataframe of SOLUTION/ESTIMATE block only. 
+    """
+    This function reads in a SINEX file and returns
+    a dataframe of SOLUTION/ESTIMATE block only.
 
     :param str sinex: path of input SINEX file
-    return: df
+    :return: df
     """
-    
+
     # Get lines
     lines = read_sinex_solution_estimate_block(fp)
 
     # Remove non-data lines
     for l in lines[:]:
-        if l.startswith('*'):
+        if l.startswith("*"):
             lines.remove(l)
-        if l.startswith('+'):
+        if l.startswith("+"):
             lines.remove(l)
-        if l.startswith('-'):
+        if l.startswith("-"):
             lines.remove(l)
 
     # Split by column
@@ -890,40 +964,42 @@ def sinex2dataframe_solution_estimate(fp):
 
     # Organise into DataFrame
     dict_temp = {
-                "row":row,
-                "par":par,
-                "code":code,
-                "pt":pt,
-                "soln":soln,
-                "refEpoch":refEpoch,
-                "unit":unit,
-                "s":s,
-                "est":est,
-                "sigma":sigma,
+        "row": row,
+        "par": par,
+        "code": code,
+        "pt": pt,
+        "soln": soln,
+        "refEpoch": refEpoch,
+        "unit": unit,
+        "s": s,
+        "est": est,
+        "sigma": sigma,
     }
     df = pd.DataFrame(dict_temp)
 
     # Return
     return df
 
+
 def sinex2dataframe_solution_apriori(fp):
-    """This function reads in a SINEX file and returns 
-    a dataframe of SOLUTION/APRIORI block only. 
+    """
+    This function reads in a SINEX file and returns
+    a dataframe of SOLUTION/APRIORI block only.
 
     :param str sinex: path of input SINEX file
-    return: df
+    :return: df
     """
-    
+
     # Get lines
     lines = read_sinex_solution_apriori_block(fp)
 
     # Remove non-data lines
     for l in lines[:]:
-        if l.startswith('*'):
+        if l.startswith("*"):
             lines.remove(l)
-        if l.startswith('+'):
+        if l.startswith("+"):
             lines.remove(l)
-        if l.startswith('-'):
+        if l.startswith("-"):
             lines.remove(l)
 
     # Split by column
@@ -943,28 +1019,30 @@ def sinex2dataframe_solution_apriori(fp):
 
     # Organise into DataFrame
     dict_temp = {
-                "row":row,
-                "par":par,
-                "code":code,
-                "pt":pt,
-                "soln":soln,
-                "refEpoch":refEpoch,
-                "unit":unit,
-                "s":s,
-                "est":est,
-                "sigma":sigma,
+        "row": row,
+        "par": par,
+        "code": code,
+        "pt": pt,
+        "soln": soln,
+        "refEpoch": refEpoch,
+        "unit": unit,
+        "s": s,
+        "est": est,
+        "sigma": sigma,
     }
     df = pd.DataFrame(dict_temp)
 
     # Return
     return df
 
+
 def sinex2dataframe_solution_matrix_estimate(fp):
-    """This function reads in a SINEX file and returns 
-    a dataframe of SOLUTION/MATRIX_ESTIMATE block only. 
+    """
+    This function reads in a SINEX file and returns
+    a dataframe of SOLUTION/MATRIX_ESTIMATE block only.
 
     :param str sinex: path of input SINEX file
-    return: df
+    :return: df
     """
 
     # Get lines
@@ -972,11 +1050,11 @@ def sinex2dataframe_solution_matrix_estimate(fp):
 
     # Remove non-data lines
     for l in lines[:]:
-        if l.startswith('*'):
+        if l.startswith("*"):
             lines.remove(l)
-        if l.startswith('+'):
+        if l.startswith("+"):
             lines.remove(l)
-        if l.startswith('-'):
+        if l.startswith("-"):
             lines.remove(l)
 
     # Split by column
@@ -984,14 +1062,14 @@ def sinex2dataframe_solution_matrix_estimate(fp):
 
     # Pad out lines with NaN
     for i in range(len(lines)):
-        if len(lines[i])==5:
+        if len(lines[i]) == 5:
             continue
         if len(lines[i]) == 4:
             lines[i].append(np.nan)
         if len(lines[i]) == 3:
             lines[i].append(np.nan)
             lines[i].append(np.nan)
-        
+
     # Isolate into vectors
     row = np.int_(list(zip(*lines))[0])
     col = np.int_(list(zip(*lines))[1])
@@ -1001,84 +1079,118 @@ def sinex2dataframe_solution_matrix_estimate(fp):
 
     # Organise into DataFrame
     dict_temp = {
-                "row":row,
-                "col":col,
-                "q1":q1,
-                "q2":q2,
-                "q3":q3,
+        "row": row,
+        "col": col,
+        "q1": q1,
+        "q2": q2,
+        "q3": q3,
     }
     df = pd.DataFrame(dict_temp)
 
     # Return
     return df
 
+
 def dataframe2sinex_solution_estimate(df):
-    """This function reads in a dataframe of the 
+    """
+    This function reads in a dataframe of the
     SOLUTIONS/ESTIMATE block from a SINEX, then
-    converts each row to a string in a list 
+    converts each row to a string in a list
     ready for writing to SINEX.
 
     :param dataframe df: dataframe of SOLUTION/ESTIMATE block
-    return: list of strings
+    :return: list of strings
     """
 
-    lines =lines = ["+SOLUTION/ESTIMATE"]
-    lines.append("*INDEX TYPE__ CODE PT SOLN _REF_EPOCH__ UNIT S __ESTIMATED VALUE____ _STD_DEV___")
+    lines = lines = ["+SOLUTION/ESTIMATE"]
+    lines.append(
+        "*INDEX TYPE__ CODE PT SOLN _REF_EPOCH__ UNIT S __ESTIMATED VALUE____ _STD_DEV___"
+    )
 
     for i in range(len(df.code)):
-        l = " %5i %s   %s  %s    %s %s %-3s  %s %21.14e %.5e" % (df.row.iloc[i], df.par.iloc[i], df.code.iloc[i], df.pt.iloc[i], df.soln.iloc[i], df.refEpoch.iloc[i], df.unit.iloc[i], df.s.iloc[i], df.est.iloc[i], df.sigma.iloc[i])
+        l = " %5i %s   %s  %s    %s %s %-3s  %s %21.14e %.5e" % (
+            df.row.iloc[i],
+            df.par.iloc[i],
+            df.code.iloc[i],
+            df.pt.iloc[i],
+            df.soln.iloc[i],
+            df.refEpoch.iloc[i],
+            df.unit.iloc[i],
+            df.s.iloc[i],
+            df.est.iloc[i],
+            df.sigma.iloc[i],
+        )
         lines.append(l)
-    
+
     lines.append("-SOLUTION/ESTIMATE")
 
     # Return
     return lines
 
+
 def dataframe2sinex_solution_apriori(df):
-    """This function reads in a dataframe of the 
+    """
+    This function reads in a dataframe of the
     SOLUTION/APRIORI block from a SINEX, then
-    converts each row to a string in a list 
+    converts each row to a string in a list
     ready for writing to SINEX.
 
     :param dataframe df: dataframe of SOLUTION/APRIORI block
-    return: list of strings
+    :return: list of strings
     """
 
-    lines =lines = ["+SOLUTION/APRIORI"]
-    lines.append("*INDEX TYPE__ CODE PT SOLN _REF_EPOCH__ UNIT S __ESTIMATED VALUE____ _STD_DEV___")
+    lines = lines = ["+SOLUTION/APRIORI"]
+    lines.append(
+        "*INDEX TYPE__ CODE PT SOLN _REF_EPOCH__ UNIT S __ESTIMATED VALUE____ _STD_DEV___"
+    )
 
     for i in range(len(df.code)):
-        l = " %5i %s   %s  %s    %s %s %-3s  %s %21.14e %.5e" % (df.row.iloc[i], df.par.iloc[i], df.code.iloc[i], df.pt.iloc[i], df.soln.iloc[i], df.refEpoch.iloc[i], df.unit.iloc[i], df.s.iloc[i], df.est.iloc[i], df.sigma.iloc[i])
+        l = " %5i %s   %s  %s    %s %s %-3s  %s %21.14e %.5e" % (
+            df.row.iloc[i],
+            df.par.iloc[i],
+            df.code.iloc[i],
+            df.pt.iloc[i],
+            df.soln.iloc[i],
+            df.refEpoch.iloc[i],
+            df.unit.iloc[i],
+            df.s.iloc[i],
+            df.est.iloc[i],
+            df.sigma.iloc[i],
+        )
         lines.append(l)
-    
+
     lines.append("-SOLUTION/APRIORI")
 
     # Return
     return lines
 
+
 def dataframe2matrix_snx_vcv(df, numPar=3):
-    """This function converts a dataframe created from a
-    SINEX VCV based from read_sinex_matrix(), and converts 
+    """
+    This function converts a dataframe created from a
+    SINEX VCV based from read_sinex_matrix(), and converts
     it to a full VCV without covariances between sites.
 
-    i.e.  xx xy xz          0  0  0
-          xy yy yz .  .  .  0  0  0
-          xz yz zz          0  0  0
-             .     .           .
-             .        .        .
-             .           .     .
-          0  0  0           xx xy xz 
-          0  0  0  .  .  .  xy yy yz
-          0  0  0           xz yz zz
+    .. code-block:: text
+
+        i.e.  xx xy xz          0  0  0
+              xy yy yz .  .  .  0  0  0
+              xz yz zz          0  0  0
+                   .     .           .
+                   .        .        .
+                   .           .     .
+              0  0  0           xx xy xz
+              0  0  0  .  .  .  xy yy yz
+              0  0  0           xz yz zz
 
     :param DataFrame: dataframe formed from read_sinex_matrix():
-    return: Numpy matrix of VCV with no covariances between sites. 
+    :return: Numpy matrix of VCV with no covariances between sites.
     """
-    
+
     # Matrix dimensions
     # - To Do: Handle check for velocities (?)
-    par = numPar # (is there a way to automatically determine if velocitie exist?)
-    n = len(df.code)*par
+    par = numPar  # (is there a way to automatically determine if velocitie exist?)
+    n = len(df.code) * par
     Q = np.zeros((n, n))
 
     # Matrix elements and rows of dataframe
@@ -1088,36 +1200,37 @@ def dataframe2matrix_snx_vcv(df, numPar=3):
     while r < len(df.code):
 
         # variances
-        Q[i+0, j+0] = df.xx[r]
-        Q[i+1, j+1] = df.yy[r]
-        Q[i+2, j+2] = df.zz[r]
+        Q[i + 0, j + 0] = df.xx[r]
+        Q[i + 1, j + 1] = df.yy[r]
+        Q[i + 2, j + 2] = df.zz[r]
 
         # covariances
-        Q[i+1, j+0] = df.xy[r]
-        Q[i+0, j+1] = df.xy[r]
-        Q[i+2, j+0] = df.xz[r]
-        Q[i+0, j+2] = df.xz[r]
-        Q[i+2, j+1] = df.yz[r]
-        Q[i+1, j+2] = df.yz[r]
-        
+        Q[i + 1, j + 0] = df.xy[r]
+        Q[i + 0, j + 1] = df.xy[r]
+        Q[i + 2, j + 0] = df.xz[r]
+        Q[i + 0, j + 2] = df.xz[r]
+        Q[i + 2, j + 1] = df.yz[r]
+        Q[i + 1, j + 2] = df.yz[r]
 
         # Counter
-        r = r+1
-        i = i+3
-        j = j+3
+        r = r + 1
+        i = i + 3
+        j = j + 3
 
     # Return
     return Q
-    
+
+
 def dataframe2matrix_solution_matrix_estimate(df, tri="L"):
-    """This function reads in a dataframe of the SINEX 
-    SOLUTION/MATRIX_ESTIMATE block formed from 
-    sinex2dataframe_solution_matrix_estimate(), and then 
-    forms the full VCV matrix from that dataframe. 
+    """
+    This function reads in a dataframe of the SINEX
+    SOLUTION/MATRIX_ESTIMATE block formed from
+    sinex2dataframe_solution_matrix_estimate(), and then
+    forms the full VCV matrix from that dataframe.
 
     :param DataFrame df: dataframe from sinex2dataframe_solution_matrix_estimate().
-    :param String tri: String to indicate "upper" or "lower" triagle matrix. 
-    return: Numpy matrix of full VCV. 
+    :param String tri: String to indicate "upper" or "lower" triagle matrix.
+    :return: Numpy matrix of full VCV.
     """
 
     # Triangularity of matrix
@@ -1130,26 +1243,26 @@ def dataframe2matrix_solution_matrix_estimate(df, tri="L"):
     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
-            
+
             # Fill PARA2+0
-            q1 = df.q1[i]    
+            q1 = df.q1[i]
             Q[row, col] = q1
             Q[col, row] = q1
-            
+
             # Fill PARA2+1
             q2 = df.q2[i]
-            Q[row, col+1] = q2
-            Q[col+1, row] = q2
-            
+            Q[row, col + 1] = q2
+            Q[col + 1, row] = q2
+
             # Fill PARA2+2
             q3 = df.q3[i]
-            Q[row, col+2] = q3
-            Q[col+2, row] = q3
-        
+            Q[row, col + 2] = q3
+            Q[col + 2, row] = q3
+
     if triangle == "U":
 
         for i in range(len(df.row)):
@@ -1158,53 +1271,56 @@ def dataframe2matrix_solution_matrix_estimate(df, tri="L"):
             row = int(df.row[i]) - 1
             col = int(df.col[i]) - 1
 
-            if df.col[i] < n-1:
-            
+            if df.col[i] < n - 1:
+
                 # Fill PARA2+0
-                q1 = df.q1[i]    
+                q1 = df.q1[i]
                 Q[row, col] = q1
                 Q[col, row] = q1
-                
+
                 # Fill PARA2+1
                 q2 = df.q2[i]
-                Q[row, col+1] = q2
-                Q[col+1, row] = q2
-                
+                Q[row, col + 1] = q2
+                Q[col + 1, row] = q2
+
                 # Fill PARA2+2
                 q3 = df.q3[i]
-                Q[row, col+2] = q3
-                Q[col+2, row] = q3
-            
-            if df.col[i] == n-1:
-            
+                Q[row, col + 2] = q3
+                Q[col + 2, row] = q3
+
+            if df.col[i] == n - 1:
+
                 # Fill PARA2+0
-                q1 = df.q1[i]    
+                q1 = df.q1[i]
                 Q[row, col] = q1
                 Q[col, row] = q1
-                
+
                 # Fill PARA2+1
                 q2 = df.q2[i]
-                Q[row, col+1] = q2
-                Q[col+1, row] = q2
+                Q[row, col + 1] = q2
+                Q[col + 1, row] = q2
 
             if df.col[i] == n:
-            
+
                 # Fill PARA2+0
-                q1 = df.q1[i]    
+                q1 = df.q1[i]
                 Q[row, col] = q1
                 Q[col, row] = q1
 
     # Return
     return Q
 
+
 def matrix2dataframe_solution_matrix_estimate(m, tri="L"):
-    """This function reads a VCV in matrix format and writes it
-    to dataframe for SINEX SOLUTION/MATRIX_ESTIMATE format. It 
+    """
+    This function reads a VCV in matrix format and writes it
+    to dataframe for SINEX SOLUTION/MATRIX_ESTIMATE format. It
     is the format produced from sinex2dataframe_solution_matrix_estimate().
 
-    :param numpy.array() m: A numpy array of the VCV matrix. 
-    :param String tri: String to indicate "upper" or "lower" triagle matrix. 
-    return: DataFrame df: A dataframe of SOLUTION/MATRIX_ESTIMATE.
+    :param numpy.array() m: A numpy array of the VCV matrix.
+    :param str tri: String to indicate "upper" or "lower" triagle matrix.
+    :return: A dataframe of SOLUTION/MATRIX_ESTIMATE.
+    :rtype: DataFrame
     """
 
     # Matrix dimensions
@@ -1226,11 +1342,11 @@ def matrix2dataframe_solution_matrix_estimate(m, tri="L"):
         j = 0
         while i < n:
             while j <= i:
-                row.append(i+1)
-                col.append(j+1)
+                row.append(i + 1)
+                col.append(j + 1)
                 q1.append(Q[i, j])
-                q2.append(Q[i, j+1])
-                q3.append(Q[i, j+2])
+                q2.append(Q[i, j + 1])
+                q3.append(Q[i, j + 2])
                 j += 3
             j = 0
             i += 1
@@ -1249,60 +1365,64 @@ def matrix2dataframe_solution_matrix_estimate(m, tri="L"):
         j = 0
         while i < n:
             while j < n:
-                if j < n-2:
-                    row.append(i+1)
-                    col.append(j+1)
+                if j < n - 2:
+                    row.append(i + 1)
+                    col.append(j + 1)
                     q1.append(Q[i, j])
-                    q2.append(Q[i, j+1])
-                    q3.append(Q[i, j+2])
+                    q2.append(Q[i, j + 1])
+                    q3.append(Q[i, j + 2])
                     j += 3
 
-                if j == n-2: 
-                    row.append(i+1)
-                    col.append(j+1)
+                if j == n - 2:
+                    row.append(i + 1)
+                    col.append(j + 1)
                     q1.append(Q[i, j])
-                    q2.append(Q[i, j+1])
+                    q2.append(Q[i, j + 1])
                     q3.append(np.nan)
                     j += 3
 
-                if j == n-1: 
-                    row.append(i+1)
-                    col.append(j+1)
+                if j == n - 1:
+                    row.append(i + 1)
+                    col.append(j + 1)
                     q1.append(Q[i, j])
                     q2.append(np.nan)
                     q3.append(np.nan)
                     j += 3
-            
+
             i += 1
             j = i
 
     dict_temp = {
-                "row":row,
-                "col":col,
-                "q1":q1,
-                "q2":q2,
-                "q3":q3,
+        "row": row,
+        "col": col,
+        "q1": q1,
+        "q2": q2,
+        "q3": q3,
     }
     df = pd.DataFrame(dict_temp)
 
     # Return
     return df
 
+
 def dataframe2sinex_solution_matrix_estimate(df, tri="L"):
-    """This function reads in a dataframe of the 
+    """
+    This function reads in a dataframe of the
     SOLUTIONS/MATRIX_ESTIMATE block from a SINEX, the
-    converts each row to a string in a list 
+    converts each row to a string in a list
     ready for writing to SINEX.
 
     :param dataframe df: dataframe of SOLUTION/ESTIMATE block
-    return: list of strings
+    :return: list of strings
     """
-    
+
     # Upper or lower triangle
     triangle = tri
 
     lines = [f"+SOLUTION/MATRIX_ESTIMATE {triangle} COVA"]
-    lines.append("*PARA1 PARA2 ____PARA2+0__________ ____PARA2+1__________ ____PARA2+2__________")
+    lines.append(
+        "*PARA1 PARA2 ____PARA2+0__________ ____PARA2+1__________ ____PARA2+2__________"
+    )
 
     for i in range(len(df.row)):
         p1 = df.row.iloc[i]
@@ -1310,62 +1430,64 @@ def dataframe2sinex_solution_matrix_estimate(df, tri="L"):
         q1 = df.q1.iloc[i]
         q2 = df.q2.iloc[i]
         q3 = df.q3.iloc[i]
-        l = ' {:5n} {:5n} {:>21.14e} {:>21.14e} {:>21.14e}'.format(p1, p2, q1, q2, q3)
-        l = l.replace('nan', '')
+        l = " {:5n} {:5n} {:>21.14e} {:>21.14e} {:>21.14e}".format(p1, p2, q1, q2, q3)
+        l = l.replace("nan", "")
         lines.append(l)
-    
+
     lines.append(f"-SOLUTION/MATRIX_ESTIMATE {triangle} COVA")
 
     # Return
     return lines
 
-def writeSINEX(fp, 
-               header=None, 
-               comment=None, 
-               siteID=None, 
-               solutionEpochs=None, 
-               solutionEstimate=None, 
-               solutionMatrixEstimate=None,
-               fileReference=None,
-               inputAcknowledgments=None,
-               solutionStatistics=None, 
-               siteReceiver=None,
-               siteAntenna=None,
-               siteGpsPhaseCenter=None,
-               siteEccentricity=None,
-               solutionApriori=None,
-               solutionMatrixApriori=None):
-    """This function writes out SINEX blocks to a new SINEX file. The
-    SINEX blocks can be obtained from many of the read_sinex_...() 
-    functions when writing the same input to output. Or can use the 
-    dataframe2sinex_...() functions when SINEX manipulations have
+
+def writeSINEX(
+    fp,
+    header=None,
+    comment=None,
+    siteID=None,
+    solutionEpochs=None,
+    solutionEstimate=None,
+    solutionMatrixEstimate=None,
+    fileReference=None,
+    inputAcknowledgments=None,
+    solutionStatistics=None,
+    siteReceiver=None,
+    siteAntenna=None,
+    siteGpsPhaseCenter=None,
+    siteEccentricity=None,
+    solutionApriori=None,
+    solutionMatrixApriori=None,
+):
+    """
+    This function writes out SINEX blocks to a new SINEX file. The
+    SINEX blocks can be obtained from many of the :literal:`read_sinex_...()`
+    functions when writing the same input to output. Or can use the
+    :literal:`dataframe2sinex_...()` functions when SINEX manipulations have
     occurred on that specific block. Input arguments are set to 'None'
     by default. This allows user to only write out the required blocks.
 
-    Parameters:
-    fp (string): Full filepath to output SINEX. 
-    header (string): Single header line. Can get from read_sinex_header_line().
-    comment (list of strings): +FILE/COMMENT block. Can get from read_sinex_comments().
-    SiteID (list of strings): +SITE/ID block. Can get from read_sinex_site_id_block().
-    SolutionEpochs (list of strings): +SOLUTION/EPOCHS block. Can get from read_sinex_solution_epochs_block().
-    SolutionEstimatee (list of strings): +SOLUTION/ESTIMATE block. Can get from read_sinex_solution_estimate_block().
-    SolutionMatricEstimate (list of strings): +SOLUTION/MATRIX_ESTIMATE block. Can get from read_sinex_solution_matrix_estimate_block().
-    fileReference (list of strings): +FILE/REFERENCE block. Can get from read_sinex_file_reference_block().
-    inputAcknowledgments (list of strings): +INPUT/ACKNOWLEDGEMENTS block. Can get from read_sinex_input_acknowledgments_block().
-    siteReceiver (list of strings): +SITE/RECEIVER block. Can get from read_sinex_site_receiver_block().
-    siteAntenna (list of strings): +SITE/ANTENNA block. Can get from read_sinex_site_antenna_block().
-    siteGpsPhaseCenter (list of strings): +SITE/GPS_PHASE_CENTER block. Can get from read_site_gps_phase_center_block().
-    siteEccentricity (list of strings): +SITE/ECCENTRICITY block. Can get from read_sinex_site_eccentricity_block().
-    solutionApriori (list of strings): +SOLUTION/APRIORI block. Can get from read_sinex_solution_apriori_block().
-    solutionMatrixApriori (list of strings): +SOLUTION/MATRIX_APRIORI block. Can get from read_sinex_solution_matric_apriori_block().
-
-    Return:
-    No return. But a new SINEX file will be written out to the file path (fp).
+    :param str fp: Full filepath to output SINEX.
+    :param str header: Single header line. Can get from read_sinex_header_line().
+    :param list of str comment:  +FILE/COMMENT block. Can get from read_sinex_comments().
+    :param list of str SiteID:  +SITE/ID block. Can get from read_sinex_site_id_block().
+    :param list of str SolutionEpochs:  +SOLUTION/EPOCHS block. Can get from read_sinex_solution_epochs_block().
+    :param list of str SolutionEstimate:  +SOLUTION/ESTIMATE block. Can get from read_sinex_solution_estimate_block().
+    :param list of str SolutionMatricEstimate:  +SOLUTION/MATRIX_ESTIMATE block. Can get from read_sinex_solution_matrix_estimate_block().
+    :param list of str fileReference:  +FILE/REFERENCE block. Can get from read_sinex_file_reference_block().
+    :param list of str inputAcknowledgments:  +INPUT/ACKNOWLEDGEMENTS block. Can get from read_sinex_input_acknowledgments_block().
+    :param list of str siteReceiver:  +SITE/RECEIVER block. Can get from read_sinex_site_receiver_block().
+    :param list of str siteAntenna:  +SITE/ANTENNA block. Can get from read_sinex_site_antenna_block().
+    :param list of str siteGpsPhaseCenter: +SITE/GPS_PHASE_CENTER block. Can get from read_site_gps_phase_center_block().
+    :param list of str siteEccentricity: +SITE/ECCENTRICITY block. Can get from read_sinex_site_eccentricity_block().
+    :param list of str solutionApriori: +SOLUTION/APRIORI block. Can get from read_sinex_solution_apriori_block().
+    :param list of str solutionMatrixApriori: +SOLUTION/MATRIX_APRIORI block. Can get from read_sinex_solution_matric_apriori_block().
+
+    :return: No return. But a new SINEX file will be written out to the file path (fp).
 
     """
 
     # Open File
-    with open(fp, 'w') as f:
+    with open(fp, "w") as f:
 
         # Header
         if header == None:
@@ -1373,7 +1495,9 @@ def writeSINEX(fp,
         else:
             f.write("{}".format(header))
 
-            f.write("*-------------------------------------------------------------------------------\n")
+            f.write(
+                "*-------------------------------------------------------------------------------\n"
+            )
 
         # Comment
         if comment == None:
@@ -1382,8 +1506,10 @@ def writeSINEX(fp,
             for i in range(len(comment)):
                 f.write("{}\n".format(comment[i]))
 
-            f.write("*-------------------------------------------------------------------------------\n")
-        
+            f.write(
+                "*-------------------------------------------------------------------------------\n"
+            )
+
         # FILE/REFERENCE
         if fileReference == None:
             pass
@@ -1391,7 +1517,9 @@ def writeSINEX(fp,
             for i in range(len(fileReference)):
                 f.write("{}\n".format(fileReference[i]))
 
-            f.write("*-------------------------------------------------------------------------------\n")
+            f.write(
+                "*-------------------------------------------------------------------------------\n"
+            )
 
         # INPUT/ACKNOWLEDGMENTS
         if inputAcknowledgments == None:
@@ -1400,7 +1528,9 @@ def writeSINEX(fp,
             for i in range(len(inputAcknowledgments)):
                 f.write("{}\n".format(inputAcknowledgments[i]))
 
-            f.write("*-------------------------------------------------------------------------------\n")
+            f.write(
+                "*-------------------------------------------------------------------------------\n"
+            )
 
         # SOLUTION/STATISTICS
         if solutionStatistics == None:
@@ -1409,16 +1539,20 @@ def writeSINEX(fp,
             for i in range(len(solutionStatistics)):
                 f.write("{}\n".format(solutionStatistics[i]))
 
-            f.write("*-------------------------------------------------------------------------------\n")
-        
-        #SITE/ID
+            f.write(
+                "*-------------------------------------------------------------------------------\n"
+            )
+
+        # SITE/ID
         if siteID == None:
             pass
         else:
             for i in range(len(siteID)):
                 f.write("{}\n".format(siteID[i]))
 
-            f.write("*-------------------------------------------------------------------------------\n")
+            f.write(
+                "*-------------------------------------------------------------------------------\n"
+            )
 
         # SITE/RECEIVER
         if siteReceiver == None:
@@ -1427,7 +1561,9 @@ def writeSINEX(fp,
             for i in range(len(siteReceiver)):
                 f.write("{}\n".format(siteReceiver[i]))
 
-            f.write("*-------------------------------------------------------------------------------\n")
+            f.write(
+                "*-------------------------------------------------------------------------------\n"
+            )
 
         # SITE/ANTENNA
         if siteAntenna == None:
@@ -1436,7 +1572,9 @@ def writeSINEX(fp,
             for i in range(len(siteAntenna)):
                 f.write("{}\n".format(siteAntenna[i]))
 
-            f.write("*-------------------------------------------------------------------------------\n")
+            f.write(
+                "*-------------------------------------------------------------------------------\n"
+            )
 
         # SITE/GPS_PHASE_CENTER
         if siteGpsPhaseCenter == None:
@@ -1445,7 +1583,9 @@ def writeSINEX(fp,
             for i in range(len(siteGpsPhaseCenter)):
                 f.write("{}\n".format(siteGpsPhaseCenter[i]))
 
-            f.write("*-------------------------------------------------------------------------------\n")
+            f.write(
+                "*-------------------------------------------------------------------------------\n"
+            )
 
         # SITE/ECCENTRICITY
         if siteEccentricity == None:
@@ -1454,7 +1594,9 @@ def writeSINEX(fp,
             for i in range(len(siteEccentricity)):
                 f.write("{}\n".format(siteEccentricity[i]))
 
-            f.write("*-------------------------------------------------------------------------------\n")
+            f.write(
+                "*-------------------------------------------------------------------------------\n"
+            )
 
         # SOLUTION/EPOCHS
         if solutionEpochs == None:
@@ -1463,7 +1605,9 @@ def writeSINEX(fp,
             for i in range(len(solutionEpochs)):
                 f.write("{}\n".format(solutionEpochs[i]))
 
-            f.write("*-------------------------------------------------------------------------------\n")
+            f.write(
+                "*-------------------------------------------------------------------------------\n"
+            )
 
         # SOLUTION/ESTIMATE
         if solutionEstimate == None:
@@ -1472,7 +1616,9 @@ def writeSINEX(fp,
             for i in range(len(solutionEstimate)):
                 f.write("{}\n".format(solutionEstimate[i]))
 
-            f.write("*-------------------------------------------------------------------------------\n")
+            f.write(
+                "*-------------------------------------------------------------------------------\n"
+            )
 
         # SOLUTION/APRIORI
         if solutionApriori == None:
@@ -1481,7 +1627,9 @@ def writeSINEX(fp,
             for i in range(len(solutionApriori)):
                 f.write("{}\n".format(solutionApriori[i]))
 
-            f.write("*-------------------------------------------------------------------------------\n")
+            f.write(
+                "*-------------------------------------------------------------------------------\n"
+            )
 
         # SOLUTION/MATRIX_ESTIMATE
         if solutionMatrixEstimate == None:
@@ -1490,24 +1638,30 @@ def writeSINEX(fp,
             for i in range(len(solutionMatrixEstimate)):
                 f.write("{}\n".format(solutionMatrixEstimate[i]))
 
-            f.write("*-------------------------------------------------------------------------------\n")
-        
+            f.write(
+                "*-------------------------------------------------------------------------------\n"
+            )
+
         # SOLUTION/MATRIX_APRIORI
         if solutionMatrixApriori == None:
             pass
         else:
             for i in range(len(solutionMatrixApriori)):
                 f.write("{}\n".format(solutionMatrixApriori[i]))
-            
-            f.write("*-------------------------------------------------------------------------------\n")
+
+            f.write(
+                "*-------------------------------------------------------------------------------\n"
+            )
 
         # End Line
         f.write("%ENDSNX")
 
     f.close()
 
+
 def remove_stns_sinex(sinex, sites):
-    """This function removes a list sites from a SINEX file
+    """
+    This function removes a list sites from a SINEX file
 
     :param sinex: input SINEX file
     :param sites: list of the sites to be removed
@@ -1515,7 +1669,7 @@ def remove_stns_sinex(sinex, sites):
     """
 
     # Open the output file
-    with open('output.snx', 'w') as out:
+    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
@@ -1524,7 +1678,7 @@ def remove_stns_sinex(sinex, sites):
         creation_time = set_creation_time()
         header = header.replace(old_creation_time, creation_time)
         old_num_params = header[60:65]
-        if header[70:71] == 'V':
+        if header[70:71] == "V":
             num_stn_params = 6
         else:
             num_stn_params = 3
@@ -1536,24 +1690,27 @@ def remove_stns_sinex(sinex, sites):
                 num_stns_to_remove += 1
         del solution_epochs
         num_params = int(old_num_params) - num_stn_params * num_stns_to_remove
-        num_params = '{:05d}'.format(num_params)
+        num_params = "{:05d}".format(num_params)
         header = header.replace(str(old_num_params), str(num_params))
         out.write(header)
 
-        out.write("*-------------------------------------------------------------------------------\n")
+        out.write(
+            "*-------------------------------------------------------------------------------\n"
+        )
 
         # Read in the +FILE/COMMENT block and write to output file
         comments = read_sinex_comments(sinex)
         for i in comments:
             out.write(f"{i}\n")
 
-        out.write("*-------------------------------------------------------------------------------\n")
+        out.write(
+            "*-------------------------------------------------------------------------------\n"
+        )
 
         # Read in the site ID block and write out the sites not being removed
         site_id = read_sinex_site_id_block(sinex)
         for line in site_id:
-            if line.startswith('*') or line.startswith('+') or \
-                    line.startswith('-'):
+            if line.startswith("*") or line.startswith("+") or line.startswith("-"):
                 out.write(f"{line}\n")
             else:
                 site = line[1:5]
@@ -1561,14 +1718,15 @@ def remove_stns_sinex(sinex, sites):
                     out.write(f"{line}\n")
         del site_id
 
-        out.write("*-------------------------------------------------------------------------------\n")
+        out.write(
+            "*-------------------------------------------------------------------------------\n"
+        )
 
         # Read in the solution epochs block and write out the epochs of the
         # sites not being removed
         solution_epochs = read_sinex_solution_epochs_block(sinex)
         for line in solution_epochs:
-            if line.startswith('*') or line.startswith('+') or \
-                    line.startswith('-'):
+            if line.startswith("*") or line.startswith("+") or line.startswith("-"):
                 out.write(f"{line}\n")
             else:
                 site = line[1:5]
@@ -1576,7 +1734,9 @@ def remove_stns_sinex(sinex, sites):
                     out.write(f"{line}\n")
         del solution_epochs
 
-        out.write("*-------------------------------------------------------------------------------\n")
+        out.write(
+            "*-------------------------------------------------------------------------------\n"
+        )
 
         # Read in the solution estimate block and write out the estimates of
         # the sites not being removed
@@ -1584,8 +1744,7 @@ def remove_stns_sinex(sinex, sites):
         estimate_number = 0
         solution_estimate = read_sinex_solution_estimate_block(sinex)
         for line in solution_estimate:
-            if line.startswith('*') or line.startswith('+') or \
-                    line.startswith('-'):
+            if line.startswith("*") or line.startswith("+") or line.startswith("-"):
                 out.write(f"{line}\n")
             else:
                 site = line[14:18]
@@ -1594,27 +1753,28 @@ def remove_stns_sinex(sinex, sites):
                     skip.append(num)
                 else:
                     estimate_number += 1
-                    number = '{:5d}'.format(estimate_number)
-                    line = ' ' + number + line[6:]
+                    number = "{:5d}".format(estimate_number)
+                    line = " " + number + line[6:]
                     out.write(f"{line}\n")
         del solution_estimate
 
-        out.write("*-------------------------------------------------------------------------------\n")
+        out.write(
+            "*-------------------------------------------------------------------------------\n"
+        )
 
         # Read in the matrix estimate block and write out minus the sites
         # being removed
         vcv = {}
-        solution_matrix_estimate = \
-            read_sinex_solution_matrix_estimate_block(sinex)
-        if solution_matrix_estimate[0][26:27] == 'L':
-            matrix = 'lower'
-        elif solution_matrix_estimate[0][26:27] == 'U':
-            matrix = 'upper'
+        solution_matrix_estimate = read_sinex_solution_matrix_estimate_block(sinex)
+        if solution_matrix_estimate[0][26:27] == "L":
+            matrix = "lower"
+        elif solution_matrix_estimate[0][26:27] == "U":
+            matrix = "upper"
         out.write(f"{solution_matrix_estimate[0]}\n")
-        if solution_matrix_estimate[1].startswith('*'):
+        if solution_matrix_estimate[1].startswith("*"):
             out.write(f"{solution_matrix_estimate[1]}\n")
         for line in solution_matrix_estimate:
-            if line.startswith(' '):
+            if line.startswith(" "):
                 cols = line.split()
                 row = cols[0]
                 for i in range(2, len(cols)):
@@ -1627,71 +1787,75 @@ def remove_stns_sinex(sinex, sites):
         del solution_matrix_estimate
         sub_vcv = {}
         sub_row = 0
-        for i in range(1, len(vcv)+1):
+        for i in range(1, len(vcv) + 1):
             if i not in skip:
                 sub_row += 1
-                if matrix == 'lower':
+                if matrix == "lower":
                     for j in range(i):
-                        if j+1 not in skip:
+                        if j + 1 not in skip:
                             try:
                                 sub_vcv[str(sub_row)].append(vcv[str(i)][j])
                             except KeyError:
                                 sub_vcv[str(sub_row)] = []
                                 sub_vcv[str(sub_row)].append(vcv[str(i)][j])
-                if matrix == 'upper':
-                    for j in range(len(vcv)-(i-1)):
-                        if j+i not in skip:
+                if matrix == "upper":
+                    for j in range(len(vcv) - (i - 1)):
+                        if j + i not in skip:
                             try:
                                 sub_vcv[str(sub_row)].append(vcv[str(i)][j])
                             except KeyError:
                                 sub_vcv[str(sub_row)] = []
                                 sub_vcv[str(sub_row)].append(vcv[str(i)][j])
-        for i in range(1, len(sub_vcv)+1):
-            para1 = '{:5d}'.format(i)
-            if matrix == 'lower':
+        for i in range(1, len(sub_vcv) + 1):
+            para1 = "{:5d}".format(i)
+            if matrix == "lower":
                 j = -2
-            elif matrix == 'upper':
+            elif matrix == "upper":
                 j = i - 3
             while sub_vcv[str(i)]:
                 j += 3
-                para2 = '{:5d}'.format(j)
-                line = ' ' + para1 + ' ' + para2
+                para2 = "{:5d}".format(j)
+                line = " " + para1 + " " + para2
                 n = min([3, len(sub_vcv[str(i)])])
                 for k in range(n):
-                    val = '{:21.14e}'.format(float(sub_vcv[str(i)].pop(0)))
-                    line += ' ' + str(val)
-                out.write(line + '\n')
+                    val = "{:21.14e}".format(float(sub_vcv[str(i)].pop(0)))
+                    line += " " + str(val)
+                out.write(line + "\n")
         out.write(block_end)
 
         # Write out the trailer line
-        out.write('%ENDSNX\n')
+        out.write("%ENDSNX\n")
 
     return
 
+
 def remove_velocity_sinex(sinex):
-    """This function reads in a SINEX file and removes the 
+    """
+    This function reads in a SINEX file and removes the
     velocity parameters, including the zeros of the SOLUTION/MATRIX_ESTIMATE block,
 
     :param str sinex: input SINEX file
-    return: SINEX file output.snx
+    :return: SINEX file output.snx
     """
 
     # From header, confirm that the SINEX has velocity parameters
     header = read_sinex_header_line(sinex)
     header = header.strip()
-    if header[-1] == 'V':
+    if header[-1] == "V":
         pass
     else:
-        print("Not removing velocities because SINEX file does not have velocity parameters.")
+        print(
+            "Not removing velocities because SINEX file does not have velocity parameters."
+        )
         exit()
 
     # Open the output file
-    with open('output.snx', 'w') as out:
+    with open("output.snx", "w") as out:
 
-        # With header line: 
+        # With header line:
         # - update the creation time
         # - update number of parameter estimates
-        # - remove 'V' from parameter list 
+        # - remove 'V' from parameter list
         # - then write to file
         old_creation_time = header[15:27]
         creation_time = set_creation_time()
@@ -1699,61 +1863,71 @@ def remove_velocity_sinex(sinex):
         old_num_params = int(header[60:65])
         num_params = int(old_num_params / 2)
         header = header.replace(str(old_num_params), str(num_params))
-        header = header.replace('V', '')
+        header = header.replace("V", "")
         out.write(header)
         out.write("\n")
         del header
 
-        out.write("*-------------------------------------------------------------------------------\n")
+        out.write(
+            "*-------------------------------------------------------------------------------\n"
+        )
 
         # Read in the +FILE/COMMENT block and write to output file
         comments = read_sinex_comments(sinex)
         for i in comments:
             out.write(f"{i}\n")
 
-        out.write("*-------------------------------------------------------------------------------\n")
-        
+        out.write(
+            "*-------------------------------------------------------------------------------\n"
+        )
+
         # Read in the +SITE/ID block and write to file
         site_id = read_sinex_site_id_block(sinex)
         for line in site_id:
-            out.write(f"{line}\n")  
+            out.write(f"{line}\n")
         del site_id
 
-        out.write("*-------------------------------------------------------------------------------\n")
-        
+        out.write(
+            "*-------------------------------------------------------------------------------\n"
+        )
+
         # Read in the +SOLUTION/EPOCHS block and write to file
         # - also collect count on number of sites for use later
         numSites = 0
         solution_epochs = read_sinex_solution_epochs_block(sinex)
         for line in solution_epochs:
             out.write(f"{line}\n")
-            if line[0]!="+" and line[0]!="*" and line[0]!="-":
-                numSites+=1
+            if line[0] != "+" and line[0] != "*" and line[0] != "-":
+                numSites += 1
         del solution_epochs
 
-        out.write("*-------------------------------------------------------------------------------\n")
+        out.write(
+            "*-------------------------------------------------------------------------------\n"
+        )
 
-        # Read in the +SOLUTION/ESTIMATE block: 
-        # - gather velocity indices 
-        # - remove velocity rows 
+        # Read in the +SOLUTION/ESTIMATE block:
+        # - gather velocity indices
+        # - remove velocity rows
         # - change indices to account for removed velocities
         # - write to file
         vel_indices = []
         estimate_number = 0
         solution_estimate = read_sinex_solution_estimate_block(sinex)
         for line in solution_estimate:
-            if line[7:10]=="VEL":
+            if line[7:10] == "VEL":
                 vel_indices.append(int(line[0:6]))
-            elif line[0]=="+" or line[0]=="*" or line[0]=="-":
+            elif line[0] == "+" or line[0] == "*" or line[0] == "-":
                 out.write(f"{line}\n")
             else:
-                estimate_number+=1
-                number = '{:5d}'.format(estimate_number)
-                line = ' ' + number + line[6:]
+                estimate_number += 1
+                number = "{:5d}".format(estimate_number)
+                line = " " + number + line[6:]
                 out.write(f"{line}\n")
         del solution_estimate
 
-        out.write("*-------------------------------------------------------------------------------\n")
+        out.write(
+            "*-------------------------------------------------------------------------------\n"
+        )
 
         # Read in the +SOLUTION/MATRIX_ESTIMATE block:
         # - identify if matrix is upper or lower triangle form
@@ -1761,49 +1935,49 @@ def remove_velocity_sinex(sinex):
         # - remove all rows/columns associated with velocity
         # - write to file with new matrix indices (para1, para2)
         solution_matrix_estimate = read_sinex_solution_matrix_estimate_block(sinex)
-        if solution_matrix_estimate[0][26:27] == 'L':
-                matrix = 'lower'
-        elif solution_matrix_estimate[0][26:27] == 'U':
-                matrix = 'upper'
+        if solution_matrix_estimate[0][26:27] == "L":
+            matrix = "lower"
+        elif solution_matrix_estimate[0][26:27] == "U":
+            matrix = "upper"
         # Size of original matrix
-        matrix_dim = numSites*6
+        matrix_dim = numSites * 6
         # Setup matrix of zeros
         Q = zeros((matrix_dim, matrix_dim))
         # Write initial comment line(s), save last comment line, and form matrix
         for line in solution_matrix_estimate:
-            if line[0]=="+":
+            if line[0] == "+":
                 out.write(f"{line}\n")
                 continue
-            if line[0]=="*":
+            if line[0] == "*":
                 out.write(f"{line}\n")
                 continue
-            if line[0]=="-":
+            if line[0] == "-":
                 block_end = line
             else:
-                lineMAT = re.split('\s+', line)
+                lineMAT = re.split("\s+", line)
                 lineMAT = list(filter(None, lineMAT))
                 row = int(lineMAT[0])
                 col = int(lineMAT[1])
             if len(lineMAT) >= 3:
                 q1 = float(lineMAT[2])
-                Q[row-1, col-1] = q1
-                Q[col-1, row-1] = q1
+                Q[row - 1, col - 1] = q1
+                Q[col - 1, row - 1] = q1
             if len(lineMAT) >= 4:
                 q2 = float(lineMAT[3])
-                Q[row-1, col] = q2
-                Q[col, row-1] = q2
+                Q[row - 1, col] = q2
+                Q[col, row - 1] = q2
             if len(lineMAT) >= 5:
                 q3 = float(lineMAT[4])
-                Q[row-1, col+1] = q3
-                Q[col+1, row-1] = q3
+                Q[row - 1, col + 1] = q3
+                Q[col + 1, row - 1] = q3
         # Remove velocity rows/columns from matrix
         num_removed = 0
         for i in vel_indices:
-            Q = delete(Q, i-1-num_removed, 0)
-            Q = delete(Q, i-1-num_removed, 1)
+            Q = delete(Q, i - 1 - num_removed, 0)
+            Q = delete(Q, i - 1 - num_removed, 1)
             num_removed += 1
         # Write matrix to SINEX (lower triangle)
-        if matrix == 'lower':
+        if matrix == "lower":
             i = 0
             j = 0
             while i < len(Q):
@@ -1820,10 +1994,10 @@ def remove_velocity_sinex(sinex):
                 j = 0
                 i += 1
         # Write matrix to SINEX (upper triangle)
-        if matrix == 'upper':
+        if matrix == "upper":
             j = 0
             for i in range(len(Q)):
-                j = i 
+                j = i
                 while j < len(Q):
                     out.write(f" {i+1:5d} {j+1:5d} {Q[i,j]:21.14E} ")
                     j += 1
@@ -1840,23 +2014,25 @@ def remove_velocity_sinex(sinex):
         del Q
 
         # Write out the trailer line
-        out.write('%ENDSNX\n')
+        out.write("%ENDSNX\n")
 
     return
 
+
 def remove_matrixzeros_sinex(sinex):
-    """This function reads in a SINEX file and removes the 
-    zeros from the SOLUTION/MATRIX_ESTIMATE block only. 
+    """
+    This function reads in a SINEX file and removes the
+    zeros from the SOLUTION/MATRIX_ESTIMATE block only.
 
     :param str sinex: input SINEX file
-    return: SINEX file output.snx
+    :return: SINEX file output.snx
     """
-    
+
     # Open the output file
-    with open('output.snx', 'w') as out:
+    with open("output.snx", "w") as out:
 
         # With header line:
-        # - update the creation time 
+        # - update the creation time
         # - then write to file
         header = read_sinex_header_line(sinex)
         old_creation_time = header[15:27]
@@ -1865,38 +2041,48 @@ def remove_matrixzeros_sinex(sinex):
         out.write(header)
         del header
 
-        out.write("*-------------------------------------------------------------------------------\n")
+        out.write(
+            "*-------------------------------------------------------------------------------\n"
+        )
 
         # Read in the +FILE/COMMENT block and write to output file
         comments = read_sinex_comments(sinex)
         for i in comments:
             out.write(f"{i}\n")
 
-        out.write("*-------------------------------------------------------------------------------\n")
-        
+        out.write(
+            "*-------------------------------------------------------------------------------\n"
+        )
+
         # Read in the +SITE/ID block and write to file
         site_id = read_sinex_site_id_block(sinex)
         for line in site_id:
-            out.write(f"{line}\n")  
+            out.write(f"{line}\n")
         del site_id
 
-        out.write("*-------------------------------------------------------------------------------\n")
-        
+        out.write(
+            "*-------------------------------------------------------------------------------\n"
+        )
+
         # Read in the +SOLUTION/EPOCHS block and write to file
         solution_epochs = read_sinex_solution_epochs_block(sinex)
         for line in solution_epochs:
             out.write(f"{line}\n")
         del solution_epochs
 
-        out.write("*-------------------------------------------------------------------------------\n")
+        out.write(
+            "*-------------------------------------------------------------------------------\n"
+        )
 
         # Read in the +SOLUTION/ESTIMATE block
         solution_estimate = read_sinex_solution_estimate_block(sinex)
         for line in solution_estimate:
-                out.write(f"{line}\n")
+            out.write(f"{line}\n")
         del solution_estimate
 
-        out.write("*-------------------------------------------------------------------------------\n")
+        out.write(
+            "*-------------------------------------------------------------------------------\n"
+        )
 
         # Read in the +SOLUTION/MATRIX_ESTIMATE block:
         # - Remove lines that contain only zeros
@@ -1904,19 +2090,26 @@ def remove_matrixzeros_sinex(sinex):
         for line in solution_matrix_estimate:
             col = line.split()
             numCol = len(col)
-            if numCol==3:
-                if col[2]=="0.00000000000000e+00":
+            if numCol == 3:
+                if col[2] == "0.00000000000000e+00":
                     continue
-            if numCol==4:
-                if col[2]=="0.00000000000000e+00" and col[3]=="0.00000000000000e+00":
+            if numCol == 4:
+                if (
+                    col[2] == "0.00000000000000e+00"
+                    and col[3] == "0.00000000000000e+00"
+                ):
                     continue
-            if numCol==5:
-                if col[2]=="0.00000000000000e+00" and col[3]=="0.00000000000000e+00" and col[4]=="0.00000000000000e+00":
+            if numCol == 5:
+                if (
+                    col[2] == "0.00000000000000e+00"
+                    and col[3] == "0.00000000000000e+00"
+                    and col[4] == "0.00000000000000e+00"
+                ):
                     continue
             out.write(line)
         del solution_matrix_estimate
 
         # Write out the trailer line
-        out.write('%ENDSNX\n')
+        out.write("%ENDSNX\n")
 
     return
diff --git a/geodepy/height.py b/geodepy/height.py
index bc5f8d4..41b8690 100644
--- a/geodepy/height.py
+++ b/geodepy/height.py
@@ -1,167 +1,224 @@
-#___________________________________________________________________________#
+# ___________________________________________________________________________#
 # Some notes:
 # Written by Jack McCubbine of Geoscience Australia, date: 08/11/2019
-# This code contains functions to handle tranformations between GPS and 
-# AWVS/AHD and Vice Versa 
+# This code contains functions to handle tranformations between GPS and
+# AWVS/AHD and Vice Versa
 # Gridded data used for the varisous reference surfaces are geotiff files
 # These allow direct access remotely using "gdal"
-#___________________________________________________________________________#
-# Import dependencies 
+# ___________________________________________________________________________#
+# Import dependencies
 import geodepy.constants as cons
 import geodepy.geodesy as gg
 from osgeo import gdal
 import numpy as np
 from scipy.interpolate import griddata
 import math as m
-#___________________________________________________________________________#
+
+
+# ___________________________________________________________________________#
 # Interpolation functions
-def interp_file(Lat,Long,file):
+def interp_file(Lat, Long, file):
     # Import the DOVPM file
     f = gdal.Open(file)
     # load band (akin to a variable in dataset)
-    band = f.GetRasterBand(1)   
+    band = f.GetRasterBand(1)
     # get the pixel width, height, etc.
     transform = f.GetGeoTransform()
     # Grid resolution (known)
-    res=transform[1]
+    res = transform[1]
     # convert lat,lon to row,col
     column = (Long - transform[0]) / transform[1]
     row = (Lat - transform[3]) / transform[5]
     # get pixel values surrounding data point
-    Surrounding_data=(band.ReadAsArray(np.floor(column-2), np.floor(row-2), 5, 5))
+    Surrounding_data = band.ReadAsArray(np.floor(column - 2), np.floor(row - 2), 5, 5)
     # convert row,col back to north,east
     Long_c = transform[0] + np.floor(column) * res
     Lat_c = transform[3] - np.floor(row) * res
     # set up matrices for interpolation
-    count=-1
-    pos=np.zeros((25,2))
-    Surrounding_data_v=np.zeros((25,1))
-    for k in range(-2,3):
-        for j in range(-2,3):
-            count=count+1
-            pos[count]=(Long_c+j*res,Lat_c-k*res)
-            Surrounding_data_v[count]=Surrounding_data[k+2,j+2]          
-    interp_val=griddata(pos,Surrounding_data_v,(Long,Lat),method='cubic')
+    count = -1
+    pos = np.zeros((25, 2))
+    Surrounding_data_v = np.zeros((25, 1))
+    for k in range(-2, 3):
+        for j in range(-2, 3):
+            count = count + 1
+            pos[count] = (Long_c + j * res, Lat_c - k * res)
+            Surrounding_data_v[count] = Surrounding_data[k + 2, j + 2]
+    interp_val = griddata(pos, Surrounding_data_v, (Long, Lat), method="cubic")
     return interp_val
 
-#___________________________________________________________________________#
+
+# ___________________________________________________________________________#
 # Functions to handle the conversions from one height to another
-def GPS_to_AVWS(Lat,Long,GPS_H):
-    zeta=interp_file(Lat, Long, cons.file_AVWS) # AVWS file
-    zeta_std=interp_file(Lat, Long, cons.file_AVWS_STD) # AVWS STD file
-    NORMAL_H=GPS_H-zeta
-    return [NORMAL_H,zeta_std]
-
-def AVWS_to_GPS(Lat,Long,AVWS_H):
-    zeta=interp_file(Lat, Long, cons.file_AVWS) # AVWS file
-    zeta_std=interp_file(Lat, Long, cons.file_AVWS_STD) # AVWS STD file
-    GPS_H=AVWS_H+zeta
-    return [GPS_H,zeta_std]
-
-def AHD_to_AVWS(Lat,Long,AHD_H):
+def GPS_to_AVWS(Lat, Long, GPS_H):
+    zeta = interp_file(Lat, Long, cons.file_AVWS)  # AVWS file
+    zeta_std = interp_file(Lat, Long, cons.file_AVWS_STD)  # AVWS STD file
+    NORMAL_H = GPS_H - zeta
+    return [NORMAL_H, zeta_std]
+
+
+def AVWS_to_GPS(Lat, Long, AVWS_H):
+    zeta = interp_file(Lat, Long, cons.file_AVWS)  # AVWS file
+    zeta_std = interp_file(Lat, Long, cons.file_AVWS_STD)  # AVWS STD file
+    GPS_H = AVWS_H + zeta
+    return [GPS_H, zeta_std]
+
+
+def AHD_to_AVWS(Lat, Long, AHD_H):
     # Convert to GPS
-    GPS_H=AHD_H+interp_file(Lat, Long, cons.file_AG2020) # AUSGEOID2020 file
+    GPS_H = AHD_H + interp_file(Lat, Long, cons.file_AG2020)  # AUSGEOID2020 file
     # Convert to AVWS
-    Normal_H=GPS_H-interp_file(Lat, Long, cons.file_AVWS) # AVWS file
+    Normal_H = GPS_H - interp_file(Lat, Long, cons.file_AVWS)  # AVWS file
     return [Normal_H]
 
-def GPS_to_AHD(Lat,Long,GPS_H):
-    N=interp_file(Lat, Long, cons.file_AG2020) # AUSGEOID2020 file
-    N_std=interp_file(Lat, Long, cons.file_AG2020_STD) # AUSGEOID2020 STD file
-    AHD_H=GPS_H-N
-    return [AHD_H,N_std]
-
-def AHD_to_GPS(Lat,Long,AHD_H):
-    N=interp_file(Lat, Long, cons.file_AG2020) # AUSGEOID2020 file
-    N_std=interp_file(Lat, Long, cons.file_AG2020_STD) # AUSGEOID2020 STD file
-    GPS_H=AHD_H+N
-    return [GPS_H,N_std]
-
-def AVWS_to_AHD(Lat,Long,Normal_H):   
-    # Convert to GPS    
-    GPS_H=Normal_H+interp_file(Lat, Long, cons.file_AVWS) # AVWS file
+
+def GPS_to_AHD(Lat, Long, GPS_H):
+    N = interp_file(Lat, Long, cons.file_AG2020)  # AUSGEOID2020 file
+    N_std = interp_file(Lat, Long, cons.file_AG2020_STD)  # AUSGEOID2020 STD file
+    AHD_H = GPS_H - N
+    return [AHD_H, N_std]
+
+
+def AHD_to_GPS(Lat, Long, AHD_H):
+    N = interp_file(Lat, Long, cons.file_AG2020)  # AUSGEOID2020 file
+    N_std = interp_file(Lat, Long, cons.file_AG2020_STD)  # AUSGEOID2020 STD file
+    GPS_H = AHD_H + N
+    return [GPS_H, N_std]
+
+
+def AVWS_to_AHD(Lat, Long, Normal_H):
+    # Convert to GPS
+    GPS_H = Normal_H + interp_file(Lat, Long, cons.file_AVWS)  # AVWS file
     # Convert to AHD
-    AHD_H=GPS_H-interp_file(Lat, Long, cons.file_AG2020) # AUSGEOID2020 file
+    AHD_H = GPS_H - interp_file(Lat, Long, cons.file_AG2020)  # AUSGEOID2020 file
     return [AHD_H]
 
-def DOV(Lat,Long):   
-    # Convert to GPS    
-    DOV_PM=interp_file(Lat, Long, cons.file_DOV_PM) # AVWS file
+
+def DOV(Lat, Long):
+    # Convert to GPS
+    DOV_PM = interp_file(Lat, Long, cons.file_DOV_PM)  # AVWS file
     # Convert to AHD
-    DOV_PV=interp_file(Lat, Long, cons.file_DOV_PV) # AUSGEOID2020 file
-    return [DOV_PM,DOV_PV]
+    DOV_PV = interp_file(Lat, Long, cons.file_DOV_PV)  # AUSGEOID2020 file
+    return [DOV_PM, DOV_PV]
 
-def GPS_to_AUSGeoid98(Lat,Long,GPS_H):
-    N=interp_file(Lat,Long,cons.file_AG98) # AUSGEOID98 file
-    AHD_H=GPS_H-N
+
+def GPS_to_AUSGeoid98(Lat, Long, GPS_H):
+    N = interp_file(Lat, Long, cons.file_AG98)  # AUSGEOID98 file
+    AHD_H = GPS_H - N
     return [AHD_H]
 
-def AUSGeoid98_to_GPS(Lat,Long,AHD_H):
-    N=interp_file(Lat,Long,cons.file_AG98) # AUSGEOID98 file
-    GPS_H=AHD_H+N
+
+def AUSGeoid98_to_GPS(Lat, Long, AHD_H):
+    N = interp_file(Lat, Long, cons.file_AG98)  # AUSGEOID98 file
+    GPS_H = AHD_H + N
     return [GPS_H]
 
-def GPS_to_AUSGeoid09(Lat,Long,GPS_H):
-    N=interp_file(Lat,Long,cons.file_AG09) # AUSGEOID09 file
-    AHD_H=GPS_H-N
+
+def GPS_to_AUSGeoid09(Lat, Long, GPS_H):
+    N = interp_file(Lat, Long, cons.file_AG09)  # AUSGEOID09 file
+    AHD_H = GPS_H - N
     return [AHD_H]
 
-def AUSGeoid09_to_GPS(Lat,Long,AHD_H):
-    N=interp_file(Lat,Long,cons.file_AG09) # AUSGEOID09 file
-    GPS_H=AHD_H+N
+
+def AUSGeoid09_to_GPS(Lat, Long, AHD_H):
+    N = interp_file(Lat, Long, cons.file_AG09)  # AUSGEOID09 file
+    GPS_H = AHD_H + N
     return [GPS_H]
 
-def DOV_09(Lat,Long):   
+
+def DOV_09(Lat, Long):
     # Interp PM
-    DOV_PM=interp_file(Lat,Long,cons.file_AG09_DOV_PM) # AGQG09 DOV file
+    DOV_PM = interp_file(Lat, Long, cons.file_AG09_DOV_PM)  # AGQG09 DOV file
     # Interp PV
-    DOV_PV=interp_file(Lat,Long,cons.file_AG09_DOV_PV) # AGQG09 DOV file
-    return [DOV_PM,DOV_PV]
+    DOV_PV = interp_file(Lat, Long, cons.file_AG09_DOV_PV)  # AGQG09 DOV file
+    return [DOV_PM, DOV_PV]
 
-def DOV_98(Lat,Long):   
-    # Interp PM  
-    DOV_PM=interp_file(Lat,Long,cons.file_AG98_DOV_PM) # AGQG98 DOV file
+
+def DOV_98(Lat, Long):
+    # Interp PM
+    DOV_PM = interp_file(Lat, Long, cons.file_AG98_DOV_PM)  # AGQG98 DOV file
     # Interp PV
-    DOV_PV=interp_file(Lat,Long,cons.file_AG98_DOV_PV) # AGQG98 DOV file
-    return [DOV_PM,DOV_PV]
+    DOV_PV = interp_file(Lat, Long, cons.file_AG98_DOV_PV)  # AGQG98 DOV file
+    return [DOV_PM, DOV_PV]
 
-def mean_normal_grav(Lat,h):
+
+def mean_normal_grav(Lat, h):
     # GRS 80 constants
-    a=6378137
-    b=6356752.3141
-    omega=7292115*(10**-11)
-    e2=0.00669438002290
-    GM=3986005*10**8
-    k=0.001931851353
+    a = 6378137
+    b = 6356752.3141
+    omega = 7292115 * (10**-11)
+    e2 = 0.00669438002290
+    GM = 3986005 * 10**8
+    k = 0.001931851353
     # GRS80 normal gravity
-    EllGrav=(10**5)*9.7803267715*(1+k*(np.sin(Lat*np.pi/180)**2))/np.sqrt(1-e2*(np.sin(Lat*np.pi/180)**2))
-    FA=-((2*(EllGrav/a)*(1+(a-b)/a + omega**2*a**2*b/GM - 2*(a-b)/a*(np.sin(Lat*np.pi/180)**2))*(h**2)/2-3*(EllGrav/a**2)*(h**3)/3)/h)
-    mean_normal_g=(EllGrav+FA)*(10**-5)
+    EllGrav = (
+        (10**5)
+        * 9.7803267715
+        * (1 + k * (np.sin(Lat * np.pi / 180) ** 2))
+        / np.sqrt(1 - e2 * (np.sin(Lat * np.pi / 180) ** 2))
+    )
+    FA = -(
+        (
+            2
+            * (EllGrav / a)
+            * (
+                1
+                + (a - b) / a
+                + omega**2 * a**2 * b / GM
+                - 2 * (a - b) / a * (np.sin(Lat * np.pi / 180) ** 2)
+            )
+            * (h**2)
+            / 2
+            - 3 * (EllGrav / a**2) * (h**3) / 3
+        )
+        / h
+    )
+    mean_normal_g = (EllGrav + FA) * (10**-5)
     return mean_normal_g
 
-def normal_grav(Lat,h):
+
+def normal_grav(Lat, h):
     # GRS 80 constants
-    a=6378137
-    b=6356752.3141
-    omega=7292115*(10**-11)
-    e2=0.00669438002290
-    GM=3986005*10**8
-    k=0.001931851353
+    a = 6378137
+    b = 6356752.3141
+    omega = 7292115 * (10**-11)
+    e2 = 0.00669438002290
+    GM = 3986005 * 10**8
+    k = 0.001931851353
     # GRS80 normal gravity
-    EllGrav=(10**5)*9.7803267715*(1+k*(np.sin(Lat*np.pi/180)**2))/np.sqrt(1-e2*(np.sin(Lat*np.pi/180)**2))
-    FA=-(2*EllGrav*h/a)*(1+(a-b)/a+omega**2*a**2*b/GM-2*(a-b)/a*(np.sin(Lat*np.pi/180)**2))+3*(EllGrav*h**2)/(a**2)
-    normal_g=(EllGrav+FA)*(10**-5)
+    EllGrav = (
+        (10**5)
+        * 9.7803267715
+        * (1 + k * (np.sin(Lat * np.pi / 180) ** 2))
+        / np.sqrt(1 - e2 * (np.sin(Lat * np.pi / 180) ** 2))
+    )
+    FA = -(2 * EllGrav * h / a) * (
+        1
+        + (a - b) / a
+        + omega**2 * a**2 * b / GM
+        - 2 * (a - b) / a * (np.sin(Lat * np.pi / 180) ** 2)
+    ) + 3 * (EllGrav * h**2) / (a**2)
+    normal_g = (EllGrav + FA) * (10**-5)
     return normal_g
 
-def mean_surface_grav(Lat_A,Long_A,H_A,Lat_B,Long_B,H_B):
-    Surf_Grav_A=interp_grav(Lat_A,Long_A)*(10**-5)+normal_grav(Lat_A,H_A)+0.0419*2.67*H_A*(10**-5)
-    Surf_Grav_B=interp_grav(Lat_B,Long_B)*(10**-5)+normal_grav(Lat_B,H_B)+0.0419*2.67*H_B*(10**-5)
-    mean_g=(Surf_Grav_A+Surf_Grav_B)/2
+
+def mean_surface_grav(Lat_A, Long_A, H_A, Lat_B, Long_B, H_B):
+    Surf_Grav_A = (
+        interp_grav(Lat_A, Long_A) * (10**-5)
+        + normal_grav(Lat_A, H_A)
+        + 0.0419 * 2.67 * H_A * (10**-5)
+    )
+    Surf_Grav_B = (
+        interp_grav(Lat_B, Long_B) * (10**-5)
+        + normal_grav(Lat_B, H_B)
+        + 0.0419 * 2.67 * H_B * (10**-5)
+    )
+    mean_g = (Surf_Grav_A + Surf_Grav_B) / 2
     return mean_g
 
-def interp_grav(Lat,Long):
+
+def interp_grav(Lat, Long):
     # Grid resolution (known)
-    res=1.0/60
+    res = 1.0 / 60
     # open geotiff file
     f = gdal.Open(cons.file_GRAV_BA)
     # load band (akin to a variable in dataset)
@@ -172,35 +229,40 @@ def interp_grav(Lat,Long):
     column = (Long - transform[0]) / transform[1]
     row = (Lat - transform[3]) / transform[5]
     # get pixel values surrounding data point
-    Surrounding_data=(band.ReadAsArray(np.floor(column-2), np.floor(row-2), 5, 5))
+    Surrounding_data = band.ReadAsArray(np.floor(column - 2), np.floor(row - 2), 5, 5)
     # convert row,col back to north,east
     Long_c = transform[0] + np.floor(column) * res
     Lat_c = transform[3] - np.floor(row) * res
     # set up matrices for interpolation
-    count=-1
-    pos=np.zeros((25,2))
-    Surrounding_data_v=np.zeros((25,1))
-    for k in range(-2,3):
-        for j in range(-2,3):
-            count=count+1
-            pos[count]=(Long_c+j*res,Lat_c-k*res)
-            Surrounding_data_v[count]=Surrounding_data[k+2,j+2]
-    interp_g=griddata(pos,Surrounding_data_v,(Long,Lat))
+    count = -1
+    pos = np.zeros((25, 2))
+    Surrounding_data_v = np.zeros((25, 1))
+    for k in range(-2, 3):
+        for j in range(-2, 3):
+            count = count + 1
+            pos[count] = (Long_c + j * res, Lat_c - k * res)
+            Surrounding_data_v[count] = Surrounding_data[k + 2, j + 2]
+    interp_g = griddata(pos, Surrounding_data_v, (Long, Lat))
     return interp_g
 
-def normal_correction(Lat_A,Long_A,H_A,Lat_B,Long_B,H_B):
+
+def normal_correction(Lat_A, Long_A, H_A, Lat_B, Long_B, H_B):
     # ellipsoidal gravity at 45 deg. Lat
-    Gamma_0=9.8061992115
+    Gamma_0 = 9.8061992115
     # Normal Gravity at the point
-    normal_g_A=mean_normal_grav(Lat_A,H_A)
-#    print normal_g_A
-    normal_g_B=mean_normal_grav(Lat_B,H_B)
-#    print normal_g_B
-    dn=H_B-H_A
-    g=mean_surface_grav(Lat_A,Long_A,H_A,Lat_B,Long_B,H_B)
-   # print g
-    NC=(dn*(g-Gamma_0)/Gamma_0)+H_A*(normal_g_A-Gamma_0)/Gamma_0-H_B*(normal_g_B-Gamma_0)/Gamma_0
-    return NC,g
+    normal_g_A = mean_normal_grav(Lat_A, H_A)
+    #    print normal_g_A
+    normal_g_B = mean_normal_grav(Lat_B, H_B)
+    #    print normal_g_B
+    dn = H_B - H_A
+    g = mean_surface_grav(Lat_A, Long_A, H_A, Lat_B, Long_B, H_B)
+    # print g
+    NC = (
+        (dn * (g - Gamma_0) / Gamma_0)
+        + H_A * (normal_g_A - Gamma_0) / Gamma_0
+        - H_B * (normal_g_B - Gamma_0) / Gamma_0
+    )
+    return NC, g
 
 
 def normal_orthometric_correction(lat1, lon1, H1, lat2, lon2, H2):
@@ -227,6 +289,8 @@ def normal_orthometric_correction(lat1, lon1, H1, lat2, lon2, H2):
     dist = vinc_inv[0]
     az = vinc_inv[1]
 
-    noc = - f_ng / m_rad * mid_height * m.sin(2.0 * mid_lat) * m.cos(m.radians(az)) * dist
+    noc = (
+        -f_ng / m_rad * mid_height * m.sin(2.0 * mid_lat) * m.cos(m.radians(az)) * dist
+    )
 
     return noc
diff --git a/geodepy/inputoutput.py b/geodepy/inputoutput.py
index 2232bfb..52daaf5 100644
--- a/geodepy/inputoutput.py
+++ b/geodepy/inputoutput.py
@@ -1,4 +1,3 @@
-
 __all__ = ["grid2geoio", "geo2gridio", "gdatrans7"]
 
 import geodepy.convert
@@ -8,30 +7,28 @@
 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
+     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
 
-        Output:
-        Data in the file 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
     # geotypeout value was provided
@@ -44,12 +41,17 @@ def grid2geoio(fn, fn_out, easting, northing, utmzone, geotypeout):
     # 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: geodepy.convert.grid2geo(x[utmzone], x[easting], x[northing]), axis=1)
+    returned = csvdf.apply(
+        lambda x: geodepy.convert.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.dec2hp)
-        resultdf['Longitude'] = resultdf['Longitude'].apply(cv.dec2hp)
+    resultdf = pd.DataFrame(
+        list(returned),
+        columns=["Latitude", "Longitude", "Point Scale Factor", "Grid Convergence"],
+    )
+    if geotypeout == "DMS":
+        resultdf["Latitude"] = resultdf["Latitude"].apply(cv.dec2hp)
+        resultdf["Longitude"] = resultdf["Longitude"].apply(cv.dec2hp)
     # Adds the results to the original dataframe from the csv
     csvdf = pd.concat([csvdf, resultdf], axis=1)
     # Writes the dataframe to a csv
@@ -58,19 +60,17 @@ def grid2geoio(fn, fn_out, easting, northing, utmzone, geotypeout):
 
 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
+    The CSV data must have headers.
 
-        Output:
-        Data in the file is output to the fn_out location as a CSV.
-        """
+    :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
+
+    :return: Data 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
@@ -84,17 +84,28 @@ def geo2gridio(fn, fn_out, latitude, longitude, geotypein):
     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.hp2dec)
-        csvdf['LongitudeDD'] = csvdf[longitude].apply(cv.hp2dec)
-        latitude = 'LatitudeDD'
-        longitude = 'LongitudeDD'
+    if geotypein == "DMS":
+        csvdf["LatitudeDD"] = csvdf[latitude].apply(cv.hp2dec)
+        csvdf["LongitudeDD"] = csvdf[longitude].apply(cv.hp2dec)
+        latitude = "LatitudeDD"
+        longitude = "LongitudeDD"
 
     # Sends data to tf.geo2grid
-    returned = csvdf.apply(lambda x: geodepy.convert.geo2grid(x[latitude], x[longitude]), axis=1)
+    returned = csvdf.apply(
+        lambda x: geodepy.convert.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'])
+    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
@@ -102,12 +113,10 @@ def geo2gridio(fn, fn_out, latitude, longitude, geotypein):
 
 
 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
@@ -116,12 +125,7 @@ def gdatrans7(fn, fn_out, latitude, longitude, ellht, gdageotypein, direction):
      :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.
+     :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
@@ -138,18 +142,40 @@ def gdatrans7(fn, fn_out, latitude, longitude, ellht, gdageotypein, direction):
         gdageotypein = gdageotypein.get()
     gdageotypein_options = ["DD", "DMS"]
     if gdageotypein not in gdageotypein_options:
-        raise ValueError("Invalid gdageotypein. Expected one of: %s" % 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)
+        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__()
+        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"
@@ -158,37 +184,62 @@ def gdatrans7(fn, fn_out, latitude, longitude, ellht, gdageotypein, direction):
     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.hp2dec)
-        csvdf['Longitude'] = csvdf[longitude].apply(cv.hp2dec)
+    if gdageotypein == "DMS":
+        csvdf["LatitudeDMS"] = csvdf[latitude]
+        csvdf["LongitudeDMS"] = csvdf[longitude]
+        csvdf["Latitude"] = csvdf[latitude].apply(cv.hp2dec)
+        csvdf["Longitude"] = csvdf[longitude].apply(cv.hp2dec)
 
     # Converts Lat, Long & ElipHt XYZ
-    returned = csvdf.apply(lambda x: geodepy.convert.llh2xyz(x[latitude], x[longitude], x[ellht]), axis=1)
+    returned = csvdf.apply(
+        lambda x: geodepy.convert.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'])
+    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)
+    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'])
+    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: geodepy.convert.xyz2llh(x.TransCartesianX, x.TransCartesianY, x.TransCartesianZ), axis=1)
+    returned = csvdf.apply(
+        lambda x: geodepy.convert.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])
+    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)
+    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)
diff --git a/geodepy/ntv2reader.py b/geodepy/ntv2reader.py
index 6a152ef..2ae9bf7 100644
--- a/geodepy/ntv2reader.py
+++ b/geodepy/ntv2reader.py
@@ -12,36 +12,95 @@
 
 
 class NTv2Grid(object):
-    def __init__(self, num_orec, num_srec, num_file, gs_type, version, system_f, system_t, major_f, minor_f, major_t,
-                 minor_t, file_path):
-        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
-        self.gs_type = gs_type          # grid shift type
-        self.version = version          # grid file version
-        self.system_f = system_f        # reference system
-        self.system_t = system_t        # reference system
-        self.major_f = major_f          # semi major of from system
-        self.minor_f = minor_f          # semi minor of from system
-        self.major_t = major_t          # semi major of to system
-        self.minor_t = minor_t          # semi minor of to system
+    def __init__(
+        self,
+        num_orec,
+        num_srec,
+        num_file,
+        gs_type,
+        version,
+        system_f,
+        system_t,
+        major_f,
+        minor_f,
+        major_t,
+        minor_t,
+        file_path,
+    ):
+        '''
+        NTv2 Grid Parameters
+
+        :param num_orec: Number of header identifiers
+        :param num_srec: Number of sub-header idents
+        :param num_file: Number of subgrids in file
+        :param gs_type: grid shift type
+        :param version: grid file version
+        :param system_f: reference system
+        :param system_t: reference system
+        :param major_f: semi major of from system
+        :param minor_f: semi minor of from system
+        :param major_t: semi major of to system
+        :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
+        self.gs_type = gs_type  # grid shift type
+        self.version = version  # grid file version
+        self.system_f = system_f  # reference system
+        self.system_t = system_t  # reference system
+        self.major_f = major_f  # semi major of from system
+        self.minor_f = minor_f  # semi minor of from system
+        self.major_t = major_t  # semi major of to system
+        self.minor_t = minor_t  # semi minor of to system
         self.subgrids = {}
         self.file_path = file_path
 
 
 class SubGrid(object):
-    def __init__(self, sub_name, parent, created, updated, s_lat, n_lat, e_long, w_long, lat_inc, long_inc, gs_count):
-        self.sub_name = sub_name        # subgrid name
-        self.parent = parent            # parent name
-        self.created = created          # date created
-        self.updated = updated          # date modified
-        self.s_lat = s_lat              # south latitude extents
-        self.n_lat = n_lat              # north latitude extents
-        self.e_long = e_long            # east longitude extents
-        self.w_long = w_long            # west longitude extents
-        self.lat_inc = lat_inc          # latitude increment
-        self.long_inc = long_inc        # longitude increment
-        self.gs_count = gs_count        # total nodes in subgrid
+    def __init__(
+        self,
+        sub_name,
+        parent,
+        created,
+        updated,
+        s_lat,
+        n_lat,
+        e_long,
+        w_long,
+        lat_inc,
+        long_inc,
+        gs_count,
+    ):
+        '''
+        Sub Grid Parameters
+
+        :param sub_name: subgrid name
+        :param parent: parent name
+        :param created: date created
+        :param updated: date modified
+        :param s_lat: south latitude extents
+        :param n_lat: north latitude extents
+        :param e_long: east longitude extents
+        :param w_long: west longitude extents
+        :param lat_inc: latitude increment
+        :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
+        self.updated = updated  # date modified
+        self.s_lat = s_lat  # south latitude extents
+        self.n_lat = n_lat  # north latitude extents
+        self.e_long = e_long  # east longitude extents
+        self.w_long = w_long  # west longitude extents
+        self.lat_inc = lat_inc  # latitude increment
+        self.long_inc = long_inc  # longitude increment
+        self.gs_count = gs_count  # total nodes in subgrid
 
     def ntv2_bilinear(self, lat, lon, num_cols, row, col, f, start_byte):
         """
@@ -55,7 +114,7 @@ def ntv2_bilinear(self, lat, lon, num_cols, row, col, f, start_byte):
         :param f: variable for open file NTv2 being read as binary
         :param start_byte: start index of subgrid
 
-        :return: four field tuple of interpolation results at point of interest.
+        :return: Four field tuple of interpolation results at point of interest.
         """
 
         #   |     |
@@ -83,7 +142,7 @@ def ntv2_bilinear(self, lat, lon, num_cols, row, col, f, start_byte):
         node_2 = read_node(f)
 
         # Navigate to beginning of node 3
-        f.seek(16*(pos3 - pos2 - 1), 1)
+        f.seek(16 * (pos3 - pos2 - 1), 1)
 
         # Read in values for nodes 3 and 4
         node_3 = read_node(f)
@@ -97,10 +156,18 @@ def ntv2_bilinear(self, lat, lon, num_cols, row, col, f, start_byte):
         x = (lon - long1) / self.long_inc
         y = (lat - lat1) / self.lat_inc
 
-        field_1 = round(bilinear_interpolation(node_1[0], node_2[0], node_3[0], node_4[0], x, y), 6)
-        field_2 = round(bilinear_interpolation(node_1[1], node_2[1], node_3[1], node_4[1], x, y), 6)
-        field_3 = round(bilinear_interpolation(node_1[2], node_2[2], node_3[2], node_4[2], x, y), 6)
-        field_4 = round(bilinear_interpolation(node_1[3], node_2[3], node_3[3], node_4[3], x, y), 6)
+        field_1 = round(
+            bilinear_interpolation(node_1[0], node_2[0], node_3[0], node_4[0], x, y), 6
+        )
+        field_2 = round(
+            bilinear_interpolation(node_1[1], node_2[1], node_3[1], node_4[1], x, y), 6
+        )
+        field_3 = round(
+            bilinear_interpolation(node_1[2], node_2[2], node_3[2], node_4[2], x, y), 6
+        )
+        field_4 = round(
+            bilinear_interpolation(node_1[3], node_2[3], node_3[3], node_4[3], x, y), 6
+        )
 
         return field_1, field_2, field_3, field_4
 
@@ -116,7 +183,7 @@ def ntv2_bicubic(self, lat, lon, num_cols, row, col, f, start_byte):
         :param f: variable for open file NTv2 being read as binary
         :param start_byte: start index of subgrid
 
-        :return: four field tuple of interpolation results at point of interest.
+        :return: Four field tuple of interpolation results at point of interest.
 
         """
 
@@ -200,26 +267,98 @@ def ntv2_bicubic(self, lat, lon, num_cols, row, col, f, start_byte):
         y = round((lat - lat1) / self.lat_inc, 6)
 
         # Call bicubic interpolation function to interpolate ntv2 fields.
-        field_1 = round(bicubic_interpolation(node_1[0], node_2[0], node_3[0], node_4[0],
-                                              node_5[0], node_6[0], node_7[0], node_8[0],
-                                              node_9[0], node_10[0], node_11[0], node_12[0],
-                                              node_13[0], node_14[0], node_15[0], node_16[0],
-                                              x, y), 6)
-        field_2 = round(bicubic_interpolation(node_1[1], node_2[1], node_3[1], node_4[1],
-                                              node_5[1], node_6[1], node_7[1], node_8[1],
-                                              node_9[1], node_10[1], node_11[1], node_12[1],
-                                              node_13[1], node_14[1], node_15[1], node_16[1],
-                                              x, y), 6)
-        field_3 = round(bicubic_interpolation(node_1[2], node_2[2], node_3[2], node_4[2],
-                                              node_5[2], node_6[2], node_7[2], node_8[2],
-                                              node_9[2], node_10[2], node_11[2], node_12[2],
-                                              node_13[2], node_14[2], node_15[2], node_16[2],
-                                              x, y), 6)
-        field_4 = round(bicubic_interpolation(node_1[3], node_2[3], node_3[3], node_4[3],
-                                              node_5[3], node_6[3], node_7[3], node_8[3],
-                                              node_9[3], node_10[3], node_11[3], node_12[3],
-                                              node_13[3], node_14[3], node_15[3], node_16[3],
-                                              x, y), 6)
+        field_1 = round(
+            bicubic_interpolation(
+                node_1[0],
+                node_2[0],
+                node_3[0],
+                node_4[0],
+                node_5[0],
+                node_6[0],
+                node_7[0],
+                node_8[0],
+                node_9[0],
+                node_10[0],
+                node_11[0],
+                node_12[0],
+                node_13[0],
+                node_14[0],
+                node_15[0],
+                node_16[0],
+                x,
+                y,
+            ),
+            6,
+        )
+        field_2 = round(
+            bicubic_interpolation(
+                node_1[1],
+                node_2[1],
+                node_3[1],
+                node_4[1],
+                node_5[1],
+                node_6[1],
+                node_7[1],
+                node_8[1],
+                node_9[1],
+                node_10[1],
+                node_11[1],
+                node_12[1],
+                node_13[1],
+                node_14[1],
+                node_15[1],
+                node_16[1],
+                x,
+                y,
+            ),
+            6,
+        )
+        field_3 = round(
+            bicubic_interpolation(
+                node_1[2],
+                node_2[2],
+                node_3[2],
+                node_4[2],
+                node_5[2],
+                node_6[2],
+                node_7[2],
+                node_8[2],
+                node_9[2],
+                node_10[2],
+                node_11[2],
+                node_12[2],
+                node_13[2],
+                node_14[2],
+                node_15[2],
+                node_16[2],
+                x,
+                y,
+            ),
+            6,
+        )
+        field_4 = round(
+            bicubic_interpolation(
+                node_1[3],
+                node_2[3],
+                node_3[3],
+                node_4[3],
+                node_5[3],
+                node_6[3],
+                node_7[3],
+                node_8[3],
+                node_9[3],
+                node_10[3],
+                node_11[3],
+                node_12[3],
+                node_13[3],
+                node_14[3],
+                node_15[3],
+                node_16[3],
+                x,
+                y,
+            ),
+            6,
+        )
 
         return field_1, field_2, field_3, field_4
 
@@ -229,21 +368,21 @@ def read_node(f):
     Function to read in values of nodes
 
     :param f: variable for open file NTv2 being read as binary
-    :return: tuple containing the four ntv2 fields at the grid node.
+    :return: Tuple containing the four ntv2 fields at the grid node.
     """
 
     # field_1: shift lat / geoid separation (N)
     byte = f.read(4)
-    field_1 = struct.unpack('f', byte)[0]
+    field_1 = struct.unpack("f", byte)[0]
     # field 2: shift lon / deflection in prime meridian value (Xi)
     byte = f.read(4)
-    field_2 = struct.unpack('f', byte)[0]
+    field_2 = struct.unpack("f", byte)[0]
     # field 3: reliability lat / deflection in prime vertical value (Eta)
     byte = f.read(4)
-    field_3 = struct.unpack('f', byte)[0]
+    field_3 = struct.unpack("f", byte)[0]
     # field 4: reliability lon / NA
     byte = f.read(4)
-    field_4 = struct.unpack('f', byte)[0]
+    field_4 = struct.unpack("f", byte)[0]
 
     return field_1, field_2, field_3, field_4
 
@@ -259,7 +398,7 @@ def bilinear_interpolation(n1, n2, n3, n4, x, y):
     :param x: interpolation scale factor for x axis
     :param y: interpolation scale factor for y axis
 
-    :return: value at node P
+    :return: Value at node P
     """
 
     a0 = n1
@@ -270,7 +409,9 @@ def bilinear_interpolation(n1, n2, n3, n4, x, y):
     return p
 
 
-def bicubic_interpolation(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, x, y):
+def bicubic_interpolation(
+    n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, x, y
+):
     """
     Bicubic interpolation of value for point of interest (P).
 
@@ -293,26 +434,30 @@ def bicubic_interpolation(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13
     :param x: interpolation scale factor for x axis
     :param y: interpolation scale factor for y axis
 
-    :return: value at node P
+    :return: Value at node P
     """
 
     # Define the inverse of the coefficient matrix
-    cinv = np.array([[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-                     [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
-                     [-3, 0, 0, 3, 0, 0, 0, 0, -2, 0, 0, -1, 0, 0, 0, 0],
-                     [2, 0, 0, -2, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0],
-                     [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-                     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
-                     [0, 0, 0, 0, -3, 0, 0, 3, 0, 0, 0, 0, -2, 0, 0, -1],
-                     [0, 0, 0, 0, 2, 0, 0, -2, 0, 0, 0, 0, 1, 0, 0, 1],
-                     [-3, 3, 0, 0, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-                     [0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, -2, -1, 0, 0],
-                     [9, -9, 9, -9, 6, 3, -3, -6, 6, -6, -3, 3, 4, 2, 1, 2],
-                     [-6, 6, -6, 6, -4, -2, 2, 4, -3, 3, 3, -3, -2, -1, -1, -2],
-                     [2, -2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-                     [0, 0, 0, 0, 0, 0, 0, 0, 2, -2, 0, 0, 1, 1, 0, 0],
-                     [-6, 6, -6, 6, -3, -3, 3, 3, -4, 4, 2, -2, -2, -2, -1, -1],
-                     [4, -4, 4, -4, 2, 2, -2, -2, 2, -2, -2, 2, 1, 1, 1, 1]])
+    cinv = np.array(
+        [
+            [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+            [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
+            [-3, 0, 0, 3, 0, 0, 0, 0, -2, 0, 0, -1, 0, 0, 0, 0],
+            [2, 0, 0, -2, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0],
+            [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
+            [0, 0, 0, 0, -3, 0, 0, 3, 0, 0, 0, 0, -2, 0, 0, -1],
+            [0, 0, 0, 0, 2, 0, 0, -2, 0, 0, 0, 0, 1, 0, 0, 1],
+            [-3, 3, 0, 0, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+            [0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, -2, -1, 0, 0],
+            [9, -9, 9, -9, 6, 3, -3, -6, 6, -6, -3, 3, 4, 2, 1, 2],
+            [-6, 6, -6, 6, -4, -2, 2, 4, -3, 3, 3, -3, -2, -1, -1, -2],
+            [2, -2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+            [0, 0, 0, 0, 0, 0, 0, 0, 2, -2, 0, 0, 1, 1, 0, 0],
+            [-6, 6, -6, 6, -3, -3, 3, 3, -4, 4, 2, -2, -2, -2, -1, -1],
+            [4, -4, 4, -4, 2, 2, -2, -2, 2, -2, -2, 2, 1, 1, 1, 1],
+        ]
+    )
 
     # Define x parameters
     # Function values
@@ -337,7 +482,9 @@ def bicubic_interpolation(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13
     x16 = (n12 - n2 - n14 + n16) / 4
 
     # Create array from x parameters
-    xarr = np.array([x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16])
+    xarr = np.array(
+        [x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16]
+    )
 
     # Multiply the inverse of the coefficient matrix by the array of x values to give array of alpha values
     alpha = np.matmul(cinv, xarr)
@@ -346,7 +493,7 @@ def bicubic_interpolation(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13
     n_p = 0
     for i in range(0, 4):
         for j in range(0, 4):
-            n_p = n_p + alpha[i * 4 + j] * x ** i * y ** j
+            n_p = n_p + alpha[i * 4 + j] * x**i * y**j
 
     return n_p
 
@@ -356,68 +503,68 @@ def read_ntv2_file(ntv2_gsb_file):
     Function to read an ntv2 gsb file and create grid & subgrid objects
 
     :param ntv2_gsb_file: full path to ntv2 file
-    :return: ntv2 grid object
+    :return: Ntv2 grid object
     """
 
-    with open(ntv2_gsb_file, 'rb') as f:
+    with open(ntv2_gsb_file, "rb") as f:
         # NUM_OREC
         f.seek(8, 1)
         byte = f.read(4)
-        num_orec = int.from_bytes(byte, byteorder='little')
+        num_orec = int.from_bytes(byte, byteorder="little")
 
         f.seek(4, 1)
 
         # NUM_SREC
         f.seek(8, 1)
         byte = f.read(4)
-        num_srec = int.from_bytes(byte, byteorder='little')
+        num_srec = int.from_bytes(byte, byteorder="little")
 
         f.seek(4, 1)
         # NUM_FILE
         f.seek(8, 1)
         byte = f.read(4)
-        num_file = int.from_bytes(byte, byteorder='little')
+        num_file = int.from_bytes(byte, byteorder="little")
 
         f.seek(4, 1)
         # GS_TYPE
         f.seek(8, 1)
         byte = f.read(8)
-        gs_type = byte.decode('utf8').strip('\x00').strip()
+        gs_type = byte.decode("utf8").strip("\x00").strip()
 
         # VERSION
         f.seek(8, 1)
         byte = f.read(8)
-        version = byte.decode('utf8').strip('\x00').strip()
+        version = byte.decode("utf8").strip("\x00").strip()
 
         # SYSTEM_F
         f.seek(8, 1)
         byte = f.read(8)
-        system_f = byte.decode('utf8').strip('\x00').strip()
+        system_f = byte.decode("utf8").strip("\x00").strip()
 
         # SYSTEM_T
         f.seek(8, 1)
         byte = f.read(8)
-        system_t = byte.decode('utf8').strip('\x00').strip()
+        system_t = byte.decode("utf8").strip("\x00").strip()
 
         # MAJOR_F
         f.seek(8, 1)
         byte = f.read(8)
-        major_f = struct.unpack('d', byte)[0]
+        major_f = struct.unpack("d", byte)[0]
 
         # MINOR_F
         f.seek(8, 1)
         byte = f.read(8)
-        minor_f = struct.unpack('d', byte)[0]
+        minor_f = struct.unpack("d", byte)[0]
 
         # MAJOR_T
         f.seek(8, 1)
         byte = f.read(8)
-        major_t = struct.unpack('d', byte)[0]
+        major_t = struct.unpack("d", byte)[0]
 
         # MINOR_T
         f.seek(8, 1)
         byte = f.read(8)
-        minor_t = struct.unpack('d', byte)[0]
+        minor_t = struct.unpack("d", byte)[0]
 
         grid = NTv2Grid(
             num_orec=num_orec,
@@ -431,7 +578,7 @@ def read_ntv2_file(ntv2_gsb_file):
             minor_f=minor_f,
             major_t=major_t,
             minor_t=minor_t,
-            file_path=ntv2_gsb_file
+            file_path=ntv2_gsb_file,
         )
 
         # read subgrids
@@ -439,57 +586,61 @@ def read_ntv2_file(ntv2_gsb_file):
             # SUB_NAME
             f.seek(8, 1)
             byte = f.read(8)
-            sub_name = byte.decode('utf').strip('\x00').strip()
+            sub_name = byte.decode("utf").strip("\x00").strip()
 
             # PARENT
             f.seek(8, 1)
             byte = f.read(8)
-            parent = byte.decode('utf').strip('\x00').strip()
+            parent = byte.decode("utf").strip("\x00").strip()
 
             # CREATED
             f.seek(8, 1)
             byte = f.read(8)
-            created = dt.strptime(byte.decode('utf').strip('\x00').strip(), '%d%m%Y').strftime('%d/%m/%Y')
+            created = dt.strptime(
+                byte.decode("utf").strip("\x00").strip(), "%d%m%Y"
+            ).strftime("%d/%m/%Y")
 
             # UPDATED
             f.seek(8, 1)
             byte = f.read(8)
-            updated = dt.strptime(byte.decode('utf').strip('\x00').strip(), '%d%m%Y').strftime('%d/%m/%Y')
+            updated = dt.strptime(
+                byte.decode("utf").strip("\x00").strip(), "%d%m%Y"
+            ).strftime("%d/%m/%Y")
 
             # S_LAT
             f.seek(8, 1)
             byte = f.read(8)
-            s_lat = round(struct.unpack('d', byte)[0], 3)
+            s_lat = round(struct.unpack("d", byte)[0], 3)
 
             # N_LAT
             f.seek(8, 1)
             byte = f.read(8)
-            n_lat = round(struct.unpack('d', byte)[0], 3)
+            n_lat = round(struct.unpack("d", byte)[0], 3)
 
             # E_LONG
             f.seek(8, 1)
             byte = f.read(8)
-            e_long = round(struct.unpack('d', byte)[0], 3)
+            e_long = round(struct.unpack("d", byte)[0], 3)
 
             # W_LONG
             f.seek(8, 1)
             byte = f.read(8)
-            w_long = round(struct.unpack('d', byte)[0], 3)
+            w_long = round(struct.unpack("d", byte)[0], 3)
 
             # LAT_INC
             f.seek(8, 1)
             byte = f.read(8)
-            lat_inc = round(struct.unpack('d', byte)[0], 6)
+            lat_inc = round(struct.unpack("d", byte)[0], 6)
 
             # LONG_INC
             f.seek(8, 1)
             byte = f.read(8)
-            long_inc = round(struct.unpack('d', byte)[0], 6)
+            long_inc = round(struct.unpack("d", byte)[0], 6)
 
             # GS_COUNT
             f.seek(8, 1)
             byte = f.read(4)
-            gs_count = int.from_bytes(byte, byteorder='little')
+            gs_count = int.from_bytes(byte, byteorder="little")
 
             f.seek(4, 1)
             # skip ahead to next subgrid
@@ -506,27 +657,25 @@ def read_ntv2_file(ntv2_gsb_file):
                 w_long=w_long,
                 lat_inc=lat_inc,
                 long_inc=long_inc,
-                gs_count=gs_count
+                gs_count=gs_count,
             )
 
         return grid
 
 
-def interpolate_ntv2(grid_object, lat, lon, method='bicubic'):
+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)
     :param method: interpolation strategy, bicubic or bilinear
 
-    :return: tuple of four ntv2 fields
+    :return: Tuple of four ntv2 fields
     """
 
-    interpolation_methods = {
-        'bicubic',
-        'bilinear'
-    }
+    interpolation_methods = {"bicubic", "bilinear"}
     if method not in interpolation_methods:
         raise ValueError(f'interpolation method "{method}" not supported')
 
@@ -566,17 +715,21 @@ def interpolate_ntv2(grid_object, lat, lon, method='bicubic'):
     col = int((lon - in_grid.e_long) / in_grid.long_inc)
 
     # locate data in gsb_file
-    skip_bytes = 176    # grid header length
+    skip_bytes = 176  # grid header length
 
-    with open(grid_object.file_path, 'rb') as f:
+    with open(grid_object.file_path, "rb") as f:
         for sg in grid_object.subgrids.values():
 
-            skip_bytes += 176   # subgrid header length
+            skip_bytes += 176  # subgrid header length
             if sg.sub_name == in_grid.sub_name:
-                if method == 'bilinear':
-                    results = in_grid.ntv2_bilinear(lat, lon, num_cols, row, col, f, skip_bytes)
-                elif method == 'bicubic':
-                    results = in_grid.ntv2_bicubic(lat, lon, num_cols, row, col, f, skip_bytes)
+                if method == "bilinear":
+                    results = in_grid.ntv2_bilinear(
+                        lat, lon, num_cols, row, col, f, skip_bytes
+                    )
+                elif method == "bicubic":
+                    results = in_grid.ntv2_bicubic(
+                        lat, lon, num_cols, row, col, f, skip_bytes
+                    )
             else:
                 skip_bytes += sg.gs_count * 16
 
diff --git a/geodepy/statistics.py b/geodepy/statistics.py
index d1c3ae0..7e68771 100644
--- a/geodepy/statistics.py
+++ b/geodepy/statistics.py
@@ -12,13 +12,15 @@ def rotation_matrix(lat, lon):
 
     :param lat: latitude in decimal degrees
     :param lon: longitude in decimal degrees
-    :return: rot_matrix (3x3)
+    :return: rotation matrix (3x3)
     """
     (rlat, rlon) = (radians(lat), radians(lon))
     rot_matrix = np.array(
-        [[-sin(rlon), -sin(rlat) * cos(rlon), cos(rlat) * cos(rlon)],
-         [cos(rlon), -sin(rlat) * sin(rlon), cos(rlat) * sin(rlon)],
-         [0.0, cos(rlat), sin(rlat)]]
+        [
+            [-sin(rlon), -sin(rlat) * cos(rlon), cos(rlat) * cos(rlon)],
+            [cos(rlon), -sin(rlat) * sin(rlon), cos(rlat) * sin(rlon)],
+            [0.0, cos(rlat), sin(rlat)],
+        ]
     )
     return rot_matrix
 
@@ -33,26 +35,29 @@ def vcv_cart2local(vcv_cart, lat, lon):
     :param vcv_cart: a VCV in the Cartesian reference frame (3x1 or 3x3)
     :param lat: latitude in decimal degrees
     :param lon: longitude in decimal degrees
-    :return: vcv_local (3x1 or 3x3)
+    :return: vcv array (3x1 or 3x3)
     """
     column_vector = False
     if vcv_cart.shape[0] == 3:
         if vcv_cart.shape[1] == 1:
             column_vector = True
-            vcv_cart = np.array([[vcv_cart[0, 0], 0.0, 0.0],
-                                 [0.0, vcv_cart[1, 0], 0.0],
-                                 [0.0, 0.0, vcv_cart[2, 0]]])
+            vcv_cart = np.array(
+                [
+                    [vcv_cart[0, 0], 0.0, 0.0],
+                    [0.0, vcv_cart[1, 0], 0.0],
+                    [0.0, 0.0, vcv_cart[2, 0]],
+                ]
+            )
         elif vcv_cart.shape[1] == 3:
             pass
         else:
-            raise ValueError('Matrix must be either 3x1 or 3x3')
+            raise ValueError("Matrix must be either 3x1 or 3x3")
     else:
-        raise ValueError('Matrix must be either 3x1 or 3x3')
+        raise ValueError("Matrix must be either 3x1 or 3x3")
     rot_matrix = rotation_matrix(lat, lon)
     vcv_local = rot_matrix.transpose() @ vcv_cart @ rot_matrix
     if column_vector:
-        vcv_local = np.array([[vcv_local[0, 0]], [vcv_local[1, 1]],
-                              [vcv_local[2, 2]]])
+        vcv_local = np.array([[vcv_local[0, 0]], [vcv_local[1, 1]], [vcv_local[2, 2]]])
     return vcv_local
 
 
@@ -66,26 +71,29 @@ def vcv_local2cart(vcv_local, lat, lon):
     :param vcv_local: a VCV in the local reference frame (3x1 or 3x3)
     :param lat: latitude in decimal degrees
     :param lon: longitude in decimal degrees
-    :return: vcv_cart (3x1 or 3x3)
+    :return: vcv array (3x1 or 3x3)
     """
     column_vector = False
     if vcv_local.shape[0] == 3:
         if vcv_local.shape[1] == 1:
             column_vector = True
-            vcv_local = np.array([[vcv_local[0, 0], 0.0, 0.0],
-                                 [0.0, vcv_local[1, 0], 0.0],
-                                 [0.0, 0.0, vcv_local[2, 0]]])
+            vcv_local = np.array(
+                [
+                    [vcv_local[0, 0], 0.0, 0.0],
+                    [0.0, vcv_local[1, 0], 0.0],
+                    [0.0, 0.0, vcv_local[2, 0]],
+                ]
+            )
         elif vcv_local.shape[1] == 3:
             pass
         else:
-            raise ValueError('Matrix must be either 3x1 or 3x3')
+            raise ValueError("Matrix must be either 3x1 or 3x3")
     else:
-        raise ValueError('Matrix must be either 3x1 or 3x3')
+        raise ValueError("Matrix must be either 3x1 or 3x3")
     rot_matrix = rotation_matrix(lat, lon)
     vcv_cart = rot_matrix @ vcv_local @ rot_matrix.transpose()
     if column_vector:
-        vcv_cart = np.array([[vcv_cart[0, 0]], [vcv_cart[1, 1]],
-                             [vcv_cart[2, 2]]])
+        vcv_cart = np.array([[vcv_cart[0, 0]], [vcv_cart[1, 1]], [vcv_cart[2, 2]]])
     return vcv_cart
 
 
@@ -98,13 +106,12 @@ def error_ellipse(vcv):
     :param vcv: a VCV (3x3)
     :return: a, semi-major axis
     :return: b, semi-minor axis
-    :return: orientation, the orientation of the error ellipse
+    :return: The orientation of the error ellipse
     """
-    z = sqrt((vcv[0, 0] - vcv[1, 1])**2 + 4 * vcv[0, 1]**2)
+    z = sqrt((vcv[0, 0] - vcv[1, 1]) ** 2 + 4 * vcv[0, 1] ** 2)
     a = sqrt(0.5 * (vcv[0, 0] + vcv[1, 1] + z))
     b = sqrt(0.5 * (vcv[0, 0] + vcv[1, 1] - z))
-    orientation = 90 - degrees(0.5 * atan2((2 * vcv[0, 1]),
-                                           (vcv[0, 0] - vcv[1, 1])))
+    orientation = 90 - degrees(0.5 * atan2((2 * vcv[0, 1]), (vcv[0, 0] - vcv[1, 1])))
 
     return a, b, orientation
 
@@ -114,7 +121,7 @@ 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
-        
+
     Adapted from Harvey B.R. (1998) Practical least squares and statistics for surveyors,
     Monograph 13, Section 4.4, p.135
 
@@ -136,7 +143,7 @@ def relative_error(lat, lon, var1, var2, cov12):
 
     # diagonal terms
     rel_var[0, 0] = var1_enu[0, 0] + var2_enu[0, 0] - 2 * cov12_enu[0, 0]
-    rel_var[1, 1] = var1_enu[1, 1] + var2_enu[1, 1] - 2 * cov12_enu[1, 1] 
+    rel_var[1, 1] = var1_enu[1, 1] + var2_enu[1, 1] - 2 * cov12_enu[1, 1]
     rel_var[2, 2] = var1_enu[2, 2] + var2_enu[2, 2] - 2 * cov12_enu[2, 2]
 
     # east-north covariance
@@ -166,7 +173,7 @@ def circ_hz_pu(a, b):
 
     :param a: semi-major axis
     :param b: semi-minor axis
-    :return: r the radius of the circularised error
+    :return: Radius of the circularised error
     """
     q0 = 1.960790
     q1 = 0.004071
@@ -181,19 +188,22 @@ def circ_hz_pu(a, b):
 
 def k_val95(dof):
     """
-    Returns the Coverage Factor k for a given 1 sigma (68.27%) Standard
-    Deviation to allow conversion to a 95% Standard Deviation. This
+    Returns the Coverage Factor k for a given 1 sigma (68.27%) standard
+    deviation to allow conversion to a 95% standard deviation. This
     uses a simplified table of k values rounded to 5 decimal places
     for Degrees of Freedom (DOF) in the range 1 to 120. For DOF above
     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: stats.t.ppf(1-0.025,dof)
+    for DOF = 1. Coverage Factor produced using following scipy stats:
+
+    .. code:: python 
+
+        stats.t.ppf(1-0.025,dof)
 
     :param dof: Degrees of Freedom (Number of Measurements Minus 1)
     :return: Coverage Factor k
     """
     if not isinstance(dof, int):
-        raise TypeError('Degrees of Freedom must be Int')
+        raise TypeError("Degrees of Freedom must be Int")
     if dof < 1:
         return ttable_p95[0]
     elif dof > 120:
@@ -202,23 +212,125 @@ def k_val95(dof):
         return ttable_p95[dof - 1]
 
 
-ttable_p95 = ([12.7062, 4.30265, 3.18245, 2.77645, 2.57058, 2.44691,
-              2.36462, 2.30600, 2.26216, 2.22814, 2.20099, 2.17881,
-              2.16037, 2.14479, 2.13145, 2.11991, 2.10982, 2.10092,
-              2.09302, 2.08596, 2.07961, 2.07387, 2.06866, 2.06390,
-              2.05954, 2.05553, 2.05183, 2.04841, 2.04523, 2.04227,
-              2.03951, 2.03693, 2.03452, 2.03224, 2.03011, 2.02809,
-              2.02619, 2.02439, 2.02269, 2.02108, 2.01954, 2.01808,
-              2.01669, 2.01537, 2.01410, 2.01290, 2.01174, 2.01063,
-              2.00958, 2.00856, 2.00758, 2.00665, 2.00575, 2.00488,
-              2.00404, 2.00324, 2.00247, 2.00172, 2.00100, 2.00030,
-              1.99962, 1.99897, 1.99834, 1.99773, 1.99714, 1.99656,
-              1.99601, 1.99547, 1.99495, 1.99444, 1.99394, 1.99346,
-              1.99300, 1.99254, 1.99210, 1.99167, 1.99125, 1.99085,
-              1.99045, 1.99006, 1.98969, 1.98932, 1.98896, 1.98861,
-              1.98827, 1.98793, 1.98761, 1.98729, 1.98698, 1.98667,
-              1.98638, 1.98609, 1.98580, 1.98552, 1.98525, 1.98498,
-              1.98472, 1.98447, 1.98422, 1.98397, 1.98373, 1.98350,
-              1.98326, 1.98304, 1.98282, 1.98260, 1.98238, 1.98217,
-              1.98197, 1.98177, 1.98157, 1.98137, 1.98118, 1.98099,
-              1.98081, 1.98063, 1.98045, 1.98027, 1.98010, 1.97993])
+ttable_p95 = [
+    12.7062,
+    4.30265,
+    3.18245,
+    2.77645,
+    2.57058,
+    2.44691,
+    2.36462,
+    2.30600,
+    2.26216,
+    2.22814,
+    2.20099,
+    2.17881,
+    2.16037,
+    2.14479,
+    2.13145,
+    2.11991,
+    2.10982,
+    2.10092,
+    2.09302,
+    2.08596,
+    2.07961,
+    2.07387,
+    2.06866,
+    2.06390,
+    2.05954,
+    2.05553,
+    2.05183,
+    2.04841,
+    2.04523,
+    2.04227,
+    2.03951,
+    2.03693,
+    2.03452,
+    2.03224,
+    2.03011,
+    2.02809,
+    2.02619,
+    2.02439,
+    2.02269,
+    2.02108,
+    2.01954,
+    2.01808,
+    2.01669,
+    2.01537,
+    2.01410,
+    2.01290,
+    2.01174,
+    2.01063,
+    2.00958,
+    2.00856,
+    2.00758,
+    2.00665,
+    2.00575,
+    2.00488,
+    2.00404,
+    2.00324,
+    2.00247,
+    2.00172,
+    2.00100,
+    2.00030,
+    1.99962,
+    1.99897,
+    1.99834,
+    1.99773,
+    1.99714,
+    1.99656,
+    1.99601,
+    1.99547,
+    1.99495,
+    1.99444,
+    1.99394,
+    1.99346,
+    1.99300,
+    1.99254,
+    1.99210,
+    1.99167,
+    1.99125,
+    1.99085,
+    1.99045,
+    1.99006,
+    1.98969,
+    1.98932,
+    1.98896,
+    1.98861,
+    1.98827,
+    1.98793,
+    1.98761,
+    1.98729,
+    1.98698,
+    1.98667,
+    1.98638,
+    1.98609,
+    1.98580,
+    1.98552,
+    1.98525,
+    1.98498,
+    1.98472,
+    1.98447,
+    1.98422,
+    1.98397,
+    1.98373,
+    1.98350,
+    1.98326,
+    1.98304,
+    1.98282,
+    1.98260,
+    1.98238,
+    1.98217,
+    1.98197,
+    1.98177,
+    1.98157,
+    1.98137,
+    1.98118,
+    1.98099,
+    1.98081,
+    1.98063,
+    1.98045,
+    1.98027,
+    1.98010,
+    1.97993,
+]
diff --git a/geodepy/survey.py b/geodepy/survey.py
index 0dad709..155a63e 100644
--- a/geodepy/survey.py
+++ b/geodepy/survey.py
@@ -14,67 +14,83 @@ def first_vel_params(wavelength, frequency, n_REF=None, unit_length=None):
     """
     Calculates the constant First Velocity Correction Parameters C and D
     for a given set of standard instrument settings
+
+    Reference Rueger, J.M., 2012, Electronic Distance Measurement: An Introduction, 4rd edition, Springer, Berlin
+
     :param wavelength: Instrument Carrier Wavelength (Micrometers) - Mandatory
     :param frequency: Instrument modulation frequency (Hz) - Optional
     :param n_REF: manufacturers reference refractive index - Recommended
     :param unit_length: unit length of instrument - Optional
     :return: First Velocity Correction Parameters C and D
-    Reference Rueger, J.M., 2012, Electronic Distance Measurement – An Introduction, 4rd edition, Springer, Berlin
+
     """
-    
-    if not n_REF :
+
+    if not n_REF:
         if not unit_length:
-            raise ValueError('Error - n_REF and unit_length cannot both be None')
+            raise ValueError("Error - n_REF and unit_length cannot both be None")
         if not frequency:
-            raise ValueError('Error - n_REF and frequency cannot both be None')
+            raise ValueError("Error - n_REF and frequency cannot both be None")
         # Rueger eq 6.3
         n_REF = 299792458 / (2 * unit_length * frequency)
-    
+
     # Rueger eq 6.12
-    param_c = (n_REF-1)*10**6
-    
+    param_c = (n_REF - 1) * 10**6
+
     # Rueger eq 5.12
     # https://office.iag-aig.org/doc/5d7b8fda0c032.pdf Resolution 3
-    nG_1_10_6 = 287.6155 + (4.8866 / wavelength ** 2) + (0.068 / wavelength ** 4)
+    nG_1_10_6 = 287.6155 + (4.8866 / wavelength**2) + (0.068 / wavelength**4)
     # Rueger eq 6.13
     param_d = (273.15 / 1013.25) * nG_1_10_6
-    
+
     return param_c, param_d
 
 
 def part_h2o_vap_press(dry_temp, pressure, rel_humidity=None, wet_temp=None):
     """
+    Reference Rueger, J.M., 2012, Electronic Distance Measurement: An Introduction, 4rd edition, Springer, Berlin
+
     :param dry_temp: Observed Dry Temperature (degrees Celsius)
     :param pressure: Observed Pressure (hectopascals or millibars)
     :param rel_humidity: Observed Relative Humidity (percentage) - Optional if wet_temp supplied
     :param wet_temp: Observed Wet Temperature (degrees Celsius) - Optional if rel_humidity supplied
-    Reference Rueger, J.M., 2012, Electronic Distance Measurement – An Introduction, 4rd edition, Springer, Berlin
+
     """
-    
+
     if not rel_humidity and not wet_temp:
-        raise ValueError('Error - rel_humidity and wet_temp cannot both be None')
-                         
+        raise ValueError("Error - rel_humidity and wet_temp cannot both be None")
+
     if rel_humidity:
         wet_temp = dry_temp
     # Rueger eq 5.27
-    E_w = ((1.0007 + ((3.46 * pressure) * (10**-6)))
-         * 6.1121 * exp((17.502 * wet_temp) / (240.94 + wet_temp)))
-    
+    E_w = (
+        (1.0007 + ((3.46 * pressure) * (10**-6)))
+        * 6.1121
+        * exp((17.502 * wet_temp) / (240.94 + wet_temp))
+    )
+
     if rel_humidity:
         # Rueger eq 5.29
-        e = (E_w*rel_humidity)/100
+        e = (E_w * rel_humidity) / 100
     else:
         e = E_w - 0.000662 * pressure * (dry_temp - wet_temp)
-    
+
     return e
-    
 
-def first_vel_corrn(dist, first_vel_param, temp, pressure,
-                    rel_humidity=None, wet_temp=None, CO2_ppm=None, 
-                    wavelength=None):
+
+def first_vel_corrn(
+    dist,
+    first_vel_param,
+    temp,
+    pressure,
+    rel_humidity=None,
+    wet_temp=None,
+    CO2_ppm=None,
+    wavelength=None,
+):
     """
     Carries out First Velocity Correction of Electronic Distance Measurement,
     given correction parameters and atmospheric observations
+
     :param dist: Uncorrected Observed Slope Distance
     :param first_vel_param: Tuple of First Velocity Parameters C and D (see function first_vel_params)
     :param temp: Observed Temperature (degrees Celsius)
@@ -83,58 +99,56 @@ def first_vel_corrn(dist, first_vel_param, temp, pressure,
     :return: Slope Distance with First Velocity Correction applied
     """
     param_c = first_vel_param[0]
-    if not CO2_ppm:    
+    if not CO2_ppm:
         param_d = first_vel_param[1]
         e = part_h2o_vap_press(temp, pressure, rel_humidity, wet_temp)
-        
+
         # Rueger eq 6.11
-        t_273_15 = temp+273.15
-        first_vel_corrn_ppm = (param_c-
-                               ((param_d*pressure)/t_273_15)+
-                               ((11.27*e)/t_273_15))
-        first_vel_corrn_metres = dist * first_vel_corrn_ppm * (10 ** -6)
-        
+        t_273_15 = temp + 273.15
+        first_vel_corrn_ppm = (
+            param_c - ((param_d * pressure) / t_273_15) + ((11.27 * e) / t_273_15)
+        )
+        first_vel_corrn_metres = dist * first_vel_corrn_ppm * (10**-6)
+
     else:
         if all([temp, pressure, rel_humidity, wavelength]):
             e = humidity2part_water_vapour_press(rel_humidity, temp)
-            NPROPG_1 = group_refractivity(
-                wavelength, temp, pressure, e, CO2_ppm)
+            NPROPG_1 = group_refractivity(wavelength, temp, pressure, e, CO2_ppm)
         else:
-            raise ValueError('Error - temp, pressure, rel_humidity and wavelength '+
-                             'are all mandatory when CO2_ppm is not None')
-        
+            raise ValueError(
+                "Error - temp, pressure, rel_humidity and wavelength "
+                + "are all mandatory when CO2_ppm is not None"
+            )
+
         n_ref = 1 + (param_c / 1.0e6)
         n_g = 1 + (NPROPG_1 / 1.0e8)
-        first_vel_corrn_metres = ((n_ref / n_g)-1) * dist
-        
+        first_vel_corrn_metres = ((n_ref / n_g) - 1) * dist
+
     return first_vel_corrn_metres
 
 
-def mets_partial_differentials(group_ref_Index=1.00028, 
-                               temp=15, 
-                               pressure=1013.25,
-                               rel_humidity=60):
-    """ Returns the sensitivity coefficients for temp, pressure and humidity in ppm
+def mets_partial_differentials(
+    group_ref_Index=1.00028, temp=15, pressure=1013.25, rel_humidity=60
+):
+    """
+    Calculates the sensitivity coefficients for temp, pressure and humidity in ppm
+
     :param group_ref_Index: manufacturers group refractive index of light
     :param temp: Observed Dry Temperature (degrees Celsius)
     :param pressure: Observed Pressure (hectopascals or millibars)
     :param rel_humidity: Observed Relative Humidity (percentage) - Optional if wet_temp supplied
+    :return: Sensitivity Coefficients K, L and M in ppm
     """
     ng_1 = group_ref_Index - 1
     t_273_15 = temp + 273.15
     e = part_h2o_vap_press(temp, pressure, rel_humidity)
-    
-    param_k = (((((ng_1 * 273.15 * pressure)
-                  /1013.25)
-                 -(11.27 * e * 10**-6))
-                /t_273_15**2)
-               *(10**6))
-    param_l = (0.26957809 * (ng_1 / t_273_15)
-               *(10**6))
-    param_m = (((11.27 * 10**-6)
-               /t_273_15)
-               *(10**6))
-    
+
+    param_k = (
+        (((ng_1 * 273.15 * pressure) / 1013.25) - (11.27 * e * 10**-6)) / t_273_15**2
+    ) * (10**6)
+    param_l = 0.26957809 * (ng_1 / t_273_15) * (10**6)
+    param_m = ((11.27 * 10**-6) / t_273_15) * (10**6)
+
     return param_k, param_l, param_m
 
 
@@ -143,13 +157,14 @@ 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
     :return: Instrument Height above reference mark and its standard deviation
     """
     if len(vert_list) < 3:
-        raise ValueError('ValueError: 3 or more vertical angles required')
+        raise ValueError("ValueError: 3 or more vertical angles required")
     vert_list.sort(reverse=True)
     vert_pairs = [(va1, va2) for va1, va2 in zip(vert_list, vert_list[1:])]
     base_ht = []
@@ -164,10 +179,30 @@ def precise_inst_ht(vert_list, spacing, offset):
 
 
 def joins(east1, north1, east2, north2):
+    """
+    Calculates the bearing and distance from point 1 to point 2
+
+    :param east1: Easting of Point 1
+    :param north1: Northing of Point 1
+    :param east2: Easting of Point 2
+    :param north2: Northing of Point 2
+    :return: Distance and Bearing from Point 1 to Point 2
+    """
     return rect2polar(east2 - east1, north2 - north1)
 
 
 def radiations(east1, north1, brg1to2, dist, rotation=0, psf=1):
+    """
+    Calculates the coordinates of Point 2 given Point 1, bearing and distance
+
+    :param east1: Easting of Point 1
+    :param north1: Northing of Point 1
+    :param brg1to2: Bearing from Point 1 to Point 2 (decimal degrees)
+    :param dist: Distance from Point 1 to Point 2 (metres)
+    :param rotation: Rotation to be applied to bearing (decimal degrees) - Optional
+    :param psf: Prism Scale Factor to be applied to distance - Optional
+    :return: Easting and Northing of Point 2
+    """
     delta_east, delta_north = polar2rect(dist * psf, brg1to2 + rotation)
     return east1 + delta_east, north1 + delta_north
 
@@ -185,11 +220,11 @@ 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: vert_angle_pt: Vertical Angle between Ground Points, expressed
-                            in decimal degrees
-    :return: slope_dist_pt: Slope Distance between Ground Points in metres
-    :return: hz_dist:       Horizontal Distance
-    :return: delta_ht:      Change in height between Ground Points in metres
+    :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
+        - delta_ht - Change in height between Ground Points in metres
     """
     # Convert Zenith Angle to Vertical Angle
     try:
@@ -202,17 +237,18 @@ def va_conv(zenith_angle, slope_dist, height_inst=0, height_tgt=0):
         else:
             raise ValueError
     except ValueError:
-        raise ValueError('ValueError: Vertical Angle Invalid')
+        raise ValueError("ValueError: Vertical Angle Invalid")
     # Calculate Horizontal Dist and Delta Height
     hz_dist = slope_dist * cos(zenith_angle)
     delta_ht = slope_dist * sin(zenith_angle)
     # Account for Target and Instrument Heights
     delta_ht = height_inst + delta_ht - height_tgt
-    slope_dist_pt = sqrt(delta_ht ** 2 + hz_dist ** 2)
+    slope_dist_pt = sqrt(delta_ht**2 + hz_dist**2)
     vert_angle_pt = atan(delta_ht / hz_dist)
     vert_angle_pt = degrees(vert_angle_pt)
     return vert_angle_pt, slope_dist_pt, hz_dist, delta_ht
 
+
 """
 The following has been translated from UNSW FORTRAN code
 """
@@ -295,6 +331,9 @@ def va_conv(zenith_angle, slope_dist, height_inst=0, height_tgt=0):
 
 
 def refractivity_constants():
+    """
+    :return: Refractivity constants used in the refractivity calculations.
+    """
     # PECK & REEDER (1972) AS AMMENDED BY CIDDOR
     # (DRY AIR REFRACTIVITY)
     (K0, K1, K2, K3) = (238.0185, 5792105.0, 57.362, 167917.0)
@@ -307,8 +346,16 @@ def refractivity_constants():
 
     # COMPRESSIBILITY (DAVIES 1992)
     (A0, A1, A2, B0, B1, C0, C1, DLC, E) = (
-        1.58123e-6, -2.9331e-8, 1.1043e-10, 5.707e-6, -2.051e-8,
-        1.9898e-4, -2.376e-6, 1.83e-11, -0.765e-8)
+        1.58123e-6,
+        -2.9331e-8,
+        1.1043e-10,
+        5.707e-6,
+        -2.051e-8,
+        1.9898e-4,
+        -2.376e-6,
+        1.83e-11,
+        -0.765e-8,
+    )
 
     # CIDDOR 1995 AND DAVIES 1992.  NEW CF ON 28/06/95
     (CF, R, MV) = (1.022, 8.314510, 0.018015)
@@ -316,41 +363,46 @@ def refractivity_constants():
     # STANDARD CONDITION DRY AIR (PECK & REEDER 1972)
     (TCSTDAIR, TKSTDAIR, PSTDAIR) = (15.0, 288.15, 101325.0)
     (TCSTDWV, TKSTDWV, PSTDWV) = (20.0, 293.15, 1333.0)
-    
-    return ((K0, K1, K2, K3),
-            (W0, W1, W2, W3),
-            (ALPHA, BETA, GAMMA),
-            (A0, A1, A2, B0, B1, C0, C1, DLC, E),
-            (CF, R, MV),
-            (TCSTDAIR, TKSTDAIR, PSTDAIR),
-            (TCSTDWV, TKSTDWV, PSTDWV))
-    
+
+    return (
+        (K0, K1, K2, K3),
+        (W0, W1, W2, W3),
+        (ALPHA, BETA, GAMMA),
+        (A0, A1, A2, B0, B1, C0, C1, DLC, E),
+        (CF, R, MV),
+        (TCSTDAIR, TKSTDAIR, PSTDAIR),
+        (TCSTDWV, TKSTDWV, PSTDWV),
+    )
+
 
 def phase_refractivity(LAMDA, TC, P, PV, XC=420):
     """
-    Input
-        LAMDA = wavelength (micrometre)
-        TC = temperature (degrees Celcius)
-        P = pressure (hPa)
-        PV = partial water vapour pressure (Pa)
-        XC = carbon dioxide content (ppm)
-    Return
-        NPROPP_1 = phase refractivity = (NPROPphase-1)10E8
-    """
-    
-    ((K0, K1, K2, K3),
-    (W0, W1, W2, W3),
-    (ALPHA, BETA, GAMMA),
-    (A0, A1, A2, B0, B1, C0, C1, DLC, E),
-    (CF, R, MV),
-    (TCSTDAIR, TKSTDAIR, PSTDAIR),
-    (TCSTDWV, TKSTDWV, PSTDWV)) = refractivity_constants()
+    Calculates the phase refractivity of moist air using Ciddor's equations
+
+    :param LAMDA: wavelength (micrometre)
+    :param TC: temperature (degrees Celcius)
+    :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
+    """
+
+    (
+        (K0, K1, K2, K3),
+        (W0, W1, W2, W3),
+        (ALPHA, BETA, GAMMA),
+        (A0, A1, A2, B0, B1, C0, C1, DLC, E),
+        (CF, R, MV),
+        (TCSTDAIR, TKSTDAIR, PSTDAIR),
+        (TCSTDWV, TKSTDWV, PSTDWV),
+    ) = refractivity_constants()
+
     # CONVERT LAMDA TO SIGMA, THE PRESSURE UNITS TO PASCAL AND CREATE TC AND PP
     SIGMA = 1.0 / LAMDA
 
     # CONVERSION FROM hPa TO Pa AND C TO K
-    P  = P * 100.0
+    P = P * 100.0
     PV = PV * 100.0
     TK = TC + 273.15
 
@@ -358,14 +410,12 @@ def phase_refractivity(LAMDA, TC, P, PV, XC=420):
     TEMP1 = SIGMA * SIGMA
 
     # CIDDOR EQ.(1)
-    NAS_1   = (K1 / (K0 - TEMP1)) + (K3 / (K2 - TEMP1))
+    NAS_1 = (K1 / (K0 - TEMP1)) + (K3 / (K2 - TEMP1))
 
     # CIDDOR EQ.(2) FOR AMBIENT C02 CONTENT (XC)
     NASX_1 = NAS_1 * (1 + 0.534e-6 * (XC - 450.0))
-    STD_AIR = {
-            '(Nas-1)10E8': NAS_1,
-            '(Nasx-1)10E8':NASX_1}
-    
+    STD_AIR = {"(Nas-1)10E8": NAS_1, "(Nasx-1)10E8": NASX_1}
+
     # USING EQ. 2, CALCULATE REFRACTIVITY OF WATER VAPOUR AT STANDARD CONDITIONS
     # (TC=20, P=1333)
     TEMP2 = TEMP1 * TEMP1
@@ -373,112 +423,120 @@ def phase_refractivity(LAMDA, TC, P, PV, XC=420):
 
     # FOLLOWING OWENS (1967) AS AMENDED TO FIT BIRCH & DOWNS (1988)
     NWS_1 = CF * (W0 + W1 * TEMP1 + W2 * TEMP2 + W3 * TEMP3)
-    STD_WATER_VAPOUR = {
-            '(Nws-1)10E8': NWS_1}
-    
+    STD_WATER_VAPOUR = {"(Nws-1)10E8": NWS_1}
+
     # CALCULATE THE DENSITY OF STANDARD AIR (XV=0, TC=15, P=101325)
     # EQ.(2) DAVIS (1992) XC = MOLECULAR FRACTION OF C02
     # XC IN CIDDOR'S FORMULA IS IN PPM, CONVERTED TO A FRACTION
-    MA  = (28.9635 + 12.011e-6 * (XC - 400.0)) * 1.0e-3
+    MA = (28.9635 + 12.011e-6 * (XC - 400.0)) * 1.0e-3
 
     # USING CIDDOR EQ.(A1) WITH XV = 0 : DRY AIR COMPRESSIBILITY
-    ZA = (1.0 - (PSTDAIR / TKSTDAIR) * (A0 + (A1 * TCSTDAIR) +
-         (A2 * TCSTDAIR * TCSTDAIR)) + ((PSTDAIR / TKSTDAIR) *
-         (PSTDAIR / TKSTDAIR) * DLC))
+    ZA = (
+        1.0
+        - (PSTDAIR / TKSTDAIR) * (A0 + (A1 * TCSTDAIR) + (A2 * TCSTDAIR * TCSTDAIR))
+        + ((PSTDAIR / TKSTDAIR) * (PSTDAIR / TKSTDAIR) * DLC)
+    )
 
     # USING EQ. 3 FOR DRY AIR
     RHOASX = (PSTDAIR * MA) / (ZA * R * TKSTDAIR)
-    DENSITY_OF_STD_AIR = {
-            'Ma': MA,
-            'Z_(DRY AIR)': ZA,
-            'RHOasx': RHOASX}
-    
+    DENSITY_OF_STD_AIR = {"Ma": MA, "Z_(DRY AIR)": ZA, "RHOasx": RHOASX}
+
     # CALCULATE THE DENSITY OF WATER VAPOUR AT STANDARD CONDITIONS
     # (XV=1, TC=20, P=1333)
 
     # USING CIDDOR EQUATION A1 WITH XV = 1 AND PARTIAL
     # WATER VAPOUR PRESSURE
-    ZWV = (1.0 - (PSTDWV / TKSTDWV) * (A0 + (A1 * TCSTDWV) +
-          (A2 * TCSTDWV * TCSTDWV) + (B0 + B1 * TCSTDWV) +
-          (C0 + C1 * TCSTDWV)) + ((PSTDWV / TKSTDWV) *
-          (PSTDWV / TKSTDWV) * (DLC + E)))
+    ZWV = (
+        1.0
+        - (PSTDWV / TKSTDWV)
+        * (
+            A0
+            + (A1 * TCSTDWV)
+            + (A2 * TCSTDWV * TCSTDWV)
+            + (B0 + B1 * TCSTDWV)
+            + (C0 + C1 * TCSTDWV)
+        )
+        + ((PSTDWV / TKSTDWV) * (PSTDWV / TKSTDWV) * (DLC + E))
+    )
 
     # USING EQ. 3
     RHOWS = (PSTDWV * MV) / (ZWV * R * TKSTDWV)
 
-    DENSITY_OF_STD_WATER_VAPOUR = {
-            'Z_(WATER VAPOUR)': ZWV,
-            'RHOws':RHOWS}
-    
+    DENSITY_OF_STD_WATER_VAPOUR = {"Z_(WATER VAPOUR)": ZWV, "RHOws": RHOWS}
+
     # CALCULATE THE DENSITY OF DRY AMBIENT AIR (TC= USER, P=USER)
     F = ALPHA + (BETA * P) + (GAMMA * TC * TC)
     XV = F * PV / P
 
     # USING CIDDOR EQUATION A1
-    Z = (1.0 - (P / TK) * (A0 + (A1 * TC) + (A2 * TC * TC) +
-        ((B0 + B1 * TC) * XV) + ((C0 + C1 * TC) * XV * XV)) +
-        ((P / TK) * (P / TK) * (DLC + (E * XV * XV))))
+    Z = (
+        1.0
+        - (P / TK)
+        * (
+            A0
+            + (A1 * TC)
+            + (A2 * TC * TC)
+            + ((B0 + B1 * TC) * XV)
+            + ((C0 + C1 * TC) * XV * XV)
+        )
+        + ((P / TK) * (P / TK) * (DLC + (E * XV * XV)))
+    )
 
     RHOA = (P * MA * (1.0 - XV)) / (Z * R * TK)
 
-    DENSITY_OF_DRY_AMBIENT_AIR = {
-            'f': F,
-            'Xv': XV,
-            'Z_(AMB. AIR)': Z,
-            'RHOa':RHOA}
-    
+    DENSITY_OF_DRY_AMBIENT_AIR = {"f": F, "Xv": XV, "Z_(AMB. AIR)": Z, "RHOa": RHOA}
+
     # CALCULATE THE DENSITY OF AMBIENT WATER VAPOUR
     # USING EQ. 3
     RHOW = (P * MV * XV) / (Z * R * TK)
-    
+
     # CALCULATE THE PHASE REFRACTIVITY OF MOIST AIR FROM CIDDOR EQ.(4)
     TEMP1 = RHOA / RHOASX
     TEMP2 = RHOW / RHOWS
 
-    DENSITY_OF_AMBIENT_WATER_VAPOUR = {
-        'RHOw' : RHOW,
-        'Da' : TEMP1,
-        'Dv' : TEMP2}
-    
+    DENSITY_OF_AMBIENT_WATER_VAPOUR = {"RHOw": RHOW, "Da": TEMP1, "Dv": TEMP2}
+
     TEMP1 = TEMP1 * NASX_1
     TEMP2 = TEMP2 * NWS_1
-    
-    DENSITY_OF_AMBIENT_WATER_VAPOUR['DaNasx'] = TEMP1
-    DENSITY_OF_AMBIENT_WATER_VAPOUR['DvNvs'] = TEMP2
-        
+
+    DENSITY_OF_AMBIENT_WATER_VAPOUR["DaNasx"] = TEMP1
+    DENSITY_OF_AMBIENT_WATER_VAPOUR["DvNvs"] = TEMP2
+
     NPROPP_1 = TEMP1 + TEMP2
-    
-    REFRACTIVITY_OF_MOIST_AIR = {
-            '(NpropP-1)10E8': NPROPP_1}
-    
+
+    REFRACTIVITY_OF_MOIST_AIR = {"(NpropP-1)10E8": NPROPP_1}
+
     return NPROPP_1
 
 
 def group_refractivity(LAMDA, TC, P, PV, XC=420):
     """
-    Input
-        LAMDA = wavelength (micrometre)
-        TC = temperature (degrees Celcius)
-        P = pressure (hPa)
-        PV = partial water vapour pressure (Pa)
-        XC = carbon dioxide content (ppm)
-    Return
-        NPROPG_1 = group refractivity = (NPROPgroup-1)10E8
-    """
+    Calculates the group refractivity of moist air using Ciddor's equations
+
+    :param LAMDA: wavelength (micrometre)
+    :param TC: temperature (degrees Celcius)
+    :param P: pressure (hPa)
+    :param PV: partial water vapour pressure (Pa)
+    :param XC: carbon dioxide content (ppm)
     
-    ((K0, K1, K2, K3),
-    (W0, W1, W2, W3),
-    (ALPHA, BETA, GAMMA),
-    (A0, A1, A2, B0, B1, C0, C1, DLC, E),
-    (CF, R, MV),
-    (TCSTDAIR, TKSTDAIR, PSTDAIR),
-    (TCSTDWV, TKSTDWV, PSTDWV)) = refractivity_constants()
+    :return: NPROPG_1 - group refractivity = (NPROPgroup-1)10E8
+    """
+
+    (
+        (K0, K1, K2, K3),
+        (W0, W1, W2, W3),
+        (ALPHA, BETA, GAMMA),
+        (A0, A1, A2, B0, B1, C0, C1, DLC, E),
+        (CF, R, MV),
+        (TCSTDAIR, TKSTDAIR, PSTDAIR),
+        (TCSTDWV, TKSTDWV, PSTDWV),
+    ) = refractivity_constants()
 
     # CONVERT LAMDA TO SIGMA, THE PRESSURE UNITS TO PASCAL AND CREATE TC AND PP
     SIGMA = 1.0 / LAMDA
 
     # CONVERSION FROM hPa TO Pa AND C TO K
-    P  = P * 100.0
+    P = P * 100.0
     PV = PV * 100.0
     TK = TC + 273.15
 
@@ -486,14 +544,13 @@ def group_refractivity(LAMDA, TC, P, PV, XC=420):
     TEMP1 = SIGMA * SIGMA
 
     # CIDDOR EQ.(9)
-    NGAS_1 = (K1 * ((K0 + TEMP1) / ((K0 - TEMP1) * (K0 - TEMP1))) +
-              K3 * ((K2 + TEMP1) / ((K2 - TEMP1) * (K2 - TEMP1))))
+    NGAS_1 = K1 * ((K0 + TEMP1) / ((K0 - TEMP1) * (K0 - TEMP1))) + K3 * (
+        (K2 + TEMP1) / ((K2 - TEMP1) * (K2 - TEMP1))
+    )
 
     # CIDDOR EQ.(2) FOR AMBIENT C02 CONTENT (XC)
-    NGASX_1  = NGAS_1 * (1 + 0.534e-6 * (XC - 450.0))
-    STD_AIR = {
-            '(Ngas-1)10E8': NGAS_1,
-            '(Ngasx-1)10E8':NGASX_1}
+    NGASX_1 = NGAS_1 * (1 + 0.534e-6 * (XC - 450.0))
+    STD_AIR = {"(Ngas-1)10E8": NGAS_1, "(Ngasx-1)10E8": NGASX_1}
 
     # USING EQ. 2, CALCULATE REFRACTIVITY OF WATER VAPOUR AT STANDARD CONDITIONS
     # (TC=20, P=1333)
@@ -501,62 +558,70 @@ def group_refractivity(LAMDA, TC, P, PV, XC=420):
     TEMP3 = TEMP1 * TEMP2
 
     # FOLLOWING OWENS (1967) AS AMENDED TO FIT BIRCH & DOWNS (1988)
-    NGWS_1 = (CF * (W0 + 3.0 * W1 * TEMP1 + 5.0 * W2 * TEMP2 +
-                    7.0 * W3 * TEMP3))
-    STD_WATER_VAPOUR = {
-            '(Ngws-1)10E8': NGWS_1}
-    
+    NGWS_1 = CF * (W0 + 3.0 * W1 * TEMP1 + 5.0 * W2 * TEMP2 + 7.0 * W3 * TEMP3)
+    STD_WATER_VAPOUR = {"(Ngws-1)10E8": NGWS_1}
+
     # CALCULATE THE DENSITY OF STANDARD AIR (XV=0, TC=15, P=101325)
     # EQ.(2) DAVIS (1992) XC = MOLECULAR FRACTION OF C02
     # XC IN CIDDOR'S FORMULA IS IN PPM, CONVERTED TO A FRACTION
-    MA  = (28.9635 + 12.011e-6 * (XC - 400.0)) * 1.0e-3
+    MA = (28.9635 + 12.011e-6 * (XC - 400.0)) * 1.0e-3
 
     # USING CIDDOR EQ.(A1) WITH XV = 0 : DRY AIR COMPRESSIBILITY
-    ZA = (1.0 - (PSTDAIR / TKSTDAIR) * (A0 + (A1 * TCSTDAIR) +
-         (A2 * TCSTDAIR * TCSTDAIR)) + ((PSTDAIR / TKSTDAIR) *
-         (PSTDAIR / TKSTDAIR) * DLC))
+    ZA = (
+        1.0
+        - (PSTDAIR / TKSTDAIR) * (A0 + (A1 * TCSTDAIR) + (A2 * TCSTDAIR * TCSTDAIR))
+        + ((PSTDAIR / TKSTDAIR) * (PSTDAIR / TKSTDAIR) * DLC)
+    )
 
     # USING EQ. 3 FOR DRY AIR
     RHOASX = (PSTDAIR * MA) / (ZA * R * TKSTDAIR)
-    DENSITY_OF_STD_AIR = {
-            'Ma': MA,
-            'Z_(DRY AIR)': ZA,
-            'RHOasx': RHOASX}
+    DENSITY_OF_STD_AIR = {"Ma": MA, "Z_(DRY AIR)": ZA, "RHOasx": RHOASX}
 
     # CALCULATE THE DENSITY OF WATER VAPOUR AT STANDARD CONDITIONS
     # (XV=1, TC=20, P=1333)
-    
+
     # USING CIDDOR EQUATION A1 WITH XV = 1 AND PARTIAL
     # WATER VAPOUR PRESSURE
-    ZWV = (1.0 - (PSTDWV / TKSTDWV) * (A0 + (A1 * TCSTDWV) +
-          (A2 * TCSTDWV * TCSTDWV) + (B0 + B1 * TCSTDWV) +
-          (C0 + C1 * TCSTDWV)) + ((PSTDWV / TKSTDWV) *
-          (PSTDWV / TKSTDWV) * (DLC + E)))
-                                  
+    ZWV = (
+        1.0
+        - (PSTDWV / TKSTDWV)
+        * (
+            A0
+            + (A1 * TCSTDWV)
+            + (A2 * TCSTDWV * TCSTDWV)
+            + (B0 + B1 * TCSTDWV)
+            + (C0 + C1 * TCSTDWV)
+        )
+        + ((PSTDWV / TKSTDWV) * (PSTDWV / TKSTDWV) * (DLC + E))
+    )
+
     # USING EQ. 3
     RHOWS = (PSTDWV * MV) / (ZWV * R * TKSTDWV)
 
-    DENSITY_OF_STD_WATER_VAPOUR = {
-            'Z_(WATER VAPOUR)': ZWV,
-            'RHOws':RHOWS}
+    DENSITY_OF_STD_WATER_VAPOUR = {"Z_(WATER VAPOUR)": ZWV, "RHOws": RHOWS}
 
     # CALCULATE THE DENSITY OF DRY AMBIENT AIR (TC= USER, P=USER)
     F = ALPHA + (BETA * P) + (GAMMA * TC * TC)
     XV = F * PV / P
 
     # USING CIDDOR EQUATION A1
-    Z = (1.0 - (P / TK) * (A0 + (A1 * TC) + (A2 * TC * TC) +
-        ((B0 + B1 * TC) * XV) + ((C0 + C1 * TC) * XV * XV)) +
-        ((P / TK) * (P / TK) * (DLC + (E * XV * XV))))
+    Z = (
+        1.0
+        - (P / TK)
+        * (
+            A0
+            + (A1 * TC)
+            + (A2 * TC * TC)
+            + ((B0 + B1 * TC) * XV)
+            + ((C0 + C1 * TC) * XV * XV)
+        )
+        + ((P / TK) * (P / TK) * (DLC + (E * XV * XV)))
+    )
 
     # USING EQ. 3
     RHOA = (P * MA * (1.0 - XV)) / (Z * R * TK)
 
-    DENSITY_OF_DRY_AMBIENT_AIR = {
-            'f': F,
-            'Xv': XV,
-            'Z_(AMB. AIR)': Z,
-            'RHOa':RHOA}
+    DENSITY_OF_DRY_AMBIENT_AIR = {"f": F, "Xv": XV, "Z_(AMB. AIR)": Z, "RHOa": RHOA}
 
     # CALCULATE THE DENSITY OF AMBIENT WATER VAPOUR
     # USING EQ. 3
@@ -566,42 +631,38 @@ def group_refractivity(LAMDA, TC, P, PV, XC=420):
     TEMP1 = RHOA / RHOASX
     TEMP2 = RHOW / RHOWS
 
-    DENSITY_OF_AMBIENT_WATER_VAPOUR = {
-        'RHOw' : RHOW,
-        'Da' : TEMP1,
-        'Dv' : TEMP2}
-    
+    DENSITY_OF_AMBIENT_WATER_VAPOUR = {"RHOw": RHOW, "Da": TEMP1, "Dv": TEMP2}
+
     TEMP1 = TEMP1 * NGASX_1
     TEMP2 = TEMP2 * NGWS_1
 
-    DENSITY_OF_AMBIENT_WATER_VAPOUR['DaNgasx'] = TEMP1
-    DENSITY_OF_AMBIENT_WATER_VAPOUR['DvNgvs'] = TEMP2
+    DENSITY_OF_AMBIENT_WATER_VAPOUR["DaNgasx"] = TEMP1
+    DENSITY_OF_AMBIENT_WATER_VAPOUR["DvNgvs"] = TEMP2
 
     NPROPG_1 = TEMP1 + TEMP2
-    
-    REFRACTIVITY_OF_MOIST_AIR = {
-            '(NpropG-1)10E8': NPROPG_1}
-      
+
+    REFRACTIVITY_OF_MOIST_AIR = {"(NpropG-1)10E8": NPROPG_1}
+
     return NPROPG_1
-      
-    
+
+
 def humidity2part_water_vapour_press(H, TC):
     """
-    Input
-        H = humidity (%)
-        TC = temperature (degrees Celcius)
-    Return
-        PV = partial water vapour pressure (Pa)
-    """
+    Calculates the partial water vapour pressure from relative humidity and temperature
+
+    :param H: humidity (%)
+    :param TC: temperature (degrees Celcius)
     
-    (A, B, C, D) = (1.2378847e-5, -1.9121316e-2,
-                    33.93711047, -6.3431645e3)
+    :return: PV - partial water vapour pressure (Pa)
+    """
+
+    (A, B, C, D) = (1.2378847e-5, -1.9121316e-2, 33.93711047, -6.3431645e3)
     TK = TC + 273.15
-    
+
     # NOW CONVERT THE RELATIVE HUMIDITY TO PATIAL WATER VAPOUR PRESSURE (hPa)
     # SEE EQ.(22) GIACOMO 1982
     SVP = exp(A * TK * TK + B * TK + C + D / TK)
-    PV  = (H / 100.0) * SVP
+    PV = (H / 100.0) * SVP
     PV = PV / 100.0
 
-    return PV
\ No newline at end of file
+    return PV
diff --git a/geodepy/tests/test_angles.py b/geodepy/tests/test_angles.py
index 8fd9574..afce1e6 100644
--- a/geodepy/tests/test_angles.py
+++ b/geodepy/tests/test_angles.py
@@ -2,17 +2,44 @@
 import os
 from math import radians, pi
 
-from geodepy.angles import (DECAngle, HPAngle, GONAngle, DMSAngle, DDMAngle,
-                            dec2hp, dec2hpa, dec2gon, dec2gona,
-                            dec2dms, dec2ddm,
-                            hp2dec, hp2deca, hp2gon, hp2gona,
-                            hp2dms, hp2ddm, hp2rad,
-                            gon2dec, gon2deca, gon2hp, gon2hpa,
-                            gon2dms, gon2ddm, gon2rad,
-                            dd2sec, angular_typecheck)
-
-rad_exs = [radians(123.74875), radians(12.575), radians(-12.575),
-           radians(0.0525), radians(0.005), radians(-0.005)]
+from geodepy.angles import (
+    DECAngle,
+    HPAngle,
+    GONAngle,
+    DMSAngle,
+    DDMAngle,
+    dec2hp,
+    dec2hpa,
+    dec2gon,
+    dec2gona,
+    dec2dms,
+    dec2ddm,
+    hp2dec,
+    hp2deca,
+    hp2gon,
+    hp2gona,
+    hp2dms,
+    hp2ddm,
+    hp2rad,
+    gon2dec,
+    gon2deca,
+    gon2hp,
+    gon2hpa,
+    gon2dms,
+    gon2ddm,
+    gon2rad,
+    dd2sec,
+    angular_typecheck,
+)
+
+rad_exs = [
+    radians(123.74875),
+    radians(12.575),
+    radians(-12.575),
+    radians(0.0525),
+    radians(0.005),
+    radians(-0.005),
+]
 
 dec_ex = 123.74875
 dec_ex2 = 12.575
@@ -55,12 +82,12 @@
 dms_ex6 = DMSAngle(0, 0, 18, positive=False)
 dms_exs = [dms_ex, dms_ex2, dms_ex3, dms_ex4, dms_ex5, dms_ex6]
 
-dms_str = '123 44 55.5'
-dms_str2 = '12 34 30'
-dms_str3 = '-12 34 30'
-dms_str4 = '0 3 9'
-dms_str5 = '0 0 18'
-dms_str6 = '-0 0 18'
+dms_str = "123 44 55.5"
+dms_str2 = "12 34 30"
+dms_str3 = "-12 34 30"
+dms_str4 = "0 3 9"
+dms_str5 = "0 0 18"
+dms_str6 = "-0 0 18"
 dms_strs = [dms_str, dms_str2, dms_str3, dms_str4, dms_str5, dms_str6]
 
 ddm_ex = DDMAngle(123, 44.925)
@@ -71,12 +98,12 @@
 ddm_ex6 = DDMAngle(0, 0.3, positive=False)
 ddm_exs = [ddm_ex, ddm_ex2, ddm_ex3, ddm_ex4, ddm_ex5, ddm_ex6]
 
-ddm_str = '123 44.925'
-ddm_str2 = '12 34.5'
-ddm_str3 = '-12 34.5'
-ddm_str4 = '0 3.15'
-ddm_str5 = '0 0.3'
-ddm_str6 = '-0 0.3'
+ddm_str = "123 44.925"
+ddm_str2 = "12 34.5"
+ddm_str3 = "-12 34.5"
+ddm_str4 = "0 3.15"
+ddm_str5 = "0 0.3"
+ddm_str6 = "-0 0.3"
 ddm_strs = [ddm_str, ddm_str2, ddm_str3, ddm_str4, ddm_str5, ddm_str6]
 
 gon_ex = 137.4986111111111
@@ -101,18 +128,24 @@ def setUp(self):
         self.testData = []
         degreeValues = [0, 1, 2, 4, 8, 16, 32, 64, 128, 256]
         dec_places = 13
-        error = 10**-(dec_places - 4)
+        error = 10 ** -(dec_places - 4)
         for deg in degreeValues:
             for min in range(60):
                 for sec in range(60):
                     if sec:
-                        hp_minus = float(f'{deg:4d}.{min:02d}{sec-1:02d}' + '9' * (dec_places - 4))
+                        hp_minus = float(
+                            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
+                        gon_minus = 400.0 / 360.0 * dec_minus
                         rad_minus = pi / 180.0 * dec_minus
-                        self.testData.append([hp_minus, dec_minus, gon_minus, rad_minus])
-                    hp = float(f'{deg:4d}.{min:02d}{sec:02d}')
-                    hp_plus = float(f'{deg:4d}.{min:02d}{sec:02d}' + '0' * (dec_places - 5) + '1')
+                        self.testData.append(
+                            [hp_minus, dec_minus, gon_minus, rad_minus]
+                        )
+                    hp = float(f"{deg:4d}.{min:02d}{sec:02d}")
+                    hp_plus = float(
+                        f"{deg:4d}.{min:02d}{sec:02d}" + "0" * (dec_places - 5) + "1"
+                    )
                     dec = deg + (min / 60.0 + sec / 3600.0)
                     gon = 400.0 / 360.0 * dec
                     rad = pi / 180.0 * dec
@@ -148,8 +181,8 @@ def test_DECAngle(self):
             self.assertEqual(round(ex), DECAngle(round(dec_exs[num])))
 
         # Test HPAngle Representation
-        self.assertEqual(repr(deca_ex), '{DECAngle: +123.74875}')
-        self.assertEqual(repr(deca_ex3), '{DECAngle: -12.575}')
+        self.assertEqual(repr(deca_ex), "{DECAngle: +123.74875}")
+        self.assertEqual(repr(deca_ex3), "{DECAngle: -12.575}")
 
         # Test DECAngle Overloads
         self.assertEqual(dec_ex + dec_ex2, (deca_ex + deca_ex2).dec())
@@ -171,19 +204,19 @@ def test_DECAngle(self):
         self.assertTrue(deca_ex2 < deca_ex)
         self.assertFalse(deca_ex < deca_ex2)
         with self.assertRaises(TypeError):
-            deca_ex * 'a'
+            deca_ex * "a"
         with self.assertRaises(TypeError):
-            'a' * deca_ex
+            "a" * deca_ex
         with self.assertRaises(TypeError):
-            deca_ex / 'a'
+            deca_ex / "a"
         with self.assertRaises(TypeError):
-            deca_ex + 'a'
+            deca_ex + "a"
         with self.assertRaises(TypeError):
-            'a' + deca_ex
+            "a" + deca_ex
         with self.assertRaises(TypeError):
-            deca_ex - 'a'
+            deca_ex - "a"
         with self.assertRaises(TypeError):
-            'a' - deca_ex
+            "a" - deca_ex
 
     def test_HPAngle(self):
         # Test HPAngle Methods
@@ -211,8 +244,8 @@ def test_HPAngle(self):
             self.assertEqual(round(ex), HPAngle(round(hp_exs[num])))
 
         # Test HPAngle Representation
-        self.assertEqual(repr(hpa_ex), '{HPAngle: +123.44555}')
-        self.assertEqual(repr(hpa_ex3), '{HPAngle: -12.343}')
+        self.assertEqual(repr(hpa_ex), "{HPAngle: +123.44555}")
+        self.assertEqual(repr(hpa_ex3), "{HPAngle: -12.343}")
 
         # Test DMSAngle Overloads
         self.assertAlmostEqual(dec_ex + dec_ex2, (hpa_ex + hpa_ex2).dec(), 12)
@@ -234,19 +267,19 @@ def test_HPAngle(self):
         self.assertTrue(hpa_ex2 < hpa_ex)
         self.assertFalse(hpa_ex < hpa_ex2)
         with self.assertRaises(TypeError):
-            hpa_ex * 'a'
+            hpa_ex * "a"
         with self.assertRaises(TypeError):
-            'a' * hpa_ex
+            "a" * hpa_ex
         with self.assertRaises(TypeError):
-            hpa_ex / 'a'
+            hpa_ex / "a"
         with self.assertRaises(TypeError):
-            hpa_ex + 'a'
+            hpa_ex + "a"
         with self.assertRaises(TypeError):
-            'a' + hpa_ex
+            "a" + hpa_ex
         with self.assertRaises(TypeError):
-            hpa_ex - 'a'
+            hpa_ex - "a"
         with self.assertRaises(TypeError):
-            'a' - hpa_ex
+            "a" - hpa_ex
 
         # Test Validity Checking of HP format input
         with self.assertRaises(ValueError):
@@ -279,8 +312,8 @@ def test_GONAngle(self):
             self.assertEqual(round(ex), GONAngle(round(gon_exs[num])))
 
         # Test GONAngle Representation
-        self.assertEqual(repr(gona_ex), '{GONAngle: +137.4986111111111}')
-        self.assertEqual(repr(gona_ex3), '{GONAngle: -13.97222222222222}')
+        self.assertEqual(repr(gona_ex), "{GONAngle: +137.4986111111111}")
+        self.assertEqual(repr(gona_ex3), "{GONAngle: -13.97222222222222}")
 
         # Test DMSAngle Overloads
         self.assertAlmostEqual(dec_ex + dec_ex2, (gona_ex + gona_ex2).dec(), 12)
@@ -302,19 +335,19 @@ def test_GONAngle(self):
         self.assertTrue(gona_ex2 < gona_ex)
         self.assertFalse(gona_ex < gona_ex2)
         with self.assertRaises(TypeError):
-            gona_ex * 'a'
+            gona_ex * "a"
         with self.assertRaises(TypeError):
-            'a' * gona_ex
+            "a" * gona_ex
         with self.assertRaises(TypeError):
-            gona_ex / 'a'
+            gona_ex / "a"
         with self.assertRaises(TypeError):
-            gona_ex + 'a'
+            gona_ex + "a"
         with self.assertRaises(TypeError):
-            'a' + gona_ex
+            "a" + gona_ex
         with self.assertRaises(TypeError):
-            gona_ex - 'a'
+            gona_ex - "a"
         with self.assertRaises(TypeError):
-            'a' - gona_ex
+            "a" - gona_ex
 
     def test_DMSAngle(self):
         # Test DMSAngle Methods
@@ -339,14 +372,18 @@ def test_DMSAngle(self):
             self.assertEqual((round(-ex, 2)).hp(), round(-hp_exs[num], 5))
 
         # Test DMSAngle Sign Conventions
-        self.assertEqual(-dec_ex, DMSAngle(-dms_ex.degree, dms_ex.minute,
-                                           dms_ex.second).dec())
-        self.assertEqual(dec_ex, DMSAngle(dms_ex.degree, -dms_ex.minute,
-                                          -dms_ex.second).dec())
-        self.assertAlmostEqual(-dec_ex4, DMSAngle(0, -dms_ex4.minute,
-                                                  dms_ex4.second).dec(), 9)
-        self.assertAlmostEqual(dec_ex4, DMSAngle(0, dms_ex4.minute,
-                                                 dms_ex4.second).dec(), 9)
+        self.assertEqual(
+            -dec_ex, DMSAngle(-dms_ex.degree, dms_ex.minute, dms_ex.second).dec()
+        )
+        self.assertEqual(
+            dec_ex, DMSAngle(dms_ex.degree, -dms_ex.minute, -dms_ex.second).dec()
+        )
+        self.assertAlmostEqual(
+            -dec_ex4, DMSAngle(0, -dms_ex4.minute, dms_ex4.second).dec(), 9
+        )
+        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))
@@ -363,8 +400,8 @@ def test_DMSAngle(self):
         self.assertFalse(DMSAngle(0, 0, -3).positive)
         self.assertFalse(DMSAngle(0, 1, 2, positive=False).positive)
         self.assertFalse(DMSAngle(-0.0, 1, 2).positive)
-        self.assertEqual(repr(dms_ex), '{DMSAngle: +123d 44m 55.5s}')
-        self.assertEqual(repr(dms_ex3), '{DMSAngle: -12d 34m 30s}')
+        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())
@@ -387,19 +424,19 @@ def test_DMSAngle(self):
         self.assertTrue(dms_ex2 < dms_ex)
         self.assertFalse(dms_ex < dms_ex2)
         with self.assertRaises(TypeError):
-            dms_ex * 'a'
+            dms_ex * "a"
         with self.assertRaises(TypeError):
-            'a' * dms_ex
+            "a" * dms_ex
         with self.assertRaises(TypeError):
-            dms_ex / 'a'
+            dms_ex / "a"
         with self.assertRaises(TypeError):
-            dms_ex + 'a'
+            dms_ex + "a"
         with self.assertRaises(TypeError):
-            'a' + dms_ex
+            "a" + dms_ex
         with self.assertRaises(TypeError):
-            dms_ex - 'a'
+            dms_ex - "a"
         with self.assertRaises(TypeError):
-            'a' - dms_ex
+            "a" - dms_ex
 
         # Test reading in formatted strings
         for num, ex in enumerate(dms_strs):
@@ -429,8 +466,7 @@ def test_DDMAngle(self):
             self.assertEqual((round(-ex)).hp(), round(-hp_exs[num], 2))
 
         # Test DMSAngle Sign Conventions
-        self.assertEqual(-dec_ex, DDMAngle(-dms_ex.degree,
-                                           ddm_ex.minute).dec())
+        self.assertEqual(-dec_ex, DDMAngle(-dms_ex.degree, ddm_ex.minute).dec())
         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)
@@ -447,8 +483,8 @@ def test_DDMAngle(self):
         self.assertFalse(DDMAngle(0, -1).positive)
         self.assertFalse(DDMAngle(0, 1, positive=False).positive)
         self.assertFalse(DDMAngle(-0.0, 1).positive)
-        self.assertEqual(repr(ddm_ex), '{DDMAngle: +123d 44.925m}')
-        self.assertEqual(repr(ddm_ex3), '{DDMAngle: -12d 34.5m}')
+        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())
@@ -471,19 +507,19 @@ def test_DDMAngle(self):
         self.assertTrue(ddm_ex2 < ddm_ex)
         self.assertFalse(ddm_ex < ddm_ex2)
         with self.assertRaises(TypeError):
-            ddm_ex * 'a'
+            ddm_ex * "a"
         with self.assertRaises(TypeError):
-            'a' * ddm_ex
+            "a" * ddm_ex
         with self.assertRaises(TypeError):
-            ddm_ex / 'a'
+            ddm_ex / "a"
         with self.assertRaises(TypeError):
-            ddm_ex + 'a'
+            ddm_ex + "a"
         with self.assertRaises(TypeError):
-            'a' + ddm_ex
+            "a" + ddm_ex
         with self.assertRaises(TypeError):
-            ddm_ex - 'a'
+            ddm_ex - "a"
         with self.assertRaises(TypeError):
-            'a' - ddm_ex
+            "a" - ddm_ex
 
         # Test reading in formatted strings
         for num, ex in enumerate(ddm_strs):
@@ -492,11 +528,9 @@ def test_DDMAngle(self):
 
     def test_angles_interoperability(self):
         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(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))
+        self.assertEqual(DDMAngle(3, 2) - DMSAngle(2, 2, 30), DDMAngle(0, 59.5))
 
     def test_dec2hp(self):
         for num, ex in enumerate(hp_exs):
@@ -523,10 +557,8 @@ def test_dec2gon(self):
 
     def test_dec2gona(self):
         for num, ex in enumerate(dec_exs):
-            self.assertEqual(round(dec2gona(ex), 13),
-                             round(gona_exs[num], 13))
-            self.assertEqual(round(dec2gona(-ex), 13),
-                             round(-gona_exs[num], 13))
+            self.assertEqual(round(dec2gona(ex), 13), round(gona_exs[num], 13))
+            self.assertEqual(round(dec2gona(-ex), 13), round(-gona_exs[num], 13))
 
     def test_dec2dms(self):
         self.assertEqual(dms_ex, dec2dms(dec_ex))
@@ -547,8 +579,9 @@ def test_hp2dec(self):
 
         self.assertAlmostEqual(0, hp2dec(0), 13)
         self.assertAlmostEqual(258, hp2dec(258), 13)
-        self.assertAlmostEqual(hp2dec(hp_exs[0]) + hp2dec(hp_exs[1]),
-                               dec_exs[0] + dec_exs[1], 13)
+        self.assertAlmostEqual(
+            hp2dec(hp_exs[0]) + hp2dec(hp_exs[1]), dec_exs[0] + dec_exs[1], 13
+        )
         # Test that invalid minutes and seconds components raise errors
         # (Minutes and/or Seconds can't be greater than 60, therefore
         #  123.718 - representing 123 degrees, 71 minutes, 80 seconds
@@ -614,8 +647,8 @@ def test_gon2dec(self):
             self.assertAlmostEqual(gon2dec(-ex), -dec_exs[num], 14)
         for check in self.testData:
             hp, dec, gon, rad = check
-            self.assertAlmostEqual(dec, gon2dec(gon), delta = 5.8e-14)
-            self.assertAlmostEqual(-dec, gon2dec(-gon), delta = 5.8e-14)
+            self.assertAlmostEqual(dec, gon2dec(gon), delta=5.8e-14)
+            self.assertAlmostEqual(-dec, gon2dec(-gon), delta=5.8e-14)
 
     def test_gon2deca(self):
         for num, ex in enumerate(gon_exs):
@@ -670,14 +703,12 @@ def test_angular_typecheck(self):
         class_exs = [deca_exs, hpa_exs, gona_exs, dms_exs, ddm_exs]
         for class_ex in class_exs:
             for num, ex in enumerate(class_ex):
-                self.assertAlmostEqual(angular_typecheck(ex),
-                                       dec_exs[num], 13)
-                self.assertAlmostEqual(angular_typecheck(-ex),
-                                       -dec_exs[num], 13)
+                self.assertAlmostEqual(angular_typecheck(ex), dec_exs[num], 13)
+                self.assertAlmostEqual(angular_typecheck(-ex), -dec_exs[num], 13)
         for ex in dec_exs:
             self.assertEqual(angular_typecheck(ex), ex)
             self.assertEqual(angular_typecheck(-ex), -ex)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     unittest.main()
diff --git a/geodepy/tests/test_convert.py b/geodepy/tests/test_convert.py
index 21c3bd5..3455728 100644
--- a/geodepy/tests/test_convert.py
+++ b/geodepy/tests/test_convert.py
@@ -4,107 +4,137 @@
 import numpy as np
 from geodepy.fileio import read_dnacoord
 from geodepy.constants import grs80, ans, isg
-from geodepy.convert import (dec2hp, hp2dec, DMSAngle, DDMAngle, dec2dms,
-                             dec2ddm, hp2dms, hp2ddm, dd2sec,
-                             yyyydoy_to_date, date_to_yyyydoy, grid2geo,
-                             hp2dec_v, geo2grid, llh2xyz, xyz2llh)
+from geodepy.convert import (
+    dec2hp,
+    hp2dec,
+    DMSAngle,
+    DDMAngle,
+    dec2dms,
+    dec2ddm,
+    hp2dms,
+    hp2ddm,
+    dd2sec,
+    yyyydoy_to_date,
+    date_to_yyyydoy,
+    grid2geo,
+    hp2dec_v,
+    geo2grid,
+    llh2xyz,
+    xyz2llh,
+)
 
 
 class TestConvert(unittest.TestCase):
     def test_date_to_yyyydoy(self):
-        self.assertEqual(date_to_yyyydoy(datetime.date(2020, 1, 4)),
-                         '2020.004')
-        self.assertEqual(date_to_yyyydoy(datetime.date(2020, 10, 12)),
-                         '2020.286')
-        self.assertEqual(date_to_yyyydoy(datetime.date(1998, 4, 7)),
-                         '1998.097')
-        self.assertEqual(date_to_yyyydoy(datetime.date(2000, 11, 22)),
-                         '2000.327')
-        self.assertEqual(date_to_yyyydoy(datetime.date(2008, 2, 29)),
-                         '2008.060')
+        self.assertEqual(date_to_yyyydoy(datetime.date(2020, 1, 4)), "2020.004")
+        self.assertEqual(date_to_yyyydoy(datetime.date(2020, 10, 12)), "2020.286")
+        self.assertEqual(date_to_yyyydoy(datetime.date(1998, 4, 7)), "1998.097")
+        self.assertEqual(date_to_yyyydoy(datetime.date(2000, 11, 22)), "2000.327")
+        self.assertEqual(date_to_yyyydoy(datetime.date(2008, 2, 29)), "2008.060")
         with self.assertRaises(AttributeError):
-            date_to_yyyydoy('a')
+            date_to_yyyydoy("a")
         with self.assertRaises(AttributeError):
-            date_to_yyyydoy('2020123')
+            date_to_yyyydoy("2020123")
 
     def test_yyyydoy_to_date(self):
-        self.assertEqual(yyyydoy_to_date('2020.004'),
-                         datetime.date(2020, 1, 4))
-        self.assertEqual(yyyydoy_to_date('2020.286'),
-                         datetime.date(2020, 10, 12))
-        self.assertEqual(yyyydoy_to_date('1998.097'),
-                         datetime.date(1998, 4, 7))
-        self.assertEqual(yyyydoy_to_date('2000.327'),
-                         datetime.date(2000, 11, 22))
-        self.assertEqual(yyyydoy_to_date('2008.060'),
-                         datetime.date(2008, 2, 29))
-        self.assertEqual(yyyydoy_to_date('2020004'),
-                         datetime.date(2020, 1, 4))
-        self.assertEqual(yyyydoy_to_date('2020286'),
-                         datetime.date(2020, 10, 12))
-        self.assertEqual(yyyydoy_to_date('1998097'),
-                         datetime.date(1998, 4, 7))
-        self.assertEqual(yyyydoy_to_date('2000327'),
-                         datetime.date(2000, 11, 22))
-        self.assertEqual(yyyydoy_to_date('2008060'),
-                         datetime.date(2008, 2, 29))
+        self.assertEqual(yyyydoy_to_date("2020.004"), datetime.date(2020, 1, 4))
+        self.assertEqual(yyyydoy_to_date("2020.286"), datetime.date(2020, 10, 12))
+        self.assertEqual(yyyydoy_to_date("1998.097"), datetime.date(1998, 4, 7))
+        self.assertEqual(yyyydoy_to_date("2000.327"), datetime.date(2000, 11, 22))
+        self.assertEqual(yyyydoy_to_date("2008.060"), datetime.date(2008, 2, 29))
+        self.assertEqual(yyyydoy_to_date("2020004"), datetime.date(2020, 1, 4))
+        self.assertEqual(yyyydoy_to_date("2020286"), datetime.date(2020, 10, 12))
+        self.assertEqual(yyyydoy_to_date("1998097"), datetime.date(1998, 4, 7))
+        self.assertEqual(yyyydoy_to_date("2000327"), datetime.date(2000, 11, 22))
+        self.assertEqual(yyyydoy_to_date("2008060"), datetime.date(2008, 2, 29))
         with self.assertRaises(ValueError):
-            yyyydoy_to_date('a')
+            yyyydoy_to_date("a")
         with self.assertRaises(ValueError):
-            yyyydoy_to_date('20201234')
+            yyyydoy_to_date("20201234")
         with self.assertRaises(ValueError):
-            yyyydoy_to_date('2020.1234')
+            yyyydoy_to_date("2020.1234")
         with self.assertRaises(ValueError):
-            yyyydoy_to_date('202012')
+            yyyydoy_to_date("202012")
         with self.assertRaises(ValueError):
-            yyyydoy_to_date('2020.12')
+            yyyydoy_to_date("2020.12")
 
     def test_geo_grid_transform_interoperability(self):
         abs_path = os.path.abspath(os.path.dirname(__file__))
 
-        test_geo_coords = np.genfromtxt(os.path.join(abs_path, 'resources/Test_Conversion_Geo.csv'),
-                                        delimiter=',',
-                                        dtype='S4,f8,f8',
-                                        names=['site', 'lat', 'lon'])
-
-        test_grid_coords = np.genfromtxt(os.path.join(abs_path, 'resources/Test_Conversion_Grid.csv'),
-                                         delimiter=',',
-                                         dtype='S4,i4,f8,f8',
-                                         names=['site', 'zone', 'east', 'north'])
-
-        geoed_grid = np.array([grid2geo(*x) for x in test_grid_coords[['zone', 'east', 'north']]])
-        np.testing.assert_almost_equal(geoed_grid[:, :2], hp2dec_v(np.array(test_geo_coords[['lat', 'lon']].tolist())),
-                                       decimal=8)
-
-        gridded_geo = np.stack([geo2grid(*x) for x in hp2dec_v(np.array(test_geo_coords[['lat', 'lon']].tolist()))])
-        np.testing.assert_almost_equal(gridded_geo[:, 2:4].astype(float),
-                                       np.array(test_grid_coords[['east', 'north']].tolist()),
-                                       decimal=3)
+        test_geo_coords = np.genfromtxt(
+            os.path.join(abs_path, "resources/Test_Conversion_Geo.csv"),
+            delimiter=",",
+            dtype="S4,f8,f8",
+            names=["site", "lat", "lon"],
+        )
+
+        test_grid_coords = np.genfromtxt(
+            os.path.join(abs_path, "resources/Test_Conversion_Grid.csv"),
+            delimiter=",",
+            dtype="S4,i4,f8,f8",
+            names=["site", "zone", "east", "north"],
+        )
+
+        geoed_grid = np.array(
+            [grid2geo(*x) for x in test_grid_coords[["zone", "east", "north"]]]
+        )
+        np.testing.assert_almost_equal(
+            geoed_grid[:, :2],
+            hp2dec_v(np.array(test_geo_coords[["lat", "lon"]].tolist())),
+            decimal=8,
+        )
+
+        gridded_geo = np.stack(
+            [
+                geo2grid(*x)
+                for x in hp2dec_v(np.array(test_geo_coords[["lat", "lon"]].tolist()))
+            ]
+        )
+        np.testing.assert_almost_equal(
+            gridded_geo[:, 2:4].astype(float),
+            np.array(test_grid_coords[["east", "north"]].tolist()),
+            decimal=3,
+        )
 
     def test_geo_grid_transform_interoperability_isg(self):
         abs_path = os.path.abspath(os.path.dirname(__file__))
-        test_geo_coords = np.genfromtxt(os.path.join(abs_path, 'resources/Test_Conversion_ISG_Geo.csv'),
-                                        delimiter=',',
-                                        dtype='S4,f8,f8',
-                                        names=['site', 'lat', 'lon'])
-
-        test_grid_coords = np.genfromtxt(os.path.join(abs_path, 'resources/Test_Conversion_ISG_Grid.csv'),
-                                         delimiter=',',
-                                         dtype='S4,i4,f8,f8',
-                                         names=['site', 'zone', 'east', 'north'])
-
-        geoed_grid = np.array([grid2geo(*x, ellipsoid=ans, prj=isg)
-                               for x in test_grid_coords[['zone', 'east', 'north']]])
-        np.testing.assert_almost_equal(geoed_grid[:, :2], np.array(test_geo_coords[['lat', 'lon']].tolist()),
-                                       decimal=8)
-
-        gridded_geo = np.stack([geo2grid(*x, ellipsoid=ans, prj=isg)
-                                for x in np.array(test_geo_coords[['lat', 'lon']].tolist())
-                                ])
-        np.testing.assert_almost_equal(gridded_geo[:, 2:4].astype(float),
-                                       np.array(test_grid_coords[['east', 'north']].tolist()),
-                                       decimal=3)
-
+        test_geo_coords = np.genfromtxt(
+            os.path.join(abs_path, "resources/Test_Conversion_ISG_Geo.csv"),
+            delimiter=",",
+            dtype="S4,f8,f8",
+            names=["site", "lat", "lon"],
+        )
+
+        test_grid_coords = np.genfromtxt(
+            os.path.join(abs_path, "resources/Test_Conversion_ISG_Grid.csv"),
+            delimiter=",",
+            dtype="S4,i4,f8,f8",
+            names=["site", "zone", "east", "north"],
+        )
+
+        geoed_grid = np.array(
+            [
+                grid2geo(*x, ellipsoid=ans, prj=isg)
+                for x in test_grid_coords[["zone", "east", "north"]]
+            ]
+        )
+        np.testing.assert_almost_equal(
+            geoed_grid[:, :2],
+            np.array(test_geo_coords[["lat", "lon"]].tolist()),
+            decimal=8,
+        )
+
+        gridded_geo = np.stack(
+            [
+                geo2grid(*x, ellipsoid=ans, prj=isg)
+                for x in np.array(test_geo_coords[["lat", "lon"]].tolist())
+            ]
+        )
+        np.testing.assert_almost_equal(
+            gridded_geo[:, 2:4].astype(float),
+            np.array(test_grid_coords[["east", "north"]].tolist()),
+            decimal=3,
+        )
 
     def test_llh2xyz(self):
 
@@ -115,17 +145,15 @@ def test_llh2xyz(self):
         self.assertAlmostEqual(z, -3888601.3067, 3)
 
         # Test DMSAngle input
-        x, y, z = llh2xyz(DMSAngle(-37, 48, 26.67598),
-                          DMSAngle(144, 58, 16.44114),
-                          39.6514)
+        x, y, z = llh2xyz(
+            DMSAngle(-37, 48, 26.67598), DMSAngle(144, 58, 16.44114), 39.6514
+        )
         self.assertAlmostEqual(x, -4131654.2815, 3)
         self.assertAlmostEqual(y, 2896107.9738, 3)
         self.assertAlmostEqual(z, -3888601.3067, 3)
 
         # Test DDMAngle input
-        x, y, z = llh2xyz(DDMAngle(-37, 48.4445996),
-                          DDMAngle(144, 58.274019),
-                          39.6514)
+        x, y, z = llh2xyz(DDMAngle(-37, 48.4445996), DDMAngle(144, 58.274019), 39.6514)
         self.assertAlmostEqual(x, -4131654.2815, 3)
         self.assertAlmostEqual(y, 2896107.9738, 3)
         self.assertAlmostEqual(z, -3888601.3067, 3)
@@ -134,30 +162,35 @@ def test_llh2xyz(self):
         # including 109 Points Across Australia
         abs_path = os.path.abspath(os.path.dirname(__file__))
 
-        testdata = read_dnacoord(os.path.join(abs_path, 'resources/natadjust_rvs_example.dat'))
+        testdata = read_dnacoord(
+            os.path.join(abs_path, "resources/natadjust_rvs_example.dat")
+        )
         for coord in testdata:
             coord.converthptodd()
             xcomp, ycomp, zcomp = llh2xyz(coord.lat, coord.long, coord.ell_ht)
-            assert (abs(coord.x - xcomp) < 2e-4)
-            assert (abs(coord.y - ycomp) < 2e-4)
-            assert (abs(coord.z - zcomp) < 2e-4)
+            assert abs(coord.x - xcomp) < 2e-4
+            assert abs(coord.y - ycomp) < 2e-4
+            assert abs(coord.z - zcomp) < 2e-4
 
     def test_xyz2llh(self):
         abs_path = os.path.abspath(os.path.dirname(__file__))
 
-        testdata = read_dnacoord(os.path.join(abs_path, 'resources/natadjust_rvs_example.dat'))
+        testdata = read_dnacoord(
+            os.path.join(abs_path, "resources/natadjust_rvs_example.dat")
+        )
         for coord in testdata:
             coord.converthptodd()
             latcomp, longcomp, ell_htcomp = xyz2llh(coord.x, coord.y, coord.z)
-            assert (abs(latcomp - coord.lat) < 2e-9)
-            assert (abs(longcomp - coord.long) < 2e-9)
-            assert (abs(ell_htcomp - coord.ell_ht) < 1e-4)
+            assert abs(latcomp - coord.lat) < 2e-9
+            assert abs(longcomp - coord.long) < 2e-9
+            assert abs(ell_htcomp - coord.ell_ht) < 1e-4
 
     def test_geo2grid(self):
         # Single Point Test
-        hem, zone, east, north, psf, grid_conv = geo2grid(hp2dec(-37.482667598),
-                                                          hp2dec(144.581644114))
-        self.assertEqual(hem, 'South')
+        hem, zone, east, north, psf, grid_conv = geo2grid(
+            hp2dec(-37.482667598), hp2dec(144.581644114)
+        )
+        self.assertEqual(hem, "South")
         self.assertEqual(zone, 55)
         self.assertAlmostEqual(east, 321405.5592, 3)
         self.assertAlmostEqual(north, 5813614.1613, 3)
@@ -165,10 +198,10 @@ def test_geo2grid(self):
         self.assertAlmostEqual(grid_conv, -1.2439811331, 9)
 
         # Test DMSAngle Input
-        (hem, zone, east,
-         north, psf, grid_conv) = geo2grid(DMSAngle(-37, 48, 26.67598),
-                                           DMSAngle(144, 58, 16.44114))
-        self.assertEqual(hem, 'South')
+        (hem, zone, east, north, psf, grid_conv) = geo2grid(
+            DMSAngle(-37, 48, 26.67598), DMSAngle(144, 58, 16.44114)
+        )
+        self.assertEqual(hem, "South")
         self.assertEqual(zone, 55)
         self.assertAlmostEqual(east, 321405.5592, 3)
         self.assertAlmostEqual(north, 5813614.1613, 3)
@@ -176,10 +209,10 @@ def test_geo2grid(self):
         self.assertAlmostEqual(grid_conv, -1.2439811331, 9)
 
         # Test DDMAngle Input
-        (hem, zone, east,
-         north, psf, grid_conv) = geo2grid(DDMAngle(-37, 48.4445997),
-                                           DDMAngle(144, 58.274019))
-        self.assertEqual(hem, 'South')
+        (hem, zone, east, north, psf, grid_conv) = geo2grid(
+            DDMAngle(-37, 48.4445997), DDMAngle(144, 58.274019)
+        )
+        self.assertEqual(hem, "South")
         self.assertEqual(zone, 55)
         self.assertAlmostEqual(east, 321405.5592, 3)
         self.assertAlmostEqual(north, 5813614.1613, 3)
@@ -189,21 +222,28 @@ def test_geo2grid(self):
         abs_path = os.path.abspath(os.path.dirname(__file__))
 
         # Test various coordinates in Australia
-        testdata = read_dnacoord(os.path.join(abs_path, 'resources/natadjust_rvs_example.dat'))
+        testdata = read_dnacoord(
+            os.path.join(abs_path, "resources/natadjust_rvs_example.dat")
+        )
         for coord in testdata:
             coord.converthptodd()
-            hem, zonecomp, eastcomp, northcomp, psf, grid_conv = geo2grid(coord.lat, coord.long)
+            hem, zonecomp, eastcomp, northcomp, psf, grid_conv = geo2grid(
+                coord.lat, coord.long
+            )
             self.assertEqual(zonecomp, coord.zone)
             self.assertLess(abs(eastcomp - coord.easting), 4e-4)
             self.assertLess((northcomp - coord.northing), 4e-4)
 
         # Test North and South Hemisphere Output
         north_ex = (DMSAngle(34, 57, 00.79653).dec(), DMSAngle(117, 48, 36.68783).dec())
-        south_ex = (DMSAngle(-34, 57, 00.79653).dec(), DMSAngle(117, 48, 36.68783).dec())
+        south_ex = (
+            DMSAngle(-34, 57, 00.79653).dec(),
+            DMSAngle(117, 48, 36.68783).dec(),
+        )
         north_grid = geo2grid(north_ex[0], north_ex[1])
         south_grid = geo2grid(south_ex[0], south_ex[1])
-        self.assertEqual(north_grid[0], 'North')
-        self.assertEqual(south_grid[0], 'South')
+        self.assertEqual(north_grid[0], "North")
+        self.assertEqual(south_grid[0], "South")
         self.assertEqual(north_grid[1], south_grid[1])  # Zone
         self.assertEqual(north_grid[2], south_grid[2])  # Easting
         self.assertEqual(north_grid[3], 10000000 - south_grid[3])  # Northing
@@ -233,16 +273,20 @@ def test_geo2grid(self):
     def test_grid2geo(self):
         abs_path = os.path.abspath(os.path.dirname(__file__))
 
-        testdata = read_dnacoord(os.path.join(abs_path, 'resources/natadjust_rvs_example.dat'))
+        testdata = read_dnacoord(
+            os.path.join(abs_path, "resources/natadjust_rvs_example.dat")
+        )
         for coord in testdata:
             coord.converthptodd()
-            latcomp, longcomp, psf, grid_conv = grid2geo(coord.zone, coord.easting, coord.northing)
+            latcomp, longcomp, psf, grid_conv = grid2geo(
+                coord.zone, coord.easting, coord.northing
+            )
             self.assertLess(abs(latcomp - coord.lat), 5e-9)
             self.assertLess(abs(longcomp - coord.long), 5e-9)
 
         # Test North and South Hemisphere Output
-        north_ex = (50, 573976.8747, 3867822.4539, 'North')
-        south_ex = (50, 573976.8747, 6132177.5461, 'South')
+        north_ex = (50, 573976.8747, 3867822.4539, "North")
+        south_ex = (50, 573976.8747, 6132177.5461, "South")
         north_geo = grid2geo(*north_ex)
         south_geo = grid2geo(*south_ex)
         self.assertEqual(north_geo[0], -south_geo[0])
@@ -264,7 +308,7 @@ def test_grid2geo(self):
         with self.assertRaises(ValueError):
             grid2geo(0, 0, 10000001)
         with self.assertRaises(ValueError):
-            grid2geo(0, 0, 500000, 'fail')
+            grid2geo(0, 0, 500000, "fail")
         # test ValueError raised if not a valid ISG zone
         with self.assertRaises(ValueError):
             grid2geo(zone=530, east=300000, north=1500000, ellipsoid=ans, prj=isg)
@@ -272,5 +316,6 @@ def test_grid2geo(self):
         with self.assertWarns(UserWarning):
             grid2geo(zone=551, east=300000, north=1500000, ellipsoid=grs80, prj=isg)
 
-if __name__ == '__main__':
+
+if __name__ == "__main__":
     unittest.main()
diff --git a/geodepy/tests/test_coord.py b/geodepy/tests/test_coord.py
index 0ca276a..64e14c1 100644
--- a/geodepy/tests/test_coord.py
+++ b/geodepy/tests/test_coord.py
@@ -6,29 +6,51 @@
 cart_ex1 = CoordCart(-4052052.7379, 4212835.9897, -2545104.5898, 14.269)
 cart_ex2 = CoordCart(-4052052.7379, 4212835.9897, -2545104.5898)
 
-geo_ex1 = CoordGeo(DMSAngle(-23, 40, 12.39650).deca(),
-                   DMSAngle(133, 53, 7.87779).deca(),
-                   603.2489, 588.9799)
+geo_ex1 = CoordGeo(
+    DMSAngle(-23, 40, 12.39650).deca(),
+    DMSAngle(133, 53, 7.87779).deca(),
+    603.2489,
+    588.9799,
+)
 geo_ex2 = CoordGeo(geo_ex1.lat, geo_ex1.lon, None, 588.9799)
 geo_ex3 = CoordGeo(geo_ex1.lat, geo_ex1.lon, 603.2489, None)
 geo_ex4 = CoordGeo(geo_ex1.lat, geo_ex1.lon)
 
-tm_ex1 = CoordTM(53, 386353.2343, 7381852.2986, 603.2489, 588.9799,
-                 hemi_north=False, projection=utm)
-tm_ex2 = CoordTM(tm_ex1.zone, tm_ex1.east, tm_ex1.north, None, tm_ex1.orth_ht,
-                 hemi_north=False, projection=utm)
-tm_ex3 = CoordTM(tm_ex1.zone, tm_ex1.east, tm_ex1.north, tm_ex1.ell_ht, None,
-                 hemi_north=False, projection=utm)
-tm_ex4 = CoordTM(tm_ex1.zone, tm_ex1.east, tm_ex1.north, None, None,
-                 hemi_north=False, projection=utm)
+tm_ex1 = CoordTM(
+    53, 386353.2343, 7381852.2986, 603.2489, 588.9799, hemi_north=False, projection=utm
+)
+tm_ex2 = CoordTM(
+    tm_ex1.zone,
+    tm_ex1.east,
+    tm_ex1.north,
+    None,
+    tm_ex1.orth_ht,
+    hemi_north=False,
+    projection=utm,
+)
+tm_ex3 = CoordTM(
+    tm_ex1.zone,
+    tm_ex1.east,
+    tm_ex1.north,
+    tm_ex1.ell_ht,
+    None,
+    hemi_north=False,
+    projection=utm,
+)
+tm_ex4 = CoordTM(
+    tm_ex1.zone, tm_ex1.east, tm_ex1.north, None, None, hemi_north=False, projection=utm
+)
 
 
 class TestCoord(unittest.TestCase):
     def test_CoordCart(self):
         # Test Overloads
-        self.assertEqual(repr(cart_ex1), 'CoordCart: X: -4052052.7379 '
-                                         'Y: 4212835.9897 Z: -2545104.5898 '
-                                         'NVal: 14.269')
+        self.assertEqual(
+            repr(cart_ex1),
+            "CoordCart: X: -4052052.7379 "
+            "Y: 4212835.9897 Z: -2545104.5898 "
+            "NVal: 14.269",
+        )
 
         self.assertEqual(cart_ex1, cart_ex1)
         with self.assertRaises(ValueError):
@@ -64,9 +86,12 @@ def test_CoordCart(self):
 
     def test_CoordGeo(self):
         # Test Overloads
-        self.assertEqual(repr(geo_ex1), 'CoordGeo: Lat: -23.67011013888889 '
-                                        'Lon: 133.88552160833333 '
-                                        'Ell_Ht: 603.2489 Orth_Ht: 588.9799')
+        self.assertEqual(
+            repr(geo_ex1),
+            "CoordGeo: Lat: -23.67011013888889 "
+            "Lon: 133.88552160833333 "
+            "Ell_Ht: 603.2489 Orth_Ht: 588.9799",
+        )
 
         self.assertEqual(geo_ex1, geo_ex1)
         with self.assertRaises(ValueError):
@@ -115,9 +140,12 @@ def test_CoordGeo(self):
 
     def test_CoordTM(self):
         # Test Overloads
-        self.assertEqual(repr(tm_ex1), 'CoordTM: Zone: 53 East: 386353.2343 '
-                                       'North: 7381852.2986 Ell_Ht: 603.2489 '
-                                       'Orth_Ht: 588.9799 Hemisphere: South')
+        self.assertEqual(
+            repr(tm_ex1),
+            "CoordTM: Zone: 53 East: 386353.2343 "
+            "North: 7381852.2986 Ell_Ht: 603.2489 "
+            "Orth_Ht: 588.9799 Hemisphere: South",
+        )
 
         self.assertEqual(tm_ex1, tm_ex1)
         with self.assertRaises(ValueError):
diff --git a/geodepy/tests/test_geodesy.py b/geodepy/tests/test_geodesy.py
index 20e0ef6..bf96c81 100644
--- a/geodepy/tests/test_geodesy.py
+++ b/geodepy/tests/test_geodesy.py
@@ -2,8 +2,15 @@
 import os.path
 import numpy as np
 import numpy.lib.recfunctions as rfn
-from geodepy.convert import (hp2dec, dec2hp, rect2polar, polar2rect,
-                             grid2geo, llh2xyz, DMSAngle)
+from geodepy.convert import (
+    hp2dec,
+    dec2hp,
+    rect2polar,
+    polar2rect,
+    grid2geo,
+    llh2xyz,
+    DMSAngle,
+)
 from geodepy.geodesy import vincinv, vincdir, vincinv_utm, vincdir_utm, enu2xyz, xyz2enu
 
 
@@ -21,14 +28,18 @@ def test_enu2xyz(self):
         MOBS_GDA1994_XYZ = llh2xyz(MOBS_GDA1994[0], MOBS_GDA1994[1], MOBS_MGA1994[3])
 
         # Generate Vector Between UTM Projection Coordinates
-        mga_vector = [MOBS_MGA2020[1] - MOBS_MGA1994[1],
-                      MOBS_MGA2020[2] - MOBS_MGA1994[2],
-                      MOBS_MGA2020[3] - MOBS_MGA1994[3]]
+        mga_vector = [
+            MOBS_MGA2020[1] - MOBS_MGA1994[1],
+            MOBS_MGA2020[2] - MOBS_MGA1994[2],
+            MOBS_MGA2020[3] - MOBS_MGA1994[3],
+        ]
 
         # Generate Vector Between Cartesian XYZ Coordinates
-        xyz_vector = (MOBS_GDA2020_XYZ[0] - MOBS_GDA1994_XYZ[0],
-                      MOBS_GDA2020_XYZ[1] - MOBS_GDA1994_XYZ[1],
-                      MOBS_GDA2020_XYZ[2] - MOBS_GDA1994_XYZ[2])
+        xyz_vector = (
+            MOBS_GDA2020_XYZ[0] - MOBS_GDA1994_XYZ[0],
+            MOBS_GDA2020_XYZ[1] - MOBS_GDA1994_XYZ[1],
+            MOBS_GDA2020_XYZ[2] - MOBS_GDA1994_XYZ[2],
+        )
 
         # Rotate UTM Projection Vector by Grid Convergence
         grid_dist, grid_brg = rect2polar(mga_vector[0], mga_vector[1])
@@ -84,8 +95,9 @@ def test_vincinv(self):
         self.assertEqual(test3, (0, 0, 0))
 
         # Test DMSAngle Input
-        ell_dist, azimuth1to2, azimuth2to1 = vincinv(lat1_DMS, lon1_DMS,
-                                                     lat2_DMS, lon2_DMS)
+        ell_dist, azimuth1to2, azimuth2to1 = vincinv(
+            lat1_DMS, lon1_DMS, lat2_DMS, lon2_DMS
+        )
         self.assertEqual(round(ell_dist, 3), 54972.271)
         self.assertEqual(round(dec2hp(azimuth1to2), 6), 306.520537)
         self.assertEqual(round(dec2hp(azimuth2to1), 6), 127.102507)
@@ -94,16 +106,14 @@ def test_vincinv(self):
         self.assertEqual(test2, (0, 0, 0))
 
         # Test DDMAngle Input
-        (ell_dist,
-         azimuth1to2,
-         azimuth2to1) = vincinv(lat1_DMS.ddm(), lon1_DMS.ddm(),
-                                lat2_DMS.ddm(), lon2_DMS.ddm())
+        (ell_dist, azimuth1to2, azimuth2to1) = vincinv(
+            lat1_DMS.ddm(), lon1_DMS.ddm(), lat2_DMS.ddm(), lon2_DMS.ddm()
+        )
         self.assertEqual(round(ell_dist, 3), 54972.271)
         self.assertEqual(round(dec2hp(azimuth1to2), 6), 306.520537)
         self.assertEqual(round(dec2hp(azimuth2to1), 6), 127.102507)
 
-        test2 = vincinv(lat1_DMS.ddm(), lon1_DMS.ddm(),
-                        lat1_DMS.ddm(), lon1_DMS.ddm())
+        test2 = vincinv(lat1_DMS.ddm(), lon1_DMS.ddm(), lat1_DMS.ddm(), lon1_DMS.ddm())
         self.assertEqual(test2, (0, 0, 0))
 
     def test_vincdir(self):
@@ -125,15 +135,17 @@ def test_vincdir(self):
         self.assertEqual(round(dec2hp(azimuth2to1), 6), 127.102507)
 
         # Test DMSAngle Input
-        lat2, long2, azimuth2to1 = vincdir(lat1_DMS, lon1_DMS,
-                                           azimuth1to2_DMS, ell_dist)
+        lat2, long2, azimuth2to1 = vincdir(
+            lat1_DMS, lon1_DMS, azimuth1to2_DMS, ell_dist
+        )
         self.assertEqual(round(dec2hp(lat2), 8), -37.39101561)
         self.assertEqual(round(dec2hp(long2), 8), 143.55353839)
         self.assertEqual(round(dec2hp(azimuth2to1), 6), 127.102507)
 
         # Test DDMAngle Input
-        lat2, long2, azimuth2to1 = vincdir(lat1_DMS.ddm(), lon1_DMS.ddm(),
-                                           azimuth1to2_DMS.ddm(), ell_dist)
+        lat2, long2, azimuth2to1 = vincdir(
+            lat1_DMS.ddm(), lon1_DMS.ddm(), azimuth1to2_DMS.ddm(), ell_dist
+        )
         self.assertEqual(round(dec2hp(lat2), 8), -37.39101561)
         self.assertEqual(round(dec2hp(long2), 8), 143.55353839)
         self.assertEqual(round(dec2hp(azimuth2to1), 6), 127.102507)
@@ -153,8 +165,9 @@ def test_vincinv_utm(self):
         north3 = 5828674.3402
 
         # Test Coordinates in Zone 55 only
-        grid_dist, grid1to2, grid2to1, lsf = vincinv_utm(zone1, east1, north1,
-                                                         zone2, east2, north2)
+        grid_dist, grid1to2, grid2to1, lsf = vincinv_utm(
+            zone1, east1, north1, zone2, east2, north2
+        )
         self.assertAlmostEqual(lsf, 1.00036397, 8)
         self.assertAlmostEqual(grid_dist, 54992.279, 3)
         self.assertAlmostEqual(dec2hp(grid1to2), 305.17017259, 7)
@@ -162,8 +175,9 @@ def test_vincinv_utm(self):
 
         # Test Coordinates in Different Zones (55 and 54)
         # (Point 2 Grid Bearing Different (Zone 54 Grid Bearing))
-        grid_dist, grid1to2, grid2to1, lsf = vincinv_utm(zone1, east1, north1,
-                                                         zone3, east3, north3)
+        grid_dist, grid1to2, grid2to1, lsf = vincinv_utm(
+            zone1, east1, north1, zone3, east3, north3
+        )
         self.assertAlmostEqual(lsf, 1.00036397, 8)
         self.assertAlmostEqual(grid_dist, 54992.279, 3)
         self.assertAlmostEqual(dec2hp(grid1to2), 305.17017259, 7)
@@ -180,9 +194,9 @@ def test_vincdir_utm(self):
         grid1to2_DMS = DMSAngle(305, 17, 1.7259)
 
         # Test Decimal Degrees Input
-        (zone2, east2, north2,
-         grid2to1, lsf) = vincdir_utm(zone1, east1, north1,
-                                      grid1to2, grid_dist)
+        (zone2, east2, north2, grid2to1, lsf) = vincdir_utm(
+            zone1, east1, north1, grid1to2, grid_dist
+        )
         self.assertEqual(zone2, zone1)
         self.assertAlmostEqual(east2, 228854.0513, 3)
         self.assertAlmostEqual(north2, 5828259.0384, 3)
@@ -190,9 +204,9 @@ def test_vincdir_utm(self):
         self.assertAlmostEqual(lsf, 1.00036397, 8)
 
         # Test DMSAngle Input
-        (zone2, east2, north2,
-         grid2to1, lsf) = vincdir_utm(zone1, east1, north1,
-                                      grid1to2_DMS, grid_dist)
+        (zone2, east2, north2, grid2to1, lsf) = vincdir_utm(
+            zone1, east1, north1, grid1to2_DMS, grid_dist
+        )
         self.assertEqual(zone2, zone1)
         self.assertAlmostEqual(east2, 228854.0513, 3)
         self.assertAlmostEqual(north2, 5828259.0384, 3)
@@ -203,39 +217,51 @@ def test_equality_vincentys(self):
         # Test multiple point-to-point vincinv calculations
         abs_path = os.path.abspath(os.path.dirname(__file__))
 
-        test_geo_coords =\
-            np.genfromtxt(os.path.join(abs_path,
-                                       'resources/Test_Conversion_Geo.csv'),
-                                        delimiter=',',
-                                        dtype='S4,f8,f8',
-                                        names=['site', 'lat1', 'long1'],
-                                        usecols=('lat1', 'long1'))
-
-        test_geo_coord2 = \
-            np.genfromtxt(os.path.join(abs_path,
-                                       'resources/Test_Conversion_Geo.csv'),
-                                        delimiter=',',
-                                        dtype='S4,f8,f8',
-                                        names=['site', 'lat2', 'long2'],
-                                        usecols=('lat2', 'long2'))
+        test_geo_coords = np.genfromtxt(
+            os.path.join(abs_path, "resources/Test_Conversion_Geo.csv"),
+            delimiter=",",
+            dtype="S4,f8,f8",
+            names=["site", "lat1", "long1"],
+            usecols=("lat1", "long1"),
+        )
+
+        test_geo_coord2 = np.genfromtxt(
+            os.path.join(abs_path, "resources/Test_Conversion_Geo.csv"),
+            delimiter=",",
+            dtype="S4,f8,f8",
+            names=["site", "lat2", "long2"],
+            usecols=("lat2", "long2"),
+        )
 
         # Form array with point pairs from test file
-        test_pairs = rfn.merge_arrays([test_geo_coords, np.roll(test_geo_coord2, 1)], flatten=True)
+        test_pairs = rfn.merge_arrays(
+            [test_geo_coords, np.roll(test_geo_coord2, 1)], flatten=True
+        )
 
         # Calculate Vincenty's Inverse Result using Lat, Long Pairs
-        vincinv_result = np.array(list(vincinv(*x) for x in test_pairs[['lat1', 'long1', 'lat2', 'long2']]))
+        vincinv_result = np.array(
+            list(vincinv(*x) for x in test_pairs[["lat1", "long1", "lat2", "long2"]])
+        )
 
         # Calculate Vincenty's Direct Result using Results from Inverse Function
-        vincdir_input = rfn.merge_arrays([test_geo_coords, vincinv_result[:, 1], vincinv_result[:, 0]], flatten=True)
-        vincdir_input.dtype.names = ['lat1', 'long1', 'az1to2', 'ell_dist']
-        vincdir_result = np.array(list(vincdir(*x) for x in vincdir_input[['lat1', 'long1', 'az1to2', 'ell_dist']]))
-
-        np.testing.assert_almost_equal(test_pairs['lat2'],
-                                       vincdir_result[:, 0], decimal=8)
-        np.testing.assert_almost_equal(test_pairs['long2'],
-                                       vincdir_result[:, 1], decimal=8)
-        np.testing.assert_almost_equal(vincinv_result[:, 2],
-                                       vincdir_result[:, 2])
+        vincdir_input = rfn.merge_arrays(
+            [test_geo_coords, vincinv_result[:, 1], vincinv_result[:, 0]], flatten=True
+        )
+        vincdir_input.dtype.names = ["lat1", "long1", "az1to2", "ell_dist"]
+        vincdir_result = np.array(
+            list(
+                vincdir(*x)
+                for x in vincdir_input[["lat1", "long1", "az1to2", "ell_dist"]]
+            )
+        )
+
+        np.testing.assert_almost_equal(
+            test_pairs["lat2"], vincdir_result[:, 0], decimal=8
+        )
+        np.testing.assert_almost_equal(
+            test_pairs["long2"], vincdir_result[:, 1], decimal=8
+        )
+        np.testing.assert_almost_equal(vincinv_result[:, 2], vincdir_result[:, 2])
 
     def test_vincinv_edgecases(self):
         lat1 = -32.153892
@@ -251,5 +277,5 @@ def test_vincinv_edgecases(self):
         self.assertEqual(az21, az21_2)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     unittest.main()
diff --git a/geodepy/tests/test_statistics.py b/geodepy/tests/test_statistics.py
index 3172c5f..561b347 100644
--- a/geodepy/tests/test_statistics.py
+++ b/geodepy/tests/test_statistics.py
@@ -4,23 +4,19 @@
 
 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]
-])
-var = np.array([
-    [1.44], [1.20], [1.20]
-])
+vcv = np.array([[1.44, -1.32, 1.32], [-1.32, 1.22, -1.20], [1.32, -1.20, 1.20]])
+var = np.array([[1.44], [1.20], [1.20]])
 
 
 class TestStatistics(unittest.TestCase):
     def test_rotation_matrix(self):
-        expected_result = np.array([
-            [-0.94376147, -0.1102527, 0.3117028],
-            [0.33062712, -0.31471177, 0.88974278],
-            [0.0,  0.94276235,  0.33346538],
-        ])
+        expected_result = np.array(
+            [
+                [-0.94376147, -0.1102527, 0.3117028],
+                [0.33062712, -0.31471177, 0.88974278],
+                [0.0, 0.94276235, 0.33346538],
+            ]
+        )
 
         result = statistics.rotation_matrix(lat, lon)
 
@@ -28,11 +24,13 @@ def test_rotation_matrix(self):
         self.assertEqual(type(expected_result), type(result))
 
     def test_vcv_cart2local_3x3(self):
-        expected_result = np.array([
-            [2.23971834, -1.86955194, 0.3599339],
-            [-1.86955194, 1.55096504, -0.29615085],
-            [0.3599339, -0.29615085, 0.06931662]
-        ])
+        expected_result = np.array(
+            [
+                [2.23971834, -1.86955194, 0.3599339],
+                [-1.86955194, 1.55096504, -0.29615085],
+                [0.3599339, -0.29615085, 0.06931662],
+            ]
+        )
 
         result = statistics.vcv_cart2local(vcv, lat, lon)
 
@@ -40,9 +38,7 @@ def test_vcv_cart2local_3x3(self):
         self.assertEqual(type(expected_result), type(result))
 
     def test_vcv_cart2local_3x1(self):
-        expected_result = np.array([
-            [1.41376457], [1.20291736], [1.22331807]
-        ])
+        expected_result = np.array([[1.41376457], [1.20291736], [1.22331807]])
 
         result = statistics.vcv_cart2local(var, lat, lon)
 
@@ -56,11 +52,13 @@ def test_vcv_cart2local_3X2(self):
             statistics.vcv_cart2local(v_cart, 0.0, 0.0)
 
     def test_vcv_local2cart_3X3(self):
-        expected_result = np.array([
-            [0.44517136, -1.15507667, 0.44844663],
-            [-1.15507667, 2.95156126, -1.15249271],
-            [0.44844663, -1.15249271, 0.46326737]
-        ])
+        expected_result = np.array(
+            [
+                [0.44517136, -1.15507667, 0.44844663],
+                [-1.15507667, 2.95156126, -1.15249271],
+                [0.44844663, -1.15249271, 0.46326737],
+            ]
+        )
 
         result = statistics.vcv_local2cart(vcv, lat, lon)
 
@@ -68,9 +66,7 @@ def test_vcv_local2cart_3X3(self):
         self.assertEqual(type(expected_result), type(result))
 
     def test_vcv_local2cart_3X1(self):
-        expected_result = np.array([
-            [1.41376457], [1.20291736], [1.22331807]
-        ])
+        expected_result = np.array([[1.41376457], [1.20291736], [1.22331807]])
 
         result = statistics.vcv_cart2local(var, lat, lon)
 
@@ -84,8 +80,7 @@ def test_vcv_local2cart_3X2(self):
             statistics.vcv_local2cart(v_cart, lat, lon)
 
     def test_error_ellipse(self):
-        expected_result = (1.6292867776015223, 0.07365185899111726,
-                           132.61817915463692)
+        expected_result = (1.6292867776015223, 0.07365185899111726, 132.61817915463692)
 
         result = statistics.error_ellipse(vcv)
 
@@ -95,33 +90,39 @@ def test_error_ellipse(self):
     def test_relative_error(self):
         lat1 = -33.371389383333
         lon1 = 145.673034975000
-        var1 = np.array([
-            [1.7671344090e-04, -8.9986817000e-05, 1.1789951440e-04],
-            [-8.9986817000e-05, 1.0963890720e-04, -7.1820721020e-05],
-            [1.1789951440e-04, -7.1820721020e-05, 1.4015891560e-04]
-        ])
-        var2 = np.array([
-            [1.7105233790e-04, -8.8389059620e-05, 1.1156043490e-04],
-            [-8.8389059620e-05, 1.0754378720e-04, -6.8637225330e-05],
-            [1.1156043490e-04, -6.8637225330e-05, 1.3097055280e-04]
-        ])
-        cov12 = np.array([
-            [1.5518691860e-04, -7.8107376300e-05, 1.0312885480e-04],
-            [-7.8392614650e-05, 9.5884929150e-05, -6.2159214580e-05],
-            [1.0310493330e-04, -6.1905790840e-05, 1.2226743540e-04]
-        ])
+        var1 = np.array(
+            [
+                [1.7671344090e-04, -8.9986817000e-05, 1.1789951440e-04],
+                [-8.9986817000e-05, 1.0963890720e-04, -7.1820721020e-05],
+                [1.1789951440e-04, -7.1820721020e-05, 1.4015891560e-04],
+            ]
+        )
+        var2 = np.array(
+            [
+                [1.7105233790e-04, -8.8389059620e-05, 1.1156043490e-04],
+                [-8.8389059620e-05, 1.0754378720e-04, -6.8637225330e-05],
+                [1.1156043490e-04, -6.8637225330e-05, 1.3097055280e-04],
+            ]
+        )
+        cov12 = np.array(
+            [
+                [1.5518691860e-04, -7.8107376300e-05, 1.0312885480e-04],
+                [-7.8392614650e-05, 9.5884929150e-05, -6.2159214580e-05],
+                [1.0310493330e-04, -6.1905790840e-05, 1.2226743540e-04],
+            ]
+        )
 
         expected_results = (
             0.003122110653270988,
             0.0028032035987053208,
             133.65771030508103,
-            0.008473125158578584
+            0.008473125158578584,
         )
 
         results = statistics.relative_error(lat1, lon1, var1, var2, cov12)
         np.testing.assert_almost_equal(expected_results, results)
         self.assertEqual(type(expected_results), type(results))
-        
+
     def test_circ_hz_pu(self):
         a = 1
         b = 0
@@ -163,5 +164,5 @@ def test_k_val95_between_1_and_120(self):
         self.assertEqual(expected_result, result)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     unittest.main()
diff --git a/geodepy/tests/test_survey.py b/geodepy/tests/test_survey.py
index ad06595..9a5349c 100644
--- a/geodepy/tests/test_survey.py
+++ b/geodepy/tests/test_survey.py
@@ -1,8 +1,15 @@
 import unittest
 from geodepy.convert import DMSAngle
-from geodepy.survey import (first_vel_params, first_vel_corrn, 
-                            mets_partial_differentials, precise_inst_ht, 
-                            va_conv, radiations, joins)
+from geodepy.survey import (
+    first_vel_params,
+    first_vel_corrn,
+    mets_partial_differentials,
+    precise_inst_ht,
+    va_conv,
+    radiations,
+    joins,
+)
+
 
 class TestSurveyConvert(unittest.TestCase):
     def test_first_vel_params(self):
@@ -16,43 +23,52 @@ def test_first_vel_params(self):
         self.assertEqual(round(params_new[1], 3), param_d)
 
     def test_first_vel_corrn(self):
-        params = first_vel_params(0.85,49951.33424,1.000281783)
+        params = first_vel_params(0.85, 49951.33424, 1.000281783)
         raw_obs_distance = 1117.8517
         obs_temperature = 6.8
         obs_pressure = 960.8
         obs_relative_humidity = 58.6
-        correction = first_vel_corrn(raw_obs_distance, params, obs_temperature,
-                                     obs_pressure, obs_relative_humidity)
+        correction = first_vel_corrn(
+            raw_obs_distance,
+            params,
+            obs_temperature,
+            obs_pressure,
+            obs_relative_humidity,
+        )
         corrected_obs_distance = raw_obs_distance + correction
         self.assertEqual(round(corrected_obs_distance, 4), 1117.8624)
 
     def test_first_vel_corrn_with_CO2(self):
         edm_wavelength = 0.850
-        params = first_vel_params(edm_wavelength,49951.33424,1.000281783)
+        params = first_vel_params(edm_wavelength, 49951.33424, 1.000281783)
         raw_obs_distance = 1117.8517
         obs_temperature = 6.8
         obs_pressure = 960.8
         obs_relative_humidity = 58.6
         CO2_ppm_2022 = 420
-        correction = first_vel_corrn(raw_obs_distance, params, obs_temperature,
-                                     obs_pressure, obs_relative_humidity,
-                                     CO2_ppm = CO2_ppm_2022, 
-                                     wavelength = edm_wavelength)
+        correction = first_vel_corrn(
+            raw_obs_distance,
+            params,
+            obs_temperature,
+            obs_pressure,
+            obs_relative_humidity,
+            CO2_ppm=CO2_ppm_2022,
+            wavelength=edm_wavelength,
+        )
         corrected_obs_distance = raw_obs_distance + correction
         self.assertEqual(round(corrected_obs_distance, 4), 1117.8624)
-        
+
     def test_mets_partial_differentials(self):
         group_ref_Index = 1.00028
         temp = 15
         pressure = 1013.25
         rel_humidity = 60
-        K = round(0.91973804217265260,2)
-        L = round(0.2619533756724471,2)
-        M = round(0.03911157383307305,2)
-        differ_new = mets_partial_differentials(group_ref_Index, 
-                                                temp, 
-                                                pressure,
-                                                rel_humidity)
+        K = round(0.91973804217265260, 2)
+        L = round(0.2619533756724471, 2)
+        M = round(0.03911157383307305, 2)
+        differ_new = mets_partial_differentials(
+            group_ref_Index, temp, pressure, rel_humidity
+        )
         self.assertEqual(round(differ_new[0], 2), K)
         self.assertEqual(round(differ_new[1], 2), L)
         self.assertEqual(round(differ_new[2], 2), M)
@@ -80,7 +96,7 @@ def test_va_conv(self):
         self.assertAlmostEqual(test4[3], 1.69995, 5)
         with self.assertRaises(ValueError):
             va_conv(-3.62, 1.5)
-            va_conv('brian', 16)
+            va_conv("brian", 16)
 
     def test_precise_inst_ht(self):
         va1 = 99.50920833333333
@@ -111,20 +127,30 @@ def test_joins(self):
         self.assertAlmostEqual(test4[1], 172.0831, 4)
 
     def test_radiations(self):
-        test1 = radiations(500, 500,
-                           DMSAngle(290, 13).dec(), 44.620,
-                           DMSAngle(2, 18, 35).dec(), 1.002515)
+        test1 = radiations(
+            500,
+            500,
+            DMSAngle(290, 13).dec(),
+            44.620,
+            DMSAngle(2, 18, 35).dec(),
+            1.002515,
+        )
         self.assertAlmostEqual(test1[0], 458.681, 3)
         self.assertAlmostEqual(test1[1], 517.137, 3)
         test2 = radiations(500, 500, DMSAngle(290, 13).dec(), 44.620)
         self.assertAlmostEqual(test2[0], 458.129, 3)
         self.assertAlmostEqual(test2[1], 515.419, 3)
-        test3 = radiations(564.747, 546.148,
-                           DMSAngle(41, 7).dec(), 27.720,
-                           DMSAngle(2, 18, 35).dec(), 1.002515)
+        test3 = radiations(
+            564.747,
+            546.148,
+            DMSAngle(41, 7).dec(),
+            27.720,
+            DMSAngle(2, 18, 35).dec(),
+            1.002515,
+        )
         self.assertAlmostEqual(test3[0], 583.850, 3)
         self.assertAlmostEqual(test3[1], 566.331, 3)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     unittest.main()
diff --git a/geodepy/tests/test_transform.py b/geodepy/tests/test_transform.py
index 246be5e..6b67933 100644
--- a/geodepy/tests/test_transform.py
+++ b/geodepy/tests/test_transform.py
@@ -1,12 +1,14 @@
 import unittest
 
-from geodepy.transform import (conform7,
-                               conform14,
-                               atrf2014_to_gda2020,
-                               transform_gda2020_to_atrf2014,
-                               transform_atrf2014_to_gda2020,
-                               transform_mga94_to_mga2020,
-                               transform_mga2020_to_mga94)
+from geodepy.transform import (
+    conform7,
+    conform14,
+    atrf2014_to_gda2020,
+    transform_gda2020_to_atrf2014,
+    transform_atrf2014_to_gda2020,
+    transform_mga94_to_mga2020,
+    transform_mga2020_to_mga94,
+)
 from geodepy.constants import itrf2014_to_gda2020, gda94_to_gda2020
 from datetime import date
 
@@ -20,70 +22,86 @@ def test_conform7(self):
         alic_gda2020 = (-4052052.7379, 4212835.9897, -2545104.5898)
         alic_gda2020_comp = conform7(*alic_gda1994, gda94_to_gda2020)
         alic_gda1994_comp = conform7(*alic_gda2020, -gda94_to_gda2020)
-        assert (abs(alic_gda2020_comp[0] - alic_gda2020[0]) < 5e-5)
-        assert (abs(alic_gda2020_comp[1] - alic_gda2020[1]) < 5e-5)
-        assert (abs(alic_gda2020_comp[2] - alic_gda2020[2]) < 5e-5)
-        assert (abs(alic_gda1994_comp[0] - alic_gda1994[0]) < 5e-5)
-        assert (abs(alic_gda1994_comp[1] - alic_gda1994[1]) < 5e-5)
-        assert (abs(alic_gda1994_comp[2] - alic_gda1994[2]) < 5e-5)
+        assert abs(alic_gda2020_comp[0] - alic_gda2020[0]) < 5e-5
+        assert abs(alic_gda2020_comp[1] - alic_gda2020[1]) < 5e-5
+        assert abs(alic_gda2020_comp[2] - alic_gda2020[2]) < 5e-5
+        assert abs(alic_gda1994_comp[0] - alic_gda1994[0]) < 5e-5
+        assert abs(alic_gda1994_comp[1] - alic_gda1994[1]) < 5e-5
+        assert abs(alic_gda1994_comp[2] - alic_gda1994[2]) < 5e-5
 
     def test_conform14(self):
         # Replication of tests in GDA2020 Tech Manual v1.2 - Sect 3.3.1
         alic_gda2020 = (-4052052.7373, 4212835.9835, -2545104.5867)
         alic_itrf14at2018 = (-4052052.6588, 4212835.9938, -2545104.6946)
-        alic_itrf14at2018_comp = conform14(*alic_gda2020, date(2018, 1, 1), -itrf2014_to_gda2020)
-        alic_gda2020_comp = conform14(*alic_itrf14at2018, date(2018, 1, 1), itrf2014_to_gda2020)
-        assert (abs(alic_itrf14at2018_comp[0] - alic_itrf14at2018[0]) < 5e-5)
-        assert (abs(alic_itrf14at2018_comp[1] - alic_itrf14at2018[1]) < 5e-5)
-        assert (abs(alic_itrf14at2018_comp[2] - alic_itrf14at2018[2]) < 5e-5)
-        assert (abs(alic_gda2020_comp[0] - alic_gda2020[0]) < 5e-5)
-        assert (abs(alic_gda2020_comp[1] - alic_gda2020[1]) < 5e-5)
-        assert (abs(alic_gda2020_comp[2] - alic_gda2020[2]) < 5e-5)
+        alic_itrf14at2018_comp = conform14(
+            *alic_gda2020, date(2018, 1, 1), -itrf2014_to_gda2020
+        )
+        alic_gda2020_comp = conform14(
+            *alic_itrf14at2018, date(2018, 1, 1), itrf2014_to_gda2020
+        )
+        assert abs(alic_itrf14at2018_comp[0] - alic_itrf14at2018[0]) < 5e-5
+        assert abs(alic_itrf14at2018_comp[1] - alic_itrf14at2018[1]) < 5e-5
+        assert abs(alic_itrf14at2018_comp[2] - alic_itrf14at2018[2]) < 5e-5
+        assert abs(alic_gda2020_comp[0] - alic_gda2020[0]) < 5e-5
+        assert abs(alic_gda2020_comp[1] - alic_gda2020[1]) < 5e-5
+        assert abs(alic_gda2020_comp[2] - alic_gda2020[2]) < 5e-5
 
     def test_transform_atrf2014_to_gda2020(self):
         alic_gda2020 = (-4052052.7373, 4212835.9835, -2545104.5867)
         alic_itrf14at2018 = (-4052052.6588, 4212835.9938, -2545104.6946)
-        alic_itrf14at2018_comp = transform_gda2020_to_atrf2014(*alic_gda2020, date(2018, 1, 1))
-        alic_gda2020_comp = transform_atrf2014_to_gda2020(*alic_itrf14at2018, date(2018, 1, 1))
-        assert (abs(alic_itrf14at2018_comp[0] - alic_itrf14at2018[0]) < 5e-5)
-        assert (abs(alic_itrf14at2018_comp[1] - alic_itrf14at2018[1]) < 5e-5)
-        assert (abs(alic_itrf14at2018_comp[2] - alic_itrf14at2018[2]) < 5e-5)
-        assert (abs(alic_gda2020_comp[0] - alic_gda2020[0]) < 5e-5)
-        assert (abs(alic_gda2020_comp[1] - alic_gda2020[1]) < 5e-5)
-        assert (abs(alic_gda2020_comp[2] - alic_gda2020[2]) < 5e-5)
+        alic_itrf14at2018_comp = transform_gda2020_to_atrf2014(
+            *alic_gda2020, date(2018, 1, 1)
+        )
+        alic_gda2020_comp = transform_atrf2014_to_gda2020(
+            *alic_itrf14at2018, date(2018, 1, 1)
+        )
+        assert abs(alic_itrf14at2018_comp[0] - alic_itrf14at2018[0]) < 5e-5
+        assert abs(alic_itrf14at2018_comp[1] - alic_itrf14at2018[1]) < 5e-5
+        assert abs(alic_itrf14at2018_comp[2] - alic_itrf14at2018[2]) < 5e-5
+        assert abs(alic_gda2020_comp[0] - alic_gda2020[0]) < 5e-5
+        assert abs(alic_gda2020_comp[1] - alic_gda2020[1]) < 5e-5
+        assert abs(alic_gda2020_comp[2] - alic_gda2020[2]) < 5e-5
 
     def test_transform_mga94_to_mga2020(self):
         alic_mga94 = (53, 386352.3979, 7381850.7689, 603.3466)
         alic_mga20 = (53, 386353.2343, 7381852.2986, 603.2489)
         # Test with no ellipsoid height supplied
-        alic_mga20_noellht_comp = transform_mga94_to_mga2020(alic_mga94[0], alic_mga94[1], alic_mga94[2])
-        assert ((alic_mga20_noellht_comp[0] - alic_mga20[0]) == 0)
-        assert (abs(alic_mga20_noellht_comp[1] - alic_mga20[1]) < 5e-5)
-        assert (abs(alic_mga20_noellht_comp[2] - alic_mga20[2]) < 5e-5)
-        assert (alic_mga20_noellht_comp[3] == 0)
+        alic_mga20_noellht_comp = transform_mga94_to_mga2020(
+            alic_mga94[0], alic_mga94[1], alic_mga94[2]
+        )
+        assert (alic_mga20_noellht_comp[0] - alic_mga20[0]) == 0
+        assert abs(alic_mga20_noellht_comp[1] - alic_mga20[1]) < 5e-5
+        assert abs(alic_mga20_noellht_comp[2] - alic_mga20[2]) < 5e-5
+        assert alic_mga20_noellht_comp[3] == 0
         # Test with ellipsoid height supplied
-        alic_mga20_ellht_comp = transform_mga94_to_mga2020(alic_mga94[0], alic_mga94[1], alic_mga94[2], alic_mga94[3])
-        assert ((alic_mga20_ellht_comp[0] - alic_mga20[0]) == 0)
-        assert (abs(alic_mga20_ellht_comp[1] - alic_mga20[1]) < 5e-5)
-        assert (abs(alic_mga20_ellht_comp[2] - alic_mga20[2]) < 5e-5)
-        assert (abs(alic_mga20_ellht_comp[3] - alic_mga20[3]) < 5e-5)
+        alic_mga20_ellht_comp = transform_mga94_to_mga2020(
+            alic_mga94[0], alic_mga94[1], alic_mga94[2], alic_mga94[3]
+        )
+        assert (alic_mga20_ellht_comp[0] - alic_mga20[0]) == 0
+        assert abs(alic_mga20_ellht_comp[1] - alic_mga20[1]) < 5e-5
+        assert abs(alic_mga20_ellht_comp[2] - alic_mga20[2]) < 5e-5
+        assert abs(alic_mga20_ellht_comp[3] - alic_mga20[3]) < 5e-5
 
     def test_transform_mga2020_to_mga94(self):
         alic_mga94 = (53, 386352.3979, 7381850.7689, 603.3466)
         alic_mga20 = (53, 386353.2343, 7381852.2986, 603.2489)
         # Test with no ellipsoid height supplied
-        alic_mga94_noellht_comp = transform_mga2020_to_mga94(alic_mga20[0], alic_mga20[1], alic_mga20[2])
-        assert ((alic_mga94_noellht_comp[0] - alic_mga94[0]) == 0)
-        assert (abs(alic_mga94_noellht_comp[1] - alic_mga94[1]) < 5e-5)
-        assert (abs(alic_mga94_noellht_comp[2] - alic_mga94[2]) < 5e-5)
-        assert (alic_mga94_noellht_comp[3] == 0)
+        alic_mga94_noellht_comp = transform_mga2020_to_mga94(
+            alic_mga20[0], alic_mga20[1], alic_mga20[2]
+        )
+        assert (alic_mga94_noellht_comp[0] - alic_mga94[0]) == 0
+        assert abs(alic_mga94_noellht_comp[1] - alic_mga94[1]) < 5e-5
+        assert abs(alic_mga94_noellht_comp[2] - alic_mga94[2]) < 5e-5
+        assert alic_mga94_noellht_comp[3] == 0
         # Test with ellipsoid height supplied
-        alic_mga94_ellht_comp = transform_mga2020_to_mga94(alic_mga20[0], alic_mga20[1], alic_mga20[2], alic_mga20[3])
-        assert ((alic_mga94_ellht_comp[0] - alic_mga94[0]) == 0)
-        assert (abs(alic_mga94_ellht_comp[1] - alic_mga94[1]) < 5e-5)
-        assert (abs(alic_mga94_ellht_comp[2] - alic_mga94[2]) < 5e-5)
-        assert (abs(alic_mga94_ellht_comp[3] - alic_mga94[3]) < 5e-5)
+        alic_mga94_ellht_comp = transform_mga2020_to_mga94(
+            alic_mga20[0], alic_mga20[1], alic_mga20[2], alic_mga20[3]
+        )
+        assert (alic_mga94_ellht_comp[0] - alic_mga94[0]) == 0
+        assert abs(alic_mga94_ellht_comp[1] - alic_mga94[1]) < 5e-5
+        assert abs(alic_mga94_ellht_comp[2] - alic_mga94[2]) < 5e-5
+        assert abs(alic_mga94_ellht_comp[3] - alic_mga94[3]) < 5e-5
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     unittest.main()
diff --git a/geodepy/transform.py b/geodepy/transform.py
index c41c772..9e5aa1f 100644
--- a/geodepy/transform.py
+++ b/geodepy/transform.py
@@ -14,11 +14,14 @@
 import datetime
 from math import radians
 import numpy as np
-from geodepy.constants import (Transformation, TransformationSD,
-                               atrf2014_to_gda2020, gda94_to_gda2020)
+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 hp2dec, geo2grid, grid2geo, xyz2llh, llh2xyz
 from geodepy.ntv2reader import NTv2Grid, interpolate_ntv2
 
 
@@ -26,6 +29,7 @@ def conform7(x, y, z, trans, vcv=None):
     """
     Performs a Helmert 7 Parameter Conformal Transformation using Cartesian point co-ordinates
     and a predefined transformation object.
+
     :param x: Cartesian X (m)
     :param y: Cartesian Y (m)
     :param z: Cartesian Z (m)
@@ -34,24 +38,18 @@ def conform7(x, y, z, trans, vcv=None):
     :return: Transformed X, Y, Z Cartesian Co-ordinates, vcv matrix
     """
     if type(trans) != Transformation:
-        raise ValueError('trans must be a Transformation Object')
+        raise ValueError("trans must be a Transformation Object")
     # Create XYZ Vector
-    xyz_before = np.array([[x],
-                           [y],
-                           [z]])
+    xyz_before = np.array([[x], [y], [z]])
     # Convert Units for Transformation Parameters
     scale = 1 + trans.sc / 1000000
     rx = radians(hp2dec(trans.rx / 10000))
     ry = radians(hp2dec(trans.ry / 10000))
     rz = radians(hp2dec(trans.rz / 10000))
     # Create Translation Vector
-    translation = np.array([[trans.tx],
-                            [trans.ty],
-                            [trans.tz]])
+    translation = np.array([[trans.tx], [trans.ty], [trans.tz]])
     # Create Rotation Matrix
-    rotation = np.array([[1., rz, -ry],
-                         [-rz, 1., rx],
-                         [ry, -rx, 1.]])
+    rotation = np.array([[1.0, rz, -ry], [-rz, 1.0, rx], [ry, -rx, 1.0]])
 
     rot_xyz = rotation @ xyz_before
 
@@ -74,10 +72,10 @@ def conform7(x, y, z, trans, vcv=None):
                 q_mat[i, j] = vcv[i, j]
 
         # transformation variances
-        q_mat[3, 3] = (trans.tf_sd.sd_sc / 1000000)**2
-        q_mat[4, 4] = radians(trans.tf_sd.sd_rx/3600)**2
-        q_mat[5, 5] = radians(trans.tf_sd.sd_ry/3600)**2
-        q_mat[6, 6] = radians(trans.tf_sd.sd_rz/3600)**2
+        q_mat[3, 3] = (trans.tf_sd.sd_sc / 1000000) ** 2
+        q_mat[4, 4] = radians(trans.tf_sd.sd_rx / 3600) ** 2
+        q_mat[5, 5] = radians(trans.tf_sd.sd_ry / 3600) ** 2
+        q_mat[6, 6] = radians(trans.tf_sd.sd_rz / 3600) ** 2
         q_mat[7, 7] = trans.tf_sd.sd_tx**2
         q_mat[8, 8] = trans.tf_sd.sd_ty**2
         q_mat[9, 9] = trans.tf_sd.sd_tz**2
@@ -128,6 +126,7 @@ def conform14(x, y, z, to_epoch, trans, vcv=None):
     Performs a Helmert 14 Parameter Conformal Transformation using Cartesian point co-ordinates
     and a predefined transformation object. The transformation parameters are projected from
     the transformation objects reference epoch to a specified epoch.
+
     :param x: Cartesian X (m)
     :param y: Cartesian Y (m)
     :param z: Cartesian Z (m)
@@ -137,9 +136,9 @@ def conform14(x, y, z, to_epoch, trans, vcv=None):
     :return: Cartesian X, Y, Z co-ordinates and vcv matrix transformed using Transformation parameters at desired epoch
     """
     if type(trans) != Transformation:
-        raise ValueError('trans must be a Transformation Object')
+        raise ValueError("trans must be a Transformation Object")
     if type(to_epoch) != datetime.date:
-        raise ValueError('to_epoch must be a datetime.date Object')
+        raise ValueError("to_epoch must be a datetime.date Object")
     # Calculate 7 Parameters from 14 Parameter Transformation Object
     timetrans = trans + to_epoch
 
@@ -152,6 +151,7 @@ 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
     using the GDA2020 Tech Manual v1.2 7 parameter similarity transformation parameters
+
     :param zone: Zone Number - 1 to 60
     :param east: Easting (m, within 3330km of Central Meridian)
     :param north: Northing (m, 0 to 10,000,000m)
@@ -181,6 +181,7 @@ def transform_mga2020_to_mga94(zone, east, north, ell_ht=False, vcv=None):
     """
     Performs conformal transformation of Map Grid of Australia 2020 to Map Grid of Australia 1994 Coordinates
     using the reverse form of the GDA2020 Tech Manual v1.2 7 parameter similarity transformation parameters
+
     :param zone: Zone Number - 1 to 60
     :param east: Easting (m, within 3330km of Central Meridian)
     :param north: Northing (m, 0 to 10,000,000m)
@@ -210,6 +211,7 @@ def transform_atrf2014_to_gda2020(x, y, z, epoch_from, vcv=None):
     """
     Transforms Cartesian (x, y, z) Coordinates in terms of the Australian Terrestrial Reference Frame (ATRF) at
     a specified epoch to coordinates in terms of Geocentric Datum of Australia 2020 (GDA2020 - reference epoch 2020.0)
+
     :param x: ATRF Cartesian X Coordinate (m)
     :param y: ATRF Cartesian Y Coordinate (m)
     :param z: ATRF Cartesian Z Coordinate (m)
@@ -225,6 +227,7 @@ def transform_gda2020_to_atrf2014(x, y, z, epoch_to, vcv=None):
     Transforms Cartesian (x, y, z) Coordinates in terms of Geocentric Datum of Australia 2020
     (GDA2020 - reference epoch 2020.0) to coordinates in terms of the Australian Terrestrial Reference Frame (ATRF) at
     a specified epoch
+
     :param x: GDA2020 Cartesian X Coordinate (m)
     :param y: GDA2020 Cartesian Y Coordinate (m)
     :param z: GDA2020 Cartesian Z Coordinate (m)
@@ -235,9 +238,10 @@ def transform_gda2020_to_atrf2014(x, y, z, epoch_to, vcv=None):
     return conform14(x, y, z, epoch_to, -atrf2014_to_gda2020, vcv=vcv)
 
 
-def ntv2_2d(ntv2_grid, lat, lon, forward_tf=True, method='bicubic'):
+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
@@ -250,8 +254,8 @@ def ntv2_2d(ntv2_grid, lat, lon, forward_tf=True, method='bicubic'):
 
     # validate input data
     if not isinstance(ntv2_grid, NTv2Grid):
-        raise TypeError('ntv2_grid must be Ntv2Grid object')
-    if method != 'bicubic' and method != 'bilinear':
+        raise TypeError("ntv2_grid must be Ntv2Grid object")
+    if method != "bicubic" and method != "bilinear":
         raise ValueError(f'interpolation strategy "{method}" not supported')
 
     # interrogate grid
@@ -259,7 +263,7 @@ def ntv2_2d(ntv2_grid, lat, lon, forward_tf=True, method='bicubic'):
 
     # null results are outside of grid extents.
     if shifts[0] is None:
-        raise ValueError('Coordinate outside of grid extents')
+        raise ValueError("Coordinate outside of grid extents")
 
     if forward_tf:
         tf_lat = lat + shifts[0] / 3600
