diff --git a/code/bar_plot.py b/code/bar_plot.py
deleted file mode 100644
index 404d35c..0000000
--- a/code/bar_plot.py
+++ /dev/null
@@ -1,96 +0,0 @@
-import os
-
-from experiment import Experiment
-# noinspection PyUnresolvedReferences
-from soup import Soup
-from typing import List
-
-from collections import defaultdict
-
-from argparse import ArgumentParser
-import numpy as np
-
-import plotly as pl
-import plotly.graph_objs as go
-
-import colorlover as cl
-
-import dill
-
-
-def build_args():
-    arg_parser = ArgumentParser()
-    arg_parser.add_argument('-i', '--in_file', nargs=1, type=str)
-    arg_parser.add_argument('-o', '--out_file', nargs='?', default='out', type=str)
-    return arg_parser.parse_args()
-
-
-def plot_bars(names_bars_tuple, filename='histogram_plot'):
-    # catagorical
-    ryb = cl.scales['10']['div']['RdYlBu']
-    names, bars = names_bars_tuple
-    situations = list(bars[0].keys())
-    names = ['Weightwise', 'Aggregating', 'Recurrent']  # [name.split(' ')[0] for name in names]
-    data_dict = {}
-    for idx, name in enumerate(names):
-        data_dict[name] = bars[idx]
-
-    data = []
-
-    for idx, situation in enumerate(situations):
-        bar = go.Bar(
-            y=[data_dict[name][situation] for name in names],
-            # x=[key for key in data_dict[name].keys()],
-            x=names,
-            name=situation,
-            showlegend=True,
-        )
-        data.append(bar)
-
-    layout = dict(xaxis=dict(title="Networks", titlefont=dict(size=20)),
-                  barmode='stack',
-                  # height=400, width=400,
-                  # margin=dict(l=20, r=20, t=20, b=20)
-                  legend=dict(orientation="h", x=0.05)
-                  )
-
-    fig = go.Figure(data=data, layout=layout)
-    pl.offline.plot(fig, auto_open=True, filename=filename)
-    pass
-
-
-def search_and_apply(absolut_file_or_folder, plotting_function, files_to_look_for=[]):
-    if os.path.isdir(absolut_file_or_folder):
-        for sub_file_or_folder in os.scandir(absolut_file_or_folder):
-            search_and_apply(sub_file_or_folder.path, plotting_function, files_to_look_for=files_to_look_for)
-    elif absolut_file_or_folder.endswith('.dill'):
-        file_or_folder = os.path.split(absolut_file_or_folder)[-1]
-        if file_or_folder in files_to_look_for and not os.path.exists('{}.html'.format(file_or_folder[:-5])):
-            print('Apply Plotting function "{func}" on file "{file}"'.format(func=plotting_function.__name__,
-                                                                             file=absolut_file_or_folder)
-                  )
-
-            with open(absolut_file_or_folder, 'rb') as in_f:
-                bars = dill.load(in_f)
-
-            names_dill_location = os.path.join(*os.path.split(absolut_file_or_folder)[:-1], 'all_names.dill')
-            with open(names_dill_location, 'rb') as in_f:
-                names = dill.load(in_f)
-
-            plotting_function((names, bars), filename='{}.html'.format(absolut_file_or_folder[:-5]))
-
-        else:
-            pass
-            # This was not a file i should look for.
-    else:
-        # This was either another FilyType or Plot.html alerady exists.
-        pass
-
-
-if __name__ == '__main__':
-    args = build_args()
-    in_file = args.in_file[0]
-    out_file = args.out_file
-
-    search_and_apply(in_file, plot_bars, files_to_look_for=['all_counters.dill'])
-    # , 'all_names.dill', 'all_notable_nets.dill'])
diff --git a/code/box_plots.py b/code/box_plots.py
deleted file mode 100644
index 574bdd6..0000000
--- a/code/box_plots.py
+++ /dev/null
@@ -1,129 +0,0 @@
-import os
-
-from experiment import Experiment
-# noinspection PyUnresolvedReferences
-from soup import Soup
-from typing import List
-
-from collections import defaultdict
-
-from argparse import ArgumentParser
-import numpy as np
-
-import plotly as pl
-import plotly.graph_objs as go
-
-import colorlover as cl
-
-import dill
-
-
-def build_args():
-    arg_parser = ArgumentParser()
-    arg_parser.add_argument('-i', '--in_file', nargs=1, type=str)
-    arg_parser.add_argument('-o', '--out_file', nargs='?', default='out', type=str)
-    return arg_parser.parse_args()
-
-
-def plot_box(exp: Experiment, filename='histogram_plot'):
-    # catagorical
-    ryb = cl.scales['10']['div']['RdYlBu']
-
-    data = []
-
-    for d in range(exp.depth):
-        names = ['D 10e-{}'.format(d)] * exp.trials
-        data.extend(names)
-
-    trace_list = []
-
-    vergence_box = go.Box(
-        y=exp.ys,
-        x=data,
-        name='Time to Vergence',
-        boxpoints=False,
-        showlegend=True,
-        marker=dict(
-            color=ryb[3]
-        ),
-    )
-    fixpoint_box = go.Box(
-        y=exp.zs,
-        x=data,
-        name='Time as Fixpoint',
-        boxpoints=False,
-        showlegend=True,
-        marker=dict(
-            color=ryb[-1]
-        ),
-    )
-
-    trace_list.extend([vergence_box, fixpoint_box])
-
-    layout = dict(title='{}'.format('Known Fixpoint Variation'),
-                  titlefont=dict(size=30),
-                  legend=dict(
-                      orientation="h",
-                      x=.1, y=-0.1,
-                      font=dict(
-                          size=20,
-                          color='black'
-                      ),
-                  ),
-                  boxmode='group',
-                  boxgap=0,
-                  # barmode='group',
-                  bargap=0,
-                  xaxis=dict(showgrid=False,
-                             zeroline=True,
-                             tickangle=0,
-                             showticklabels=True),
-                  yaxis=dict(
-                      title='Steps',
-                      zeroline=False,
-                      titlefont=dict(
-                          size=30
-                      )
-                  ),
-                  # height=400, width=400,
-                  margin=dict(t=50)
-                  )
-
-    fig = go.Figure(data=trace_list, layout=layout)
-    pl.offline.plot(fig, auto_open=True, filename=filename)
-    pass
-
-
-def search_and_apply(absolut_file_or_folder, plotting_function, files_to_look_for=[]):
-    if os.path.isdir(absolut_file_or_folder):
-        for sub_file_or_folder in os.scandir(absolut_file_or_folder):
-            search_and_apply(sub_file_or_folder.path, plotting_function, files_to_look_for=files_to_look_for)
-    elif absolut_file_or_folder.endswith('.dill'):
-        file_or_folder = os.path.split(absolut_file_or_folder)[-1]
-        if file_or_folder in files_to_look_for and not os.path.exists('{}.html'.format(file_or_folder[:-5])):
-            print('Apply Plotting function "{func}" on file "{file}"'.format(func=plotting_function.__name__,
-                                                                             file=absolut_file_or_folder)
-                  )
-
-            with open(absolut_file_or_folder, 'rb') as in_f:
-                exp = dill.load(in_f)
-            try:
-                plotting_function(exp, filename='{}.html'.format(absolut_file_or_folder[:-5]))
-            except AttributeError:
-                pass
-
-        else:
-            pass
-            # This was not a file i should look for.
-    else:
-        # This was either another FilyType or Plot.html alerady exists.
-        pass
-
-
-if __name__ == '__main__':
-    args = build_args()
-    in_file = args.in_file[0]
-    out_file = args.out_file
-
-    search_and_apply(in_file, plot_box, files_to_look_for=['experiment.dill'])
-    # , 'all_names.dill', 'all_notable_nets.dill'])
diff --git a/code/line_plots.py b/code/line_plots.py
deleted file mode 100644
index 412d1cb..0000000
--- a/code/line_plots.py
+++ /dev/null
@@ -1,118 +0,0 @@
-import os
-
-from experiment import Experiment
-# noinspection PyUnresolvedReferences
-from soup import Soup
-
-from argparse import ArgumentParser
-import numpy as np
-
-import plotly as pl
-import plotly.graph_objs as go
-
-import colorlover as cl
-
-import dill
-
-from sklearn.manifold.t_sne import TSNE, PCA
-
-
-def build_args():
-    arg_parser = ArgumentParser()
-    arg_parser.add_argument('-i', '--in_file', nargs=1, type=str)
-    arg_parser.add_argument('-o', '--out_file', nargs='?', default='out', type=str)
-    return arg_parser.parse_args()
-
-
-def line_plot(names_exp_tuple, filename='lineplot'):
-
-    names, line_dict_list = names_exp_tuple
-
-    names = ['Weightwise', 'Aggregating', 'Recurrent']
-
-    if False:
-        data = []
-        base_scale = cl.scales['10']['div']['RdYlGn']
-        scale = cl.interp(base_scale, len(line_dict_list) + 1)  # Map color scale to N bins
-        for ld_id, line_dict in enumerate(line_dict_list):
-            for data_point in ['ys', 'zs']:
-                trace = go.Scatter(
-                    x=line_dict['xs'],
-                    y=line_dict[data_point],
-                    name='{} {}zero-fixpoints'.format(names[ld_id], 'non-' if data_point == 'zs' else ''),
-                    line=dict(
-                        # color=scale[ld_id],
-                        width=5,
-                        # dash='dash' if data_point == 'ys' else ''
-                    ),
-                )
-
-                data.append(trace)
-    if True:
-
-        data = []
-        base_scale = cl.scales['10']['div']['RdYlGn']
-        scale = cl.interp(base_scale, len(line_dict_list) + 1)  # Map color scale to N bins
-        for ld_id, line_dict in enumerate(line_dict_list):
-            trace = go.Scatter(
-                x=line_dict['xs'],
-                y=line_dict['ys'],
-                name=names[ld_id],
-                line=dict(  # color=scale[ld_id],
-                          width=5
-                ),
-            )
-
-            data.append(trace)
-
-    layout = dict(xaxis=dict(title='Trains per self-application', titlefont=dict(size=20)),
-                  yaxis=dict(title='Average amount of fixpoints found',
-                             titlefont=dict(size=20),
-                             # type='log',
-                             # range=[0, 2]
-                             ),
-                  legend=dict(orientation='h', x=0.3, y=-0.3),
-                  # height=800, width=800,
-                  margin=dict(b=0)
-                  )
-
-    fig = go.Figure(data=data, layout=layout)
-    pl.offline.plot(fig, auto_open=True, filename=filename)
-    pass
-
-
-def search_and_apply(absolut_file_or_folder, plotting_function, files_to_look_for=[]):
-    if os.path.isdir(absolut_file_or_folder):
-        for sub_file_or_folder in os.scandir(absolut_file_or_folder):
-            search_and_apply(sub_file_or_folder.path, plotting_function, files_to_look_for=files_to_look_for)
-    elif absolut_file_or_folder.endswith('.dill'):
-        file_or_folder = os.path.split(absolut_file_or_folder)[-1]
-        if file_or_folder in files_to_look_for and not os.path.exists('{}.html'.format(absolut_file_or_folder[:-5])):
-            print('Apply Plotting function "{func}" on file "{file}"'.format(func=plotting_function.__name__,
-                                                                             file=absolut_file_or_folder)
-                  )
-            with open(absolut_file_or_folder, 'rb') as in_f:
-                exp = dill.load(in_f)
-
-            names_dill_location = os.path.join(*os.path.split(absolut_file_or_folder)[:-1], 'all_names.dill')
-            with open(names_dill_location, 'rb') as in_f:
-                names = dill.load(in_f)
-
-            try:
-                plotting_function((names, exp), filename='{}.html'.format(absolut_file_or_folder[:-5]))
-            except ValueError:
-                pass
-            except AttributeError:
-                pass
-        else:
-            # This was either another FilyType or Plot.html alerady exists.
-            pass
-
-
-if __name__ == '__main__':
-    args = build_args()
-    in_file = args.in_file[0]
-    out_file = args.out_file
-
-    search_and_apply(in_file, line_plot, ["all_data.dill"])
-
diff --git a/code/network.py b/code/network.py
index f7ce095..9d0b8bd 100644
--- a/code/network.py
+++ b/code/network.py
@@ -1,11 +1,12 @@
 import numpy as np
+from abc import abstractmethod, ABC
+from typing import List, Union
 
-from keras.models import Sequential
-from keras.callbacks import Callback
-from keras.layers import SimpleRNN, Dense
-import keras.backend as K
+from tensorflow.python.keras.models import Sequential
+from tensorflow.python.keras.callbacks import Callback
+from tensorflow.python.keras.layers import SimpleRNN, Dense
+from tensorflow.python.keras import backend as K
 
-from util import *
 from experiment import *
 
 # Supress warnings and info messages
@@ -13,12 +14,12 @@ os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
 
 
 class SaveStateCallback(Callback):
-    def __init__(self, net, epoch=0):
+    def __init__(self, network, epoch=0):
         super(SaveStateCallback, self).__init__()
-        self.net = net
+        self.net = network
         self.init_epoch = epoch
 
-    def on_epoch_end(self, epoch, logs={}):
+    def on_epoch_end(self, epoch, logs=None):
         description = dict(time=epoch+self.init_epoch)
         description['action'] = 'train_self'
         description['counterpart'] = None
@@ -26,67 +27,116 @@ class SaveStateCallback(Callback):
         return
 
 
-class NeuralNetwork(PrintingObject):
+class Weights:
 
     @staticmethod
-    def weights_to_string(weights):
-        s = ""
-        for layer_id, layer in enumerate(weights):
-            for cell_id, cell in enumerate(layer):
-                s += "[ "
-                for weight_id, weight in enumerate(cell):
-                    s += str(weight) + " "
-                s += "]"
-            s += "\n"
-        return s
+    def __reshape_flat_array__(array, shapes):
+        sizes: List[int] = [int(np.prod(shape)) for shape in shapes]
+        # Split the incoming array into slices for layers
+        slices = [array[x: y] for x, y in zip(np.cumsum([0]+sizes), np.cumsum([0]+sizes)[1:])]
+        # reshape them in accordance to the given shapes
+        weights = [np.reshape(weight_slice, shape) for weight_slice, shape in zip(slices, shapes)]
+        return weights
 
-    @staticmethod
-    def are_weights_diverged(network_weights):
-        for layer_id, layer in enumerate(network_weights):
-            for cell_id, cell in enumerate(layer):
-                for weight_id, weight in enumerate(cell):
-                    if np.isnan(weight):
-                        return True
-                    if np.isinf(weight):
-                        return True
-        return False
+    def __init__(self, weight_vector: Union[List[np.ndarray], np.ndarray], flat_array_shape=None):
+        """
+        Weight class, for easy manipulation of weight vectors from Keras models
 
-    @staticmethod
-    def are_weights_within(network_weights, lower_bound, upper_bound):
-        for layer_id, layer in enumerate(network_weights):
-            for cell_id, cell in enumerate(layer):
-                for weight_id, weight in enumerate(cell):
-                    # could be a chain comparission "lower_bound <= weight <= upper_bound"
-                    if not (lower_bound <= weight and weight <= upper_bound):
-                        return False
-        return True
+        :param weight_vector: A numpy array holding weights
+        :type weight_vector: List[np.ndarray]
+        """
+        self.__iter_idx = [0, 0]
+        if flat_array_shape:
+            weight_vector = self.__reshape_flat_array__(weight_vector, flat_array_shape)
 
-    @staticmethod
-    def fill_weights(old_weights, new_weights_list):
-        new_weights = copy.deepcopy(old_weights)
+        self.layers = weight_vector
+
+        # TODO: implement a way to access the cells directly
+        # self.cells = len(self)
+        # TODO: implement a way to access the weights directly
+        # self.weights = self.to_flat_array() ?
+
+    def __iter__(self):
+        self.__iter_idx = [0, 0]
+        return self
+
+    def __getitem__(self, item):
+        return self.layers[item]
+
+    def __len__(self):
+        return sum([x.size for x in self.layers])
+
+    def shapes(self):
+        return [x.shape for x in self.layers]
+
+    def num_layers(self):
+        return len(self.layers)
+
+    def __copy__(self):
+        return copy.deepcopy(self)
+
+    def __next__(self):
+        # ToDo: Check iteration progress over layers
+        # ToDo: There is still a problem interation, currently only cell level is the last loop stage.
+        # Do we need this?
+        if self.__iter_idx[0] >= len(self.layers):
+            if self.__iter_idx[1] >= len(self.layers[self.__iter_idx[0]]):
+                raise StopIteration
+        result = self.layers[self.__iter_idx[0]][self.__iter_idx[1]]
+
+        if self.__iter_idx[1] >= len(self.layers[self.__iter_idx[0]]):
+            self.__iter_idx[0] += 1
+            self.__iter_idx[1] = 0
+        else:
+            self.__iter_idx[1] += 1
+        return result
+
+    def __repr__(self):
+        return f'Weights({self.to_flat_array().tolist()})'
+
+    def to_flat_array(self) -> np.ndarray:
+        return np.hstack([weight.flatten() for weight in self.layers])
+
+    def from_flat_array(self, array):
+        new_weights = self.__reshape_flat_array__(array, self.shapes())
+        return new_weights
+
+    def are_diverged(self):
+        return any([np.isnan(x).any() for x in self.layers]) or any([np.isinf(x).any() for x in self.layers])
+
+    def are_within_bounds(self, lower_bound: float, upper_bound: float):
+        return bool(sum([((lower_bound < x) & (x > upper_bound)).size for x in self.layers]))
+
+    def apply_new_weights(self, weights: np.ndarray):
+        # TODO: Make this more Pythonic
+        new_weights = copy.deepcopy(self.layers)
         current_weight_id = 0
         for layer_id, layer in enumerate(new_weights):
             for cell_id, cell in enumerate(layer):
                 for weight_id, weight in enumerate(cell):
-                    new_weight = new_weights_list[current_weight_id]
+                    new_weight = weights[current_weight_id]
                     new_weights[layer_id][cell_id][weight_id] = new_weight
                     current_weight_id += 1
         return new_weights
 
+
+class NeuralNetwork(ABC):
+    """
+    This is the Base Network Class, including abstract functions that must be implemented.
+    """
+
     def __init__(self, **params):
         super().__init__()
         self.params = dict(epsilon=0.00000000000001)
         self.params.update(params)
         self.keras_params = dict(activation='linear', use_bias=False)
         self.states = []
+        self.model: Sequential
 
-    def get_model(self):
-        raise NotImplementedError
-
-    def get_params(self):
+    def get_params(self) -> dict:
         return self.params
 
-    def get_keras_params(self):
+    def get_keras_params(self) -> dict:
         return self.keras_params
 
     def with_params(self, **kwargs):
@@ -97,96 +147,96 @@ class NeuralNetwork(PrintingObject):
         self.keras_params.update(kwargs)
         return self
 
-    def get_weights(self):
-        return self.model.get_weights()
+    def get_weights(self) -> Weights:
+        return Weights(self.model.get_weights())
 
-    def get_weights_flat(self):
-        return np.hstack([weight.flatten() for weight in self.get_weights()])
+    def get_weights_flat(self) -> np.ndarray:
+        return self.get_weights().to_flat_array()
 
-    def set_weights(self, new_weights):
+    def set_weights(self, new_weights: Weights):
         return self.model.set_weights(new_weights)
 
-    def apply_to_weights(self, old_weights):
+    @abstractmethod
+    def apply_to_weights(self, old_weights) -> Weights:
+        # TODO: add a dogstring, telling the user what this does, e.g. what is applied?
         raise NotImplementedError
 
-    def apply_to_network(self, other_network):
+    def apply_to_network(self, other_network) -> Weights:
+        # TODO: add a dogstring, telling the user what this does, e.g. what is applied?
         new_weights = self.apply_to_weights(other_network.get_weights())
         return new_weights
 
     def attack(self, other_network):
+        # TODO: add a dogstring, telling the user what this does, e.g. what is an attack?
         other_network.set_weights(self.apply_to_network(other_network))
         return self
 
     def fuck(self, other_network):
+        # TODO: add a dogstring, telling the user what this does, e.g. what is fucking?
         self.set_weights(self.apply_to_network(other_network))
         return self
 
     def self_attack(self, iterations=1):
+        # TODO: add a dogstring, telling the user what this does, e.g. what is self attack?
         for _ in range(iterations):
             self.attack(self)
         return self
 
     def meet(self, other_network):
+        # TODO: add a dogstring, telling the user what this does, e.g. what is meeting?
         new_other_network = copy.deepcopy(other_network)
         return self.attack(new_other_network)
 
     def is_diverged(self):
-        return self.are_weights_diverged(self.get_weights())
+        return self.get_weights().are_diverged()
 
     def is_zero(self, epsilon=None):
         epsilon = epsilon or self.get_params().get('epsilon')
-        return self.are_weights_within(self.get_weights(), -epsilon, epsilon)
+        return self.get_weights().are_within_bounds(-epsilon, epsilon)
 
-    def is_fixpoint(self, degree=1, epsilon=None):
+    def is_fixpoint(self, degree: int = 1, epsilon: float = None) -> bool:
         assert degree >= 1, "degree must be >= 1"
         epsilon = epsilon or self.get_params().get('epsilon')
-        old_weights = self.get_weights()
-        new_weights = copy.deepcopy(old_weights)
+
+        new_weights = copy.deepcopy(self.get_weights())
 
         for _ in range(degree):
             new_weights = self.apply_to_weights(new_weights)
+            if new_weights.are_diverged():
+                return False
 
-        if NeuralNetwork.are_weights_diverged(new_weights):
-            return False
-        for layer_id, layer in enumerate(old_weights):
-            for cell_id, cell in enumerate(layer):
-                for weight_id, weight in enumerate(cell):
-                    new_weight = new_weights[layer_id][cell_id][weight_id]
-                    if abs(new_weight - weight) >= epsilon:
-                        return False
-        return True
+        biggerEpsilon = (np.abs(new_weights.to_flat_array() - self.get_weights().to_flat_array()) >= epsilon).any()
 
-    def repr_weights(self, weights=None):
-        return self.weights_to_string(weights or self.get_weights())
+        # Boolean Value needs to be flipped to answer "is_fixpoint"
+        return not biggerEpsilon
 
     def print_weights(self, weights=None):
-        print(self.repr_weights(weights))
+        print(weights or self.get_weights())
 
 
 class ParticleDecorator:
     next_uid = 0
 
-    def __init__(self, net):
+    def __init__(self, network):
+
+        # ToDo: Add DocString, What does it do?
+
         self.uid = self.__class__.next_uid
         self.__class__.next_uid += 1
-        self.net = net
+        self.network = network
         self.states = []
-        self.save_state(time=0,
-                        action='init',
-                        counterpart=None
-        )
+        self.save_state(time=0, action='init', counterpart=None)
 
     def __getattr__(self, name):
-        return getattr(self.net, name)
+        return getattr(self.network, name)
 
     def get_uid(self):
         return self.uid
 
     def make_state(self, **kwargs):
-        weights = self.net.get_weights_flat()
-        if any(np.isinf(weights)) or any(np.isnan(weights)):
+        if self.network.is_diverged():
             return None
-        state = {'class': self.net.__class__.__name__, 'weights': weights}
+        state = {'class': self.network.__class__.__name__, 'weights': self.network.get_weights_flat()}
         state.update(kwargs)
         return state
 
@@ -196,6 +246,7 @@ class ParticleDecorator:
             self.states += [state]
         else:
             pass
+        return True
 
     def update_state(self, number, **kwargs):
         raise NotImplementedError('Result is vague')
@@ -212,81 +263,33 @@ class ParticleDecorator:
 
 class WeightwiseNeuralNetwork(NeuralNetwork):
 
-    @staticmethod
-    def normalize_id(value, norm):
-        if norm > 1:
-            return float(value) / float(norm)
-        else:
-            return float(value)
-
     def __init__(self, width, depth, **kwargs):
+        # ToDo: Insert Docstring
         super().__init__(**kwargs)
-        self.width = width
-        self.depth = depth
+        self.width: int = width
+        self.depth: int = depth
         self.model = Sequential()
         self.model.add(Dense(units=self.width, input_dim=4, **self.keras_params))
         for _ in range(self.depth-1):
             self.model.add(Dense(units=self.width, **self.keras_params))
         self.model.add(Dense(units=1, **self.keras_params))
 
-    def get_model(self):
-        return self.model
+    def apply(self, inputs):
+        # TODO: Write about it... What does it do?
+        return self.model.predict(inputs)
 
-    def apply(self, *inputs):
-        stuff = np.transpose(np.array([[inputs[0]], [inputs[1]], [inputs[2]], [inputs[3]]]))
-        return self.model.predict(stuff)[0][0]
-
-    @classmethod
-    def compute_all_duplex_weight_points(cls, old_weights):
-        points = []
-        normal_points = []
-        max_layer_id = len(old_weights) - 1
-        for layer_id, layer in enumerate(old_weights):
-            max_cell_id = len(layer) - 1
-            for cell_id, cell in enumerate(layer):
-                max_weight_id = len(cell) - 1
-                for weight_id, weight in enumerate(cell):
-                    normal_layer_id = cls.normalize_id(layer_id, max_layer_id)
-                    normal_cell_id = cls.normalize_id(cell_id, max_cell_id)
-                    normal_weight_id = cls.normalize_id(weight_id, max_weight_id)
-
-                    points += [[weight, layer_id, cell_id, weight_id]]
-                    normal_points += [[weight, normal_layer_id, normal_cell_id, normal_weight_id]]
-        return points, normal_points
-
-    @classmethod
-    def compute_all_weight_points(cls, all_weights):
-        return cls.compute_all_duplex_weight_points(all_weights)[0]
-
-    @classmethod
-    def compute_all_normal_weight_points(cls, all_weights):
-        return cls.compute_all_duplex_weight_points(all_weights)[1]
-
-    def apply_to_weights(self, old_weights):
-        new_weights = copy.deepcopy(self.get_weights())
-        for (weight_point, normal_weight_point) in zip(*self.__class__.compute_all_duplex_weight_points(old_weights)):
-            weight, layer_id, cell_id, weight_id = weight_point
-            _, normal_layer_id, normal_cell_id, normal_weight_id = normal_weight_point
-
-            new_weight = self.apply(*normal_weight_point)
-            new_weights[layer_id][cell_id][weight_id] = new_weight
-
-            if self.params.get("print_all_weight_updates", False) and not self.is_silent():
-                print("updated old weight {weight}\t @ ({layer},{cell},{weight_id}) "
-                      "to new value {new_weight}\t calling @ ({normal_layer},{normal_cell},{normal_weight_id})").format(
-                    weight=weight, layer=layer_id, cell=cell_id, weight_id=weight_id, new_weight=new_weight,
-                    normal_layer=normal_layer_id, normal_cell=normal_cell_id, normal_weight_id=normal_weight_id)
-        return new_weights
-
-    def compute_samples(self):
-        samples = []
-        for normal_weight_point in self.compute_all_normal_weight_points(self.get_weights()):
-            weight, normal_layer_id, normal_cell_id, normal_weight_id = normal_weight_point
-
-            sample = np.transpose(np.array([[weight], [normal_layer_id], [normal_cell_id], [normal_weight_id]]))
-            samples += [sample[0]]
-        samples_array = np.asarray(samples)
-        return samples_array, samples_array[:, 0]
+    def apply_to_weights(self, weights) -> Weights:
+        # ToDo: Insert DocString
+        # Transform the weight matrix in an horizontal stack as: array([[weight, layer, cell, position], ...])
+        transformed_weights = np.asarray([
+            [weight, idx, *x] for idx, layer in enumerate(weights.layers) for x, weight in np.ndenumerate(layer)
+                         ])
+        # normalize [layer, cell, position]
+        for idx in range(1, transformed_weights.shape[1]):
+            transformed_weights[:, idx] = transformed_weights[:, idx] / np.max(transformed_weights[:, idx])
+        new_weights = self.apply(transformed_weights)
+        # use the original weight shape to transform the new tensor
+        return Weights(new_weights, flat_array_shape=weights.shapes())
 
 
 class AggregatingNeuralNetwork(NeuralNetwork):
@@ -332,9 +335,6 @@ class AggregatingNeuralNetwork(NeuralNetwork):
             self.model.add(Dense(units=width, **self.keras_params))
         self.model.add(Dense(units=self.aggregates, **self.keras_params))
 
-    def get_model(self):
-        return self.model
-
     def get_aggregator(self):
         return self.params.get('aggregator', self.aggregate_average)
 
@@ -378,11 +378,11 @@ class AggregatingNeuralNetwork(NeuralNetwork):
         new_weights = self.fill_weights(old_weights, new_weights_list)
 
         # return results
-        if self.params.get("print_all_weight_updates", False) and not self.is_silent():
-            print("updated old weight aggregations " + str(old_aggregations))
-            print("to new weight aggregations      " + str(new_aggregations))
-            print("resulting in network weights ...")
-            print(self.weights_to_string(new_weights))
+        # if self.params.get("print_all_weight_updates", False) and not self.is_silent():
+        #     print("updated old weight aggregations " + str(old_aggregations))
+        #     print("to new weight aggregations      " + str(new_aggregations))
+        #     print("resulting in network weights ...")
+        #     print(self.weights_to_string(new_weights))
         return new_weights
 
     @staticmethod
@@ -420,23 +420,23 @@ class AggregatingNeuralNetwork(NeuralNetwork):
         assert degree >= 1, "degree must be >= 1"
         epsilon = epsilon or self.get_params().get('epsilon')
 
-        old_weights = self.get_weights()
         old_aggregations, _ = self.get_aggregated_weights()
+        new_weights = copy.deepcopy(self.get_weights())
 
-        new_weights = copy.deepcopy(old_weights)
         for _ in range(degree):
             new_weights = self.apply_to_weights(new_weights)
-        if NeuralNetwork.are_weights_diverged(new_weights):
-            return False
+            if new_weights.are_diverged():
+                return False
+
+        # ToDo: Explain This, what the heck is happening?
         collection_size = self.get_amount_of_weights() // self.aggregates
         collections, leftovers = self.__class__.collect_weights(new_weights, collection_size)
         new_aggregations = [self.get_aggregator()(collection) for collection in collections]
 
-        for aggregation_id, old_aggregation in enumerate(old_aggregations):
-            new_aggregation = new_aggregations[aggregation_id]
-            if abs(new_aggregation - old_aggregation) >= epsilon:
-                return False, new_aggregations
-        return True, new_aggregations
+        # ToDo: Explain This, why are you additionally checking tolerances of aggregated weights?
+        biggerEpsilon = (np.abs(np.asarray(old_aggregations) - np.asarray(new_aggregations)) >= epsilon).any()
+        # Boolean value hast to be flipped to answer the question.
+        return True, not biggerEpsilon
 
 
 class FFTNeuralNetwork(NeuralNetwork):
@@ -473,9 +473,6 @@ class FFTNeuralNetwork(NeuralNetwork):
             self.model.add(Dense(units=width, **self.keras_params))
         self.model.add(Dense(units=self.aggregates, **self.keras_params))
 
-    def get_model(self):
-        return self.model
-
     def get_shuffler(self):
         return self.params.get('shuffler', self.shuffle_not)
 
@@ -508,11 +505,11 @@ class FFTNeuralNetwork(NeuralNetwork):
         new_weights = self.fill_weights(old_weights, new_weights_list)
 
         # return results
-        if self.params.get("print_all_weight_updates", False) and not self.is_silent():
-            print("updated old weight aggregations " + str(old_aggregation))
-            print("to new weight aggregations      " + str(new_aggregation))
-            print("resulting in network weights ...")
-            print(self.__class__.weights_to_string(new_weights))
+        # if self.params.get("print_all_weight_updates", False) and not self.is_silent():
+        #     print("updated old weight aggregations " + str(old_aggregation))
+        #     print("to new weight aggregations      " + str(new_aggregation))
+        #     print("resulting in network weights ...")
+        #     print(self.weights_to_string(new_weights))
         return new_weights
 
     def compute_samples(self):
@@ -534,9 +531,6 @@ class RecurrentNeuralNetwork(NeuralNetwork):
             self.model.add(SimpleRNN(units=width, return_sequences=True, **self.keras_params))
         self.model.add(SimpleRNN(units=self.features, return_sequences=True, **self.keras_params))
 
-    def get_model(self):
-        return self.model
-
     def apply(self, *inputs):
         stuff = np.transpose(np.array([[[inputs[i]] for i in range(len(inputs))]]))
         return self.model.predict(stuff)[0].flatten()
@@ -645,7 +639,7 @@ if __name__ == '__main__':
                 K.clear_session()
             exp.log(exp.counters)
 
-    if True:
+    if False:
         # Aggregating Neural Network
         with FixpointExperiment() as exp:
             for run_id in tqdm(range(100)):
@@ -655,7 +649,7 @@ if __name__ == '__main__':
                 K.clear_session()
             exp.log(exp.counters)
 
-    if True:
+    if False:
         #FFT Neural Network
         with FixpointExperiment() as exp:
             for run_id in tqdm(range(100)):
@@ -665,7 +659,7 @@ if __name__ == '__main__':
                 K.clear_session()
             exp.log(exp.counters)
 
-    if True:
+    if False:
         # ok so this works quite realiably
         with FixpointExperiment() as exp:
             for i in range(1):
diff --git a/code/setups/applying-fixpoints.py b/code/setups/applying-fixpoints.py
index e8bdc9f..2da1579 100644
--- a/code/setups/applying-fixpoints.py
+++ b/code/setups/applying-fixpoints.py
@@ -4,7 +4,6 @@ import os
 # Concat top Level dir to system environmental variables
 sys.path += os.path.join('..', '.')
 
-from util import *
 from experiment import *
 from network import *
 
diff --git a/code/setups/fixpoint-density.py b/code/setups/fixpoint-density.py
index 1c0419f..26b8ec2 100644
--- a/code/setups/fixpoint-density.py
+++ b/code/setups/fixpoint-density.py
@@ -3,16 +3,18 @@ import os
 # Concat top Level dir to system environmental variables
 sys.path += os.path.join('..', '.')
 
-from util import *
 from experiment import *
 from network import *
 
-import keras.backend
+import tensorflow.python.keras.backend as K
+
 
 def generate_counters():
     return {'divergent': 0, 'fix_zero': 0, 'fix_other': 0, 'fix_sec': 0, 'other': 0}
 
-def count(counters, net, notable_nets=[]):
+
+def count(counters, net, notable_nets=None):
+    notable_nets = notable_nets or []
     if net.is_diverged():
         counters['divergent'] += 1
     elif net.is_fixpoint():
@@ -52,7 +54,7 @@ if __name__ == '__main__':
                 net = ParticleDecorator(net)
                 name = str(net.__class__.__name__) + " activiation='" + str(net.get_keras_params().get('activation')) + "' use_bias='" + str(net.get_keras_params().get('use_bias')) + "'"
                 count(counters, net, notable_nets)
-                keras.backend.clear_session()
+                K.clear_session()
             all_counters += [counters]
             # all_notable_nets += [notable_nets]
             all_names += [name]
diff --git a/code/setups/known-fixpoint-variation.py b/code/setups/known-fixpoint-variation.py
index e1c070f..be0c249 100644
--- a/code/setups/known-fixpoint-variation.py
+++ b/code/setups/known-fixpoint-variation.py
@@ -5,12 +5,11 @@ import os
 # Concat top Level dir to system environmental variables
 sys.path += os.path.join('..', '.')
 
-from util import *
 from experiment import *
 from network import *
 from soup import prng
 
-import keras.backend
+import tensorflow.python.keras.backend as K
 
 
 from statistics import mean
@@ -85,7 +84,7 @@ if __name__ == '__main__':
                 exp.ys += [time_to_something]
                 # time steps still regarded as sthe initial fix-point
                 exp.zs += [time_as_fixpoint]
-                keras.backend.clear_session()
+                K.backend.clear_session()
             current_scale /= 10.0
         for d in range(exp.depth):
             exp.log('variation 10e-' + str(d))
diff --git a/code/setups/learn_from_soup.py b/code/setups/learn_from_soup.py
index f6bcb44..5cf1f1a 100644
--- a/code/setups/learn_from_soup.py
+++ b/code/setups/learn_from_soup.py
@@ -6,13 +6,12 @@ sys.path += os.path.join('..', '.')
 
 from typing import Tuple
 
-from util import *
 from experiment import *
 from network import *
 from soup import *
 
 
-import keras.backend
+import tensorflow.python.keras.backend as K
 
 from statistics import mean
 avg = mean
@@ -28,7 +27,7 @@ def generate_counters():
     return {'divergent': 0, 'fix_zero': 0, 'fix_other': 0, 'fix_sec': 0, 'other': 0}
 
 
-def count(counters, soup, notable_nets=[]):
+def count(counters, soup, notable_nets=None):
     """
     Count the occurences ot the types of weight trajectories.
 
@@ -40,6 +39,7 @@ def count(counters, soup, notable_nets=[]):
     :return:    Both the counter dictionary and the list of interessting nets.
     """
 
+    notable_nets = notable_nets or list()
     for net in soup.particles:
         if net.is_diverged():
             counters['divergent'] += 1
diff --git a/code/setups/mixed-self-fixpoints.py b/code/setups/mixed-self-fixpoints.py
index d7c494e..1c38bb1 100644
--- a/code/setups/mixed-self-fixpoints.py
+++ b/code/setups/mixed-self-fixpoints.py
@@ -6,11 +6,10 @@ from typing import Tuple
 # Concat top Level dir to system environmental variables
 sys.path += os.path.join('..', '.')
 
-from util import *
 from experiment import *
 from network import *
 
-import keras.backend
+import tensorflow.python.keras.backend as K
 
 
 def generate_counters():
@@ -23,7 +22,7 @@ def generate_counters():
     return {'divergent': 0, 'fix_zero': 0, 'fix_other': 0, 'fix_sec': 0, 'other': 0}
 
 
-def count(counters, net, notable_nets=[]):
+def count(counters, net, notable_nets=None):
     """
     Count the occurences ot the types of weight trajectories.
 
@@ -34,7 +33,7 @@ def count(counters, net, notable_nets=[]):
     :rtype      Tuple[dict, list]
     :return:    Both the counter dictionary and the list of interessting nets.
     """
-
+    notable_nets = notable_nets or list()
     if net.is_diverged():
         counters['divergent'] += 1
     elif net.is_fixpoint():
diff --git a/code/setups/mixed-soup.py b/code/setups/mixed-soup.py
index 2471e2c..84212ea 100644
--- a/code/setups/mixed-soup.py
+++ b/code/setups/mixed-soup.py
@@ -6,12 +6,11 @@ sys.path += os.path.join('..', '.')
 
 from typing import Tuple
 
-from util import *
 from experiment import *
 from network import *
 from soup import *
 
-import keras.backend
+import tensorflow.python.keras.backend as K
 
 
 def generate_counters():
@@ -24,7 +23,7 @@ def generate_counters():
     return {'divergent': 0, 'fix_zero': 0, 'fix_other': 0, 'fix_sec': 0, 'other': 0}
 
 
-def count(counters, soup, notable_nets=[]):
+def count(counters, soup, notable_nets=None):
     """
     Count the occurences ot the types of weight trajectories.
 
@@ -36,6 +35,7 @@ def count(counters, soup, notable_nets=[]):
     :return:    Both the counter dictionary and the list of interessting nets.
     """
 
+    notable_nets = notable_nets or list()
     for net in soup.particles:
         if net.is_diverged():
             counters['divergent'] += 1
diff --git a/code/setups/training-fixpoints.py b/code/setups/training-fixpoints.py
index 9d615d5..b2f19eb 100644
--- a/code/setups/training-fixpoints.py
+++ b/code/setups/training-fixpoints.py
@@ -4,16 +4,16 @@ import os
 # Concat top Level dir to system environmental variables
 sys.path += os.path.join('..', '.')
 
-from util import *
 from experiment import *
 from network import *
 
-import keras.backend as K
+import tensorflow.python.keras.backend as K
 
 def generate_counters():
     return {'divergent': 0, 'fix_zero': 0, 'fix_other': 0, 'fix_sec': 0, 'other': 0}
 
-def count(counters, net, notable_nets=[]):
+def count(counters, net, notable_nets=None):
+    notable_nets = notable_nets or list()
     if net.is_diverged():
         counters['divergent'] += 1
     elif net.is_fixpoint():
diff --git a/code/test.py b/code/test.py
index 156e354..a986443 100644
--- a/code/test.py
+++ b/code/test.py
@@ -61,7 +61,7 @@ class LearningNeuralNetwork(NeuralNetwork):
             print("updated old weight aggregations " + str(old_aggregation))
             print("to new weight aggregations      " + str(new_aggregation))
             print("resulting in network weights ...")
-            print(self.__class__.weights_to_string(new_weights))
+            print(self.weights_to_string(new_weights))
         return new_weights
 
     def with_compile_params(self, **kwargs):
diff --git a/code/util.py b/code/util.py
deleted file mode 100644
index a8604c4..0000000
--- a/code/util.py
+++ /dev/null
@@ -1,39 +0,0 @@
-class PrintingObject:
-
-    class SilenceSignal():
-        def __init__(self, obj, value):
-            self.obj = obj
-            self.new_silent = value
-        def __enter__(self):
-            self.old_silent = self.obj.get_silence()
-            self.obj.set_silence(self.new_silent)
-        def __exit__(self, exception_type, exception_value, traceback):
-            self.obj.set_silence(self.old_silent)
-    
-    def __init__(self):
-        self.silent = True
-    
-    def is_silent(self):
-        return self.silent
-    
-    def get_silence(self):
-        return self.is_silent()
-    
-    def set_silence(self, value=True):
-        self.silent = value
-        return self
-    
-    def unset_silence(self):
-        self.silent = False
-        return self
-        
-    def with_silence(self, value=True):
-        self.set_silence(value)
-        return self
-        
-    def silence(self, value=True):
-        return self.__class__.SilenceSignal(self, value)
-        
-    def _print(self, *args, **kwargs):
-        if not self.silent:
-            print(*args, **kwargs)
\ No newline at end of file
diff --git a/code/visualization.py b/code/visualization.py
deleted file mode 100644
index 69594ac..0000000
--- a/code/visualization.py
+++ /dev/null
@@ -1,283 +0,0 @@
-import os
-
-from experiment import Experiment
-# noinspection PyUnresolvedReferences
-from soup import Soup
-
-from argparse import ArgumentParser
-import numpy as np
-
-import plotly as pl
-import plotly.graph_objs as go
-
-import colorlover as cl
-
-import dill
-
-from sklearn.manifold.t_sne import TSNE, PCA
-
-
-def build_args():
-    arg_parser = ArgumentParser()
-    arg_parser.add_argument('-i', '--in_file', nargs=1, type=str)
-    arg_parser.add_argument('-o', '--out_file', nargs='?', default='out', type=str)
-    return arg_parser.parse_args()
-
-
-def build_from_soup_or_exp(soup):
-    particles = soup.historical_particles
-    particle_list = []
-    for particle in particles.values():
-        particle_dict = dict(
-            trajectory=[event['weights'] for event in particle],
-            time=[event['time'] for event in particle],
-            action=[event.get('action', None) for event in particle],
-            counterpart=[event.get('counterpart', None) for event in particle]
-        )
-        if any([x is not None for x in particle_dict['counterpart']]):
-            print('counterpart')
-        particle_list.append(particle_dict)
-    return particle_list
-
-
-def plot_latent_trajectories(soup_or_experiment, filename='latent_trajectory_plot'):
-    assert isinstance(soup_or_experiment, (Experiment, Soup))
-    bupu = cl.scales['11']['div']['RdYlGn']
-    data_dict = build_from_soup_or_exp(soup_or_experiment)
-    scale = cl.interp(bupu, len(data_dict)+1)  # Map color scale to N bins
-
-    # Fit the mebedding space
-    transformer = TSNE()
-    for particle_dict in data_dict:
-        array = np.asarray([np.hstack([x.flatten() for x in timestamp]).flatten()
-                            for timestamp in particle_dict['trajectory']])
-        particle_dict['trajectory'] = array
-        transformer.fit(array)
-
-    # Transform data accordingly and plot it
-    data = []
-    for p_id, particle_dict in enumerate(data_dict):
-        transformed = transformer._fit(np.asarray(particle_dict['trajectory']))
-        line_trace = go.Scatter(
-            x=transformed[:, 0],
-            y=transformed[:, 1],
-            text='Hovertext goes here'.format(),
-            line=dict(color=scale[p_id]),
-            # legendgroup='Position -{}'.format(pos),
-            name='Particle - {}'.format(p_id),
-            showlegend=True,
-            # hoverinfo='text',
-            mode='lines')
-        line_start = go.Scatter(mode='markers', x=[transformed[0, 0]], y=[transformed[0, 1]],
-                                marker=dict(
-                                    color='rgb(255, 0, 0)',
-                                    size=4
-                                ),
-                                showlegend=False
-                                )
-        line_end = go.Scatter(mode='markers', x=[transformed[-1, 0]], y=[transformed[-1, 1]],
-                              marker=dict(
-                                  color='rgb(0, 0, 0)',
-                                  size=4
-                              ),
-                              showlegend=False
-                              )
-        data.extend([line_trace, line_start, line_end])
-
-    layout = dict(title='{} - Latent Trajectory Movement'.format('Penis'),
-                  height=800, width=800, margin=dict(l=0, r=0, t=0, b=0))
-    # import plotly.io as pio
-    # pio.write_image(fig, filename)
-    fig = go.Figure(data=data, layout=layout)
-    pl.offline.plot(fig, auto_open=True, filename=filename)
-    pass
-
-
-def plot_latent_trajectories_3D(soup_or_experiment, filename='plot'):
-    def norm(val, a=0, b=0.25):
-        return (val - a) / (b - a)
-
-    data_list = build_from_soup_or_exp(soup_or_experiment)
-    if not data_list:
-        return
-
-    base_scale = cl.scales['9']['div']['RdYlGn']
-    # base_scale = cl.scales['9']['qual']['Set1']
-    scale = cl.interp(base_scale, len(data_list)+1)  # Map color scale to N bins
-
-    # Fit the embedding space
-    transformer = PCA(n_components=2)
-
-    array = []
-    for particle_dict in data_list:
-        array.append(particle_dict['trajectory'])
-
-    transformer.fit(np.vstack(array))
-
-    # Transform data accordingly and plot it
-    data = []
-    for p_id, particle_dict in enumerate(data_list):
-        transformed = transformer.transform(particle_dict['trajectory'])
-        line_trace = go.Scatter3d(
-            x=transformed[:, 0],
-            y=transformed[:, 1],
-            z=np.asarray(particle_dict['time']),
-            text='Particle: {}<br> It had {} lifes.'.format(p_id, len(particle_dict['trajectory'])),
-            line=dict(
-                color=scale[p_id],
-                width=4
-            ),
-            # legendgroup='Particle - {}'.format(p_id),
-            name='Particle -{}'.format(p_id),
-            showlegend=False,
-            hoverinfo='text',
-            mode='lines')
-
-        line_start = go.Scatter3d(mode='markers', x=[transformed[0, 0]], y=[transformed[0, 1]],
-                                  z=np.asarray(particle_dict['time'][0]),
-                                  marker=dict(
-                                      color='rgb(255, 0, 0)',
-                                      size=4
-                                  ),
-                                  showlegend=False
-                                  )
-
-        line_end = go.Scatter3d(mode='markers', x=[transformed[-1, 0]], y=[transformed[-1, 1]],
-                                z=np.asarray(particle_dict['time'][-1]),
-                                marker=dict(
-                                    color='rgb(0, 0, 0)',
-                                    size=4
-                                ),
-                                showlegend=False
-                                )
-
-        data.extend([line_trace, line_start, line_end])
-
-    axis_layout = dict(gridcolor='rgb(255, 255, 255)',
-                       gridwidth=3,
-                       zerolinecolor='rgb(255, 255, 255)',
-                       showbackground=True,
-                       backgroundcolor='rgb(230, 230,230)',
-                       titlefont=dict(
-                           color='black',
-                           size=30
-                           )
-                       )
-
-    layout = go.Layout(scene=dict(
-        # aspectratio=dict(x=2, y=2, z=2),
-        xaxis=dict(title='Transformed X', **axis_layout),
-        yaxis=dict(title='Transformed Y', **axis_layout),
-        zaxis=dict(title='Epoch', **axis_layout)),
-        # title='{} - Latent Trajectory Movement'.format('Soup'),
-
-        width=1024, height=1024,
-        margin=dict(l=0, r=0, b=0, t=0)
-    )
-
-    fig = go.Figure(data=data, layout=layout)
-    pl.offline.plot(fig, auto_open=True, filename=filename, validate=True)
-    pass
-
-
-def plot_histogram(bars_dict_list, filename='histogram_plot'):
-    # catagorical
-    ryb = cl.scales['10']['div']['RdYlBu']
-
-    data = []
-    for bar_id, bars_dict in bars_dict_list:
-        hist = go.Histogram(
-            histfunc="count",
-            y=bars_dict.get('value', 14),
-            x=bars_dict.get('name', 'gimme a name'),
-            showlegend=False,
-            marker=dict(
-                color=ryb[bar_id]
-            ),
-        )
-        data.append(hist)
-
-    layout=dict(title='{} Histogram Plot'.format('Experiment Name Penis'),
-                height=400, width=400, margin=dict(l=0, r=0, t=0, b=0))
-
-    fig = go.Figure(data=data, layout=layout)
-    pl.offline.plot(fig, auto_open=True, filename=filename)
-
-    pass
-
-
-def line_plot(line_dict_list, filename='lineplot'):
-    # lines with standard deviation
-    # Transform data accordingly and plot it
-    data = []
-    rdylgn = cl.scales['10']['div']['RdYlGn']
-    rdylgn_background = [scale + (0.4,) for scale in cl.to_numeric(rdylgn)]
-    for line_id, line_dict in enumerate(line_dict_list):
-        name = line_dict.get('name', 'gimme a name')
-
-        upper_bound = go.Scatter(
-            name='Upper Bound',
-            x=line_dict['x'],
-            y=line_dict['upper_y'],
-            mode='lines',
-            marker=dict(color="#444"),
-            line=dict(width=0),
-            fillcolor=rdylgn_background[line_id],
-        )
-
-        trace = go.Scatter(
-            x=line_dict['x'],
-            y=line_dict['main_y'],
-            mode='lines',
-            name=name,
-            line=dict(color=line_id),
-            fillcolor=rdylgn_background[line_id],
-            fill='tonexty')
-
-        lower_bound = go.Scatter(
-            name='Lower Bound',
-            x=line_dict['x'],
-            y=line_dict['lower_y'],
-            marker=dict(color="#444"),
-            line=dict(width=0),
-            mode='lines')
-
-        data.extend([upper_bound, trace, lower_bound])
-
-    layout=dict(title='{} Line Plot'.format('Experiment Name Penis'),
-                height=800, width=800, margin=dict(l=0, r=0, t=0, b=0))
-
-    fig = go.Figure(data=data, layout=layout)
-    pl.offline.plot(fig, auto_open=True, filename=filename)
-    pass
-
-
-def search_and_apply(absolut_file_or_folder, plotting_function, files_to_look_for=[]):
-    if os.path.isdir(absolut_file_or_folder):
-        for sub_file_or_folder in os.scandir(absolut_file_or_folder):
-            search_and_apply(sub_file_or_folder.path, plotting_function, files_to_look_for=files_to_look_for)
-    elif absolut_file_or_folder.endswith('.dill'):
-        file_or_folder = os.path.split(absolut_file_or_folder)[-1]
-        if file_or_folder in files_to_look_for and not os.path.exists('{}.html'.format(absolut_file_or_folder[:-5])):
-            print('Apply Plotting function "{func}" on file "{file}"'.format(func=plotting_function.__name__,
-                                                                             file=absolut_file_or_folder)
-                  )
-            with open(absolut_file_or_folder, 'rb') as in_f:
-                exp = dill.load(in_f)
-            try:
-                plotting_function(exp, filename='{}.html'.format(absolut_file_or_folder[:-5]))
-            except ValueError:
-                pass
-            except AttributeError:
-                pass
-        else:
-            # This was either another FilyType or Plot.html alerady exists.
-            pass
-
-
-if __name__ == '__main__':
-    args = build_args()
-    in_file = args.in_file[0]
-    out_file = args.out_file
-
-    search_and_apply(in_file, plot_latent_trajectories_3D, ["trajectorys.dill", "soup.dill"])