diff --git a/build/lib/navipy/database/__init__.py b/build/lib/navipy/database/__init__.py
index 2df843460a1acdec657782cbac74091d54d05847..cd9019245cb2e5c807b10646f5b2d70cb9967c14 100644
--- a/build/lib/navipy/database/__init__.py
+++ b/build/lib/navipy/database/__init__.py
@@ -403,7 +403,17 @@ database
         toreturn = toreturn.astype(float)
         return toreturn
 
-    def read_image(self, posorient=None, rowid=None):
+    def scene(self, posorient=None, rowid=None):
+        """Read an image at a given position-orientation or given id of row in the \
+        database.
+
+        :param posorient: a pandas Series with index \
+                          ['x','y','z','alpha_0','alpha_1','alpha_2']
+        :param rowid: an integer
+        :returns: an image
+        :rtype: numpy.ndarray
+        """
+
         if not isinstance(posorient, pd.Series):
             ('posorient should be a pandas Series')
         if posorient is not None:
@@ -436,15 +446,6 @@ database
                 raise Exception('posorient and rowid can not be both None')
             if posorient is not None:
                 rowid = self.get_posid(posorient)
-        """Read an image at a given position-orientation or given id of row in the \
-        database.
-
-        :param posorient: a pandas Series with index \
-                          ['x','y','z','alpha_0','alpha_1','alpha_2']
-        :param rowid: an integer
-        :returns: an image
-        :rtype: numpy.ndarray
-        """
         if (posorient is None) and (rowid is None):
             Exception('posorient and rowid can not be both None')
         if posorient is not None:
@@ -472,7 +473,9 @@ database
         cmaxminrange.name = cmaxminrange.id
         cmaxminrange.drop('id')
         cmaxminrange = cmaxminrange.astype(float)
-        return self.denormalise_image(image, cmaxminrange)
+        toreturn = self.denormalise_image(image, cmaxminrange)
+        toreturn = toreturn[..., np.newaxis]
+        return toreturn
 
     def denormalise_image(self, image, cmaxminrange):
         if len(image.shape) != 3:
diff --git a/build/lib/navipy/moving/agent.py b/build/lib/navipy/moving/agent.py
index ad3cd9c6c4370243c9b43b4edb629c4bd3f57340..f6f10f98d5e558e4d75193b81a698a4b33710e8e 100644
--- a/build/lib/navipy/moving/agent.py
+++ b/build/lib/navipy/moving/agent.py
@@ -15,47 +15,173 @@ from navipy.database import DataBaseLoad
 import navipy.moving.maths as navimomath
 
 
-def defaultcallback(database, posorients):
+def defaultcallback(*args, **kwargs):
     raise NameError('No Callback')
 
 
 class AbstractAgent():
+    def __init__(self):
+        self._sensors = defaultcallback
+        self._motion = defaultcallback
+        self._alter_posorientvel = defaultcallback
+        self._posorient_col = ['x', 'y', 'z',
+                               'alpha_0', 'alpha_1', 'alpha_2']
+        self._velocity_col = ['d' + col for col in self._posorient_col]
+        self._posorient_vel_col = self._posorient_col.copy()
+        self._posorient_vel_col.extend(self._velocity_col)
+        self._posorient_vel = pd.Series(
+            index=self._posorient_vel_col,
+            data=np.nan)
+
+    @property
+    def posorient(self):
+        return self._posorient_vel.loc[self._posorient_col].copy()
+
+    @posorient.setter
+    def posorient(self, posorient):
+        if isinstance(posorient, pd.Series) is False:
+            raise TypeError('posorient should be a pandas Series')
+        for col in self._posorient_col:
+            if col not in posorient.index:
+                raise KeyError(
+                    'posorient should have {} as index'.format(col))
+        self._posorient_vel.loc[self._posorient_col] = \
+            posorient.loc[self._posorient_col]
+
+    @property
+    def velocity(self):
+        return self._posorient_vel.loc[self._velocity_col].copy()
+
+    @velocity.setter
+    def velocity(self, velocity):
+        if isinstance(velocity, pd.Series) is False:
+            raise TypeError('velocity should be a pandas Series')
+        for col in self._velocity_col:
+            if col not in velocity.index:
+                raise KeyError(
+                    'velocity should have {} as index'.format(col))
+        self._posorient_vel.loc[self._velocity_col] = \
+            velocity.loc[self._velocity_col]
+
+    @property
+    def motion(self):
+        return inspect.getsourcelines(self._motion)
+
+    @property
+    def sensors(self):
+        return inspect.getsourcelines(self._sensors)
+
+    @property
+    def alter_posorientvel(self):
+        return inspect.getsourcelines(self._alter_posorientvel)
+
+    def move(self):
+        scene = self._sensors(self.posorient)
+        newpos = self._motion(self.posorient, scene)
+        alteredpos = self._alter_posorientvel(newpos)
+        self.posorient = alteredpos
+        self.velocity = alteredpos
+
+    def fly(self, max_nstep, return_tra=False):
+        """move cyberbee until max step has been performed
+        """
+        if return_tra:
+            trajectory = pd.DataFrame(index=range(0, max_nstep),
+                                      columns=self.posorient_vel_col)
+            trajectory.loc[0, :] = self._posorient_vel.copy()
+        for stepi in range(1, max_nstep):
+            print(stepi, self._posorient_vel)
+            self.move()
+            if return_tra:
+                trajectory.loc[stepi, :] = self._posorient_vel.copy()
+        if return_tra:
+            return trajectory
+        else:
+            return None
+
+
+class CyberBeeAgent(AbstractAgent):
+    """
+    A common method to make an agent moves is to update the sensory \
+    information at the current agent location, then process this \
+    information such to deduce the agent motion, and finally displaced\
+    the agent at its new location. This iterative method can be used \
+    with a wide range of models.
+    In navipy the update of the sensory information is done by the \
+    Cyberbee a class interfacing blender with the navipy, such that \
+    visual information can be rendered at the agent location.
+    To use the CyberBeeAgent you first need to create a function with \
+    input the scene and the position orientation of the agent, and \
+    with output the agent motion. The CyberBeeAgent can then be moved \
+    for a single step, or fly until a given number of movement has \
+    been effectuated or the agent stopped.
+    """
+
+    def __init__(self, cyberbee):
+        AbstractAgent.__init__(self)
+        AbstractAgent._alter_posorientvel = \
+            lambda motion_vec: navimomath.next_pos(motion_vec,
+                                                   move_mode='free_run')
+        self.sensors = cyberbee.scene
+
+    @AbstractAgent.sensors.setter
+    def sensors(self, cyberbee):
+        self._sensors = cyberbee.scene
+
+    @AbstractAgent.motion.setter
+    def motion(self, motion):
+        self._motion = motion
+
+
+class GridAgent(AbstractAgent, Process):
     """
-    An abtract class for agent
+    The use of a close loop model including visual rendering is \
+    sometimes too slow to efficiently test several models or tune the \
+    parameters of a given models. The GridAgent solves this problem by \
+    restricting the agent motion on locations with rendered scene. The \
+    agent moves thus on a grid, and its next position is always \
+    snapped to the closest grid location. The finer the grid is, the \
+    larger the database storing all sceneries and grid location is; \
+    but also the more accurate the agent motion is. The grid size \
+    depend on the storage space, the time you can wait for the \
+    database creation, and how sensitive to exact location your model is.
+    Similar to the CyberBeeAgent, your navigational model should be \
+    contained in a function with input the scene and the position \
+    orientation of the agent, and with output the agent motion. The \
+    agent can be move a single step, or fly until a given number of \
+    movement has been effectuated or the agent stopped. It is here \
+    worth mentioning that the GridAgent inherit from the Process \
+    class of the multiprocessing module of the standard python \
+    library. Thus, several GridAgents can safely be run in parallel.
     """
 
-    def __init__(self,
-                 database_filename,
-                 memory_friendly=False):
+    def __init__(self, database_filename,
+                 posorients_queue=None,
+                 results_queue=None):
+        if (posorients_queue is not None) and (results_queue is not None):
+            multiprocessing.Process.__init__(self)
+        AbstractAgent.__init__(self)
+        self._alter_posorientvel = self.snap_to_grid
+        self.sensors = database_filename
 
+    @AbstractAgent.sensors.setter
+    def sensors(self, database_filename):
         self.db = DataBaseLoad(database_filename)
-        self.dbname = database_filename
-        if memory_friendly:
-            self.__posorients = None
-        else:
-            self.__posorients = self.db.posorients
-        # set mode of motion
-        mode_move = {'mode': 'on_cubic_grid',
-                     'param': {'grid_spacing':
-                               pd.Series(data=1,
-                                         index=['dx', 'dy', 'dz'])}}
-        self.mode_of_motion = mode_move
+        self._posorients = self.db.posorients
+        self._sensors = self.db.scene
 
-    @property
-    def posorients(self):
-        toreturn = self.__posorients
-        if toreturn is not None:
-            toreturn = toreturn.copy()
-        return toreturn
+    @AbstractAgent.motion.setter
+    def motion(self, motion):
+        self._motion = motion
 
     @property
     def mode_of_motion(self):
         """
         """
-        toreturn = self.__mode_move
+        toreturn = self._mode_move
         toreturn['describe'] = \
             navimomath.mode_moves_supported()[
-                self.__mode_move['mode']]['describe']
+                self._mode_move['mode']]['describe']
         return toreturn
 
     @mode_of_motion.setter
@@ -75,165 +201,109 @@ class AbstractAgent():
                 if param not in mode['param']:
                     raise KeyError(
                         "'{}' is not in mode['param']".format(param))
-            self.__mode_move = mode
+            self._mode_move = mode
         else:
             raise ValueError('mode is not supported')
 
-    def abstractmove(self, posorients_vel):
-        if isinstance(posorients_vel, pd.Series) is False:
-            raise TypeError('posorients_vel should be a pandas Series')
-        for col in ['x', 'y', 'z', 'alpha_0', 'alpha_1', 'alpha_2',
-                    'dx', 'dy', 'dz', 'dalpha_0', 'dalpha_1', 'dalpha_2']:
-            if col not in posorients_vel.index:
-                raise KeyError(
-                    'posorients_vel should have {} as index'.format(col))
-        # Compute the next position
-        posorients_vel = navimomath.next_pos(
-            posorients_vel,
-            move_mode=self.__mode_move['mode'],
-            move_param=self.__mode_move['param'])
-
-        # Compute the closest possible position
-        if posorients_vel is None:
-            tmp = navimomath.closest_pos_memory_friendly(
-                posorients_vel,
-                self.db)
-            posorients_vel[['x', 'y', 'z',
-                            'alpha_0', 'alpha_1', 'alpha_2']] = tmp
-            posorients_vel.name = tmp.name
-        else:
-            tmp = navimomath.closest_pos(
-                posorients_vel,
-                self.__posorients)
-            posorients_vel[['x', 'y', 'z',
-                            'alpha_0', 'alpha_1', 'alpha_2']] = tmp
-            posorients_vel.name = tmp.name
-        return posorients_vel
-
-
-class Single(AbstractAgent, Process):
-
-    def __init__(self,
-                 database_filename,
-                 initial_condition,
-                 memory_friendly=False,
-                 posorients_queue=None,
-                 results_queue=None):
-        if (posorients_queue is not None) and (results_queue is not None):
-            multiprocessing.Process.__init__(self)
-        AbstractAgent.__init__(self, database_filename,
-                               memory_friendly)
-
-        self.__posorientvel = pd.Series(
-            data=0,
-            index=['x', 'y', 'z',
-                   'alpha_0', 'alpha_1', 'alpha_2',
-                   'dx', 'dy', 'dz',
-                   'dalpha_0', 'dalpha_1', 'dalpha_2'],
-            dtype=np.float)
-
-        if isinstance(initial_condition, pd.Series):
-            if is_numeric_dtype(initial_condition):
-                common_id = list(set(initial_condition.index).intersection(
-                    self.__posorientvel.index))
-                self.__posorientvel.loc[common_id] = \
-                    initial_condition.loc[common_id]
-            else:
-                raise TypeError('vel should be numeric')
+    def snap_to_grid(self, posorient_vel):
+        posorient_vel = navimomath.next_pos(
+            posorient_vel,
+            move_mode=self._mode_move['mode'],
+            move_param=self._mode_move['param'])
+        tmp = navimomath.closest_pos(
+            posorient_vel, self._posorients)
+        posorient_vel.loc[self._posorient_col] = \
+            tmp.loc[self._posorient_col]
+        posorient_vel.name = tmp.name
+        return posorient_vel
 
+    def move(self):
+        if hasattr(self, '_mode_move'):
+            AbstractAgent.move(self)
         else:
-            raise TypeError('vel should be a pandas Series')
+            raise AttributeError(
+                'GridAgent object has no attribute _mode_move\n' +
+                'Please set the mode of motion')
 
-        self.__posorients_queue = posorients_queue
-        self.__results_queue = results_queue
-        self.__callback_function = defaultcallback
-
-    def move(self):
-        # Compute the next position
-        tmp = self.__callback_function(database=self.db,
-                                       posorient=self.__posorientvel)
-        common_id = list(set(tmp.index).intersection(
-            self.__posorientvel.index))
-        self.__posorientvel.loc[common_id] = tmp.loc[common_id]
-        self.__posorientvel = self.abstractmove(self.__posorientvel)
-
-    def fly(self,  nsteps):
-        """move until either speed is null, or nsteps has been reached"""
-        prev_move = self.__posorientvel
-        for stepi in range(nsteps):
-            self.move()
-            if prev_move.equals(self.__posorientvel):
-                break
-            prev_move = self.__posorientvel
+    def fly(self, max_nstep, return_tra=False):
+        if hasattr(self, '_mode_move'):
+            return AbstractAgent.fly(self, max_nstep, return_tra)
+        else:
+            raise AttributeError(
+                'GridAgent object has no attribute _mode_move\n' +
+                'Please set the mode of motion')
 
     def run(self):
         """ Only supported when multiprocess"""
-        if self.__posorients_queue is None or self.__results_queue is None:
+        if self._posorients_queue is None or self._results_queue is None:
             raise NameError('Single agent class has not be inititialised '
                             + 'with multiprocessing suppport')
         proc_name = self.name
         print('Process {} started'.format(proc_name))
         while True:
-            start_posorient = self.__posorients_queue.get(timeout=1)
+            start_posorient = self._posorients_queue.get(timeout=1)
             if start_posorient is None:
                 # Poison pill means shutdown)
                 break
             common_id = list(set(start_posorient.index).intersection(
-                self.__posorientvel.index))
-            self.__posorientvel.loc[common_id] = start_posorient.loc[common_id]
+                self._posorientvel.index))
+            self._posorientvel.loc[common_id] = start_posorient.loc[common_id]
             self.move()
-            next_posorient = self.__posorientvel
+            next_posorient = self._posorientvel
 
-            self.__posorients_queue.task_done()
-            self.__results_queue.put((start_posorient, next_posorient))
-        self.__posorients_queue.task_done()
+            self._posorients_queue.task_done()
+            self._results_queue.put((start_posorient, next_posorient))
+        self._posorients_queue.task_done()
         print('Process {} done'.format(proc_name))
 
-    @property
-    def callback_function(self):
-        return inspect.getsourcelines(self.__callback_function)
-
-    @callback_function.setter
-    def callback_function(self, callback_function):
-        self.__callback_function = callback_function
-
-    @property
-    def position(self):
-        return self.__posorientvel.loc[['x', 'y', 'z']]
-
-    @property
-    def velocity(self):
-        return self.__posorientvel.loc[['dx', 'dy', 'dz']]
-
-    @property
-    def orientation(self):
-        return self.__posorientvel.loc[['alpha_0', 'alpha_1', 'alpha_2']]
-
-    @property
-    def angular_velocity(self):
-        return self.__posorientvel.loc[['dalpha_0', 'dalpha_1', 'dalpha_2']]
-
 
-class Multi(AbstractAgent):
+class GraphAgent():
+    """
+    As mentioned above, in every model of navigation the agent motion \
+    is derived from its current external state, its position \
+    orientation as well as the derivatives, and its internal state. \
+    However, when the agent motion is only derived from its current \
+    position orientation, and what is seen from this location, the \
+    simulation of an agent can be drastically simplified. Indeed, \
+    not only the scene at relevant location can be pre-rendered, but \
+    the motion of the agent from those locations as well. The agent \
+    being restricted to move from relevant locations to relevant \
+    locations, a graph of interconnected locations can be built. The \
+    nodes of the graph are the relevant locations, and the directed \
+    edges the motion of the agent from one location to the next. \
+    GraphAgent can build such graph by simply using a database of \
+    pre-rendered scenery at relevant locations, and a function \
+    giving the motion of the agent from a scene and the agent \
+    position orientation. Once the graph has been generated, \
+    attractors can be found, the number of locations converging to \
+    those (i.e. the catchment area or volume), if two locations are \
+    connected, etc.
+    To speed up certain calculations, additional values can stored \
+    at each graph node and access from the callback function. It is \
+    worth mentioning a warning here. The size of the graph can be \
+    incredibly large. Thus, not too much information can be stored \
+    at each node. To assess the memory size of the graph before \
+    creating it, one can use the tool agent.tools.assess_graphmemsize.
+    """
 
     def __init__(self, database_filename):
-        super().__init__(database_filename, False)
+        self.db = DataBaseLoad(database_filename)
         # Init the graph
-        self.__graph = nx.DiGraph()
+        self._graph = nx.DiGraph()
         for row_id, posor in self.db.posorients.iterrows():
             posor.name = row_id
-            self.__graph.add_node(row_id,
-                                  posorient=posor)
+            self._graph.add_node(row_id,
+                                 posorient=posor)
 
     @property
     def graph(self):
-        return self.__graph
+        return self._graph
 
     @graph.setter
     def graph(self, graph):
         if isinstance(graph, nx.DiGraph) is False:
             raise TypeError('graph is not a nx.DiGraph')
-        self.__graph = graph.copy()
+        self._graph = graph.copy()
         self.check_graph()
 
     def build_graph(self, callback_function,
@@ -243,17 +313,14 @@ class Multi(AbstractAgent):
         results_edges = []
         posorients_queue = JoinableQueue()
         results_queue = Queue()
-        for node in self.__graph.nodes:
-            posorients_queue.put(self.__graph.nodes[node]['posorient'])
-            initpos = 0 * self.__graph.nodes[node]['posorient']
+        for node in self._graph.nodes:
+            posorients_queue.put(self._graph.nodes[node]['posorient'])
 
         # Start ndatabase loader
         num_agents = ncpu
-        agents = [Single(self.dbname,
-                         initial_condition=initpos,
-                         memory_friendly=False,
-                         posorients_queue=posorients_queue,
-                         results_queue=results_queue)
+        agents = [GridAgent(self.dbname,
+                            posorients_queue=posorients_queue,
+                            results_queue=results_queue)
                   for _ in range(num_agents)]
         for w in agents:
             w.callback_function = callback_function
@@ -266,21 +333,21 @@ class Multi(AbstractAgent):
         # Wait for all of the tasks to finish
         # posorients_queue.join()
 
-        for _ in range(nx.number_of_nodes(self.__graph)):
+        for _ in range(nx.number_of_nodes(self._graph)):
             result = results_queue.get(timeout=timeout)
             results_edges.append((result[0].name,
                                   result[1].name))
             # print(results_edges[-1])
-        self.__graph.add_edges_from(results_edges)
+        self._graph.add_edges_from(results_edges)
         self.check_graph()
 
     def check_graph(self):
         self.check_single_target()
 
     def check_single_target(self):
-        for node in self.__graph.nodes:
+        for node in self._graph.nodes:
             # not connected -> loop not ran
-            for count, _ in enumerate(self.__graph.neighbors(node)):
+            for count, _ in enumerate(self._graph.neighbors(node)):
                 # count == 0 -> connected to one node
                 # count == 1 -> connected to two nodes
                 if count > 0:
@@ -291,7 +358,7 @@ class Multi(AbstractAgent):
         """Return a list of node going to each attractor in a graph
         """
         attractors = list()
-        for attractor in nx.attracting_components(self.__graph):
+        for attractor in nx.attracting_components(self._graph):
             att = dict()
             att['attractor'] = attractor
             attractors.append(att)
@@ -349,13 +416,13 @@ class Multi(AbstractAgent):
 
     def reach_goals(self, goals):
         """ Return all paths to the goals """
-        return nx.shortest_path(self.__graph, target=goals)
+        return nx.shortest_path(self._graph, target=goals)
 
     def neighboring_nodes(self, target):
         """ Return the nodes going to the target """
         # Reverse graph because nx.neighbors give the end node
         # and we want to find the start node going to target
         # not where target goes.
-        tmpgraph = self.__graph.reverse(copy=True)
+        tmpgraph = self._graph.reverse(copy=True)
         neighbors = tmpgraph.neighbors(target)
         return neighbors
diff --git a/build/lib/navipy/moving/test_agent.py b/build/lib/navipy/moving/test_agent.py
index 8775361fbcede6c9ee87feb54c9d41bd8ca496c5..5f73a7a0e743a0cfba81b0dffd9b85c43f2e7dfe 100644
--- a/build/lib/navipy/moving/test_agent.py
+++ b/build/lib/navipy/moving/test_agent.py
@@ -1,5 +1,5 @@
 """
-Test of maths
+Test of agent
 """
 import numpy as np
 import pandas as pd
@@ -17,78 +17,86 @@ class TestNavipyMovingAgent(unittest.TestCase):
         self.mydb_filename = pkg_resources.resource_filename(
             'navipy', 'resources/database.db')
         self.mydb = navidb.DataBaseLoad(self.mydb_filename)
+        self.__posorient_col = ['x', 'y', 'z',
+                                'alpha_0', 'alpha_1', 'alpha_2']
+        self.__velocity_col = ['d' + col for col in self.__posorient_col]
+        self.__posorient_vel_col = self.__posorient_col
+        self.__posorient_vel_col.extend(self.__velocity_col)
 
-    def test_memfriendly(self):
-        """posorient is loaded if memory_friendly is False """
-        agent = naviagent.AbstractAgent(self.mydb_filename,
-                                        memory_friendly=False)
-        self.assertTrue(
-            isinstance(agent.posorients, pd.DataFrame),
-            'posorients should be a pd.DataFrame when memfriendly is false')
-        agent = naviagent.AbstractAgent(self.mydb_filename,
-                                        memory_friendly=True)
-        self.assertTrue(
-            agent.posorients is None,
-            'posorients should be None when memfriendly is true')
-
-    def test_abstractmove_inputs(self):
-        """abstractmove should TypeError if not pandas Series """
-        agent = naviagent.AbstractAgent(self.mydb_filename,
-                                        memory_friendly=False)
-        with self.assertRaises(TypeError):
-            agent.abstractmove('NotPandasSeries')
-
-        posorient_vel = pd.Series()
-        for col in ['x', 'y', 'z', 'alpha_0', 'alpha_1', 'alpha_2',
-                    'dx', 'dy', 'dz', 'dalpha_0', 'dalpha_1', 'dalpha_2']:
-            with self.assertRaises(KeyError):
-                agent.abstractmove(posorient_vel)
-            posorient_vel[col] = 2
-
-    def test_abstractmove_null_vellocity(self):
-        """abstractmove should leads to same point with null vel"""
-        agent = naviagent.AbstractAgent(self.mydb_filename,
-                                        memory_friendly=False)
-
-        posorient_vel = pd.Series(data=0,
-                                  index=['x', 'y', 'z',
-                                         'alpha_0', 'alpha_1', 'alpha_2',
-                                         'dx', 'dy', 'dz',
-                                         'dalpha_0', 'dalpha_1', 'dalpha_2'])
-        pos = self.mydb.read_posorient(rowid=1)
-        posorient_vel.loc[['x', 'y', 'z']] = pos.loc[['x', 'y', 'z']]
-
-        newpos = agent.abstractmove(posorient_vel)
-        self.assertTrue(newpos.equals(posorient_vel),
-                        'Agent moved although velocity is null')
+    #
+    # AbstractAgent
+    #
+    def test_move_abstractagent(self):
+        agent = naviagent.AbstractAgent()
+        with self.assertRaises(NameError):
+            agent.move()
+
+    def test_fly_abstractagent(self):
+        agent = naviagent.AbstractAgent()
+        with self.assertRaises(NameError):
+            agent.fly(max_nstep=10)
 
     #
-    # Single
+    # GridAgent
     #
-    def test_init_inputs(self):
-        initial_condition = 'A'
-        with self.assertRaises(TypeError):
-            naviagent.Single(self.mydb_filename,
-                             initial_condition,
-                             memory_friendly=False)
-
-        initial_condition = pd.Series(index=['x'], data='a')
-        with self.assertRaises(TypeError):
-            naviagent.Single(self.mydb_filename,
-                             initial_condition,
-                             memory_friendly=False)
+    def test_move_gridagent(self):
+        agent = naviagent.GridAgent(self.mydb_filename)
+        initposorient = agent.db.posorients.loc[13, :]
+        initposovel = pd.Series(data=0,
+                                index=self.__posorient_vel_col)
+        initposovel.loc[initposorient.index] = initposorient
+        agent.posorient = initposovel
+        agent.motion = lambda posorient, scene:\
+            pd.Series(data=0,
+                      index=self.__posorient_vel_col)
+        with self.assertRaises(AttributeError):
+            agent.move()
+        mode_move = {'mode': 'on_cubic_grid',
+                     'param': {'grid_spacing':
+                               pd.Series(data=1,
+                                         index=['dx', 'dy', 'dz'])}}
+        agent.mode_of_motion = mode_move
+        agent.move()
+        obtained = agent.posorient
+        self.assertTrue(np.allclose(
+            obtained, initposorient.loc[obtained.index]))
+
+    def test_fly_gridagent(self):
+        agent = naviagent.GridAgent(self.mydb_filename)
+        initposorient = agent.db.posorients.loc[13, :]
+        initposovel = pd.Series(data=0,
+                                index=self.__posorient_vel_col)
+        initposovel.loc[initposorient.index] = initposorient
+        agent.posorient = initposovel
+        agent.motion = lambda posorient, scene:\
+            pd.Series(data=0,
+                      index=self.__posorient_vel_col)
+        with self.assertRaises(AttributeError):
+            agent.fly(max_nstep=10)
+        mode_move = {'mode': 'on_cubic_grid',
+                     'param': {'grid_spacing':
+                               pd.Series(data=1,
+                                         index=['dx', 'dy', 'dz'])}}
+        agent.mode_of_motion = mode_move
+        agent.fly(max_nstep=10)
+        obtained = agent.posorient
+        print(obtained)
+        print(initposorient.loc[obtained.index])
+        self.assertTrue(np.allclose(obtained,
+                                    initposorient.loc[obtained.index]))
 
     #
-    # Multi
+    # GraphAgent
     #
-    def test_init(self):
-        agent = naviagent.Multi(self.mydb_filename)
+
+    def test_init_graphagent(self):
+        agent = naviagent.GraphAgent(self.mydb_filename)
         self.assertEqual(sorted(agent.graph.nodes),
                          sorted(list(self.mydb.posorients.index)),
                          'Init of graph failed. Node missmatch')
 
     def test_graph_setter(self):
-        agent = naviagent.Multi(self.mydb_filename)
+        agent = naviagent.GraphAgent(self.mydb_filename)
         graph_nodes = list(agent.graph.nodes)
         graph_edges = list()
         for gnode in graph_nodes[1:]:
@@ -113,7 +121,7 @@ class TestNavipyMovingAgent(unittest.TestCase):
         3 Two loops attractors
         """
         # Test all node to first
-        agent = naviagent.Multi(self.mydb_filename)
+        agent = naviagent.GraphAgent(self.mydb_filename)
 
         graph_nodes = list(agent.graph.nodes)
         graph_edges = list()
@@ -175,7 +183,7 @@ class TestNavipyMovingAgent(unittest.TestCase):
         2. Saddle points
         3. Local minima
         """
-        agent = naviagent.Multi(self.mydb_filename)
+        agent = naviagent.GraphAgent(self.mydb_filename)
         # Local maxima
         graph_nodes = list(agent.graph.nodes)
         graph_edges = list()
diff --git a/build/lib/navipy/rendering/cyber_bee.py b/build/lib/navipy/rendering/cyber_bee.py
index 9c203e55a30fae9d6fdc3189894cf868aa336e1f..530a11b38698a1608a72c506c7e711aeed2ca974 100644
--- a/build/lib/navipy/rendering/cyber_bee.py
+++ b/build/lib/navipy/rendering/cyber_bee.py
@@ -376,6 +376,20 @@ class Cyberbee():
         distance = distance[:, :, 0]
         return distance
 
+    def scene(self, posorient):
+        """ update position orientation and return a RGBD image
+
+        :param posorient: is a 1x6 vector containing:
+             x,y,z, angle_1, angle_2, angle_3,
+             here the angles are euler rotation around the axis
+             specified by scene.camera.rotation_mode
+        :type posorient: 1x6 double array
+        """
+        self.update(posorient)
+        image = self.image
+        image[:, :, 3] = self.distance
+        return image
+
 
 if __name__ == "__main__":
     # Initiate the Cyberbee
diff --git a/navipy.egg-info/SOURCES.txt b/navipy.egg-info/SOURCES.txt
index f0f931e235dddb99eb6045a59229abd5918b4d7e..fac8f815f529879e696ebbd5fe66152fd9f0625e 100644
--- a/navipy.egg-info/SOURCES.txt
+++ b/navipy.egg-info/SOURCES.txt
@@ -1,3 +1,4 @@
+README.md
 setup.py
 navipy/__init__.py
 navipy/python_test.py
@@ -12,6 +13,7 @@ navipy/database/__init__.py
 navipy/database/tools.py
 navipy/moving/__init__.py
 navipy/moving/agent.py
+navipy/moving/agent_old.py
 navipy/moving/maths.py
 navipy/moving/test_agent.py
 navipy/moving/test_maths.py
diff --git a/navipy/database/__init__.py b/navipy/database/__init__.py
index 2df843460a1acdec657782cbac74091d54d05847..cd9019245cb2e5c807b10646f5b2d70cb9967c14 100644
--- a/navipy/database/__init__.py
+++ b/navipy/database/__init__.py
@@ -403,7 +403,17 @@ database
         toreturn = toreturn.astype(float)
         return toreturn
 
-    def read_image(self, posorient=None, rowid=None):
+    def scene(self, posorient=None, rowid=None):
+        """Read an image at a given position-orientation or given id of row in the \
+        database.
+
+        :param posorient: a pandas Series with index \
+                          ['x','y','z','alpha_0','alpha_1','alpha_2']
+        :param rowid: an integer
+        :returns: an image
+        :rtype: numpy.ndarray
+        """
+
         if not isinstance(posorient, pd.Series):
             ('posorient should be a pandas Series')
         if posorient is not None:
@@ -436,15 +446,6 @@ database
                 raise Exception('posorient and rowid can not be both None')
             if posorient is not None:
                 rowid = self.get_posid(posorient)
-        """Read an image at a given position-orientation or given id of row in the \
-        database.
-
-        :param posorient: a pandas Series with index \
-                          ['x','y','z','alpha_0','alpha_1','alpha_2']
-        :param rowid: an integer
-        :returns: an image
-        :rtype: numpy.ndarray
-        """
         if (posorient is None) and (rowid is None):
             Exception('posorient and rowid can not be both None')
         if posorient is not None:
@@ -472,7 +473,9 @@ database
         cmaxminrange.name = cmaxminrange.id
         cmaxminrange.drop('id')
         cmaxminrange = cmaxminrange.astype(float)
-        return self.denormalise_image(image, cmaxminrange)
+        toreturn = self.denormalise_image(image, cmaxminrange)
+        toreturn = toreturn[..., np.newaxis]
+        return toreturn
 
     def denormalise_image(self, image, cmaxminrange):
         if len(image.shape) != 3:
diff --git a/navipy/moving/agent.py b/navipy/moving/agent.py
index e12f39cc4038da280d3d37466ad714bc185932ad..f6f10f98d5e558e4d75193b81a698a4b33710e8e 100644
--- a/navipy/moving/agent.py
+++ b/navipy/moving/agent.py
@@ -21,64 +21,64 @@ def defaultcallback(*args, **kwargs):
 
 class AbstractAgent():
     def __init__(self):
-        self.__sensors = defaultcallback
-        self.__motion = defaultcallback
-        self.__alter_posorientvel = defaultcallback
-        self.__posorient_col = ['x', 'y', 'z',
-                                'alpha_0', 'alpha_1', 'alpha_2']
-        self.__velocity_col = ['d' + col for col in self.__posorient_col]
-        self.__posorient_vel_col = self.__posorient_col.append(
-            self.__velocity_col)
-        self.__posorient_vel = pd.Series(
-            index=self.__posorient_vel_col,
+        self._sensors = defaultcallback
+        self._motion = defaultcallback
+        self._alter_posorientvel = defaultcallback
+        self._posorient_col = ['x', 'y', 'z',
+                               'alpha_0', 'alpha_1', 'alpha_2']
+        self._velocity_col = ['d' + col for col in self._posorient_col]
+        self._posorient_vel_col = self._posorient_col.copy()
+        self._posorient_vel_col.extend(self._velocity_col)
+        self._posorient_vel = pd.Series(
+            index=self._posorient_vel_col,
             data=np.nan)
 
     @property
     def posorient(self):
-        return self.__posorient_vel.loc[self.__posorient_col].copy()
+        return self._posorient_vel.loc[self._posorient_col].copy()
 
     @posorient.setter
     def posorient(self, posorient):
         if isinstance(posorient, pd.Series) is False:
             raise TypeError('posorient should be a pandas Series')
-        for col in self.__posorient_col:
+        for col in self._posorient_col:
             if col not in posorient.index:
                 raise KeyError(
                     'posorient should have {} as index'.format(col))
-        self.__posorient_vel.loc[self.__posorient_col] = \
-            posorient.loc[self.__posorient_col]
+        self._posorient_vel.loc[self._posorient_col] = \
+            posorient.loc[self._posorient_col]
 
     @property
     def velocity(self):
-        return self.__posorient_vel.loc[self.__velocity_col].copy()
+        return self._posorient_vel.loc[self._velocity_col].copy()
 
     @velocity.setter
     def velocity(self, velocity):
         if isinstance(velocity, pd.Series) is False:
             raise TypeError('velocity should be a pandas Series')
-        for col in self.__velocity_col:
+        for col in self._velocity_col:
             if col not in velocity.index:
                 raise KeyError(
                     'velocity should have {} as index'.format(col))
-        self.__posorient_vel.loc[self.__velocity_col] = \
-            velocity.loc[self.__velocity_col]
+        self._posorient_vel.loc[self._velocity_col] = \
+            velocity.loc[self._velocity_col]
 
     @property
     def motion(self):
-        return inspect.getsourcelines(self.__motion)
+        return inspect.getsourcelines(self._motion)
 
     @property
     def sensors(self):
-        return inspect.getsourcelines(self.__sensors)
+        return inspect.getsourcelines(self._sensors)
 
     @property
     def alter_posorientvel(self):
-        return inspect.getsourcelines(self.__alter_posorientvel)
+        return inspect.getsourcelines(self._alter_posorientvel)
 
     def move(self):
-        scene = self.__sensors(self.posorient)
-        newpos = self.__motion(self.posorient, scene)
-        alteredpos = self.__alter_posorientvel(newpos)
+        scene = self._sensors(self.posorient)
+        newpos = self._motion(self.posorient, scene)
+        alteredpos = self._alter_posorientvel(newpos)
         self.posorient = alteredpos
         self.velocity = alteredpos
 
@@ -88,11 +88,12 @@ class AbstractAgent():
         if return_tra:
             trajectory = pd.DataFrame(index=range(0, max_nstep),
                                       columns=self.posorient_vel_col)
-            trajectory.loc[0, :] = self.__posorient_col.copy()
+            trajectory.loc[0, :] = self._posorient_vel.copy()
         for stepi in range(1, max_nstep):
+            print(stepi, self._posorient_vel)
             self.move()
             if return_tra:
-                trajectory.loc[stepi, :] = self.__posorient_col.copy()
+                trajectory.loc[stepi, :] = self._posorient_vel.copy()
         if return_tra:
             return trajectory
         else:
@@ -118,18 +119,18 @@ class CyberBeeAgent(AbstractAgent):
 
     def __init__(self, cyberbee):
         AbstractAgent.__init__(self)
-        AbstractAgent.__alter_posorientvel = \
+        AbstractAgent._alter_posorientvel = \
             lambda motion_vec: navimomath.next_pos(motion_vec,
                                                    move_mode='free_run')
         self.sensors = cyberbee.scene
 
     @AbstractAgent.sensors.setter
     def sensors(self, cyberbee):
-        self.__sensors = cyberbee.scene
+        self._sensors = cyberbee.scene
 
     @AbstractAgent.motion.setter
     def motion(self, motion):
-        self.__motion = motion
+        self._motion = motion
 
 
 class GridAgent(AbstractAgent, Process):
@@ -160,27 +161,27 @@ class GridAgent(AbstractAgent, Process):
         if (posorients_queue is not None) and (results_queue is not None):
             multiprocessing.Process.__init__(self)
         AbstractAgent.__init__(self)
-        AbstractAgent.__alter_posorientvel = self.snap_to_grid
+        self._alter_posorientvel = self.snap_to_grid
         self.sensors = database_filename
 
     @AbstractAgent.sensors.setter
     def sensors(self, database_filename):
         self.db = DataBaseLoad(database_filename)
-        self.__posorients = self.db.posorients()
-        self.__sensors = self.db.scene
+        self._posorients = self.db.posorients
+        self._sensors = self.db.scene
 
     @AbstractAgent.motion.setter
     def motion(self, motion):
-        self.__motion = motion
+        self._motion = motion
 
     @property
     def mode_of_motion(self):
         """
         """
-        toreturn = self.__mode_move
+        toreturn = self._mode_move
         toreturn['describe'] = \
             navimomath.mode_moves_supported()[
-                self.__mode_move['mode']]['describe']
+                self._mode_move['mode']]['describe']
         return toreturn
 
     @mode_of_motion.setter
@@ -200,43 +201,59 @@ class GridAgent(AbstractAgent, Process):
                 if param not in mode['param']:
                     raise KeyError(
                         "'{}' is not in mode['param']".format(param))
-            self.__mode_move = mode
+            self._mode_move = mode
         else:
             raise ValueError('mode is not supported')
 
     def snap_to_grid(self, posorient_vel):
         posorient_vel = navimomath.next_pos(
             posorient_vel,
-            move_mode=self.__mode_move['mode'],
-            move_param=self.__mode_move['param'])
+            move_mode=self._mode_move['mode'],
+            move_param=self._mode_move['param'])
         tmp = navimomath.closest_pos(
-            posorient_vel, self.__posorients)
-        posorient_vel[['x', 'y', 'z',
-                       'alpha_0', 'alpha_1', 'alpha_2']] = tmp
+            posorient_vel, self._posorients)
+        posorient_vel.loc[self._posorient_col] = \
+            tmp.loc[self._posorient_col]
         posorient_vel.name = tmp.name
         return posorient_vel
 
+    def move(self):
+        if hasattr(self, '_mode_move'):
+            AbstractAgent.move(self)
+        else:
+            raise AttributeError(
+                'GridAgent object has no attribute _mode_move\n' +
+                'Please set the mode of motion')
+
+    def fly(self, max_nstep, return_tra=False):
+        if hasattr(self, '_mode_move'):
+            return AbstractAgent.fly(self, max_nstep, return_tra)
+        else:
+            raise AttributeError(
+                'GridAgent object has no attribute _mode_move\n' +
+                'Please set the mode of motion')
+
     def run(self):
         """ Only supported when multiprocess"""
-        if self.__posorients_queue is None or self.__results_queue is None:
+        if self._posorients_queue is None or self._results_queue is None:
             raise NameError('Single agent class has not be inititialised '
                             + 'with multiprocessing suppport')
         proc_name = self.name
         print('Process {} started'.format(proc_name))
         while True:
-            start_posorient = self.__posorients_queue.get(timeout=1)
+            start_posorient = self._posorients_queue.get(timeout=1)
             if start_posorient is None:
                 # Poison pill means shutdown)
                 break
             common_id = list(set(start_posorient.index).intersection(
-                self.__posorientvel.index))
-            self.__posorientvel.loc[common_id] = start_posorient.loc[common_id]
+                self._posorientvel.index))
+            self._posorientvel.loc[common_id] = start_posorient.loc[common_id]
             self.move()
-            next_posorient = self.__posorientvel
+            next_posorient = self._posorientvel
 
-            self.__posorients_queue.task_done()
-            self.__results_queue.put((start_posorient, next_posorient))
-        self.__posorients_queue.task_done()
+            self._posorients_queue.task_done()
+            self._results_queue.put((start_posorient, next_posorient))
+        self._posorients_queue.task_done()
         print('Process {} done'.format(proc_name))
 
 
@@ -272,21 +289,21 @@ class GraphAgent():
     def __init__(self, database_filename):
         self.db = DataBaseLoad(database_filename)
         # Init the graph
-        self.__graph = nx.DiGraph()
+        self._graph = nx.DiGraph()
         for row_id, posor in self.db.posorients.iterrows():
             posor.name = row_id
-            self.__graph.add_node(row_id,
-                                  posorient=posor)
+            self._graph.add_node(row_id,
+                                 posorient=posor)
 
     @property
     def graph(self):
-        return self.__graph
+        return self._graph
 
     @graph.setter
     def graph(self, graph):
         if isinstance(graph, nx.DiGraph) is False:
             raise TypeError('graph is not a nx.DiGraph')
-        self.__graph = graph.copy()
+        self._graph = graph.copy()
         self.check_graph()
 
     def build_graph(self, callback_function,
@@ -296,8 +313,8 @@ class GraphAgent():
         results_edges = []
         posorients_queue = JoinableQueue()
         results_queue = Queue()
-        for node in self.__graph.nodes:
-            posorients_queue.put(self.__graph.nodes[node]['posorient'])
+        for node in self._graph.nodes:
+            posorients_queue.put(self._graph.nodes[node]['posorient'])
 
         # Start ndatabase loader
         num_agents = ncpu
@@ -316,21 +333,21 @@ class GraphAgent():
         # Wait for all of the tasks to finish
         # posorients_queue.join()
 
-        for _ in range(nx.number_of_nodes(self.__graph)):
+        for _ in range(nx.number_of_nodes(self._graph)):
             result = results_queue.get(timeout=timeout)
             results_edges.append((result[0].name,
                                   result[1].name))
             # print(results_edges[-1])
-        self.__graph.add_edges_from(results_edges)
+        self._graph.add_edges_from(results_edges)
         self.check_graph()
 
     def check_graph(self):
         self.check_single_target()
 
     def check_single_target(self):
-        for node in self.__graph.nodes:
+        for node in self._graph.nodes:
             # not connected -> loop not ran
-            for count, _ in enumerate(self.__graph.neighbors(node)):
+            for count, _ in enumerate(self._graph.neighbors(node)):
                 # count == 0 -> connected to one node
                 # count == 1 -> connected to two nodes
                 if count > 0:
@@ -341,7 +358,7 @@ class GraphAgent():
         """Return a list of node going to each attractor in a graph
         """
         attractors = list()
-        for attractor in nx.attracting_components(self.__graph):
+        for attractor in nx.attracting_components(self._graph):
             att = dict()
             att['attractor'] = attractor
             attractors.append(att)
@@ -399,13 +416,13 @@ class GraphAgent():
 
     def reach_goals(self, goals):
         """ Return all paths to the goals """
-        return nx.shortest_path(self.__graph, target=goals)
+        return nx.shortest_path(self._graph, target=goals)
 
     def neighboring_nodes(self, target):
         """ Return the nodes going to the target """
         # Reverse graph because nx.neighbors give the end node
         # and we want to find the start node going to target
         # not where target goes.
-        tmpgraph = self.__graph.reverse(copy=True)
+        tmpgraph = self._graph.reverse(copy=True)
         neighbors = tmpgraph.neighbors(target)
         return neighbors
diff --git a/navipy/moving/test_agent.py b/navipy/moving/test_agent.py
index 8775361fbcede6c9ee87feb54c9d41bd8ca496c5..5f73a7a0e743a0cfba81b0dffd9b85c43f2e7dfe 100644
--- a/navipy/moving/test_agent.py
+++ b/navipy/moving/test_agent.py
@@ -1,5 +1,5 @@
 """
-Test of maths
+Test of agent
 """
 import numpy as np
 import pandas as pd
@@ -17,78 +17,86 @@ class TestNavipyMovingAgent(unittest.TestCase):
         self.mydb_filename = pkg_resources.resource_filename(
             'navipy', 'resources/database.db')
         self.mydb = navidb.DataBaseLoad(self.mydb_filename)
+        self.__posorient_col = ['x', 'y', 'z',
+                                'alpha_0', 'alpha_1', 'alpha_2']
+        self.__velocity_col = ['d' + col for col in self.__posorient_col]
+        self.__posorient_vel_col = self.__posorient_col
+        self.__posorient_vel_col.extend(self.__velocity_col)
 
-    def test_memfriendly(self):
-        """posorient is loaded if memory_friendly is False """
-        agent = naviagent.AbstractAgent(self.mydb_filename,
-                                        memory_friendly=False)
-        self.assertTrue(
-            isinstance(agent.posorients, pd.DataFrame),
-            'posorients should be a pd.DataFrame when memfriendly is false')
-        agent = naviagent.AbstractAgent(self.mydb_filename,
-                                        memory_friendly=True)
-        self.assertTrue(
-            agent.posorients is None,
-            'posorients should be None when memfriendly is true')
-
-    def test_abstractmove_inputs(self):
-        """abstractmove should TypeError if not pandas Series """
-        agent = naviagent.AbstractAgent(self.mydb_filename,
-                                        memory_friendly=False)
-        with self.assertRaises(TypeError):
-            agent.abstractmove('NotPandasSeries')
-
-        posorient_vel = pd.Series()
-        for col in ['x', 'y', 'z', 'alpha_0', 'alpha_1', 'alpha_2',
-                    'dx', 'dy', 'dz', 'dalpha_0', 'dalpha_1', 'dalpha_2']:
-            with self.assertRaises(KeyError):
-                agent.abstractmove(posorient_vel)
-            posorient_vel[col] = 2
-
-    def test_abstractmove_null_vellocity(self):
-        """abstractmove should leads to same point with null vel"""
-        agent = naviagent.AbstractAgent(self.mydb_filename,
-                                        memory_friendly=False)
-
-        posorient_vel = pd.Series(data=0,
-                                  index=['x', 'y', 'z',
-                                         'alpha_0', 'alpha_1', 'alpha_2',
-                                         'dx', 'dy', 'dz',
-                                         'dalpha_0', 'dalpha_1', 'dalpha_2'])
-        pos = self.mydb.read_posorient(rowid=1)
-        posorient_vel.loc[['x', 'y', 'z']] = pos.loc[['x', 'y', 'z']]
-
-        newpos = agent.abstractmove(posorient_vel)
-        self.assertTrue(newpos.equals(posorient_vel),
-                        'Agent moved although velocity is null')
+    #
+    # AbstractAgent
+    #
+    def test_move_abstractagent(self):
+        agent = naviagent.AbstractAgent()
+        with self.assertRaises(NameError):
+            agent.move()
+
+    def test_fly_abstractagent(self):
+        agent = naviagent.AbstractAgent()
+        with self.assertRaises(NameError):
+            agent.fly(max_nstep=10)
 
     #
-    # Single
+    # GridAgent
     #
-    def test_init_inputs(self):
-        initial_condition = 'A'
-        with self.assertRaises(TypeError):
-            naviagent.Single(self.mydb_filename,
-                             initial_condition,
-                             memory_friendly=False)
-
-        initial_condition = pd.Series(index=['x'], data='a')
-        with self.assertRaises(TypeError):
-            naviagent.Single(self.mydb_filename,
-                             initial_condition,
-                             memory_friendly=False)
+    def test_move_gridagent(self):
+        agent = naviagent.GridAgent(self.mydb_filename)
+        initposorient = agent.db.posorients.loc[13, :]
+        initposovel = pd.Series(data=0,
+                                index=self.__posorient_vel_col)
+        initposovel.loc[initposorient.index] = initposorient
+        agent.posorient = initposovel
+        agent.motion = lambda posorient, scene:\
+            pd.Series(data=0,
+                      index=self.__posorient_vel_col)
+        with self.assertRaises(AttributeError):
+            agent.move()
+        mode_move = {'mode': 'on_cubic_grid',
+                     'param': {'grid_spacing':
+                               pd.Series(data=1,
+                                         index=['dx', 'dy', 'dz'])}}
+        agent.mode_of_motion = mode_move
+        agent.move()
+        obtained = agent.posorient
+        self.assertTrue(np.allclose(
+            obtained, initposorient.loc[obtained.index]))
+
+    def test_fly_gridagent(self):
+        agent = naviagent.GridAgent(self.mydb_filename)
+        initposorient = agent.db.posorients.loc[13, :]
+        initposovel = pd.Series(data=0,
+                                index=self.__posorient_vel_col)
+        initposovel.loc[initposorient.index] = initposorient
+        agent.posorient = initposovel
+        agent.motion = lambda posorient, scene:\
+            pd.Series(data=0,
+                      index=self.__posorient_vel_col)
+        with self.assertRaises(AttributeError):
+            agent.fly(max_nstep=10)
+        mode_move = {'mode': 'on_cubic_grid',
+                     'param': {'grid_spacing':
+                               pd.Series(data=1,
+                                         index=['dx', 'dy', 'dz'])}}
+        agent.mode_of_motion = mode_move
+        agent.fly(max_nstep=10)
+        obtained = agent.posorient
+        print(obtained)
+        print(initposorient.loc[obtained.index])
+        self.assertTrue(np.allclose(obtained,
+                                    initposorient.loc[obtained.index]))
 
     #
-    # Multi
+    # GraphAgent
     #
-    def test_init(self):
-        agent = naviagent.Multi(self.mydb_filename)
+
+    def test_init_graphagent(self):
+        agent = naviagent.GraphAgent(self.mydb_filename)
         self.assertEqual(sorted(agent.graph.nodes),
                          sorted(list(self.mydb.posorients.index)),
                          'Init of graph failed. Node missmatch')
 
     def test_graph_setter(self):
-        agent = naviagent.Multi(self.mydb_filename)
+        agent = naviagent.GraphAgent(self.mydb_filename)
         graph_nodes = list(agent.graph.nodes)
         graph_edges = list()
         for gnode in graph_nodes[1:]:
@@ -113,7 +121,7 @@ class TestNavipyMovingAgent(unittest.TestCase):
         3 Two loops attractors
         """
         # Test all node to first
-        agent = naviagent.Multi(self.mydb_filename)
+        agent = naviagent.GraphAgent(self.mydb_filename)
 
         graph_nodes = list(agent.graph.nodes)
         graph_edges = list()
@@ -175,7 +183,7 @@ class TestNavipyMovingAgent(unittest.TestCase):
         2. Saddle points
         3. Local minima
         """
-        agent = naviagent.Multi(self.mydb_filename)
+        agent = naviagent.GraphAgent(self.mydb_filename)
         # Local maxima
         graph_nodes = list(agent.graph.nodes)
         graph_edges = list()