diff --git a/.gitignore b/.gitignore
index 684adee5cac3c318d61d660a906faa48e7185d1a..f2d219a41c5b6082a40a7949b51cb8e4b48fa70e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
 #for docs and setup.py outputs
 build/
+tresults/
 # test cache
 gwinc/test/cache
 
diff --git a/conftest.py b/conftest.py
new file mode 100644
index 0000000000000000000000000000000000000000..546d97072babe34cfebfa48731308e43f13f5c65
--- /dev/null
+++ b/conftest.py
@@ -0,0 +1,272 @@
+"""
+Requires pytest to import
+"""
+import os
+from os import path
+import os
+from shutil import rmtree
+import contextlib
+
+import pytest
+
+_options_added = False
+
+def pytest_addoption(parser):
+    global _options_added
+    #this check fixes issues if this gets run multiple times from sub conftest.py's
+    if _options_added:
+        return
+    else:
+        _options_added = True
+
+    parser.addoption(
+        "--plot",
+        action="store_true",
+        dest = 'plot',
+        help = "Have tests update plots (it is slow)",
+    )
+
+    parser.addoption(
+        "--do-stresstest",
+        action = "store_true",
+        help   = "Run slow repeated stress tests"
+    )
+
+    parser.addoption(
+        "--no-preclear",
+        action="store_true",
+        default=False,
+        dest='no_preclear',
+        help="Do not preclear tpaths",
+    )
+
+
+@pytest.fixture
+def plot(request):
+    return request.config.getvalue('--plot')
+    return request.config.option.plot
+
+
+@pytest.fixture
+def tpath_preclear(request):
+    """
+    Fixture that indicates that the test path should be cleared automatically
+    before running each test. This cleans up the test data.
+    """
+    tpath_raw = tpath_raw_make(request)
+    no_preclear = request.config.getvalue('--no-preclear')
+    if not no_preclear:
+        rmtree(tpath_raw, ignore_errors = True)
+
+
+@pytest.fixture
+def tpath(request):
+    """
+    Fixture that takes the value of the special test-specific folder for test
+    run data and plots. Usually the <folder of the test>/tresults/test_name/
+    """
+    tpath_raw = tpath_raw_make(request)
+
+    os.makedirs(tpath_raw, exist_ok = True)
+    os.utime(tpath_raw, None)
+    return tpath_raw
+
+
+@pytest.fixture
+def tpath_join(request):
+    """
+    Fixture that joins subpaths to the value of the special test-specific folder for test
+    run data and plots. Usually the <folder of the test>/tresults/test_name/.
+
+    This function should be use like test_thing.save(tpath_join('output_file.png'))
+    """
+    tpath_raw = tpath_raw_make(request)
+    first_call = True
+
+    def tpath_joiner(*subpath):
+        nonlocal first_call
+        if first_call:
+            os.makedirs(tpath_raw, exist_ok = True)
+            os.utime(tpath_raw, None)
+            first_call = False
+        return path.join(tpath_raw, *subpath)
+
+    return tpath_joiner
+
+
+@pytest.fixture
+def fpath(request):
+    """
+    py.test fixture that returns the folder path of the test being run. Useful
+    for accessing data files.
+    """
+    return fpath_raw_make(request)
+
+
+@pytest.fixture
+def fpath_join(request):
+    """
+    py.test fixture that runs :code:`os.path.join(path, *arguments)` to merge subpaths
+    with the folder path of the current test being run. Useful for referring to
+    data files.
+    """
+    def join_func(*path):
+        return os.path.join(fpath_raw_make(request), *path)
+    return join_func
+
+@pytest.fixture
+def closefigs():
+    import matplotlib.pyplot as plt
+    yield
+    plt.close('all')
+
+
+@pytest.fixture
+def test_trigger():
+    """
+    This fixture provides a contextmanager that causes a function to call
+    if an AssertionError is raised. It will also call if any of its argument,
+    or keyword arguments is true. This allows you to conveniently force
+    calling using other flags or fixtures.
+
+    The primary usage of this is to plot outputs only on test failures, while also
+    allowing plotting to happen using the plot fixture and pytest cmdline argument
+    """
+    run_store = []
+
+    @contextlib.contextmanager
+    def fail(call, **kwargs):
+        run_store.append(call)
+
+        def call(did_fail):
+            do_call = did_fail
+            for k, v in kwargs.items():
+                if v:
+                    do_call = True
+                    break
+
+            if do_call:
+                for call in run_store:
+                    call(fail = did_fail, **kwargs)
+                run_store.clear()
+        try:
+            yield
+        except AssertionError:
+            call(True)
+            raise
+        else:
+            call(False)
+
+        return
+    return fail
+
+
+@pytest.fixture()
+def ic():
+    """
+    Fixture to provide icecream imports without requiring that the package exist
+    """
+    try:
+        from icecream import ic
+        return ic
+    except ImportError:
+        pass
+    try:
+        from IPython.lib.pretty import pprint
+        return pprint
+    except ImportError:
+        from pprint import pprint
+        return pprint
+
+
+#these are used with the pprint fixture
+try:
+    import icecream
+except ImportError:
+    icecream = None
+    pass
+try:
+    from IPython.lib.pretty import pprint, pretty
+    pformat = pretty
+except ImportError:
+    from pprint import pprint, pformat
+
+
+@pytest.fixture
+def pprint(request, tpath_join):
+    """
+    This is a fixture providing a wrapper function for pretty printing. It uses
+    the icecream module for pretty printing, falling back to ipythons pretty
+    printer if needed, then to the python build in pretty printing module.
+
+    Along with printing to stdout, this function prints into the tpath_folder to
+    save all output into output.txt.
+    """
+    fname = tpath_join('output.txt')
+
+    #pushes past the dot
+    print('---------------:{}:--------------'.format(request.node.name))
+    with open(fname, 'w') as F:
+        def pprint(*args, F = F, pretty = True, **kwargs):
+            outs = []
+            if pretty:
+                for arg in args:
+                    outs.append(
+                        pformat(arg)
+                    )
+            else:
+                outs = args
+            if F is not None:
+                print(*outs, file = F)
+            if icecream is not None:
+                icecream.DEFAULT_OUTPUT_FUNCTION(' '.join(outs), **kwargs)
+            else:
+                print(*outs, **kwargs)
+
+        yield pprint
+
+
+def tpath_raw_make(request):
+    if isinstance(request.node, pytest.Function):
+        return relfile_test(request.node.function.__code__.co_filename, request, 'tresults')
+    raise RuntimeError("TPath currently only works for functions")
+
+
+def fpath_raw_make(request):
+    if isinstance(request.node, pytest.Function):
+        return os.path.split(request.node.function.__code__.co_filename)[0]
+    raise RuntimeError("TPath currently only works for functions")
+
+
+def relfile(_file_, *args, fname = None):
+    fpath = path.split(_file_)[0]
+    post = path.join(*args)
+    fpath = path.join(fpath, post)
+    #os.makedirs(fpath, exist_ok = True)
+    #os.utime(fpath, None)
+
+    if fname is None:
+        return fpath
+    else:
+        return path.join(fpath, fname)
+
+
+def relfile_test(_file_, request, pre = None, post = None, fname = None):
+    """
+    Generates a folder specific to py.test function
+    (provided by using the "request" fixture in the test's arguments)
+    """
+    if isinstance(pre, (list, tuple)):
+        pre = path.join(pre)
+
+    testname = request.node.name
+    if pre is not None:
+        testname = path.join(pre, testname)
+
+    if isinstance(post, (list, tuple)):
+        post = path.join(post)
+    if post is not None:
+        return relfile(_file_, testname, post, fname = fname)
+    else:
+        return relfile(_file_, testname, fname = fname)
+
diff --git a/docs/Makefile b/docs/Makefile
index 61a3b8a0ebbadd5b285a983bfe3ce3f2afe50823..0912b469bba38d01f51c44239b6e7d6c31887726 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -41,7 +41,7 @@ clean:
 	-rm -rf $(BUILDDIR)/*
 
 livehtml:
-	sphinx-autobuild -i .#* -i *.pyc -i .*.swp -i .*.swo -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	sphinx-autobuild -z ../gwinc -i '*.#*' -i '*.pyc' -i '*.swp' -i '*.swo' -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
 
 html:
 	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
diff --git a/docs/_static/my_theme.css b/docs/_static/my_theme.css
new file mode 100644
index 0000000000000000000000000000000000000000..c6043e121f1c8203bd5edf2dec24c4576b252e71
--- /dev/null
+++ b/docs/_static/my_theme.css
@@ -0,0 +1,15 @@
+
+.wy-nav-content {
+    max-width: 1200px !important;
+}
+
+div.document {
+    width: auto;
+    margin: 30px auto 0 auto;
+}
+
+div.body{
+    max-width: 95%;
+    margin: 50px auto 0 auto;
+}
+
diff --git a/docs/api.rst b/docs/api.rst
new file mode 100644
index 0000000000000000000000000000000000000000..5bc793ebc271ed45399ba2ec64b78aebff6cf280
--- /dev/null
+++ b/docs/api.rst
@@ -0,0 +1,6 @@
+API
+################################################################################
+.. _API:
+
+.. py:module:: gwinc
+
diff --git a/docs/conf.py b/docs/conf.py
index ccbaff5399e7b6d6a057eb4eafa8810ea65949dc..5a0fa8b9fe4cf94e5d6c4fc7fb81e5a866ae02b9 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -17,9 +17,15 @@
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
 #
-# import os
-# import sys
-# sys.path.insert(0, os.path.abspath('.'))
+import os
+import sys
+#add the previous folder to the top of path, so that conftest.py can be found
+#dirty but does the trick
+sys.path.insert(0, os.path.abspath('..'))
+
+#gwinc must be importable to build the docs properly anyway, using apidoc, so
+#import it now for the __version__ parameter
+import gwinc
 
 
 # -- General configuration ------------------------------------------------
@@ -33,11 +39,12 @@
 # ones.
 extensions = [
     'sphinx.ext.autodoc',
-    'sphinx.ext.todo',
-    'sphinx.ext.coverage',
+    #'sphinx.ext.todo',
+    #'sphinx.ext.coverage',
     'sphinx.ext.mathjax',
-    'sphinx.ext.githubpages',
+    #'sphinx.ext.githubpages',
     'sphinx.ext.napoleon',
+    'sphinx.ext.viewcode',
 ]
 
 # Add any paths that contain templates here, relative to this directory.
@@ -54,7 +61,7 @@ master_doc = 'index'
 
 # General information about the project.
 project = 'GWINC'
-copyright = '2018, LIGO Laboratory'
+copyright = '2021, LIGO Laboratory'
 author = 'LIGO Laboratory'
 
 # The version info for the project you're documenting, acts as replacement for
@@ -62,7 +69,7 @@ author = 'LIGO Laboratory'
 # built documents.
 #
 # The short X.Y version.
-version = '0.0.0'
+version = gwinc.__version__
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
@@ -74,7 +81,7 @@ language = None
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
 # This patterns also effect to html_static_path and html_extra_path
-exclude_patterns = ['_build', '**.ipynb_checkpoints']
+exclude_patterns = ['_build', ]
 
 # The name of the Pygments (syntax highlighting) style to use.
 #pygments_style = 'sphinx'
@@ -84,9 +91,10 @@ pygments_style = 'default'
 # If true, `todo` and `todoList` produce output, else they produce nothing.
 todo_include_todos = True
 
+# Autodoc settings
+autodoc_default_flags = ["members", "undoc-members"]
 
 # -- Options for sourcelinks
-
 srclink_project = 'https://git.ligo.org/gwinc/pygwinc'
 srclink_src_path = 'gwinc'
 srclink_branch = 'master'
@@ -96,24 +104,41 @@ srclink_branch = 'master'
 #useful for downloading the ipynb files
 html_sourcelink_suffix = ''
 
+
+html_title = 'GWINC docs'
+html_short_title = 'GWINC docs'
+
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
 #
-import sphinx_rtd_theme
-html_theme = "sphinx_rtd_theme"
-html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
+#import sphinx_rtd_theme
+#html_theme = "sphinx_rtd_theme"
+#html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
 
 #import jupyter_sphinx_theme
 #html_theme = "jupyter_sphinx_theme"
 #html_theme_path = [jupyter_sphinx_theme.get_html_theme_path()]
 
-#html_theme = "alabaster"
+html_theme = "alabaster"
 
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
 # documentation.
 #
-# html_theme_options = {}
+html_theme_options = dict(
+    description = "Gravitational Wave Interferometer Noise Calculator, to determine the fundamental limiting noises in interferometer designs",
+    extra_nav_links = {
+        'repository' : 'https://git.ligo.org/gwinc/pygwinc'
+    },
+    show_powered_by = False,
+    show_related = True,
+    #page_width = 'auto',
+)
+
+napoleon_type_aliases = {
+    #"CustomType": "mypackage.CustomType",
+    #"dict-like": ":term:`dict-like <mapping>`",
+}
 
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
@@ -125,118 +150,24 @@ html_static_path = ['_static']
 #
 # This is required for the alabaster theme
 # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
-#html_sidebars = {
-#    '**': [
-#        'about.html',
-#        'navigation.html',
-#        'relations.html',  # needs 'show_related': True theme option to display
-#        'searchbox.html',
-#        ''
-#        #'donate.html',
-#    ]
-#}
-# Custom sidebar templates, maps document names to template names.
-
 html_sidebars = {
     '**': [
-        'localtoc.html',
+        'about.html',
+        #'globaltoc.html',
         'navigation.html',
         'relations.html',
         'searchbox.html',
-        'srclinks.html',
-        ],
-    'index': [
-        'globaltoc.html',
-        'navigation.html',
-        'relations.html',
-        'searchbox.html',
-        'srclinks.html',
-        ],
+    ]
 }
 
-# -- Options for HTMLHelp output ------------------------------------------
-
 # Output file base name for HTML help builder.
 htmlhelp_basename = 'GWINC'
 
+html_logo = 'logo/LIGO_F0900035-v1.jpg'
 
-# -- Options for LaTeX output ---------------------------------------------
-
-latex_elements = {
-    # The paper size ('letterpaper' or 'a4paper').
-    #
-    # 'papersize': 'letterpaper',
-
-    # The font size ('10pt', '11pt' or '12pt').
-    #
-    # 'pointsize': '10pt',
-
-    # Additional stuff for the LaTeX preamble.
-    #
-    # 'preamble': '',
-
-    # Latex figure (float) alignment
-    #
-    # 'figure_align': 'htbp',
-}
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title,
-#  author, documentclass [howto, manual, or own class]).
-latex_documents = [
-    (
-        master_doc,
-        'GWINC.tex',
-        'GWINC Documentation',
-        author,
-        'manual'
-    ),
-]
-
-#http://www.sphinx-doc.org/en/master/usage/configuration.html#latex-options
-#it appears that the LIGO docclass doesn't play well with all of the sphinx commands. Giving up for now
-#latex_docclass = {
-#    'manual' : 'ligodoc_v3',
-#}
-#latex_additional_files = [
-#    'ligodoc_v3.tex'
-#]
-
-
-# -- Options for manual page output ---------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [
-    (
-        master_doc,
-        'GWINC',
-        'GWINC Documentation',
-        [author],
-        1
-    )
-]
-
-
-# -- Options for Texinfo output -------------------------------------------
-
-# Grouping the document tree into Texinfo files. List of tuples
-# (source start file, target name, title, author,
-#  dir menu entry, description, category)
-texinfo_documents = [
-    (
-        master_doc,
-        'GWINC',
-        'GWINC Documentation',
-        author,
-        'GWINC',
-        'One line description of project.',
-        'Miscellaneous'
-    ),
-]
-
-#def setup(app):
-#    app.add_stylesheet('my_theme.css')
-#    app.add_stylesheet('pygments_adjust.css')
+def setup(app):
+    app.add_stylesheet('my_theme.css')
+    #updates the coloring
+    #app.add_stylesheet('pygments_adjust.css')
 
 
diff --git a/docs/dev.rst b/docs/dev.rst
new file mode 100644
index 0000000000000000000000000000000000000000..f09ae4b87032a7e8e24041eaf96b7cbfed5c7147
--- /dev/null
+++ b/docs/dev.rst
@@ -0,0 +1,76 @@
+Development
+################################################################################
+.. _development:
+
+Testing with py.test
+================================================================================
+
+.. py:module:: conftest
+
+
+py.test fixtures and setup
+--------------------------------------------------------------------------------
+
+
+.. autofunction:: plot
+
+
+.. autofunction:: tpath_preclear
+
+
+.. autofunction:: tpath
+
+
+.. autofunction:: tpath_join
+
+
+.. autofunction:: fpath
+
+
+.. autofunction:: fpath_join
+
+
+.. autofunction:: closefigs
+
+
+.. autofunction:: test_trigger
+
+
+.. autofunction:: ic
+
+
+.. autofunction:: pprint
+
+py.test setup hooks
+--------------------------------------------------------------------------------
+
+.. autofunction:: pytest_addoption
+
+
+py.test helper functions
+--------------------------------------------------------------------------------
+
+
+.. autofunction:: tpath_raw_make
+
+
+.. autofunction:: fpath_raw_make
+
+
+.. autofunction:: relfile
+ 
+ 
+.. autofunction:: relfile_test
+
+
+
+Git setup for development
+================================================================================
+
+
+PyPI Releases
+================================================================================
+
+versioning
+--------------------------------------------------------------------------------
+
diff --git a/docs/index.rst b/docs/index.rst
index 9e9ea7f449c2b2d8b31083d3879dfac7c4fdeabd..67c4f34f691e6a12f414d7e4bd2cd4512c1ff39c 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -30,6 +30,7 @@ Contents
    :maxdepth: 2
 
    install
-   quickstart
+   api
+   dev
 
 
diff --git a/docs/install.rst b/docs/install.rst
new file mode 100644
index 0000000000000000000000000000000000000000..c5b5c0400f8639be5a69da386e3aadd6cfbf59a5
--- /dev/null
+++ b/docs/install.rst
@@ -0,0 +1,4 @@
+Install
+################################################################################
+.. _install:
+
diff --git a/docs/logo/LIGO_F0900035-v1.jpg b/docs/logo/LIGO_F0900035-v1.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..f4d3245ede21fd1af4af4d31e53b5bdba8e047e2
Binary files /dev/null and b/docs/logo/LIGO_F0900035-v1.jpg differ
diff --git a/docs/notebooks/.gitignore b/docs/notebooks/.gitignore
deleted file mode 100644
index c05a8f846eae941788db09633ca05938e1bcc759..0000000000000000000000000000000000000000
--- a/docs/notebooks/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*.mat
-.ipynb_checkpoints/
diff --git a/pytest.ini b/pytest.ini
new file mode 100644
index 0000000000000000000000000000000000000000..fec9652012f23441a2da101231609b67d26c1217
--- /dev/null
+++ b/pytest.ini
@@ -0,0 +1,8 @@
+[pytest]
+norecursedirs=_old fixme fix* out-*
+python_files = test_*.py T*_*.py 
+python_functions = test_* T*
+usefixtures = closefigs
+
+[pytest-watch]
+ignore = .* 
diff --git a/test/budgets/test_budgets.py b/test/budgets/test_budgets.py
new file mode 100644
index 0000000000000000000000000000000000000000..3c01773724db92b8db92baaed9af3b69d2681baa
--- /dev/null
+++ b/test/budgets/test_budgets.py
@@ -0,0 +1,14 @@
+"""
+"""
+import gwinc
+from gwinc import load_budget
+
+
+def test_load(pprint, tpath_join, fpath_join):
+    pprint(gwinc.IFOS)
+    for ifo in gwinc.IFOS:
+        B = load_budget(ifo)
+        trace = B.run()
+        fig = trace.plot()
+        fig.savefig(tpath_join('budget_{}.pdf'.format(ifo)))
+