diff --git a/navipy/rendering/bee_sampling.py b/navipy/rendering/bee_sampling.py
index 98e1de4004e316ec8b4fa98e8aa4009d41e81c1a..2d77e2ccf59dfbfab1aebe87a3c6046b303f70c3 100644
--- a/navipy/rendering/bee_sampling.py
+++ b/navipy/rendering/bee_sampling.py
@@ -41,6 +41,18 @@ harddrive space, as each image is composed of 4 channels of 180x360 pixels.
         :param alpha2: the 2nd euler angles
         :param alpha3: the 3rd euler angles
         """
+        if not (isinstance(x, int) or isinstance(x, float)):
+            raise TypeError('x must be integer')
+        if not (isinstance(y, int) or isinstance(y, float)):
+            raise TypeError('y must be integer')
+        if not (isinstance(z, int) or isinstance(z, float)):
+            raise TypeError('z must be integer')
+        if not (isinstance(alpha1, float) or isinstance(alpha1, int)):
+            raise TypeError('alpha1 must be float')
+        if not (isinstance(alpha2, float) or isinstance(alpha2, int)):
+            raise TypeError('alpha2 must be float')
+        if not (isinstance(alpha3, float) or isinstance(alpha3, int)):
+            raise TypeError('alpha3 must be float')
         [mx, my, mz, ma1, ma2, ma3] = np.meshgrid(x,
                                                   y,
                                                   z,
@@ -68,7 +80,8 @@ harddrive space, as each image is composed of 4 channels of 180x360 pixels.
         self.__grid_posorients.index.name = 'grid_index'
         self.__grid_posorients.name = 'grid_position_orientation'
 
-    def get_grid_posorients(self):
+    @property
+    def grid_posorients(self):
         """return a copy of the posorientation matrix
 
         :returns: position-orientations of the grid
@@ -91,9 +104,15 @@ harddrive space, as each image is composed of 4 channels of 180x360 pixels.
         .. todo: use @property.setter
                      def blacklist_indeces(self,indeces)
         """
+        if not isinstance(indeces, list):
+            raise TypeError('indeces must be a list')
+        if any(np.isnan(indeces)):
+            raise ValueError('indeces must not contain nans')
         self.__grid_posorients.loc[indeces, :] = np.nan
 
     def render(self, database_filename):
+        if not isinstance(database_filename, str):
+            raise TypeError('filename must be a string')
         database_folder = os.path.dirname(database_filename)
         if not os.path.exists(database_folder):
             os.makedirs(database_folder)
diff --git a/navipy/rendering/bee_sampling.py~ b/navipy/rendering/bee_sampling.py~
new file mode 100644
index 0000000000000000000000000000000000000000..247ccc2e49fa7b960ae301a1b56750eb245f4a36
--- /dev/null
+++ b/navipy/rendering/bee_sampling.py~
@@ -0,0 +1,165 @@
+"""
+The beesampling class
+
+.. tothinkof: conditional bpy import to build doc from comments
+"""
+import bpy
+import os
+import numpy as np
+import pandas as pd
+import warnings
+from navipy.rendering.cyber_bee import Cyberbee
+from navipy.database import DataBaseSave
+
+
+class BeeSampling(Cyberbee):
+    """
+    BeeSampling is a class deriving from Cyberbee.
+    The BeeSampling can be used to generate a database of
+images taken on a rectangular regular grid. For the database,
+the BeeSampling rely on DataBase
+    It worth noting that the generated database can take a large
+harddrive space, as each image is composed of 4 channels of 180x360 pixels.
+    """
+
+    def __init__(self):
+        """Initialise the BeeSampling"""
+        Cyberbee.__init__(self)
+        self.blenddirname = os.path.dirname(bpy.data.filepath)
+        self.blendfilename = os.path.basename(bpy.data.filepath)
+        self.__grid_posorients = None
+        self.__grid_size = None
+        self.world_dim = np.inf
+
+    def create_sampling_grid(self, x, y, z, alpha1, alpha2, alpha3):
+        """Create a cubic grid from all the sampling points
+
+        :param x: the positions along the x-axis
+        :param y: the positions along the y-axis
+        :param z: the positions along the z-axis
+        :param alpha1: the first euler angles
+        :param alpha2: the 2nd euler angles
+        :param alpha3: the 3rd euler angles
+        """
+        if not (isinstance(x, int) or isinstance(x, float)):
+            raise TypeError('x must be integer')
+        if not (isinstance(y, int) or isinstance(y, float)):
+            raise TypeError('y must be integer')
+        if not (isinstance(z, int) or isinstance(z, float)):
+            raise TypeError('z must be integer')
+        if not (isinstance(alpha1, float) or isinstance(alpha1, int)):
+            raise TypeError('alpha1 must be float')
+        if not (isinstance(alpha2, float) or isinstance(alpha2, int)):
+            raise TypeError('alpha2 must be float')
+        if not (isinstance(alpha3, float) or isinstance(alpha3, int)):
+            raise TypeError('alpha3 must be float')
+        [mx, my, mz, ma1, ma2, ma3] = np.meshgrid(x,
+                                                  y,
+                                                  z,
+                                                  alpha1,
+                                                  alpha2,
+                                                  alpha3)
+        self.grid_size = mx.shape
+        mx = mx.flatten()
+        my = my.flatten()
+        mz = mz.flatten()
+        ma1 = ma1.flatten()
+        ma2 = ma2.flatten()
+        ma3 = ma3.flatten()
+        self.__grid_posorients = pd.DataFrame(index=range(mx.shape[0]),
+                                              columns=['x', 'y', 'z',
+                                                       'alpha_0',
+                                                       'alpha_1',
+                                                       'alpha_2'])
+        self.__grid_posorients.loc[:, 'x'] = mx
+        self.__grid_posorients.loc[:, 'y'] = my
+        self.__grid_posorients.loc[:, 'z'] = mz
+        self.__grid_posorients.loc[:, 'alpha_0'] = ma1
+        self.__grid_posorients.loc[:, 'alpha_1'] = ma2
+        self.__grid_posorients.loc[:, 'alpha_2'] = ma3
+        self.__grid_posorients.index.name = 'grid_index'
+        self.__grid_posorients.name = 'grid_position_orientation'
+
+    @property
+    def grid_posorients(self):
+        """return a copy of the posorientation matrix
+
+        :returns: position-orientations of the grid
+        :rtype: pandas array
+
+        .. todo: use @property
+                     def grid_posorients(self)
+
+        .. todo: create @property.setter
+                        def grid_posorients(self,posorients)
+                        (need a type check, and col check, and copy of df)
+        """
+        return self.__grid_posorients.copy()
+
+    @gridindeces2nan.setter
+    def gridindeces2nan(self, indeces):
+        """Set certain grid point to nan, so they will be ignore in the rendering
+
+        :param indeces: a list of indeces to be set to nan
+
+        .. todo: use @property.setter
+                     def blacklist_indeces(self,indeces)
+        """
+        if not isinstance(indeces, list):
+            raise TypeError('indeces must be a list')
+        if any(np.isnan(indeces)):
+            raise ValueError('indeces must not contain nans')
+        self.__grid_posorients.loc[indeces, :] = np.nan
+
+    def render(self, database_filename):
+        if not isinstance(database_filename, str):
+            raise TypeError('filename must be a string')
+        database_folder = os.path.dirname(database_filename)
+        if not os.path.exists(database_folder):
+            os.makedirs(database_folder)
+        dataloger = DataBaseSave(database_filename,
+                                 channels=['R', 'G', 'B', 'D'],
+                                 arr_dtype=np.uint8)
+        for frame_i, posorient in self.__grid_posorients.iloc[::-1].iterrows():
+            print(frame_i)
+            if np.any(np.isnan(posorient)):
+                # warnings.warn('frame_i: {} posorient nans'.format(frame_i))
+                continue
+            rowid = dataloger.get_posid(posorient)
+            if dataloger.check_data_validity(rowid):
+                warnings.warn(
+                    'frame_i: {} data is valid rowid {}'.format(frame_i,
+                                                                rowid))
+                continue
+            # The position-orientatios is valid (none nan)
+            # and the cmaxminrange has not already been assigned
+            # so the image need to be rendered
+            self.update(posorient)
+            distance = self.get_distance()
+            distance[distance > self.world_dim] = self.world_dim
+            image = self.get_image()
+            image[:, :, 3] = distance
+            dataloger.write_image(posorient, image)
+        print('rendering completed')
+
+
+if __name__ == "__main__":
+    import tempfile
+    bee_samp = BeeSampling()
+    # Create mesh
+    world_dim = 15.0
+    x = np.linspace(-7.5, 7.5, 5)
+    y = np.linspace(-7.5, 7.5, 5)
+    z = np.arange(1, 8, 2)
+    alpha_1 = np.array([0]) + np.pi / 2
+    alpha_2 = np.array([0])
+    alpha_3 = np.array([0])
+    bee_samp.create_sampling_grid(
+        x, y, z, alpha1=alpha_1, alpha2=alpha_2, alpha3=alpha_3)
+    bee_samp.world_dim = world_dim
+    grid_pos = bee_samp.get_grid_posorients()
+    condition = (grid_pos.x**2 + grid_pos.y**2) < ((bee_samp.world_dim / 2)**2)
+    bee_samp.set_gridindeces2nan(condition[condition == 0].index)
+    bee_samp.set_cycle_samples(samples=5)
+    with tempfile.TemporaryDirectory() as folder:
+        bee_samp.render(folder + '/database.db')
diff --git a/navipy/rendering/cyber_bee.py b/navipy/rendering/cyber_bee.py
index c1b508c949cfbd39451eba7a7715ea7474c1515b..fd9550f5febfcd13faa3eefdca1ac77a2d8040bb 100644
--- a/navipy/rendering/cyber_bee.py
+++ b/navipy/rendering/cyber_bee.py
@@ -80,54 +80,112 @@ class Cyberbee():
         )
         self.tmp_fileoutput = tmp_fileoutput
 
-    def set_camera_rotation_mode(self, mode='XYZ'):
+    @property
+    def camera_rotation_mode(self):
+        """get the current camera rotation mode
+
+        :returns: the mode of rotation used by the camera
+        :rtype: string
+
+        ..todo: Use @property
+                    def camera_rotation_mode(self)
+        """
+        return bpy.data.scenes["Scene"].camera.rotation_mode
+
+    @camera_rotation_mode.setter
+    def camera_rotation_mode(self, mode='XYZ'):
         """change the camera rotation mode
 
+
+
         :param mode: the mode of rotation for the camera see blender doc
+
                      (default: 'XYZ').
+
         :type mode: a string
+
         .. seealso: blender bpy.data.scenes["Scene"].camera.rotation_mode
 
+
+
         ..todo: Use @property.setter
+
                     def camera_rotation_mode(self, mode='XYZ')
+
         """
+        if not isinstance(mode, str):
+
+            raise TypeError('mode must be a string')
         bpy.data.scenes["Scene"].camera.rotation_mode = mode
 
-    def get_camera_rotation_mode(self):
-        """get the current camera rotation mode
+    @property
+    def cycle_samples(self):
+        """get the samples for rendering with cycle
 
-        :returns: the mode of rotation used by the camera
-        :rtype: string
+        :returns: the number of samples used for the rendering
+        :rtype: int
 
-        ..todo: Use @property
-                    def camera_rotation_mode(self)
+        ..todo use @property
+                   def cycle_samples(self)
         """
-        return bpy.data.scenes["Scene"].camera.rotation_mode
+        return bpy.context.scene.cycles.samples
 
-    def set_cycle_samples(self, samples=30):
+    @cycle_samples.setter
+    def cycle_samples(self, samples=30):
         """change the samples for rendering with cycle
 
+
         :param samples: the number of samples to use when rendering images
+
         :type samples: int
 
+
         ..todo: Use @property.setter
+
                     def cycle_samples(self, samples=30)
         """
+        if not isinstance(samples, int):
+            raise TypeError('samples must be an integer')
         bpy.context.scene.cycles.samples = samples
 
-    def get_cycle_samples(self):
-        """get the samples for rendering with cycle
+    @property
+    def camera_fov(self):
+        """get fov of camera
+
+
+
+        :returns: the field of view of the camera as min/max,longitude/latitude
+
+               in degrees
+
+        :rtype: dict
+
 
-        :returns: the number of samples used for the rendering
-        :rtype: int
 
         ..todo use @property
-                   def cycle_samples(self)
+
+                   def camera_fov()
+
+
+
+        ..todo Change assert to if -> raise TypeError/KeyError
+
         """
-        return bpy.context.scene.cycles.samples
+        assert self.camera.data.type == 'PANO', 'Camera is not panoramic'
+        assert self.camera.cycles.panorama_type == 'EQUIRECTANGULAR',\
+            'Camera is not equirectangular'
+        fov = dict()
+        fov['latitude_min'] = np.rad2ged(self.camera.data.cycles.latitude_min)
+        fov['latitude_max'] = np.rad2ged(self.camera.data.cycles.latitude_max)
+        fov['longitude_min'] = np.rad2ged(
+            self.camera.data.cycles.longitude_min)
+        fov['longitude_max'] = np.rad2ged(
+            self.camera.data.cycles.longitude_max)
+        return fov
 
-    def set_camera_fov(self, latmin=-90, latmax=+90,
-                       longmin=-180, longmax=+180):
+    @camera_fov.setter
+    def camera_fov(self, latmin=-90, latmax=+90,
+                   longmin=-180, longmax=+180):
         """change the field of view of the panoramic camera
 
         :param latmin: minimum latitude (in deg)
@@ -146,94 +204,103 @@ class Cyberbee():
 
         ..todo Change assert to if -> raise TypeError()/KeyError()
         """
-        assert self.camera.data.type == 'PANO', 'Camera is not panoramic'
-        assert self.camera.data.cycles.panorama_type == 'EQUIRECTANGULAR',\
-            'Camera is not equirectangular'
+        if not (isinstance(latmin, int) or isinstance(latmin, float)):
+            raise TypeError('latmin must be of type integer or float')
+        if not (isinstance(latmax, int) or isinstance(latmax, float)):
+            raise TypeError('latmin must be of type integer or float')
+        if not (isinstance(longmin, int) or isinstance(longmin, float)):
+            raise TypeError('latmin must be of type integer or float')
+        if not (isinstance(longmax, int) or isinstance(longmax, float)):
+            raise TypeError('latmin must be of type integer or float')
+        if not self.camera.data.type == 'PANO':
+            raise Exception('Camera is not panoramic')
+        if not self.camera.data.cycles.panorama_type == 'EQUIRECTANGULAR':
+            raise Exception('Camera is not equirectangular')
         self.camera.data.cycles.latitude_min = np.deg2rad(latmin)
         self.camera.data.cycles.latitude_max = np.deg2rad(latmax)
         self.camera.data.cycles.longitude_min = np.deg2rad(longmin)
         self.camera.data.cycles.longitude_max = np.deg2rad(longmax)
 
-    def get_camera_fov(self):
-        """get fov of camera
+    @property
+    def camera_gaussian_width(self, gauss_w=1.5):
+        """get width of the gaussian spatial filter
 
-        :returns: the field of view of the camera as min/max,longitude/latitude
-               in degrees
-        :rtype: dict
+        :returns: the width of the gaussian filter
+        :rtype: float
 
         ..todo use @property
-                   def camera_fov()
-
-        ..todo Change assert to if -> raise TypeError/KeyError
+                   def camera_gaussian_width(self)
         """
-        assert self.camera.data.type == 'PANO', 'Camera is not panoramic'
-        assert self.camera.cycles.panorama_type == 'EQUIRECTANGULAR',\
-            'Camera is not equirectangular'
-        fov = dict()
-        fov['latitude_min'] = np.rad2ged(self.camera.data.cycles.latitude_min)
-        fov['latitude_max'] = np.rad2ged(self.camera.data.cycles.latitude_max)
-        fov['longitude_min'] = np.rad2ged(
-            self.camera.data.cycles.longitude_min)
-        fov['longitude_max'] = np.rad2ged(
-            self.camera.data.cycles.longitude_max)
-        return fov
+        if not (isinstance(gauss_w, int) or isinstance(gauss_w, float)):
+            raise TypeError('gauss window must be integer or float')
+        return bpy.context.scene.cycles.filter_width
 
-    def set_camera_gaussian_width(self, gauss_w=1.5):
+    @camera_gaussian_width.setter
+    def camera_gaussian_width(self, gauss_w=1.5):
         """change width of the gaussian spatial filter
 
         :param gauss_w: width of the gaussian filter
+
         :type gauss_w: float
 
         ..todo use @property.setter
                    def camera_gaussian_width(self)
 
+
         ..todo check that input argument is of correct type,
                if not raise TypeError()
+
         """
+        if not (isinstance(gauss_w, int) or isinstance(gauss_w, float)):
+            raise TypeError('gauss window must be integer or float')
         bpy.context.scene.cycles.filter_width = gauss_w
 
-    def get_camera_gaussian_width(self, gauss_w=1.5):
-        """get width of the gaussian spatial filter
+    @property
+    def camera_resolution(self):
+        """return camera resolution (x,y)
 
-        :returns: the width of the gaussian filter
-        :rtype: float
+        :returns: the resolution of the camera along (x-axis,y-axis)
+        :rtype: (int,int)
 
         ..todo use @property
-                   def camera_gaussian_width(self)
+                   def camera_resolution(self)
         """
-        return bpy.context.scene.cycles.filter_width
+        resolution_x = bpy.context.scene.render.resolution_x
+        resolution_y = bpy.context.scene.render.resolution_y
+        return resolution_x, resolution_y
 
-    def set_camera_resolution(self, resolution_x=360, resolution_y=180):
+    @camera_resolution.setter
+    def camera_resolution(self, resolution_x=360, resolution_y=180):
         """change the camera resolution (nb of pixels)
 
+
         :param resolution_x: number of pixels along the x-axis of the camera
         :type resolution_x: int
+
         :param resolution_y: number of pixels along the y-axis of the camera
+
         :type resolution_y: int
 
+
         ..todo use @property.setter
+
                    def camera_resolution(self,resolution)
+
                    here resolution is [res_x,res_y]
 
+
+
         ..todo check type and raise TypeError
+
         """
+        if not isinstance(resolution_x, int):
+            raise TypeError('resolution must be integer')
+        if not isinstance(resolution_y, int):
+            raise TypeError('resolution must be integer')
         bpy.context.scene.render.resolution_x = resolution_x
         bpy.context.scene.render.resolution_y = resolution_y
         bpy.context.scene.render.resolution_percentage = 100
 
-    def get_camera_resolution(self):
-        """return camera resolution (x,y)
-
-        :returns: the resolution of the camera along (x-axis,y-axis)
-        :rtype: (int,int)
-
-        ..todo use @property
-                   def camera_resolution(self)
-        """
-        resolution_x = bpy.context.scene.render.resolution_x
-        resolution_y = bpy.context.scene.render.resolution_y
-        return resolution_x, resolution_y
-
     def update(self, posorient):
         """assign the position and the orientation of the camera.
 
@@ -243,13 +310,18 @@ class Cyberbee():
              specified by scene.camera.rotation_mode
         :type posorient: 1x6 double array
         """
-        assert len(posorient) == 6, 'posorient should be a 1x6 double array'
+        if len(posorient) != 6:
+            raise Exception('posorient should be a 1x6 double array')
+        if not (isinstance(posorient, np.ndarray) or
+                isinstance(posorient, list)):
+            raise TypeError('posorient must be of type array or list')
         self.camera.location = posorient[:3]
         self.camera.rotation_euler = posorient[3:]
         # Render
         bpy.ops.render.render()
 
-    def get_image(self):
+    @property
+    def image(self):
         """return the last rendered image as a numpy array
 
         :returns: the image (height,width,4)
@@ -274,7 +346,8 @@ class Cyberbee():
         pixels = pixels.reshape([im_height, im_width, 4])
         return pixels
 
-    def get_distance(self):
+    @property
+    def distance(self):
         """return the last rendered distance map as a numpy array
 
         :returns: the distance map (height, width)
diff --git a/navipy/rendering/cyber_bee.py~ b/navipy/rendering/cyber_bee.py~
new file mode 100644
index 0000000000000000000000000000000000000000..f2d0efe89570a68cd2a9018cd4703d6ae54c465e
--- /dev/null
+++ b/navipy/rendering/cyber_bee.py~
@@ -0,0 +1,391 @@
+"""
+    How to test the script:
+    -----------------------
+    >>> blender test.blend --background --python Cyberbee.py
+
+    :Author: Olivier Bertrand (olivier.bertrand@uni-bielefeld.de)
+    :Parent module: Scene_rendering
+
+    ..tothinkof for the doc bpy will raise an issue.
+                conditional import of bpy
+"""
+import bpy
+import numpy as np
+import tempfile
+import os
+
+
+class Cyberbee():
+    """
+    Cyberbee is a small class binding python with blender.
+    With Cyberbee one can move the bee to a position, and render what
+    the bee see at this position.
+
+    The Bee eye is a panoramic camera with equirectangular projection
+    The light rays attaining the eyes are filtered with a gaussian.
+    """
+
+    def __init__(self):
+        """Initialise the Cyberbee
+        ..todo check that TemporaryDirectory is writtable and readable
+        """
+        # Rendering engine needs to be Cycles to support panoramic
+        # equirectangular camera
+        bpy.context.scene.render.engine = 'CYCLES'
+        bpy.context.scene.render.layers["RenderLayer"].use_pass_z = True
+        # Look for object camera
+        camera_found = False
+        for obj in bpy.context.scene.objects:
+            if obj.type == 'CAMERA':
+                self.camera = obj
+                camera_found = True
+                break
+        assert camera_found, 'The blender file does not contain a camera'
+        # The bee eye is panoramic, and with equirectangular projection
+        self.camera.data.type = 'PANO'
+        self.camera.data.cycles.panorama_type = 'EQUIRECTANGULAR'
+        # Filtering props
+        bpy.context.scene.cycles.filter_type = 'GAUSSIAN'
+        # Call all set function with default values
+        self.set_camera_rotation_mode()
+        self.set_camera_fov()
+        self.set_camera_gaussian_width()
+        self.set_camera_resolution()
+        self.set_cycle_samples()
+        # switch on nodes
+        # Create render link to OutputFile with Image and Z buffer
+        bpy.context.scene.use_nodes = True
+        scene = bpy.context.scene
+        nodes = scene.node_tree.nodes
+
+        render_layers = nodes['Render Layers']
+        output_file = nodes.new("CompositorNodeOutputFile")
+        output_file.format.file_format = "OPEN_EXR"
+        output_file.file_slots.remove(output_file.inputs[0])
+        tmp_fileoutput = dict()
+        tmp_fileoutput['Image'] = 'Image'
+        tmp_fileoutput['Depth'] = 'Depth'
+        tmp_fileoutput['Folder'] = tempfile.TemporaryDirectory().name
+        tmp_fileoutput['ext'] = '.exr'
+        output_file.file_slots.new(tmp_fileoutput['Image'])
+        output_file.file_slots.new(tmp_fileoutput['Depth'])
+        output_file.base_path = tmp_fileoutput['Folder']
+        scene.node_tree.links.new(
+            render_layers.outputs['Image'],
+            output_file.inputs['Image']
+        )
+        scene.node_tree.links.new(
+            render_layers.outputs['Z'],
+            output_file.inputs['Depth']
+        )
+        self.tmp_fileoutput = tmp_fileoutput
+
+    @property
+    def camera_rotation_mode(self):
+        """get the current camera rotation mode
+
+        :returns: the mode of rotation used by the camera
+        :rtype: string
+
+        ..todo: Use @property
+                    def camera_rotation_mode(self)
+        """
+        return bpy.data.scenes["Scene"].camera.rotation_mode
+
+    @camera_rotation_mode.setter
+    def camera_rotation_mode(self, mode='XYZ'):
+        """change the camera rotation mode
+
+
+
+        :param mode: the mode of rotation for the camera see blender doc
+
+                     (default: 'XYZ').
+
+        :type mode: a string
+
+        .. seealso: blender bpy.data.scenes["Scene"].camera.rotation_mode
+
+
+
+        ..todo: Use @property.setter
+
+                    def camera_rotation_mode(self, mode='XYZ')
+
+        """
+        if not isinstance(mode, str):
+
+            raise TypeError('mode must be a string')
+        bpy.data.scenes["Scene"].camera.rotation_mode = mode
+
+    @property
+    def cycle_samples(self):
+        """get the samples for rendering with cycle
+
+        :returns: the number of samples used for the rendering
+        :rtype: int
+
+        ..todo use @property
+                   def cycle_samples(self)
+        """
+        return bpy.context.scene.cycles.samples
+
+    @cycle_samples.setter
+    def cycle_samples(self, samples=30):
+        """change the samples for rendering with cycle
+
+
+        :param samples: the number of samples to use when rendering images
+
+        :type samples: int
+
+
+        ..todo: Use @property.setter
+
+                    def cycle_samples(self, samples=30)
+        """
+        if not isinstance(samples, int):
+            raise TypeError('samples must be an integer')
+        bpy.context.scene.cycles.samples = samples
+
+    @property
+    def camera_fov(self):
+        """get fov of camera
+
+
+
+        :returns: the field of view of the camera as min/max,longitude/latitude
+
+               in degrees
+
+        :rtype: dict
+
+
+
+        ..todo use @property
+
+                   def camera_fov()
+
+
+
+        ..todo Change assert to if -> raise TypeError/KeyError
+
+        """
+        assert self.camera.data.type == 'PANO', 'Camera is not panoramic'
+        assert self.camera.cycles.panorama_type == 'EQUIRECTANGULAR',\
+            'Camera is not equirectangular'
+        fov = dict()
+        fov['latitude_min'] = np.rad2ged(self.camera.data.cycles.latitude_min)
+        fov['latitude_max'] = np.rad2ged(self.camera.data.cycles.latitude_max)
+        fov['longitude_min'] = np.rad2ged(
+            self.camera.data.cycles.longitude_min)
+        fov['longitude_max'] = np.rad2ged(
+            self.camera.data.cycles.longitude_max)
+        return fov
+
+    @camera_fov.setter
+    def camera_fov(self, latmin=-90, latmax=+90,
+                   longmin=-180, longmax=+180):
+        """change the field of view of the panoramic camera
+
+        :param latmin: minimum latitude (in deg)
+        :type latmin: float
+        :param latmax: maximum latitude (in deg)
+        :type latmax: float
+        :param longmin: minimum longitude (in deg)
+        :type longmin: float
+        :param longmin: maximum longitude (in deg)
+        :type longmin: float
+
+        ..todo use @property.setter
+                   def camera_fov(self, latlongrange)
+                   here latlongrange is a a 2x2 list or array:
+                         [[latmin,latmax],[longmin,longmax]]
+
+        ..todo Change assert to if -> raise TypeError()/KeyError()
+        """
+        if not (isinstance(latmin, int) or isinstance(latmin, float)):
+            raise TypeError('latmin must be of type integer or float')
+        if not (isinstance(latmax, int) or isinstance(latmax, float)):
+            raise TypeError('latmin must be of type integer or float')
+        if not (isinstance(longmin, int) or isinstance(longmin, float)):
+            raise TypeError('latmin must be of type integer or float')
+        if not (isinstance(longmax, int) or isinstance(longmax, float)):
+            raise TypeError('latmin must be of type integer or float')
+        if not self.camera.data.type == 'PANO':
+            raise Exception('Camera is not panoramic')
+        if not self.camera.data.cycles.panorama_type == 'EQUIRECTANGULAR':
+            raise Exception('Camera is not equirectangular')
+        self.camera.data.cycles.latitude_min = np.deg2rad(latmin)
+        self.camera.data.cycles.latitude_max = np.deg2rad(latmax)
+        self.camera.data.cycles.longitude_min = np.deg2rad(longmin)
+        self.camera.data.cycles.longitude_max = np.deg2rad(longmax)
+
+    @property
+    def camera_gaussian_width(self, gauss_w=1.5):
+        """get width of the gaussian spatial filter
+
+        :returns: the width of the gaussian filter
+        :rtype: float
+
+        ..todo use @property
+                   def camera_gaussian_width(self)
+        """
+        if not (isinstance(gauss_w, int) or isinstance(gauss_w, float)):
+            raise TypeError('gauss window must be integer or float')
+        return bpy.context.scene.cycles.filter_width
+
+    @camera_gaussian_width.setter
+    def camera_gaussian_width(self, gauss_w=1.5):
+        """change width of the gaussian spatial filter
+
+        :param gauss_w: width of the gaussian filter
+
+        :type gauss_w: float
+
+        ..todo use @property.setter
+                   def camera_gaussian_width(self)
+
+
+        ..todo check that input argument is of correct type,
+               if not raise TypeError()
+
+        """
+        if not (isinstance(gauss_w, int) or isinstance(gauss_w, float)):
+            raise TypeError('gauss window must be integer or float')
+        bpy.context.scene.cycles.filter_width = gauss_w
+
+    @property
+    def camera_resolution(self):
+        """return camera resolution (x,y)
+
+        :returns: the resolution of the camera along (x-axis,y-axis)
+        :rtype: (int,int)
+
+        ..todo use @property
+                   def camera_resolution(self)
+        """
+        resolution_x = bpy.context.scene.render.resolution_x
+        resolution_y = bpy.context.scene.render.resolution_y
+        return resolution_x, resolution_y
+
+    @camera_resolution.setter
+    def camera_resolution(self, resolution_x=360, resolution_y=180):
+        """change the camera resolution (nb of pixels)
+
+
+        :param resolution_x: number of pixels along the x-axis of the camera
+        :type resolution_x: int
+
+        :param resolution_y: number of pixels along the y-axis of the camera
+
+        :type resolution_y: int
+
+
+        ..todo use @property.setter
+
+                   def camera_resolution(self,resolution)
+
+                   here resolution is [res_x,res_y]
+
+
+
+        ..todo check type and raise TypeError
+
+        """
+        if not isinstance(resolution_x, int):
+            raise TypeError('resolution must be integer')
+        if not isinstance(resolution_y, int):
+            raise TypeError('resolution must be integer')
+        bpy.context.scene.render.resolution_x = resolution_x
+        bpy.context.scene.render.resolution_y = resolution_y
+        bpy.context.scene.render.resolution_percentage = 100
+
+    def update(self, posorient):
+        """assign the position and the orientation of the camera.
+
+        :param posorient: is a 1x6 vector continaing:
+             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
+        """
+        if len(posorient) != 6:
+            raise Exception('posorient should be a 1x6 double array')
+        if not (isinstance(posorient, np.ndarray) or
+               isinstance(posorient, list)):
+            raise TypeError('posorient must be of type array or list')
+        self.camera.location = posorient[:3]
+        self.camera.rotation_euler = posorient[3:]
+        # Render
+        bpy.ops.render.render()
+
+    @property
+    def image(self):
+        """return the last rendered image as a numpy array
+
+        :returns: the image (height,width,4)
+        :rtype: a double numpy array
+
+        .. note: A temporary file will be written on the harddrive,
+                 due to API blender limitation
+
+        .. todo: use @property
+                     def image(self)
+        """
+        # save image as a temporary file, and then loaded
+        # sadly the rendered image pixels can not directly be access
+        filename = os.path.join(self.tmp_fileoutput['Folder'],
+                                self.tmp_fileoutput['Image'] + '0001' +
+                                self.tmp_fileoutput['ext'])
+        im_width, im_height = self.get_camera_resolution()
+        im = bpy.data.images.load(filename)
+        pixels = np.array(im.pixels)
+        # im=PIL.Image.open(filename)
+        # pixels=np.asarray(im)
+        pixels = pixels.reshape([im_height, im_width, 4])
+        return pixels
+
+    @property
+    def distance(self):
+        """return the last rendered distance map as a numpy array
+
+        :returns: the distance map (height, width)
+        :rtype: a double numpy array
+
+        .. note: A temporary file will be written on the harddrive,
+                 due to API blender limitation
+
+        .. todo: use @property
+                     def distance(self)
+        """
+        # save image as a temporary file, and then loaded
+        # sadly the rendered image pixels can not directly be access
+        filename = os.path.join(self.tmp_fileoutput['Folder'],
+                                self.tmp_fileoutput['Depth'] + '0001' +
+                                self.tmp_fileoutput['ext'])
+        im_width, im_height = self.get_camera_resolution()
+        im = bpy.data.images.load(filename)
+        distance = np.array(im.pixels)
+        # im=PIL.Image.open(filename)
+        # distance=np.asarray(im)
+        distance = distance.reshape([im_height, im_width, 4])
+        distance = distance[:, :, 0]
+        return distance
+
+
+if __name__ == "__main__":
+    # Initiate the Cyberbee
+    mybee = Cyberbee()
+    frames_per_revolution = 5.0
+    step_size = 2 * np.pi / frames_per_revolution
+    posorients = np.zeros((frames_per_revolution, 6))
+    posorients[:, 0] = np.sin(np.arange(frames_per_revolution) * step_size) * 5
+    posorients[:, 1] = np.cos(np.arange(frames_per_revolution) * step_size) * 5
+    for frame_i, posorient in enumerate(posorients):
+        mybee.update(posorient)
+        # Test image
+        image = mybee.get_image()
+        # Test distance
+        distance = mybee.get_distance()
+    print('Cyberbee OK')
diff --git a/todo~ b/todo~
new file mode 100644
index 0000000000000000000000000000000000000000..e1a0fa9d49479cc05553767fb207b2b804b2df31
--- /dev/null
+++ b/todo~
@@ -0,0 +1,39 @@
+=======
+------------------------------------------------------
+0003: Improve database
+In the init database I would like to use class properties instead of get/read
+line: 263,273,and 394
+    def create(self)
+should be replaced by:
+    @property
+    def create(self)
+
+It implies that at every point that self.create() is called should be changed to self.create [Note the absence of parenthesis]
+
+line: 298
+    def get_posorients(self) 
+should be replaced by
+    @property
+    def posorients(self)
+
+Need to propagate the changes through all the code (see rendering / processing / moving )
+------------------------------------------------------
+0004: Change every assert by a if () raise TypeError/IOError/KeyError/... 
+- present in processing
+- present in database
+
+------------------------------------------------------
+0005: Write test function for raise Error
+- for every raise error create a test function, checking that the error is correctly thrown (see moving/test_agent for inspiration)
+
+------------------------------------------------------
+0006: Improve comparing/__init__.py
+- Change comment in simple_image_diff
+- call simple_image_diff in imagediff. you can then remove all the assert (that should be raise Error at that point) from imagediff
+- Add comment to diff_optic_flow / add reference to article. 
+- rename capitalised variable A,ATA, and b as longer variable name [future PEP8 will forbid this]
+
+------------------------------------------------------
+0007: Improve cyber_bee so that every getter and setter are properties
+
+0008: Improve bee_sampling so that every getter and setter are properties