From 9bb2a24692ca438279fdfc6b5c6f662642df765e Mon Sep 17 00:00:00 2001
From: Daniel Brown <ddb@star.sr.bham.ac.uk>
Date: Tue, 1 Dec 2015 16:22:42 +0000
Subject: [PATCH] first go at putting in plotting functions

---
 bin/test_plot.py                  |  13 +-
 pykat/__init__.py                 |   4 +-
 pykat/components.py               |   4 +-
 pykat/detectors.py                |   1 +
 pykat/finesse.py                  |  86 ++-
 pykat/plotting.py                 | 142 +++--
 pykat/profiling.py                |   6 +-
 pykat/tools/modematching.py       |   4 +-
 pykat/tools/plotting/beamtrace.py |   3 +-
 pykat/tools/plotting/colormap.py  | 644 ++++++++++----------
 pykat/tools/plotting/tools.py     | 974 +++++++++++++++---------------
 11 files changed, 983 insertions(+), 898 deletions(-)

diff --git a/bin/test_plot.py b/bin/test_plot.py
index 7f14ab2..2b41826 100644
--- a/bin/test_plot.py
+++ b/bin/test_plot.py
@@ -1,3 +1,6 @@
+import pykat
+pykat.init_pykat_plotting(mode="display", dpi=100)
+
 from pykat import finesse
 from pykat.detectors import *
 from pykat.components import *
@@ -5,7 +8,6 @@ from pykat.commands import *
 from pykat.structs import *
 
 import numpy as np
-import pylab as pl
 
 code = """
 l l1 1 0 0 n1 
@@ -15,10 +17,12 @@ s s2 10 1 n3 n4
 m m2 0.5 0.5 0 n4 n5
 s s3 10 1 n5 n6
 
-yaxis abs:deg
+yaxis re:im
 
+ad circ 0 0 0 n4
 pd pd_cav n3
 
+
 cav c1 m1 n3 m2 n4
 
 attr m1 Rc 1
@@ -27,7 +31,7 @@ attr m1 Rc 1
 kat = finesse.kat()
 kat.parseCommands(code)
 
-kat.add(xaxis("lin", [0, 360], kat.m2.phi, 100))
+kat.add(xaxis("lin", [0, 360], kat.m2.phi, 500))
 
 kat.m1.Rcx = -1000.0
 kat.m1.Rcy = -1000.0
@@ -37,5 +41,4 @@ kat.m2.Rcy =  1000.0
 kat.maxtem = 0
 
 out = kat.run()
-out.plot()
-
+fig = out.plot("test_plot.pdf")
diff --git a/pykat/__init__.py b/pykat/__init__.py
index 420f930..647d331 100644
--- a/pykat/__init__.py
+++ b/pykat/__init__.py
@@ -8,7 +8,9 @@ __version__ = "0.8.1"
 # This flag is used to switch on the gui features in pkat at import time
 USE_GUI = False
 HAS_OPTIVIS = False
+
 import imp
+
 try:
 	imp.find_module('optivis')
 	HAS_OPTIVIS = True
@@ -26,6 +28,6 @@ import pykat.commands as commands
 
 from pykat.optics.gaussian_beams import beam_param
 
-
+from pykat.plotting import init_pykat_plotting
 
 
diff --git a/pykat/components.py b/pykat/components.py
index 0bb6bbc..2f38226 100644
--- a/pykat/components.py
+++ b/pykat/components.py
@@ -1063,7 +1063,7 @@ class modulator(Component):
         self._requested_node_names.append(node1)
         self._requested_node_names.append(node2)
         self._svgItem = None
-        self.__f = Param("f", self, SIfloat(f))
+        self.__f = Param("f", self, SIfloat(f), canFsig=True, fsig_name="fre")
         self.__midx = Param("midx", self, SIfloat(midx))
         self.__phase = Param("phase", self, SIfloat(phase), canFsig=True, fsig_name="phase")
         self.__order = int(order)
@@ -1171,7 +1171,7 @@ class laser(Component):
         self._requested_node_names.append(node)
         
         self.__power = Param("P", self, SIfloat(P), canFsig=True, fsig_name="amp")
-        self.__f_offset = Param("f", self, SIfloat(f), canFsig=True, fsig_name="f")
+        self.__f_offset = Param("f", self, SIfloat(f), canFsig=True, fsig_name="freq")
         self.__phase = Param("phase", self, SIfloat(phase), canFsig=True, fsig_name="phase")
         self.__noise = AttrParam("noise", self, None)
         self._svgItem = None
diff --git a/pykat/detectors.py b/pykat/detectors.py
index 2628531..ec28374 100644
--- a/pykat/detectors.py
+++ b/pykat/detectors.py
@@ -65,6 +65,7 @@ class BaseDetector(object) :
         self._mask = {}
         self.__scale = []
         self.__removed = False
+        self.noplot = False
         
         self._alternate_beam = []
         self._nodes = []
diff --git a/pykat/finesse.py b/pykat/finesse.py
index 66f9567..36744be 100644
--- a/pykat/finesse.py
+++ b/pykat/finesse.py
@@ -240,13 +240,74 @@ class katRun(object):
         self.katVersion = None
         self.yaxis = None
         
-    def plot(self, logy=False):
-        import pylab
+    def plot(self, filename=None, show=True):
+        import matplotlib.pyplot as pyplot
+        import pykat.plotting as plt
+
+        kat = pykat.finesse.kat()
+        kat.verbose = False
+        kat.parseCommands(self.katScript)
+
+        plot_cmd = None
+
+        if "log" in kat.yaxis:
+            if kat.xaxis.scale == "log":
+                plot_cmd = pyplot.loglog
+            else:
+                plot_cmd = pyplot.semilogy
+        else:
+            if kat.xaxis.scale == "log":
+                plot_cmd = pyplot.semilogx
+            else:
+                plot_cmd = pyplot.plot
+
+        dual_plot = False
+
+        if ":" in kat.yaxis:
+            fig = plt.figure(width="full", height=1)
+            dual_plot = True
+        else:
+            fig = plt.figure(width="full")
+
+        for lbl in self.ylabels:
+            lbl = lbl.split()[0]
+            if not dual_plot:
+                plot_cmd(self.x, np.abs(self[lbl]))
+            else:
+                pyplot.subplot(2,1,1)
+                plot_cmd(self.x, np.abs(self[lbl]))
         
-        pylab.plot(self.x, self.y)
-        pylab.legend(self.ylabels,0)
-        pylab.xlabel(self.xlabel)
-        pylab.show()
+                pyplot.subplot(2,1,2)
+                plot_cmd(self.x, np.angle(self[lbl]))
+
+        if dual_plot:
+            pyplot.subplot(2,1,1)
+            pyplot.xlabel(self.xlabel, fontsize=pyplot.rcParams["font.size"])
+            pyplot.xlim(self.x.min(), self.x.max())
+    
+            if "abs" in kat.yaxis: pyplot.ylabel("Absolute [au]", fontsize=pyplot.rcParams["font.size"])
+            if "re" in kat.yaxis: pyplot.ylabel("Real part [au]", fontsize=pyplot.rcParams["font.size"])
+    
+            pyplot.subplot(2,1,2)
+            pyplot.xlabel(self.xlabel, fontsize=pyplot.rcParams["font.size"])
+            pyplot.xlim(self.x.min(), self.x.max())
+    
+            if "deg" in kat.yaxis: pyplot.ylabel("Phase [deg]", fontsize=pyplot.rcParams["font.size"])
+            if "im" in kat.yaxis: pyplot.ylabel("Imaginary part [au]", fontsize=pyplot.rcParams["font.size"])
+        else:
+            pyplot.xlabel(self.xlabel, fontsize=pyplot.rcParams["font.size"])
+            pyplot.ylabel(" [au]")
+            pyplot.xlim(self.x.min(), self.x.max())
+    
+        fig.tight_layout()
+        
+        if filename is not None:
+            fig.savefig(filename)
+            
+        if show:
+            pyplot.show(fig)
+        
+        return fig
         
     def savekatRun(self, filename):
         with open(filename,'w') as outfile:
@@ -916,8 +977,7 @@ class kat(object):
                     elif(first == "fsig"):
                         after_process.append((line, self.__currentTag))
                     elif(first == "noplot"):
-                        obj = line
-                        #self.__blocks[self.__currentTag].contents.append(line) 
+                        after_process.append((line, self.__currentTag))
                     else:
                         if self.verbose:
                             print ("Parsing `{0}` into pykat object not implemented yet, added as extra line.".format(line))
@@ -938,7 +998,7 @@ class kat(object):
             # components to exist first before they can be processed
             for item in after_process:
                 line = item[0]
-                first = line.split(" ",1)[0] 
+                first, rest = line.split(" ",1)
                 block = item[1]
                 
                 if first == "gauss" or first == "gauss*" or first == "gauss**":
@@ -955,6 +1015,11 @@ class kat(object):
                     
                 elif (first == "variable"):
                     self.add(pykat.commands.variable.parseFinesseText(line, self), block=block)
+                elif (first == "noplot"):
+                    if not hasattr(self, rest):
+                        raise pkex.BasePyKatException("noplot command `{0}` refers to non-existing detector".format(line))
+                        
+                    getattr(self, rest).noplot = True
                     
                 elif (first == "scale"):
                     v = line.split()
@@ -1264,7 +1329,7 @@ class kat(object):
                             err="".join((err,str(line, 'utf-8')))
 
             
-            [out,errpipe] = p.communicate()
+            [out, errpipe] = p.communicate()
 
             if six.PY2:
                 _out = str(out).split("\n")
@@ -1286,6 +1351,7 @@ class kat(object):
             # get the version number
             ix = out.find(b'build ') + 6
             ix2 = out.find(b')',ix)
+            
             r.katVersion = out[ix:ix2]
             
             r.runDateTime = datetime.datetime.now()
diff --git a/pykat/plotting.py b/pykat/plotting.py
index 7abd88c..095b734 100644
--- a/pykat/plotting.py
+++ b/pykat/plotting.py
@@ -9,79 +9,87 @@ from __future__ import division
 from __future__ import print_function
 from __future__ import unicode_literals
 
-import numpy as np
-import matplotlib
+# Should be either display (showing in windows) or paper (saving for paper/report/etc.)
+__mode__ = None
+__DPI__ = None
 
-BACKEND = 'Qt4Agg'
-matplotlib.use(BACKEND)
-
-from matplotlib import rc
-import matplotlib.pyplot as plt
-
-mainpid = -1
-
-def plot1D(run, title=""):
+def in_ipython():
+    try:
+        cfg = get_ipython() 
+        return True
+    except NameError:
+        return False
+        
+        
+def init_pykat_plotting(mode="display", dpi=100):
+    import matplotlib as mpl
     
-    rc('font', **pp.font)
-    rc('xtick',labelsize=pp.TICK_SIZE)
-    rc('ytick',labelsize=pp.TICK_SIZE)
-    rc('text', usetex=pp.USETEX)
-    rc('axes', labelsize = pp.LABEL_SIZE)
+    __DPI__ = int(dpi)
     
-    fig=plt.figure()
-    fig.set_size_inches(pp.fig_size)
-    fig.set_dpi(pp.FIG_DPI)
-        
-    ax1 = fig.add_subplot(111)
-    ax1.set_xlim(np.min(run.x),np.max(run.x))
-    traces = ax1.plot(run.x,run.y)
-    ax1.grid(pp.GRID)
+    if in_ipython():
+        from IPython.display import set_matplotlib_formats
+        set_matplotlib_formats('pdf', 'svg')
+        ipy = get_ipython()
+        ipy.magic("matplotlib inline")
     
-    ax1.set_xlabel(run.xlabel)
-    legends = run.ylabels
-    ax1.legend(traces, legends, loc=0, shadow=pp.SHADOW,prop={'size':pp.LEGEND_SIZE})
+    if mode == "display":
+        __mode__ = mode
+        
+    elif mode == "paper":
+        __mode__ = mode
+        
+        mpl.use("pgf")
+
+        pgf_with_pdflatex = {
+            "pgf.texsystem": "pdflatex",
+            "pgf.preamble": [
+                 r"\usepackage{amsmath, amssymb}",
+                 r"\usepackage{mathtools, siunitx}" ,
+                 r"\usepackage{amsmath}",
+                 r"\usepackage[utf8x]{inputenc}",
+                 r"\usepackage[T1]{fontenc}"
+                 ]
+        }
 
-    if pp.PRINT_TITLE:
-        plt.title(title)
+        mpl.rcParams.update(pgf_with_pdflatex)
+    else:
+        raise(BaseException("Plotting mode must be either 'display' or 'paper'."))
         
-    if pp.SCREEN_TITLE:
-        fig.canvas.manager.set_window_title(title)
+    mpl.rcParams.update({"figure.figsize": (6, 3.708)})
+    mpl.rcParams.update({'font.size': 11})
+    mpl.rcParams.update({'figure.dpi': __DPI__})
+    mpl.rcParams.update({'savefig.dpi': __DPI__})
+    mpl.rcParams.update({'font.family': "serif"})
+    mpl.rcParams.update({'axes.grid': True})
+    mpl.rcParams.update({'axes.axisbelow': True})
+    mpl.rcParams.update({'grid.linewidth': 0.25})
+    mpl.rcParams.update({'grid.linestyle': ":"})
+    mpl.rcParams.update({'grid.color': (0.7,0.7,0.7,1)})
+    mpl.rcParams.update({'savefig.bbox': "tight"})
+    mpl.rcParams.update({'savefig.pad_inches': 0.05})
+    mpl.rcParams.update({'xtick.labelsize': "small"})
+    mpl.rcParams.update({'ytick.labelsize': "small"})
+    mpl.rcParams.update({'axes.formatter.useoffset': False})
+
+def figure(width="full", height=0.618, textwidth=6, **kwargs):
+    """
+    Options:
+        width: 'full', 'half' (0.49*textwidth) (default: full)
+        height: relative height to width (default: 1/golden ratio = 0.618)
+        textwidth: Width of text in inches (default: 9.84252 in = 25 cm )
+    """
+    import matplotlib.pyplot as plt
+    
+    if width == "full":
+        fig_size = [textwidth, textwidth*height]
+    elif width == "half":
+        fig_size = [textwidth*0.49, textwidth*height*0.49]
     else:
-        fig.canvas.manager.set_window_title('')
+        raise(BaseException("width must be either 'full' or 'half'."))
         
-    #plt.ion()
-    plt.show()
+    fig = plt.figure(figsize=fig_size, dpi=__DPI__)
+    
+    return fig
+    
     
-class pp():
-    # set some gobal settings first
-    BACKEND = 'Qt4Agg' # matplotlib backend
-    FIG_DPI=90 # DPI of on sceen plot
-    # Some help in calculating good figure size for Latex
-    # documents. Starting with plot size in pt,
-    # get this from LaTeX using \showthe\columnwidth
-    fig_width_pt = 484.0
-    inches_per_pt = 1.0/72.27  # Convert TeX pt to inches
-    golden_mean = (np.sqrt(5)-1.0)/2.0   # Aesthetic ratio
-    fig_width = fig_width_pt*inches_per_pt  # width in inches
-    fig_height = fig_width*golden_mean      # height in inches
-    fig_size = [fig_width,fig_height]
-    # some plot options:
-    LINEWIDTH = 1 # linewidths of traces in plot
-    AA = True # antialiasing of traces
-    USETEX = False # use Latex encoding in text
-    SHADOW = False # shadow of legend box
-    GRID = True # grid on or off
-    # font sizes for normal text, tick labels and legend
-    FONT_SIZE = 10 # size of normal text
-    TICK_SIZE = 10 # size of tick labels
-    LABEL_SIZE = 10 # size of axes labels
-    LEGEND_SIZE = 10 # size of legend
-    # font family and type
-    font = {'family':'sans-serif','sans-serif':['Helvetica'],'size':FONT_SIZE}
-    DPI=300 # DPI for saving via savefig
-    # print options given to savefig command:
-    print_options = {'dpi':DPI, 'transparent':True, 'bbox_inches':'tight', 'pad_inches':0.1}
-    # for Palatino and other serif fonts use:
-    #font = {'family':'serif','serif':['Palatino']}
-    SCREEN_TITLE = True # show title on screen?
-    PRINT_TITLE = False # show title in saved file?
+    
\ No newline at end of file
diff --git a/pykat/profiling.py b/pykat/profiling.py
index 4d1a7b9..f0b43bf 100644
--- a/pykat/profiling.py
+++ b/pykat/profiling.py
@@ -3,10 +3,10 @@ from __future__ import division
 from __future__ import print_function
 from __future__ import unicode_literals
 
-import numpy as np
-import pylab as pl
-
 def plotReducedPerformanceData(perfdata, ordered=False):
+    import numpy as np
+    import pylab as pl
+    
     labels = []
     times = []
 
diff --git a/pykat/tools/modematching.py b/pykat/tools/modematching.py
index e14483a..b089b2a 100644
--- a/pykat/tools/modematching.py
+++ b/pykat/tools/modematching.py
@@ -1,4 +1,4 @@
-import pylab as pl
+#import pylab as pl # removed by DDB 1/12/2015
 import scipy.optimize as opt
 from pykat import finesse
 from pykat.detectors import *
@@ -7,7 +7,7 @@ from pykat.commands import *
 from pykat.structs import *
 from numpy import *
 # from modematch import modematch
-import pykat.utilities.optics.ABCD as abcd
+import pykat.optics.ABCD as abcd
 import time
 
 
diff --git a/pykat/tools/plotting/beamtrace.py b/pykat/tools/plotting/beamtrace.py
index 6f9f3c9..dc99be3 100644
--- a/pykat/tools/plotting/beamtrace.py
+++ b/pykat/tools/plotting/beamtrace.py
@@ -2,9 +2,10 @@ import pykat
 import pykat.exceptions as pkex
 import copy
 import numpy as np
-import pylab
 
 def plot_beam_trace(_kat, from_node, to_node):
+    import pylab
+    
     if _kat == None:
         raise pkex.BasePyKatException('kat object in None')
 
diff --git a/pykat/tools/plotting/colormap.py b/pykat/tools/plotting/colormap.py
index 03d4f39..bc312d6 100644
--- a/pykat/tools/plotting/colormap.py
+++ b/pykat/tools/plotting/colormap.py
@@ -1,322 +1,322 @@
-
-import numpy as np
-import matplotlib
-from matplotlib import rc
-import matplotlib.pyplot as plt
-
-# =============================================================================
-# ====================== The Class ColorMapCreator ============================
-# =============================================================================
-
-class CM:
-    """
-    Class ColorMapCreator:
-    Create diverging colormaps from RGB1 to RGB2 using the method of Moreland
-    or a simple CIELAB-interpolation. numColors controls the number of color
-    values to output (odd number) and divide gives the possibility to output
-    RGB-values from 0.0-1.0 instead of 0-255. If a filename different than
-    "" is given, the colormap will be saved to this file, otherwise a simple
-    output using print will be given.
-    """
-
-    # ======================== Global Variables ===============================
-
-    # Reference white-point D65
-    Xn, Yn, Zn = [95.047, 100.0, 108.883] # from Adobe Cookbook
-
-    # Transfer-matrix for the conversion of RGB to XYZ color space
-    transM = np.array([[0.4124564, 0.2126729, 0.0193339], 
-                        [0.3575761, 0.7151522, 0.1191920],
-                        [0.1804375, 0.0721750, 0.9503041]])
-
-
-    # ============================= Functions =================================
-
-
-    def __init__(self, RGB1, RGB2, numColors = 257., divide = 255., 
-                  method = "moreland", filename = ""):
-        
-        # create a class variable for the number of colors
-        self.numColors = numColors
-        
-        # assert an odd number of points
-        assert np.mod(numColors,2) == 1, \
-            "For diverging colormaps odd numbers of colors are desireable!"
-        
-        # assert a known method was specified
-        knownMethods = ["moreland", "lab"]
-        assert method in knownMethods, "Unknown method was specified!"
-        
-        if method == knownMethods[0]:
-            #generate the Msh diverging colormap
-            self.colorMap = self.generateColorMap(RGB1, RGB2, divide)
-        elif method == knownMethods[1]:
-            # generate the Lab diverging colormap
-            self.colorMap = self.generateColorMapLab(RGB1, RGB2, divide)
-
-    def getMap(self):
-        return self.colorMap
-
-    def showMap(self):
-        #rc('text', usetex=False)
-        a=np.outer(np.arange(0,1,0.01),np.ones(10))
-        fig=plt.figure(99,figsize=(10,2))
-        plt.axis("off")
-        cm = matplotlib.colors.ListedColormap(self.colorMap)
-        pm=plt.imshow(a,aspect='auto',cmap=cm,origin="lower")
-        plt.clim(0,1)
-        fig.colorbar(pm)
-        plt.draw()
-
-        
-    def rgblinear(self, RGB):
-        """
-        Conversion from the sRGB components to RGB components with physically
-        linear properties.
-        """
-        
-        # initialize the linear RGB array
-        RGBlinear = np.zeros((3,)) 
-        
-        #  calculate the linear RGB values
-        for i,value in enumerate(RGB):
-            value = float(value) / 255.
-            if value > 0.04045 :
-                value = ( ( value + 0.055 ) / 1.055 ) ** 2.4
-            else :
-                value = value / 12.92
-            RGBlinear[i] = value * 100.
-        return RGBlinear
-    #-
-
-    def sRGB(self, RGBlinear):
-        """
-        Back conversion from linear RGB to sRGB.
-        """
-        
-        # initialize the sRGB array
-        RGB = np.zeros((3,))
-        
-        #  calculate the sRGB values
-        for i,value in enumerate(RGBlinear):
-            value = float(value) / 100.
-
-            if value > 0.00313080495356037152:
-                value = (1.055 * np.power(value,1./2.4) ) - 0.055
-            else :
-                value = value * 12.92
-
-            RGB[i] = round(value * 255.)
-        return RGB
-    #-
-
-    def rgb2xyz(self, RGB):
-        """
-        Conversion of RGB to XYZ using the transfer-matrix
-        """
-        return np.dot(self.rgblinear(RGB), self.transM)
-    #-
-
-    def xyz2rgb(self, XYZ):
-        """
-        Conversion of RGB to XYZ using the transfer-matrix
-        """
-        #return np.round(np.dot(XYZ, np.array(np.matrix(transM).I)))
-        return self.sRGB(np.dot(XYZ, np.array(np.matrix(self.transM).I)))
-    #-
-
-    def rgb2Lab(self, RGB):
-        """
-        Conversion of RGB to CIELAB
-        """
-        
-        # convert RGB to XYZ
-        X, Y, Z = (self.rgb2xyz(RGB)).tolist()
-        
-        # helper function
-        def f(x):
-            limit = 0.008856
-            if x> limit:
-                return np.power(x, 1./3.)
-            else:
-                return 7.787*x + 16./116.
-        
-        # calculation of L, a and b
-        L = 116. * ( f(Y/self.Yn) - (16./116.) )
-        a = 500. * ( f(X/self.Xn) - f(Y/self.Yn) )
-        b = 200. * ( f(Y/self.Yn) - f(Z/self.Zn) )
-        return np.array([L, a, b])
-    #-
-
-    def Lab2rgb(self, Lab):
-        """
-        Conversion of CIELAB to RGB
-        """
-        
-        # unpack the Lab-array
-        L, a, b = Lab.tolist()
-        
-        # helper function
-        def finverse(x):
-            xlim = 0.008856
-            a = 7.787
-            b = 16./116.
-            ylim = a*xlim+b
-            if x > ylim:
-                return np.power(x, 3)
-            else:
-                return ( x - b ) / a
-            
-        # calculation of X, Y and Z
-        X = self.Xn * finverse( (a/500.) + (L+16.)/116. )
-        Y = self.Yn * finverse( (L+16.)/116. )
-        Z = self.Zn * finverse( (L+16.)/116. - (b/200.) )
-        
-        # conversion of XYZ to RGB
-        return self.xyz2rgb(np.array([X,Y,Z]))
-    #-
-
-    def Lab2Msh(self, Lab):
-        """
-        Conversion of CIELAB to Msh
-        """
-
-        # unpack the Lab-array
-        L, a, b = Lab.tolist()
-
-        # calculation of M, s and h
-        M = np.sqrt(np.sum(np.power(Lab, 2)))
-        s = np.arccos(L/M)
-        h = np.arctan2(b,a)
-        return np.array([M,s,h])
-    #-
-
-    def Msh2Lab(self, Msh):
-        """
-        Conversion of Msh to CIELAB
-        """
-
-        # unpack the Msh-array
-        M, s, h = Msh.tolist()
-
-        # calculation of L, a and b
-        L = M*np.cos(s)
-        a = M*np.sin(s)*np.cos(h)
-        b = M*np.sin(s)*np.sin(h)
-        return np.array([L,a,b])
-    #-
-
-    def rgb2Msh(self, RGB):
-        """ Direct conversion of RGB to Msh. """
-        return self.Lab2Msh(self.rgb2Lab(RGB))
-    #-
-
-    def Msh2rgb(self, Msh):
-        """ Direct conversion of Msh to RGB. """
-        return self.Lab2rgb(self.Msh2Lab(Msh))
-    #-
-
-    def adjustHue(self, MshSat, Munsat):
-        """
-        Function to provide an adjusted hue when interpolating to an 
-        unsaturated color in Msh space.
-        """
-        
-        # unpack the saturated Msh-array
-        Msat, ssat, hsat = MshSat.tolist()
-        
-        if Msat >= Munsat:
-            return hsat
-        else:
-            hSpin = ssat * np.sqrt(Munsat**2 - Msat**2) / \
-                    (Msat * np.sin(ssat))
-            if hsat > -np.pi/3:
-                return hsat + hSpin
-            else:
-                return hsat - hSpin
-    #-
-
-    def interpolateColor(self, RGB1, RGB2, interp):
-        """
-        Interpolation algorithm to automatically create continuous diverging
-        color maps.
-        """
-        
-        # convert RGB to Msh and unpack
-        Msh1 = self.rgb2Msh(RGB1)
-        M1, s1, h1 = Msh1.tolist()
-        Msh2 = self.rgb2Msh(RGB2)
-        M2, s2, h2 = Msh2.tolist()
-        
-        # If points saturated and distinct, place white in middle
-        if (s1>0.05) and (s2>0.05) and ( np.abs(h1-h2) > np.pi/3. ):
-            Mmid = max([M1, M2, 88.])
-            if interp < 0.5:
-                M2 = Mmid
-                s2 = 0.
-                h2 = 0.
-                interp = 2*interp
-            else:
-                M1 = Mmid
-                s1 = 0.
-                h1 = 0.
-                interp = 2*interp-1.
-                
-        # Adjust hue of unsaturated colors
-        if (s1 < 0.05) and (s2 > 0.05):
-            h1 = self.adjustHue(np.array([M2,s2,h2]), M1)
-        elif (s2 < 0.05) and (s1 > 0.05):
-            h2 = self.adjustHue(np.array([M1,s1,h1]), M2)
-            
-        # Linear interpolation on adjusted control points
-        MshMid = (1-interp)*np.array([M1,s1,h1]) + \
-                 interp*np.array([M2,s2,h2])
-        
-        return self.Msh2rgb(MshMid)
-    #-
-
-    def generateColorMap(self, RGB1, RGB2, divide):
-        """
-        Generate the complete diverging color map using the Moreland-technique
-        from RGB1 to RGB2, placing "white" in the middle. The number of points
-        given by "numPoints" controls the resolution of the colormap. The 
-        optional parameter "divide" gives the possibility to scale the whole
-        colormap, for example to have float values from 0 to 1.
-        """
-        
-        # calculate
-        scalars = np.linspace(0., 1., self.numColors)
-        RGBs = np.zeros((self.numColors, 3))
-        for i,s in enumerate(scalars):
-            RGBs[i,:] = self.interpolateColor(RGB1, RGB2, s)
-        return RGBs/divide
-    #-
-
-    def generateColorMapLab(self, RGB1, RGB2, divide):
-        """
-        Generate the complete diverging color map using a transition from
-        Lab1 to Lab2, transitioning true RGB-white. The number of points
-        given by "numPoints" controls the resolution of the colormap. The 
-        optional parameter "divide" gives the possibility to scale the whole
-        colormap, for example to have float values from 0 to 1.
-        """
-        
-        # convert to Lab-space
-        Lab1 = self.rgb2Lab(RGB1)
-        Lab2 = self.rgb2Lab(RGB2)
-        LabWhite = np.array([100., 0., 0.])
-        
-        # initialize the resulting arrays
-        Lab = np.zeros((self.numColors ,3))
-        RGBs = np.zeros((self.numColors ,3))
-        N2 = np.floor(self.numColors/2.)
-        
-        # calculate
-        for i in range(3):
-            Lab[0:N2+1, i] = np.linspace(Lab1[i], LabWhite[i], N2+1)
-            Lab[N2:, i] = np.linspace(LabWhite[i], Lab2[i], N2+1)
-        for i,l in enumerate(Lab):
-            RGBs[i,:] = self.Lab2rgb(l)
-        return RGBs/divide
-    #-
-
+#
+# import numpy as np
+# import matplotlib
+# from matplotlib import rc
+# import matplotlib.pyplot as plt
+#
+# # =============================================================================
+# # ====================== The Class ColorMapCreator ============================
+# # =============================================================================
+#
+# class CM:
+#     """
+#     Class ColorMapCreator:
+#     Create diverging colormaps from RGB1 to RGB2 using the method of Moreland
+#     or a simple CIELAB-interpolation. numColors controls the number of color
+#     values to output (odd number) and divide gives the possibility to output
+#     RGB-values from 0.0-1.0 instead of 0-255. If a filename different than
+#     "" is given, the colormap will be saved to this file, otherwise a simple
+#     output using print will be given.
+#     """
+#
+#     # ======================== Global Variables ===============================
+#
+#     # Reference white-point D65
+#     Xn, Yn, Zn = [95.047, 100.0, 108.883] # from Adobe Cookbook
+#
+#     # Transfer-matrix for the conversion of RGB to XYZ color space
+#     transM = np.array([[0.4124564, 0.2126729, 0.0193339],
+#                         [0.3575761, 0.7151522, 0.1191920],
+#                         [0.1804375, 0.0721750, 0.9503041]])
+#
+#
+#     # ============================= Functions =================================
+#
+#
+#     def __init__(self, RGB1, RGB2, numColors = 257., divide = 255.,
+#                   method = "moreland", filename = ""):
+#
+#         # create a class variable for the number of colors
+#         self.numColors = numColors
+#
+#         # assert an odd number of points
+#         assert np.mod(numColors,2) == 1, \
+#             "For diverging colormaps odd numbers of colors are desireable!"
+#
+#         # assert a known method was specified
+#         knownMethods = ["moreland", "lab"]
+#         assert method in knownMethods, "Unknown method was specified!"
+#
+#         if method == knownMethods[0]:
+#             #generate the Msh diverging colormap
+#             self.colorMap = self.generateColorMap(RGB1, RGB2, divide)
+#         elif method == knownMethods[1]:
+#             # generate the Lab diverging colormap
+#             self.colorMap = self.generateColorMapLab(RGB1, RGB2, divide)
+#
+#     def getMap(self):
+#         return self.colorMap
+#
+#     def showMap(self):
+#         #rc('text', usetex=False)
+#         a=np.outer(np.arange(0,1,0.01),np.ones(10))
+#         fig=plt.figure(99,figsize=(10,2))
+#         plt.axis("off")
+#         cm = matplotlib.colors.ListedColormap(self.colorMap)
+#         pm=plt.imshow(a,aspect='auto',cmap=cm,origin="lower")
+#         plt.clim(0,1)
+#         fig.colorbar(pm)
+#         plt.draw()
+#
+#
+#     def rgblinear(self, RGB):
+#         """
+#         Conversion from the sRGB components to RGB components with physically
+#         linear properties.
+#         """
+#
+#         # initialize the linear RGB array
+#         RGBlinear = np.zeros((3,))
+#
+#         #  calculate the linear RGB values
+#         for i,value in enumerate(RGB):
+#             value = float(value) / 255.
+#             if value > 0.04045 :
+#                 value = ( ( value + 0.055 ) / 1.055 ) ** 2.4
+#             else :
+#                 value = value / 12.92
+#             RGBlinear[i] = value * 100.
+#         return RGBlinear
+#     #-
+#
+#     def sRGB(self, RGBlinear):
+#         """
+#         Back conversion from linear RGB to sRGB.
+#         """
+#
+#         # initialize the sRGB array
+#         RGB = np.zeros((3,))
+#
+#         #  calculate the sRGB values
+#         for i,value in enumerate(RGBlinear):
+#             value = float(value) / 100.
+#
+#             if value > 0.00313080495356037152:
+#                 value = (1.055 * np.power(value,1./2.4) ) - 0.055
+#             else :
+#                 value = value * 12.92
+#
+#             RGB[i] = round(value * 255.)
+#         return RGB
+#     #-
+#
+#     def rgb2xyz(self, RGB):
+#         """
+#         Conversion of RGB to XYZ using the transfer-matrix
+#         """
+#         return np.dot(self.rgblinear(RGB), self.transM)
+#     #-
+#
+#     def xyz2rgb(self, XYZ):
+#         """
+#         Conversion of RGB to XYZ using the transfer-matrix
+#         """
+#         #return np.round(np.dot(XYZ, np.array(np.matrix(transM).I)))
+#         return self.sRGB(np.dot(XYZ, np.array(np.matrix(self.transM).I)))
+#     #-
+#
+#     def rgb2Lab(self, RGB):
+#         """
+#         Conversion of RGB to CIELAB
+#         """
+#
+#         # convert RGB to XYZ
+#         X, Y, Z = (self.rgb2xyz(RGB)).tolist()
+#
+#         # helper function
+#         def f(x):
+#             limit = 0.008856
+#             if x> limit:
+#                 return np.power(x, 1./3.)
+#             else:
+#                 return 7.787*x + 16./116.
+#
+#         # calculation of L, a and b
+#         L = 116. * ( f(Y/self.Yn) - (16./116.) )
+#         a = 500. * ( f(X/self.Xn) - f(Y/self.Yn) )
+#         b = 200. * ( f(Y/self.Yn) - f(Z/self.Zn) )
+#         return np.array([L, a, b])
+#     #-
+#
+#     def Lab2rgb(self, Lab):
+#         """
+#         Conversion of CIELAB to RGB
+#         """
+#
+#         # unpack the Lab-array
+#         L, a, b = Lab.tolist()
+#
+#         # helper function
+#         def finverse(x):
+#             xlim = 0.008856
+#             a = 7.787
+#             b = 16./116.
+#             ylim = a*xlim+b
+#             if x > ylim:
+#                 return np.power(x, 3)
+#             else:
+#                 return ( x - b ) / a
+#
+#         # calculation of X, Y and Z
+#         X = self.Xn * finverse( (a/500.) + (L+16.)/116. )
+#         Y = self.Yn * finverse( (L+16.)/116. )
+#         Z = self.Zn * finverse( (L+16.)/116. - (b/200.) )
+#
+#         # conversion of XYZ to RGB
+#         return self.xyz2rgb(np.array([X,Y,Z]))
+#     #-
+#
+#     def Lab2Msh(self, Lab):
+#         """
+#         Conversion of CIELAB to Msh
+#         """
+#
+#         # unpack the Lab-array
+#         L, a, b = Lab.tolist()
+#
+#         # calculation of M, s and h
+#         M = np.sqrt(np.sum(np.power(Lab, 2)))
+#         s = np.arccos(L/M)
+#         h = np.arctan2(b,a)
+#         return np.array([M,s,h])
+#     #-
+#
+#     def Msh2Lab(self, Msh):
+#         """
+#         Conversion of Msh to CIELAB
+#         """
+#
+#         # unpack the Msh-array
+#         M, s, h = Msh.tolist()
+#
+#         # calculation of L, a and b
+#         L = M*np.cos(s)
+#         a = M*np.sin(s)*np.cos(h)
+#         b = M*np.sin(s)*np.sin(h)
+#         return np.array([L,a,b])
+#     #-
+#
+#     def rgb2Msh(self, RGB):
+#         """ Direct conversion of RGB to Msh. """
+#         return self.Lab2Msh(self.rgb2Lab(RGB))
+#     #-
+#
+#     def Msh2rgb(self, Msh):
+#         """ Direct conversion of Msh to RGB. """
+#         return self.Lab2rgb(self.Msh2Lab(Msh))
+#     #-
+#
+#     def adjustHue(self, MshSat, Munsat):
+#         """
+#         Function to provide an adjusted hue when interpolating to an
+#         unsaturated color in Msh space.
+#         """
+#
+#         # unpack the saturated Msh-array
+#         Msat, ssat, hsat = MshSat.tolist()
+#
+#         if Msat >= Munsat:
+#             return hsat
+#         else:
+#             hSpin = ssat * np.sqrt(Munsat**2 - Msat**2) / \
+#                     (Msat * np.sin(ssat))
+#             if hsat > -np.pi/3:
+#                 return hsat + hSpin
+#             else:
+#                 return hsat - hSpin
+#     #-
+#
+#     def interpolateColor(self, RGB1, RGB2, interp):
+#         """
+#         Interpolation algorithm to automatically create continuous diverging
+#         color maps.
+#         """
+#
+#         # convert RGB to Msh and unpack
+#         Msh1 = self.rgb2Msh(RGB1)
+#         M1, s1, h1 = Msh1.tolist()
+#         Msh2 = self.rgb2Msh(RGB2)
+#         M2, s2, h2 = Msh2.tolist()
+#
+#         # If points saturated and distinct, place white in middle
+#         if (s1>0.05) and (s2>0.05) and ( np.abs(h1-h2) > np.pi/3. ):
+#             Mmid = max([M1, M2, 88.])
+#             if interp < 0.5:
+#                 M2 = Mmid
+#                 s2 = 0.
+#                 h2 = 0.
+#                 interp = 2*interp
+#             else:
+#                 M1 = Mmid
+#                 s1 = 0.
+#                 h1 = 0.
+#                 interp = 2*interp-1.
+#
+#         # Adjust hue of unsaturated colors
+#         if (s1 < 0.05) and (s2 > 0.05):
+#             h1 = self.adjustHue(np.array([M2,s2,h2]), M1)
+#         elif (s2 < 0.05) and (s1 > 0.05):
+#             h2 = self.adjustHue(np.array([M1,s1,h1]), M2)
+#
+#         # Linear interpolation on adjusted control points
+#         MshMid = (1-interp)*np.array([M1,s1,h1]) + \
+#                  interp*np.array([M2,s2,h2])
+#
+#         return self.Msh2rgb(MshMid)
+#     #-
+#
+#     def generateColorMap(self, RGB1, RGB2, divide):
+#         """
+#         Generate the complete diverging color map using the Moreland-technique
+#         from RGB1 to RGB2, placing "white" in the middle. The number of points
+#         given by "numPoints" controls the resolution of the colormap. The
+#         optional parameter "divide" gives the possibility to scale the whole
+#         colormap, for example to have float values from 0 to 1.
+#         """
+#
+#         # calculate
+#         scalars = np.linspace(0., 1., self.numColors)
+#         RGBs = np.zeros((self.numColors, 3))
+#         for i,s in enumerate(scalars):
+#             RGBs[i,:] = self.interpolateColor(RGB1, RGB2, s)
+#         return RGBs/divide
+#     #-
+#
+#     def generateColorMapLab(self, RGB1, RGB2, divide):
+#         """
+#         Generate the complete diverging color map using a transition from
+#         Lab1 to Lab2, transitioning true RGB-white. The number of points
+#         given by "numPoints" controls the resolution of the colormap. The
+#         optional parameter "divide" gives the possibility to scale the whole
+#         colormap, for example to have float values from 0 to 1.
+#         """
+#
+#         # convert to Lab-space
+#         Lab1 = self.rgb2Lab(RGB1)
+#         Lab2 = self.rgb2Lab(RGB2)
+#         LabWhite = np.array([100., 0., 0.])
+#
+#         # initialize the resulting arrays
+#         Lab = np.zeros((self.numColors ,3))
+#         RGBs = np.zeros((self.numColors ,3))
+#         N2 = np.floor(self.numColors/2.)
+#
+#         # calculate
+#         for i in range(3):
+#             Lab[0:N2+1, i] = np.linspace(Lab1[i], LabWhite[i], N2+1)
+#             Lab[N2:, i] = np.linspace(LabWhite[i], Lab2[i], N2+1)
+#         for i,l in enumerate(Lab):
+#             RGBs[i,:] = self.Lab2rgb(l)
+#         return RGBs/divide
+#     #-
+#
diff --git a/pykat/tools/plotting/tools.py b/pykat/tools/plotting/tools.py
index 2ddd950..74d6ee8 100644
--- a/pykat/tools/plotting/tools.py
+++ b/pykat/tools/plotting/tools.py
@@ -1,485 +1,489 @@
-# ------------------------------------------------------
-# This file is very much in flux at the moment and will 
-# undergo many significant changes without notice.
-# Don't use this for anything but playing/testing yet.
-# Andreas 06.03.2014
-# ------------------------------------------------------
-
-import numpy as np
-import matplotlib
-import matplotlib.backends.backend_pdf
-from matplotlib import cm
-BACKEND = 'Qt4Agg'
-matplotlib.use(BACKEND)
-from matplotlib import rc
-import matplotlib.pyplot as plt
-
-formatter = matplotlib.ticker.EngFormatter(unit='', places=0)
-formatter.ENG_PREFIXES[-6] = 'u'
-
-
-def argmaxM(data):
-	return(np.unravel_index(np.argmax(data),data.shape))
-
-
-def printPDF(fig, filename):
-	if filename !='' and filename != None:
-		if not filename.lower().endswith(('.pdf')):
-			filename=filename+'.pdf'
-		pdfp = matplotlib.backends.backend_pdf.PdfPages(filename)
-		pdfp.savefig(fig, dpi=300,bbox_inches='tight')
-		pdfp.close()
-
-def plot_field(field):
-	ax,fig=plot_setup()
-	im = ax.imshow(np.abs(field),origin='lower', aspect='auto')
-	cb = fig.colorbar(im, format="%.4g")
-	#cb.set_clim(-1.0*zlimit, zlimit) 
-	ax.autoscale(False)
-	plt.show(block=0)
-
-def plot_propagation(field, grid, Lambda, axis, normalise, Lrange, nr):
-	# axis = 0 for x and =1 for y crosssection
-	# if normalise = 1, each slice is normalises to peak intensity
-	[n,m]=field.shape
-	slices = np.zeros((n,np.size(Lrange)))
-	from pykat.optics.fft import FFT_propagate
-	for idx, L in enumerate(Lrange):
-		field2 = FFT_propagate(field,grid, Lambda, L, nr)
-		if axis==0:
-			slices[:,idx]=np.abs(field2[:,int(m/2)])**2
-		else:
-			slices[:,idx]=np.abs(field2[int(n/2),:])**2
-		if normalise==1:
-			peak_intensity= np.abs(field2[int(n/2),int(m/2)])**2
-			slices[:,idx]=slices[:,idx]/peak_intensity
-	ax,fig=plot_setup()
-	im = ax.imshow(slices, aspect='auto')
-	cb = fig.colorbar(im, format="%.4g")
-	#cb.set_clim(-1.0*zlimit, zlimit) 
-	ax.autoscale(False)
-	plt.show(block=0)
-
-			
-def plot_power_contour(x,y,z,xlabel, ylabel, clabel, title='', filename=''):
-	ax,fig=plot_setup()
-	xm,ym=np.meshgrid(x,y)
-	extent = [x[0], x[-1], y[0], y[-1]]
-	mycm='YlOrRd_r'
-	#mycm='hot'
-	#im = ax.imshow(z,origin='lower',extent=extent,cmap=mycm, aspect='auto', interpolation='nearest')
-	im = ax.imshow(z,origin='lower',extent=extent,cmap=mycm, aspect='auto')
-	#im = ax.imshow(z,origin='lower',cmap=mycm, aspect='auto')
-	cb = fig.colorbar(im, format="%.4g")
-	#cb.set_clim(-1.0*zlimit, zlimit) 
-	ax.autoscale(False)
-	#ct = ax.contour(xm,ym,z, zdir='z', levels = [0])
-	#ax.clabel(ct,inline=1,fontsize=10)
-	ax.set_xlabel(xlabel)
-	ax.set_ylabel(ylabel)
-	cb.set_label(clabel)
-	ax.xaxis.set_major_formatter(formatter)
-	ax.yaxis.set_major_formatter(formatter)
-	fig.canvas.manager.set_window_title(title)
-	plt.show(block=0)
-	printPDF(fig, filename)
-
-
-	
-def plot_error_contour(x,y,z,xlabel, ylabel, clabel, title='', filename=''):
-	global fig, ax, cb, ct, data
-	rc('font',**pp.font)
-	rc('xtick',labelsize=pp.TICK_SIZE)
-	rc('ytick',labelsize=pp.TICK_SIZE)
-	rc('text', usetex=pp.USETEX)
-	rc('axes', labelsize = pp.LABEL_SIZE)
-	fig, ax =plt.subplots()
-	fig.set_size_inches(pp.fig_size)
-	fig.set_dpi(pp.FIG_DPI)
-	xm,ym=np.meshgrid(x,y)
-	RGB1 = 255*np.array([0.23, 0.299, 0.754])
-	RGB2 = 255*np.array([0.706,0.016, 0.15])
-	cm1 = CM(RGB1, RGB2)
-	cm_values = cm1.getMap()
-	#cm1.showMap()
-	mycm = matplotlib.colors.ListedColormap(cm_values)
-	extent = [x[0], x[-1], y[0], y[-1] ]
-	data=z
-	# make symmetric color display
-	zlimit=np.max([abs(data.max()),abs(data.min())])
-	im = ax.imshow(data,origin='lower',extent=extent,cmap=mycm, aspect='auto', interpolation='nearest')
-	#im = ax.imshow(data,origin='lower',extent=extent,cmap=mycm, aspect='auto')
-	cb = fig.colorbar(im, format="%.4g")
-	cb.set_clim(-1.0*zlimit, zlimit) 
-	ax.autoscale(False)
-	ct = ax.contour(xm,ym,data, zdir='z', levels = [0])
-	ax.clabel(ct,inline=1,fontsize=10)
-	ax.set_xlabel(xlabel)
-	ax.set_ylabel(ylabel)
-	cb.set_label(clabel)
-	ax.xaxis.set_major_formatter(formatter)
-	fig.canvas.manager.set_window_title(title)
-	plt.show()
-	printPDF(fig, filename)
-
-def plot_setup():
-	rc('font',**pp.font)
-	rc('xtick',labelsize=pp.TICK_SIZE)
-	rc('ytick',labelsize=pp.TICK_SIZE)
-	rc('text', usetex=pp.USETEX)
-	rc('axes', labelsize = pp.LABEL_SIZE)
-	fig, ax =plt.subplots()
-	fig.set_size_inches(pp.fig_size)
-	fig.set_dpi(pp.FIG_DPI)
-	return ax,fig
-
-class pp():
-	# set some gobal settings first
-	BACKEND = 'Qt4Agg' # matplotlib backend
-	FIG_DPI=90 # DPI of on sceen plot
-	# Some help in calculating good figure size for Latex
-	# documents. Starting with plot size in pt,
-	# get this from LaTeX using \showthe\columnwidth
-	fig_width_pt = 484.0
-	inches_per_pt = 1.0/72.27  # Convert TeX pt to inches
-	golden_mean = (np.sqrt(5)-1.0)/2.0   # Aesthetic ratio
-	fig_width = fig_width_pt*inches_per_pt  # width in inches
-	fig_height = fig_width*golden_mean      # height in inches
-	fig_size = [fig_width,fig_height]
-	# some plot options:
-	LINEWIDTH = 1 # linewidths of traces in plot
-	AA = True # antialiasing of traces
-	USETEX = False # use Latex encoding in text
-	SHADOW = False # shadow of legend box
-	GRID = True # grid on or off
-	# font sizes for normal text, tick labels and legend
-	FONT_SIZE = 10 # size of normal text
-	TICK_SIZE = 10 # size of tick labels
-	LABEL_SIZE = 10 # size of axes labels
-	LEGEND_SIZE = 10 # size of legend
-	# font family and type
-	font = {'family':'sans-serif','sans-serif':['Helvetica'],'size':FONT_SIZE}
-	DPI=300 # DPI for saving via savefig
-	# print options given to savefig command:
-	print_options = {'dpi':DPI, 'transparent':True, 'bbox_inches':'tight', 'pad_inches':0.1}
-	# for Palatino and other serif fonts use:
-	#font = {'family':'serif','serif':['Palatino']}
-	SCREEN_TITLE = True # show title on screen?
-	PRINT_TITLE = False # show title in saved file?
-        
-# =============================================================================
-# ====================== The Class ColorMapCreator ============================
-# =============================================================================
-
-class CM:
-    """
-    Class ColorMapCreator:
-    Create diverging colormaps from RGB1 to RGB2 using the method of Moreland
-    or a simple CIELAB-interpolation. numColors controls the number of color
-    values to output (odd number) and divide gives the possibility to output
-    RGB-values from 0.0-1.0 instead of 0-255. If a filename different than
-    "" is given, the colormap will be saved to this file, otherwise a simple
-    output using print will be given.
-    """
-
-    # ======================== Global Variables ===============================
-
-    # Reference white-point D65
-    Xn, Yn, Zn = [95.047, 100.0, 108.883] # from Adobe Cookbook
-
-    # Transfer-matrix for the conversion of RGB to XYZ color space
-    transM = np.array([[0.4124564, 0.2126729, 0.0193339], 
-                        [0.3575761, 0.7151522, 0.1191920],
-                        [0.1804375, 0.0721750, 0.9503041]])
-
-
-    # ============================= Functions =================================
-
-
-    def __init__(self, RGB1, RGB2, numColors = 257., divide = 255., 
-                  method = "moreland", filename = ""):
-        
-        # create a class variable for the number of colors
-        self.numColors = numColors
-        
-        # assert an odd number of points
-        assert np.mod(numColors,2) == 1, \
-            "For diverging colormaps odd numbers of colors are desireable!"
-        
-        # assert a known method was specified
-        knownMethods = ["moreland", "lab"]
-        assert method in knownMethods, "Unknown method was specified!"
-        
-        if method == knownMethods[0]:
-            #generate the Msh diverging colormap
-            self.colorMap = self.generateColorMap(RGB1, RGB2, divide)
-        elif method == knownMethods[1]:
-            # generate the Lab diverging colormap
-            self.colorMap = self.generateColorMapLab(RGB1, RGB2, divide)
-
-    def getMap(self):
-        return self.colorMap
-
-    def showMap(self):
-        #rc('text', usetex=False)
-        a=np.outer(np.arange(0,1,0.01),np.ones(10))
-        fig=plt.figure(99,figsize=(10,2))
-        plt.axis("off")
-        cm = matplotlib.colors.ListedColormap(self.colorMap)
-        pm=plt.imshow(a,aspect='auto',cmap=cm,origin="lower")
-        plt.clim(0,1)
-        fig.colorbar(pm)
-        plt.draw()
-
-        
-    def rgblinear(self, RGB):
-        """
-        Conversion from the sRGB components to RGB components with physically
-        linear properties.
-        """
-        
-        # initialize the linear RGB array
-        RGBlinear = np.zeros((3,)) 
-        
-        #  calculate the linear RGB values
-        for i,value in enumerate(RGB):
-            value = float(value) / 255.
-            if value > 0.04045 :
-                value = ( ( value + 0.055 ) / 1.055 ) ** 2.4
-            else :
-                value = value / 12.92
-            RGBlinear[i] = value * 100.
-        return RGBlinear
-    #-
-
-    def sRGB(self, RGBlinear):
-        """
-        Back conversion from linear RGB to sRGB.
-        """
-        
-        # initialize the sRGB array
-        RGB = np.zeros((3,))
-        
-        #  calculate the sRGB values
-        for i,value in enumerate(RGBlinear):
-            value = float(value) / 100.
-
-            if value > 0.00313080495356037152:
-                value = (1.055 * np.power(value,1./2.4) ) - 0.055
-            else :
-                value = value * 12.92
-
-            RGB[i] = round(value * 255.)
-        return RGB
-    #-
-
-    def rgb2xyz(self, RGB):
-        """
-        Conversion of RGB to XYZ using the transfer-matrix
-        """
-        return np.dot(self.rgblinear(RGB), self.transM)
-    #-
-
-    def xyz2rgb(self, XYZ):
-        """
-        Conversion of RGB to XYZ using the transfer-matrix
-        """
-        #return np.round(np.dot(XYZ, np.array(np.matrix(transM).I)))
-        return self.sRGB(np.dot(XYZ, np.array(np.matrix(self.transM).I)))
-    #-
-
-    def rgb2Lab(self, RGB):
-        """
-        Conversion of RGB to CIELAB
-        """
-        
-        # convert RGB to XYZ
-        X, Y, Z = (self.rgb2xyz(RGB)).tolist()
-        
-        # helper function
-        def f(x):
-            limit = 0.008856
-            if x> limit:
-                return np.power(x, 1./3.)
-            else:
-                return 7.787*x + 16./116.
-        
-        # calculation of L, a and b
-        L = 116. * ( f(Y/self.Yn) - (16./116.) )
-        a = 500. * ( f(X/self.Xn) - f(Y/self.Yn) )
-        b = 200. * ( f(Y/self.Yn) - f(Z/self.Zn) )
-        return np.array([L, a, b])
-    #-
-
-    def Lab2rgb(self, Lab):
-        """
-        Conversion of CIELAB to RGB
-        """
-        
-        # unpack the Lab-array
-        L, a, b = Lab.tolist()
-        
-        # helper function
-        def finverse(x):
-            xlim = 0.008856
-            a = 7.787
-            b = 16./116.
-            ylim = a*xlim+b
-            if x > ylim:
-                return np.power(x, 3)
-            else:
-                return ( x - b ) / a
-            
-        # calculation of X, Y and Z
-        X = self.Xn * finverse( (a/500.) + (L+16.)/116. )
-        Y = self.Yn * finverse( (L+16.)/116. )
-        Z = self.Zn * finverse( (L+16.)/116. - (b/200.) )
-        
-        # conversion of XYZ to RGB
-        return self.xyz2rgb(np.array([X,Y,Z]))
-    #-
-
-    def Lab2Msh(self, Lab):
-        """
-        Conversion of CIELAB to Msh
-        """
-
-        # unpack the Lab-array
-        L, a, b = Lab.tolist()
-
-        # calculation of M, s and h
-        M = np.sqrt(np.sum(np.power(Lab, 2)))
-        s = np.arccos(L/M)
-        h = np.arctan2(b,a)
-        return np.array([M,s,h])
-    #-
-
-    def Msh2Lab(self, Msh):
-        """
-        Conversion of Msh to CIELAB
-        """
-
-        # unpack the Msh-array
-        M, s, h = Msh.tolist()
-
-        # calculation of L, a and b
-        L = M*np.cos(s)
-        a = M*np.sin(s)*np.cos(h)
-        b = M*np.sin(s)*np.sin(h)
-        return np.array([L,a,b])
-    #-
-
-    def rgb2Msh(self, RGB):
-        """ Direct conversion of RGB to Msh. """
-        return self.Lab2Msh(self.rgb2Lab(RGB))
-    #-
-
-    def Msh2rgb(self, Msh):
-        """ Direct conversion of Msh to RGB. """
-        return self.Lab2rgb(self.Msh2Lab(Msh))
-    #-
-
-    def adjustHue(self, MshSat, Munsat):
-        """
-        Function to provide an adjusted hue when interpolating to an 
-        unsaturated color in Msh space.
-        """
-        
-        # unpack the saturated Msh-array
-        Msat, ssat, hsat = MshSat.tolist()
-        
-        if Msat >= Munsat:
-            return hsat
-        else:
-            hSpin = ssat * np.sqrt(Munsat**2 - Msat**2) / \
-                    (Msat * np.sin(ssat))
-            if hsat > -np.pi/3:
-                return hsat + hSpin
-            else:
-                return hsat - hSpin
-    #-
-
-    def interpolateColor(self, RGB1, RGB2, interp):
-        """
-        Interpolation algorithm to automatically create continuous diverging
-        color maps.
-        """
-        
-        # convert RGB to Msh and unpack
-        Msh1 = self.rgb2Msh(RGB1)
-        M1, s1, h1 = Msh1.tolist()
-        Msh2 = self.rgb2Msh(RGB2)
-        M2, s2, h2 = Msh2.tolist()
-        
-        # If points saturated and distinct, place white in middle
-        if (s1>0.05) and (s2>0.05) and ( np.abs(h1-h2) > np.pi/3. ):
-            Mmid = max([M1, M2, 88.])
-            if interp < 0.5:
-                M2 = Mmid
-                s2 = 0.
-                h2 = 0.
-                interp = 2*interp
-            else:
-                M1 = Mmid
-                s1 = 0.
-                h1 = 0.
-                interp = 2*interp-1.
-                
-        # Adjust hue of unsaturated colors
-        if (s1 < 0.05) and (s2 > 0.05):
-            h1 = self.adjustHue(np.array([M2,s2,h2]), M1)
-        elif (s2 < 0.05) and (s1 > 0.05):
-            h2 = self.adjustHue(np.array([M1,s1,h1]), M2)
-            
-        # Linear interpolation on adjusted control points
-        MshMid = (1-interp)*np.array([M1,s1,h1]) + \
-                 interp*np.array([M2,s2,h2])
-        
-        return self.Msh2rgb(MshMid)
-    #-
-
-    def generateColorMap(self, RGB1, RGB2, divide):
-        """
-        Generate the complete diverging color map using the Moreland-technique
-        from RGB1 to RGB2, placing "white" in the middle. The number of points
-        given by "numPoints" controls the resolution of the colormap. The 
-        optional parameter "divide" gives the possibility to scale the whole
-        colormap, for example to have float values from 0 to 1.
-        """
-        
-        # calculate
-        scalars = np.linspace(0., 1., self.numColors)
-        RGBs = np.zeros((self.numColors, 3))
-        for i,s in enumerate(scalars):
-            RGBs[i,:] = self.interpolateColor(RGB1, RGB2, s)
-        return RGBs/divide
-    #-
-
-    def generateColorMapLab(self, RGB1, RGB2, divide):
-        """
-        Generate the complete diverging color map using a transition from
-        Lab1 to Lab2, transitioning true RGB-white. The number of points
-        given by "numPoints" controls the resolution of the colormap. The 
-        optional parameter "divide" gives the possibility to scale the whole
-        colormap, for example to have float values from 0 to 1.
-        """
-        
-        # convert to Lab-space
-        Lab1 = self.rgb2Lab(RGB1)
-        Lab2 = self.rgb2Lab(RGB2)
-        LabWhite = np.array([100., 0., 0.])
-        
-        # initialize the resulting arrays
-        Lab = np.zeros((self.numColors ,3))
-        RGBs = np.zeros((self.numColors ,3))
-        N2 = np.floor(self.numColors/2.)
-        
-        # calculate
-        for i in range(3):
-            Lab[0:N2+1, i] = np.linspace(Lab1[i], LabWhite[i], N2+1)
-            Lab[N2:, i] = np.linspace(LabWhite[i], Lab2[i], N2+1)
-        for i,l in enumerate(Lab):
-            RGBs[i,:] = self.Lab2rgb(l)
-        return RGBs/divide
-    #-
-
+# This all needs to be reworked to fit in with new plotting
+# methods. Daniel 1/12/2015
+
+
+# # ------------------------------------------------------
+# # This file is very much in flux at the moment and will
+# # undergo many significant changes without notice.
+# # Don't use this for anything but playing/testing yet.
+# # Andreas 06.03.2014
+# # ------------------------------------------------------
+#
+# import numpy as np
+# import matplotlib
+# import matplotlib.backends.backend_pdf
+# from matplotlib import cm
+# BACKEND = 'Qt4Agg'
+# matplotlib.use(BACKEND)
+# from matplotlib import rc
+# import matplotlib.pyplot as plt
+#
+# formatter = matplotlib.ticker.EngFormatter(unit='', places=0)
+# formatter.ENG_PREFIXES[-6] = 'u'
+#
+#
+# def argmaxM(data):
+#     return(np.unravel_index(np.argmax(data),data.shape))
+#
+#
+# def printPDF(fig, filename):
+#     if filename !='' and filename != None:
+#         if not filename.lower().endswith(('.pdf')):
+#             filename=filename+'.pdf'
+#         pdfp = matplotlib.backends.backend_pdf.PdfPages(filename)
+#         pdfp.savefig(fig, dpi=300,bbox_inches='tight')
+#         pdfp.close()
+#
+# def plot_field(field):
+#     ax,fig=plot_setup()
+#     im = ax.imshow(np.abs(field),origin='lower', aspect='auto')
+#     cb = fig.colorbar(im, format="%.4g")
+#     #cb.set_clim(-1.0*zlimit, zlimit)
+#     ax.autoscale(False)
+#     plt.show(block=0)
+#
+# def plot_propagation(field, grid, Lambda, axis, normalise, Lrange, nr):
+#     # axis = 0 for x and =1 for y crosssection
+#     # if normalise = 1, each slice is normalises to peak intensity
+#     [n,m]=field.shape
+#     slices = np.zeros((n,np.size(Lrange)))
+#     from pykat.optics.fft import FFT_propagate
+#     for idx, L in enumerate(Lrange):
+#         field2 = FFT_propagate(field,grid, Lambda, L, nr)
+#         if axis==0:
+#             slices[:,idx]=np.abs(field2[:,int(m/2)])**2
+#         else:
+#             slices[:,idx]=np.abs(field2[int(n/2),:])**2
+#         if normalise==1:
+#             peak_intensity= np.abs(field2[int(n/2),int(m/2)])**2
+#             slices[:,idx]=slices[:,idx]/peak_intensity
+#     ax,fig=plot_setup()
+#     im = ax.imshow(slices, aspect='auto')
+#     cb = fig.colorbar(im, format="%.4g")
+#     #cb.set_clim(-1.0*zlimit, zlimit)
+#     ax.autoscale(False)
+#     plt.show(block=0)
+#
+#
+# def plot_power_contour(x,y,z,xlabel, ylabel, clabel, title='', filename=''):
+#     ax,fig=plot_setup()
+#     xm,ym=np.meshgrid(x,y)
+#     extent = [x[0], x[-1], y[0], y[-1]]
+#     mycm='YlOrRd_r'
+#     #mycm='hot'
+#     #im = ax.imshow(z,origin='lower',extent=extent,cmap=mycm, aspect='auto', interpolation='nearest')
+#     im = ax.imshow(z,origin='lower',extent=extent,cmap=mycm, aspect='auto')
+#     #im = ax.imshow(z,origin='lower',cmap=mycm, aspect='auto')
+#     cb = fig.colorbar(im, format="%.4g")
+#     #cb.set_clim(-1.0*zlimit, zlimit)
+#     ax.autoscale(False)
+#     #ct = ax.contour(xm,ym,z, zdir='z', levels = [0])
+#     #ax.clabel(ct,inline=1,fontsize=10)
+#     ax.set_xlabel(xlabel)
+#     ax.set_ylabel(ylabel)
+#     cb.set_label(clabel)
+#     ax.xaxis.set_major_formatter(formatter)
+#     ax.yaxis.set_major_formatter(formatter)
+#     fig.canvas.manager.set_window_title(title)
+#     plt.show(block=0)
+#     printPDF(fig, filename)
+#
+#
+#
+# def plot_error_contour(x,y,z,xlabel, ylabel, clabel, title='', filename=''):
+#     global fig, ax, cb, ct, data
+#     rc('font',**pp.font)
+#     rc('xtick',labelsize=pp.TICK_SIZE)
+#     rc('ytick',labelsize=pp.TICK_SIZE)
+#     rc('text', usetex=pp.USETEX)
+#     rc('axes', labelsize = pp.LABEL_SIZE)
+#     fig, ax =plt.subplots()
+#     fig.set_size_inches(pp.fig_size)
+#     fig.set_dpi(pp.FIG_DPI)
+#     xm,ym=np.meshgrid(x,y)
+#     RGB1 = 255*np.array([0.23, 0.299, 0.754])
+#     RGB2 = 255*np.array([0.706,0.016, 0.15])
+#     cm1 = CM(RGB1, RGB2)
+#     cm_values = cm1.getMap()
+#     #cm1.showMap()
+#     mycm = matplotlib.colors.ListedColormap(cm_values)
+#     extent = [x[0], x[-1], y[0], y[-1] ]
+#     data=z
+#     # make symmetric color display
+#     zlimit=np.max([abs(data.max()),abs(data.min())])
+#     im = ax.imshow(data,origin='lower',extent=extent,cmap=mycm, aspect='auto', interpolation='nearest')
+#     #im = ax.imshow(data,origin='lower',extent=extent,cmap=mycm, aspect='auto')
+#     cb = fig.colorbar(im, format="%.4g")
+#     cb.set_clim(-1.0*zlimit, zlimit)
+#     ax.autoscale(False)
+#     ct = ax.contour(xm,ym,data, zdir='z', levels = [0])
+#     ax.clabel(ct,inline=1,fontsize=10)
+#     ax.set_xlabel(xlabel)
+#     ax.set_ylabel(ylabel)
+#     cb.set_label(clabel)
+#     ax.xaxis.set_major_formatter(formatter)
+#     fig.canvas.manager.set_window_title(title)
+#     plt.show()
+#     printPDF(fig, filename)
+#
+# def plot_setup():
+#     rc('font',**pp.font)
+#     rc('xtick',labelsize=pp.TICK_SIZE)
+#     rc('ytick',labelsize=pp.TICK_SIZE)
+#     rc('text', usetex=pp.USETEX)
+#     rc('axes', labelsize = pp.LABEL_SIZE)
+#     fig, ax =plt.subplots()
+#     fig.set_size_inches(pp.fig_size)
+#     fig.set_dpi(pp.FIG_DPI)
+#     return ax,fig
+#
+# class pp():
+#     # set some gobal settings first
+#     BACKEND = 'Qt4Agg' # matplotlib backend
+#     FIG_DPI=90 # DPI of on sceen plot
+#     # Some help in calculating good figure size for Latex
+#     # documents. Starting with plot size in pt,
+#     # get this from LaTeX using \showthe\columnwidth
+#     fig_width_pt = 484.0
+#     inches_per_pt = 1.0/72.27  # Convert TeX pt to inches
+#     golden_mean = (np.sqrt(5)-1.0)/2.0   # Aesthetic ratio
+#     fig_width = fig_width_pt*inches_per_pt  # width in inches
+#     fig_height = fig_width*golden_mean      # height in inches
+#     fig_size = [fig_width,fig_height]
+#     # some plot options:
+#     LINEWIDTH = 1 # linewidths of traces in plot
+#     AA = True # antialiasing of traces
+#     USETEX = False # use Latex encoding in text
+#     SHADOW = False # shadow of legend box
+#     GRID = True # grid on or off
+#     # font sizes for normal text, tick labels and legend
+#     FONT_SIZE = 10 # size of normal text
+#     TICK_SIZE = 10 # size of tick labels
+#     LABEL_SIZE = 10 # size of axes labels
+#     LEGEND_SIZE = 10 # size of legend
+#     # font family and type
+#     font = {'family':'sans-serif','sans-serif':['Helvetica'],'size':FONT_SIZE}
+#     DPI=300 # DPI for saving via savefig
+#     # print options given to savefig command:
+#     print_options = {'dpi':DPI, 'transparent':True, 'bbox_inches':'tight', 'pad_inches':0.1}
+#     # for Palatino and other serif fonts use:
+#     #font = {'family':'serif','serif':['Palatino']}
+#     SCREEN_TITLE = True # show title on screen?
+#     PRINT_TITLE = False # show title in saved file?
+#
+# # =============================================================================
+# # ====================== The Class ColorMapCreator ============================
+# # =============================================================================
+#
+# class CM:
+#     """
+#     Class ColorMapCreator:
+#     Create diverging colormaps from RGB1 to RGB2 using the method of Moreland
+#     or a simple CIELAB-interpolation. numColors controls the number of color
+#     values to output (odd number) and divide gives the possibility to output
+#     RGB-values from 0.0-1.0 instead of 0-255. If a filename different than
+#     "" is given, the colormap will be saved to this file, otherwise a simple
+#     output using print will be given.
+#     """
+#
+#     # ======================== Global Variables ===============================
+#
+#     # Reference white-point D65
+#     Xn, Yn, Zn = [95.047, 100.0, 108.883] # from Adobe Cookbook
+#
+#     # Transfer-matrix for the conversion of RGB to XYZ color space
+#     transM = np.array([[0.4124564, 0.2126729, 0.0193339],
+#                         [0.3575761, 0.7151522, 0.1191920],
+#                         [0.1804375, 0.0721750, 0.9503041]])
+#
+#
+#     # ============================= Functions =================================
+#
+#
+#     def __init__(self, RGB1, RGB2, numColors = 257., divide = 255.,
+#                   method = "moreland", filename = ""):
+#
+#         # create a class variable for the number of colors
+#         self.numColors = numColors
+#
+#         # assert an odd number of points
+#         assert np.mod(numColors,2) == 1, \
+#             "For diverging colormaps odd numbers of colors are desireable!"
+#
+#         # assert a known method was specified
+#         knownMethods = ["moreland", "lab"]
+#         assert method in knownMethods, "Unknown method was specified!"
+#
+#         if method == knownMethods[0]:
+#             #generate the Msh diverging colormap
+#             self.colorMap = self.generateColorMap(RGB1, RGB2, divide)
+#         elif method == knownMethods[1]:
+#             # generate the Lab diverging colormap
+#             self.colorMap = self.generateColorMapLab(RGB1, RGB2, divide)
+#
+#     def getMap(self):
+#         return self.colorMap
+#
+#     def showMap(self):
+#         #rc('text', usetex=False)
+#         a=np.outer(np.arange(0,1,0.01),np.ones(10))
+#         fig=plt.figure(99,figsize=(10,2))
+#         plt.axis("off")
+#         cm = matplotlib.colors.ListedColormap(self.colorMap)
+#         pm=plt.imshow(a,aspect='auto',cmap=cm,origin="lower")
+#         plt.clim(0,1)
+#         fig.colorbar(pm)
+#         plt.draw()
+#
+#
+#     def rgblinear(self, RGB):
+#         """
+#         Conversion from the sRGB components to RGB components with physically
+#         linear properties.
+#         """
+#
+#         # initialize the linear RGB array
+#         RGBlinear = np.zeros((3,))
+#
+#         #  calculate the linear RGB values
+#         for i,value in enumerate(RGB):
+#             value = float(value) / 255.
+#             if value > 0.04045 :
+#                 value = ( ( value + 0.055 ) / 1.055 ) ** 2.4
+#             else :
+#                 value = value / 12.92
+#             RGBlinear[i] = value * 100.
+#         return RGBlinear
+#     #-
+#
+#     def sRGB(self, RGBlinear):
+#         """
+#         Back conversion from linear RGB to sRGB.
+#         """
+#
+#         # initialize the sRGB array
+#         RGB = np.zeros((3,))
+#
+#         #  calculate the sRGB values
+#         for i,value in enumerate(RGBlinear):
+#             value = float(value) / 100.
+#
+#             if value > 0.00313080495356037152:
+#                 value = (1.055 * np.power(value,1./2.4) ) - 0.055
+#             else :
+#                 value = value * 12.92
+#
+#             RGB[i] = round(value * 255.)
+#         return RGB
+#     #-
+#
+#     def rgb2xyz(self, RGB):
+#         """
+#         Conversion of RGB to XYZ using the transfer-matrix
+#         """
+#         return np.dot(self.rgblinear(RGB), self.transM)
+#     #-
+#
+#     def xyz2rgb(self, XYZ):
+#         """
+#         Conversion of RGB to XYZ using the transfer-matrix
+#         """
+#         #return np.round(np.dot(XYZ, np.array(np.matrix(transM).I)))
+#         return self.sRGB(np.dot(XYZ, np.array(np.matrix(self.transM).I)))
+#     #-
+#
+#     def rgb2Lab(self, RGB):
+#         """
+#         Conversion of RGB to CIELAB
+#         """
+#
+#         # convert RGB to XYZ
+#         X, Y, Z = (self.rgb2xyz(RGB)).tolist()
+#
+#         # helper function
+#         def f(x):
+#             limit = 0.008856
+#             if x> limit:
+#                 return np.power(x, 1./3.)
+#             else:
+#                 return 7.787*x + 16./116.
+#
+#         # calculation of L, a and b
+#         L = 116. * ( f(Y/self.Yn) - (16./116.) )
+#         a = 500. * ( f(X/self.Xn) - f(Y/self.Yn) )
+#         b = 200. * ( f(Y/self.Yn) - f(Z/self.Zn) )
+#         return np.array([L, a, b])
+#     #-
+#
+#     def Lab2rgb(self, Lab):
+#         """
+#         Conversion of CIELAB to RGB
+#         """
+#
+#         # unpack the Lab-array
+#         L, a, b = Lab.tolist()
+#
+#         # helper function
+#         def finverse(x):
+#             xlim = 0.008856
+#             a = 7.787
+#             b = 16./116.
+#             ylim = a*xlim+b
+#             if x > ylim:
+#                 return np.power(x, 3)
+#             else:
+#                 return ( x - b ) / a
+#
+#         # calculation of X, Y and Z
+#         X = self.Xn * finverse( (a/500.) + (L+16.)/116. )
+#         Y = self.Yn * finverse( (L+16.)/116. )
+#         Z = self.Zn * finverse( (L+16.)/116. - (b/200.) )
+#
+#         # conversion of XYZ to RGB
+#         return self.xyz2rgb(np.array([X,Y,Z]))
+#     #-
+#
+#     def Lab2Msh(self, Lab):
+#         """
+#         Conversion of CIELAB to Msh
+#         """
+#
+#         # unpack the Lab-array
+#         L, a, b = Lab.tolist()
+#
+#         # calculation of M, s and h
+#         M = np.sqrt(np.sum(np.power(Lab, 2)))
+#         s = np.arccos(L/M)
+#         h = np.arctan2(b,a)
+#         return np.array([M,s,h])
+#     #-
+#
+#     def Msh2Lab(self, Msh):
+#         """
+#         Conversion of Msh to CIELAB
+#         """
+#
+#         # unpack the Msh-array
+#         M, s, h = Msh.tolist()
+#
+#         # calculation of L, a and b
+#         L = M*np.cos(s)
+#         a = M*np.sin(s)*np.cos(h)
+#         b = M*np.sin(s)*np.sin(h)
+#         return np.array([L,a,b])
+#     #-
+#
+#     def rgb2Msh(self, RGB):
+#         """ Direct conversion of RGB to Msh. """
+#         return self.Lab2Msh(self.rgb2Lab(RGB))
+#     #-
+#
+#     def Msh2rgb(self, Msh):
+#         """ Direct conversion of Msh to RGB. """
+#         return self.Lab2rgb(self.Msh2Lab(Msh))
+#     #-
+#
+#     def adjustHue(self, MshSat, Munsat):
+#         """
+#         Function to provide an adjusted hue when interpolating to an
+#         unsaturated color in Msh space.
+#         """
+#
+#         # unpack the saturated Msh-array
+#         Msat, ssat, hsat = MshSat.tolist()
+#
+#         if Msat >= Munsat:
+#             return hsat
+#         else:
+#             hSpin = ssat * np.sqrt(Munsat**2 - Msat**2) / \
+#                     (Msat * np.sin(ssat))
+#             if hsat > -np.pi/3:
+#                 return hsat + hSpin
+#             else:
+#                 return hsat - hSpin
+#     #-
+#
+#     def interpolateColor(self, RGB1, RGB2, interp):
+#         """
+#         Interpolation algorithm to automatically create continuous diverging
+#         color maps.
+#         """
+#
+#         # convert RGB to Msh and unpack
+#         Msh1 = self.rgb2Msh(RGB1)
+#         M1, s1, h1 = Msh1.tolist()
+#         Msh2 = self.rgb2Msh(RGB2)
+#         M2, s2, h2 = Msh2.tolist()
+#
+#         # If points saturated and distinct, place white in middle
+#         if (s1>0.05) and (s2>0.05) and ( np.abs(h1-h2) > np.pi/3. ):
+#             Mmid = max([M1, M2, 88.])
+#             if interp < 0.5:
+#                 M2 = Mmid
+#                 s2 = 0.
+#                 h2 = 0.
+#                 interp = 2*interp
+#             else:
+#                 M1 = Mmid
+#                 s1 = 0.
+#                 h1 = 0.
+#                 interp = 2*interp-1.
+#
+#         # Adjust hue of unsaturated colors
+#         if (s1 < 0.05) and (s2 > 0.05):
+#             h1 = self.adjustHue(np.array([M2,s2,h2]), M1)
+#         elif (s2 < 0.05) and (s1 > 0.05):
+#             h2 = self.adjustHue(np.array([M1,s1,h1]), M2)
+#
+#         # Linear interpolation on adjusted control points
+#         MshMid = (1-interp)*np.array([M1,s1,h1]) + \
+#                  interp*np.array([M2,s2,h2])
+#
+#         return self.Msh2rgb(MshMid)
+#     #-
+#
+#     def generateColorMap(self, RGB1, RGB2, divide):
+#         """
+#         Generate the complete diverging color map using the Moreland-technique
+#         from RGB1 to RGB2, placing "white" in the middle. The number of points
+#         given by "numPoints" controls the resolution of the colormap. The
+#         optional parameter "divide" gives the possibility to scale the whole
+#         colormap, for example to have float values from 0 to 1.
+#         """
+#
+#         # calculate
+#         scalars = np.linspace(0., 1., self.numColors)
+#         RGBs = np.zeros((self.numColors, 3))
+#         for i,s in enumerate(scalars):
+#             RGBs[i,:] = self.interpolateColor(RGB1, RGB2, s)
+#         return RGBs/divide
+#     #-
+#
+#     def generateColorMapLab(self, RGB1, RGB2, divide):
+#         """
+#         Generate the complete diverging color map using a transition from
+#         Lab1 to Lab2, transitioning true RGB-white. The number of points
+#         given by "numPoints" controls the resolution of the colormap. The
+#         optional parameter "divide" gives the possibility to scale the whole
+#         colormap, for example to have float values from 0 to 1.
+#         """
+#
+#         # convert to Lab-space
+#         Lab1 = self.rgb2Lab(RGB1)
+#         Lab2 = self.rgb2Lab(RGB2)
+#         LabWhite = np.array([100., 0., 0.])
+#
+#         # initialize the resulting arrays
+#         Lab = np.zeros((self.numColors ,3))
+#         RGBs = np.zeros((self.numColors ,3))
+#         N2 = np.floor(self.numColors/2.)
+#
+#         # calculate
+#         for i in range(3):
+#             Lab[0:N2+1, i] = np.linspace(Lab1[i], LabWhite[i], N2+1)
+#             Lab[N2:, i] = np.linspace(LabWhite[i], Lab2[i], N2+1)
+#         for i,l in enumerate(Lab):
+#             RGBs[i,:] = self.Lab2rgb(l)
+#         return RGBs/divide
+#     #-
+#
-- 
GitLab