diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 02803f2e..a9043a80 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -42,6 +42,9 @@ containers: # Fail if differences exist. If this fails, you may need to run # write_dockerfiles.py and commit the changes. - git diff --exit-code + - cp env-template.yml env.yml + - echo " - python=3.10" >> env.yml + - mamba env create -f env.yml -n test --dry-run .test-python: &test-python stage: initial diff --git a/AUTHORS.md b/AUTHORS.md index 1c137a2a..8c227ed6 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -29,6 +29,7 @@ Gregory Ashton Hank Hua Hector Estelles Ignacio MagaƱa Hernandez +Isaac McMahon Isobel Marguarethe Romero-Shaw Jack Heinzel Jacob Golomb diff --git a/CHANGELOG.md b/CHANGELOG.md index a6cdc8d1..564b6a37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,40 @@ # All notable changes will be documented in this file -## [2.2.3] 2024-02-24 +## [Unreleased] + + +## [2.3.0] - 2024-05-30 + +### Added + +- Add support for sampler plugins via entry points (!1340, !1355) +- Add `bilby.core.sampler.get_implemented_samplers` and `bilby.core.get_sampler_class` (!1340) +- Add `bilby.core.utils.entry_points.get_entry_points` (!1340) +- Add support for reading results from PathLike objects (!1342) +- Add `snrs_as_sample` property to `bilby.gw.likelihood.base.GravitationalWaveTransient` (!1344) +- Add `get_expected_outputs` method to the sampler classes (!1336) + +### Changed + +- Change `bilby_mcmc` to use `glasflow` instead of `nflows` (!1332) +- Sampler classes in are no longer imported in `bilby.core.sampler` (!1340) +- Sampler classes in `bilby.core.sampler.IMPLEMENTED_SAMPLERS` must now be loaded before use (!1340) +- `bilby.core.sampler.IMPLEMENTED_SAMPLERS` is now an instance of `bilby.core.sampler.ImplementedSampler` instead of a dictionary (!1355) +- Updates to support numpy v2 (!1362) + +### Fixed + +- Include final frequency point in relative binning integration (!1310) +- Address various deprecation warnings and deprecated keyword arguments (!1316, !1326, !1343) +- Fix typo in logging statement in `bilby.gw.source` (!1325) +- Fix missing import in `bilby.gw.detector.load_data_from_cache_file` (!1327) +- Fix bug where `linestyle` was ignored in `bilby.core.result.plot_multiple` (!1238) +- Fix `soft_init` sampler keyword argument with `dynesty` (!1335) +- Fix ZeroDivisionError when using the `dynesty` with `act-walk` and large values of `nact` (!1346) +- Fix custom prior loading from result file (!1360) + + +## [2.2.3] - 2024-02-24 Version 2.2.3 release of Bilby This is a bugfix release @@ -13,7 +47,7 @@ There are also a number of testing/infrastructure updates. - Add the ability to change the pool size when resuming a `dynesty` job (!1315) - Fix how the random seed is passed to `dynesty` (!1319) -## [2.2.2] 2023-11-29 +## [2.2.2] - 2023-11-29 Version 2.2.2 release of Bilby This is a bugfix release reverting a change from 2.2.1 @@ -21,7 +55,7 @@ This is a bugfix release reverting a change from 2.2.1 ### Changes - Revert !1284 (!1306) -## [2.2.1] 2023-1111 +## [2.2.1] - 2023-1111 Version 2.2.1 release of Bilby This release is a bugfix release. @@ -36,7 +70,7 @@ This release is a bugfix release. - A bug with saving lists that contain None (!1301) - Preparatory fix an upcoming change in dynesty (!1302) -## [2.2.0] 2023-07-24 +## [2.2.0] - 2023-07-24 Version 2.2.0 release of Bilby This release contains one new feature and drops support for Python 3.8. @@ -56,7 +90,7 @@ This release contains one new feature and drops support for Python 3.8. ### Deprecated - Drop support for py38 (!1277) -## [2.1.2] 2023-07-17 +## [2.1.2] - 2023-07-17 Version 2.1.2 release of Bilby This is a bugfix release. @@ -70,7 +104,7 @@ Where users have previously used `np.random.seed` they should now call - Enable cosmological priors to be written/read in our plain text format (!1258) - Allow posterior reweighting to be performed when changing the likelihood and the prior (!1260) -## [2.1.1] 2023-04-28 +## [2.1.1] - 2023-04-28 Version 2.1.1 release of Bilby Bugfix release @@ -80,7 +114,7 @@ Bugfix release - Bugfix for Fisher matrix proposals in `bilby_mcmc` (!1251) - Make the changes to the spline calibration backward compatible, 2.0.2 resume files can't be read with 2.1.0 (!1250) -## [2.1.0] 2023-04-12 +## [2.1.0] - 2023-04-12 Version 2.1.0 release of Bilby Minor feature improvements and bug fixes @@ -103,7 +137,7 @@ Minor feature improvements and bug fixes ### Deprecated - Reading/writing ROQ weights to json (!1232) -## [2.0.2] 2023-03-21 +## [2.0.2] - 2023-03-21 Version 2.0.2 release of Bilby This is a bugfix release after the last major update. @@ -113,7 +147,7 @@ This is a bugfix release after the last major update. - Fix to time calibration (!1234) - Fix nessai sampling time (!1236) -## [2.0.1] 2023-03-13 +## [2.0.1] - 2023-03-13 Version 2.0.1 release of Bilby This is a bugfix release after the last major update. @@ -126,7 +160,7 @@ Users may notice changes in inferred binary neutron star masses after updating t - Update value for the solar mass (!1229). - Make `scikit-learn` an explicit dependence of `bilby[GW]` (!1230). -## [2.0.0] 2023-02-29 +## [2.0.0] - 2023-02-29 Version 2.0.0 release of Bilby This major version release has a significant change to the behaviour of the `dynesty` wrapper. @@ -152,7 +186,7 @@ There are also a number of bugfixes and some new features in sampling and GW uti - Optimize ROQ waveform and calibration calls (!1216) - Add different proposal distribution and MCMC length for `dynesty` (!1187, !1222) -## [1.4.1] 2022-12-07 +## [1.4.1] - 2022-12-07 Version 1.4.1 release of Bilby This is a bugfix release to address some minor issues identified after v1.4.0. @@ -166,7 +200,7 @@ This is a bugfix release to address some minor issues identified after v1.4.0. - Make sure that all dumping pickle files is done safely (!1189) - Make error catching for `dynesty` checkpointing more robust (!1190) -## [1.4.0] 2022-11-18 +## [1.4.0] - 2022-11-18 Version 1.4.0 release of Bilby The main changes in this release are support for more recent versions of `dynesty` (!1138) @@ -188,7 +222,7 @@ and `nessai` (!1161) and adding the - Allow prior arguments read from a string to be functions (!1144) - Support `dynesty>=1.1.0` (!1138) -## [1.3.0] 2022-10-23 +## [1.3.0] - 2022-10-23 Version 1.3.0 release of Bilby This release has a major change to a sampler interface, `pymc3` is no longer supported, users should switch to `pymc>=4`. @@ -212,7 +246,7 @@ This release also contains various documentation improvements. - Fix issue when specifying distance and redshfit independently (!1154) - Fix a bug in the storage of likelihood/prior samples for `bilby_mcmc` (!1156) -## [1.2.1] 2022-09-05 +## [1.2.1] - 2022-09-05 Version 1.2.1 release of Bilby This release contains a few bug fixes following 1.2.0. @@ -230,7 +264,7 @@ This release contains a few bug fixes following 1.2.0. - Extend mass conversions to include source-frame parameters (!1131) - Fix prior ranges for GW150914 example (!1129) -## [1.2.0] 2022-08-15 +## [1.2.0] - 2022-08-15 Version 1.2.0 release of Bilby This is the first release that drops support for `Python<3.8`. @@ -261,7 +295,7 @@ with multiprocessing. - `bilby.core.utils.progress` - Deepdish IO for `Result`, `Interferometer`, and `InterferometerList` -## [1.1.5] 2022-01-14 +## [1.1.5] - 2022-01-14 Version 1.1.5 release of Bilby ### Added @@ -279,7 +313,7 @@ Version 1.1.5 release of Bilby - Improvements to the multi-banded GWT likelihood (!1026) - Improve meta data comparison (!1035) -## [1.1.4] 2021-10-08 +## [1.1.4] - 2021-10-08 Version 1.1.4 release of bilby ### Added @@ -299,7 +333,7 @@ Version 1.1.4 release of bilby - Typo fix in eart light crossing (!1003) - Fix zero spin conversion (!1002) -## [1.1.3] 2021-07-02 +## [1.1.3] - 2021-07-02 Version 1.1.3 release of bilby ### Added @@ -329,7 +363,7 @@ Version 1.1.3 release of bilby - Restructured utils module into several submodules. API remains backwards compatible (!873) - Changed number of default walks in `dynesty` from `10*self.ndim` to `100` (!961) -## [1.1.2] 2021-05-05 +## [1.1.2] - 2021-05-05 Version 1.1.2 release of bilby ### Added @@ -359,13 +393,13 @@ Version 1.1.2 release of bilby - Fixed issues with pickle saving and loading (!932) - Fixed an issue with the `_base_roq_waveform` (!959) -## [1.1.1] 2021-03-16 +## [1.1.1] - 2021-03-16 Version 1.1.1 release of bilby ### Changes - Added `include requirements.txt` in `MANIFEST.in` to stop the pip installation from breaking -## [1.1.0] 2021-03-15 +## [1.1.0] - 2021-03-15 Version 1.1.0 release of bilby ### Added @@ -404,7 +438,7 @@ Version 1.1.0 release of bilby - Fixed the likelihood count in `dynesty` (!853) - Changed the ordering of keyword arguments for the `Sine` and `Cosine` constructors (!892) -## [1.0.4] 2020-11-23 +## [1.0.4] - 2020-11-23 Version 1.0.4 release of bilby ### Added @@ -413,7 +447,7 @@ Version 1.0.4 release of bilby ### Changes - Fixed issue in the CI -## [1.0.3] 2020-10-23 +## [1.0.3] - 2020-10-23 Version 1.0.3 release of bilby @@ -432,7 +466,7 @@ Version 1.0.3 release of bilby - Typo fixes (!878, !887, !879) - Minor bug fixes (!888) -## [1.0.2] 2020-09-14 +## [1.0.2] - 2020-09-14 Version 1.0.2 release of bilby @@ -454,7 +488,7 @@ Version 1.0.2 release of bilby - Clean up of code (!854) - Various minor bug, test and plotting fixes (!859, !874, !872, !865) -## [1.0.1] 2020-08-29 +## [1.0.1] - 2020-08-29 Version 1.0.1 release of bilby @@ -479,7 +513,7 @@ Version 1.0.1 release of bilby - Various minor bug fixes and improvements to the documentation (!820)(!823)(!837) - Various testing improvements (!833)(!847)(!855)(!852) -## [1.0.0] 2020-07-06 +## [1.0.0] - 2020-07-06 Version 1.0 release of bilby @@ -1030,3 +1064,33 @@ First `pip` installable version https://pypi.org/project/BILBY/ . ### Removed - All chainconsumer dependency as this was causing issues. + + +[Unreleased]: https://git.ligo.org/lscsoft/bilby/-/compare/v2.3.0...master +[2.3.0]: https://git.ligo.org/lscsoft/bilby/-/compare/v2.2.3...v2.3.0 +[2.2.3]: https://git.ligo.org/lscsoft/bilby/-/compare/v2.2.2...v2.2.3 +[2.2.2]: https://git.ligo.org/lscsoft/bilby/-/compare/v2.2.1...v2.2.2 +[2.2.1]: https://git.ligo.org/lscsoft/bilby/-/compare/v2.2.0...v2.2.1 +[2.2.0]: https://git.ligo.org/lscsoft/bilby/-/compare/v2.1.2...v2.2.0 +[2.1.2]: https://git.ligo.org/lscsoft/bilby/-/compare/v2.1.1...v2.1.2 +[2.1.1]: https://git.ligo.org/lscsoft/bilby/-/compare/v2.1.0...v2.1.1 +[2.1.0]: https://git.ligo.org/lscsoft/bilby/-/compare/v2.0.2...v2.1.0 +[2.0.2]: https://git.ligo.org/lscsoft/bilby/-/compare/v2.0.1...v2.0.2 +[2.0.1]: https://git.ligo.org/lscsoft/bilby/-/compare/v2.0.0...v2.0.1 +[2.0.0]: https://git.ligo.org/lscsoft/bilby/-/compare/v1.4.1...v2.0.0 +[1.4.1]: https://git.ligo.org/lscsoft/bilby/-/compare/v1.4.0...v1.4.1 +[1.4.0]: https://git.ligo.org/lscsoft/bilby/-/compare/1.3.0...v1.4.0 +[1.3.0]: https://git.ligo.org/lscsoft/bilby/-/compare/1.2.1...1.3.0 +[1.2.1]: https://git.ligo.org/lscsoft/bilby/-/compare/1.2.0...1.2.1 +[1.2.0]: https://git.ligo.org/lscsoft/bilby/-/compare/1.1.5...1.2.0 +[1.1.5]: https://git.ligo.org/lscsoft/bilby/-/compare/1.1.4...1.1.5 +[1.1.4]: https://git.ligo.org/lscsoft/bilby/-/compare/1.1.2...1.1.4 +[1.1.3]: https://git.ligo.org/lscsoft/bilby/-/compare/1.1.2...1.1.3 +[1.1.2]: https://git.ligo.org/lscsoft/bilby/-/compare/1.1.1...1.1.2 +[1.1.1]: https://git.ligo.org/lscsoft/bilby/-/compare/1.1.0...1.1.1 +[1.1.0]: https://git.ligo.org/lscsoft/bilby/-/compare/1.0.4...1.1.0 +[1.0.4]: https://git.ligo.org/lscsoft/bilby/-/compare/1.0.3...1.0.4 +[1.0.3]: https://git.ligo.org/lscsoft/bilby/-/compare/1.0.2...1.0.3 +[1.0.2]: https://git.ligo.org/lscsoft/bilby/-/compare/1.0.1...1.0.2 +[1.0.1]: https://git.ligo.org/lscsoft/bilby/-/compare/1.0.0...1.0.1 +[1.0.0]: https://git.ligo.org/lscsoft/bilby/-/compare/0.6.9...1.0.0 diff --git a/README.rst b/README.rst index 70bc2efa..d14c44fe 100644 --- a/README.rst +++ b/README.rst @@ -30,47 +30,7 @@ us directly. For advice on contributing, see `the contributing guide `__ -* `Bayesian inference for compact binary coalescences with BILBY: validation and application to the first LIGO-Virgo gravitational-wave transient catalogue `__ - -The first of these papers introduces the software, while the second introduces advances in the sampling approaches and validation of the software. -If you use the :code:`bilby_mcmc` sampler, please additionally cite - -* `BILBY-MCMC: an MCMC sampler for gravitational-wave inference `__ - -Additionally, :code:`bilby` builds on a number of open-source packages. If you -make use of this functionality in your publications, we recommend you cite them -as requested in their associated documentation. - -**Samplers** - -* `dynesty `__ -* `nestle `__ -* `pymultinest `__ -* `cpnest `__ -* `emcee `__ -* `nessai `_ -* `ptemcee `__ -* `ptmcmcsampler `__ -* `pypolychord `__ -* `PyMC3 `_ - - -**Gravitational-wave tools** - -* `gwpy `__ -* `lalsuite `__ -* `astropy `__ - -**Plotting** - -* `corner `__ for generating corner plot -* `matplotlib `__ for general plotting routines - +Please refer to the `Acknowledging/citing bilby guide `__. .. |pipeline status| image:: https://git.ligo.org/lscsoft/bilby/badges/master/pipeline.svg :target: https://git.ligo.org/lscsoft/bilby/commits/master diff --git a/bilby/bilby_mcmc/sampler.py b/bilby/bilby_mcmc/sampler.py index fcd4c9c5..6676c76d 100644 --- a/bilby/bilby_mcmc/sampler.py +++ b/bilby/bilby_mcmc/sampler.py @@ -127,6 +127,9 @@ class Bilby_MCMC(MCMCSampler): initial_sample_dict: dict A dictionary of the initial sample value. If incomplete, will overwrite the initial_sample drawn using initial_sample_method. + normalize_prior: bool + When False, disables calculation of constraint normalization factor + during prior probability computation. Default value is True. verbose: bool Whether to print diagnostic output during the run. @@ -175,6 +178,7 @@ def __init__( resume=True, exit_code=130, verbose=True, + normalize_prior=True, **kwargs, ): @@ -194,6 +198,7 @@ def __init__( self.kwargs["target_nsamples"] = self.kwargs["nsamples"] self.L1steps = self.kwargs["L1steps"] self.L2steps = self.kwargs["L2steps"] + self.normalize_prior = normalize_prior self.pt_inputs = ParallelTemperingInputs( **{key: self.kwargs[key] for key in ParallelTemperingInputs._fields} ) @@ -309,6 +314,7 @@ def init_ptsampler(self): evidence_method=self.evidence_method, initial_sample_method=self.initial_sample_method, initial_sample_dict=self.initial_sample_dict, + normalize_prior=self.normalize_prior, ) def get_setup_string(self): @@ -547,6 +553,29 @@ def plot_progress(ptsampler, label, outdir, priors, diagnostic=False): all_samples=ptsampler.samples, ) + @classmethod + def get_expected_outputs(cls, outdir=None, label=None): + """Get lists of the expected outputs directories and files. + + These are used by :code:`bilby_pipe` when transferring files via HTCondor. + + Parameters + ---------- + outdir : str + The output directory. + label : str + The label for the run. + + Returns + ------- + list + List of file names. + list + List of directory names. Will always be empty for bilby_mcmc. + """ + filenames = [os.path.join(outdir, f"{label}_resume.pickle")] + return filenames, [] + class BilbyPTMCMCSampler(object): def __init__( @@ -560,11 +589,13 @@ def __init__( evidence_method, initial_sample_method, initial_sample_dict, + normalize_prior=True, ): self.set_pt_inputs(pt_inputs) self.use_ratio = use_ratio self.initial_sample_method = initial_sample_method self.initial_sample_dict = initial_sample_dict + self.normalize_prior = normalize_prior self.setup_sampler_dictionary(convergence_inputs, proposal_cycle) self.set_convergence_inputs(convergence_inputs) self.pt_rejection_sample = pt_rejection_sample @@ -635,6 +666,7 @@ def setup_sampler_dictionary(self, convergence_inputs, proposal_cycle): use_ratio=self.use_ratio, initial_sample_method=self.initial_sample_method, initial_sample_dict=self.initial_sample_dict, + normalize_prior=self.normalize_prior, ) for Eindex in range(n) ] @@ -1129,12 +1161,13 @@ def __init__( use_ratio=False, initial_sample_method="prior", initial_sample_dict=None, + normalize_prior=True, ): self.beta = beta self.Tindex = Tindex self.Eindex = Eindex self.use_ratio = use_ratio - + self.normalize_prior = normalize_prior self.parameters = _sampling_convenience_dump.priors.non_fixed_keys self.ndim = len(self.parameters) @@ -1209,7 +1242,10 @@ def log_likelihood(self, sample): return logl def log_prior(self, sample): - return _sampling_convenience_dump.priors.ln_prob(sample.parameter_only_dict) + return _sampling_convenience_dump.priors.ln_prob( + sample.parameter_only_dict, + normalized=self.normalize_prior, + ) def accept_proposal(self, prop, proposal): self.chain.append(prop) diff --git a/bilby/core/prior/dict.py b/bilby/core/prior/dict.py index 33fab56e..6b532cc4 100644 --- a/bilby/core/prior/dict.py +++ b/bilby/core/prior/dict.py @@ -537,7 +537,7 @@ def check_prob(self, sample, prob): constrained_prob[keep] = prob[keep] * ratio return constrained_prob - def ln_prob(self, sample, axis=None): + def ln_prob(self, sample, axis=None, normalized=True): """ Parameters @@ -546,6 +546,9 @@ def ln_prob(self, sample, axis=None): Dictionary of the samples of which to calculate the log probability axis: None or int Axis along which the summation is performed + normalized: bool + When False, disables calculation of constraint normalization factor + during prior probability computation. Default value is True. Returns ======= @@ -554,10 +557,14 @@ def ln_prob(self, sample, axis=None): """ ln_prob = np.sum([self[key].ln_prob(sample[key]) for key in sample], axis=axis) - return self.check_ln_prob(sample, ln_prob) + return self.check_ln_prob(sample, ln_prob, + normalized=normalized) - def check_ln_prob(self, sample, ln_prob): - ratio = self.normalize_constraint_factor(tuple(sample.keys())) + def check_ln_prob(self, sample, ln_prob, normalized=True): + if normalized: + ratio = self.normalize_constraint_factor(tuple(sample.keys())) + else: + ratio = 1 if np.all(np.isinf(ln_prob)): return ln_prob else: @@ -785,7 +792,7 @@ def prob(self, sample, **kwargs): prob = np.prod(res, **kwargs) return self.check_prob(sample, prob) - def ln_prob(self, sample, axis=None): + def ln_prob(self, sample, axis=None, normalized=True): """ Parameters @@ -794,6 +801,9 @@ def ln_prob(self, sample, axis=None): Dictionary of the samples of which we want to have the log probability of axis: Union[None, int] Axis along which the summation is performed + normalized: bool + When False, disables calculation of constraint normalization factor + during prior probability computation. Default value is True. Returns ======= @@ -806,7 +816,8 @@ def ln_prob(self, sample, axis=None): for key in sample ] ln_prob = np.sum(res, axis=axis) - return self.check_ln_prob(sample, ln_prob) + return self.check_ln_prob(sample, ln_prob, + normalized=normalized) def cdf(self, sample): self._prepare_evaluation(*zip(*sample.items())) diff --git a/bilby/core/sampler/__init__.py b/bilby/core/sampler/__init__.py index 5d56b3ea..ef65ce1d 100644 --- a/bilby/core/sampler/__init__.py +++ b/bilby/core/sampler/__init__.py @@ -13,7 +13,74 @@ from . import proposal from .base_sampler import Sampler, SamplingMarginalisedParameterError -IMPLEMENTED_SAMPLERS = get_entry_points("bilby.samplers") + +class ImplementedSamplers: + """Dictionary-like object that contains implemented samplers. + + This class is singleton and only one instance can exist. + """ + + _instance = None + + _samplers = get_entry_points("bilby.samplers") + + def keys(self): + """Iterator of available samplers by name. + + Reduces the list to its simplest. This includes removing the 'bilby.' + prefix from native samplers if a corresponding plugin is not available. + """ + keys = [] + for key in self._samplers.keys(): + name = key.replace("bilby.", "") + if name in self._samplers.keys(): + keys.append(key) + else: + keys.append(name) + return iter(keys) + + def values(self): + """Iterator of sampler classes. + + Note: the classes need to loaded using :code:`.load()` before being + called. + """ + return iter(self._samplers.values()) + + def items(self): + """Iterator of tuples containing keys (sampler names) and classes. + + Note: the classes need to loaded using :code:`.load()` before being + called. + """ + return iter(((k, v) for k, v in zip(self.keys(), self.values()))) + + def valid_keys(self): + """All valid keys including bilby..""" + keys = set(self._samplers.keys()) + return iter(keys.union({k.replace("bilby.", "") for k in keys})) + + def __getitem__(self, key): + if key in self._samplers: + return self._samplers[key] + elif f"bilby.{key}" in self._samplers: + return self._samplers[f"bilby.{key}"] + else: + raise ValueError( + f"Sampler {key} is not implemented! " + f"Available samplers are: {list(self.keys())}" + ) + + def __contains__(self, value): + return value in self.valid_keys() + + def __new__(cls): + if cls._instance is None: + cls._instance = super().__new__(cls) + return cls._instance + + +IMPLEMENTED_SAMPLERS = ImplementedSamplers() def get_implemented_samplers(): @@ -51,14 +118,7 @@ def get_sampler_class(sampler): ValueError Raised if the sampler is not implemented. """ - sampler = sampler.lower() - if sampler in IMPLEMENTED_SAMPLERS: - return IMPLEMENTED_SAMPLERS[sampler].load() - else: - raise ValueError( - f"Sampler {sampler} not yet implemented. " - f"The available samplers are: {get_implemented_samplers()}" - ) + return IMPLEMENTED_SAMPLERS[sampler.lower()].load() if command_line_args.sampler_help: diff --git a/bilby/core/sampler/base_sampler.py b/bilby/core/sampler/base_sampler.py index 3f73cb79..3c573afe 100644 --- a/bilby/core/sampler/base_sampler.py +++ b/bilby/core/sampler/base_sampler.py @@ -173,6 +173,13 @@ class Sampler(object): Whether the implemented sampler exits hard (:code:`os._exit` rather than :code:`sys.exit`). The latter can be escaped as :code:`SystemExit`. The former cannot. + sampler_name : str + Name of the sampler. This is used when creating the output directory for + the sampler. + abbreviation : str + Abbreviated name of the sampler. Does not have to be specified in child + classes. If set to a value other than :code:`None`, this will be used + instead of :code:`sampler_name` when creating the output directory. Raises ====== @@ -187,6 +194,8 @@ class Sampler(object): """ + sampler_name = "sampler" + abbreviation = None default_kwargs = dict() npool_equiv_kwargs = [ "npool", @@ -779,8 +788,37 @@ def _setup_pool(self): def write_current_state(self): raise NotImplementedError() + @classmethod + def get_expected_outputs(cls, outdir=None, label=None): + """Get lists of the expected outputs directories and files. + + These are used by :code:`bilby_pipe` when transferring files via HTCondor. + Both can be empty. Defaults to a single directory: + :code:`"{outdir}/{name}_{label}/"`, where :code:`name` + is :code:`abbreviation` if it is defined for the sampler class, otherwise + it defaults to :code:`sampler_name`. + + Parameters + ---------- + outdir : str + The output directory. + label : str + The label for the run. + + Returns + ------- + list + List of file names. + list + List of directory names. + """ + name = cls.abbreviation or cls.sampler_name + dirname = os.path.join(outdir, f"{name}_{label}", "") + return [], [dirname] + class NestedSampler(Sampler): + sampler_name = "nested_sampler" npoints_equiv_kwargs = [ "nlive", "nlives", @@ -854,6 +892,7 @@ def log_likelihood(self, theta): class MCMCSampler(Sampler): + sampler_name = "mcmc_sampler" nwalkers_equiv_kwargs = ["nwalker", "nwalkers", "draws", "Niter"] nburn_equiv_kwargs = ["burn", "nburn"] diff --git a/bilby/core/sampler/cpnest.py b/bilby/core/sampler/cpnest.py index e1f3ae19..e777ebc6 100644 --- a/bilby/core/sampler/cpnest.py +++ b/bilby/core/sampler/cpnest.py @@ -40,6 +40,7 @@ class Cpnest(NestedSampler): """ + sampler_name = "cpnest" default_kwargs = dict( verbose=3, nthreads=1, diff --git a/bilby/core/sampler/dnest4.py b/bilby/core/sampler/dnest4.py index a767ef89..87717f6f 100644 --- a/bilby/core/sampler/dnest4.py +++ b/bilby/core/sampler/dnest4.py @@ -99,6 +99,7 @@ class DNest4(_TemporaryFileSamplerMixin, NestedSampler): If True, prints information during run """ + sampler_name = "d4nest" default_kwargs = dict( max_num_levels=20, num_steps=500, diff --git a/bilby/core/sampler/dynamic_dynesty.py b/bilby/core/sampler/dynamic_dynesty.py index 294d8fd6..8c7f2966 100644 --- a/bilby/core/sampler/dynamic_dynesty.py +++ b/bilby/core/sampler/dynamic_dynesty.py @@ -14,6 +14,7 @@ class DynamicDynesty(Dynesty): """ external_sampler_name = "dynesty" + sampler_name = "dynamic_dynesty" @property def nlive(self): diff --git a/bilby/core/sampler/dynesty.py b/bilby/core/sampler/dynesty.py index faebfc6b..852fb88c 100644 --- a/bilby/core/sampler/dynesty.py +++ b/bilby/core/sampler/dynesty.py @@ -151,6 +151,7 @@ class Dynesty(NestedSampler): specified. """ + sampler_name = "dynesty" sampling_seed_key = "seed" @property @@ -299,6 +300,32 @@ def _verify_kwargs_against_default_kwargs(self): ) Sampler._verify_kwargs_against_default_kwargs(self) + @classmethod + def get_expected_outputs(cls, outdir=None, label=None): + """Get lists of the expected outputs directories and files. + + These are used by :code:`bilby_pipe` when transferring files via HTCondor. + + Parameters + ---------- + outdir : str + The output directory. + label : str + The label for the run. + + Returns + ------- + list + List of file names. + list + List of directory names. Will always be empty for dynesty. + """ + filenames = [] + for kind in ["resume", "dynesty"]: + filename = os.path.join(outdir, f"{label}_{kind}.pickle") + filenames.append(filename) + return filenames, [] + def _print_func( self, results, diff --git a/bilby/core/sampler/emcee.py b/bilby/core/sampler/emcee.py index 7253a0fa..db88ee5a 100644 --- a/bilby/core/sampler/emcee.py +++ b/bilby/core/sampler/emcee.py @@ -45,6 +45,7 @@ class Emcee(MCMCSampler): """ + sampler_name = "emcee" default_kwargs = dict( nwalkers=500, a=2, diff --git a/bilby/core/sampler/fake_sampler.py b/bilby/core/sampler/fake_sampler.py index 5f375fdb..9795631f 100644 --- a/bilby/core/sampler/fake_sampler.py +++ b/bilby/core/sampler/fake_sampler.py @@ -17,6 +17,8 @@ class FakeSampler(Sampler): A string pointing to the posterior data file to be loaded. """ + sampler_name = "fake_sampler" + default_kwargs = dict( verbose=True, logl_args=None, logl_kwargs=None, print_progress=True ) diff --git a/bilby/core/sampler/kombine.py b/bilby/core/sampler/kombine.py index 1f09387c..bda7c6d4 100644 --- a/bilby/core/sampler/kombine.py +++ b/bilby/core/sampler/kombine.py @@ -39,6 +39,7 @@ class Kombine(Emcee): """ + sampler_name = "kombine" default_kwargs = dict( nwalkers=500, args=[], diff --git a/bilby/core/sampler/nessai.py b/bilby/core/sampler/nessai.py index b6f40f8a..65a650ef 100644 --- a/bilby/core/sampler/nessai.py +++ b/bilby/core/sampler/nessai.py @@ -20,6 +20,7 @@ class Nessai(NestedSampler): Documentation: https://nessai.readthedocs.io/ """ + sampler_name = "nessai" _default_kwargs = None _run_kwargs_list = None sampling_seed_key = "seed" @@ -300,5 +301,30 @@ def write_current_state_and_exit(self, signum=None, frame=None): self._log_interruption(signum=signum) sys.exit(self.exit_code) + @classmethod + def get_expected_outputs(cls, outdir=None, label=None): + """Get lists of the expected outputs directories and files. + + These are used by :code:`bilby_pipe` when transferring files via HTCondor. + + Parameters + ---------- + outdir : str + The output directory. + label : str + The label for the run. + + Returns + ------- + list + List of file names. This will be empty for nessai. + list + List of directory names. + """ + dirs = [os.path.join(outdir, f"{label}_{cls.sampler_name}", "")] + dirs += [os.path.join(dirs[0], d, "") for d in ["proposal", "diagnostics"]] + filenames = [] + return filenames, dirs + def _setup_pool(self): pass diff --git a/bilby/core/sampler/nestle.py b/bilby/core/sampler/nestle.py index ebd95537..75d93bf6 100644 --- a/bilby/core/sampler/nestle.py +++ b/bilby/core/sampler/nestle.py @@ -24,6 +24,7 @@ class Nestle(NestedSampler): """ + sampler_name = "nestle" default_kwargs = dict( verbose=True, method="multi", diff --git a/bilby/core/sampler/polychord.py b/bilby/core/sampler/polychord.py index e43c5d50..9391dd20 100644 --- a/bilby/core/sampler/polychord.py +++ b/bilby/core/sampler/polychord.py @@ -1,3 +1,5 @@ +import os + import numpy as np from .base_sampler import NestedSampler, signal_wrapper @@ -20,6 +22,7 @@ class PyPolyChord(NestedSampler): To see what the keyword arguments are for, see the docstring of PyPolyChordSettings """ + sampler_name = "pypolychord" default_kwargs = dict( use_polychord_defaults=False, nlive=None, @@ -130,6 +133,28 @@ def _read_sample_file(self): physical_parameters = samples[:, -self.ndim :] return log_likelihoods, physical_parameters + @classmethod + def get_expected_outputs(cls, outdir=None, label=None): + """Get lists of the expected outputs directories and files. + + These are used by :code:`bilby_pipe` when transferring files via HTCondor. + + Parameters + ---------- + outdir : str + The output directory. + label : str + Ignored for pypolychord. + + Returns + ------- + list + List of file names. This will always be empty for pypolychord. + list + List of directory names. + """ + return [], [os.path.join(outdir, "chains", "")] + @property def _sample_file_directory(self): return self.outdir + "/chains" diff --git a/bilby/core/sampler/ptemcee.py b/bilby/core/sampler/ptemcee.py index 531fb102..fd927235 100644 --- a/bilby/core/sampler/ptemcee.py +++ b/bilby/core/sampler/ptemcee.py @@ -128,6 +128,7 @@ class Ptemcee(MCMCSampler): """ + sampler_name = "ptemcee" # Arguments used by ptemcee default_kwargs = dict( ntemps=10, @@ -710,6 +711,29 @@ def write_current_state(self, plot=True): except Exception as e: logger.info(f"mean_logl plot failed with exception {e}") + @classmethod + def get_expected_outputs(cls, outdir=None, label=None): + """Get lists of the expected outputs directories and files. + + These are used by :code:`bilby_pipe` when transferring files via HTCondor. + + Parameters + ---------- + outdir : str + The output directory. + label : str + The label for the run. + + Returns + ------- + list + List of file names. + list + List of directory names. Will always be empty for ptemcee. + """ + filenames = [f"{outdir}/{label}_checkpoint_resume.pickle"] + return filenames, [] + def get_minimum_stable_itertion(mean_array, frac, nsteps_min=10): nsteps = mean_array.shape[1] diff --git a/bilby/core/sampler/ptmcmc.py b/bilby/core/sampler/ptmcmc.py index 42279e01..f2a771cb 100644 --- a/bilby/core/sampler/ptmcmc.py +++ b/bilby/core/sampler/ptmcmc.py @@ -41,6 +41,8 @@ class PTMCMCSampler(MCMCSampler): """ + sampler_name = "ptmcmcsampler" + abbreviation = "ptmcmc_temp" default_kwargs = { "p0": None, "Niter": 2 * 10**4 + 1, diff --git a/bilby/core/sampler/pymc.py b/bilby/core/sampler/pymc.py index e72aace4..fd138b98 100644 --- a/bilby/core/sampler/pymc.py +++ b/bilby/core/sampler/pymc.py @@ -52,6 +52,7 @@ class for further help. Under Other Parameters, we list commonly used """ + sampler_name = "pymc" default_kwargs = dict( draws=500, step=None, diff --git a/bilby/core/sampler/pymultinest.py b/bilby/core/sampler/pymultinest.py index 303acb70..0a9bb0aa 100644 --- a/bilby/core/sampler/pymultinest.py +++ b/bilby/core/sampler/pymultinest.py @@ -34,6 +34,8 @@ class Pymultinest(_TemporaryFileSamplerMixin, NestedSampler): """ + sampler_name = "pymultinest" + abbreviation = "pm" default_kwargs = dict( importance_nested_sampling=False, resume=True, diff --git a/bilby/core/sampler/ultranest.py b/bilby/core/sampler/ultranest.py index 542f8624..6aacfa99 100644 --- a/bilby/core/sampler/ultranest.py +++ b/bilby/core/sampler/ultranest.py @@ -38,6 +38,8 @@ class Ultranest(_TemporaryFileSamplerMixin, NestedSampler): stepping behaviour is used. """ + sampler_name = "ultranest" + abbreviation = "ultra" default_kwargs = dict( resume=True, show_status=True, diff --git a/bilby/core/sampler/zeus.py b/bilby/core/sampler/zeus.py index c7ae40da..ad6e7edb 100644 --- a/bilby/core/sampler/zeus.py +++ b/bilby/core/sampler/zeus.py @@ -38,6 +38,7 @@ class Zeus(Emcee): """ + sampler_name = "zeus" default_kwargs = dict( nwalkers=500, args=[], diff --git a/bilby/core/utils/io.py b/bilby/core/utils/io.py index b6e9b79c..57a2cd2d 100644 --- a/bilby/core/utils/io.py +++ b/bilby/core/utils/io.py @@ -154,13 +154,16 @@ def decode_bilby_json(dct): try: cls = getattr(import_module(dct["__module__"]), dct["__name__"]) except AttributeError: - logger.debug( + logger.warning( "Unknown prior class for parameter {}, defaulting to base Prior object".format( dct["kwargs"]["name"] ) ) from ..prior import Prior + for key in list(dct["kwargs"].keys()): + if key not in ["name", "latex_label", "unit", "minimum", "maximum", "boundary"]: + dct["kwargs"].pop(key) cls = Prior obj = cls(**dct["kwargs"]) return obj @@ -264,9 +267,9 @@ def encode_for_hdf5(key, item): if isinstance(item, np.int_): item = int(item) - elif isinstance(item, np.float_): + elif isinstance(item, np.float64): item = float(item) - elif isinstance(item, np.complex_): + elif isinstance(item, np.complex128): item = complex(item) if isinstance(item, np.ndarray): # Numpy's wide unicode strings are not supported by hdf5 diff --git a/bilby/gw/conversion.py b/bilby/gw/conversion.py index 4be5634e..85bdf115 100644 --- a/bilby/gw/conversion.py +++ b/bilby/gw/conversion.py @@ -2261,8 +2261,8 @@ def compute_snrs(sample, likelihood, npool=1): snr_update = new_sample[ii].snrs_as_sample for key, val in snr_update.items(): snr_updates[f"{ifo.name}_{key}"].append(val) - for k, v in snr_updates.items(): - sample[k] = v + for k, v in snr_updates.items(): + sample[k] = v else: logger.debug('Not computing SNRs.') diff --git a/bilby/gw/prior.py b/bilby/gw/prior.py index 81dd2d55..21767411 100644 --- a/bilby/gw/prior.py +++ b/bilby/gw/prior.py @@ -1362,6 +1362,7 @@ def __init__(self, hp_file, names=None, bounds=None, distance=False): else: self.distance = False self.prob = self.hp.read_map(hp_file) + self.prob = self._check_norm(self.prob) super(HealPixMapPriorDist, self).__init__(names=names, bounds=bounds) self.distname = "hpmap" @@ -1436,7 +1437,7 @@ def _rescale(self, samp, **kwargs): self.update_distance(int(round(val))) dist_samples[i] = self.distance_icdf(dist_samp[i]) if self.distance: - sample = np.row_stack([sample[:, 0], sample[:, 1], dist_samples]) + sample = np.vstack([sample[:, 0], sample[:, 1], dist_samples]) return sample.reshape((-1, self.num_vars)) def update_distance(self, pix_idx): @@ -1501,9 +1502,7 @@ def _sample(self, size, **kwargs): sample : array_like sample of ra, and dec (and distance if 3D=True) """ - pixel_choices = np.arange(self.npix) - pixel_probs = self._check_norm(self.prob) - sample_pix = random.rng.choice(pixel_choices, size=size, p=pixel_probs, replace=True) + sample_pix = random.rng.choice(self.npix, size=size, p=self.prob, replace=True) sample = np.empty((size, self.num_vars)) for samp in range(size): theta, ra = self.hp.pix2ang(self.nside, sample_pix[samp]) diff --git a/containers/env-template.yml b/containers/env-template.yml index c2b050c3..647709a2 100644 --- a/containers/env-template.yml +++ b/containers/env-template.yml @@ -69,7 +69,7 @@ dependencies: - nbconvert - twine - glasflow - - myst_parser + - myst-parser - pip: - autodoc - ipykernel diff --git a/docs/citing-bilby.txt b/docs/citing-bilby.txt index 3e196a57..d91e289b 100644 --- a/docs/citing-bilby.txt +++ b/docs/citing-bilby.txt @@ -58,7 +58,7 @@ If you use any of the accelerated likelihoods like `ROQGravitationalWaveTransien - `ROQGravitationalWaveTransient` .. code:: bibtex - @article{roq_paper, + @article{roq_paper_1, author = {Smith, Rory and Field, Scott E. and Blackburn, Kent and Haster, Carl-Johan and P\"urrer, Michael and Raymond, Vivien and Schmidt, Patricia}, title = "{Fast and accurate inference on gravitational waves from precessing compact binaries}", eprint = "1604.08253", @@ -73,6 +73,21 @@ If you use any of the accelerated likelihoods like `ROQGravitationalWaveTransien year = "2016" } + @article{roq_paper_2, + author = "Morisaki, Soichiro and Smith, Rory and Tsukada, Leo and Sachdev, Surabhi and Stevenson, Simon and Talbot, Colm and Zimmerman, Aaron", + title = "{Rapid localization and inference on compact binary coalescences with the Advanced LIGO-Virgo-KAGRA gravitational-wave detector network}", + eprint = "2307.13380", + archivePrefix = "arXiv", + primaryClass = "gr-qc", + doi = "10.1103/PhysRevD.108.123040", + journal = "Phys. Rev. D", + volume = "108", + number = "12", + pages = "123040", + year = "2023" + } + + - `MBGravitationalWaveTransient` .. code:: bibtex @@ -93,8 +108,18 @@ If you use any of the accelerated likelihoods like `ROQGravitationalWaveTransien - `RelativeBinningGravitationalWaveTransient` .. code:: bibtex + + @article{relbin_bilby, + author = "Krishna, Kruthi and Vijaykumar, Aditya and Ganguly, Apratim and Talbot, Colm and Biscoveanu, Sylvia and George, Richard N. and Williams, Natalie and Zimmerman, Aaron", + title = "{Accelerated parameter estimation in Bilby with relative binning}", + eprint = "2312.06009", + archivePrefix = "arXiv", + primaryClass = "gr-qc", + month = "12", + year = "2023" + } - @article{relbin_paper, + @article{relbin_cornish, author = "Cornish, Neil J.", title = "{Fast Fisher Matrices and Lazy Likelihoods}", eprint = "1007.4820", @@ -102,10 +127,64 @@ If you use any of the accelerated likelihoods like `ROQGravitationalWaveTransien primaryClass = "gr-qc", month = "7", year = "2010" - } + } + + @article{relbin_zackay, + author = "Zackay, Barak and Dai, Liang and Venumadhav, Tejaswi", + title = "{Relative Binning and Fast Likelihood Evaluation for Gravitational Wave Parameter Estimation}", + eprint = "1806.08792", + archivePrefix = "arXiv", + primaryClass = "astro-ph.IM", + month = "6", + year = "2018" + } + +If you use the :code:`bilby_mcmc` sampler, please additionally cite the following paper -Please also ensure that you appropriately cite the following: + .. code:: bibtex + + @article{bilby_mcmc_paper, + author = "Ashton, Gregory and Talbot, Colm", + title = "{B\,ilby-MCMC: an MCMC sampler for gravitational-wave inference}", + eprint = "2106.08730", + archivePrefix = "arXiv", + primaryClass = "gr-qc", + doi = "10.1093/mnras/stab2236", + journal = "Mon. Not. Roy. Astron. Soc.", + volume = "507", + number = "2", + pages = "2037--2051", + year = "2021" + } -- The sampler(s) used for your analysis -- Any additional package(s) that you use to generate waveforms e.g. `lalsuite` (https://doi.org/10.7935/GT1W-FZ16) -as well as the original scientific papers for each waveform. +Additionally, :code:`bilby` builds on a number of open-source packages. If you +make use of this functionality in your publications, we recommend you cite them +as requested in their associated documentation. + +**Samplers** +* `cpnest `__ +* `dnest4 `__ +* `dynesty `__ +* `emcee `__ +* `kombine `__ +* `nestle `__ +* `nessai `__ +* `PyMC3 `__ +* `pymultinest `__ +* `pypolychord `__ +* `ptemcee `__ +* `ptmcmcsampler `__ +* `ultranest `__ +* `zeus `_ + + +**Gravitational-wave tools** + +* `gwpy `__ +* `lalsuite `__ +* `astropy `__ + +**Plotting** + +* `corner `__ for generating corner plot +* `matplotlib `__ for general plotting routines diff --git a/docs/plugins.txt b/docs/plugins.txt index 38422e64..a73f0ce4 100644 --- a/docs/plugins.txt +++ b/docs/plugins.txt @@ -61,6 +61,19 @@ here, we encourage you to open a - This could be your sampler +Bilby-native samplers +--------------------- + +Some samplers are implemented directly in :code:`bilby` and these are avertised +under two possible names: + +- :code:`bilby.`: always available, indicates the sampler is implemented in bilby, +- :code:``: only refers to the native bilby implementation if an external plugin does not already provide this sampler. + +This allows for an external plugin to provide a sampler without introducing +namespace conflicts. + + -------------------------------- Information for bilby developers -------------------------------- diff --git a/docs/samplers.txt b/docs/samplers.txt index 69699dad..7b4a190f 100644 --- a/docs/samplers.txt +++ b/docs/samplers.txt @@ -73,6 +73,18 @@ MCMC samplers - zeus :code:`bilby.core.sampler.zeus.Zeus` +-------------------------- +Listing available samplers +-------------------------- + +A list of available samplers can be produced using +:py:func:`bilby.core.sampler.get_implemented_samplers`. +This will list native bilby samplers and any samplers available via a plugin. +If a plugin provides a sampler that is also implemented in bilby, the bilby +implementation will be labeled with the prfix `bilby.` to distinguish it from +the plugin version. See `sampler plugins`_ for more details. + + ------------------- Installing samplers ------------------- diff --git a/setup.py b/setup.py index b929d5bb..353e92ee 100644 --- a/setup.py +++ b/setup.py @@ -84,23 +84,23 @@ def readfile(filename): "bilby_result=cli_bilby.bilby_result:main", ], "bilby.samplers": [ - "bilby_mcmc=bilby.bilby_mcmc.sampler:Bilby_MCMC", - "cpnest=bilby.core.sampler.cpnest:Cpnest", - "dnest4=bilby.core.sampler.dnest4:DNest4", - "dynesty=bilby.core.sampler.dynesty:Dynesty", - "dynamic_dynesty=bilby.core.sampler.dynamic_dynesty:DynamicDynesty", - "emcee=bilby.core.sampler.emcee:Emcee", - "kombine=bilby.core.sampler.kombine:Kombine", - "nessai=bilby.core.sampler.nessai:Nessai", - "nestle=bilby.core.sampler.nestle:Nestle", - "ptemcee=bilby.core.sampler.ptemcee:Ptemcee", - "ptmcmcsampler=bilby.core.sampler.ptmcmc:PTMCMCSampler", - "pymc=bilby.core.sampler.pymc:Pymc", - "pymultinest=bilby.core.sampler.pymultinest:Pymultinest", - "pypolychord=bilby.core.sampler.polychord:PyPolyChord", - "ultranest=bilby.core.sampler.ultranest:Ultranest", - "zeus=bilby.core.sampler.zeus:Zeus", - "fake_sampler=bilby.core.sampler.fake_sampler:FakeSampler", + "bilby.bilby_mcmc=bilby.bilby_mcmc.sampler:Bilby_MCMC", + "bilby.cpnest=bilby.core.sampler.cpnest:Cpnest", + "bilby.dnest4=bilby.core.sampler.dnest4:DNest4", + "bilby.dynesty=bilby.core.sampler.dynesty:Dynesty", + "bilby.dynamic_dynesty=bilby.core.sampler.dynamic_dynesty:DynamicDynesty", + "bilby.emcee=bilby.core.sampler.emcee:Emcee", + "bilby.kombine=bilby.core.sampler.kombine:Kombine", + "bilby.nessai=bilby.core.sampler.nessai:Nessai", + "bilby.nestle=bilby.core.sampler.nestle:Nestle", + "bilby.ptemcee=bilby.core.sampler.ptemcee:Ptemcee", + "bilby.ptmcmcsampler=bilby.core.sampler.ptmcmc:PTMCMCSampler", + "bilby.pymc=bilby.core.sampler.pymc:Pymc", + "bilby.pymultinest=bilby.core.sampler.pymultinest:Pymultinest", + "bilby.pypolychord=bilby.core.sampler.polychord:PyPolyChord", + "bilby.ultranest=bilby.core.sampler.ultranest:Ultranest", + "bilby.zeus=bilby.core.sampler.zeus:Zeus", + "bilby.fake_sampler=bilby.core.sampler.fake_sampler:FakeSampler", ], }, classifiers=[ diff --git a/test/bilby_mcmc/test_sampler.py b/test/bilby_mcmc/test_sampler.py index 746eb1a9..7e636e1a 100644 --- a/test/bilby_mcmc/test_sampler.py +++ b/test/bilby_mcmc/test_sampler.py @@ -85,5 +85,16 @@ def test_default_proposal_cycle(self): self.assertTrue(isinstance(sampler.samples, pd.DataFrame)) +def test_get_expected_outputs(): + label = "par0" + outdir = os.path.join("some", "bilby_pipe", "dir") + filenames, directories = Bilby_MCMC.get_expected_outputs( + outdir=outdir, label=label + ) + assert len(filenames) == 1 + assert len(directories) == 0 + assert os.path.join(outdir, f"{label}_resume.pickle") in filenames + + if __name__ == "__main__": unittest.main() diff --git a/test/check_author_list.py b/test/check_author_list.py index c04932d5..95d5be1c 100644 --- a/test/check_author_list.py +++ b/test/check_author_list.py @@ -3,7 +3,7 @@ import re import subprocess -special_cases = ["plasky", "thomas", "mj-will", "richard", "douglas"] +special_cases = ["plasky", "thomas", "mj-will", "richard", "douglas", "nixnyxnyx"] AUTHORS_list = [] with open("AUTHORS.md", "r") as f: AUTHORS_list = " ".join([line for line in f]).lower() diff --git a/test/core/sampler/base_sampler_test.py b/test/core/sampler/base_sampler_test.py index 1250fa0d..d20ee978 100644 --- a/test/core/sampler/base_sampler_test.py +++ b/test/core/sampler/base_sampler_test.py @@ -148,6 +148,30 @@ def test_bad_value_neg_inf_nan_to_num(self): ) +def test_get_expected_outputs(): + outdir = os.path.join("some", "bilby_pipe", "dir") + label = "par0" + filenames, directories = bilby.core.sampler.Sampler.get_expected_outputs( + outdir=outdir, label=label + ) + assert len(filenames) == 0 + assert len(directories) == 1 + assert directories[0] == os.path.join(outdir, f"sampler_{label}", "") + + +def test_get_expected_outputs_abbreviation(): + outdir = os.path.join("some", "bilby_pipe", "dir") + label = "par0" + bilby.core.sampler.Sampler.abbreviation = "abbr" + filenames, directories = bilby.core.sampler.Sampler.get_expected_outputs( + outdir=outdir, label=label + ) + assert len(filenames) == 0 + assert len(directories) == 1 + assert directories[0] == os.path.join(outdir, f"abbr_{label}", "") + bilby.core.sampler.Sampler.abbreviation = None + + samplers = [ "bilby_mcmc", "dynamic_dynesty", diff --git a/test/core/sampler/dynesty_test.py b/test/core/sampler/dynesty_test.py index 39ac6f23..d33cc2e2 100644 --- a/test/core/sampler/dynesty_test.py +++ b/test/core/sampler/dynesty_test.py @@ -9,6 +9,7 @@ from bilby.core.sampler import dynesty_utils from scipy.stats import gamma, ks_1samp, uniform, powerlaw import shutil +import os @define @@ -101,6 +102,18 @@ def test_run_test_runs(self): self.sampler._run_test() +def test_get_expected_outputs(): + label = "par0" + outdir = os.path.join("some", "bilby_pipe", "dir") + filenames, directories = bilby.core.sampler.dynesty.Dynesty.get_expected_outputs( + outdir=outdir, label=label + ) + assert len(filenames) == 2 + assert len(directories) == 0 + assert os.path.join(outdir, f"{label}_resume.pickle") in filenames + assert os.path.join(outdir, f"{label}_dynesty.pickle") in filenames + + class ProposalsTest(unittest.TestCase): def test_boundaries(self): diff --git a/test/core/sampler/implemented_samplers_test.py b/test/core/sampler/implemented_samplers_test.py new file mode 100644 index 00000000..c3439818 --- /dev/null +++ b/test/core/sampler/implemented_samplers_test.py @@ -0,0 +1,39 @@ +from bilby.core.sampler import IMPLEMENTED_SAMPLERS, ImplementedSamplers +import pytest + + +def test_singleton(): + assert ImplementedSamplers() is IMPLEMENTED_SAMPLERS + + +def test_keys(): + # The fake sampler should never have a plugin, so this should always work + assert "fake_sampler" in IMPLEMENTED_SAMPLERS.keys() + assert "bilby.fake_sampler" not in IMPLEMENTED_SAMPLERS.keys() + + +def test_allowed_keys(): + # The fake sampler should never have a plugin, so this should always work + assert "fake_sampler" in IMPLEMENTED_SAMPLERS.valid_keys() + assert "bilby.fake_sampler" in IMPLEMENTED_SAMPLERS.valid_keys() + + +def test_values(): + # Values and keys should have the same lengths + assert len(list(IMPLEMENTED_SAMPLERS.values())) \ + == len(list(IMPLEMENTED_SAMPLERS.keys())) + assert len(list(IMPLEMENTED_SAMPLERS.values())) \ + == len(list(IMPLEMENTED_SAMPLERS._samplers.values())) + + +def test_items(): + keys, values = list(zip(*IMPLEMENTED_SAMPLERS.items())) + assert len(keys) == len(values) + # Keys and values should be the same as the individual methods + assert list(keys) == list(IMPLEMENTED_SAMPLERS.keys()) + assert list(values) == list(IMPLEMENTED_SAMPLERS.values()) + + +@pytest.mark.parametrize("sampler", ["fake_sampler", "bilby.fake_sampler"]) +def test_in_operator(sampler): + assert sampler in IMPLEMENTED_SAMPLERS diff --git a/test/core/sampler/nessai_test.py b/test/core/sampler/nessai_test.py index cca5d22b..3246c74e 100644 --- a/test/core/sampler/nessai_test.py +++ b/test/core/sampler/nessai_test.py @@ -3,6 +3,7 @@ import bilby import bilby.core.sampler.nessai +import os class TestNessai(unittest.TestCase): @@ -84,5 +85,19 @@ def test_update_from_config_file(self): self.assertDictEqual(expected, self.sampler.kwargs) +def test_get_expected_outputs(): + label = "par0" + outdir = os.path.join("some", "bilby_pipe", "dir") + filenames, directories = bilby.core.sampler.nessai.Nessai.get_expected_outputs( + outdir=outdir, label=label + ) + assert len(filenames) == 0 + assert len(directories) == 3 + base_dir = os.path.join(outdir, f"{label}_nessai", "") + assert base_dir in directories + assert os.path.join(base_dir, "proposal", "") in directories + assert os.path.join(base_dir, "diagnostics", "") in directories + + if __name__ == "__main__": unittest.main() diff --git a/test/core/sampler/ptemcee_test.py b/test/core/sampler/ptemcee_test.py index ec135eee..4708a12b 100644 --- a/test/core/sampler/ptemcee_test.py +++ b/test/core/sampler/ptemcee_test.py @@ -5,6 +5,7 @@ from bilby.core.sampler.ptemcee import Ptemcee from bilby.core.sampler.base_sampler import MCMCSampler import numpy as np +import os class TestPTEmcee(unittest.TestCase): @@ -89,5 +90,16 @@ def test_set_pos0_from_minimize(self): self.assertEqual(old, new) +def test_get_expected_outputs(): + label = "par0" + outdir = os.path.join("some", "bilby_pipe", "dir") + filenames, directories = Ptemcee.get_expected_outputs( + outdir=outdir, label=label + ) + assert len(filenames) == 1 + assert len(directories) == 0 + assert os.path.join(outdir, f"{label}_checkpoint_resume.pickle") in filenames + + if __name__ == "__main__": unittest.main() diff --git a/test/gw/conversion_test.py b/test/gw/conversion_test.py index aef17c82..8ce40e3b 100644 --- a/test/gw/conversion_test.py +++ b/test/gw/conversion_test.py @@ -475,7 +475,7 @@ def _generate(self, func, expected): def test_generate_bbh_parameters_with_likelihood(self): priors = bilby.gw.prior.BBHPriorDict() priors["geocent_time"] = bilby.core.prior.Uniform(0.4, 0.6) - ifos = bilby.gw.detector.InterferometerList(["H1"]) + ifos = bilby.gw.detector.InterferometerList(["H1", "L1"]) ifos.set_strain_data_from_power_spectral_densities(duration=1, sampling_frequency=256) wfg = bilby.gw.waveform_generator.WaveformGenerator( frequency_domain_source_model=bilby.gw.source.lal_binary_black_hole @@ -501,6 +501,8 @@ def test_generate_bbh_parameters_with_likelihood(self): "phase", "H1_optimal_snr", "H1_matched_filter_snr", + "L1_optimal_snr", + "L1_matched_filter_snr", "ra", "dec", ]