diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f6ceb56370c370db095756dbc954cbdde6b791f4..a7951562cb3b317a492365f78ab1dc867e79bec3 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,6 +1,6 @@
 # This script is an edited version of the example found at
 # https://git.ligo.org/lscsoft/example-ci-project/blob/python/.gitlab-ci.yml
-# Each 0th-indendation level is a job that will be run within GitLab CI
+# Each 0th-indentation level is a job that will be run within GitLab CI
 # The only exception are a short list of reserved keywords
 #
 # https://docs.gitlab.com/ee/ci/yaml/#gitlab-ci-yml
@@ -25,7 +25,7 @@ python-2:
   script:
     - python setup.py install
     # Run tests without finding coverage
-    - pytest
+    - pytest --ignore=test/utils_py3_test.py
 
 # test example on python 3
 python-3:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dc59652c4e01aefbccb780c1fe65b469887c3586..c4ef6726fe4d68382315c14b4545c342c8fd445b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,7 +3,13 @@
 ## Unreleased
 
 Changes currently on master, but not under a tag.
-Removed unnecessary arguments (`ra`, `dec`, `geocent_time`, `psi`) from source functions and replaced them with `**kwargs` where appropriate.
+
+- Removed unnecessary arguments (`ra`, `dec`, `geocent_time`, `psi`) from source functions and replaced them with `**kwargs` where appropriate.
+- Renamed `PriorSet` to `PriorDict`
+- Renamed `BBHPriorSet` to `BBHPriorDict`
+- Renamed `BNSPriorSet` to `BNSPriorDict`
+- Renamed `CalibrationPriorSet` to `CalibrationPriorDict`
+- Fixed a bug which caused `Interferometer.detector_tensor` not to update when `latitude`, `longitude`, `xarm_azimuth`, `yarm_azimuth`, `xarm_tilt`, `yarm_tilt` were updated.
 
 ## [0.3.1] 2018-11-06
 
diff --git a/bilby/__init__.py b/bilby/__init__.py
index df7998a26647b685848de6d50c9a5775f36683e2..57073bbee46aa72aea43c168b2d147d56681d20d 100644
--- a/bilby/__init__.py
+++ b/bilby/__init__.py
@@ -23,3 +23,5 @@ from . import core, gw, hyper
 from .core import utils, likelihood, prior, result, sampler
 from .core.sampler import run_sampler
 from .core.likelihood import Likelihood
+
+__version__ = utils.get_version_information()
diff --git a/bilby/core/prior.py b/bilby/core/prior.py
index 7378efc80b859fc365d5b9ee2c3190e688cee096..eb92472fa2de1ca1686f03cd61c5dc2df0393acf 100644
--- a/bilby/core/prior.py
+++ b/bilby/core/prior.py
@@ -9,13 +9,12 @@ import os
 from collections import OrderedDict
 from future.utils import iteritems
 
-from .utils import logger
+from .utils import logger, infer_args_from_method
 from . import utils
 import bilby  # noqa
-import inspect
 
 
-class PriorSet(OrderedDict):
+class PriorDict(OrderedDict):
     def __init__(self, dictionary=None, filename=None):
         """ A set of priors
 
@@ -36,7 +35,7 @@ class PriorSet(OrderedDict):
         elif type(filename) is str:
             self.from_file(filename)
         elif dictionary is not None:
-            raise ValueError("PriorSet input dictionary not understood")
+            raise ValueError("PriorDict input dictionary not understood")
 
     def to_file(self, outdir, label):
         """ Write the prior distribution to file.
@@ -187,20 +186,22 @@ class PriorSet(OrderedDict):
                 logger.debug('{} not a known prior.'.format(key))
         return samples
 
-    def prob(self, sample):
+    def prob(self, sample, **kwargs):
         """
 
         Parameters
         ----------
         sample: dict
             Dictionary of the samples of which we want to have the probability of
+        kwargs:
+            The keyword arguments are passed directly to `np.product`
 
         Returns
         -------
         float: Joint probability of all individual sample probabilities
 
         """
-        return np.product([self[key].prob(sample[key]) for key in sample])
+        return np.product([self[key].prob(sample[key]) for key in sample], **kwargs)
 
     def ln_prob(self, sample):
         """
@@ -238,6 +239,14 @@ class PriorSet(OrderedDict):
         return False
 
 
+class PriorSet(PriorDict):
+
+    def __init__(self, dictionary=None, filename=None):
+        """ DEPRECATED: USE PriorDict INSTEAD"""
+        logger.warning("The name 'PriorSet' is deprecated use 'PriorDict' instead")
+        super(PriorSet, self).__init__(dictionary, filename)
+
+
 def create_default_prior(name, default_priors_file=None):
     """Make a default prior for a parameter with a known name.
 
@@ -261,7 +270,7 @@ def create_default_prior(name, default_priors_file=None):
             "No prior file given.")
         prior = None
     else:
-        default_priors = PriorSet(filename=default_priors_file)
+        default_priors = PriorDict(filename=default_priors_file)
         if name in default_priors.keys():
             prior = default_priors[name]
         else:
@@ -424,8 +433,7 @@ class Prior(object):
         str: A string representation of this instance
 
         """
-        subclass_args = inspect.getargspec(self.__init__).args
-        subclass_args.pop(0)
+        subclass_args = infer_args_from_method(self.__init__)
         prior_name = self.__class__.__name__
 
         property_names = [p for p in dir(self.__class__) if isinstance(getattr(self.__class__, p), property)]
diff --git a/bilby/core/result.py b/bilby/core/result.py
index 86faa4aa732370ad89a82f8f3d14e4351c7eef52..01e37b056ea4233394fc5a00f07f16344f481250 100644
--- a/bilby/core/result.py
+++ b/bilby/core/result.py
@@ -6,11 +6,11 @@ import pandas as pd
 import corner
 import matplotlib
 import matplotlib.pyplot as plt
-from collections import OrderedDict
+from collections import OrderedDict, namedtuple
 
 from . import utils
 from .utils import logger, infer_parameters_from_function
-from .prior import PriorSet, DeltaFunction
+from .prior import PriorDict, DeltaFunction
 
 
 def result_file_name(outdir, label):
@@ -81,7 +81,7 @@ class Result(dict):
                 setattr(self, key, val)
 
         if getattr(self, 'priors', None) is not None:
-            self.priors = PriorSet(self.priors)
+            self.priors = PriorDict(self.priors)
 
     def __add__(self, other):
         matches = ['sampler', 'search_parameter_keys']
@@ -285,22 +285,112 @@ class Result(dict):
 
         Returns
         -------
-        string: str
-            A string of latex-formatted text of the mean and 1-sigma quantiles
+        summary: namedtuple
+            An object with attributes, median, lower, upper and string
 
         """
+        summary = namedtuple('summary', ['median', 'lower', 'upper', 'string'])
+
         if len(quantiles) != 2:
             raise ValueError("quantiles must be of length 2")
 
         quants_to_compute = np.array([quantiles[0], 0.5, quantiles[1]])
         quants = np.percentile(self.posterior[key], quants_to_compute * 100)
-        median = quants[1]
-        upper = quants[2] - median
-        lower = median - quants[0]
+        summary.median = quants[1]
+        summary.plus = quants[2] - summary.median
+        summary.minus = summary.median - quants[0]
 
         fmt = "{{0:{0}}}".format(fmt).format
-        string = r"${{{0}}}_{{-{1}}}^{{+{2}}}$"
-        return string.format(fmt(median), fmt(lower), fmt(upper))
+        string_template = r"${{{0}}}_{{-{1}}}^{{+{2}}}$"
+        summary.string = string_template.format(
+            fmt(summary.median), fmt(summary.minus), fmt(summary.plus))
+        return summary
+
+    def plot_marginals(self, parameters=None, priors=None, titles=True,
+                       file_base_name=None, bins=50, label_fontsize=16,
+                       title_fontsize=16, quantiles=[0.16, 0.84], dpi=300):
+        """ Plot 1D marginal distributions
+
+        Parameters
+        ----------
+        parameters: (list, dict), optional
+            If given, either a list of the parameter names to include, or a
+            dictionary of parameter names and their "true" values to plot.
+        priors: {bool (False), bilby.core.prior.PriorSet}
+            If true, add the stored prior probability density functions to the
+            one-dimensional marginal distributions. If instead a PriorSet
+            is provided, this will be plotted.
+        titles: bool
+            If true, add 1D titles of the median and (by default 1-sigma)
+            error bars. To change the error bars, pass in the quantiles kwarg.
+            See method `get_one_dimensional_median_and_error_bar` for further
+            details). If `quantiles=None` is passed in, no title is added.
+        file_base_name: str, optional
+            If given, the base file name to use (by default `outdir/label_` is
+            used)
+        bins: int
+            The number of histogram bins
+        label_fontsize, title_fontsize: int
+            The fontsizes for the labels and titles
+        quantiles: list
+            A length-2 list of the lower and upper-quantiles to calculate
+            the errors bars for.
+        dpi: int
+            Dots per inch resolution of the plot
+
+        Returns
+        -------
+        figures: dictionary
+            A dictionary of the matplotlib figures
+
+        """
+
+        if isinstance(parameters, dict):
+            plot_parameter_keys = list(parameters.keys())
+            truths = list(parameters.values())
+        elif parameters is None:
+            plot_parameter_keys = self.search_parameter_keys
+            truths = None
+        else:
+            plot_parameter_keys = list(parameters)
+            truths = None
+
+        labels = self.get_latex_labels_from_parameter_keys(plot_parameter_keys)
+        if file_base_name is None:
+            file_base_name = '{}/{}_'.format(self.outdir, self.label)
+
+        if priors is True:
+            priors = getattr(self, 'priors', False)
+        elif isinstance(priors, (dict)) or priors in [False, None]:
+            pass
+        else:
+            raise ValueError('Input priors={} not understood'.format(priors))
+
+        figures = dict()
+        for i, key in enumerate(plot_parameter_keys):
+            fig, ax = plt.subplots()
+            ax.hist(self.posterior[key].values, bins=bins, density=True,
+                    histtype='step')
+            ax.set_xlabel(labels[i], fontsize=label_fontsize)
+            if truths is not None:
+                ax.axvline(truths[i], ls='--', color='orange')
+
+            summary = self.get_one_dimensional_median_and_error_bar(
+                key, quantiles=quantiles)
+            ax.axvline(summary.median - summary.minus, ls='--', color='C0')
+            ax.axvline(summary.median + summary.plus, ls='--', color='C0')
+            if titles:
+                ax.set_title(summary.string, fontsize=title_fontsize)
+
+            if isinstance(priors, dict):
+                theta = np.linspace(ax.get_xlim()[0], ax.get_xlim()[1], 300)
+                ax.plot(theta, priors[key].prob(theta), color='C2')
+
+            fig.tight_layout()
+            fig.savefig(file_base_name + key)
+            figures[key] = fig
+
+        return figures
 
     def plot_corner(self, parameters=None, priors=None, titles=True, save=True,
                     filename=None, dpi=300, **kwargs):
@@ -311,9 +401,9 @@ class Result(dict):
         parameters: (list, dict), optional
             If given, either a list of the parameter names to include, or a
             dictionary of parameter names and their "true" values to plot.
-        priors: {bool (False), bilby.core.prior.PriorSet}
+        priors: {bool (False), bilby.core.prior.PriorDict}
             If true, add the stored prior probability density functions to the
-            one-dimensional marginal distributions. If instead a PriorSet
+            one-dimensional marginal distributions. If instead a PriorDict
             is provided, this will be plotted.
         titles: bool
             If true, add 1D titles of the median and (by default 1-sigma)
@@ -418,7 +508,7 @@ class Result(dict):
                 ax = axes[i + i * len(plot_parameter_keys)]
                 if ax.title.get_text() == '':
                     ax.set_title(self.get_one_dimensional_median_and_error_bar(
-                        par, quantiles=kwargs['quantiles']),
+                        par, quantiles=kwargs['quantiles']).string,
                         **kwargs['title_kwargs'])
 
         #  Add priors to the 1D plots
@@ -577,7 +667,7 @@ class Result(dict):
 
         Parameters
         ----------
-        priors: dict, PriorSet
+        priors: dict, PriorDict
             Prior distributions
         """
         self.prior_values = pd.DataFrame()
diff --git a/bilby/core/sampler/__init__.py b/bilby/core/sampler/__init__.py
index 12f90306b4f48eecaaf52ac3bb5df4b2c4d1c66c..bf5f8391489c36fd4b7415d44fe459d9eb310d4d 100644
--- a/bilby/core/sampler/__init__.py
+++ b/bilby/core/sampler/__init__.py
@@ -4,7 +4,7 @@ import datetime
 from collections import OrderedDict
 
 from ..utils import command_line_args, logger
-from ..prior import PriorSet
+from ..prior import PriorDict
 
 from .base_sampler import Sampler
 from .cpnest import Cpnest
@@ -47,8 +47,8 @@ def run_sampler(likelihood, priors=None, label='label', outdir='outdir',
     ----------
     likelihood: `bilby.Likelihood`
         A `Likelihood` instance
-    priors: `bilby.PriorSet`
-        A PriorSet/dictionary of the priors for each parameter - missing
+    priors: `bilby.PriorDict`
+        A PriorDict/dictionary of the priors for each parameter - missing
         parameters will use default priors, if None, all priors will be default
     label: str
         Name for the run, used in output files
@@ -101,8 +101,8 @@ def run_sampler(likelihood, priors=None, label='label', outdir='outdir',
         priors = dict()
 
     if type(priors) in [dict, OrderedDict]:
-        priors = PriorSet(priors)
-    elif isinstance(priors, PriorSet):
+        priors = PriorDict(priors)
+    elif isinstance(priors, PriorDict):
         pass
     else:
         raise ValueError("Input priors not understood")
diff --git a/bilby/core/sampler/base_sampler.py b/bilby/core/sampler/base_sampler.py
index a8ddc2fb0cf68effcfdcc5ea8bfc57ccdfe66e65..c9f1190fe13787da1754f3c4956628d462536897 100644
--- a/bilby/core/sampler/base_sampler.py
+++ b/bilby/core/sampler/base_sampler.py
@@ -3,7 +3,7 @@ import datetime
 import numpy as np
 from pandas import DataFrame
 from ..utils import logger, command_line_args
-from ..prior import Prior, PriorSet
+from ..prior import Prior, PriorDict
 from ..result import Result, read_in_result
 
 
@@ -14,7 +14,7 @@ class Sampler(object):
     ----------
     likelihood: likelihood.Likelihood
         A  object with a log_l method
-    priors: bilby.core.prior.PriorSet, dict
+    priors: bilby.core.prior.PriorDict, dict
         Priors to be used in the search.
         This has attributes for each parameter to be sampled.
     external_sampler: str, Sampler, optional
@@ -35,7 +35,7 @@ class Sampler(object):
     -------
     likelihood: likelihood.Likelihood
         A  object with a log_l method
-    priors: bilby.core.prior.PriorSet
+    priors: bilby.core.prior.PriorDict
         Priors to be used in the search.
         This has attributes for each parameter to be sampled.
     external_sampler: Module
@@ -74,10 +74,10 @@ class Sampler(object):
             self, likelihood, priors, outdir='outdir', label='label',
             use_ratio=False, plot=False, skip_import_verification=False, **kwargs):
         self.likelihood = likelihood
-        if isinstance(priors, PriorSet):
+        if isinstance(priors, PriorDict):
             self.priors = priors
         else:
-            self.priors = PriorSet(priors)
+            self.priors = PriorDict(priors)
         self.label = label
         self.outdir = outdir
         self.use_ratio = use_ratio
diff --git a/bilby/core/sampler/pymc3.py b/bilby/core/sampler/pymc3.py
index a797836f26617118acffa67915388d9cbd90fe29..bf6435ab8002969d662e49ea22391fff5227076d 100644
--- a/bilby/core/sampler/pymc3.py
+++ b/bilby/core/sampler/pymc3.py
@@ -1,10 +1,9 @@
 from __future__ import absolute_import, print_function
 
 from collections import OrderedDict
-import inspect
 import numpy as np
 
-from ..utils import derivatives, logger
+from ..utils import derivatives, logger, infer_args_from_method
 from ..prior import Prior
 from ..result import Result
 from .base_sampler import Sampler, MCMCSampler
@@ -437,7 +436,7 @@ class Pymc3(MCMCSampler):
         # then use that log_likelihood function, with the assumption that it
         # takes in a Pymc3 Sampler, with a pymc3_model attribute, and defines
         # the likelihood within that context manager
-        likeargs = inspect.getargspec(self.likelihood.log_likelihood).args
+        likeargs = infer_args_from_method(self.likelihood.log_likelihood)
         if 'sampler' in likeargs:
             self.likelihood.log_likelihood(sampler=self)
         else:
@@ -480,7 +479,7 @@ class Pymc3(MCMCSampler):
             for key in self.priors:
                 # if the prior contains ln_prob method that takes a 'sampler' argument
                 # then try using that
-                lnprobargs = inspect.getargspec(self.priors[key].ln_prob).args
+                lnprobargs = infer_args_from_method(self.priors[key].ln_prob)
                 if 'sampler' in lnprobargs:
                     try:
                         self.pymc3_priors[key] = self.priors[key].ln_prob(sampler=self)
@@ -500,7 +499,7 @@ class Pymc3(MCMCSampler):
                             if pymc3distname not in pymc3.__dict__:
                                 raise ValueError("Prior '{}' is not a known PyMC3 distribution.".format(pymc3distname))
 
-                            reqargs = inspect.getargspec(pymc3.__dict__[pymc3distname].__init__).args[1:]
+                            reqargs = infer_args_from_method(pymc3.__dict__[pymc3distname].__init__)
 
                             # set keyword arguments
                             priorkwargs = {}
diff --git a/bilby/core/utils.py b/bilby/core/utils.py
index bf88828d96b1093bed952e6f30017d19e1843e8a..4c9474b8b34c1f7702a4191405e01c0e0f05e21e 100644
--- a/bilby/core/utils.py
+++ b/bilby/core/utils.py
@@ -18,10 +18,39 @@ radius_of_earth = 6371 * 1e3  # metres
 
 
 def infer_parameters_from_function(func):
-    """ Infers the arguments of function (except the first arg which is
-        assumed to be the dep. variable)
+    """ Infers the arguments of a function
+        (except the first arg which is assumed to be the dep. variable).
+
+        Throws out *args and **kwargs type arguments
+
+        Can deal with type hinting!
+
+        Returns
+        ---------
+        list: A list of strings with the parameters
+    """
+    return _infer_args_from_function_except_for_first_arg(func=func)
+
+
+def infer_args_from_method(method):
+    """ Infers all arguments of a method except for 'self'
+
+    Throws out *args and **kwargs type arguments.
+
+    Can deal with type hinting!
+
+    Returns
+    ---------
+    list: A list of strings with the parameters
     """
-    parameters = inspect.getargspec(func).args
+    return _infer_args_from_function_except_for_first_arg(func=method)
+
+
+def _infer_args_from_function_except_for_first_arg(func):
+    try:
+        parameters = inspect.getfullargspec(func).args
+    except AttributeError:
+        parameters = inspect.getargspec(func).args
     parameters.pop(0)
     return parameters
 
@@ -348,15 +377,21 @@ def setup_logger(outdir=None, label=None, log_level='INFO', print_version=False)
     for handler in logger.handlers:
         handler.setLevel(level)
 
-    version_file = os.path.join(
-        os.path.dirname(os.path.dirname(__file__)), '.version')
-    with open(version_file, 'r') as f:
-        version = f.readline().rstrip()
-
     if print_version:
+        version = get_version_information()
         logger.info('Running bilby version: {}'.format(version))
 
 
+def get_version_information():
+    version_file = os.path.join(
+        os.path.dirname(os.path.dirname(__file__)), '.version')
+    try:
+        with open(version_file, 'r') as f:
+            return f.readline().rstrip()
+    except EnvironmentError:
+        print("No version information file '.version' found")
+
+
 def get_progress_bar(module='tqdm'):
     """
     TODO: Write proper docstring
@@ -453,9 +488,14 @@ def set_up_command_line_arguments():
     with `--help`.
 
     """
-    parser = argparse.ArgumentParser(
-        description="Command line interface for bilby scripts",
-        add_help=False)
+    try:
+        parser = argparse.ArgumentParser(
+            description="Command line interface for bilby scripts",
+            add_help=False, allow_abbrev=False)
+    except TypeError:
+        parser = argparse.ArgumentParser(
+            description="Command line interface for bilby scripts",
+            add_help=False)
     parser.add_argument("-v", "--verbose", action="store_true",
                         help=("Increase output verbosity [logging.DEBUG]." +
                               " Overridden by script level settings"))
diff --git a/bilby/gw/detector.py b/bilby/gw/detector.py
index 23eb90fbd16d28231fba60a322307fd172a764e4..20b67f79cec9a67414f9eb155c6a37ae3e5ce051 100644
--- a/bilby/gw/detector.py
+++ b/bilby/gw/detector.py
@@ -1134,6 +1134,8 @@ class Interferometer(object):
         array_like: A 3x3 array representation of the detector tensor
 
         """
+        if not self.__x_updated or not self.__y_updated:
+            _, _ = self.x, self.y  # noqa
         if not self.__detector_tensor_updated:
             self.__detector_tensor = 0.5 * (np.einsum('i,j->ij', self.x, self.x) - np.einsum('i,j->ij', self.y, self.y))
             self.__detector_tensor_updated = True
diff --git a/bilby/gw/likelihood.py b/bilby/gw/likelihood.py
index a06e0c1865f98a235dbcadc8b30e94d09dbd3b53..e775cd639b44dcf60e5a2ec7afdf3abdcc620de5 100644
--- a/bilby/gw/likelihood.py
+++ b/bilby/gw/likelihood.py
@@ -12,7 +12,7 @@ from ..core import likelihood
 from ..core.utils import logger
 from ..core.prior import Prior, Uniform
 from .detector import InterferometerList
-from .prior import BBHPriorSet
+from .prior import BBHPriorDict
 from .source import lal_binary_black_hole
 from .utils import noise_weighted_inner_product
 from .waveform_generator import WaveformGenerator
@@ -122,7 +122,7 @@ class GravitationalWaveTransient(likelihood.Likelihood):
                     self.interferometers.start_time,
                     self.interferometers.start_time + self.interferometers.duration)
             else:
-                self.prior[key] = BBHPriorSet()[key]
+                self.prior[key] = BBHPriorDict()[key]
 
     @property
     def prior(self):
diff --git a/bilby/gw/prior.py b/bilby/gw/prior.py
index 0907e49b6addf30dc77abb8008fa5f105a88bbad..2a1cff07c7868169b89e8f84d30beea5d52f27b3 100644
--- a/bilby/gw/prior.py
+++ b/bilby/gw/prior.py
@@ -1,7 +1,7 @@
 import os
 import numpy as np
 from scipy.interpolate import UnivariateSpline
-from ..core.prior import (PriorSet, Uniform, FromFile, Prior, DeltaFunction,
+from ..core.prior import (PriorDict, Uniform, FromFile, Prior, DeltaFunction,
                           Gaussian, Interped)
 from ..core.utils import logger
 
@@ -65,7 +65,7 @@ class AlignedSpin(Interped):
                           latex_label=latex_label, unit=unit)
 
 
-class BBHPriorSet(PriorSet):
+class BBHPriorDict(PriorDict):
     def __init__(self, dictionary=None, filename=None):
         """ Initialises a Prior set for Binary Black holes
 
@@ -82,7 +82,7 @@ class BBHPriorSet(PriorSet):
         elif filename is not None:
             if not os.path.isfile(filename):
                 filename = os.path.join(os.path.dirname(__file__), 'prior_files', filename)
-        PriorSet.__init__(self, dictionary=dictionary, filename=filename)
+        PriorDict.__init__(self, dictionary=dictionary, filename=filename)
 
     def test_redundancy(self, key):
         """
@@ -135,7 +135,15 @@ class BBHPriorSet(PriorSet):
         return redundant
 
 
-class BNSPriorSet(PriorSet):
+class BBHPriorSet(BBHPriorDict):
+
+    def __init__(self, dictionary=None, filename=None):
+        """ DEPRECATED: USE BBHPriorDict INSTEAD"""
+        logger.warning("The name 'BBHPriorSet' is deprecated use 'BBHPriorDict' instead")
+        super(BBHPriorSet, self).__init__(dictionary, filename)
+
+
+class BNSPriorDict(PriorDict):
 
     def __init__(self, dictionary=None, filename=None):
         """ Initialises a Prior set for Binary Neutron Stars
@@ -153,10 +161,10 @@ class BNSPriorSet(PriorSet):
         elif filename is not None:
             if not os.path.isfile(filename):
                 filename = os.path.join(os.path.dirname(__file__), 'prior_files', filename)
-        PriorSet.__init__(self, dictionary=dictionary, filename=filename)
+        PriorDict.__init__(self, dictionary=dictionary, filename=filename)
 
     def test_redundancy(self, key):
-        bbh_redundancy = BBHPriorSet().test_redundancy(key)
+        bbh_redundancy = BBHPriorDict().test_redundancy(key)
         if bbh_redundancy:
             return True
         redundant = False
@@ -174,6 +182,14 @@ class BNSPriorSet(PriorSet):
         return redundant
 
 
+class BNSPriorSet(BNSPriorDict):
+
+    def __init__(self, dictionary=None, filename=None):
+        """ DEPRECATED: USE BNSPriorDict INSTEAD"""
+        super(BNSPriorSet, self).__init__(dictionary, filename)
+        logger.warning("The name 'BNSPriorSet' is deprecated use 'BNSPriorDict' instead")
+
+
 Prior._default_latex_labels = {
     'mass_1': '$m_1$',
     'mass_2': '$m_2$',
@@ -203,7 +219,7 @@ Prior._default_latex_labels = {
     'delta_lambda': '$\\delta\\Lambda$'}
 
 
-class CalibrationPriorSet(PriorSet):
+class CalibrationPriorDict(PriorDict):
 
     def __init__(self, dictionary=None, filename=None):
         """ Initialises a Prior set for Binary Black holes
@@ -218,7 +234,7 @@ class CalibrationPriorSet(PriorSet):
         if dictionary is None and filename is not None:
             filename = os.path.join(os.path.dirname(__file__),
                                     'prior_files', filename)
-        PriorSet.__init__(self, dictionary=dictionary, filename=filename)
+        PriorDict.__init__(self, dictionary=dictionary, filename=filename)
         self.source = None
 
     def write_to_file(self, outdir, label):
@@ -233,7 +249,7 @@ class CalibrationPriorSet(PriorSet):
         label: str
             Label for prior.
         """
-        PriorSet.write_to_file(self, outdir=outdir, label=label)
+        PriorDict.write_to_file(self, outdir=outdir, label=label)
         if self.source is not None:
             prior_file = os.path.join(outdir, "{}.prior".format(label))
             with open(prior_file, "a") as outfile:
@@ -264,7 +280,7 @@ class CalibrationPriorSet(PriorSet):
 
         Returns
         -------
-        prior: PriorSet
+        prior: PriorDict
             Priors for the relevant parameters.
             This includes the frequencies of the nodes which are _not_ sampled.
         """
@@ -287,7 +303,7 @@ class CalibrationPriorSet(PriorSet):
         phase_sigma_nodes =\
             UnivariateSpline(frequency_array, phase_sigma)(nodes)
 
-        prior = CalibrationPriorSet()
+        prior = CalibrationPriorDict()
         for ii in range(n_nodes):
             name = "recalib_{}_amplitude_{}".format(label, ii)
             latex_label = "$A^{}_{}$".format(label, ii)
@@ -334,7 +350,7 @@ class CalibrationPriorSet(PriorSet):
 
         Returns
         -------
-        prior: PriorSet
+        prior: PriorDict
             Priors for the relevant parameters.
             This includes the frequencies of the nodes which are _not_ sampled.
         """
@@ -346,7 +362,7 @@ class CalibrationPriorSet(PriorSet):
         phase_mean_nodes = [0] * n_nodes
         phase_sigma_nodes = [phase_sigma] * n_nodes
 
-        prior = CalibrationPriorSet()
+        prior = CalibrationPriorDict()
         for ii in range(n_nodes):
             name = "recalib_{}_amplitude_{}".format(label, ii)
             latex_label = "$A^{}_{}$".format(label, ii)
@@ -366,3 +382,11 @@ class CalibrationPriorSet(PriorSet):
                                         latex_label=latex_label)
 
         return prior
+
+
+class CalibrationPriorSet(CalibrationPriorDict):
+
+    def __init__(self, dictionary=None, filename=None):
+        """ DEPRECATED: USE BNSPriorDict INSTEAD"""
+        super(CalibrationPriorSet, self).__init__(dictionary, filename)
+        logger.warning("The name 'CalibrationPriorSet' is deprecated use 'CalibrationPriorDict' instead")
diff --git a/bilby/hyper/model.py b/bilby/hyper/model.py
index d4859dc7feb3894cfcdc97f7fe16fbbc3a962f69..6fe300cf9a83d427fbce6a5993a2c07060460a03 100644
--- a/bilby/hyper/model.py
+++ b/bilby/hyper/model.py
@@ -1,4 +1,4 @@
-import inspect
+from bilby.core.utils import infer_parameters_from_function
 
 
 class Model(object):
@@ -18,8 +18,9 @@ class Model(object):
         self.models = model_functions
 
         self.parameters = dict()
-        for function in self.models:
-            for key in inspect.getargspec(function).args[1:]:
+        for func in self.models:
+            param_keys = infer_parameters_from_function(func)
+            for key in param_keys:
                 self.parameters[key] = None
 
     def prob(self, data):
@@ -30,6 +31,7 @@ class Model(object):
                 probability *= function(data, **self._get_function_parameters(function))
         return probability
 
-    def _get_function_parameters(self, function):
-        parameters = {key: self.parameters[key] for key in inspect.getargspec(function).args[1:]}
+    def _get_function_parameters(self, func):
+        param_keys = infer_parameters_from_function(func)
+        parameters = {key: self.parameters[key] for key in param_keys}
         return parameters
diff --git a/docs/conf.py b/docs/conf.py
index 26826cd01e885f00864b28b0b9a3838c7c48a557..cee8ec2b80bb5c4a03014d439b3c9a203933fabb 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -18,9 +18,9 @@
 #
 import os
 import sys
+import bilby
 sys.path.insert(0, os.path.abspath('../bilby/'))
 
-
 # -- General configuration ------------------------------------------------
 
 # If your documentation needs a minimal Sphinx version, state it here.
@@ -54,10 +54,13 @@ author = u'Paul Lasky'
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 #
+fullversion = bilby.__version__.split(':')[0]
+
 # The short X.Y version.
-version = u'0.2'
+version = '.'.join(fullversion.split('.')[:2])
+
 # The full version, including alpha/beta/rc tags.
-release = u'0.2'
+release = fullversion
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/examples/injection_examples/australian_detector.py b/examples/injection_examples/australian_detector.py
index 9fa165e03e765c65f41e52ffa705bb3e13a7af48..d770af182ce106e4b0e760a78413cb624bdf9aa7 100644
--- a/examples/injection_examples/australian_detector.py
+++ b/examples/injection_examples/australian_detector.py
@@ -89,7 +89,7 @@ for interferometer in interferometers:
     interferometer.plot_data(signal=signal, outdir=outdir, label=label)
 
 # set up priors
-priors = bilby.gw.prior.BBHPriorSet()
+priors = bilby.gw.prior.BBHPriorDict()
 for key in ['a_1', 'a_2', 'tilt_1', 'tilt_2', 'phi_12', 'phi_jl', 'psi',
             'geocent_time', 'phase']:
     priors[key] = injection_parameters[key]
diff --git a/examples/injection_examples/basic_tutorial.py b/examples/injection_examples/basic_tutorial.py
index 9fde009d64725aaa429c7c5131243951814ed2d1..cb9831e2a2e4f4b5b011b9d92dcad7cf15ead732 100644
--- a/examples/injection_examples/basic_tutorial.py
+++ b/examples/injection_examples/basic_tutorial.py
@@ -54,7 +54,7 @@ ifos.set_strain_data_from_power_spectral_densities(
 ifos.inject_signal(waveform_generator=waveform_generator,
                    parameters=injection_parameters)
 
-# Set up a PriorSet, which inherits from dict.
+# Set up a PriorDict, which inherits from dict.
 # By default we will sample all terms in the signal models.  However, this will
 # take a long time for the calculation, so for this example we will set almost
 # all of the priors to be equall to their injected values.  This implies the
@@ -64,7 +64,7 @@ ifos.inject_signal(waveform_generator=waveform_generator,
 # The above list does *not* include mass_1, mass_2, iota and luminosity
 # distance, which means those are the parameters that will be included in the
 # sampler.  If we do nothing, then the default priors get used.
-priors = bilby.gw.prior.BBHPriorSet()
+priors = bilby.gw.prior.BBHPriorDict()
 priors['geocent_time'] = bilby.core.prior.Uniform(
     minimum=injection_parameters['geocent_time'] - 1,
     maximum=injection_parameters['geocent_time'] + 1,
diff --git a/examples/injection_examples/binary_neutron_star_example.py b/examples/injection_examples/binary_neutron_star_example.py
index f46eb0e6e0defe874917a0756fa0c2b95478e8b8..f1ad6d2d372ec18049630a2b0d92f199c9fa7ad1 100644
--- a/examples/injection_examples/binary_neutron_star_example.py
+++ b/examples/injection_examples/binary_neutron_star_example.py
@@ -64,7 +64,7 @@ interferometers.inject_signal(parameters=injection_parameters,
 # Load the default prior for binary neutron stars.
 # We're going to sample in chirp_mass, symmetric_mass_ratio, lambda_tilde, and
 # delta_lambda rather than mass_1, mass_2, lambda_1, and lambda_2.
-priors = bilby.gw.prior.BNSPriorSet()
+priors = bilby.gw.prior.BNSPriorDict()
 for key in ['psi', 'geocent_time', 'ra', 'dec', 'chi_1', 'chi_2',
             'iota', 'luminosity_distance', 'phase']:
     priors[key] = injection_parameters[key]
diff --git a/examples/injection_examples/change_sampled_parameters.py b/examples/injection_examples/change_sampled_parameters.py
index 06dfa174033d12e53b02bb0f033eceeb64609da7..b2c848576bcde36985796e28c206c887411114d3 100644
--- a/examples/injection_examples/change_sampled_parameters.py
+++ b/examples/injection_examples/change_sampled_parameters.py
@@ -48,7 +48,7 @@ ifos.inject_signal(waveform_generator=waveform_generator,
 # Set up prior
 # Note it is possible to sample in different parameters to those that were
 # injected.
-priors = bilby.gw.prior.BBHPriorSet()
+priors = bilby.gw.prior.BBHPriorDict()
 priors.pop('mass_1')
 priors.pop('mass_2')
 priors.pop('luminosity_distance')
diff --git a/examples/injection_examples/eccentric_inspiral.py b/examples/injection_examples/eccentric_inspiral.py
index 2709220fc7b07e91af9597bff6872178447c7a43..ce4635c7b982cc4a44e0f7d976c1b300d0e1bc19 100644
--- a/examples/injection_examples/eccentric_inspiral.py
+++ b/examples/injection_examples/eccentric_inspiral.py
@@ -58,7 +58,7 @@ ifos.inject_signal(waveform_generator=waveform_generator,
                    parameters=injection_parameters)
 
 # Now we set up the priors on each of the binary parameters.
-priors = bilby.core.prior.PriorSet()
+priors = bilby.core.prior.PriorDict()
 priors["mass_1"] = bilby.core.prior.Uniform(
     name='mass_1', minimum=5, maximum=60, unit='$M_{\\odot}$')
 priors["mass_2"] = bilby.core.prior.Uniform(
diff --git a/examples/injection_examples/how_to_specify_the_prior.py b/examples/injection_examples/how_to_specify_the_prior.py
index 6a5eb033729cb1d3cb7f442c594084e8decd27f9..885ab328b955bc5794cf63bc194dc428972ac1fd 100644
--- a/examples/injection_examples/how_to_specify_the_prior.py
+++ b/examples/injection_examples/how_to_specify_the_prior.py
@@ -39,7 +39,7 @@ ifos.inject_signal(waveform_generator=waveform_generator,
 
 # Set up prior
 # This loads in a predefined set of priors for BBHs.
-priors = bilby.gw.prior.BBHPriorSet()
+priors = bilby.gw.prior.BBHPriorDict()
 # These parameters will not be sampled
 for key in ['tilt_1', 'tilt_2', 'phi_12', 'phi_jl', 'phase', 'iota', 'ra',
             'dec', 'geocent_time', 'psi']:
diff --git a/examples/injection_examples/marginalized_likelihood.py b/examples/injection_examples/marginalized_likelihood.py
index 05c1def463d2ddad61bbff15997e49c50f0233ec..685657725301d2ffd214aaad6f71b99eb4b257b8 100644
--- a/examples/injection_examples/marginalized_likelihood.py
+++ b/examples/injection_examples/marginalized_likelihood.py
@@ -38,7 +38,7 @@ ifos.inject_signal(waveform_generator=waveform_generator,
                    parameters=injection_parameters)
 
 # Set up prior
-priors = bilby.gw.prior.BBHPriorSet()
+priors = bilby.gw.prior.BBHPriorDict()
 # These parameters will not be sampled
 for key in ['a_1', 'a_2', 'tilt_1', 'tilt_2', 'phi_12', 'phi_jl', 'iota', 'ra',
             'dec']:
diff --git a/examples/injection_examples/plot_skymap.py b/examples/injection_examples/plot_skymap.py
index 5f1db3fc1c293dede1c59bc20445b554be135cdc..6453669ba0bc52396e892f1312351d69562e201a 100644
--- a/examples/injection_examples/plot_skymap.py
+++ b/examples/injection_examples/plot_skymap.py
@@ -30,7 +30,7 @@ ifos.set_strain_data_from_power_spectral_densities(
 ifos.inject_signal(waveform_generator=waveform_generator,
                    parameters=injection_parameters)
 
-priors = bilby.gw.prior.BBHPriorSet()
+priors = bilby.gw.prior.BBHPriorDict()
 for key in ['a_1', 'a_2', 'tilt_1', 'tilt_2', 'phi_12', 'phi_jl', 'psi',
             'mass_1', 'mass_2', 'phase', 'geocent_time', 'luminosity_distance',
             'iota']:
diff --git a/examples/open_data_examples/GW150914.py b/examples/open_data_examples/GW150914.py
index f44c9dd1cb4c82867f8880e612bf2cf0b1c711d2..f406b535f54916e360bbdc15901bd7306cffdca4 100644
--- a/examples/open_data_examples/GW150914.py
+++ b/examples/open_data_examples/GW150914.py
@@ -30,7 +30,7 @@ interferometers = bilby.gw.detector.get_event_data(label)
 # The prior is printed to the terminal at run-time.
 # You can overwrite this using the syntax below in the file,
 # or choose a fixed value by just providing a float value as the prior.
-prior = bilby.gw.prior.BBHPriorSet(filename='GW150914.prior')
+prior = bilby.gw.prior.BBHPriorDict(filename='GW150914.prior')
 
 # In this step we define a `waveform_generator`. This is out object which
 # creates the frequency-domain strain. In this instance, we are using the
diff --git a/examples/open_data_examples/GW150914_minimal.py b/examples/open_data_examples/GW150914_minimal.py
index 520fe6ae9aa3c7428207e6880660fc62dbc9f827..e37cb0003d170be2b4d832035fe26dabce7b24a8 100644
--- a/examples/open_data_examples/GW150914_minimal.py
+++ b/examples/open_data_examples/GW150914_minimal.py
@@ -6,7 +6,7 @@ stimation on GW150914 using open data.
 """
 import bilby
 
-prior = bilby.gw.prior.BBHPriorSet(filename='GW150914.prior')
+prior = bilby.gw.prior.BBHPriorDict(filename='GW150914.prior')
 interferometers = bilby.gw.detector.get_event_data("GW150914")
 likelihood = bilby.gw.likelihood.get_binary_black_hole_likelihood(interferometers)
 result = bilby.run_sampler(likelihood, prior, label='GW150914')
diff --git a/setup.py b/setup.py
index 1fb510d196306d87f49e47ef8d9632cbcd1f0fca..5747efc3ccfc320d6c99067b366b1fde5f2397e2 100644
--- a/setup.py
+++ b/setup.py
@@ -2,7 +2,7 @@
 
 from setuptools import setup
 import subprocess
-from os import path
+import os
 
 
 def write_version_file(version):
@@ -35,7 +35,7 @@ def write_version_file(version):
         git_status = ''
 
     version_file = '.version'
-    if path.isfile(version_file) is False:
+    if os.path.isfile(version_file) is False:
         with open('bilby/' + version_file, 'w+') as f:
             f.write('{}: {}'.format(version, git_status))
 
@@ -44,14 +44,21 @@ def write_version_file(version):
 
 def get_long_description():
     """ Finds the README and reads in the description """
-    here = path.abspath(path.dirname(__file__))
-    with open(path.join(here, 'README.rst')) as f:
+    here = os.path.abspath(os.path.dirname(__file__))
+    with open(os.path.join(here, 'README.rst')) as f:
             long_description = f.read()
     return long_description
 
 
-version = '0.3.1'
-version_file = write_version_file(version)
+# get version info from __init__.py
+def readfile(filename):
+    with open(filename) as fp:
+        filecontents = fp.read()
+    return filecontents
+
+
+VERSION = '0.3.1'
+version_file = write_version_file(VERSION)
 long_description = get_long_description()
 
 setup(name='bilby',
@@ -61,7 +68,7 @@ setup(name='bilby',
       author='Greg Ashton, Moritz Huebner, Paul Lasky, Colm Talbot',
       author_email='paul.lasky@monash.edu',
       license="MIT",
-      version=version,
+      version=VERSION,
       packages=['bilby', 'bilby.core', 'bilby.core.sampler',
                 'bilby.gw', 'bilby.hyper', 'cli_bilby'],
       package_dir={'bilby': 'bilby'},
diff --git a/test/detector_test.py b/test/detector_test.py
index 154bacf4a1fb020d2569c689a87bb9c7240e1beb..59efc53c8cb1e0986868e3c2a9a1263895882699 100644
--- a/test/detector_test.py
+++ b/test/detector_test.py
@@ -179,18 +179,50 @@ class TestDetector(unittest.TestCase):
         _ = self.ifo.detector_tensor
         with mock.patch('numpy.einsum') as m:
             m.return_value = 1
-            self.assertIsInstance(self.ifo.detector_tensor, np.ndarray)
+            expected = np.array([[-9.24529394e-06, 1.02425803e-04, 3.24550668e-04],
+                                 [1.02425803e-04, 1.37390844e-03, -8.61137566e-03],
+                                 [3.24550668e-04, -8.61137566e-03, -1.36466315e-03]])
+            self.assertTrue(np.allclose(expected, self.ifo.detector_tensor))
 
-    def test_detector_tensor_with_x_update(self):
+    def test_detector_tensor_with_x_azimuth_update(self):
+        _ = self.ifo.detector_tensor
         with mock.patch('numpy.einsum') as m:
             m.return_value = 1
-            self.ifo.xarm_azimuth = 12
-            self.assertEqual(self.ifo.detector_tensor, 0)
+            self.ifo.xarm_azimuth = 1
+            self.assertEqual(0, self.ifo.detector_tensor)
+
+    def test_detector_tensor_with_y_azimuth_update(self):
+        _ = self.ifo.detector_tensor
+        with mock.patch('numpy.einsum') as m:
+            m.return_value = 1
+            self.ifo.yarm_azimuth = 1
+            self.assertEqual(0, self.ifo.detector_tensor)
 
-    def test_detector_tensor_with_y_update(self):
+    def test_detector_tensor_with_x_tilt_update(self):
+        _ = self.ifo.detector_tensor
         with mock.patch('numpy.einsum') as m:
             m.return_value = 1
-            self.ifo.yarm_azimuth = 12
+            self.ifo.xarm_tilt = 1
+            self.assertEqual(0, self.ifo.detector_tensor)
+
+    def test_detector_tensor_with_y_tilt_update(self):
+        _ = self.ifo.detector_tensor
+        with mock.patch('numpy.einsum') as m:
+            m.return_value = 1
+            self.ifo.yarm_tilt = 1
+            self.assertEqual(0, self.ifo.detector_tensor)
+
+    def test_detector_tensor_with_longitude_update(self):
+        with mock.patch('numpy.einsum') as m:
+            m.return_value = 1
+            self.ifo.longitude = 1
+            self.assertEqual(0, self.ifo.detector_tensor)
+
+    def test_detector_tensor_with_latitude_update(self):
+        with mock.patch('numpy.einsum') as m:
+            _ = self.ifo.detector_tensor
+            m.return_value = 1
+            self.ifo.latitude = 1
             self.assertEqual(self.ifo.detector_tensor, 0)
 
     def test_antenna_response_default(self):
@@ -312,7 +344,6 @@ class TestDetector(unittest.TestCase):
                     float(self.maximum_frequency), float(self.length), float(self.latitude), float(self.longitude),
                     float(self.elevation), float(self.xarm_azimuth), float(self.yarm_azimuth), float(self.xarm_tilt),
                     float(self.yarm_tilt))
-        print(repr(self.ifo))
         self.assertEqual(expected, repr(self.ifo))
 
 
@@ -825,12 +856,12 @@ class TestPowerSpectralDensityWithoutFiles(unittest.TestCase):
 
     def test_power_spectral_density_interpolated_from_asd_array(self):
         expected = np.array([25.])
-        psd = bilby.gw.detector.PowerSpectralDensity(frequency_array=self.frequency_array, asd_array = self.asd_array)
+        psd = bilby.gw.detector.PowerSpectralDensity(frequency_array=self.frequency_array, asd_array=self.asd_array)
         self.assertEqual(expected, psd.power_spectral_density_interpolated(2))
 
     def test_power_spectral_density_interpolated_from_psd_array(self):
         expected = np.array([25.])
-        psd = bilby.gw.detector.PowerSpectralDensity(frequency_array=self.frequency_array, psd_array = self.psd_array)
+        psd = bilby.gw.detector.PowerSpectralDensity(frequency_array=self.frequency_array, psd_array=self.psd_array)
         self.assertEqual(expected, psd.power_spectral_density_interpolated(2))
 
     def test_from_amplitude_spectral_density_array(self):
diff --git a/test/gw_likelihood_test.py b/test/gw_likelihood_test.py
index b497cc15057fa5c13de0f862457acb7661ce2e12..133fadde7eb3bad57b1b1d5bf20065664ec175d6 100644
--- a/test/gw_likelihood_test.py
+++ b/test/gw_likelihood_test.py
@@ -85,7 +85,7 @@ class TestGWTransient(unittest.TestCase):
             frequency_domain_source_model=bilby.gw.source.lal_binary_black_hole,
         )
 
-        self.prior = bilby.gw.prior.BBHPriorSet()
+        self.prior = bilby.gw.prior.BBHPriorDict()
         self.prior['geocent_time'] = bilby.prior.Uniform(
             minimum=self.parameters['geocent_time'] - self.duration / 2,
             maximum=self.parameters['geocent_time'] + self.duration / 2)
@@ -158,7 +158,7 @@ class TestTimeMarginalization(unittest.TestCase):
             frequency_domain_source_model=bilby.gw.source.lal_binary_black_hole,
         )
 
-        self.prior = bilby.gw.prior.BBHPriorSet()
+        self.prior = bilby.gw.prior.BBHPriorDict()
         self.prior['geocent_time'] = bilby.prior.Uniform(
             minimum=self.parameters['geocent_time'] - self.duration / 2,
             maximum=self.parameters['geocent_time'] + self.duration / 2)
@@ -224,7 +224,7 @@ class TestMarginalizedLikelihood(unittest.TestCase):
             frequency_domain_source_model=bilby.gw.source.lal_binary_black_hole,
         )
 
-        self.prior = bilby.gw.prior.BBHPriorSet()
+        self.prior = bilby.gw.prior.BBHPriorDict()
         self.prior['geocent_time'] = bilby.prior.Uniform(
             minimum=self.parameters['geocent_time'] - self.duration / 2,
             maximum=self.parameters['geocent_time'] + self.duration / 2)
@@ -287,7 +287,7 @@ class TestPhaseMarginalization(unittest.TestCase):
             frequency_domain_source_model=bilby.gw.source.lal_binary_black_hole,
         )
 
-        self.prior = bilby.gw.prior.BBHPriorSet()
+        self.prior = bilby.gw.prior.BBHPriorDict()
         self.prior['geocent_time'] = bilby.prior.Uniform(
             minimum=self.parameters['geocent_time'] - self.duration / 2,
             maximum=self.parameters['geocent_time'] + self.duration / 2)
@@ -350,7 +350,7 @@ class TestTimePhaseMarginalization(unittest.TestCase):
             frequency_domain_source_model=bilby.gw.source.lal_binary_black_hole,
         )
 
-        self.prior = bilby.gw.prior.BBHPriorSet()
+        self.prior = bilby.gw.prior.BBHPriorDict()
         self.prior['geocent_time'] = bilby.prior.Uniform(
             minimum=self.parameters['geocent_time'] - self.duration / 2,
             maximum=self.parameters['geocent_time'] + self.duration / 2)
diff --git a/test/gw_prior_test.py b/test/gw_prior_test.py
index 966ccfe2c9e27a1003a674ef4969196065300773..dcab53d9e0bf1fd829e32c312f55563d9968bbf0 100644
--- a/test/gw_prior_test.py
+++ b/test/gw_prior_test.py
@@ -5,7 +5,7 @@ import os
 import sys
 
 
-class TestBBHPriorSet(unittest.TestCase):
+class TestBBHPriorDict(unittest.TestCase):
 
     def setUp(self):
         self.prior_dict = dict()
@@ -13,7 +13,7 @@ class TestBBHPriorSet(unittest.TestCase):
             '/'.join(os.path.dirname(
                 os.path.abspath(sys.argv[0])).split('/')[:-1])
         self.filename = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'prior_files/binary_black_holes.prior')
-        self.default_prior = bilby.gw.prior.BBHPriorSet(
+        self.default_prior = bilby.gw.prior.BBHPriorDict(
             filename=self.filename)
 
     def tearDown(self):
@@ -21,7 +21,7 @@ class TestBBHPriorSet(unittest.TestCase):
         del self.filename
 
     def test_create_default_prior(self):
-        default = bilby.gw.prior.BBHPriorSet()
+        default = bilby.gw.prior.BBHPriorDict()
         minima = all([self.default_prior[key].minimum == default[key].minimum
                       for key in default.keys()])
         maxima = all([self.default_prior[key].maximum == default[key].maximum
@@ -32,10 +32,10 @@ class TestBBHPriorSet(unittest.TestCase):
         self.assertTrue(all([minima, maxima, names]))
 
     def test_create_from_dict(self):
-        bilby.gw.prior.BBHPriorSet(dictionary=self.prior_dict)
+        bilby.gw.prior.BBHPriorDict(dictionary=self.prior_dict)
 
     def test_create_from_filename(self):
-        bilby.gw.prior.BBHPriorSet(filename=self.filename)
+        bilby.gw.prior.BBHPriorDict(filename=self.filename)
 
     def test_key_in_prior_not_redundant(self):
         test = self.default_prior.test_redundancy('mass_1')
@@ -62,7 +62,7 @@ class TestCalibrationPrior(unittest.TestCase):
         phase_sigma = 0.1
         n_nodes = 9
         label = 'test'
-        test = bilby.gw.prior.CalibrationPriorSet.constant_uncertainty_spline(
+        test = bilby.gw.prior.CalibrationPriorDict.constant_uncertainty_spline(
             amplitude_sigma, phase_sigma, self.minimum_frequency,
             self.maximum_frequency, n_nodes, label)
 
diff --git a/test/prior_test.py b/test/prior_test.py
index 94daee7f04c97f38b64d8bdca9d1c1ff73816549..c1a9c9fc1df745a2449d80d06c16b0e4abe77d31 100644
--- a/test/prior_test.py
+++ b/test/prior_test.py
@@ -295,7 +295,7 @@ class TestPriorClasses(unittest.TestCase):
             self.assertEqual(prior, repr_prior)
 
 
-class TestPriorSet(unittest.TestCase):
+class TestPriorDict(unittest.TestCase):
 
     def setUp(self):
         self.first_prior = bilby.core.prior.Uniform(name='a', minimum=0, maximum=1, unit='kg')
@@ -304,10 +304,10 @@ class TestPriorSet(unittest.TestCase):
         self.prior_dict = dict(mass=self.first_prior,
                                speed=self.second_prior,
                                length=self.third_prior)
-        self.prior_set_from_dict = bilby.core.prior.PriorSet(dictionary=self.prior_dict)
+        self.prior_set_from_dict = bilby.core.prior.PriorDict(dictionary=self.prior_dict)
         self.default_prior_file = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                                'prior_files/binary_black_holes.prior')
-        self.prior_set_from_file = bilby.core.prior.PriorSet(filename=self.default_prior_file)
+        self.prior_set_from_file = bilby.core.prior.PriorDict(filename=self.default_prior_file)
 
     def tearDown(self):
         del self.first_prior
@@ -387,7 +387,7 @@ class TestPriorSet(unittest.TestCase):
         self.assertDictEqual(expected, self.prior_set_from_dict)
 
     def test_prior_set_from_dict_but_using_a_string(self):
-        prior_set = bilby.core.prior.PriorSet(dictionary=self.default_prior_file)
+        prior_set = bilby.core.prior.PriorDict(dictionary=self.default_prior_file)
         expected = dict(
             mass_1=bilby.core.prior.Uniform(
                 name='mass_1', minimum=5, maximum=100, unit='$M_{\\odot}$'),
@@ -416,7 +416,7 @@ class TestPriorSet(unittest.TestCase):
 
     def test_dict_argument_is_not_string_or_dict(self):
         with self.assertRaises(ValueError):
-            bilby.core.prior.PriorSet(dictionary=list())
+            bilby.core.prior.PriorDict(dictionary=list())
 
     def test_sample_subset_correct_size(self):
         size = 7
@@ -476,7 +476,7 @@ class TestFillPrior(unittest.TestCase):
         self.likelihood.parameters = dict(a=0, b=0, c=0, d=0, asdf=0, ra=1)
         self.likelihood.non_standard_sampling_parameter_keys = dict(t=8)
         self.priors = dict(a=1, b=1.1, c='string', d=bilby.core.prior.Uniform(0, 1))
-        self.priors = bilby.core.prior.PriorSet(dictionary=self.priors)
+        self.priors = bilby.core.prior.PriorDict(dictionary=self.priors)
         self.default_prior_file = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                                'prior_files/binary_black_holes.prior')
         self.priors.fill_priors(self.likelihood, self.default_prior_file)
@@ -515,7 +515,7 @@ class TestCreateDefaultPrior(unittest.TestCase):
 
     def test_bbh_params(self):
         prior_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'prior_files/binary_black_holes.prior')
-        prior_set = bilby.core.prior.PriorSet(filename=prior_file)
+        prior_set = bilby.core.prior.PriorDict(filename=prior_file)
         for prior in prior_set:
             self.assertEqual(prior_set[prior], bilby.core.prior.create_default_prior(name=prior,
                                                                                      default_priors_file=prior_file))
diff --git a/test/result_test.py b/test/result_test.py
index 50a5e49588da7c9bc94e41a2853733256c419d87..8dabec04c819c040fb147764a7643c74d150b165 100644
--- a/test/result_test.py
+++ b/test/result_test.py
@@ -59,7 +59,7 @@ class TestResult(unittest.TestCase):
         self.result.plot_corner(parameters=dict(x=1, y=1))
 
     def test_plot_corner_with_priors(self):
-        priors = bilby.core.prior.PriorSet()
+        priors = bilby.core.prior.PriorDict()
         priors['x'] = bilby.core.prior.Uniform(-1, 1, 'x')
         priors['y'] = bilby.core.prior.Uniform(-1, 1, 'y')
         self.result.plot_corner(priors=priors)
diff --git a/test/utils_py3_test.py b/test/utils_py3_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..da7aeab899ea92413277323b1f6d11d4bd562434
--- /dev/null
+++ b/test/utils_py3_test.py
@@ -0,0 +1,54 @@
+from __future__ import absolute_import, division
+
+import unittest
+
+from bilby.core import utils
+
+
+class TestInferParameters(unittest.TestCase):
+
+    def setUp(self):
+        def source_function1(freqs, a, b: int):
+            return None
+
+        def source_function2(freqs, a, b, *args, **kwargs):
+            return None
+
+        def source_function3(freqs, a, b: int, *args, **kwargs):
+            return None
+
+        class TestClass:
+            def test_method(self, a, b: int, *args, **kwargs):
+                pass
+
+        self.source1 = source_function1
+        self.source2 = source_function2
+        self.source3 = source_function3
+        test_obj = TestClass()
+        self.source4 = test_obj.test_method
+
+    def tearDown(self):
+        del self.source1
+        del self.source2
+        del self.source3
+        del self.source4
+
+    def test_type_hinting(self):
+        expected = ['a', 'b']
+        actual = utils.infer_parameters_from_function(self.source1)
+        self.assertListEqual(expected, actual)
+
+    def test_args_kwargs_handling(self):
+        expected = ['a', 'b']
+        actual = utils.infer_parameters_from_function(self.source2)
+        self.assertListEqual(expected, actual)
+
+    def test_both(self):
+        expected = ['a', 'b']
+        actual = utils.infer_parameters_from_function(self.source3)
+        self.assertListEqual(expected, actual)
+
+    def test_self_handling(self):
+        expected = ['a', 'b']
+        actual = utils.infer_args_from_method(self.source4)
+        self.assertListEqual(expected, actual)
diff --git a/test/utils_test.py b/test/utils_test.py
index bea0d19e73d3e91af2a69ef5a5c12880842ec4d5..9b3abf9414755f6e641397caa653a1e452a4ae69 100644
--- a/test/utils_test.py
+++ b/test/utils_test.py
@@ -1,9 +1,10 @@
 from __future__ import absolute_import, division
 
-import bilby
 import unittest
 import numpy as np
-import matplotlib.pyplot as plt
+
+import bilby
+from bilby.core import utils
 
 
 class TestFFT(unittest.TestCase):
@@ -30,5 +31,34 @@ class TestFFT(unittest.TestCase):
         self.assertTrue(np.all(np.abs((tds - tds2) / tds) < 1e-12))
 
 
+class TestInferParameters(unittest.TestCase):
+
+    def setUp(self):
+        def source_function(freqs, a, b, *args, **kwargs):
+            return None
+
+        class TestClass:
+            def test_method(self, a, b, *args, **kwargs):
+                pass
+
+        self.source1 = source_function
+        test_obj = TestClass()
+        self.source2 = test_obj.test_method
+
+    def tearDown(self):
+        del self.source1
+        del self.source2
+
+    def test_args_kwargs_handling(self):
+        expected = ['a', 'b']
+        actual = utils.infer_parameters_from_function(self.source1)
+        self.assertListEqual(expected, actual)
+
+    def test_self_handling(self):
+        expected = ['a', 'b']
+        actual = utils.infer_args_from_method(self.source2)
+        self.assertListEqual(expected, actual)
+
+
 if __name__ == '__main__':
     unittest.main()