From 76c176702cdfe3e1088f01ebc62d269c1e98d55c Mon Sep 17 00:00:00 2001
From: "Joern Ungermann (IEK-7 FZ-Juelich)" <j.ungermann@fz-juelich.de>
Date: Wed, 29 Oct 2014 16:09:23 +0100
Subject: [PATCH] fixed some minor compilation bugs and updated to current
 jutil. prepared jutil reconstruction routines.

---
 pyramid/costfunction.py                 | 16 +++++++++---
 pyramid/reconstruction.py               | 34 ++++++++++++-------------
 pyramid/regularisator.py                |  4 +--
 scripts/collaborations/example_joern.py | 33 ++++++++++++++++--------
 4 files changed, 55 insertions(+), 32 deletions(-)

diff --git a/pyramid/costfunction.py b/pyramid/costfunction.py
index 04ed291..ad7c226 100644
--- a/pyramid/costfunction.py
+++ b/pyramid/costfunction.py
@@ -53,6 +53,8 @@ class Costfunction(object):
         # Extract important information:
         self.y = data_set.phase_vec
         self.Se_inv = data_set.Se_inv
+        self.n = data_set.n * 3
+        self.m = len(self.y)
         self.LOG.debug('Created '+str(self))
 
     def __repr__(self):
@@ -65,10 +67,14 @@ class Costfunction(object):
         return 'Costfunction(data_set=%s, fwd_model=%s, regularisator=%s)' % \
             (self.data_set, self.fwd_model, self.regularisator)
 
+    def init(self, x):
+        self(x)
+
     def __call__(self, x):
         self.LOG.debug('Calling __call__')
-        delta_y = self.fwd_model(x)-self.y
-        return delta_y.dot(self.Se_inv.dot(delta_y)) + self.regularisator(x)
+        delta_y = self.fwd_model(x) - self.y
+        self.chisq = delta_y.dot(self.Se_inv.dot(delta_y)) + self.regularisator(x)
+        return self.chisq
 
     def jac(self, x):
         '''Calculate the derivative of the costfunction for a given magnetization distribution.
@@ -85,7 +91,8 @@ class Costfunction(object):
 
         '''
         self.LOG.debug('Calling jac')
-        return (2 * self.fwd_model.jac_T_dot(x, self.Se_inv.dot(self.fwd_model(x)-self.y))
+        assert len(x) == self.n
+        return (2 * self.fwd_model.jac_T_dot(x, self.Se_inv.dot(self.fwd_model(x) - self.y))
                 + self.regularisator.jac(x))
 
     def hess_dot(self, x, vector):
@@ -111,6 +118,9 @@ class Costfunction(object):
         return (2 * self.fwd_model.jac_T_dot(x, self.Se_inv.dot(self.fwd_model.jac_dot(x, vector)))
                 + self.regularisator.hess_dot(x, vector))
 
+    def hess_diag(self, _):
+        return np.ones(self.n)
+
 
 class CFAdapterScipyCG(LinearOperator):
 
diff --git a/pyramid/reconstruction.py b/pyramid/reconstruction.py
index 90704d5..1eff2ea 100644
--- a/pyramid/reconstruction.py
+++ b/pyramid/reconstruction.py
@@ -83,7 +83,7 @@ class PrintIterator(object):
         return self.iteration
 
 
-def optimize_sparse_cg(data, regularisator=None, maxiter=1000, verbosity=0):
+def optimize_linear(data, regularisator=None, maxiter=1000, verbosity=0):
     '''Reconstruct a three-dimensional magnetic distribution from given phase maps via the
     conjugate gradient optimizaion method :func:`~.scipy.sparse.linalg.cg`.
 
@@ -113,22 +113,21 @@ def optimize_sparse_cg(data, regularisator=None, maxiter=1000, verbosity=0):
         The reconstructed magnetic distribution as a :class:`~.MagData` object.
 
     '''
+    import jutil
     LOG.debug('Calling optimize_sparse_cg')
     # Set up necessary objects:
-    y = data.phase_vec
     fwd_model = ForwardModel(data)
     cost = Costfunction(data, regularisator)
-    # Optimize:
-    A = CFAdapterScipyCG(cost)
-    b = fwd_model.jac_T_dot(None, y)
-    x_opt, info = cg(A, b, callback=PrintIterator(cost, verbosity), maxiter=maxiter)
+    print cost(np.zeros(cost.n))
+    x_opt = jutil.cg.conj_grad_minimize(cost)
+    print cost(x_opt)
     # Create and return fitting MagData object:
     mag_opt = MagData(data.a, np.zeros((3,)+data.dim))
     mag_opt.mag_vec = x_opt
     return mag_opt
 
 
-def optimize_cg(data, first_guess):
+def optimize_nonlin(data, first_guess=None, regularisator=None):
     '''Reconstruct a three-dimensional magnetic distribution from given phase maps via the
     conjugate gradient optimizaion method :func:`~.scipy.sparse.linalg.cg`.
 
@@ -149,19 +148,18 @@ def optimize_cg(data, first_guess):
         The reconstructed magnetic distribution as a :class:`~.MagData` object.
 
     '''
+    import jutil
     LOG.debug('Calling optimize_cg')
-    mag_0 = first_guess
+    if first_guess is None:
+        first_guess = MagData(data.a, np.zeros((3,)+data.dim))
     x_0 = first_guess.mag_vec
-    y = data.phase_vec
-    kernel = Kernel(data.a, data.dim_uv)
-    fwd_model = ForwardModel(data.projectors, kernel, data.b_0)
-    cost = Costfunction(y, fwd_model)
-    # Optimize:
-    result = minimize(cost, x_0, method='Newton-CG', jac=cost.jac, hessp=cost.hess_dot,
-                      options={'maxiter': 1000, 'disp': True})
-    # Create optimized MagData object:
+    fwd_model = ForwardModel(data)
+    cost = Costfunction(data, regularisator)
+    assert len(x_0) == cost.n, (len(x_0), cost.m, cost.n)
+    result = jutil.minimizer.minimize(cost, x_0, options={"conv_rel":1e-20}, tol={"max_iteration":1})
     x_opt = result.x
-    mag_opt = MagData(mag_0.a, np.zeros((3,)+mag_0.dim))
+    print cost(x_opt)
+    mag_opt = MagData(data.a, np.zeros((3,)+data.dim))
     mag_opt.mag_vec = x_opt
     return mag_opt
 
@@ -236,6 +234,8 @@ def optimize_simple_leastsq(phase_map, mask, b_0=1, lam=1E-4, order=0):
 
     J_DICT = [J_0, J_1]  # list of cost-functions with different regularisations
     # Reconstruct the magnetization components:
+    # TODO Use jutil.minimizer.minimize(jutil.costfunction.LeastSquaresCostFunction(J_DICT[order],
+    # ...) or a simpler frontend.
     x_rec, _ = leastsq(J_DICT[order], np.zeros(3*count))
     mag_data_rec.set_vector(x_rec, mask)
     return mag_data_rec
diff --git a/pyramid/regularisator.py b/pyramid/regularisator.py
index a7adf41..bd06648 100644
--- a/pyramid/regularisator.py
+++ b/pyramid/regularisator.py
@@ -52,7 +52,7 @@ class Regularisator(object):
     def jac(self, x):
         # TODO: Docstring!
         self.LOG.debug('Calling jac')
-        return self.lam * self.norm.jac_dot(x)
+        return self.lam * self.norm.jac(x)
 
     def hess_dot(self, x, vector):
         # TODO: Docstring!
@@ -105,7 +105,7 @@ class ZeroOrderRegularisator(Regularisator):
 
     def __init__(self, lam):
         self.LOG.debug('Calling __init__')
-        norm = jnorm.NormL2Square()
+        norm = jnorm.L2Square()
         super(ZeroOrderRegularisator, self).__init__(norm, lam)
         self.LOG.debug('Created '+str(self))
 
diff --git a/scripts/collaborations/example_joern.py b/scripts/collaborations/example_joern.py
index 7890c35..e3b1a4d 100644
--- a/scripts/collaborations/example_joern.py
+++ b/scripts/collaborations/example_joern.py
@@ -28,6 +28,7 @@ LOGGING_CONF = os.path.join(os.path.dirname(os.path.realpath(pyramid.__file__)),
 
 
 logging.config.fileConfig(LOGGING_CONF, disable_existing_loggers=False)
+logging.basicConfig(level=logging.INFO)
 ###################################################################################################
 threshold = 1
 a = 1.0  # in nm
@@ -40,12 +41,13 @@ smoothed_pictures = True
 lam = 1E-4
 order = 1
 log = True
-PATH = '../../output/joern/'
+PATH = './'
+dirname = PATH
 ###################################################################################################
 # Read in files:
 phase_map = PhaseMap.load_from_netcdf4(PATH+'phase_map.nc')
 #mask = np.genfromtxt('mask.txt', dtype=bool)
-with open(PATH+'mask.pickle') as pf:
+with open(PATH + 'mask.pickle') as pf:
     mask = pickle.load(pf)
 # Setup:
 data_set = DataSet(a, dim, b_0)
@@ -53,29 +55,40 @@ data_set.append(phase_map, SimpleProjector(dim))
 regularisator = ZeroOrderRegularisator(lam)
 # Reconstruct the magnetic distribution:
 tic = clock()
-mag_data_rec = rc.optimize_sparse_cg(data_set, regularisator, maxiter=100, verbosity=2)
+mag_data_rec1 = rc.optimize_linear(data_set, regularisator=regularisator)
+mag_data_rec = rc.optimize_nonlin(data_set, regularisator=regularisator)
 #  .optimize_simple_leastsq(phase_map, mask, b_0, lam=lam, order=order)
+
 print 'reconstruction time:', clock() - tic
 # Display the reconstructed phase map and holography image:
 phase_map_rec = pm(mag_data_rec)
-phase_map_rec.display_combined('Reconstr. Distribution', gain=gain, interpolation=inter)
+phase_map_rec.display_combined('Reconstr. Distribution', gain=gain, interpolation=inter, show=False)
+plt.savefig(dirname + "/reconstr.png")
+
 # Plot the magnetization:
-axis = (mag_data_rec*(1/mag_data_rec.magnitude.max())).quiver_plot()
+axis = (mag_data_rec*(1/mag_data_rec.magnitude.max())).quiver_plot(show=False)
 axis.set_xlim(20, 45)
 axis.set_ylim(20, 45)
+plt.savefig(dirname + "/quiver.png")
+
 # Display the Phase:
 phase_diff = phase_map_rec-phase_map
-phase_diff.display_phase('Difference')
+phase_diff.display_phase('Difference', show=False)
+plt.savefig(dirname + "/difference.png")
+
 # Get the average difference from the experimental results:
 print 'Average difference:', np.average(phase_diff.phase)
 # Plot holographic contour maps with overlayed magnetic distributions:
-axis = phase_map_rec.display_holo('Magnetization Overlay', gain=0.1, interpolation=inter)
-mag_data_rec.quiver_plot(axis=axis)
+axis = phase_map_rec.display_holo('Magnetization Overlay', gain=0.1, interpolation=inter, show=False)
+mag_data_rec.quiver_plot(axis=axis, show=False)
 axis = plt.gca()
 axis.set_xlim(20, 45)
 axis.set_ylim(20, 45)
-axis = phase_map_rec.display_holo('Magnetization Overlay', gain=0.1, interpolation=inter)
-mag_data_rec.quiver_plot(axis=axis, log=log)
+plt.savefig(dirname + "/overlay_normal.png")
+
+axis = phase_map_rec.display_holo('Magnetization Overlay', gain=0.1, interpolation=inter, show=False)
+mag_data_rec.quiver_plot(axis=axis, log=log, show=False)
 axis = plt.gca()
 axis.set_xlim(20, 45)
 axis.set_ylim(20, 45)
+plt.savefig(dirname + "/overlay_log.png")
-- 
GitLab