Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/analysis combined visualize #696

Merged
merged 16 commits into from
Apr 17, 2023
3 changes: 2 additions & 1 deletion autofit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
from .non_linear.abstract_search import NonLinearSearch
from .non_linear.abstract_search import PriorPasser
from .non_linear.analysis.analysis import Analysis
from .non_linear.analysis.combined import CombinedAnalysis
from .non_linear.grid.grid_search import GridSearchResult
from .non_linear.initializer import InitializerBall
from .non_linear.initializer import InitializerPrior
Expand Down Expand Up @@ -109,4 +110,4 @@ def save_abc(pickler, obj):

conf.instance.register(__file__)

__version__ = "2023.3.21.3"
__version__ = "2023.3.27.1"
3 changes: 3 additions & 0 deletions autofit/config/general.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ analysis:
hpc:
hpc_mode: false # If True, use HPC mode, which disables GUI visualization, logging to screen and other settings which are not suited to running on a super computer.
iterations_per_update: 5000 # The number of iterations between every update (visualization, results output, etc) in HPC mode.
inversion:
check_reconstruction: true # If True, the inversion's reconstruction is checked to ensure the solution of a meshs's mapper is not an invalid solution where the values are all the same.
reconstruction_vmax_factor: 0.5 # Plots of an Inversion's reconstruction use the reconstructed data's bright value multiplied by this factor.
model:
ignore_prior_limits: false # If ``True`` the limits applied to priors will be ignored, where limits set upper / lower limits. This stops PriorLimitException's from being raised.
output:
Expand Down
5 changes: 5 additions & 0 deletions autofit/graphical/declarative/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,11 @@ def visualize(
instance,
during_analysis
)
model_factor.visualize_combined(
paths,
instance,
during_analysis
)

@property
def global_prior_model(self) -> Collection:
Expand Down
5 changes: 5 additions & 0 deletions autofit/graphical/declarative/factor/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ def visualize(
instance,
during_analysis
)
self.analysis.visualize_combined(
paths,
instance,
during_analysis
)

def log_likelihood_function(
self,
Expand Down
4 changes: 4 additions & 0 deletions autofit/non_linear/abstract_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
FactorApproximation,
)
from autofit.graphical.utils import Status
from autofit.graphical.utils import Status
from autofit.mapper.prior_model.collection import Collection
from autofit.non_linear.initializer import Initializer
from autofit.non_linear.parallel import SneakyPool
Expand Down Expand Up @@ -768,6 +769,9 @@ def perform_update(self, model, analysis, during_analysis):
analysis.visualize(
paths=self.paths, instance=instance, during_analysis=during_analysis
)
analysis.visualize_combined(
analyses=None, paths=self.paths, instance=instance, during_analysis=during_analysis
)

if self.should_profile:
self.logger.debug("Profiling Maximum Likelihood Model")
Expand Down
3 changes: 3 additions & 0 deletions autofit/non_linear/analysis/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ def log_likelihood_function(self, instance):
def visualize(self, paths: AbstractPaths, instance, during_analysis):
pass

def visualize_combined(self, analyses, paths: AbstractPaths, instance, during_analysis):
pass

def save_attributes_for_aggregator(self, paths: AbstractPaths):
pass

Expand Down
22 changes: 22 additions & 0 deletions autofit/non_linear/analysis/combined.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,28 @@ def func(child_paths, analysis):

self._for_each_analysis(func, paths)

def visualize_combined(self, analyses : List["Analysis"], paths: AbstractPaths, instance, during_analysis):
"""
Visualise the instance using images and quantities which are shared across all analyses.

For example, each Analysis may have a different dataset, where the fit to each dataset is intended to all
be plotted on the same matplotlib subplot. This function can be overwritten to allow the visualization of such
a plot.

Only the first analysis is used to visualize the combined results, where it is assumed that it uses the
`analyses` property to access the other analyses and perform visualization.

Parameters
----------
paths
An object describing the paths for saving data (e.g. hard-disk directories or entries in sqlite database).
instance
The maximum likelihood instance of the model so far in the non-linear search.
during_analysis
Is this visualisation during analysis?
"""
self.analyses[0].visualize_combined(analyses=self.analyses, paths=paths, instance=instance, during_analysis=during_analysis)

def profile_log_likelihood_function(
self, paths: AbstractPaths, instance,
):
Expand Down
3 changes: 3 additions & 0 deletions autofit/non_linear/analysis/indexed.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ def log_likelihood_function(self, instance):
def visualize(self, paths: AbstractPaths, instance, during_analysis):
return self.analysis.visualize(paths, instance[self.index], during_analysis)

def visualize_combined(self, analyses, paths: AbstractPaths, instance, during_analysis):
return self.analysis.visualize_combined(paths, instance[self.index], during_analysis)

def profile_log_likelihood_function(self, paths: AbstractPaths, instance):
return self.profile_log_likelihood_function(paths, instance[self.index])

Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ pyprojroot==0.2.0
pyswarms==1.3.0
h5py>=2.10.0
SQLAlchemy==1.3.20
scipy>=1.5.1
scipy>=1.5.4,<=1.8.1
astunparse==1.6.3
xxhash==3.0.0
6 changes: 5 additions & 1 deletion test_autofit/config/general.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ analysis:
hpc:
hpc_mode: false # If True, use HPC mode, which disables GUI visualization, logging to screen and other settings which are not suited to running on a super computer.
iterations_per_update: 5000 # The number of iterations between every update (visualization, results output, etc) in HPC mode.
inversion:
check_reconstruction: true # If True, the inversion's reconstruction is checked to ensure the solution of a meshs's mapper is not an invalid solution where the values are all the same.
reconstruction_vmax_factor: 0.5 # Plots of an Inversion's reconstruction use the reconstructed data's bright value multiplied by this factor.
model:
ignore_prior_limits: false # If ``True`` the limits applied to priors will be ignored, where limits set upper / lower limits. This stops PriorLimitException's from being raised.
output:
Expand All @@ -21,6 +24,7 @@ profiling:
should_profile: false # If True, the ``profile_log_likelihood_function()`` function of an analysis class is called throughout a model-fit, profiling run times.
repeats: 1 # The number of repeat function calls used to measure run-times when profiling.
test:
check_preloads: false # If True, perform a sanity check that the likelihood using preloads is identical to the likelihood not using preloads.
check_preloads: false
preloads_check_threshold: 0.1 # If the figure of merit of a fit with and without preloads is greater than this threshold, the check preload test fails and an exception raised for a model-fit. # If True, perform a sanity check that the likelihood using preloads is identical to the likelihood not using preloads.
exception_override: false
parallel_profile: false
Binary file not shown.
16 changes: 16 additions & 0 deletions test_autofit/non_linear/test_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
class Analysis(af.Analysis):
def __init__(self):
self.did_visualise = False
self.did_visualise_combined = False
self.did_profile = False

def log_likelihood_function(self, instance):
Expand All @@ -23,6 +24,10 @@ def visualize(self, paths: AbstractPaths, instance, during_analysis):
os.makedirs(paths.image_path)
open(f"{paths.image_path}/image.png", "w+").close()

def visualize_combined(self, analyses, paths: AbstractPaths, instance, during_analysis):

self.did_visualise_combined = True

def profile_log_likelihood_function(self, paths: AbstractPaths, instance):
self.did_profile = True

Expand All @@ -37,6 +42,17 @@ def test_visualise():
assert analysis_2.did_visualise is True


def test_visualise_combined():
analysis_1 = Analysis()
analysis_2 = Analysis()

(analysis_1 + analysis_2).visualize_combined(af.DirectoryPaths(), None, None)

assert analysis_1.did_visualise_combined is True
assert analysis_2.did_visualise_combined is False



def test__profile_log_likelihood():
analysis_1 = Analysis()
analysis_2 = Analysis()
Expand Down