diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 087d0de67da5b0faebcea69187293ed4ce75fc57..6b5dbc4f7d68c27870081fcfbcf3089e31f6053e 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,5 +1,5 @@
 repos:
--   repo: https://github.com/ambv/black
-    rev: stable
+  - repo: https://github.com/ambv/black
+    rev: 20.8b1
     hooks:
-    - id: black
+      - id: black
diff --git a/bin/monitor.py b/bin/monitor.py
index 7910bb098a5883697e5040fe411960de035e7675..ad57d77a103778e582ca877b9a5d9a9a36d54cee 100755
--- a/bin/monitor.py
+++ b/bin/monitor.py
@@ -91,7 +91,7 @@ def get_gap_total(gaps, interval):
 
 
 def get_last_time(gaps, endtime):
-    """ Return the last time that a channel has in it.
+    """Return the last time that a channel has in it.
     Parameters
     ----------
     gaps: array
@@ -141,7 +141,7 @@ def get_table_header():
 
 
 def has_gaps(gaps):
-    """ Returns True if gaps dictionary has gaps in it.
+    """Returns True if gaps dictionary has gaps in it.
     Parameters
     ----------
     gaps: dictionary
diff --git a/geomagio/PlotTimeseriesFactory.py b/geomagio/PlotTimeseriesFactory.py
index db9574e4f692a22471e761c1c32b2f26eceaac2f..a892b5e03f9cff0ba9f81d99741db9b9f43d710e 100644
--- a/geomagio/PlotTimeseriesFactory.py
+++ b/geomagio/PlotTimeseriesFactory.py
@@ -6,8 +6,7 @@ from .TimeseriesFactory import TimeseriesFactory
 
 
 class PlotTimeseriesFactory(TimeseriesFactory):
-    """TimeseriesFactory that generates a plot.
-    """
+    """TimeseriesFactory that generates a plot."""
 
     def __init__(self, *args, **kwargs):
         TimeseriesFactory.__init__(self, *args, **kwargs)
@@ -21,8 +20,7 @@ class PlotTimeseriesFactory(TimeseriesFactory):
         type=None,
         interval=None,
     ):
-        """This factory does not support get_timeseries.
-        """
+        """This factory does not support get_timeseries."""
         raise NotImplementedError('"get_timeseries" not implemented')
 
     def put_timeseries(
diff --git a/geomagio/StreamTimeseriesFactory.py b/geomagio/StreamTimeseriesFactory.py
index 56ae0dcb4fa001fcf935045052a1112913b4032f..32837aca5c083431318df3630cfb837a8a6481e3 100644
--- a/geomagio/StreamTimeseriesFactory.py
+++ b/geomagio/StreamTimeseriesFactory.py
@@ -34,8 +34,7 @@ class StreamTimeseriesFactory(TimeseriesFactory):
         type=None,
         interval=None,
     ):
-        """Get timeseries using stream as input.
-        """
+        """Get timeseries using stream as input."""
         if self.stream_data is None:
             # only read stream once
             self.stream_data = self.stream.read()
@@ -55,6 +54,5 @@ class StreamTimeseriesFactory(TimeseriesFactory):
         type=None,
         interval=None,
     ):
-        """Put timeseries using stream as output.
-        """
+        """Put timeseries using stream as output."""
         self.factory.write_file(self.stream, timeseries, channels)
diff --git a/geomagio/algorithm/AdjustedAlgorithm.py b/geomagio/algorithm/AdjustedAlgorithm.py
index 0c1bbf2f646283c76dc20d40f79cbd31f2625c7d..601bad2444246efeee5b0f81f4551f245e3a9406 100644
--- a/geomagio/algorithm/AdjustedAlgorithm.py
+++ b/geomagio/algorithm/AdjustedAlgorithm.py
@@ -27,7 +27,9 @@ class AdjustedAlgorithm(Algorithm):
         inchannels = inchannels or ["H", "E", "Z", "F"]
         outchannels = outchannels or ["X", "Y", "Z", "F"]
         Algorithm.__init__(
-            self, inchannels=inchannels, outchannels=outchannels,
+            self,
+            inchannels=inchannels,
+            outchannels=outchannels,
         )
         # state variables
         self.matrix = matrix
diff --git a/geomagio/algorithm/FilterAlgorithm.py b/geomagio/algorithm/FilterAlgorithm.py
index ee81bb47984149c37d5d050e5987fc8c3eee2bc5..99b7177bdafa51ec4541f24d12193cb498f92eae 100644
--- a/geomagio/algorithm/FilterAlgorithm.py
+++ b/geomagio/algorithm/FilterAlgorithm.py
@@ -35,7 +35,7 @@ STEPS = [
 
 class FilterAlgorithm(Algorithm):
     """
-        Filter Algorithm that filters and downsamples data
+    Filter Algorithm that filters and downsamples data
     """
 
     def __init__(
diff --git a/geomagio/algorithm/SqDistAlgorithm.py b/geomagio/algorithm/SqDistAlgorithm.py
index d9aa1584a957f8b79023dc6f607ee927ca4dd2ad..4344505404d76f0891ee3a957f33c75807646fc9 100644
--- a/geomagio/algorithm/SqDistAlgorithm.py
+++ b/geomagio/algorithm/SqDistAlgorithm.py
@@ -101,8 +101,7 @@ class SqDistAlgorithm(Algorithm):
         return (start - 3 * 30 * 24 * 60 * 60, end)
 
     def get_next_starttime(self):
-        """Return the next_starttime from the state, if it is set.
-        """
+        """Return the next_starttime from the state, if it is set."""
         return self.next_starttime
 
     def clear_state(self):
diff --git a/geomagio/algorithm/XYZAlgorithm.py b/geomagio/algorithm/XYZAlgorithm.py
index d87b4c0996f0b7c54b0d9cb3489fceab871b5dd6..1f43c87853c8da21d7a4636ad1bf7560f35e5471 100644
--- a/geomagio/algorithm/XYZAlgorithm.py
+++ b/geomagio/algorithm/XYZAlgorithm.py
@@ -58,7 +58,7 @@ class XYZAlgorithm(Algorithm):
 
     def get_required_channels(self):
         """Only the first two channels are required
-            for the XYZAlgorithm
+        for the XYZAlgorithm
         """
         return self._inchannels[:2]
 
diff --git a/geomagio/api/db/create.py b/geomagio/api/db/create.py
index 80fc17e878bde68070f327f8e79278fa06a7dfdc..0ccc0a97a0d0ce5161a3850dfc0d8588ada2fdfd 100644
--- a/geomagio/api/db/create.py
+++ b/geomagio/api/db/create.py
@@ -8,8 +8,7 @@ from .session_table import session
 
 
 def create_db():
-    """Create the database using sqlalchemy.
-    """
+    """Create the database using sqlalchemy."""
     engine = sqlalchemy.create_engine(str(database.url))
     sqlalchemy_metadata.create_all(engine)
 
diff --git a/geomagio/api/secure/SessionMiddleware.py b/geomagio/api/secure/SessionMiddleware.py
index 1138e0797e0635e00c5ec2ac17ea28208594b178..04c621c18d6058340ca6aaa40f0334e883d10aaf 100644
--- a/geomagio/api/secure/SessionMiddleware.py
+++ b/geomagio/api/secure/SessionMiddleware.py
@@ -110,7 +110,10 @@ class SessionMiddleware:
         await self.save_session_callback(session_id, data)
 
     def set_cookie(
-        self, message: Message, value: str, max_age: int = None,
+        self,
+        message: Message,
+        value: str,
+        max_age: int = None,
     ):
         headers = MutableHeaders(scope=message)
         headers.append("Cache-Control", "no-cache")
diff --git a/geomagio/api/secure/app.py b/geomagio/api/secure/app.py
index 47dd3f61650efce3ffc2f7d296ec1bc55afe49ec..753b9e3bca9ff2cdfe4cda7fb6bd50d882b3f00c 100644
--- a/geomagio/api/secure/app.py
+++ b/geomagio/api/secure/app.py
@@ -35,8 +35,7 @@ app.include_router(metadata_router)
 
 @app.get("/")
 async def index(request: Request, user: User = Depends(current_user)):
-    """Route to demo user login.
-    """
+    """Route to demo user login."""
     if user:
         link = f"""
             Logged in as {user.email}<br/>
diff --git a/geomagio/api/secure/login.py b/geomagio/api/secure/login.py
index 3bc77487362ef38fc3cf26c660f292e1b770aefa..c3407d9317c5f6d4fad6f6a0f62c0b2b23d1df40 100644
--- a/geomagio/api/secure/login.py
+++ b/geomagio/api/secure/login.py
@@ -45,8 +45,7 @@ from starlette.responses import RedirectResponse
 
 
 class User(BaseModel):
-    """Information about a logged in user.
-    """
+    """Information about a logged in user."""
 
     email: str
     sub: str  # unique outh id
@@ -68,7 +67,9 @@ async def current_user(request: Request) -> Optional[User]:
     return None
 
 
-def require_user(allowed_groups: List[str] = None,) -> Callable[[Request, User], User]:
+def require_user(
+    allowed_groups: List[str] = None,
+) -> Callable[[Request, User], User]:
     """Create function to verifies user in allowed_groups
 
     Usage example:
@@ -113,8 +114,7 @@ router = APIRouter()
 
 @router.get("/authorize")
 async def authorize(request: Request):
-    """Authorize callback after authenticating using OpenID
-    """
+    """Authorize callback after authenticating using OpenID"""
 
     # finish login
     token = await oauth.openid.authorize_access_token(request)
@@ -135,8 +135,7 @@ async def authorize(request: Request):
 
 @router.get("/login")
 async def login(request: Request):
-    """Redirect to OpenID provider.
-    """
+    """Redirect to OpenID provider."""
     redirect_uri = request.url_for("authorize")
     # save original location
     if "Referer" in request.headers:
@@ -147,8 +146,7 @@ async def login(request: Request):
 
 @router.get("/logout")
 async def logout(request: Request):
-    """Clear session and redirect to index page.
-    """
+    """Clear session and redirect to index page."""
     request.session.pop("token", None)
     request.session.pop("user", None)
     return RedirectResponse(
@@ -162,6 +160,5 @@ async def logout(request: Request):
 
 @router.get("/user")
 async def user(request: Request, user: User = Depends(require_user())) -> User:
-    """Get currently logged in user.
-    """
+    """Get currently logged in user."""
     return user
diff --git a/geomagio/api/secure/metadata.py b/geomagio/api/secure/metadata.py
index 5e4f084622ff72c54eadfdb95e82838bf788e3cc..fb0dfc4cfeed3981e07d37f501062975c5055420 100644
--- a/geomagio/api/secure/metadata.py
+++ b/geomagio/api/secure/metadata.py
@@ -31,7 +31,9 @@ router = APIRouter()
 
 @router.post("/metadata", response_model=Metadata)
 async def create_metadata(
-    request: Request, metadata: Metadata, user: User = Depends(require_user()),
+    request: Request,
+    metadata: Metadata,
+    user: User = Depends(require_user()),
 ):
     metadata = await metadata_table.create_metadata(metadata)
     return Response(metadata, status_code=201, media_type="application/json")
diff --git a/geomagio/api/ws/Element.py b/geomagio/api/ws/Element.py
index eff80cca91d247ee2cd5f3cc664c5ab648ca54f7..952feae9024d7fb3f42d00e5a5fa01166018773d 100644
--- a/geomagio/api/ws/Element.py
+++ b/geomagio/api/ws/Element.py
@@ -24,7 +24,10 @@ ELEMENTS = [
     Element(id="SQ", name="Solar Quiet", units="nT"),
     Element(id="SV", name="Solar Variation", units="nT"),
     Element(
-        id="UK1", abbreviation="T-Electric", name="Electronics Temperature", units="°C",
+        id="UK1",
+        abbreviation="T-Electric",
+        name="Electronics Temperature",
+        units="°C",
     ),
     Element(
         id="UK2",
diff --git a/geomagio/api/ws/app.py b/geomagio/api/ws/app.py
index b8b96a49b0bfca6233ec79d37fccae8f723027dc..9431fc44756063c5258b4052fc3dc4f0c35e2186 100644
--- a/geomagio/api/ws/app.py
+++ b/geomagio/api/ws/app.py
@@ -25,8 +25,6 @@ VERSION = os.getenv("GEOMAG_VERSION", "version")
 
 app = FastAPI(docs_url="/docs", root_path="/ws")
 
-app.add_middleware(CORSMiddleware, allow_origins=["*"], max_age=86400)
-
 app.include_router(algorithms.router)
 app.include_router(data.router)
 app.include_router(elements.router)
@@ -40,8 +38,7 @@ async def redirect_to_docs():
 
 @app.exception_handler(RequestValidationError)
 async def validation_exception_handler(request: Request, exc: RequestValidationError):
-    """Value errors are user errors.
-    """
+    """Value errors are user errors."""
     data_format = (
         "format" in request.query_params
         and str(request.query_params["format"])
@@ -52,8 +49,7 @@ async def validation_exception_handler(request: Request, exc: RequestValidationE
 
 @app.exception_handler(Exception)
 async def server_exception_handler(request: Request, exc: Exception):
-    """Other exceptions are server errors.
-    """
+    """Other exceptions are server errors."""
     data_format = (
         "format" in request.query_params
         and str(request.query_params["format"])
@@ -65,8 +61,7 @@ async def server_exception_handler(request: Request, exc: Exception):
 def format_error(
     status_code: int, exception: str, format: str, request: Request
 ) -> Response:
-    """Assign error_body value based on error format.
-    """
+    """Assign error_body value based on error format."""
     if format == "json":
         return json_error(status_code, exception, request.url)
     else:
diff --git a/geomagio/binlog/BinLogWriter.py b/geomagio/binlog/BinLogWriter.py
index f43ac161ee871621a09a0d72520ffce8f2b3b904..7364628c249b7d428ce23adfc75f181a7eb298c0 100644
--- a/geomagio/binlog/BinLogWriter.py
+++ b/geomagio/binlog/BinLogWriter.py
@@ -19,8 +19,7 @@ Zbuf = []
 
 
 class BinLogWriter(object):
-    """BinLog writer.
-    """
+    """BinLog writer."""
 
     def __init__(self):
         return
diff --git a/geomagio/edge/EdgeFactory.py b/geomagio/edge/EdgeFactory.py
index 83c278a6e24ae73ab8ad37c7e8d0667ee6e4ee65..a22514650586aaaad0da69ac12cd0365e0f1d405 100644
--- a/geomagio/edge/EdgeFactory.py
+++ b/geomagio/edge/EdgeFactory.py
@@ -544,7 +544,14 @@ class EdgeFactory(TimeseriesFactory):
         TimeseriesUtility.pad_timeseries(timeseries, starttime, endtime)
 
     def _put_channel(
-        self, timeseries, observatory, channel, type, interval, starttime, endtime,
+        self,
+        timeseries,
+        observatory,
+        channel,
+        type,
+        interval,
+        starttime,
+        endtime,
     ):
         """Put a channel worth of data
 
diff --git a/geomagio/edge/MiniSeedInputClient.py b/geomagio/edge/MiniSeedInputClient.py
index dc66c17b0cb288d70cfb0896a2f3b9fdd6284df7..906c37e32e2e4bd821c4696234c2dbce87b31394 100644
--- a/geomagio/edge/MiniSeedInputClient.py
+++ b/geomagio/edge/MiniSeedInputClient.py
@@ -24,8 +24,7 @@ class MiniSeedInputClient(object):
         self.socket = None
 
     def close(self):
-        """Close socket if open.
-        """
+        """Close socket if open."""
         if self.socket is not None:
             try:
                 self.socket.close()
diff --git a/geomagio/edge/RawInputClient.py b/geomagio/edge/RawInputClient.py
index 695b93688e0b6e1c64e5f3bced2e760f978f907a..20c29acfd8845cd53ec7f2259e0f9e95f3587dd5 100644
--- a/geomagio/edge/RawInputClient.py
+++ b/geomagio/edge/RawInputClient.py
@@ -109,8 +109,7 @@ class RawInputClient:
             raise TimeseriesFactoryException("Tag limited to 10 characters")
 
     def close(self):
-        """close the open sockets
-        """
+        """close the open sockets"""
         if self.socket is not None:
             self.socket.close()
             self.socket = None
@@ -144,7 +143,7 @@ class RawInputClient:
         return str(network + observatory.ljust(5) + channel + location).encode()
 
     def forceout(self):
-        """ force edge to recognize data
+        """force edge to recognize data
         NOTES
         -----
         When sending data to edge it hangs on to the data, until either
@@ -206,7 +205,7 @@ class RawInputClient:
             starttime += nsamp * timeoffset
 
     def _send(self, buf):
-        """ Send a block of data to the Edge/CWB combination.
+        """Send a block of data to the Edge/CWB combination.
 
         PARAMETERS
         ----------
diff --git a/geomagio/iaga2002/IAGA2002Writer.py b/geomagio/iaga2002/IAGA2002Writer.py
index 14363bf8832968e01de7e371b9d30254aaf52698..2e9bbdfdd35cfc15c92273d25265b9bb4151c660 100644
--- a/geomagio/iaga2002/IAGA2002Writer.py
+++ b/geomagio/iaga2002/IAGA2002Writer.py
@@ -13,8 +13,7 @@ from . import IAGA2002Parser
 
 
 class IAGA2002Writer(object):
-    """IAGA2002 writer.
-    """
+    """IAGA2002 writer."""
 
     def __init__(
         self,
diff --git a/geomagio/imfjson/IMFJSONWriter.py b/geomagio/imfjson/IMFJSONWriter.py
index 81584224b0ded7891f80064b73d2498eeaf25e24..fed776cedcec7d3ddebb76e56da0b48a5bdf22b7 100644
--- a/geomagio/imfjson/IMFJSONWriter.py
+++ b/geomagio/imfjson/IMFJSONWriter.py
@@ -10,8 +10,7 @@ from ..TimeseriesFactoryException import TimeseriesFactoryException
 
 
 class IMFJSONWriter(object):
-    """JSON writer.
-    """
+    """JSON writer."""
 
     def write(self, out, timeseries, channels, url=None):
         """Write timeseries to json file.
diff --git a/geomagio/imfv283/IMFV283Parser.py b/geomagio/imfv283/IMFV283Parser.py
index e9bcbfe564cc572f0b4dfa2ffa054eeb0de3fbcc..ae23d5e72734b13cbee5010021872520d01f4f88 100644
--- a/geomagio/imfv283/IMFV283Parser.py
+++ b/geomagio/imfv283/IMFV283Parser.py
@@ -218,7 +218,7 @@ class IMFV283Parser(object):
         return HEADER_SIZE
 
     def _parse_goes_header(self, data):
-        """ parse goes data header
+        """parse goes data header
 
         Parameters
         ----------
diff --git a/geomagio/pcdcp/PCDCPFactory.py b/geomagio/pcdcp/PCDCPFactory.py
index 5941528de90c42395fd4c348fbe20bd041e647de..f7633d2c0ebf525805f6e18887b095426a9e07b5 100644
--- a/geomagio/pcdcp/PCDCPFactory.py
+++ b/geomagio/pcdcp/PCDCPFactory.py
@@ -36,7 +36,9 @@ class PCDCPFactory(TimeseriesFactory):
     """
 
     def __init__(
-        self, temperatures=False, **kwargs,
+        self,
+        temperatures=False,
+        **kwargs,
     ):
         TimeseriesFactory.__init__(self, **kwargs)
         self.temperatures = temperatures
diff --git a/geomagio/pcdcp/PCDCPWriter.py b/geomagio/pcdcp/PCDCPWriter.py
index 8409ab5e8dbb0e19505eaee8ebc463f348960ee7..f974a8b3eb197abfa54db91e5a3f518b12166a0a 100644
--- a/geomagio/pcdcp/PCDCPWriter.py
+++ b/geomagio/pcdcp/PCDCPWriter.py
@@ -11,8 +11,7 @@ from obspy.core import Stream
 
 
 class PCDCPWriter(object):
-    """PCDCP writer.
-    """
+    """PCDCP writer."""
 
     def __init__(self, empty_value=PCDCPParser.NINES, temperatures=False):
         self.empty_value = empty_value
diff --git a/geomagio/processing/magproc.py b/geomagio/processing/magproc.py
index 1522e311e20dcfa9f31847fa9bed4542919f282d..14f2fc744950131ffdf61717fc55a18fe4ac87b2 100644
--- a/geomagio/processing/magproc.py
+++ b/geomagio/processing/magproc.py
@@ -69,7 +69,10 @@ def prepfiles(
 
 
 def write_cal_file(
-    starttime: UTCDateTime, endtime: UTCDateTime, observatory: str, template: str,
+    starttime: UTCDateTime,
+    endtime: UTCDateTime,
+    observatory: str,
+    template: str,
 ):
     print(
         f"Loading calibration data for {observatory} [{starttime}, {endtime}]",
diff --git a/geomagio/residual/SpreadsheetAbsolutesFactory.py b/geomagio/residual/SpreadsheetAbsolutesFactory.py
index 1cf007856ddfb445c69d52c6d63d9a32ada9504e..d53b772bd0cf6b67006c8d43884e5da9d03a6e60 100644
--- a/geomagio/residual/SpreadsheetAbsolutesFactory.py
+++ b/geomagio/residual/SpreadsheetAbsolutesFactory.py
@@ -246,8 +246,7 @@ class SpreadsheetAbsolutesFactory(object):
         endtime: UTCDateTime,
         include_measurements: bool = True,
     ) -> List[Reading]:
-        """Read spreadsheet files between starttime/endtime.
-        """
+        """Read spreadsheet files between starttime/endtime."""
         readings = []
         start_filename = f"{observatory}-{starttime.datetime:%Y%j%H%M}.xlsm"
         end_filename = f"{observatory}-{endtime.datetime:%Y%j%H%M}.xlsm"
@@ -289,7 +288,8 @@ class SpreadsheetAbsolutesFactory(object):
         return Reading(
             absolutes=absolutes,
             azimuth=Angle.from_dms(
-                degrees=int(mark_azimuth / 100.0), minutes=mark_azimuth % 100,
+                degrees=int(mark_azimuth / 100.0),
+                minutes=mark_azimuth % 100,
             ),
             hemisphere=metadata["hemisphere"],
             measurements=measurements,
@@ -301,8 +301,7 @@ class SpreadsheetAbsolutesFactory(object):
     def _parse_absolutes(
         self, sheet: openpyxl.worksheet, base_date: str
     ) -> List[Absolute]:
-        """Parse absolutes from a summary sheet.
-        """
+        """Parse absolutes from a summary sheet."""
         absolutes = [
             Absolute(
                 element="D",
@@ -333,8 +332,7 @@ class SpreadsheetAbsolutesFactory(object):
     def _parse_measurements(
         self, sheet: openpyxl.worksheet, base_date: str, precision: str
     ) -> List[Measurement]:
-        """Parse measurements from a measurement sheet.
-        """
+        """Parse measurements from a measurement sheet."""
         measurements = []
         for m in SPREADSHEET_MEASUREMENTS:
             measurement_type = m["type"]
@@ -374,8 +372,7 @@ class SpreadsheetAbsolutesFactory(object):
         calculation_sheet: openpyxl.worksheet,
         summary_sheet: openpyxl.worksheet,
     ) -> Dict:
-        """Parse metadata from various sheets.
-        """
+        """Parse metadata from various sheets."""
         errors = []
         mark_azimuth = None
         try:
diff --git a/geomagio/residual/WebAbsolutesFactory.py b/geomagio/residual/WebAbsolutesFactory.py
index 120734293ff682c225d7d850f387bf6ab5d8c9fd..56998fb976fb0b1e465f50116cb76b57d0677518 100644
--- a/geomagio/residual/WebAbsolutesFactory.py
+++ b/geomagio/residual/WebAbsolutesFactory.py
@@ -11,8 +11,7 @@ from .Reading import Reading
 
 
 class WebAbsolutesFactory(object):
-    """Read absolutes from web absolutes service.
-    """
+    """Read absolutes from web absolutes service."""
 
     def __init__(
         self, url: str = "https://geomag.usgs.gov/baselines/observation.json.php"
@@ -39,8 +38,7 @@ class WebAbsolutesFactory(object):
             return self.parse_json(data)
 
     def parse_json(self, jsonstr: IO[str]) -> List[Reading]:
-        """Parse readings from the web absolutes JSON format.
-        """
+        """Parse readings from the web absolutes JSON format."""
         readings = []
         response = json.load(jsonstr)
         for data in response["data"]:
@@ -88,8 +86,7 @@ class WebAbsolutesFactory(object):
         }
 
     def _parse_reading(self, metadata: Mapping, data: Mapping) -> Reading:
-        """Parse absolutes and measurements from Reading json.
-        """
+        """Parse absolutes and measurements from Reading json."""
         absolutes = [
             self._parse_absolute(element, data[element])
             for element in ["D", "H", "Z"]
diff --git a/geomagio/temperature/TEMPWriter.py b/geomagio/temperature/TEMPWriter.py
index 57667d0152d787fdcc79a23cc48e6c26a6a4ea3e..630f452da57250244bae62d10cd4799f7d54df7a 100644
--- a/geomagio/temperature/TEMPWriter.py
+++ b/geomagio/temperature/TEMPWriter.py
@@ -9,8 +9,7 @@ from obspy.core import Stream
 
 
 class TEMPWriter(object):
-    """TEMP writer.
-    """
+    """TEMP writer."""
 
     def __init__(self, empty_value=numpy.int("9999")):
         self.empty_value = empty_value
diff --git a/geomagio/vbf/VBFWriter.py b/geomagio/vbf/VBFWriter.py
index 518e4a0ba68fca1ee4711bfcc896f42cd1211b7a..bfb18f5e6a20bc7e5a6fd57375a0185644a420a8 100644
--- a/geomagio/vbf/VBFWriter.py
+++ b/geomagio/vbf/VBFWriter.py
@@ -9,8 +9,7 @@ from obspy.core import Stream
 
 
 class VBFWriter(object):
-    """VBF writer.
-    """
+    """VBF writer."""
 
     def __init__(self, empty_value=numpy.int("9999999")):
         self.empty_value = empty_value
diff --git a/setup.py b/setup.py
index b923235ecb0fe6ff2797a6876680058d49160f2a..29212231e0bda9dc9e4064d9a6bbde16dcf1ca39 100644
--- a/setup.py
+++ b/setup.py
@@ -19,7 +19,9 @@ setuptools.setup(
     },
     python_requires=">=3.6, <4",
     scripts=["bin/geomag.py", "bin/geomag_webservice.py", "bin/make_cal.py"],
-    setup_requires=["setuptools-pipfile",],
+    setup_requires=[
+        "setuptools-pipfile",
+    ],
     use_pipfile=True,
     entry_points={
         "console_scripts": ["magproc-prepfiles=geomagio.processing.magproc:main"],
diff --git a/test/Controller_test.py b/test/Controller_test.py
index c7d0509d00e2e01cf7fb5f7435cdddc06abcf237..4a722adaa053afcff76db7f56fcdf85a0dbd3035 100644
--- a/test/Controller_test.py
+++ b/test/Controller_test.py
@@ -21,9 +21,9 @@ from obspy.core import UTCDateTime
 def test_controller():
     """Controller_test.test_controller()
 
-  instantiate the controller, make certain the factories and algorithms
-  are set
-  """
+    instantiate the controller, make certain the factories and algorithms
+    are set
+    """
     inputfactory = TimeseriesFactory()
     outputfactory = TimeseriesFactory()
     algorithm = Algorithm()
diff --git a/test/ObservatoryMetadata_test.py b/test/ObservatoryMetadata_test.py
index 135548946d101e064b22006119cad34658630abb..902abffbbb523c61581055f2d0eb4e5a27b920d5 100644
--- a/test/ObservatoryMetadata_test.py
+++ b/test/ObservatoryMetadata_test.py
@@ -46,8 +46,7 @@ DATA_INTERVAL_TYPE = {
 
 
 def test_set_metadata():
-    """ObservatoryMetadata_test.test_set_metadata()
-    """
+    """ObservatoryMetadata_test.test_set_metadata()"""
     # Test set_metadata by passing in a stats class, and looking
     # for parameters that are both passed in, and aquired from the default
     # metadata.
diff --git a/test/TimeseriesUtility_test.py b/test/TimeseriesUtility_test.py
index 6a0d4e684a209629ecc9d0a4460cd90e6fdf53cc..827b0afeced6bc9e7a80c0cb75f48bc3cf98ee34 100644
--- a/test/TimeseriesUtility_test.py
+++ b/test/TimeseriesUtility_test.py
@@ -12,8 +12,7 @@ assert_array_equal = numpy.testing.assert_array_equal
 
 
 def test_create_empty_trace():
-    """TimeseriesUtility_test.test_create_empty_trace()
-    """
+    """TimeseriesUtility_test.test_create_empty_trace()"""
     trace1 = _create_trace([1, 1, 1, 1, 1], "H", UTCDateTime("2018-01-01"))
     trace2 = _create_trace([2, 2], "E", UTCDateTime("2018-01-01"))
     observatory = "Test"
@@ -171,8 +170,7 @@ def test_get_merged_gaps():
 
 
 def test_get_trace_values():
-    """TimeseriesUtility_test.test_get_trace_values()
-    """
+    """TimeseriesUtility_test.test_get_trace_values()"""
     stream = Stream(
         [
             __create_trace("H", [numpy.nan, 1, 1, numpy.nan, numpy.nan]),
@@ -213,8 +211,7 @@ def test_get_trace_values():
 
 
 def test_has_all_channels():
-    """TimeseriesUtility_test.test_has_all_channels():
-    """
+    """TimeseriesUtility_test.test_has_all_channels():"""
     nan = numpy.nan
     stream = Stream(
         [
@@ -245,8 +242,7 @@ def test_has_all_channels():
 
 
 def test_has_any_channels():
-    """TimeseriesUtility_test.test_has_any_channels():
-    """
+    """TimeseriesUtility_test.test_has_any_channels():"""
     nan = numpy.nan
     stream = Stream(
         [
@@ -338,8 +334,7 @@ def test_merge_streams():
 
 
 def test_pad_timeseries():
-    """TimeseriesUtility_test.test_pad_timeseries()
-    """
+    """TimeseriesUtility_test.test_pad_timeseries()"""
     trace1 = _create_trace([1, 1, 1, 1, 1], "H", UTCDateTime("2018-01-01"))
     trace2 = _create_trace([2, 2], "E", UTCDateTime("2018-01-01"))
     timeseries = Stream(traces=[trace1, trace2])
@@ -363,8 +358,7 @@ def test_pad_timeseries():
 
 
 def test_pad_and_trim_trace():
-    """TimeseriesUtility_test.test_pad_and_trim_trace()
-    """
+    """TimeseriesUtility_test.test_pad_and_trim_trace()"""
     trace = _create_trace([0, 1, 2, 3, 4], "X", UTCDateTime("2018-01-01"))
     assert_equal(trace.stats.starttime, UTCDateTime("2018-01-01T00:00:00Z"))
     assert_equal(trace.stats.endtime, UTCDateTime("2018-01-01T00:04:00Z"))
diff --git a/test/Util_test.py b/test/Util_test.py
index 2c44beb7d316ebe0aab324675ec15152bb58ff0b..3920bf0d535780836e2cb00a8b2f14125f9d8614 100644
--- a/test/Util_test.py
+++ b/test/Util_test.py
@@ -7,8 +7,7 @@ from obspy.core import UTCDateTime
 
 
 def test_get_file_for_url__throws_exception():
-    """Util_test.test_get_file_for_url__throws_exception()
-    """
+    """Util_test.test_get_file_for_url__throws_exception()"""
     # throws exception for non "file://" urls
     try:
         Util.get_file_from_url("http://someserver/path")
@@ -18,16 +17,14 @@ def test_get_file_for_url__throws_exception():
 
 
 def test_get_file_for_url__parses_file_urls():
-    """Util_test.test_get_file_for_url__parses_file_urls()
-    """
+    """Util_test.test_get_file_for_url__parses_file_urls()"""
     # parses file urls
     f = Util.get_file_from_url("file://./somefile")
     assert_equal(f, "./somefile")
 
 
 def test_get_file_for_url__creates_directories():
-    """Util_test.test_get_file_for_url__creates_directories()
-    """
+    """Util_test.test_get_file_for_url__creates_directories()"""
     # creates directories if requested
     if os.path.isdir("/tmp/_geomag_algorithms_test_"):
         shutil.rmtree("/tmp/_geomag_algorithms_test_")
@@ -41,8 +38,7 @@ def test_get_file_for_url__creates_directories():
 
 
 def test_get_interval__defaults():
-    """Util_test.test_get_interval()
-    """
+    """Util_test.test_get_interval()"""
     starttime = UTCDateTime("2015-01-01T00:00:00Z")
     endtime = UTCDateTime("2015-02-01T00:00:00Z")
     intervals = Util.get_intervals(starttime, endtime)
@@ -50,8 +46,7 @@ def test_get_interval__defaults():
 
 
 def test_get_interval__custom_size():
-    """Util_test.test_get_interval__custom_size()
-    """
+    """Util_test.test_get_interval__custom_size()"""
     starttime = UTCDateTime("2015-01-01T00:00:00Z")
     endtime = UTCDateTime("2015-01-02T00:00:00Z")
     intervals = Util.get_intervals(starttime, endtime, size=3600)
@@ -59,8 +54,7 @@ def test_get_interval__custom_size():
 
 
 def test_get_interval__negative_size():
-    """Util_test.test_get_interval__negative_size()
-    """
+    """Util_test.test_get_interval__negative_size()"""
     starttime = UTCDateTime("2015-01-01T00:00:00Z")
     endtime = UTCDateTime("2015-01-02T00:00:00Z")
     intervals = Util.get_intervals(starttime, endtime, size=-1)
@@ -70,8 +64,7 @@ def test_get_interval__negative_size():
 
 
 def test_get_interval__trim():
-    """Util_test.test_get_interval__trim()
-    """
+    """Util_test.test_get_interval__trim()"""
     starttime = UTCDateTime("2015-01-01T01:00:00Z")
     endtime = UTCDateTime("2015-01-02T00:00:00Z")
     intervals = Util.get_intervals(starttime, endtime, trim=True)
diff --git a/test/algorithm_test/AdjustedAlgorithm_test.py b/test/algorithm_test/AdjustedAlgorithm_test.py
index 532bb8c6905805a52c309d24de629251cb6f5705..f37f93f78893e6f13b22e50923724bca0b4ee260 100644
--- a/test/algorithm_test/AdjustedAlgorithm_test.py
+++ b/test/algorithm_test/AdjustedAlgorithm_test.py
@@ -4,8 +4,7 @@ from numpy.testing import assert_almost_equal, assert_equal
 
 
 def test_construct():
-    """algorithm_test.AdjustedAlgorithm_test.test_construct()
-    """
+    """algorithm_test.AdjustedAlgorithm_test.test_construct()"""
     # load adjusted data transform matrix and pier correction
     a = adj(statefile="etc/adjusted/adjbou_state_.json")
 
diff --git a/test/algorithm_test/SQDistAlgorithm_test.py b/test/algorithm_test/SQDistAlgorithm_test.py
index 49d15728322f2038f5b193786ee2263ce7210ca6..767f71c122a8acfa72cc92ccb4691fb13419f850 100644
--- a/test/algorithm_test/SQDistAlgorithm_test.py
+++ b/test/algorithm_test/SQDistAlgorithm_test.py
@@ -11,8 +11,8 @@ from numpy.testing import (
 def test_sqdistalgorithm_additive1():
     """SqDistAlgorithm_test.test_sqdistalgorithm_additive1()
 
-       Uses a simple 12 point data series to compare additive inputs with
-       corresponding outputs.
+    Uses a simple 12 point data series to compare additive inputs with
+    corresponding outputs.
     """
     # configure to test zero-step predictions of 4 "season" cycles
     m = 4
@@ -314,8 +314,8 @@ def test_sqdistalgorithm_additive1():
 def test_sqdistalgorithm_additive2():
     """SqDistAlgorithm_test.test_sqdistalgorithm_additive2()
 
-       Uses synthetic data time series over 300 days to test additive method
-       outputs.
+    Uses synthetic data time series over 300 days to test additive method
+    outputs.
     """
     # set up smoothing parameters
     m = 100  # length of "day"
diff --git a/test/edge_test/EdgeFactory_test.py b/test/edge_test/EdgeFactory_test.py
index 433ddd75a2935c9b4f5beefe5bebbc92ddfef459..fca38a8c8df6fb8cd08a7717ff2114f5e7f5daf3 100644
--- a/test/edge_test/EdgeFactory_test.py
+++ b/test/edge_test/EdgeFactory_test.py
@@ -6,22 +6,19 @@ from numpy.testing import assert_equal
 
 
 def test__get_edge_network():
-    """edge_test.EdgeFactory_test.test__get_edge_network()
-    """
+    """edge_test.EdgeFactory_test.test__get_edge_network()"""
     # _get_edge_network should always return NT for use by USGS geomag
     assert_equal(EdgeFactory()._get_edge_network(" ", " ", " ", " "), "NT")
 
 
 def test__get_edge_station():
-    """edge_test.EdgeFactory_test.test__get_edge_station()
-    """
+    """edge_test.EdgeFactory_test.test__get_edge_station()"""
     # _get_edge_station will return the observatory code passed in.
     assert_equal(EdgeFactory()._get_edge_station("BOU", " ", " ", " "), "BOU")
 
 
 def test__get_edge_channel():
-    """edge_test.EdgeFactory_test.test__get_edge_channel()
-    """
+    """edge_test.EdgeFactory_test.test__get_edge_channel()"""
     # Call private function _get_edge_channel, make certain
     # it gets back the appropriate 2 character code.
     assert_equal(EdgeFactory()._get_edge_channel("", "D", "", "minute"), "MVD")
@@ -35,8 +32,7 @@ def test__get_edge_channel():
 
 
 def test__get_edge_location():
-    """edge_test.EdgeFactory_test.test__get_edge_location()
-    """
+    """edge_test.EdgeFactory_test.test__get_edge_location()"""
     # Call _get_edge_location, make certain it returns the correct edge
     # location code.
     assert_equal(EdgeFactory()._get_edge_location("", "", "variation", ""), "R0")
@@ -45,8 +41,7 @@ def test__get_edge_location():
 
 
 def test__get_interval_code():
-    """edge_test.EdgeFactory_test.test__get_interval_code()
-    """
+    """edge_test.EdgeFactory_test.test__get_interval_code()"""
     assert_equal(EdgeFactory()._get_interval_code("day"), "D")
     assert_equal(EdgeFactory()._get_interval_code("hour"), "H")
     assert_equal(EdgeFactory()._get_interval_code("minute"), "M")
@@ -54,8 +49,7 @@ def test__get_interval_code():
 
 
 def test__set_metadata():
-    """edge_test.EdgeFactory_test.test__set_metadata()
-    """
+    """edge_test.EdgeFactory_test.test__set_metadata()"""
     # Call _set_metadata with 2 traces,  and make certain the stats get
     # set for both traces.
     trace1 = Trace()
diff --git a/test/edge_test/MiniSeedFactory_test.py b/test/edge_test/MiniSeedFactory_test.py
index 18f2cee5eddd387804379a6aef8d6c0139c4e5ee..24397dbcbde8e20781418f133a23696609b6ec9e 100644
--- a/test/edge_test/MiniSeedFactory_test.py
+++ b/test/edge_test/MiniSeedFactory_test.py
@@ -8,22 +8,19 @@ from geomagio.edge import MiniSeedFactory
 
 
 def test__get_edge_network():
-    """edge_test.MiniSeedFactory_test.test__get_edge_network()
-    """
+    """edge_test.MiniSeedFactory_test.test__get_edge_network()"""
     # _get_edge_network should always return NT for use by USGS geomag
     assert_equal(MiniSeedFactory()._get_edge_network(" ", " ", " ", " "), "NT")
 
 
 def test__get_edge_station():
-    """edge_test.MiniSeedFactory_test.test__get_edge_station()
-    """
+    """edge_test.MiniSeedFactory_test.test__get_edge_station()"""
     # _get_edge_station will return the observatory code passed in.
     assert_equal(MiniSeedFactory()._get_edge_station("BOU", " ", " ", " "), "BOU")
 
 
 def test__get_edge_channel():
-    """edge_test.MiniSeedFactory_test.test__get_edge_channel()
-    """
+    """edge_test.MiniSeedFactory_test.test__get_edge_channel()"""
     # Call private function _get_edge_channel, make certain
     # it gets back the appropriate 2 character code.
     factory = MiniSeedFactory()
@@ -39,8 +36,7 @@ def test__get_edge_channel():
 
 
 def test__get_edge_location():
-    """edge_test.MiniSeedFactory_test.test__get_edge_location()
-    """
+    """edge_test.MiniSeedFactory_test.test__get_edge_location()"""
     # Call _get_edge_location, make certain it returns the correct edge
     # location code.
     assert_equal(MiniSeedFactory()._get_edge_location("", "", "variation", ""), "R0")
@@ -51,8 +47,7 @@ def test__get_edge_location():
 
 
 def test__get_interval_code():
-    """edge_test.MiniSeedFactory_test.test__get_interval_code()
-    """
+    """edge_test.MiniSeedFactory_test.test__get_interval_code()"""
     assert_equal(MiniSeedFactory()._get_interval_code("day"), "P")
     assert_equal(MiniSeedFactory()._get_interval_code("hour"), "R")
     assert_equal(MiniSeedFactory()._get_interval_code("minute"), "U")
@@ -73,8 +68,7 @@ class MockMiniSeedInputClient(object):
 
 
 def test__put_timeseries():
-    """edge_test.MiniSeedFactory_test.test__put_timeseries()
-    """
+    """edge_test.MiniSeedFactory_test.test__put_timeseries()"""
     trace1 = __create_trace([0, 1, 2, 3, numpy.nan, 5, 6, 7, 8, 9], channel="H")
     client = MockMiniSeedInputClient()
     factory = MiniSeedFactory()
@@ -97,8 +91,7 @@ def test__put_timeseries():
 
 
 def test__set_metadata():
-    """edge_test.MiniSeedFactory_test.test__set_metadata()
-    """
+    """edge_test.MiniSeedFactory_test.test__set_metadata()"""
     # Call _set_metadata with 2 traces,  and make certain the stats get
     # set for both traces.
     trace1 = Trace()
diff --git a/test/edge_test/RawInputClient_test.py b/test/edge_test/RawInputClient_test.py
index d9676b526756357230b365df51b2bd1ef1e27543..850f1a7dfff04cc18d0dc45ffc860d334ba36bd8 100644
--- a/test/edge_test/RawInputClient_test.py
+++ b/test/edge_test/RawInputClient_test.py
@@ -17,8 +17,7 @@ class MockRawInputClient(RawInputClient):
 
 
 def test_raw_input_client():
-    """edge_test.RawInputClient_test.test_raw_input_client()
-    """
+    """edge_test.RawInputClient_test.test_raw_input_client()"""
     network = "NT"
     station = "BOU"
     channel = "MVH"
@@ -57,8 +56,7 @@ def test_raw_input_client():
 
 
 def test__get_tag():
-    """edge_test.RawInputClient_test.test_raw_input_client()
-    """
+    """edge_test.RawInputClient_test.test_raw_input_client()"""
     network = "NT"
     station = "BOU"
     channel = "MVH"
diff --git a/test/imfv122_test/IMFV122Parser_test.py b/test/imfv122_test/IMFV122Parser_test.py
index 951d41608ef82d07d8e078b8124fcd604a4c6396..2a3d87a1a9d2f421e647276f53a74b97bf335506 100644
--- a/test/imfv122_test/IMFV122Parser_test.py
+++ b/test/imfv122_test/IMFV122Parser_test.py
@@ -6,8 +6,7 @@ from obspy.core import UTCDateTime
 
 
 def test_imfv122_parse_header__hour_of_day():
-    """imfv122_test.test_imfv122_parse_header__minutes.
-    """
+    """imfv122_test.test_imfv122_parse_header__minutes."""
     parser = IMFV122Parser()
     parser._parse_header(
         "KAK MAY0216 123 03 HDZF A KYO 05381402 000000 RRRRRRRRRRRRRRRR"
@@ -23,8 +22,7 @@ def test_imfv122_parse_header__hour_of_day():
 
 
 def test_imfv122_parse_header__minute_of_day():
-    """imfv122_test.test_imfv122_parse_header__seconds.
-    """
+    """imfv122_test.test_imfv122_parse_header__seconds."""
     parser = IMFV122Parser()
     parser._parse_header(
         "HER JAN0116 001 0123 HDZF R EDI 12440192 -14161 DRRRRRRRRRRRRRRR"
@@ -40,8 +38,7 @@ def test_imfv122_parse_header__minute_of_day():
 
 
 def test_imfv122_parse_data():
-    """imfv122_test.test_imfv122_parse_data.
-    """
+    """imfv122_test.test_imfv122_parse_data."""
     parser = IMFV122Parser()
     parser._parse_header(
         "HER JAN0116 001 0123 HDZF R EDI 12440192 -14161 DRRRRRRRRRRRRRRR"
@@ -63,8 +60,7 @@ def test_imfv122_parse_data():
 
 
 def test_imfv122_post_process():
-    """imfv122_test.test_imfv122_post_process.
-    """
+    """imfv122_test.test_imfv122_post_process."""
     parser = IMFV122Parser()
     parser._parse_header(
         "HER JAN0116 001 0123 HDZF R EDI 12440192 -14161 DRRRRRRRRRRRRRRR"
diff --git a/test/imfv283_test/IMFV283Parser_test.py b/test/imfv283_test/IMFV283Parser_test.py
index 70dcbf76f17d97d9f590863d27e31e1f5ff15ccc..02ca2d3bda7abc23344363c1054c65135b8fe6f7 100644
--- a/test/imfv283_test/IMFV283Parser_test.py
+++ b/test/imfv283_test/IMFV283Parser_test.py
@@ -33,8 +33,7 @@ def test_parse_msg_header():
 
 
 def test_parse_goes_header():
-    """imfv283_test.IMFV283Parser_test.test_parse_goes_header()
-    """
+    """imfv283_test.IMFV283Parser_test.test_parse_goes_header()"""
     goes_data = IMFV283Parser()._process_ness_block(
         IMFV283_EXAMPLE_VIC, imfv283_codes.OBSERVATORIES["VIC"], 191
     )