From 24423b9d5cd586361654a80b8ef527fa8928ad89 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 2 Apr 2025 11:31:32 +0100 Subject: [PATCH 01/29] dictionaries from computed columns --- autofit/aggregator/summary/aggregate_csv.py | 22 +++++++++++++++++-- .../summary_files/test_aggregate_csv.py | 21 ++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/autofit/aggregator/summary/aggregate_csv.py b/autofit/aggregator/summary/aggregate_csv.py index 72c1750cc..363a944ad 100644 --- a/autofit/aggregator/summary/aggregate_csv.py +++ b/autofit/aggregator/summary/aggregate_csv.py @@ -176,10 +176,22 @@ def dict(self) -> dict: """ row = {"id": self.result.id} for column in self._columns: - row[column.name] = column.value(self) + value = column.value(self) + if isinstance(value, dict): + for key, value in value.items(): + row[f"{column.name}_{key}"] = value + else: + row[column.name] = column.value(self) return row + @property + def column_names(self): + """ + The names of the columns. + """ + return list(self.dict().keys()) + class AggregateCSV: def __init__(self, aggregator: Aggregator): @@ -274,7 +286,13 @@ def fieldnames(self) -> List[str]: """ The fieldnames for the CSV file. """ - return ["id"] + [column.name for column in self._columns] + for i, result in enumerate(self._aggregator): + row = Row( + result, + self._columns, + i, + ) + return row.column_names def save(self, path: Union[str, Path]): """ diff --git a/test_autofit/aggregator/summary_files/test_aggregate_csv.py b/test_autofit/aggregator/summary_files/test_aggregate_csv.py index 0a64170a2..3b94eca12 100644 --- a/test_autofit/aggregator/summary_files/test_aggregate_csv.py +++ b/test_autofit/aggregator/summary_files/test_aggregate_csv.py @@ -133,3 +133,24 @@ def compute(samples): dicts = load_output() assert dicts[0]["computed"] == "1" + + +def test_dict_computed_column( + output_path, + summary, + load_output, +): + def compute(samples): + return {"a": 1, "b": 2} + + summary.add_computed_column( + "computed", + compute, + ) + summary.save(output_path) + + dicts = load_output() + + first = dicts[0] + assert first["computed_a"] == "1" + assert first["computed_b"] == "2" From ec7fb3a8057208d8207bed6e2f9fa34e616277aa Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 2 Apr 2025 12:25:58 +0100 Subject: [PATCH 02/29] add errors and values to example sample summary files --- .../fit_1/files/samples_summary.json | 107 +++++++++++++++++- .../fit_2/files/samples_summary.json | 105 +++++++++++++++++ 2 files changed, 211 insertions(+), 1 deletion(-) diff --git a/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/samples_summary.json b/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/samples_summary.json index 163ab48bc..534df4bc5 100644 --- a/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/samples_summary.json +++ b/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/samples_summary.json @@ -33,6 +33,111 @@ } } } - } + }, + "errors_at_sigma_1": { + "type": "list", + "values": [ + { + "type": "tuple", + "values": [ + 0.8219585320794973, + 0.8807834487242916 + ] + }, + { + "type": "tuple", + "values": [ + 0.4098203614718814, + 0.49773247178232705 + ] + }, + { + "type": "tuple", + "values": [ + 0.9465636903061116, + 0.8021642641500877 + ] + } + ] + }, + "values_at_sigma_3": { + "type": "list", + "values": [ + { + "type": "tuple", + "values": [ + 1.6742483855526449, + 5.93749816282317 + ] + }, + { + "type": "tuple", + "values": [ + -0.21891974607628695, + 2.6115900726705954 + ] + }, + { + "type": "tuple", + "values": [ + -2.1913196826905836, + 1.8153566490823205 + ] + } + ] + }, + "log_evidence": -4.214938026111044, + "errors_at_sigma_3": { + "type": "list", + "values": [ + { + "type": "tuple", + "values": [ + 2.579654153630685, + 1.6835956236398397 + ] + }, + { + "type": "tuple", + "values": [ + 1.2322215615775107, + 1.5982882571693717 + ] + }, + { + "type": "tuple", + "values": [ + 2.165073661630271, + 1.8416026701426333 + ] + } + ] + }, + "values_at_sigma_1": { + "type": "list", + "values": [ + { + "type": "tuple", + "values": [ + 3.4319440071038327, + 5.134685987907622 + ] + }, + { + "type": "tuple", + "values": [ + 0.6034814540293423, + 1.5110342872835507 + ] + }, + { + "type": "tuple", + "values": [ + -0.9728097113664245, + 0.7759182430897749 + ] + } + ] + } } } \ No newline at end of file diff --git a/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/samples_summary.json b/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/samples_summary.json index 32b1652ea..1e619e7c6 100644 --- a/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/samples_summary.json +++ b/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/samples_summary.json @@ -33,6 +33,111 @@ } } } + }, + "errors_at_sigma_1": { + "type": "list", + "values": [ + { + "type": "tuple", + "values": [ + 0.8219585320794973, + 0.8807834487242916 + ] + }, + { + "type": "tuple", + "values": [ + 0.4098203614718814, + 0.49773247178232705 + ] + }, + { + "type": "tuple", + "values": [ + 0.9465636903061116, + 0.8021642641500877 + ] + } + ] + }, + "values_at_sigma_3": { + "type": "list", + "values": [ + { + "type": "tuple", + "values": [ + 1.6742483855526449, + 5.93749816282317 + ] + }, + { + "type": "tuple", + "values": [ + -0.21891974607628695, + 2.6115900726705954 + ] + }, + { + "type": "tuple", + "values": [ + -2.1913196826905836, + 1.8153566490823205 + ] + } + ] + }, + "log_evidence": -4.214938026111044, + "errors_at_sigma_3": { + "type": "list", + "values": [ + { + "type": "tuple", + "values": [ + 2.579654153630685, + 1.6835956236398397 + ] + }, + { + "type": "tuple", + "values": [ + 1.2322215615775107, + 1.5982882571693717 + ] + }, + { + "type": "tuple", + "values": [ + 2.165073661630271, + 1.8416026701426333 + ] + } + ] + }, + "values_at_sigma_1": { + "type": "list", + "values": [ + { + "type": "tuple", + "values": [ + 3.4319440071038327, + 5.134685987907622 + ] + }, + { + "type": "tuple", + "values": [ + 0.6034814540293423, + 1.5110342872835507 + ] + }, + { + "type": "tuple", + "values": [ + -0.9728097113664245, + 0.7759182430897749 + ] + } + ] } } } \ No newline at end of file From 70710b1358d38badc0e58fbbbcde5fe857bb7d13 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 2 Apr 2025 12:29:43 +0100 Subject: [PATCH 03/29] refactor into package --- autofit/aggregator/summary/aggregate_csv.py | 323 ------------------ .../summary/aggregate_csv/__init__.py | 144 ++++++++ .../summary/aggregate_csv/column.py | 103 ++++++ .../aggregator/summary/aggregate_csv/row.py | 85 +++++ 4 files changed, 332 insertions(+), 323 deletions(-) delete mode 100644 autofit/aggregator/summary/aggregate_csv.py create mode 100644 autofit/aggregator/summary/aggregate_csv/__init__.py create mode 100644 autofit/aggregator/summary/aggregate_csv/column.py create mode 100644 autofit/aggregator/summary/aggregate_csv/row.py diff --git a/autofit/aggregator/summary/aggregate_csv.py b/autofit/aggregator/summary/aggregate_csv.py deleted file mode 100644 index 363a944ad..000000000 --- a/autofit/aggregator/summary/aggregate_csv.py +++ /dev/null @@ -1,323 +0,0 @@ -from abc import ABC, abstractmethod -from typing import Optional, Callable, List, Union, Tuple - -from pathlib import Path - -from autofit.aggregator.aggregator import Aggregator -from autofit.aggregator.search_output import SearchOutput - -import csv - - -class AbstractColumn(ABC): - def __init__(self, name: str): - """ - A column in the summary table. - - Parameters - ---------- - name - An optional name for the column - """ - self.name = name - - @abstractmethod - def value(self, row: "Row"): - pass - - -class Column(AbstractColumn): - def __init__( - self, - argument: str, - name: Optional[str] = None, - use_max_log_likelihood: Optional[bool] = False, - ): - """ - A column in the summary table. - - Parameters - ---------- - argument - The argument as it appears in the median_pdf_sample arguments - name - An optional name for the column - """ - super().__init__( - name - or argument.replace( - ".", - "_", - ) - ) - self.argument = argument - self.use_max_log_likelihood = use_max_log_likelihood - - def value(self, row: "Row"): - if self.use_max_log_likelihood: - kwargs = row.max_likelihood_kwargs - else: - kwargs = row.median_pdf_sample_kwargs - - return kwargs[self.path] - - @property - def path(self) -> tuple: - """ - The path of an argument in the median_pdf_sample arguments. - """ - return tuple(self.argument.split(".")) - - -class ComputedColumn(AbstractColumn): - def __init__(self, name: str, compute: Callable): - """ - A column in the summary table that is computed from other columns. - - Parameters - ---------- - name - The name of the column - compute - A function that takes the median_pdf_sample arguments and returns the computed value - """ - super().__init__(name) - self.compute = compute - - def value(self, row: "Row"): - try: - return self.compute(row.result.samples) - except AttributeError as e: - raise AssertionError( - "Cannot compute additional fields if no samples.json present" - ) from e - - -class LabelColumn(AbstractColumn): - def __init__(self, name: str, values: list): - """ - A column in the summary table that is a label. - - Parameters - ---------- - name - The name of the column - """ - super().__init__(name) - self.values = values - - def value(self, row: "Row"): - return self.values[row.number] - - -class Row: - def __init__( - self, - result: SearchOutput, - columns: list, - number: int, - ): - """ - A row in the summary table corresponding to one search. - - Parameters - ---------- - result - The search output from the aggregator - columns - The columns to include in the summary. These are taken from samples_summary or latent_summary - """ - self.result = result - self._columns = columns - self.number = number - - def _all_paths(self, path: Tuple[str, ...]): - model = self.result.model - return model.all_paths_for_prior(model.object_for_path(path)) - - def _add_paths(self, kwargs): - return { - path: value - for key, value in kwargs.items() - for path in self._all_paths(key) - } - - @property - def median_pdf_sample_kwargs(self) -> dict: - """ - The median_pdf_sample arguments for the search from the samples_summary and latent_summary. - """ - samples_summary = self.result.value("samples_summary") - kwargs = self._add_paths(samples_summary.median_pdf_sample.kwargs) - - latent_summary = self.result.value("latent.latent_summary") - if latent_summary is not None: - kwargs.update(latent_summary.median_pdf_sample.kwargs) - - return kwargs - - @property - def max_likelihood_kwargs(self): - """ - The median_pdf_sample arguments for the search from the samples_summary and latent_summary. - """ - samples_summary = self.result.value("samples_summary") - kwargs = self._add_paths(samples_summary.median_pdf_sample.kwargs) - - latent_summary = self.result.value("latent.latent_summary") - if latent_summary is not None: - kwargs.update(latent_summary.max_log_likelihood_sample.kwargs) - - return kwargs - - def dict(self) -> dict: - """ - The row as a dictionary including an id and one entry for each column. - """ - row = {"id": self.result.id} - for column in self._columns: - value = column.value(self) - if isinstance(value, dict): - for key, value in value.items(): - row[f"{column.name}_{key}"] = value - else: - row[column.name] = column.value(self) - - return row - - @property - def column_names(self): - """ - The names of the columns. - """ - return list(self.dict().keys()) - - -class AggregateCSV: - def __init__(self, aggregator: Aggregator): - """ - Summarise results from the aggregator as a CSV. - - Parameters - ---------- - aggregator - """ - if len(aggregator) == 0: - raise ValueError("The aggregator is empty.") - - self._aggregator = aggregator - self._columns = [] - - def add_column( - self, - argument: str, - name: Optional[str] = None, - use_max_log_likelihood: Optional[bool] = False, - ): - """ - Add a column to the summary table. - - This will be taken from the samples_summary or latent_summary. - - Parameters - ---------- - argument - The argument as it appears in the median_pdf_sample arguments - e.g. "galaxies.lens.bulge.centre.centre_0" - name - An optional name for the column. If not provided, the argument will be used. - use_max_log_likelihood - If True, the maximum likelihood value will be used instead of the median PDF value. - """ - self._columns.append( - Column( - argument, - name=name, - use_max_log_likelihood=use_max_log_likelihood, - ) - ) - - def add_computed_column( - self, - name: str, - compute: Callable, - ): - """ - Add a column to the summary table that is computed from other columns. - - Parameters - ---------- - name - The name of the column - compute - A function that takes the median_pdf_sample arguments and returns the computed value - """ - self._columns.append( - ComputedColumn( - name, - compute, - ) - ) - - def add_label_column( - self, - name: str, - values: list, - ): - """ - Add a column to the summary table that is a label. - - Parameters - ---------- - name - The name of the column - values - The values of the column - """ - self._columns.append( - LabelColumn( - name, - values, - ) - ) - - @property - def fieldnames(self) -> List[str]: - """ - The fieldnames for the CSV file. - """ - for i, result in enumerate(self._aggregator): - row = Row( - result, - self._columns, - i, - ) - return row.column_names - - def save(self, path: Union[str, Path]): - """ - Save the summary table to a CSV file. - - Parameters - ---------- - path - The path to save the file to - """ - - folder_path = path.parent if path.suffix else path - folder_path.mkdir(parents=True, exist_ok=True) - - with open(path, "w") as f: - writer = csv.DictWriter( - f, - fieldnames=self.fieldnames, - ) - writer.writeheader() - for i, result in enumerate(self._aggregator): - row = Row( - result, - self._columns, - i, - ) - - writer.writerow(row.dict()) diff --git a/autofit/aggregator/summary/aggregate_csv/__init__.py b/autofit/aggregator/summary/aggregate_csv/__init__.py new file mode 100644 index 000000000..e07f6bdd3 --- /dev/null +++ b/autofit/aggregator/summary/aggregate_csv/__init__.py @@ -0,0 +1,144 @@ +from typing import Optional, Callable, List, Union + +from pathlib import Path + +from autofit.aggregator.aggregator import Aggregator + +import csv + +from autofit.aggregator.summary.aggregate_csv.column import ( + LabelColumn, + Column, + ComputedColumn, +) +from autofit.aggregator.summary.aggregate_csv.row import Row + + +class AggregateCSV: + def __init__(self, aggregator: Aggregator): + """ + Summarise results from the aggregator as a CSV. + + Parameters + ---------- + aggregator + """ + if len(aggregator) == 0: + raise ValueError("The aggregator is empty.") + + self._aggregator = aggregator + self._columns = [] + + def add_column( + self, + argument: str, + name: Optional[str] = None, + use_max_log_likelihood: Optional[bool] = False, + ): + """ + Add a column to the summary table. + + This will be taken from the samples_summary or latent_summary. + + Parameters + ---------- + argument + The argument as it appears in the median_pdf_sample arguments + e.g. "galaxies.lens.bulge.centre.centre_0" + name + An optional name for the column. If not provided, the argument will be used. + use_max_log_likelihood + If True, the maximum likelihood value will be used instead of the median PDF value. + """ + self._columns.append( + Column( + argument, + name=name, + use_max_log_likelihood=use_max_log_likelihood, + ) + ) + + def add_computed_column( + self, + name: str, + compute: Callable, + ): + """ + Add a column to the summary table that is computed from other columns. + + Parameters + ---------- + name + The name of the column + compute + A function that takes the median_pdf_sample arguments and returns the computed value + """ + self._columns.append( + ComputedColumn( + name, + compute, + ) + ) + + def add_label_column( + self, + name: str, + values: list, + ): + """ + Add a column to the summary table that is a label. + + Parameters + ---------- + name + The name of the column + values + The values of the column + """ + self._columns.append( + LabelColumn( + name, + values, + ) + ) + + @property + def fieldnames(self) -> List[str]: + """ + The fieldnames for the CSV file. + """ + for i, result in enumerate(self._aggregator): + row = Row( + result, + self._columns, + i, + ) + return row.column_names + + def save(self, path: Union[str, Path]): + """ + Save the summary table to a CSV file. + + Parameters + ---------- + path + The path to save the file to + """ + + folder_path = path.parent if path.suffix else path + folder_path.mkdir(parents=True, exist_ok=True) + + with open(path, "w") as f: + writer = csv.DictWriter( + f, + fieldnames=self.fieldnames, + ) + writer.writeheader() + for i, result in enumerate(self._aggregator): + row = Row( + result, + self._columns, + i, + ) + + writer.writerow(row.dict()) diff --git a/autofit/aggregator/summary/aggregate_csv/column.py b/autofit/aggregator/summary/aggregate_csv/column.py new file mode 100644 index 000000000..757157bed --- /dev/null +++ b/autofit/aggregator/summary/aggregate_csv/column.py @@ -0,0 +1,103 @@ +from abc import ABC, abstractmethod +from typing import Optional, Callable + + +class AbstractColumn(ABC): + def __init__(self, name: str): + """ + A column in the summary table. + + Parameters + ---------- + name + An optional name for the column + """ + self.name = name + + @abstractmethod + def value(self, row: "Row"): + pass + + +class Column(AbstractColumn): + def __init__( + self, + argument: str, + name: Optional[str] = None, + use_max_log_likelihood: Optional[bool] = False, + ): + """ + A column in the summary table. + + Parameters + ---------- + argument + The argument as it appears in the median_pdf_sample arguments + name + An optional name for the column + """ + super().__init__( + name + or argument.replace( + ".", + "_", + ) + ) + self.argument = argument + self.use_max_log_likelihood = use_max_log_likelihood + + def value(self, row: "Row"): + if self.use_max_log_likelihood: + kwargs = row.max_likelihood_kwargs + else: + kwargs = row.median_pdf_sample_kwargs + + return kwargs[self.path] + + @property + def path(self) -> tuple: + """ + The path of an argument in the median_pdf_sample arguments. + """ + return tuple(self.argument.split(".")) + + +class ComputedColumn(AbstractColumn): + def __init__(self, name: str, compute: Callable): + """ + A column in the summary table that is computed from other columns. + + Parameters + ---------- + name + The name of the column + compute + A function that takes the median_pdf_sample arguments and returns the computed value + """ + super().__init__(name) + self.compute = compute + + def value(self, row: "Row"): + try: + return self.compute(row.result.samples) + except AttributeError as e: + raise AssertionError( + "Cannot compute additional fields if no samples.json present" + ) from e + + +class LabelColumn(AbstractColumn): + def __init__(self, name: str, values: list): + """ + A column in the summary table that is a label. + + Parameters + ---------- + name + The name of the column + """ + super().__init__(name) + self.values = values + + def value(self, row: "Row"): + return self.values[row.number] diff --git a/autofit/aggregator/summary/aggregate_csv/row.py b/autofit/aggregator/summary/aggregate_csv/row.py new file mode 100644 index 000000000..3ac49ada6 --- /dev/null +++ b/autofit/aggregator/summary/aggregate_csv/row.py @@ -0,0 +1,85 @@ +from typing import Tuple +from autofit.aggregator.search_output import SearchOutput + + +class Row: + def __init__( + self, + result: SearchOutput, + columns: list, + number: int, + ): + """ + A row in the summary table corresponding to one search. + + Parameters + ---------- + result + The search output from the aggregator + columns + The columns to include in the summary. These are taken from samples_summary or latent_summary + """ + self.result = result + self._columns = columns + self.number = number + + def _all_paths(self, path: Tuple[str, ...]): + model = self.result.model + return model.all_paths_for_prior(model.object_for_path(path)) + + def _add_paths(self, kwargs): + return { + path: value + for key, value in kwargs.items() + for path in self._all_paths(key) + } + + @property + def median_pdf_sample_kwargs(self) -> dict: + """ + The median_pdf_sample arguments for the search from the samples_summary and latent_summary. + """ + samples_summary = self.result.value("samples_summary") + kwargs = self._add_paths(samples_summary.median_pdf_sample.kwargs) + + latent_summary = self.result.value("latent.latent_summary") + if latent_summary is not None: + kwargs.update(latent_summary.median_pdf_sample.kwargs) + + return kwargs + + @property + def max_likelihood_kwargs(self): + """ + The median_pdf_sample arguments for the search from the samples_summary and latent_summary. + """ + samples_summary = self.result.value("samples_summary") + kwargs = self._add_paths(samples_summary.median_pdf_sample.kwargs) + + latent_summary = self.result.value("latent.latent_summary") + if latent_summary is not None: + kwargs.update(latent_summary.max_log_likelihood_sample.kwargs) + + return kwargs + + def dict(self) -> dict: + """ + The row as a dictionary including an id and one entry for each column. + """ + row = {"id": self.result.id} + for column in self._columns: + value = column.value(self) + if isinstance(value, dict): + for key, value in value.items(): + row[f"{column.name}_{key}"] = value + else: + row[column.name] = column.value(self) + + return row + + @property + def column_names(self): + """ + The names of the columns. + """ + return list(self.dict().keys()) From 655e46d4a76207d8fbe8e319f2e8126f2799350d Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 2 Apr 2025 12:50:14 +0100 Subject: [PATCH 04/29] fix sample summary examples --- .../fit_1/files/samples_summary.json | 172 ++++++++---------- .../fit_2/files/samples_summary.json | 28 --- 2 files changed, 72 insertions(+), 128 deletions(-) diff --git a/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/samples_summary.json b/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/samples_summary.json index 534df4bc5..1a7697d7e 100644 --- a/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/samples_summary.json +++ b/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/samples_summary.json @@ -35,109 +35,81 @@ } }, "errors_at_sigma_1": { - "type": "list", - "values": [ - { - "type": "tuple", - "values": [ - 0.8219585320794973, - 0.8807834487242916 - ] - }, - { - "type": "tuple", - "values": [ - 0.4098203614718814, - 0.49773247178232705 - ] - }, - { - "type": "tuple", - "values": [ - 0.9465636903061116, - 0.8021642641500877 - ] - } - ] + "type": "list", + "values": [ + { + "type": "tuple", + "values": [ + 0.8219585320794973, + 0.8807834487242916 + ] }, - "values_at_sigma_3": { - "type": "list", - "values": [ - { - "type": "tuple", - "values": [ - 1.6742483855526449, - 5.93749816282317 - ] - }, - { - "type": "tuple", - "values": [ - -0.21891974607628695, - 2.6115900726705954 - ] - }, - { - "type": "tuple", - "values": [ - -2.1913196826905836, - 1.8153566490823205 - ] - } - ] + { + "type": "tuple", + "values": [ + 0.4098203614718814, + 0.49773247178232705 + ] + } + ] + }, + "values_at_sigma_3": { + "type": "list", + "values": [ + { + "type": "tuple", + "values": [ + 1.6742483855526449, + 5.93749816282317 + ] }, - "log_evidence": -4.214938026111044, - "errors_at_sigma_3": { - "type": "list", - "values": [ - { - "type": "tuple", - "values": [ - 2.579654153630685, - 1.6835956236398397 - ] - }, - { - "type": "tuple", - "values": [ - 1.2322215615775107, - 1.5982882571693717 - ] - }, - { - "type": "tuple", - "values": [ - 2.165073661630271, - 1.8416026701426333 - ] - } - ] + { + "type": "tuple", + "values": [ + -0.21891974607628695, + 2.6115900726705954 + ] + } + ] + }, + "log_evidence": -4.214938026111044, + "errors_at_sigma_3": { + "type": "list", + "values": [ + { + "type": "tuple", + "values": [ + 2.579654153630685, + 1.6835956236398397 + ] + }, + { + "type": "tuple", + "values": [ + 1.2322215615775107, + 1.5982882571693717 + ] + } + ] + }, + "values_at_sigma_1": { + "type": "list", + "values": [ + { + "type": "tuple", + "values": [ + 3.4319440071038327, + 5.134685987907622 + ] }, - "values_at_sigma_1": { - "type": "list", - "values": [ - { - "type": "tuple", - "values": [ - 3.4319440071038327, - 5.134685987907622 - ] - }, - { - "type": "tuple", - "values": [ - 0.6034814540293423, - 1.5110342872835507 - ] - }, - { - "type": "tuple", - "values": [ - -0.9728097113664245, - 0.7759182430897749 - ] - } - ] + { + "type": "tuple", + "values": [ + 0.6034814540293423, + 1.5110342872835507 + ] } + ] + } } } \ No newline at end of file diff --git a/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/samples_summary.json b/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/samples_summary.json index 1e619e7c6..9fe621459 100644 --- a/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/samples_summary.json +++ b/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/samples_summary.json @@ -50,13 +50,6 @@ 0.4098203614718814, 0.49773247178232705 ] - }, - { - "type": "tuple", - "values": [ - 0.9465636903061116, - 0.8021642641500877 - ] } ] }, @@ -76,13 +69,6 @@ -0.21891974607628695, 2.6115900726705954 ] - }, - { - "type": "tuple", - "values": [ - -2.1913196826905836, - 1.8153566490823205 - ] } ] }, @@ -103,13 +89,6 @@ 1.2322215615775107, 1.5982882571693717 ] - }, - { - "type": "tuple", - "values": [ - 2.165073661630271, - 1.8416026701426333 - ] } ] }, @@ -129,13 +108,6 @@ 0.6034814540293423, 1.5110342872835507 ] - }, - { - "type": "tuple", - "values": [ - -0.9728097113664245, - 0.7759182430897749 - ] } ] } From 1601fb5a886177a31cc8471003987ab6329854e3 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 2 Apr 2025 12:54:29 +0100 Subject: [PATCH 05/29] property to get errors_at_sigma_1_kwargs --- autofit/aggregator/summary/aggregate_csv/row.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/autofit/aggregator/summary/aggregate_csv/row.py b/autofit/aggregator/summary/aggregate_csv/row.py index 3ac49ada6..f13776fdf 100644 --- a/autofit/aggregator/summary/aggregate_csv/row.py +++ b/autofit/aggregator/summary/aggregate_csv/row.py @@ -1,3 +1,4 @@ +from functools import cached_property from typing import Tuple from autofit.aggregator.search_output import SearchOutput @@ -62,6 +63,17 @@ def max_likelihood_kwargs(self): return kwargs + @cached_property + def model_paths(self): + return self.result.model.all_paths + + def _dict_for_list(self, list_): + return {key: value for key, value in zip(self.model_paths, list_)} + + @cached_property + def errors_at_sigma_1_kwargs(self): + return self._dict_for_list(self.result.samples_summary.errors_at_sigma_1) + def dict(self) -> dict: """ The row as a dictionary including an id and one entry for each column. From 6263b3314feccf89c2358162d4d62675460dbd91 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 2 Apr 2025 14:37:36 +0100 Subject: [PATCH 06/29] simultaneous column creation --- autofit/aggregator/summary/aggregate_csv/column.py | 8 ++++---- autofit/aggregator/summary/aggregate_csv/row.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/autofit/aggregator/summary/aggregate_csv/column.py b/autofit/aggregator/summary/aggregate_csv/column.py index 757157bed..2b1c9b66e 100644 --- a/autofit/aggregator/summary/aggregate_csv/column.py +++ b/autofit/aggregator/summary/aggregate_csv/column.py @@ -47,12 +47,12 @@ def __init__( self.use_max_log_likelihood = use_max_log_likelihood def value(self, row: "Row"): + result = {"": row.median_pdf_sample_kwargs[self.path]} + if self.use_max_log_likelihood: - kwargs = row.max_likelihood_kwargs - else: - kwargs = row.median_pdf_sample_kwargs + result["max_lh"] = row.max_likelihood_kwargs - return kwargs[self.path] + return result @property def path(self) -> tuple: diff --git a/autofit/aggregator/summary/aggregate_csv/row.py b/autofit/aggregator/summary/aggregate_csv/row.py index f13776fdf..5e3bab952 100644 --- a/autofit/aggregator/summary/aggregate_csv/row.py +++ b/autofit/aggregator/summary/aggregate_csv/row.py @@ -83,7 +83,7 @@ def dict(self) -> dict: value = column.value(self) if isinstance(value, dict): for key, value in value.items(): - row[f"{column.name}_{key}"] = value + row[f"{column.name}_{key}" if key else column.name] = value else: row[column.name] = column.value(self) From 954ae223d028a50cb0e4791c29e9c508579d6f97 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 2 Apr 2025 14:38:00 +0100 Subject: [PATCH 07/29] fix test --- test_autofit/aggregator/summary_files/test_aggregate_csv.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_autofit/aggregator/summary_files/test_aggregate_csv.py b/test_autofit/aggregator/summary_files/test_aggregate_csv.py index 3b94eca12..78ed25353 100644 --- a/test_autofit/aggregator/summary_files/test_aggregate_csv.py +++ b/test_autofit/aggregator/summary_files/test_aggregate_csv.py @@ -79,8 +79,8 @@ def test_use_max_log_likelihood( dicts = load_output() - assert dicts[0]["galaxies_lens_bulge_centre_centre_0"] == "-1.0" or "-5.0" - assert dicts[1]["galaxies_lens_bulge_centre_centre_0"] == "-5.0" or "-1.0" + assert dicts[0]["galaxies_lens_bulge_centre_centre_0_max_lh"] == "-1.0" or "-5.0" + assert dicts[1]["galaxies_lens_bulge_centre_centre_0_max_lh"] == "-5.0" or "-1.0" def test_add_named_column( From aeeeba646def64b432864f2f3878b5ebb3e75d45 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 2 Apr 2025 14:47:55 +0100 Subject: [PATCH 08/29] refactor to use value type enum --- .../summary/aggregate_csv/__init__.py | 9 +++++---- .../summary/aggregate_csv/column.py | 19 ++++++++++++++---- .../summary_files/test_aggregate_csv.py | 20 +++++++++++++++++-- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/autofit/aggregator/summary/aggregate_csv/__init__.py b/autofit/aggregator/summary/aggregate_csv/__init__.py index e07f6bdd3..36733f8a4 100644 --- a/autofit/aggregator/summary/aggregate_csv/__init__.py +++ b/autofit/aggregator/summary/aggregate_csv/__init__.py @@ -10,6 +10,7 @@ LabelColumn, Column, ComputedColumn, + ValueType, ) from autofit.aggregator.summary.aggregate_csv.row import Row @@ -33,7 +34,7 @@ def add_column( self, argument: str, name: Optional[str] = None, - use_max_log_likelihood: Optional[bool] = False, + value_types: list = (ValueType.Median,), ): """ Add a column to the summary table. @@ -47,14 +48,14 @@ def add_column( e.g. "galaxies.lens.bulge.centre.centre_0" name An optional name for the column. If not provided, the argument will be used. - use_max_log_likelihood - If True, the maximum likelihood value will be used instead of the median PDF value. + value_types + Value types to include. Each one actually gets its own column. """ self._columns.append( Column( argument, name=name, - use_max_log_likelihood=use_max_log_likelihood, + value_types=value_types, ) ) diff --git a/autofit/aggregator/summary/aggregate_csv/column.py b/autofit/aggregator/summary/aggregate_csv/column.py index 2b1c9b66e..740d106bc 100644 --- a/autofit/aggregator/summary/aggregate_csv/column.py +++ b/autofit/aggregator/summary/aggregate_csv/column.py @@ -1,4 +1,5 @@ from abc import ABC, abstractmethod +from enum import Enum from typing import Optional, Callable @@ -19,12 +20,19 @@ def value(self, row: "Row"): pass +class ValueType(Enum): + Median = 0 + MaxLogLikelihood = 1 + ValuesAt1Sigma = 2 + ValuesAt3Sigma = 3 + + class Column(AbstractColumn): def __init__( self, argument: str, name: Optional[str] = None, - use_max_log_likelihood: Optional[bool] = False, + value_types: list[ValueType] = (ValueType.Median,), ): """ A column in the summary table. @@ -44,12 +52,15 @@ def __init__( ) ) self.argument = argument - self.use_max_log_likelihood = use_max_log_likelihood + self.value_types = value_types def value(self, row: "Row"): - result = {"": row.median_pdf_sample_kwargs[self.path]} + result = {} + + if ValueType.Median in self.value_types: + result[""] = row.median_pdf_sample_kwargs[self.path] - if self.use_max_log_likelihood: + if ValueType.MaxLogLikelihood in self.value_types: result["max_lh"] = row.max_likelihood_kwargs return result diff --git a/test_autofit/aggregator/summary_files/test_aggregate_csv.py b/test_autofit/aggregator/summary_files/test_aggregate_csv.py index 78ed25353..0dce54083 100644 --- a/test_autofit/aggregator/summary_files/test_aggregate_csv.py +++ b/test_autofit/aggregator/summary_files/test_aggregate_csv.py @@ -2,7 +2,7 @@ from pathlib import Path -from autofit.aggregator.summary.aggregate_csv import AggregateCSV +from autofit.aggregator.summary.aggregate_csv import AggregateCSV, ValueType import pytest @@ -73,7 +73,7 @@ def test_use_max_log_likelihood( ): summary.add_column( "galaxies.lens.bulge.centre.centre_0", - use_max_log_likelihood=True, + value_types=[ValueType.MaxLogLikelihood], ) summary.save(output_path) @@ -154,3 +154,19 @@ def compute(samples): first = dicts[0] assert first["computed_a"] == "1" assert first["computed_b"] == "2" + + +def test_values_at_sigma( + output_path, + summary, + load_output, +): + summary.add_column( + "galaxies.lens.bulge.centre.centre_0", + value_types=[ValueType.ValuesAt1Sigma], + ) + summary.save(output_path) + + dicts = load_output() + + print(dicts) From 0fec815c458300a2f2ea87864fbbdc3ddf48c021 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 2 Apr 2025 14:50:58 +0100 Subject: [PATCH 09/29] adding implementation for sigmas --- autofit/aggregator/summary/aggregate_csv/column.py | 10 ++++++++++ autofit/aggregator/summary/aggregate_csv/row.py | 8 ++++++++ 2 files changed, 18 insertions(+) diff --git a/autofit/aggregator/summary/aggregate_csv/column.py b/autofit/aggregator/summary/aggregate_csv/column.py index 740d106bc..6d98a0fcf 100644 --- a/autofit/aggregator/summary/aggregate_csv/column.py +++ b/autofit/aggregator/summary/aggregate_csv/column.py @@ -63,6 +63,16 @@ def value(self, row: "Row"): if ValueType.MaxLogLikelihood in self.value_types: result["max_lh"] = row.max_likelihood_kwargs + if ValueType.ValuesAt1Sigma in self.value_types: + lower, upper = row.values_at_sigma_1_kwargs[self.path] + result["lower_1_sigma"] = lower + result["upper_1_sigma"] = upper + + if ValueType.ValuesAt3Sigma in self.value_types: + lower, upper = row.values_at_sigma_3_kwargs[self.path] + result["lower_3_sigma"] = lower + result["upper_3_sigma"] = upper + return result @property diff --git a/autofit/aggregator/summary/aggregate_csv/row.py b/autofit/aggregator/summary/aggregate_csv/row.py index 5e3bab952..b440b8647 100644 --- a/autofit/aggregator/summary/aggregate_csv/row.py +++ b/autofit/aggregator/summary/aggregate_csv/row.py @@ -74,6 +74,14 @@ def _dict_for_list(self, list_): def errors_at_sigma_1_kwargs(self): return self._dict_for_list(self.result.samples_summary.errors_at_sigma_1) + @cached_property + def values_at_sigma_1_kwargs(self): + return self._dict_for_list(self.result.samples_summary.values_at_sigma_1) + + @cached_property + def values_at_sigma_3_kwargs(self): + return self._dict_for_list(self.result.samples_summary.values_at_sigma_3) + def dict(self) -> dict: """ The row as a dictionary including an id and one entry for each column. From 9c41cf0591f51346a38a5d8abf882f86f8b052cc Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 2 Apr 2025 15:11:51 +0100 Subject: [PATCH 10/29] loading all possibile paths --- autofit/aggregator/summary/aggregate_csv/row.py | 4 +++- .../aggregator/summary_files/test_aggregate_csv.py | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/autofit/aggregator/summary/aggregate_csv/row.py b/autofit/aggregator/summary/aggregate_csv/row.py index b440b8647..02c6e7f7c 100644 --- a/autofit/aggregator/summary/aggregate_csv/row.py +++ b/autofit/aggregator/summary/aggregate_csv/row.py @@ -68,7 +68,9 @@ def model_paths(self): return self.result.model.all_paths def _dict_for_list(self, list_): - return {key: value for key, value in zip(self.model_paths, list_)} + return { + key: value for paths, value in zip(self.model_paths, list_) for key in paths + } @cached_property def errors_at_sigma_1_kwargs(self): diff --git a/test_autofit/aggregator/summary_files/test_aggregate_csv.py b/test_autofit/aggregator/summary_files/test_aggregate_csv.py index 0dce54083..7badccb56 100644 --- a/test_autofit/aggregator/summary_files/test_aggregate_csv.py +++ b/test_autofit/aggregator/summary_files/test_aggregate_csv.py @@ -169,4 +169,10 @@ def test_values_at_sigma( dicts = load_output() - print(dicts) + first = dicts[0] + assert ( + first["galaxies_lens_bulge_centre_centre_0_lower_1_sigma"] == 3.4319440071038327 + ) + assert ( + first["galaxies_lens_bulge_centre_centre_0_upper_1_sigma"] == 3.4319440071038327 + ) From 85ede9f72ea024f15afa65c8279a9d36bb41002f Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 2 Apr 2025 15:15:40 +0100 Subject: [PATCH 11/29] working --- .../summary/aggregate_csv/column.py | 4 +-- .../summary_files/test_aggregate_csv.py | 31 +++++++++++++++++-- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/autofit/aggregator/summary/aggregate_csv/column.py b/autofit/aggregator/summary/aggregate_csv/column.py index 6d98a0fcf..51f2dda03 100644 --- a/autofit/aggregator/summary/aggregate_csv/column.py +++ b/autofit/aggregator/summary/aggregate_csv/column.py @@ -65,8 +65,8 @@ def value(self, row: "Row"): if ValueType.ValuesAt1Sigma in self.value_types: lower, upper = row.values_at_sigma_1_kwargs[self.path] - result["lower_1_sigma"] = lower - result["upper_1_sigma"] = upper + result["lower_1_sigma"] = float(lower) + result["upper_1_sigma"] = float(upper) if ValueType.ValuesAt3Sigma in self.value_types: lower, upper = row.values_at_sigma_3_kwargs[self.path] diff --git a/test_autofit/aggregator/summary_files/test_aggregate_csv.py b/test_autofit/aggregator/summary_files/test_aggregate_csv.py index 7badccb56..e1c500908 100644 --- a/test_autofit/aggregator/summary_files/test_aggregate_csv.py +++ b/test_autofit/aggregator/summary_files/test_aggregate_csv.py @@ -156,7 +156,7 @@ def compute(samples): assert first["computed_b"] == "2" -def test_values_at_sigma( +def test_values_at_1_sigma( output_path, summary, load_output, @@ -171,8 +171,33 @@ def test_values_at_sigma( first = dicts[0] assert ( - first["galaxies_lens_bulge_centre_centre_0_lower_1_sigma"] == 3.4319440071038327 + first["galaxies_lens_bulge_centre_centre_0_lower_1_sigma"] + == "3.4319440071038327" ) assert ( - first["galaxies_lens_bulge_centre_centre_0_upper_1_sigma"] == 3.4319440071038327 + first["galaxies_lens_bulge_centre_centre_0_upper_1_sigma"] + == "5.134685987907622" + ) + + +def test_values_at_3_sigma( + output_path, + summary, + load_output, +): + summary.add_column( + "galaxies.lens.bulge.centre.centre_0", + value_types=[ValueType.ValuesAt3Sigma], + ) + summary.save(output_path) + + dicts = load_output() + + first = dicts[0] + assert ( + first["galaxies_lens_bulge_centre_centre_0_lower_3_sigma"] + == "1.6742483855526449" + ) + assert ( + first["galaxies_lens_bulge_centre_centre_0_upper_3_sigma"] == "5.93749816282317" ) From 12cdc64c8dbe339ddf1169425fe72d5c97677b99 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 2 Apr 2025 15:17:17 +0100 Subject: [PATCH 12/29] docs --- autofit/aggregator/summary/aggregate_csv/__init__.py | 6 +++--- autofit/aggregator/summary/aggregate_csv/column.py | 12 ++++++++---- .../aggregator/summary_files/test_aggregate_csv.py | 12 ++++++------ 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/autofit/aggregator/summary/aggregate_csv/__init__.py b/autofit/aggregator/summary/aggregate_csv/__init__.py index 36733f8a4..3bd8531d4 100644 --- a/autofit/aggregator/summary/aggregate_csv/__init__.py +++ b/autofit/aggregator/summary/aggregate_csv/__init__.py @@ -30,14 +30,14 @@ def __init__(self, aggregator: Aggregator): self._aggregator = aggregator self._columns = [] - def add_column( + def add_variable( self, argument: str, name: Optional[str] = None, value_types: list = (ValueType.Median,), ): """ - Add a column to the summary table. + Add a variable to include columns for in the summary table. This will be taken from the samples_summary or latent_summary. @@ -49,7 +49,7 @@ def add_column( name An optional name for the column. If not provided, the argument will be used. value_types - Value types to include. Each one actually gets its own column. + Value types to include. See ValueType. """ self._columns.append( Column( diff --git a/autofit/aggregator/summary/aggregate_csv/column.py b/autofit/aggregator/summary/aggregate_csv/column.py index 51f2dda03..734f375d1 100644 --- a/autofit/aggregator/summary/aggregate_csv/column.py +++ b/autofit/aggregator/summary/aggregate_csv/column.py @@ -21,10 +21,14 @@ def value(self, row: "Row"): class ValueType(Enum): - Median = 0 - MaxLogLikelihood = 1 - ValuesAt1Sigma = 2 - ValuesAt3Sigma = 3 + """ + Possible value types to create columns for. + """ + + Median = 0 # The median_pdf_sample value + MaxLogLikelihood = 1 # The max likelihood value + ValuesAt1Sigma = 2 # The values at 1 sigma. This includes a lower and upper value + ValuesAt3Sigma = 3 # The values at 3 sigma. This includes a lower and upper value class Column(AbstractColumn): diff --git a/test_autofit/aggregator/summary_files/test_aggregate_csv.py b/test_autofit/aggregator/summary_files/test_aggregate_csv.py index e1c500908..8f5c0166f 100644 --- a/test_autofit/aggregator/summary_files/test_aggregate_csv.py +++ b/test_autofit/aggregator/summary_files/test_aggregate_csv.py @@ -57,7 +57,7 @@ def test_add_column( summary, load_output, ): - summary.add_column("galaxies.lens.bulge.centre.centre_0") + summary.add_variable("galaxies.lens.bulge.centre.centre_0") summary.save(output_path) dicts = load_output() @@ -71,7 +71,7 @@ def test_use_max_log_likelihood( summary, load_output, ): - summary.add_column( + summary.add_variable( "galaxies.lens.bulge.centre.centre_0", value_types=[ValueType.MaxLogLikelihood], ) @@ -88,7 +88,7 @@ def test_add_named_column( summary, load_output, ): - summary.add_column( + summary.add_variable( "galaxies.lens.bulge.centre.centre_0", name="centre_0", ) @@ -105,7 +105,7 @@ def test_add_latent_column( summary, load_output, ): - summary.add_column( + summary.add_variable( "latent.value", ) summary.save(output_path) @@ -161,7 +161,7 @@ def test_values_at_1_sigma( summary, load_output, ): - summary.add_column( + summary.add_variable( "galaxies.lens.bulge.centre.centre_0", value_types=[ValueType.ValuesAt1Sigma], ) @@ -185,7 +185,7 @@ def test_values_at_3_sigma( summary, load_output, ): - summary.add_column( + summary.add_variable( "galaxies.lens.bulge.centre.centre_0", value_types=[ValueType.ValuesAt3Sigma], ) From f453eddaaccd9a9b83617b20541ca21edaf43987 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 2 Apr 2025 15:17:29 +0100 Subject: [PATCH 13/29] docs --- autofit/aggregator/summary/aggregate_csv/column.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autofit/aggregator/summary/aggregate_csv/column.py b/autofit/aggregator/summary/aggregate_csv/column.py index 734f375d1..6b4edcce4 100644 --- a/autofit/aggregator/summary/aggregate_csv/column.py +++ b/autofit/aggregator/summary/aggregate_csv/column.py @@ -47,6 +47,8 @@ def __init__( The argument as it appears in the median_pdf_sample arguments name An optional name for the column + value_types + Value types to include. See ValueType. """ super().__init__( name From 71c58593a263b305397c80a5c84d007eb56f0bc6 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 2 Apr 2025 17:13:51 +0100 Subject: [PATCH 14/29] useless casrt --- autofit/aggregator/summary/aggregate_csv/column.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autofit/aggregator/summary/aggregate_csv/column.py b/autofit/aggregator/summary/aggregate_csv/column.py index 6b4edcce4..662209e32 100644 --- a/autofit/aggregator/summary/aggregate_csv/column.py +++ b/autofit/aggregator/summary/aggregate_csv/column.py @@ -71,8 +71,8 @@ def value(self, row: "Row"): if ValueType.ValuesAt1Sigma in self.value_types: lower, upper = row.values_at_sigma_1_kwargs[self.path] - result["lower_1_sigma"] = float(lower) - result["upper_1_sigma"] = float(upper) + result["lower_1_sigma"] = lower + result["upper_1_sigma"] = upper if ValueType.ValuesAt3Sigma in self.value_types: lower, upper = row.values_at_sigma_3_kwargs[self.path] From c6dc6966425dd6af6b83d3bbf545f93a5117ead0 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 9 Apr 2025 15:36:44 +0100 Subject: [PATCH 15/29] cast log likelihood to float when sample is created --- autofit/non_linear/samples/sample.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autofit/non_linear/samples/sample.py b/autofit/non_linear/samples/sample.py index 60051a826..0346fbabe 100644 --- a/autofit/non_linear/samples/sample.py +++ b/autofit/non_linear/samples/sample.py @@ -31,7 +31,7 @@ def __init__( kwargs Dictionary mapping model paths to values for the sample """ - self.log_likelihood = log_likelihood + self.log_likelihood = float(log_likelihood) self.log_prior = log_prior self.weight = weight self.kwargs = { From e4c9be4163644d4be3dbec3f0f7821e57984b7da Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 9 Apr 2025 15:52:58 +0100 Subject: [PATCH 16/29] unused import --- autofit/non_linear/samples/pdf.py | 1 - 1 file changed, 1 deletion(-) diff --git a/autofit/non_linear/samples/pdf.py b/autofit/non_linear/samples/pdf.py index 083cfc836..a0771d5c3 100644 --- a/autofit/non_linear/samples/pdf.py +++ b/autofit/non_linear/samples/pdf.py @@ -1,4 +1,3 @@ -import logging import math import pathlib import warnings From 2edd1ef5314145c945ea57ed32beca496147ea37 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 9 Apr 2025 16:00:55 +0100 Subject: [PATCH 17/29] support creating dicts --- autofit/non_linear/samples/interface.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/autofit/non_linear/samples/interface.py b/autofit/non_linear/samples/interface.py index a3dd55caf..416a739bb 100644 --- a/autofit/non_linear/samples/interface.py +++ b/autofit/non_linear/samples/interface.py @@ -1,6 +1,6 @@ from abc import ABC, abstractmethod from functools import wraps -from typing import Union, List, Tuple +from typing import Union, List, Tuple, Dict from autofit.mapper.model import ModelInstance from autofit.mapper.prior_model.abstract import AbstractPriorModel @@ -23,10 +23,17 @@ def to_instance(func): @wraps(func) def wrapper( - self, *args, as_instance: bool = True, **kwargs - ) -> Union[List, ModelInstance]: + self, + *args, + as_instance: bool = True, + as_dict: bool = False, + **kwargs, + ) -> Union[List, Dict, ModelInstance]: vector = func(self, *args, **kwargs) + if as_dict: + return {name: value for name, value in zip(self.names, vector)} + if as_instance: return self._instance_from_vector(vector) From d9b4c923d4cd8919fd6fdfcef494bacc4e08bf68 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 9 Apr 2025 16:01:11 +0100 Subject: [PATCH 18/29] create dicts for samples summary --- autofit/non_linear/samples/pdf.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/autofit/non_linear/samples/pdf.py b/autofit/non_linear/samples/pdf.py index a0771d5c3..48f96e463 100644 --- a/autofit/non_linear/samples/pdf.py +++ b/autofit/non_linear/samples/pdf.py @@ -61,10 +61,22 @@ def summary(self): max_log_likelihood_sample=self.max_log_likelihood_sample, median_pdf_sample=median_pdf_sample, log_evidence=self.log_evidence, - errors_at_sigma_1=self.errors_at_sigma(sigma=1.0, as_instance=False), - errors_at_sigma_3=self.errors_at_sigma(sigma=3.0, as_instance=False), - values_at_sigma_1=self.values_at_sigma(sigma=1.0, as_instance=False), - values_at_sigma_3=self.values_at_sigma(sigma=3.0, as_instance=False), + errors_at_sigma_1=self.errors_at_sigma( + sigma=1.0, + as_dict=True, + ), + errors_at_sigma_3=self.errors_at_sigma( + sigma=3.0, + as_dict=True, + ), + values_at_sigma_1=self.values_at_sigma( + sigma=1.0, + as_dict=True, + ), + values_at_sigma_3=self.values_at_sigma( + sigma=3.0, + as_dict=True, + ), ) @classmethod From e5eb4e4f172f886b29a09edca927a4532fb33b2f Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 9 Apr 2025 16:03:13 +0100 Subject: [PATCH 19/29] use paths not names --- autofit/non_linear/samples/interface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autofit/non_linear/samples/interface.py b/autofit/non_linear/samples/interface.py index 416a739bb..d64f2eb6b 100644 --- a/autofit/non_linear/samples/interface.py +++ b/autofit/non_linear/samples/interface.py @@ -32,7 +32,7 @@ def wrapper( vector = func(self, *args, **kwargs) if as_dict: - return {name: value for name, value in zip(self.names, vector)} + return {name: value for name, value in zip(self.paths, vector)} if as_instance: return self._instance_from_vector(vector) From bfe720bda2abdc92bef809c3b514be459f58531a Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 9 Apr 2025 16:14:34 +0100 Subject: [PATCH 20/29] join paths for more readable output --- autofit/non_linear/samples/interface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autofit/non_linear/samples/interface.py b/autofit/non_linear/samples/interface.py index d64f2eb6b..636416814 100644 --- a/autofit/non_linear/samples/interface.py +++ b/autofit/non_linear/samples/interface.py @@ -32,7 +32,7 @@ def wrapper( vector = func(self, *args, **kwargs) if as_dict: - return {name: value for name, value in zip(self.paths, vector)} + return {".".join(path[0]): value for path, value in zip(self.paths, vector)} if as_instance: return self._instance_from_vector(vector) From 9bee875653735416fb697b30c84b35c9cf47eb3e Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 9 Apr 2025 16:14:43 +0100 Subject: [PATCH 21/29] update test --- test_autofit/serialise/test_samples.py | 92 +++++++++++++------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/test_autofit/serialise/test_samples.py b/test_autofit/serialise/test_samples.py index 6f7331d03..d333176ae 100644 --- a/test_autofit/serialise/test_samples.py +++ b/test_autofit/serialise/test_samples.py @@ -52,6 +52,22 @@ def make_summary_dict(): "type": "instance", "class_path": "autofit.non_linear.samples.summary.SamplesSummary", "arguments": { + "values_at_sigma_1": { + "type": "dict", + "arguments": { + "centre": {"type": "tuple", "values": [0.0, 2.0]}, + "normalization": {"type": "tuple", "values": [1.0, 4.0]}, + "sigma": {"type": "tuple", "values": [2.0, 6.0]}, + }, + }, + "errors_at_sigma_3": { + "type": "dict", + "arguments": { + "centre": {"type": "tuple", "values": [2.0, 0.0]}, + "normalization": {"type": "tuple", "values": [3.0, 0.0]}, + "sigma": {"type": "tuple", "values": [4.0, 0.0]}, + }, + }, "median_pdf_sample": { "type": "instance", "class_path": "autofit.non_linear.samples.sample.Sample", @@ -69,13 +85,30 @@ def make_summary_dict(): }, }, }, - "values_at_sigma_3": { - "type": "list", - "values": [ - {"type": "tuple", "values": [0.0, 2.0]}, - {"type": "tuple", "values": [1.0, 4.0]}, - {"type": "tuple", "values": [2.0, 6.0]}, - ], + "max_log_likelihood_sample": { + "type": "instance", + "class_path": "autofit.non_linear.samples.sample.Sample", + "arguments": { + "log_likelihood": 4.0, + "log_prior": 5.0, + "weight": 6.0, + "kwargs": { + "type": "dict", + "arguments": { + "centre": 2.0, + "normalization": 4.0, + "sigma": 6.0, + }, + }, + }, + }, + "errors_at_sigma_1": { + "type": "dict", + "arguments": { + "centre": {"type": "tuple", "values": [2.0, 0.0]}, + "normalization": {"type": "tuple", "values": [3.0, 0.0]}, + "sigma": {"type": "tuple", "values": [4.0, 0.0]}, + }, }, "model": { "class_path": "autofit.example.model.Gaussian", @@ -98,48 +131,15 @@ def make_summary_dict(): }, }, }, - "max_log_likelihood_sample": { - "type": "instance", - "class_path": "autofit.non_linear.samples.sample.Sample", + "log_evidence": None, + "values_at_sigma_3": { + "type": "dict", "arguments": { - "log_likelihood": 4.0, - "log_prior": 5.0, - "weight": 6.0, - "kwargs": { - "type": "dict", - "arguments": { - "centre": 2.0, - "normalization": 4.0, - "sigma": 6.0, - }, - }, + "centre": {"type": "tuple", "values": [0.0, 2.0]}, + "normalization": {"type": "tuple", "values": [1.0, 4.0]}, + "sigma": {"type": "tuple", "values": [2.0, 6.0]}, }, }, - "values_at_sigma_1": { - "type": "list", - "values": [ - {"type": "tuple", "values": [0.0, 2.0]}, - {"type": "tuple", "values": [1.0, 4.0]}, - {"type": "tuple", "values": [2.0, 6.0]}, - ], - }, - "errors_at_sigma_1": { - "type": "list", - "values": [ - {"type": "tuple", "values": [2.0, 0.0]}, - {"type": "tuple", "values": [3.0, 0.0]}, - {"type": "tuple", "values": [4.0, 0.0]}, - ], - }, - "errors_at_sigma_3": { - "type": "list", - "values": [ - {"type": "tuple", "values": [2.0, 0.0]}, - {"type": "tuple", "values": [3.0, 0.0]}, - {"type": "tuple", "values": [4.0, 0.0]}, - ], - }, - "log_evidence": None, }, } From 0bfee6da2f45a6fe4108862ea43a55c33b0867b7 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 9 Apr 2025 16:26:32 +0100 Subject: [PATCH 22/29] unused error fields in test data --- .../fit_1/files/samples_summary.json | 38 ------------------- .../fit_2/files/samples_summary.json | 38 ------------------- 2 files changed, 76 deletions(-) diff --git a/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/samples_summary.json b/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/samples_summary.json index 1a7697d7e..70928d65d 100644 --- a/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/samples_summary.json +++ b/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/samples_summary.json @@ -34,25 +34,6 @@ } } }, - "errors_at_sigma_1": { - "type": "list", - "values": [ - { - "type": "tuple", - "values": [ - 0.8219585320794973, - 0.8807834487242916 - ] - }, - { - "type": "tuple", - "values": [ - 0.4098203614718814, - 0.49773247178232705 - ] - } - ] - }, "values_at_sigma_3": { "type": "list", "values": [ @@ -73,25 +54,6 @@ ] }, "log_evidence": -4.214938026111044, - "errors_at_sigma_3": { - "type": "list", - "values": [ - { - "type": "tuple", - "values": [ - 2.579654153630685, - 1.6835956236398397 - ] - }, - { - "type": "tuple", - "values": [ - 1.2322215615775107, - 1.5982882571693717 - ] - } - ] - }, "values_at_sigma_1": { "type": "list", "values": [ diff --git a/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/samples_summary.json b/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/samples_summary.json index 9fe621459..895e2fc94 100644 --- a/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/samples_summary.json +++ b/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/samples_summary.json @@ -34,25 +34,6 @@ } } }, - "errors_at_sigma_1": { - "type": "list", - "values": [ - { - "type": "tuple", - "values": [ - 0.8219585320794973, - 0.8807834487242916 - ] - }, - { - "type": "tuple", - "values": [ - 0.4098203614718814, - 0.49773247178232705 - ] - } - ] - }, "values_at_sigma_3": { "type": "list", "values": [ @@ -73,25 +54,6 @@ ] }, "log_evidence": -4.214938026111044, - "errors_at_sigma_3": { - "type": "list", - "values": [ - { - "type": "tuple", - "values": [ - 2.579654153630685, - 1.6835956236398397 - ] - }, - { - "type": "tuple", - "values": [ - 1.2322215615775107, - 1.5982882571693717 - ] - } - ] - }, "values_at_sigma_1": { "type": "list", "values": [ From 6002b4bee83d6b8d6ac017a24cacc8f8727a82cf Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 9 Apr 2025 16:31:22 +0100 Subject: [PATCH 23/29] update values at sigma in test data to use dict --- .../fit_1/files/samples_summary.json | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/samples_summary.json b/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/samples_summary.json index 70928d65d..072379d23 100644 --- a/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/samples_summary.json +++ b/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/samples_summary.json @@ -35,43 +35,43 @@ } }, "values_at_sigma_3": { - "type": "list", - "values": [ - { + "type": "dict", + "arguments": { + "galaxies.lens.bulge.centre.centre_0": { "type": "tuple", "values": [ 1.6742483855526449, 5.93749816282317 ] }, - { + "galaxies.lens.bulge.centre.centre_1": { "type": "tuple", "values": [ -0.21891974607628695, 2.6115900726705954 ] } - ] + } }, "log_evidence": -4.214938026111044, "values_at_sigma_1": { - "type": "list", - "values": [ - { + "type": "dict", + "arguments": { + "galaxies.lens.bulge.centre.centre_0": { "type": "tuple", "values": [ 3.4319440071038327, 5.134685987907622 ] }, - { + "galaxies.lens.bulge.centre.centre_1": { "type": "tuple", "values": [ 0.6034814540293423, 1.5110342872835507 ] } - ] + } } } } \ No newline at end of file From 82e0391886018e5648bc07881269e6801f1e1f21 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 9 Apr 2025 16:40:18 +0100 Subject: [PATCH 24/29] structure in second samples summary --- .../fit_2/files/samples_summary.json | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/samples_summary.json b/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/samples_summary.json index 895e2fc94..c87d60c0c 100644 --- a/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/samples_summary.json +++ b/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/samples_summary.json @@ -35,43 +35,43 @@ } }, "values_at_sigma_3": { - "type": "list", - "values": [ - { + "type": "dict", + "arguments": { + "galaxies.lens.bulge.centre.centre_0": { "type": "tuple", "values": [ 1.6742483855526449, 5.93749816282317 ] }, - { + "galaxies.lens.bulge.centre.centre_1": { "type": "tuple", "values": [ -0.21891974607628695, 2.6115900726705954 ] } - ] + } }, "log_evidence": -4.214938026111044, "values_at_sigma_1": { - "type": "list", - "values": [ - { + "type": "dict", + "arguments": { + "galaxies.lens.bulge.centre.centre_0": { "type": "tuple", "values": [ 3.4319440071038327, 5.134685987907622 ] }, - { + "galaxies.lens.bulge.centre.centre_1": { "type": "tuple", "values": [ 0.6034814540293423, 1.5110342872835507 ] } - ] + } } } } \ No newline at end of file From 1a62a78c72f9a83bd9de39c6d93f8413fd15bb98 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 9 Apr 2025 16:40:33 +0100 Subject: [PATCH 25/29] use dict repr of values at sigma --- .../aggregator/summary/aggregate_csv/row.py | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/autofit/aggregator/summary/aggregate_csv/row.py b/autofit/aggregator/summary/aggregate_csv/row.py index 02c6e7f7c..8bd724ed4 100644 --- a/autofit/aggregator/summary/aggregate_csv/row.py +++ b/autofit/aggregator/summary/aggregate_csv/row.py @@ -32,7 +32,9 @@ def _add_paths(self, kwargs): return { path: value for key, value in kwargs.items() - for path in self._all_paths(key) + for path in self._all_paths( + key.split(".") if isinstance(key, str) else key, + ) } @property @@ -54,7 +56,7 @@ def max_likelihood_kwargs(self): """ The median_pdf_sample arguments for the search from the samples_summary and latent_summary. """ - samples_summary = self.result.value("samples_summary") + samples_summary = self.result.samples_summary kwargs = self._add_paths(samples_summary.median_pdf_sample.kwargs) latent_summary = self.result.value("latent.latent_summary") @@ -67,22 +69,13 @@ def max_likelihood_kwargs(self): def model_paths(self): return self.result.model.all_paths - def _dict_for_list(self, list_): - return { - key: value for paths, value in zip(self.model_paths, list_) for key in paths - } - - @cached_property - def errors_at_sigma_1_kwargs(self): - return self._dict_for_list(self.result.samples_summary.errors_at_sigma_1) - @cached_property def values_at_sigma_1_kwargs(self): - return self._dict_for_list(self.result.samples_summary.values_at_sigma_1) + return self._add_paths(self.result.samples_summary.values_at_sigma_1) @cached_property def values_at_sigma_3_kwargs(self): - return self._dict_for_list(self.result.samples_summary.values_at_sigma_3) + return self._add_paths(self.result.samples_summary.values_at_sigma_3) def dict(self) -> dict: """ From a7aa9f4881cafb873865567e1914f43b7c60934e Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 9 Apr 2025 16:42:33 +0100 Subject: [PATCH 26/29] unused method --- autofit/aggregator/summary/aggregate_csv/row.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/autofit/aggregator/summary/aggregate_csv/row.py b/autofit/aggregator/summary/aggregate_csv/row.py index 8bd724ed4..f77852502 100644 --- a/autofit/aggregator/summary/aggregate_csv/row.py +++ b/autofit/aggregator/summary/aggregate_csv/row.py @@ -65,10 +65,6 @@ def max_likelihood_kwargs(self): return kwargs - @cached_property - def model_paths(self): - return self.result.model.all_paths - @cached_property def values_at_sigma_1_kwargs(self): return self._add_paths(self.result.samples_summary.values_at_sigma_1) From f8e7073e09f0ae77b687742523096012cdcbb4e1 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 9 Apr 2025 16:43:06 +0100 Subject: [PATCH 27/29] docs --- autofit/aggregator/summary/aggregate_csv/row.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/autofit/aggregator/summary/aggregate_csv/row.py b/autofit/aggregator/summary/aggregate_csv/row.py index f77852502..c5d28e4d8 100644 --- a/autofit/aggregator/summary/aggregate_csv/row.py +++ b/autofit/aggregator/summary/aggregate_csv/row.py @@ -66,11 +66,17 @@ def max_likelihood_kwargs(self): return kwargs @cached_property - def values_at_sigma_1_kwargs(self): + def values_at_sigma_1_kwargs(self) -> dict: + """ + The values_at_sigma_1 arguments for the search from the samples_summary. + """ return self._add_paths(self.result.samples_summary.values_at_sigma_1) @cached_property - def values_at_sigma_3_kwargs(self): + def values_at_sigma_3_kwargs(self) -> dict: + """ + The values_at_sigma_3 arguments for the search from the samples_summary. + """ return self._add_paths(self.result.samples_summary.values_at_sigma_3) def dict(self) -> dict: From ab8780376f5a7f1eaa624b91e181c4fcc4dd93ab Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 9 Apr 2025 16:47:19 +0100 Subject: [PATCH 28/29] also account for latent summary --- autofit/aggregator/summary/aggregate_csv/row.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/autofit/aggregator/summary/aggregate_csv/row.py b/autofit/aggregator/summary/aggregate_csv/row.py index c5d28e4d8..8f0d9c84e 100644 --- a/autofit/aggregator/summary/aggregate_csv/row.py +++ b/autofit/aggregator/summary/aggregate_csv/row.py @@ -70,14 +70,26 @@ def values_at_sigma_1_kwargs(self) -> dict: """ The values_at_sigma_1 arguments for the search from the samples_summary. """ - return self._add_paths(self.result.samples_summary.values_at_sigma_1) + kwargs = self._add_paths(self.result.samples_summary.values_at_sigma_1) + + latent_summary = self.result.value("latent.latent_summary") + if latent_summary is not None: + kwargs.update(latent_summary.values_at_sigma_1) + + return kwargs @cached_property def values_at_sigma_3_kwargs(self) -> dict: """ The values_at_sigma_3 arguments for the search from the samples_summary. """ - return self._add_paths(self.result.samples_summary.values_at_sigma_3) + kwargs = self._add_paths(self.result.samples_summary.values_at_sigma_3) + + latent_summary = self.result.value("latent.latent_summary") + if latent_summary is not None: + kwargs.update(latent_summary.values_at_sigma_3) + + return kwargs def dict(self) -> dict: """ From b15d0dae41d205661711ec44275cd894260c9cd7 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 9 Apr 2025 16:58:30 +0100 Subject: [PATCH 29/29] fixes --- .../aggregator/summary/aggregate_csv/row.py | 14 +++++++++-- .../fit_1/files/latent/latent_summary.json | 25 +++++++++++++++++++ .../fit_2/files/latent/latent_summary.json | 25 +++++++++++++++++++ .../summary_files/test_aggregate_csv.py | 19 ++++++++++++++ 4 files changed, 81 insertions(+), 2 deletions(-) diff --git a/autofit/aggregator/summary/aggregate_csv/row.py b/autofit/aggregator/summary/aggregate_csv/row.py index 8f0d9c84e..b73a31528 100644 --- a/autofit/aggregator/summary/aggregate_csv/row.py +++ b/autofit/aggregator/summary/aggregate_csv/row.py @@ -74,7 +74,12 @@ def values_at_sigma_1_kwargs(self) -> dict: latent_summary = self.result.value("latent.latent_summary") if latent_summary is not None: - kwargs.update(latent_summary.values_at_sigma_1) + kwargs.update( + { + tuple(key.split(".")): value + for key, value in latent_summary.values_at_sigma_1.items() + } + ) return kwargs @@ -87,7 +92,12 @@ def values_at_sigma_3_kwargs(self) -> dict: latent_summary = self.result.value("latent.latent_summary") if latent_summary is not None: - kwargs.update(latent_summary.values_at_sigma_3) + kwargs.update( + { + tuple(key.split(".")): value + for key, value in latent_summary.values_at_sigma_1.items() + } + ) return kwargs diff --git a/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/latent/latent_summary.json b/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/latent/latent_summary.json index dafef9958..4583ec3dd 100644 --- a/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/latent/latent_summary.json +++ b/test_autofit/aggregator/summary_files/aggregate_summary/fit_1/files/latent/latent_summary.json @@ -31,6 +31,31 @@ } } } + }, + "values_at_sigma_3": { + "type": "dict", + "arguments": { + "galaxies.lens.bulge.centre.latent": { + "type": "tuple", + "values": [ + 1.6742483855526449, + 5.93749816282317 + ] + } + } + }, + "log_evidence": -4.214938026111044, + "values_at_sigma_1": { + "type": "dict", + "arguments": { + "galaxies.lens.bulge.centre.latent": { + "type": "tuple", + "values": [ + 3.4319440071038327, + 5.134685987907622 + ] + } + } } } } \ No newline at end of file diff --git a/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/latent/latent_summary.json b/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/latent/latent_summary.json index b5f85f863..4c30b8304 100644 --- a/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/latent/latent_summary.json +++ b/test_autofit/aggregator/summary_files/aggregate_summary/fit_2/files/latent/latent_summary.json @@ -31,6 +31,31 @@ } } } + }, + "values_at_sigma_3": { + "type": "dict", + "arguments": { + "galaxies.lens.bulge.centre.latent": { + "type": "tuple", + "values": [ + 1.6742483855526449, + 5.93749816282317 + ] + } + } + }, + "log_evidence": -4.214938026111044, + "values_at_sigma_1": { + "type": "dict", + "arguments": { + "galaxies.lens.bulge.centre.latent": { + "type": "tuple", + "values": [ + 3.4319440071038327, + 5.134685987907622 + ] + } + } } } } \ No newline at end of file diff --git a/test_autofit/aggregator/summary_files/test_aggregate_csv.py b/test_autofit/aggregator/summary_files/test_aggregate_csv.py index 8f5c0166f..3be6fbffd 100644 --- a/test_autofit/aggregator/summary_files/test_aggregate_csv.py +++ b/test_autofit/aggregator/summary_files/test_aggregate_csv.py @@ -201,3 +201,22 @@ def test_values_at_3_sigma( assert ( first["galaxies_lens_bulge_centre_centre_0_upper_3_sigma"] == "5.93749816282317" ) + + +def test_latent_values_at_1_sigma( + output_path, + summary, + load_output, +): + summary.add_variable( + "galaxies.lens.bulge.centre.latent", + value_types=[ValueType.ValuesAt1Sigma], + ) + summary.save(output_path) + + dicts = load_output() + + first = dicts[0] + assert ( + first["galaxies_lens_bulge_centre_latent_lower_1_sigma"] == "3.4319440071038327" + )