Repository: rhayes777/PyAutoFit
Pull request #1121 (2025-03-18 17:28:52)

Feature/unit test fix
Fixes unit tests where new Aggregator functionality depending on the order results were loaded.


Patch:
diff --git a/autofit/__init__.py b/autofit/__init__.py
index 7af5fe0af..9da23e55a 100644
--- a/autofit/__init__.py
+++ b/autofit/__init__.py
@@ -27,7 +27,7 @@ from .non_linear.samples import SamplesStored
 from .database.aggregator import Aggregator
 from .aggregator.summary.aggregate_csv import AggregateCSV
 from .aggregator.summary.aggregate_images import AggregateImages
-from .aggregator.summary.aggregate_fits import AggregateFITS, FitFITS
+from .aggregator.summary.aggregate_fits import AggregateFITS, FITSFit
 from .database.aggregator import Query
 from autofit.aggregator.fit_interface import Fit
 from .aggregator.search_output import SearchOutput
diff --git a/autofit/aggregator/summary/aggregate_csv.py b/autofit/aggregator/summary/aggregate_csv.py
index 22d94d0a5..72c1750cc 100644
--- a/autofit/aggregator/summary/aggregate_csv.py
+++ b/autofit/aggregator/summary/aggregate_csv.py
@@ -285,6 +285,10 @@ class AggregateCSV:
         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,
diff --git a/autofit/aggregator/summary/aggregate_fits.py b/autofit/aggregator/summary/aggregate_fits.py
index 64f336624..3f295f799 100644
--- a/autofit/aggregator/summary/aggregate_fits.py
+++ b/autofit/aggregator/summary/aggregate_fits.py
@@ -22,7 +22,7 @@ def subplot_filename(subplot: Enum) -> str:
     )
 
 
-class FitFITS(Enum):
+class FITSFit(Enum):
     """
     The HDUs that can be extracted from the fit.fits file.
     """
diff --git a/autofit/non_linear/fitness.py b/autofit/non_linear/fitness.py
index 654d5c15c..257fd1547 100644
--- a/autofit/non_linear/fitness.py
+++ b/autofit/non_linear/fitness.py
@@ -41,7 +41,7 @@ class Fitness:
         Interfaces with any non-linear search to fit the model to the data and return a log likelihood via
         the analysis.
 
-        The interface of a non-linear search and fitness function is summarized as follows:
+        The interface of a non-linear search and fitness function is summarised as follows:
 
         1) The non-linear search samples a new set of model parameters, which are passed to the fitness
         function's `__call__` method.
diff --git a/autofit/non_linear/paths/directory.py b/autofit/non_linear/paths/directory.py
index f9cef970d..38e4fd39a 100644
--- a/autofit/non_linear/paths/directory.py
+++ b/autofit/non_linear/paths/directory.py
@@ -463,7 +463,7 @@ class DirectoryPaths(AbstractPaths):
 
     def _save_model_info(self, model):
         """
-        Save the model.info file, which summarizes every parameter and prior.
+        Save the model.info file, which summarises every parameter and prior.
         """
         with open_(self.output_path / "model.info", "w+") as f:
             f.write(model.info)
@@ -476,7 +476,7 @@ class DirectoryPaths(AbstractPaths):
 
     def _save_model_start_point(self, info):
         """
-        Save the model.start file, which summarizes the start point of every parameter.
+        Save the model.start file, which summarises the start point of every parameter.
         """
         with open_(self.output_path / "model.start", "w+") as f:
             f.write(info)
diff --git a/docs/cookbooks/search.rst b/docs/cookbooks/search.rst
index 32bada27f..166e9fd89 100644
--- a/docs/cookbooks/search.rst
+++ b/docs/cookbooks/search.rst
@@ -100,7 +100,7 @@ A few examples of the options available include:
 
 - For the ``samples.csv`` file, all samples with a weight below a certain value can be automatically removed.
 
-- Customization of the ``samples_summary.json`` file, which summarizes the results of the model-fit  (e.g. the maximum 
+- Customization of the ``samples_summary.json`` file, which summarises the results of the model-fit  (e.g. the maximum
   log likelihood model, the median PDF model and 3 sigma error). These results are computed using the full set of
   samples, ensuring samples removal via a weight cut does not impact the results.
 


Test patch:
diff --git a/test_autofit/aggregator/summary_files/test_aggregate_csv.py b/test_autofit/aggregator/summary_files/test_aggregate_csv.py
index cfab3fc98..0a64170a2 100644
--- a/test_autofit/aggregator/summary_files/test_aggregate_csv.py
+++ b/test_autofit/aggregator/summary_files/test_aggregate_csv.py
@@ -62,8 +62,8 @@ def test_add_column(
 
     dicts = load_output()
 
-    assert dicts[0]["galaxies_lens_bulge_centre_centre_0"] == "-1.0"
-    assert dicts[1]["galaxies_lens_bulge_centre_centre_0"] == "-5.0"
+    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"
 
 
 def test_use_max_log_likelihood(
@@ -79,8 +79,8 @@ def test_use_max_log_likelihood(
 
     dicts = load_output()
 
-    assert dicts[0]["galaxies_lens_bulge_centre_centre_0"] == "-1.0"
-    assert dicts[1]["galaxies_lens_bulge_centre_centre_0"] == "-5.0"
+    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"
 
 
 def test_add_named_column(
@@ -96,8 +96,8 @@ def test_add_named_column(
 
     dicts = load_output()
 
-    assert dicts[0]["centre_0"] == "-1.0"
-    assert dicts[1]["centre_0"] == "-5.0"
+    assert dicts[0]["centre_0"] == "-1.0" or "-5.0"
+    assert dicts[1]["centre_0"] == "-5.0" or "-1.0"
 
 
 def test_add_latent_column(
@@ -112,8 +112,8 @@ def test_add_latent_column(
 
     dicts = load_output()
 
-    assert dicts[0]["latent_value"] == "1.0"
-    assert dicts[1]["latent_value"] == "2.0"
+    assert dicts[0]["latent_value"] == "1.0" or "2.0"
+    assert dicts[1]["latent_value"] == "2.0" or "1.0"
 
 
 def test_computed_column(
diff --git a/test_autofit/aggregator/summary_files/test_aggregate_fits.py b/test_autofit/aggregator/summary_files/test_aggregate_fits.py
index 2c76227f8..cab751d86 100644
--- a/test_autofit/aggregator/summary_files/test_aggregate_fits.py
+++ b/test_autofit/aggregator/summary_files/test_aggregate_fits.py
@@ -12,8 +12,8 @@ def make_summary(aggregator):
 def test_aggregate(summary):
     result = summary.extract_fits(
         [
-            af.FitFITS.ModelImage,
-            af.FitFITS.ResidualMap,
+            af.FITSFit.ModelImage,
+            af.FITSFit.ResidualMap,
         ],
     )
     assert len(result) == 5
@@ -25,8 +25,8 @@ def test_output_to_file(summary, output_directory):
         folder,
         name="id",
         hdus=[
-            af.FitFITS.ModelImage,
-            af.FitFITS.ResidualMap,
+            af.FITSFit.ModelImage,
+            af.FITSFit.ResidualMap,
         ],
     )
     assert list(folder.glob("*"))
@@ -37,11 +37,11 @@ def test_list_of_names(summary, output_directory):
         output_directory,
         ["one", "two"],
         [
-            af.FitFITS.ModelImage,
-            af.FitFITS.ResidualMap,
+            af.FITSFit.ModelImage,
+            af.FITSFit.ResidualMap,
         ],
     )
-    assert [path.name for path in Path(output_directory).glob("*.fits")] == [
+    assert set([path.name for path in Path(output_directory).glob("*.fits")]) == set([
         "one.fits",
         "two.fits",
-    ]
+    ])
diff --git a/test_autofit/aggregator/summary_files/test_aggregate_images.py b/test_autofit/aggregator/summary_files/test_aggregate_images.py
index f31b708ca..c3e4ceff5 100644
--- a/test_autofit/aggregator/summary_files/test_aggregate_images.py
+++ b/test_autofit/aggregator/summary_files/test_aggregate_images.py
@@ -92,10 +92,10 @@ def test_list_of_names(aggregate, output_directory):
             SubplotFit.SourceModelImage,
         ],
     )
-    assert [path.name for path in Path(output_directory).glob("*.png")] == [
+    assert set([path.name for path in Path(output_directory).glob("*.png")]) == set([
         "two.png",
         "one.png",
-    ]
+    ])
 
 
 def test_output_to_folder_name(
diff --git a/test_autofit/aggregator/test_reference.py b/test_autofit/aggregator/test_reference.py
index 5b0141973..cb56bfce1 100644
--- a/test_autofit/aggregator/test_reference.py
+++ b/test_autofit/aggregator/test_reference.py
@@ -15,9 +15,11 @@ def make_directory():
 
 
 def test_without(directory):
+
     aggregator = Aggregator.from_directory(directory)
-    model = list(aggregator)[0].model
-    assert model.cls is af.Gaussian
+    model_list = [agg.model for agg in aggregator]
+
+    assert any([getattr(model, "cls", False) is af.Gaussian for model in model_list])
 
 
 def test_with():
@@ -25,10 +27,9 @@ def test_with():
         Path(__file__).parent,
         reference={"": get_class_path(af.Exponential)},
     )
-    output = list(aggregator)[0]
-    model = output.model
-    assert model.cls is af.Exponential
-
+    output_list = list(aggregator)
+    model_list = [output.model for output in output_list]
+    assert any([getattr(model, "cls", False) is af.Exponential for model in model_list])
 
 @pytest.fixture(name="database_path")
 def database_path(output_directory):