diff --git a/autofit/mapper/prior_model/representative.py b/autofit/mapper/prior_model/representative.py index 93a39a856..799b18db8 100644 --- a/autofit/mapper/prior_model/representative.py +++ b/autofit/mapper/prior_model/representative.py @@ -1,4 +1,5 @@ from collections import defaultdict +from typing import List def find_groups(path_value_tuples, limit=1): @@ -28,6 +29,44 @@ def find_groups(path_value_tuples, limit=1): return path_value_tuples +def integers_representative_key(integers: List[int]) -> str: + """ + Given a list of integers, return a string that represents them in a concise way. + + e.g. + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -> "1 - 10" + [1, 2, 3, 5, 6, 7, 8, 9, 10] -> "1 - 3, 5 - 10" + [1, 2, 3, 5, 6, 7, 8, 9, 10, 12] -> "1 - 3, 5 - 10, 12" + + Parameters + ---------- + integers + The list of integers to represent + + Returns + ------- + A string representing the integers in a concise way + """ + integers = sorted(integers) + ranges = [] + start = integers[0] + end = integers[0] + + for integer in integers[1:]: + if integer == end + 1: + end = integer + else: + ranges.append((start, end)) + start = integer + end = integer + + ranges.append((start, end)) + + return ", ".join( + f"{start} - {end}" if start != end else str(start) for start, end in ranges + ) + + def _find_groups(path_value_tuples, position): groups = defaultdict(list) paths = [] @@ -43,11 +82,11 @@ def _find_groups(path_value_tuples, position): for (before, after, value), names in groups.items(): try: names = list(map(int, names)) + representative_key = integers_representative_key(names) except ValueError: - pass + representative_key = ( + f"{min(names)} - {max(names)}" if len(set(names)) > 1 else names[0] + ) - representative_key = ( - f"{min(names)} - {max(names)}" if len(set(names)) > 1 else names[0] - ) paths.append(((*before, representative_key, *after), value)) return paths diff --git a/autofit/text/samples_text.py b/autofit/text/samples_text.py index 1b7e3098a..5ba7e84ea 100644 --- a/autofit/text/samples_text.py +++ b/autofit/text/samples_text.py @@ -36,16 +36,18 @@ def summary( sigma_formatter = frm.TextFormatter(indent=indent, line_length=line_length) - paths = [] + prior_result_map = {} - for i, prior_path in enumerate(samples.model.unique_prior_paths): - value_result = frm.value_result_string_from( + for i, (_, prior) in enumerate(samples.model.unique_path_prior_tuples): + prior_result_map[prior] = frm.value_result_string_from( parameter_name=parameter_names[i], value=values[i], values_at_sigma=values_at_sigma[i], ) - paths.append((prior_path, value_result)) + paths = [] + for path, prior in samples.model.path_priors_tuples: + paths.append((path, prior_result_map[prior])) for path, value in find_groups(paths): sigma_formatter.add(path, value) diff --git a/autofit/text/text_util.py b/autofit/text/text_util.py index bb7e815a0..ea13e187a 100644 --- a/autofit/text/text_util.py +++ b/autofit/text/text_util.py @@ -58,11 +58,13 @@ def result_info_from(samples) -> str: paths = [] - for prior_path, value in zip( - samples.model.unique_prior_paths, + model = samples.model + for (_, prior), value in zip( + model.unique_path_prior_tuples, max_log_likelihood_sample, ): - paths.append((prior_path, value)) + for path in model.all_paths_for_prior(prior): + paths.append((path, value)) for path, value in find_groups(paths): formatter.add(path, format_str().format(value)) diff --git a/test_autofit/mapper/info/test_representation.py b/test_autofit/mapper/info/test_representation.py index b455dbabf..8a3028011 100644 --- a/test_autofit/mapper/info/test_representation.py +++ b/test_autofit/mapper/info/test_representation.py @@ -36,10 +36,10 @@ def test_exception(): ((2, 1), 4), ] groups = find_groups(info_paths) - assert groups == [(("0 - 2", 0), 1), ((0, 1), 2), ((1, 1), 3), ((2, 1), 4)] + assert groups == [(("0 - 2", 0), 1), (("0", 1), 2), (("1", 1), 3), (("2", 1), 4)] def test_prefix(): info_paths = [((0, i, 1), 2) for i in range(3)] groups = find_groups(info_paths) - assert groups == [((0, "0 - 2", 1), 2)] + assert groups == [(("0", "0 - 2", 1), 2)] diff --git a/test_autofit/text/test_concise.py b/test_autofit/text/test_concise.py index 639d1d706..d6e8adf07 100644 --- a/test_autofit/text/test_concise.py +++ b/test_autofit/text/test_concise.py @@ -3,6 +3,7 @@ import autofit as af import pytest +from autofit.mapper.prior_model.representative import integers_representative_key from autofit.text.text_util import result_info_from @@ -73,7 +74,7 @@ def test_model_results(samples): Maximum Log Likelihood Model: -19 +0 - 19 centre 1.000 normalization 2.000 sigma 3.000 @@ -85,7 +86,7 @@ def test_model_results(samples): Summary (1.0 sigma limits): -19 +0 - 19 centre 1.00 (1.00, 1.00) normalization 2.00 (2.00, 2.00) sigma 3.00 (3.00, 3.00) @@ -94,3 +95,21 @@ def test_model_results(samples): """ ) + + +def test_non_consecutive(collection): + collection[10].centre = af.UniformPrior(0.0, 1.0) + print(collection.info) + + +@pytest.mark.parametrize( + "integers, expected", + [ + (list(range(1, 11)), "1 - 10"), + ([1], "1"), + ([1, 10], "1, 10"), + ([1, 2, 3, 8, 9, 10], "1 - 3, 8 - 10"), + ], +) +def test_integers_representative_key(integers, expected): + assert integers_representative_key(integers) == expected