diff --git a/bilby/core/prior.py b/bilby/core/prior.py
index 2bac06180c989a62b96e22b2c8c94721f54d1440..3692fa899b92db300d1e16c0beb5b6e7daf1e609 100644
--- a/bilby/core/prior.py
+++ b/bilby/core/prior.py
@@ -423,7 +423,8 @@ class Prior(object):
         maximum: float, optional
             Maximum of the domain, default=np.inf
         periodic_boundary: bool, optional
-            Whether or not the boundary condition is periodic. Not available in all samplers.
+            Whether or not the boundary condition is periodic.
+            Currently implemented in cpnest, dynesty and pymultinest.
         """
         self.name = name
         self.latex_label = latex_label
@@ -542,8 +543,8 @@ class Prior(object):
         -------
         ValueError: If val is not between 0 and 1
         """
-        val = np.atleast_1d(val)
-        tests = (val < 0) + (val > 1)
+        valarray = np.atleast_1d(val)
+        tests = (valarray < 0) + (valarray > 1)
         if np.any(tests):
             raise ValueError("Number to be rescaled should be in [0, 1]")
 
@@ -699,7 +700,7 @@ class DeltaFunction(Prior):
         -------
         float: Rescaled probability, equivalent to peak
         """
-        Prior.test_valid_for_rescaling(val)
+        self.test_valid_for_rescaling(val)
         return self.peak * val ** 0
 
     def prob(self, val):
@@ -761,7 +762,7 @@ class PowerLaw(Prior):
         -------
         float: Rescaled probability
         """
-        Prior.test_valid_for_rescaling(val)
+        self.test_valid_for_rescaling(val)
         if self.alpha == -1:
             return self.minimum * np.exp(val * np.log(self.maximum / self.minimum))
         else:
@@ -834,7 +835,7 @@ class Uniform(Prior):
                        periodic_boundary=periodic_boundary)
 
     def rescale(self, val):
-        Prior.test_valid_for_rescaling(val)
+        self.test_valid_for_rescaling(val)
         return self.minimum + val * (self.maximum - self.minimum)
 
     def prob(self, val):
@@ -938,7 +939,7 @@ class SymmetricLogUniform(Prior):
         -------
         float: Rescaled probability
         """
-        Prior.test_valid_for_rescaling(val)
+        self.test_valid_for_rescaling(val)
         if val < 0.5:
             return -self.maximum * np.exp(-2 * val * np.log(self.maximum / self.minimum))
         elif val > 0.5:
@@ -1006,7 +1007,7 @@ class Cosine(Prior):
 
         This maps to the inverse CDF. This has been analytically solved for this case.
         """
-        Prior.test_valid_for_rescaling(val)
+        self.test_valid_for_rescaling(val)
         norm = 1 / (np.sin(self.maximum) - np.sin(self.minimum))
         return np.arcsin(val / norm + np.sin(self.minimum))
 
@@ -1054,7 +1055,7 @@ class Sine(Prior):
 
         This maps to the inverse CDF. This has been analytically solved for this case.
         """
-        Prior.test_valid_for_rescaling(val)
+        self.test_valid_for_rescaling(val)
         norm = 1 / (np.cos(self.minimum) - np.cos(self.maximum))
         return np.arccos(np.cos(self.minimum) - val / norm)
 
@@ -1102,7 +1103,7 @@ class Gaussian(Prior):
 
         This maps to the inverse CDF. This has been analytically solved for this case.
         """
-        Prior.test_valid_for_rescaling(val)
+        self.test_valid_for_rescaling(val)
         return self.mu + erfinv(2 * val - 1) * 2 ** 0.5 * self.sigma
 
     def prob(self, val):
@@ -1195,7 +1196,7 @@ class TruncatedGaussian(Prior):
 
         This maps to the inverse CDF. This has been analytically solved for this case.
         """
-        Prior.test_valid_for_rescaling(val)
+        self.test_valid_for_rescaling(val)
         return erfinv(2 * val * self.normalisation + erf(
             (self.minimum - self.mu) / 2 ** 0.5 / self.sigma)) * 2 ** 0.5 * self.sigma + self.mu
 
@@ -1324,7 +1325,7 @@ class LogNormal(Prior):
 
         This maps to the inverse CDF. This has been analytically solved for this case.
         """
-        Prior.test_valid_for_rescaling(val)
+        self.test_valid_for_rescaling(val)
         return scipy.stats.lognorm.ppf(val, self.sigma, scale=np.exp(self.mu))
 
     def prob(self, val):
@@ -1397,7 +1398,7 @@ class Exponential(Prior):
 
         This maps to the inverse CDF. This has been analytically solved for this case.
         """
-        Prior.test_valid_for_rescaling(val)
+        self.test_valid_for_rescaling(val)
         return scipy.stats.expon.ppf(val, scale=self.mu)
 
     def prob(self, val):
@@ -1458,7 +1459,7 @@ class StudentT(Prior):
 
         This maps to the inverse CDF. This has been analytically solved for this case.
         """
-        Prior.test_valid_for_rescaling(val)
+        self.test_valid_for_rescaling(val)
 
         # use scipy distribution percentage point function (ppf)
         return scipy.stats.t.ppf(val, self.df, loc=self.mu, scale=self.scale)
@@ -1526,7 +1527,7 @@ class Beta(Prior):
 
         This maps to the inverse CDF. This has been analytically solved for this case.
         """
-        Prior.test_valid_for_rescaling(val)
+        self.test_valid_for_rescaling(val)
 
         # use scipy distribution percentage point function (ppf)
         return self._dist.ppf(val)
@@ -1645,7 +1646,7 @@ class Logistic(Prior):
 
         This maps to the inverse CDF. This has been analytically solved for this case.
         """
-        Prior.test_valid_for_rescaling(val)
+        self.test_valid_for_rescaling(val)
 
         # use scipy distribution percentage point function (ppf)
         return scipy.stats.logistic.ppf(val, loc=self.mu, scale=self.scale)
@@ -1702,7 +1703,7 @@ class Cauchy(Prior):
 
         This maps to the inverse CDF. This has been analytically solved for this case.
         """
-        Prior.test_valid_for_rescaling(val)
+        self.test_valid_for_rescaling(val)
 
         # use scipy distribution percentage point function (ppf)
         return scipy.stats.cauchy.ppf(val, loc=self.alpha, scale=self.beta)
@@ -1785,7 +1786,7 @@ class Gamma(Prior):
 
         This maps to the inverse CDF. This has been analytically solved for this case.
         """
-        Prior.test_valid_for_rescaling(val)
+        self.test_valid_for_rescaling(val)
 
         # use scipy distribution percentage point function (ppf)
         return scipy.stats.gamma.ppf(val, self.k, loc=0., scale=self.theta)
@@ -1915,7 +1916,7 @@ class Interped(Prior):
 
         This maps to the inverse CDF. This is done using interpolation.
         """
-        Prior.test_valid_for_rescaling(val)
+        self.test_valid_for_rescaling(val)
         rescaled = self.inverse_cumulative_distribution(val)
         if rescaled.shape == ():
             rescaled = float(rescaled)
@@ -2079,7 +2080,7 @@ class FermiDirac(Prior):
         .. [1] M. Pitkin, M. Isi, J. Veitch & G. Woan, `arXiv:1705.08978v1
            <https:arxiv.org/abs/1705.08978v1>`_, 2017.
         """
-        Prior.test_valid_for_rescaling(val)
+        self.test_valid_for_rescaling(val)
 
         inv = (-np.exp(-1. * self.r) + (1. + np.exp(self.r))**-val +
                np.exp(-1. * self.r) * (1. + np.exp(self.r))**-val)
diff --git a/bilby/core/sampler/base_sampler.py b/bilby/core/sampler/base_sampler.py
index daa204293290a26dd2017ac32b52621a80a63a26..d1c0274b9630db21e1326ea374a1596ca50dc37d 100644
--- a/bilby/core/sampler/base_sampler.py
+++ b/bilby/core/sampler/base_sampler.py
@@ -494,7 +494,8 @@ class NestedSampler(Sampler):
 
 
 class MCMCSampler(Sampler):
-    nwalkers_equiv_kwargs = ['nwalker', 'nwalkers', 'draws']
+    nwalkers_equiv_kwargs = ['nwalker', 'nwalkers', 'draws', 'Niter']
+    nburn_equiv_kwargs = ['burn', 'nburn']
 
     def print_nburn_logging_info(self):
         """ Prints logging info as to how nburn was calculated """
diff --git a/bilby/core/sampler/dynesty.py b/bilby/core/sampler/dynesty.py
index e2787895f0cf220896b5e6c7aa232f046b33058e..94b9f6e689ad4573d4c7fcb5a80b5ca504619f16 100644
--- a/bilby/core/sampler/dynesty.py
+++ b/bilby/core/sampler/dynesty.py
@@ -71,7 +71,7 @@ class Dynesty(NestedSampler):
         If true, resume run from checkpoint (if available)
     """
     default_kwargs = dict(bound='multi', sample='rwalk',
-                          verbose=True,
+                          verbose=True, periodic=None,
                           check_point_delta_t=600, nlive=500,
                           first_update=None,
                           npdim=None, rstate=None, queue_size=None, pool=None,
@@ -95,6 +95,7 @@ class Dynesty(NestedSampler):
         self.n_check_point = n_check_point
         self.check_point = check_point
         self.resume = resume
+        self._apply_dynesty_boundaries()
         if self.n_check_point is None:
             # If the log_likelihood_eval_time is not calculable then
             # check_point is set to False.
@@ -173,6 +174,15 @@ class Dynesty(NestedSampler):
         sys.stderr.write(print_str)
         sys.stderr.flush()
 
+    def _apply_dynesty_boundaries(self):
+        if self.kwargs['periodic'] is None:
+            logger.debug("Setting periodic boundaries for keys:")
+            self.kwargs['periodic'] = []
+            for ii, key in enumerate(self.search_parameter_keys):
+                if self.priors[key].periodic_boundary:
+                    self.kwargs['periodic'].append(ii)
+                    logger.debug("  {}".format(key))
+
     def run_sampler(self):
         import dynesty
         self.sampler = dynesty.NestedSampler(
@@ -397,3 +407,23 @@ class Dynesty(NestedSampler):
         self.result.log_evidence = np.nan
         self.result.log_evidence_err = np.nan
         return self.result
+
+    def prior_transform(self, theta):
+        """ Prior transform method that is passed into the external sampler.
+        cube we map this back to [0, 1].
+
+        Parameters
+        ----------
+        theta: list
+            List of sampled values on a unit interval
+
+        Returns
+        -------
+        list: Properly rescaled sampled values
+
+        Notes
+        -----
+        Since dynesty allows periodic parameters to wander outside the unit
+        """
+        theta = np.mod(theta, 1)
+        return self.priors.rescale(self._search_parameter_keys, theta)
diff --git a/bilby/core/sampler/ptmcmc.py b/bilby/core/sampler/ptmcmc.py
index bdb13962f75d5ece4977d622651e6d5d69bc6255..d8c93d7270b07b3ab824e12e064130dbfa19fe51 100644
--- a/bilby/core/sampler/ptmcmc.py
+++ b/bilby/core/sampler/ptmcmc.py
@@ -78,7 +78,7 @@ class PTMCMCSampler(MCMCSampler):
 
     def _translate_kwargs(self, kwargs):
         if 'Niter' not in kwargs:
-            for equiv in self.nsteps_equiv_kwargs:
+            for equiv in self.nwalkers_equiv_kwargs:
                 if equiv in kwargs:
                     kwargs['Niter'] = kwargs.pop(equiv)
         if 'burn' not in kwargs:
diff --git a/bilby/core/sampler/pymultinest.py b/bilby/core/sampler/pymultinest.py
index 7472e900e61a051dcea65eb5b1a791ea5e11bf16..0533e3bece39084c8f0a29c92e3a7914f216673f 100644
--- a/bilby/core/sampler/pymultinest.py
+++ b/bilby/core/sampler/pymultinest.py
@@ -46,6 +46,14 @@ class Pymultinest(NestedSampler):
                           context=0, write_output=True, log_zero=-1e100,
                           max_iter=0, init_MPI=False, dump_callback=None)
 
+    def __init__(self, likelihood, priors, outdir='outdir', label='label', use_ratio=False, plot=False,
+                 skip_import_verification=False, **kwargs):
+        NestedSampler.__init__(self, likelihood=likelihood, priors=priors, outdir=outdir, label=label,
+                               use_ratio=use_ratio, plot=plot,
+                               skip_import_verification=skip_import_verification,
+                               **kwargs)
+        self._apply_multinest_boundaries()
+
     def _translate_kwargs(self, kwargs):
         if 'n_live_points' not in kwargs:
             for equiv in self.npoints_equiv_kwargs:
@@ -75,6 +83,15 @@ class Pymultinest(NestedSampler):
             self.kwargs['outputfiles_basename'])
         NestedSampler._verify_kwargs_against_default_kwargs(self)
 
+    def _apply_multinest_boundaries(self):
+        if self.kwargs['wrapped_params'] is None:
+            self.kwargs['wrapped_params'] = []
+            for param, value in self.priors.items():
+                if value.periodic_boundary:
+                    self.kwargs['wrapped_params'].append(1)
+                else:
+                    self.kwargs['wrapped_params'].append(0)
+
     def run_sampler(self):
         import pymultinest
         self._verify_kwargs_against_default_kwargs()
diff --git a/test/sampler_test.py b/test/sampler_test.py
index 314605470f75034b3b6eba3384e92a7d66f81a64..7c1024e1ce6d3140e6a7d52f67d5dc3e37b63db6 100644
--- a/test/sampler_test.py
+++ b/test/sampler_test.py
@@ -132,7 +132,9 @@ class TestDynesty(unittest.TestCase):
 
     def setUp(self):
         self.likelihood = MagicMock()
-        self.priors = dict()
+        self.priors = bilby.core.prior.PriorDict()
+        self.priors['a'] = bilby.core.prior.Prior(periodic_boundary=True)
+        self.priors['b'] = bilby.core.prior.Prior(periodic_boundary=False)
         self.sampler = bilby.core.sampler.Dynesty(self.likelihood, self.priors,
                                                   outdir='outdir', label='label',
                                                   use_ratio=False, plot=False,
@@ -144,7 +146,7 @@ class TestDynesty(unittest.TestCase):
         del self.sampler
 
     def test_default_kwargs(self):
-        expected = dict(bound='multi', sample='rwalk', verbose=True,
+        expected = dict(bound='multi', sample='rwalk', periodic=None, verbose=True,
                         check_point_delta_t=600, nlive=500, first_update=None,
                         npdim=None, rstate=None, queue_size=None, pool=None,
                         use_pool=None, live_points=None, logl_args=None, logl_kwargs=None,
@@ -152,12 +154,18 @@ class TestDynesty(unittest.TestCase):
                         enlarge=None, bootstrap=None, vol_dec=0.5, vol_check=2.0,
                         facc=0.5, slices=5, dlogz=0.1, maxiter=None, maxcall=None,
                         logl_max=np.inf, add_live=True, print_progress=True, save_bounds=True,
-                        walks=0, update_interval=300, print_func='func')
+                        walks=10, update_interval=300, print_func='func')
         self.sampler.kwargs['print_func'] = 'func'  # set this manually as this is not testable otherwise
+        self.assertListEqual([0], self.sampler.kwargs['periodic'])  # Check this separately
+        self.sampler.kwargs['periodic'] = None  # The dict comparison can't handle lists
+        for key in self.sampler.kwargs.keys():
+            print(key)
+            print(expected[key])
+            print(self.sampler.kwargs[key])
         self.assertDictEqual(expected, self.sampler.kwargs)
 
     def test_translate_kwargs(self):
-        expected = dict(bound='multi', sample='rwalk', verbose=True,
+        expected = dict(bound='multi', sample='rwalk', periodic=[0], verbose=True,
                         check_point_delta_t=600, nlive=250, first_update=None,
                         npdim=None, rstate=None, queue_size=None, pool=None,
                         use_pool=None, live_points=None, logl_args=None, logl_kwargs=None,
@@ -165,7 +173,7 @@ class TestDynesty(unittest.TestCase):
                         enlarge=None, bootstrap=None, vol_dec=0.5, vol_check=2.0,
                         facc=0.5, slices=5, dlogz=0.1, maxiter=None, maxcall=None,
                         logl_max=np.inf, add_live=True, print_progress=True, save_bounds=True,
-                        walks=0, update_interval=300, print_func='func')
+                        walks=10, update_interval=300, print_func='func')
 
         for equiv in bilby.core.sampler.base_sampler.NestedSampler.npoints_equiv_kwargs:
             new_kwargs = self.sampler.kwargs.copy()
@@ -385,7 +393,9 @@ class TestPymultinest(unittest.TestCase):
 
     def setUp(self):
         self.likelihood = MagicMock()
-        self.priors = dict()
+        self.priors = bilby.core.prior.PriorDict()
+        self.priors['a'] = bilby.core.prior.Prior(periodic_boundary=True)
+        self.priors['b'] = bilby.core.prior.Prior(periodic_boundary=False)
         self.sampler = bilby.core.sampler.Pymultinest(self.likelihood, self.priors,
                                                       outdir='outdir', label='label',
                                                       use_ratio=False, plot=False,
@@ -408,6 +418,8 @@ class TestPymultinest(unittest.TestCase):
                         max_modes=100, mode_tolerance=-1e90, seed=-1,
                         context=0, write_output=True, log_zero=-1e100,
                         max_iter=0, init_MPI=False, dump_callback=None)
+        self.assertListEqual([1, 0], self.sampler.kwargs['wrapped_params'])  # Check this separately
+        self.sampler.kwargs['wrapped_params'] = None  # The dict comparison can't handle lists
         self.assertDictEqual(expected, self.sampler.kwargs)
 
     def test_translate_kwargs(self):
@@ -425,6 +437,7 @@ class TestPymultinest(unittest.TestCase):
         for equiv in bilby.core.sampler.base_sampler.NestedSampler.npoints_equiv_kwargs:
             new_kwargs = self.sampler.kwargs.copy()
             del new_kwargs['n_live_points']
+            new_kwargs['wrapped_params'] = None  # The dict comparison can't handle lists
             new_kwargs[equiv] = 123
             self.sampler.kwargs = new_kwargs
             self.assertDictEqual(expected, self.sampler.kwargs)
@@ -444,8 +457,9 @@ class TestRunningSamplers(unittest.TestCase):
         self.likelihood = bilby.likelihood.GaussianLikelihood(
             self.x, self.y, self.model, self.sigma)
 
-        self.priors = dict(
-            m=bilby.core.prior.Uniform(0, 5), c=bilby.core.prior.Uniform(-2, 2))
+        self.priors = bilby.core.prior.PriorDict()
+        self.priors['m'] = bilby.core.prior.Uniform(0, 5, periodic_boundary=False)
+        self.priors['c'] = bilby.core.prior.Uniform(-2, 2, periodic_boundary=False)
         bilby.core.utils.check_directory_exists_and_if_not_mkdir('outdir')
 
     def tearDown(self):