From 3f80965306044f7f563d2058deb22dd56cd6c4d1 Mon Sep 17 00:00:00 2001 From: Joe Zuntz Date: Wed, 29 May 2024 09:54:13 +0100 Subject: [PATCH 1/7] fix list sampler ignoring burn/thin --- cosmosis/samplers/list/list_sampler.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/cosmosis/samplers/list/list_sampler.py b/cosmosis/samplers/list/list_sampler.py index c8f736d3..09a3919d 100755 --- a/cosmosis/samplers/list/list_sampler.py +++ b/cosmosis/samplers/list/list_sampler.py @@ -26,7 +26,13 @@ def config(self): self.converged = False self.filename = self.read_ini("filename", str) self.save_name = self.read_ini("save", str, "") - self.burn = self.read_ini("burn", int, 0) + # The burn parameter can be an int or a float + # so we read it as a string and then convert it + burn = self.read_ini("burn", str, "0") + try: + self.burn = int(burn) + except ValueError: + self.burn = float(burn) self.thin = self.read_ini("thin", int, 1) limits = self.read_ini("limits", bool, False) self.chunk_size = self.read_ini("chunk_size", int, 100) @@ -57,6 +63,12 @@ def execute(self): file_options = {"filename":self.filename} column_names, samples, _, _, _ = TextColumnOutput.load_from_options(file_options) samples = samples[0] + if (self.burn != 0) or (self.thin != 1): + if isinstance(self.burn, float): + burn = int(self.burn*len(samples)) + else: + burn = self.burn + samples = samples[burn::self.thin] # find where in the parameter vector of the pipeline # each of the table parameters can be found replaced_params = [] From 9ef01dbe6ccf03b122be23632d05e8695094e527 Mon Sep 17 00:00:00 2001 From: Joe Zuntz Date: Wed, 29 May 2024 09:54:39 +0100 Subject: [PATCH 2/7] fix wrong value being printed for success count --- cosmosis/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cosmosis/main.py b/cosmosis/main.py index 713d10db..f921e60a 100755 --- a/cosmosis/main.py +++ b/cosmosis/main.py @@ -430,7 +430,7 @@ def run_cosmosis(ini, pool=None, pipeline=None, values=None, priors=None, overri logs.overview(f"Successful posterior evaluations = {run_count_ok_total} across all processes") if output: output.final("evaluations", run_count_total) - output.final("successes", run_count_total) + output.final("successes", run_count_ok_total) output.final("complete", "1") From 68c8c52cf50e5a36ab99ab5858f0e5f5de23566d Mon Sep 17 00:00:00 2001 From: Joe Zuntz Date: Wed, 29 May 2024 09:55:03 +0100 Subject: [PATCH 3/7] add name of lib to minuit class var --- cosmosis/samplers/minuit/minuit_sampler.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cosmosis/samplers/minuit/minuit_sampler.py b/cosmosis/samplers/minuit/minuit_sampler.py index 94184421..f9bb8573 100755 --- a/cosmosis/samplers/minuit/minuit_sampler.py +++ b/cosmosis/samplers/minuit/minuit_sampler.py @@ -28,15 +28,16 @@ class MinuitOptionsStruct(ct.Structure): class MinuitSampler(ParallelSampler): needs_output = True needs_parallel_output = False + libminuit_name = libname libminuit = None sampler_outputs = [("prior", float), ("post", float)] def config(self): self.converged = False if MinuitSampler.libminuit is None: - if not os.path.exists(libname): + if not os.path.exists(self.libminuit_name): raise ValueError("The CosmoSIS minuit2 wrapper was not compiled. If you installed CosmoSIS manually you need the library minuit2 to use this sampler. See the wiki for more details.") - MinuitSampler.libminuit = ct.cdll.LoadLibrary(libname) + MinuitSampler.libminuit = ct.cdll.LoadLibrary(self.libminuit_name) self.maxiter = self.read_ini("maxiter", int, 1000) self.save_dir = self.read_ini("save_dir", str, "") self.save_cov = self.read_ini("save_cov", str, "") From d54bff8b70500323e2f0aef791f676ada0973166 Mon Sep 17 00:00:00 2001 From: Joe Zuntz Date: Wed, 29 May 2024 09:55:21 +0100 Subject: [PATCH 4/7] fix get_sampler function --- cosmosis/samplers/sampler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cosmosis/samplers/sampler.py b/cosmosis/samplers/sampler.py index eccbdc4a..752027a4 100644 --- a/cosmosis/samplers/sampler.py +++ b/cosmosis/samplers/sampler.py @@ -154,7 +154,7 @@ def read_resume_info(self): @classmethod def get_sampler(cls, name): try: - cls.registry[name.lower()] + return cls.registry[name.lower()] except KeyError: raise KeyError(f"Unknown sampler {name}") From 094e02aef725a84de03c47673720663ce6b9814e Mon Sep 17 00:00:00 2001 From: Joe Zuntz Date: Wed, 29 May 2024 09:55:45 +0100 Subject: [PATCH 5/7] add more things to import --- cosmosis/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cosmosis/__init__.py b/cosmosis/__init__.py index 2c2ad70d..74b58043 100644 --- a/cosmosis/__init__.py +++ b/cosmosis/__init__.py @@ -9,3 +9,4 @@ from .gaussian_likelihood import GaussianLikelihood, \ SingleValueGaussianLikelihood, \ WindowedGaussianLikelihood +from .output import TextColumnOutput, InMemoryOutput, NullOutput, AstropyOutput, CosmoMCOutput, FitsOutput From 57ef8cce28a71d19d528ae8689c39ecb5b549066 Mon Sep 17 00:00:00 2001 From: Joe Zuntz Date: Wed, 29 May 2024 09:55:53 +0100 Subject: [PATCH 6/7] add test for list sampler --- cosmosis/test/test_samplers.py | 40 +++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/cosmosis/test/test_samplers.py b/cosmosis/test/test_samplers.py index c1c533f2..d0e2e22e 100644 --- a/cosmosis/test/test_samplers.py +++ b/cosmosis/test/test_samplers.py @@ -1,8 +1,4 @@ -from cosmosis.runtime.config import Inifile -from cosmosis.samplers.sampler import Sampler -import cosmosis.samplers.minuit.minuit_sampler -from cosmosis.runtime.pipeline import LikelihoodPipeline -from cosmosis.output.in_memory_output import InMemoryOutput +from cosmosis import Inifile, Sampler, LikelihoodPipeline, InMemoryOutput, TextColumnOutput from cosmosis.postprocessing import postprocessor_for_sampler import tempfile import os @@ -11,7 +7,8 @@ import numpy as np from astropy.table import Table -minuit_compiled = os.path.exists(cosmosis.samplers.minuit.minuit_sampler.libname) + +minuit_compiled = os.path.exists(Sampler.get_sampler("minuit").libminuit_name) def run(name, check_prior, check_extra=True, can_postprocess=True, do_truth=False, no_extra=False, pp_extra=True, pp_2d=True, **options): @@ -175,6 +172,37 @@ def test_star(): def test_test(): run('test', False, can_postprocess=False) +def test_list_sampler(): + # test that the burn and thin parameters work + # make a mock output file with some samples + with tempfile.TemporaryDirectory() as dirname: + + input_chain_filename = os.path.join(dirname, "input_chain.txt") + input_chain = TextColumnOutput(input_chain_filename) + input_chain.add_column('parameters--p1', float) + input_chain.add_column('parameters--p2', float) + nrow = 100 + data = np.random.normal(size=(nrow, 2)) + for i in range(nrow): + input_chain.parameters(data[i, 0], data[i, 1]) + input_chain.close() + + burn = 0.2 + thin = 2 + + data = data[20::thin] + + output = run("list", True, can_postprocess=False, filename=input_chain_filename, burn=burn, thin=thin) + p1 = output['parameters--p1'] + p2 = output['parameters--p2'] + p3 = p1 + p2 + expected_like = -(p1**2 + p2**2)/2. + assert p1.size == 40 + assert np.allclose(p1, data[:, 0]) + assert np.allclose(p2, data[:, 1]) + assert np.allclose(output['PARAMETERS--P3'], p3) + assert np.allclose(output["post"] - output["prior"], expected_like) + @pytest.mark.skipif(sys.version_info < (3,7), reason="pocomc requires python3.6+") def test_poco(): try: From beb5d6073bf8e5c0ac39ef1b78ff013225df65ff Mon Sep 17 00:00:00 2001 From: Joe Zuntz Date: Wed, 29 May 2024 10:09:23 +0100 Subject: [PATCH 7/7] fix test assuming that all parameters were in the prior range --- cosmosis/test/test_samplers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cosmosis/test/test_samplers.py b/cosmosis/test/test_samplers.py index d0e2e22e..9af59270 100644 --- a/cosmosis/test/test_samplers.py +++ b/cosmosis/test/test_samplers.py @@ -182,7 +182,7 @@ def test_list_sampler(): input_chain.add_column('parameters--p1', float) input_chain.add_column('parameters--p2', float) nrow = 100 - data = np.random.normal(size=(nrow, 2)) + data = np.random.normal(size=(nrow, 2)).clip(-2.99, 2.99) for i in range(nrow): input_chain.parameters(data[i, 0], data[i, 1]) input_chain.close()