Commit baccf4fd authored by Philipp Arras's avatar Philipp Arras
Browse files

Add plotting for EnergyHistory

parent 06f0a797
Pipeline #75207 failed with stages
in 3 minutes and 7 seconds
......@@ -177,7 +177,8 @@ class NewtonCG(DescentMinimizer):
self._nreset = nreset
self._max_cg_iterations = max_cg_iterations
self._alpha = energy_reduction_factor
self._history = [] if activate_logging else None
from .iteration_controllers import EnergyHistory
self._history = EnergyHistory() if activate_logging else None
def get_descent_direction(self, energy, old_value=None):
if old_value is None:
......@@ -187,7 +188,7 @@ class NewtonCG(DescentMinimizer):
ic = AbsDeltaEnergyController(
ediff, iteration_limit=self._max_cg_iterations, name=self._name)
if self._history is not None:
ic.activate_logging()
ic.enable_logging()
e = QuadraticEnergy(0*energy.position, energy.metric, energy.gradient)
p = None
if self._napprox > 1:
......@@ -195,15 +196,12 @@ class NewtonCG(DescentMinimizer):
p = makeOp(approximation2endo(met, self._napprox)).inverse
e, conv = ConjugateGradient(ic, nreset=self._nreset)(e, p)
if self._history is not None:
self._history.extend(ic.pop_history())
self._history += ic.history
return -e.position
def pop_inversion_energy_history(self):
if self._history is None:
raise RuntimeError('Logging has not been enabled.')
hist = self._history
self._history = []
return hist
@property
def inversion_history(self):
return self._history
class L_BFGS(DescentMinimizer):
......
......@@ -43,7 +43,7 @@ class IterationController(metaclass=NiftyMeta):
For analyzing minimization procedures IterationControllers can log energy
values together with the respective time stamps. In order to activate this
feature `activate_and_reset_logging()` needs to be called.
feature `activate_logging()` needs to be called.
"""
CONVERGED, CONTINUE, ERROR = list(range(3))
......@@ -79,38 +79,64 @@ class IterationController(metaclass=NiftyMeta):
"""
raise NotImplementedError
def pop_history(self):
"""Returns the collected history of energy values and resets the
history afterwards.
Returns
-------
list : List of (unix timestamp, energy values) tuples
"""
def enable_logging(self):
"""Enables the logging functionality. If the log has been populated
before, it stays as it is."""
if self._history is None:
raise RuntimeError('No history was taken')
res = self._history
self._history = []
return res
self._history = EnergyHistory()
def disable_logging(self):
"""Disables the logging functionality. If the log has been populated
before, it is dropped."""
self._history = None
def activate_and_reset_logging(self):
"""Activates the logging functionality. If the log has been populated
before, it is reset."""
self._history = []
@property
def history(self):
return self._history
def activate_logging(self):
"""Activates the logging functionality. If the log has been populated
before, it stays as it is."""
if self._history is None:
self._history = []
class EnergyHistory(object):
def __init__(self):
self._lst = []
def append(self, x):
if len(x) != 2:
raise ValueError
self._lst.append((float(x[0]), float(x[1])))
def pop_all(self):
lst = self._lst
self._lst = []
return lst
@property
def timestamps(self):
return [x for x, _ in self._lst]
@property
def energy_values(self):
return [x for _, x in self._lst]
def __add__(self, other):
if not isinstance(other, EnergyHistory):
return NotImplemented
res = EnergyHistory()
res._lst = self._lst + other._lst
return res
def __iadd__(self, other):
if not isinstance(other, EnergyHistory):
return NotImplemented
self._lst += other._lst
return self
def append_history(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
if args[0]._history is not None:
energy_val = args[1].value
args[0]._history.append((time(), energy_val))
hist = args[0].history
if isinstance(hist, EnergyHistory):
hist.append((time(), args[1].value))
return func(*args, **kwargs)
return wrapper
......
......@@ -16,14 +16,17 @@
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik.
import os
from datetime import datetime as dt
import numpy as np
from matplotlib.dates import DateFormatter, date2num
from .domains.gl_space import GLSpace
from .domains.hp_space import HPSpace
from .domains.power_space import PowerSpace
from .domains.rg_space import RGSpace
from .field import Field
from .minimization.iteration_controllers import EnergyHistory
# relevant properties:
# - x/y size
......@@ -261,6 +264,38 @@ def _register_cmaps():
plt.register_cmap(cmap=LinearSegmentedColormap("Plus Minus", pm_cmap))
def _plot_history(f, ax, **kwargs):
import matplotlib.pyplot as plt
for i, fld in enumerate(f):
if not isinstance(fld, EnergyHistory):
raise TypeError
label = kwargs.pop("label", None)
if not isinstance(label, list):
label = [label] * len(f)
alpha = kwargs.pop("alpha", None)
if not isinstance(alpha, list):
alpha = [alpha] * len(f)
color = kwargs.pop("color", None)
if not isinstance(color, list):
color = [color] * len(f)
ax.set_title(kwargs.pop("title", ""))
ax.set_xlabel(kwargs.pop("xlabel", ""))
ax.set_ylabel(kwargs.pop("ylabel", ""))
plt.xscale(kwargs.pop("xscale", "linear"))
plt.yscale(kwargs.pop("yscale", "linear"))
for i, fld in enumerate(f):
xcoord = fld.timestamps
# xcoord = date2num([dt.fromtimestamp(ts) for ts in xcoord])
# xfmt = DateFormatter('%H:%M')
# ax.xaxis.set_major_formatter(xfmt)
ycoord = fld.energy_values
ax.scatter(xcoord, ycoord, label=label[i], alpha=alpha[i],
color=color[i])
_limit_xy(**kwargs)
if label != ([None]*len(f)):
plt.legend()
def _plot1D(f, ax, **kwargs):
import matplotlib.pyplot as plt
......@@ -421,11 +456,14 @@ def _plot2D(f, ax, **kwargs):
def _plot(f, ax, **kwargs):
_register_cmaps()
if isinstance(f, Field):
if isinstance(f, Field) or isinstance(f, EnergyHistory):
f = [f]
f = list(f)
if len(f) == 0:
raise ValueError("need something to plot")
if isinstance(f[0], EnergyHistory):
_plot_history(f, ax, **kwargs)
return
if not isinstance(f[0], Field):
raise TypeError("incorrect data type")
dom1 = f[0].domain
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment