Repository: rhayes777/PyAutoFit (python)

Issue:
Graphical Model 1: `model.info` and `model.graph`
The following example compares a run using analysis summing and graph:

https://github.com/Jammy2211/autolens_workspace_test/blob/main/model_graph/task_1_model_info.py

You can run it fast by using the `export PYAUTOFIT_TEST_MODE=1` environment variable.

For analysis summing, we get the following `model.info` file:

```
Total Free Parameters = 26

model                                                                           Collection (N=26)
    0 - 1                                                                       Collection (N=26)
        galaxies                                                                Collection (N=26)
            lens                                                                Galaxy (N=19)
                bulge                                                           Basis (N=6)
                    profile_list                                                Collection (N=6)
                        0 - 59                                                  Gaussian (N=4)
                disk                                                            Exponential (N=6)
                mass                                                            Isothermal (N=5)
                shear                                                           ExternalShear (N=2)
            source                                                              Galaxy (N=7)
                bulge                                                           Sersic (N=7)
        dataset_model                                                           DatasetModel (N=0)

0 - 1
    dataset_model
        background_sky_level                                                    0.0
        grid_offset
            grid_offset_0 - grid_offset_1                                       0.0
    galaxies
        lens
            redshift                                                            0.5
            disk
                intensity                                                       LogUniformPrior [557], lower_limit = 0.99999, upper_limit = 1.0000001
                effective_radius                                                UniformPrior [558], lower_limit = 0.99999, upper_limit = 1.000001
                centre
                    centre_0                                                    GaussianPrior [553], mean = 0.0, sigma = 0.0001
                    centre_1                                                    GaussianPrior [554], mean = 0.0, sigma = 0.0001
                ell_comps
                    ell_comps_0                                                 UniformPrior [555], lower_limit = -0.001, upper_limit = 0.001
                    ell_comps_1                                                 UniformPrior [556], lower_limit = -0.001, upper_limit = 0.001
            mass
                einstein_radius                                                 UniformPrior [563], lower_limit = 1.5999, upper_limit = 1.6001
                centre
                    centre_0                                                    GaussianPrior [559], mean = 0.0, sigma = 0.001
                    centre_1                                                    GaussianPrior [560], mean = 0.0, sigma = 0.001
                ell_comps
                    ell_comps_0                                                 UniformPrior [561], lower_limit = -0.001, upper_limit = 0.001
                    ell_comps_1                                                 UniformPrior [562], lower_limit = -0.001, upper_limit = 0.001
            shear
                gamma_1                                                         UniformPrior [564], lower_limit = -1e-05, upper_limit = 1e-05
                gamma_2                                                         UniformPrior [565], lower_limit = -1e-05, upper_limit = 1e-05
            bulge
                profile_list
                    0 - 59
                        centre
                            centre_0                                            GaussianPrior [99], mean = 0.0, sigma = 0.1
                            centre_1                                            GaussianPrior [100], mean = 0.0, sigma = 0.1
                    0 - 29
                        ell_comps
                            ell_comps_0                                         UniformPrior [103], lower_limit = -0.001, upper_limit = 0.001
                            ell_comps_1                                         UniformPrior [104], lower_limit = -0.001, upper_limit = 0.001
                    0
                        sigma                                                   0.01
                    1
                        sigma                                                   0.012173570475023513
                    2
                        sigma                                                   0.01481958181103642
                    3
                        sigma                                                   0.018040722358702844
                    4
                        sigma                                                   0.02196200050540015
                    5
                        sigma                                                   0.026735596092499075
                    6
                        sigma                                                   0.03254676632238009
                    7
                        sigma                                                   0.03962103535596159
                    8
                        sigma                                                   0.04823294661991968
                    9
                        sigma                                                   0.05871671748956393
                    10
                        sigma                                                   0.07147920984212522
                    11
                        sigma                                                   0.08701571985121061
                    12
                        sigma                                                   0.1059291998043615
                    13
                        sigma                                                   0.12895365791812416
                    14
                        sigma                                                   0.15698264426783584
                    15
                        sigma                                                   0.19110392833500456
                    16
                        sigma                                                   0.23264171396400207
                    17
                        sigma                                                   0.2832080300371041
                    18
                        sigma                                                   0.3447652912749263
                    19
                        sigma                                                   0.4197024570677324
                    20
                        sigma                                                   0.510927743965457
                    21
                        sigma                                                   0.6219814898808265
                    22
                        sigma                                                   0.7571735501224365
                    23
                        sigma                                                   0.9217505574239229
                    24
                        sigma                                                   1.122099537119234
                    25
                        sigma                                                   1.3659957795112256
                    26
                        sigma                                                   1.6629045890464587
                    27
                        sigma                                                   2.0243486207997075
                    28
                        sigma                                                   2.464355060132189
                    29
                        sigma                                                   3.0
                    30 - 59
                        ell_comps
                            ell_comps_0                                         UniformPrior [253], lower_limit = -0.001, upper_limit = 0.001
                            ell_comps_1                                         UniformPrior [254], lower_limit = -0.001, upper_limit = 0.001
                    30
                        sigma                                                   0.01
                    31
                        sigma                                                   0.012173570475023513
                    32
                        sigma                                                   0.01481958181103642
                    33
                        sigma                                                   0.018040722358702844
                    34
                        sigma                                                   0.02196200050540015
                    35
                        sigma                                                   0.026735596092499075
                    36
                        sigma                                                   0.03254676632238009
                    37
                        sigma                                                   0.03962103535596159
                    38
                        sigma                                                   0.04823294661991968
                    39
                        sigma                                                   0.05871671748956393
                    40
                        sigma                                                   0.07147920984212522
                    41
                        sigma                                                   0.08701571985121061
                    42
                        sigma                                                   0.1059291998043615
                    43
                        sigma                                                   0.12895365791812416
                    44
                        sigma                                                   0.15698264426783584
                    45
                        sigma                                                   0.19110392833500456
                    46
                        sigma                                                   0.23264171396400207
                    47
                        sigma                                                   0.2832080300371041
                    48
                        sigma                                                   0.3447652912749263
                    49
                        sigma                                                   0.4197024570677324
                    50
                        sigma                                                   0.510927743965457
                    51
                        sigma                                                   0.6219814898808265
                    52
                        sigma                                                   0.7571735501224365
                    53
                        sigma                                                   0.9217505574239229
                    54
                        sigma                                                   1.122099537119234
                    55
                        sigma                                                   1.3659957795112256
                    56
                        sigma                                                   1.6629045890464587
                    57
                        sigma                                                   2.0243486207997075
                    58
                        sigma                                                   2.464355060132189
                    59
                        sigma                                                   3.0
        source
            redshift                                                            1.0
            bulge
                intensity                                                       LogUniformPrior [570], lower_limit = 0.99999, upper_limit = 1.0000001
                effective_radius                                                UniformPrior [571], lower_limit = 0.99999, upper_limit = 1.000001
                sersic_index                                                    UniformPrior [572], lower_limit = 1.9999, upper_limit = 2.0001
                centre
                    centre_0                                                    GaussianPrior [566], mean = 0.0, sigma = 0.0001
                    centre_1                                                    GaussianPrior [567], mean = 0.0, sigma = 0.0001
                ell_comps
                    ell_comps_0                                                 UniformPrior [568], lower_limit = -0.001, upper_limit = 0.001
                    ell_comps_1                                                 UniformPrior [569], lower_limit = -0.001, upper_limit = 0.001
```

For graphical models, we get this:

```
PriorFactors

PriorFactor0 (AnalysisFactor0.galaxies.lens.bulge.profile_list.59.ell_comps.ell_comps_1, AnalysisFactor1.galaxies.lens.bulge.profile_list.59.ell_comps.ell_comps_1) UniformPrior [254], lower_limit = -0.001, upper_limit = 0.001
PriorFactor1 (AnalysisFactor0.galaxies.lens.bulge.profile_list.59.ell_comps.ell_comps_0, AnalysisFactor1.galaxies.lens.bulge.profile_list.59.ell_comps.ell_comps_0) UniformPrior [253], lower_limit = -0.001, upper_limit = 0.001
PriorFactor2 (AnalysisFactor0.galaxies.lens.bulge.profile_list.29.ell_comps.ell_comps_1, AnalysisFactor1.galaxies.lens.bulge.profile_list.29.ell_comps.ell_comps_1) UniformPrior [104], lower_limit = -0.001, upper_limit = 0.001
PriorFactor3 (AnalysisFactor0.galaxies.lens.bulge.profile_list.29.ell_comps.ell_comps_0, AnalysisFactor1.galaxies.lens.bulge.profile_list.29.ell_comps.ell_comps_0) UniformPrior [103], lower_limit = -0.001, upper_limit = 0.001
PriorFactor4 (AnalysisFactor0.galaxies.lens.bulge.profile_list.59.centre.centre_1, AnalysisFactor1.galaxies.lens.bulge.profile_list.59.centre.centre_1) GaussianPrior [100], mean = 0.0, sigma = 0.1
PriorFactor5 (AnalysisFactor0.galaxies.lens.bulge.profile_list.59.centre.centre_0, AnalysisFactor1.galaxies.lens.bulge.profile_list.59.centre.centre_0) GaussianPrior [99], mean = 0.0, sigma = 0.1
PriorFactor6 (AnalysisFactor0.galaxies.source.bulge.sersic_index, AnalysisFactor1.galaxies.source.bulge.sersic_index) UniformPrior [572], lower_limit = 1.9999, upper_limit = 2.0001
PriorFactor7 (AnalysisFactor0.galaxies.source.bulge.effective_radius, AnalysisFactor1.galaxies.source.bulge.effective_radius) UniformPrior [571], lower_limit = 0.99999, upper_limit = 1.000001
PriorFactor8 (AnalysisFactor0.galaxies.source.bulge.intensity, AnalysisFactor1.galaxies.source.bulge.intensity) LogUniformPrior [570], lower_limit = 0.99999, upper_limit = 1.0000001
PriorFactor9 (AnalysisFactor0.galaxies.source.bulge.ell_comps.ell_comps_1, AnalysisFactor1.galaxies.source.bulge.ell_comps.ell_comps_1) UniformPrior [569], lower_limit = -0.001, upper_limit = 0.001
PriorFactor10 (AnalysisFactor0.galaxies.source.bulge.ell_comps.ell_comps_0, AnalysisFactor1.galaxies.source.bulge.ell_comps.ell_comps_0) UniformPrior [568], lower_limit = -0.001, upper_limit = 0.001
PriorFactor11 (AnalysisFactor0.galaxies.source.bulge.centre.centre_1, AnalysisFactor1.galaxies.source.bulge.centre.centre_1) GaussianPrior [567], mean = 0.0, sigma = 0.0001
PriorFactor12 (AnalysisFactor0.galaxies.source.bulge.centre.centre_0, AnalysisFactor1.galaxies.source.bulge.centre.centre_0) GaussianPrior [566], mean = 0.0, sigma = 0.0001
PriorFactor13 (AnalysisFactor0.galaxies.lens.shear.gamma_2, AnalysisFactor1.galaxies.lens.shear.gamma_2) UniformPrior [565], lower_limit = -1e-05, upper_limit = 1e-05
PriorFactor14 (AnalysisFactor0.galaxies.lens.shear.gamma_1, AnalysisFactor1.galaxies.lens.shear.gamma_1) UniformPrior [564], lower_limit = -1e-05, upper_limit = 1e-05
PriorFactor15 (AnalysisFactor0.galaxies.lens.mass.einstein_radius, AnalysisFactor1.galaxies.lens.mass.einstein_radius) UniformPrior [563], lower_limit = 1.5999, upper_limit = 1.6001
PriorFactor16 (AnalysisFactor0.galaxies.lens.mass.ell_comps.ell_comps_1, AnalysisFactor1.galaxies.lens.mass.ell_comps.ell_comps_1) UniformPrior [562], lower_limit = -0.001, upper_limit = 0.001
PriorFactor17 (AnalysisFactor0.galaxies.lens.mass.ell_comps.ell_comps_0, AnalysisFactor1.galaxies.lens.mass.ell_comps.ell_comps_0) UniformPrior [561], lower_limit = -0.001, upper_limit = 0.001
PriorFactor18 (AnalysisFactor0.galaxies.lens.mass.centre.centre_1, AnalysisFactor1.galaxies.lens.mass.centre.centre_1) GaussianPrior [560], mean = 0.0, sigma = 0.001
PriorFactor19 (AnalysisFactor0.galaxies.lens.mass.centre.centre_0, AnalysisFactor1.galaxies.lens.mass.centre.centre_0) GaussianPrior [559], mean = 0.0, sigma = 0.001
PriorFactor20 (AnalysisFactor0.galaxies.lens.disk.effective_radius, AnalysisFactor1.galaxies.lens.disk.effective_radius) UniformPrior [558], lower_limit = 0.99999, upper_limit = 1.000001
PriorFactor21 (AnalysisFactor0.galaxies.lens.disk.intensity, AnalysisFactor1.galaxies.lens.disk.intensity) LogUniformPrior [557], lower_limit = 0.99999, upper_limit = 1.0000001
PriorFactor22 (AnalysisFactor0.galaxies.lens.disk.ell_comps.ell_comps_1, AnalysisFactor1.galaxies.lens.disk.ell_comps.ell_comps_1) UniformPrior [556], lower_limit = -0.001, upper_limit = 0.001
PriorFactor23 (AnalysisFactor0.galaxies.lens.disk.ell_comps.ell_comps_0, AnalysisFactor1.galaxies.lens.disk.ell_comps.ell_comps_0) UniformPrior [555], lower_limit = -0.001, upper_limit = 0.001
PriorFactor24 (AnalysisFactor0.galaxies.lens.disk.centre.centre_1, AnalysisFactor1.galaxies.lens.disk.centre.centre_1) GaussianPrior [554], mean = 0.0, sigma = 0.0001
PriorFactor25 (AnalysisFactor0.galaxies.lens.disk.centre.centre_0, AnalysisFactor1.galaxies.lens.disk.centre.centre_0) GaussianPrior [553], mean = 0.0, sigma = 0.0001

AnalysisFactors

AnalysisFactor0

galaxies
    lens
        bulge
            profile_list
                0
                    centre
                        centre_0 (AnalysisFactor1.galaxies.lens.bulge.profile_list.59.centre.centre_0, PriorFactor5) GaussianPrior [99], mean = 0.0, sigma = 0.1
                        centre_1 (AnalysisFactor1.galaxies.lens.bulge.profile_list.59.centre.centre_1, PriorFactor4) GaussianPrior [100], mean = 0.0, sigma = 0.1
                    ell_comps
                        ell_comps_0 (AnalysisFactor1.galaxies.lens.bulge.profile_list.29.ell_comps.ell_comps_0, PriorFactor3) UniformPrior [103], lower_limit = -0.001, upper_limit = 0.001
                        ell_comps_1 (AnalysisFactor1.galaxies.lens.bulge.profile_list.29.ell_comps.ell_comps_1, PriorFactor2) UniformPrior [104], lower_limit = -0.001, upper_limit = 0.001
                1
                    centre
                        centre_0 (AnalysisFactor1.galaxies.lens.bulge.profile_list.59.centre.centre_0, PriorFactor5) GaussianPrior [99], mean = 0.0, sigma = 0.1
                        centre_1 (AnalysisFactor1.galaxies.lens.bulge.profile_list.59.centre.centre_1, PriorFactor4) GaussianPrior [100], mean = 0.0, sigma = 0.1
                    ell_comps
                        ell_comps_0 (AnalysisFactor1.galaxies.lens.bulge.profile_list.29.ell_comps.ell_comps_0, PriorFactor3) UniformPrior [103], lower_limit = -0.001, upper_limit = 0.001
                        ell_comps_1 (AnalysisFactor1.galaxies.lens.bulge.profile_list.29.ell_comps.ell_comps_1, PriorFactor2) UniformPrior [104], lower_limit = -0.001, upper_limit = 0.001
                2
...
```

However, for graphs `model.result` looks much closer to `model.info` of analysis summing:

```
Bayesian Evidence                                                               -107816562779.35780334
Maximum Log Likelihood                                                          -107816562774.75263977
Maximum Log Posterior                                                           -107816562769.27525330

model                                                                           GlobalPriorModel (N=26)
    0 - 1                                                                       Collection (N=26)
        galaxies                                                                Collection (N=26)
            lens                                                                Galaxy (N=19)
                bulge                                                           Basis (N=6)
                    profile_list                                                Collection (N=6)
                        0 - 59                                                  Gaussian (N=4)
                disk                                                            Exponential (N=6)
                mass                                                            Isothermal (N=5)
                shear                                                           ExternalShear (N=2)
            source                                                              Galaxy (N=7)
                bulge                                                           Sersic (N=7)
        dataset_model                                                           DatasetModel (N=0)

Maximum Log Likelihood Model:

0 - 1
    galaxies
        lens
            disk
                intensity                                                       1.000
                effective_radius                                                1.000
                centre
                    centre_0                                                    0.000
                    centre_1                                                    -0.000
                ell_comps
                    ell_comps_0                                                 -0.001
                    ell_comps_1                                                 0.001
            mass
                einstein_radius                                                 1.600
                centre
                    centre_0                                                    -0.000
                    centre_1                                                    0.000
                ell_comps
                    ell_comps_0                                                 -0.000
                    ell_comps_1                                                 -0.000
            shear
                gamma_1                                                         0.000
                gamma_2                                                         -0.000
            bulge
                profile_list
                    0 - 59
                        centre
                            centre_0                                            0.027
                            centre_1                                            0.082
                    0 - 29
                        ell_comps
                            ell_comps_0                                         0.001
                            ell_comps_1                                         0.001
                    30 - 59
                        ell_comps
                            ell_comps_0                                         0.000
                            ell_comps_1                                         0.001
        source
            bulge
                intensity                                                       1.000
                effective_radius                                                1.000
                sersic_index                                                    2.000
                centre
                    centre_0                                                    0.000
                    centre_1                                                    -0.000
                ell_comps
                    ell_comps_0                                                 -0.000
                    ell_comps_1                                                 -0.001

 WARNING: The samples have not converged enough to compute a PDF and model errors. 
 The model below over estimates errors. 



Summary (1.0 sigma limits):

0 - 1
    galaxies
        lens
            disk
                effective_radius - intensity                                    1.0000 (1.0000, 1.0000)
                centre
                    centre_0                                                    0.0001 (-0.0002, 0.0002)
                    centre_1                                                    -0.0001 (-0.0002, 0.0003)
                ell_comps
                    ell_comps_0                                                 -0.0006 (-0.0010, 0.0010)
                    ell_comps_1                                                 0.0006 (-0.0009, 0.0010)
            mass
                einstein_radius                                                 1.6001 (1.5999, 1.6001)
                centre
                    centre_0                                                    -0.0001 (-0.0036, 0.0030)
                    centre_1                                                    0.0004 (-0.0025, 0.0029)
                ell_comps
                    ell_comps_0                                                 -0.0005 (-0.0010, 0.0009)
                    ell_comps_1                                                 -0.0001 (-0.0010, 0.0010)
            shear
                gamma_1                                                         0.0000 (-0.0000, 0.0000)
                gamma_2                                                         -0.0000 (-0.0000, 0.0000)
            bulge
                profile_list
                    0 - 59
                        centre
                            centre_0                                            0.0275 (-0.2514, 0.2072)
                            centre_1                                            0.0822 (-0.2261, 0.2567)
                    0 - 29
                        ell_comps
                            ell_comps_0                                         0.0007 (-0.0010, 0.0010)
                            ell_comps_1                                         0.0006 (-0.0010, 0.0010)
                    30 - 59
                        ell_comps
                            ell_comps_0                                         0.0001 (-0.0010, 0.0010)
                            ell_comps_1                                         0.0008 (-0.0010, 0.0010)
        source
            bulge
                effective_radius - intensity                                    1.0000 (1.0000, 1.0000)
                sersic_index                                                    2.0000 (1.9999, 2.0001)
                centre
                    centre_0                                                    0.0002 (-0.0002, 0.0002)
                    centre_1                                                    -0.0000 (-0.0003, 0.0003)
                ell_comps
                    ell_comps_0                                                 -0.0002 (-0.0010, 0.0010)
                    ell_comps_1                                                 -0.0009 (-0.0010, 0.0010)

instances

0 - 1
    dataset_model
        background_sky_level
            value                                                               0.0
        grid_offset
            grid_offset_0 - grid_offset_1
                value                                                           0.0
    galaxies
        lens
            redshift
                value                                                           0.5
            bulge
                profile_list
                    0, 30
                        sigma
                            value                                               0.01
                    1, 31
                        sigma
  
```

**I therefore suspect that a graphcial model can output a `model.info` file in the format of analysis summing which much effort.**

Could you make it so that when a graphical model is fitted, it outputs both a `model.info` file (Which is identical the analysis summing one) and a `model.graph` file, which is the one it currently outputs.

Pull request description:
feature/graphical fixes
Resolves #1110


Patch:
diff --git a/autofit/graphical/declarative/abstract.py b/autofit/graphical/declarative/abstract.py
index a4ff3a9b8..00e7e7afa 100644
--- a/autofit/graphical/declarative/abstract.py
+++ b/autofit/graphical/declarative/abstract.py
@@ -48,11 +48,7 @@ class AbstractDeclarativeFactor(Analysis, ABC):
         A set of all priors encompassed by the contained likelihood models
         """
         return {
-            prior
-            for model
-            in self.model_factors
-            for prior
-            in model.prior_model.priors
+            prior for model in self.model_factors for prior in model.prior_model.priors
         }
 
     @property
@@ -67,8 +63,7 @@ class AbstractDeclarativeFactor(Analysis, ABC):
                 counter[prior] += 1
         return [
             (prior, count + 1 if self.include_prior_factors else count)
-            for prior, count
-            in counter.items()
+            for prior, count in counter.items()
         ]
 
     @property
@@ -91,8 +86,7 @@ class AbstractDeclarativeFactor(Analysis, ABC):
         """
         return {
             prior: prior.message ** (1 / (count - 1)) if count > 1 else prior.message
-            for prior, count
-            in self.prior_counts
+            for prior, count in self.prior_counts
         }
 
     @property
@@ -100,20 +94,13 @@ class AbstractDeclarativeFactor(Analysis, ABC):
         """
         The complete graph made by combining all factors and priors
         """
-        factors = [
-            model
-            for model
-            in self.model_factors
-        ]
+        factors = [model for model in self.model_factors]
         if self.include_prior_factors:
             factors += self.prior_factors
         # noinspection PyTypeChecker
         return DeclarativeFactorGraph(factors)
 
-    def draw_graph(
-            self,
-            **kwargs
-    ):
+    def draw_graph(self, **kwargs):
         """
         Visualise the graph.
 
@@ -128,28 +115,23 @@ class AbstractDeclarativeFactor(Analysis, ABC):
         graph = self.graph
 
         factor_labels = {
-            factor: factor.name
-            if factor.label is None
-            else factor.label
+            factor: factor.name if factor.label is None else factor.label
             for factor in graph.factors
         }
         variable_labels = {
-            variable: variable.name
-            if variable.label is None
-            else variable.label
+            variable: variable.name if variable.label is None else variable.label
             for variable in graph.all_variables
         }
 
         import matplotlib.pyplot as plt
+
         if "draw_labels" not in kwargs:
             kwargs["draw_labels"] = True
         if "variable_labels" not in kwargs:
             kwargs["variable_labels"] = variable_labels
         if "factor_labels" not in kwargs:
             kwargs["factor_labels"] = factor_labels
-        graph.draw_graph(
-            **kwargs
-        )
+        graph.draw_graph(**kwargs)
         plt.show()
         plt.close()
 
@@ -161,16 +143,13 @@ class AbstractDeclarativeFactor(Analysis, ABC):
         """
         Returns a EPMeanField of the factor graph
         """
-        return EPMeanField.from_approx_dists(
-            self.graph,
-            self.message_dict
-        )
+        return EPMeanField.from_approx_dists(self.graph, self.message_dict)
 
     def _make_ep_optimiser(
-            self,
-            optimiser: AbstractFactorOptimiser,
-            paths: Optional[AbstractPaths] = None,
-            ep_history: Optional = None,
+        self,
+        optimiser: AbstractFactorOptimiser,
+        paths: Optional[AbstractPaths] = None,
+        ep_history: Optional = None,
     ) -> EPOptimiser:
         return EPOptimiser(
             self.graph,
@@ -181,15 +160,15 @@ class AbstractDeclarativeFactor(Analysis, ABC):
                 if factor.optimiser is not None
             },
             ep_history=ep_history,
-            paths=paths
+            paths=paths,
         )
 
     def optimise(
-            self,
-            optimiser: AbstractFactorOptimiser,
-            paths: Optional[AbstractPaths] = None,
-            ep_history: Optional = None,
-            **kwargs
+        self,
+        optimiser: AbstractFactorOptimiser,
+        paths: Optional[AbstractPaths] = None,
+        ep_history: Optional = None,
+        **kwargs
     ):
         """
         Use an EP Optimiser to optimise the graph associated with this collection
@@ -209,15 +188,9 @@ class AbstractDeclarativeFactor(Analysis, ABC):
             A collection of prior models
         """
         from autofit.graphical.declarative.result import EPResult
-        opt = self._make_ep_optimiser(
-            optimiser,
-            paths=paths,
-            ep_history=ep_history
-        )
-        updated_ep_mean_field = opt.run(
-            self.mean_field_approximation(),
-            **kwargs
-        )
+
+        opt = self._make_ep_optimiser(optimiser, paths=paths, ep_history=ep_history)
+        updated_ep_mean_field = opt.run(self.mean_field_approximation(), **kwargs)
 
         return EPResult(
             ep_history=opt.ep_history,
@@ -228,10 +201,7 @@ class AbstractDeclarativeFactor(Analysis, ABC):
     # TODO : Visualize method before fit?
 
     def visualize(
-            self,
-            paths: AbstractPaths,
-            instance: ModelInstance,
-            during_analysis: bool
+        self, paths: AbstractPaths, instance: ModelInstance, during_analysis: bool
     ):
         """
         Visualise the instances provided using each factor.
@@ -247,21 +217,9 @@ class AbstractDeclarativeFactor(Analysis, ABC):
         during_analysis
             Is this visualisation during analysis?
         """
-        for model_factor, instance in zip(
-                self.model_factors,
-                instance
-        ):
-            model_factor.visualize(
-                paths,
-                instance,
-                during_analysis
-            )
-            model_factor.visualize_combined(
-                None,
-                paths,
-                instance,
-                during_analysis
-            )
+        for model_factor, instance in zip(self.model_factors, instance):
+            model_factor.visualize(paths, instance, during_analysis)
+            model_factor.visualize_combined(None, paths, instance, during_analysis)
 
     @property
     def global_prior_model(self) -> Collection:
@@ -272,10 +230,7 @@ class AbstractDeclarativeFactor(Analysis, ABC):
 
 
 class GlobalPriorModel(Collection):
-    def __init__(
-            self,
-            factor: AbstractDeclarativeFactor
-    ):
+    def __init__(self, factor: AbstractDeclarativeFactor):
         """
         A global model comprising all factors which can be used to compare
         results between global optimisation and expectation propagation.
@@ -285,15 +240,13 @@ class GlobalPriorModel(Collection):
         factor
             A factor comprising one or more factors, usually a graph
         """
-        super().__init__([
-            model_factor.prior_model
-            for model_factor
-            in factor.model_factors
-        ])
+        super().__init__(
+            [model_factor.prior_model for model_factor in factor.model_factors]
+        )
         self.factor = factor
 
     @property
-    def info(self) -> str:
+    def graph_info(self) -> str:
         """
         A string describing the collection of factors in the graphical style
         """
diff --git a/autofit/non_linear/paths/directory.py b/autofit/non_linear/paths/directory.py
index 109a2f89f..f9cef970d 100644
--- a/autofit/non_linear/paths/directory.py
+++ b/autofit/non_linear/paths/directory.py
@@ -468,6 +468,12 @@ class DirectoryPaths(AbstractPaths):
         with open_(self.output_path / "model.info", "w+") as f:
             f.write(model.info)
 
+        try:
+            with open_(self.output_path / "model.graph", "w+") as f:
+                f.write( model.graph_info)
+        except AttributeError:
+            pass
+
     def _save_model_start_point(self, info):
         """
         Save the model.start file, which summarizes the start point of every parameter.


Test patch:
diff --git a/test_autofit/graphical/global/test_global.py b/test_autofit/graphical/global/test_global.py
index 044f4e590..24e7b8760 100644
--- a/test_autofit/graphical/global/test_global.py
+++ b/test_autofit/graphical/global/test_global.py
@@ -13,7 +13,7 @@ def reset_ids():
 
 def test_info(model_factor):
     assert (
-        model_factor.global_prior_model.info
+        model_factor.global_prior_model.graph_info
         == """PriorFactors
 
 PriorFactor0 (AnalysisFactor0.one)                                                        UniformPrior [0], lower_limit = 0.0, upper_limit = 1.0
diff --git a/test_autofit/graphical/global/test_hierarchical.py b/test_autofit/graphical/global/test_hierarchical.py
index 1ab1af310..0426ab529 100644
--- a/test_autofit/graphical/global/test_hierarchical.py
+++ b/test_autofit/graphical/global/test_hierarchical.py
@@ -33,9 +33,36 @@ def reset_ids():
     af.Prior._ids = itertools.count()
 
 
-def test_info(model):
+def test_model_info(model):
     assert (
         model.info
+        == """Total Free Parameters = 4
+
+model                                                                           GlobalPriorModel (N=4)
+    0 - 1                                                                       Collection (N=3)
+        distribution_model                                                      GaussianPrior (N=2)
+    2 - 3                                                                       Collection (N=1)
+
+0 - 1
+    distribution_model
+        mean                                                                    GaussianPrior [2], mean = 0.5, sigma = 0.1
+        sigma                                                                   GaussianPrior [3], mean = 1.0, sigma = 0.01
+        lower_limit                                                             -inf
+        upper_limit                                                             inf
+0
+    drawn_prior                                                                 UniformPrior [0], lower_limit = 0.0, upper_limit = 1.0
+1
+    drawn_prior                                                                 UniformPrior [1], lower_limit = 0.0, upper_limit = 1.0
+2 - 3
+    one                                                                         UniformPrior [0], lower_limit = 0.0, upper_limit = 1.0
+factor
+    include_prior_factors                                                       True"""
+    )
+
+
+def test_graph_info(model):
+    assert (
+        model.graph_info
         == """PriorFactors
 
 PriorFactor0 (HierarchicalFactor0)                                                        GaussianPrior [3], mean = 1.0, sigma = 0.01