From a6adb80a40304fe9479fec3a2b38bcd1dd121a8b Mon Sep 17 00:00:00 2001
From: lodenthal <lodenthal@uni-bielefeld.de>
Date: Mon, 20 Nov 2017 11:34:58 +0300
Subject: [PATCH] added tests for processing

---
 src/processing/test.py  | 467 ++++++++++++++++++++++++++++++++++++++++
 src/processing/tools.py |  42 ++--
 2 files changed, 490 insertions(+), 19 deletions(-)
 create mode 100644 src/processing/test.py

diff --git a/src/processing/test.py b/src/processing/test.py
new file mode 100644
index 0000000..4759bb4
--- /dev/null
+++ b/src/processing/test.py
@@ -0,0 +1,467 @@
+import unittest
+import sqlite3
+import numpy as np
+import pandas as pd
+import os.path as path
+from ..database import database
+import __init__ as processing
+
+
+def is_numeric_array(array):
+    """Checks if the dtype of the array is numeric.
+
+    Booleans, unsigned integer, signed integer, floats and complex are
+    considered numeric.
+
+    Parameters
+    ----------
+    array : `numpy.ndarray`-like
+    The array to check.
+
+    Returns
+    -------
+    is_numeric : `bool`
+    True if it is a recognized numerical and False if object or
+    string.
+    """
+    numerical_dtype_kinds = {'b',  # boolean
+                             'u',  # unsigned integer
+                             'i',  # signed integer
+                             'f',  # floats
+                             'c'}  # complex
+    try:
+        return array.dtype.kind in numerical_dtype_kinds
+    except AttributeError:
+        # in case it's not a numpy array it will probably have no dtype.
+        return np.asarray(array).dtype.kind in numerical_dtype_kinds
+
+
+def build_test_db():
+    db_filename = 'test_db_1'
+
+    conn = sqlite3.connect(db_filename)
+    c = conn.cursor()
+    conn.close()
+
+    db_filename = 'test_db_2'
+
+    conn = sqlite3.connect(db_filename)
+    c = conn.cursor()
+
+    c.execute('''CREATE TABLE normalisation
+              (R_max, R_min, R_range,
+               G_max, G_min, G_range,
+               B_max, B_min, B_range,
+               D_max, D_min, D_range)''')
+
+    c.execute('''CREATE TABLE position_orientation
+              (x,y,z,alpha_0,alpha_1,alpha_2)''')
+
+    c.execute('''CREATE TABLE image
+              (data)''')
+    conn.close()
+
+
+class TestCase(unittest.TestCase):
+    def setUp(self):
+        one_up = path.abspath(path.join(__file__, "../"))
+        self.mydb_filename = one_up+'/database.db'
+        self.mydb = database.DataBaseLoad(self.mydb_filename)
+
+
+#    def test_scene_rowID(self):
+#        for rowid in [-1,-6,9.4,3.0,5.4,'e',np.nan,None]:
+#            with self.assertRaises(TypeError):
+#                image = self.mydb.read_image(rowid=rowid)
+#                self.assertIsNotNone(image)
+#                self.assertFalse(sum(image.shape)==0)
+
+    def test_scene_posorient(self):
+        # get existing position for which also an image is contained in the db
+        # db_filename='/media/luiza/Daten/Repos/proj-ASV3Dnavi/data/raw/ASV_data_0_db.npy'
+
+        conn = sqlite3.connect(self.mydb_filename)
+        c = conn.cursor()
+        c.execute(""" SELECT * FROM position_orientation WHERE (rowid=1) """)
+        rows = c.fetchall()[0]
+        # print(rows)
+        # convert to pd.series
+
+        # working case
+        posorient = pd.Series(index=['x', 'y', 'z',
+                                     'alpha_0', 'alpha_1', 'alpha_2'])
+        posorient.x = rows[5]
+        posorient.y = rows[6]
+        posorient.z = rows[1]
+        posorient.alpha_0 = rows[3]
+        posorient.alpha_1 = rows[2]
+        posorient.alpha_2 = rows[4]
+        # conn.close()
+        # print("posorient",posorient)
+        # print(posorientall.head())
+        image = processing.scene(self.mydb, posorient=posorient)
+        self.assertIsNotNone(image)
+        self.assertFalse(sum(image.shape) == 0)
+        # print("shape",image.shape)
+        self.assertTrue(len(image.shape) == 4)
+        self.assertTrue(image.shape[3] == 1)
+
+        # incorrect case missing column
+        posorient2 = pd.Series(index=['y', 'z',
+                                      'alpha_0', 'alpha_1', 'alpha_2'])
+        posorient2.y = posorient.y
+        posorient2.z = posorient.z
+        posorient2.alpha_0 = posorient.alpha_0
+        posorient2.alpha_1 = posorient.alpha_1
+        posorient2.alpha_2 = posorient.alpha_2
+        with self.assertRaises(Exception) as cm:
+            image = processing.scene(self.mydb, posorient=posorient2)
+        # print("missing column")
+        print(cm.exception)
+
+        # incorrect case None
+        posorient2 = pd.Series(index=['x', 'y', 'z',
+                                      'alpha_0', 'alpha_1', 'alpha_2'])
+        posorient2.x = None
+        posorient2.y = posorient.y
+        posorient2.z = posorient.z
+        posorient2.alpha_0 = posorient.alpha_0
+        posorient2.alpha_1 = posorient.alpha_1
+        posorient2.alpha_2 = posorient.alpha_2
+        with self.assertRaises(Exception) as cm:
+            image = processing.scene(self.mydb, posorient=posorient2)
+        print(cm.exception)
+
+        # incorrect case nan
+        posorient2 = pd.Series(index=['x', 'y', 'z',
+                                      'alpha_0', 'alpha_1', 'alpha_2'])
+        posorient2.x = np.nan
+        posorient2.y = posorient.y
+        posorient2.z = posorient.z
+        posorient2.alpha_0 = posorient.alpha_0
+        posorient2.alpha_1 = posorient.alpha_1
+        posorient2.alpha_2 = posorient.alpha_2
+        with self.assertRaises(Exception) as cm:
+            image = processing.scene(self.mydb, posorient=posorient2)
+        print(cm.exception)
+
+        # incorrect case no pandas series but dict
+        posorient2 = {}
+        posorient2['x'] = posorient.x
+        posorient2['y'] = posorient.y
+        posorient2['z'] = posorient.z
+        posorient2['alpha_0'] = posorient.alpha_0
+        posorient2['alpha_1'] = posorient.alpha_1
+        posorient2['alpha_2'] = posorient.alpha_2
+        with self.assertRaises(Exception) as cm:
+            image = processing.scene(self.mydb, posorient=posorient2)
+        print(cm.exception)
+
+        # not working case empty
+        posorient2 = pd.Series(index=['x', 'y', 'z',
+                                      'alpha_0', 'alpha_1', 'alpha_2'])
+
+        with self.assertRaises(Exception) as cm:
+            image = processing.scene(self.mydb, posorient=posorient2)
+        print(cm.exception)
+
+    """
+    def test_db(self):
+
+        #build_test_db()
+        #empty database -> should not work
+        db_filename='test_db_1'
+        #loading should not work cuz not
+        #all required tables are in this database
+        with self.assertRaises(Exception) as cm:
+            db=database.DataBaseLoad(db_filename)
+        print("a wanted error occured", cm.exception)
+        #reading should not anyway
+        with self.assertRaises(Exception) as cm:
+            image = db.read_image(rowid=1)
+
+        #empty database -> should work??
+        db_filename='test_db_2'
+        #loading should work
+        db=database.DataBaseLoad(db_filename)
+        #reading should not
+        with self.assertRaises(Exception) as cm:
+            image = db.read_image(rowid=1)
+    """
+
+    def test_skyline_scene(self):
+        # image = processing.scene(self.mydb,posorient=posorient)
+        # print("image size skyline test",image.shape)
+        scene = processing.scene(self.mydb, rowid=1)
+        # print("scene size skypline test",scene.shape)
+        scene2 = scene.copy()
+        scene2[3, 5, 2, 0] = np.nan
+        scene3 = [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
+        scene3 = [scene3, scene3, scene3]
+        scene3 = np.array(scene3)
+        scene4 = np.zeros((3, 4, 5, 0))
+
+        for s in [scene2, scene3, scene4]:  # put useless stuff here
+            with self.assertRaises(Exception) as cm:
+                processing.skyline(s)
+            print("wanted exception occured", cm.exception)
+
+        # should be working -> check if result(skyline) is correct
+        for s in [scene]:
+            skyline = processing.skyline(s)
+            self.assertFalse(skyline.shape[1] <= 0)
+            self.assertTrue(skyline.shape[2] == 4)
+            self.assertFalse(np.any(np.isnan(skyline)))
+            # self.assertFalse(np.any(np.isNone(skyline)))
+            self.assertTrue(is_numeric_array(skyline))
+            self.assertTrue(skyline.shape[3] == 1)
+            self.assertTrue(skyline.shape[0] > 0)
+            self.assertTrue(skyline.shape[1] > 0)
+
+    def test_id(self):
+        # print("test_id")
+        # check for wrong cases
+        # my_scene = processing.scene(self.mydb, rowid=-2)
+        for rowid in [0, 't', -2, 4.5, np.nan, None]:
+
+            with self.assertRaises(Exception) as cm:
+                # print("rowid",rowid)
+                processing.scene(self.mydb, rowid=rowid)
+            the_exception = cm.exception
+            print("error occured", the_exception)
+
+        for rowid in [1, 2, 3, 4, 5]:
+            image = processing.scene(self.mydb, rowid=rowid)
+            # image=np.array(image)
+            self.assertIsNotNone(image)
+            self.assertFalse(sum(image.shape) == 0)
+            self.assertTrue(len(image.shape) == 4)
+            self.assertFalse(np.any(np.isnan(image)))
+            self.assertTrue(image.shape[3] == 1)
+            self.assertTrue(image.shape[2] == 4)
+            self.assertTrue(image.shape[0] > 0)
+            self.assertTrue(image.shape[1] > 0)
+
+    def test_distance_channel(self):
+        scene = processing.scene(self.mydb, rowid=1)
+        # print("scene sizejhghghhg",scene.shape)
+        # should not be working
+        for d in [-1, 'g', None, np.nan, 8.4]:
+            with self.assertRaises(Exception) as cm:
+                processing.contrast_weighted_nearness(scene,
+                                                      distance_channel=d)
+            print("wanted error occured", cm.exception)
+
+        # should work
+        for d in [0, 1, 2, 3]:
+            weighted_scene = \
+                processing.contrast_weighted_nearness(scene,
+                                                      distance_channel=d)
+            # print("last channel",d)
+            assert is_numeric_array(weighted_scene)
+            assert ~np.any(np.isnan(weighted_scene))
+            assert len(weighted_scene.shape) == 4
+            assert ~(weighted_scene.shape[1] <= 0)
+            assert ~(weighted_scene.shape[0] <= 0)
+            assert (weighted_scene.shape[2] == 4)
+            assert ~(np.any(np.isNone(weighted_scene)))
+
+    def test_contr_weight_scene(self):
+        scene = processing.scene(self.mydb, rowid=1)
+
+        # working cases
+        contrast = processing.contrast_weighted_nearness(scene)
+        self.assertIsNotNone(contrast)
+        self.assertFalse(sum(contrast.shape) == 0)
+        self.assertTrue(len(contrast.shape) == 4)
+        self.assertFalse(np.any(np.isnan(contrast)))
+        self.assertTrue(contrast.shape[3] == 1)
+        self.assertTrue(contrast.shape[2] == 4)
+        self.assertTrue(contrast.shape[0] > 0)
+        self.assertTrue(contrast.shape[1] > 0)
+
+        # not working case
+        scene2 = scene.copy()
+        scene2[3, 2, 1, 0] = np.nan
+        scene3 = [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
+        scene3 = [scene3, scene3, scene3]
+        scene3 = np.array(scene3)
+        scene4 = np.zeros((3, 4, 5, 0))
+        for s in [scene2, scene3, scene4]:
+            with self.assertRaises(Exception) as cm:
+                contrast = processing.contrast_weighted_nearness(scene)
+            print("wanted excption occured", cm.exception)
+
+    def test_contr_weight_contrast(self):
+        scene = processing.scene(self.mydb, rowid=1)
+        for size in [8, 1, 0, -4, 9.4, 'g', None, np.nan]:
+            with self.assertRaises(Exception) as cm:
+                contrast = \
+                    processing.contrast_weighted_nearness(scene,
+                                                          contrast_size=size)
+            print("wanted error occured", cm.exception)
+
+        # working cases
+        for size in [2, 3, 4, 5]:
+            contrast = \
+                processing.contrast_weighted_nearness(scene,
+                                                      contrast_size=size)
+            self.assertIsNotNone(contrast)
+            self.assertFalse(sum(contrast.shape) == 0)
+            self.assertTrue(len(contrast.shape) == 4)
+            self.assertFalse(np.any(np.isnan(contrast)))
+            self.assertTrue(contrast.shape[3] == 1)
+            self.assertTrue(contrast.shape[2] == 4)
+            self.assertTrue(contrast.shape[0] > 0)
+            self.assertTrue(contrast.shape[1] > 0)
+
+    def test_pcv(self):
+        # working case
+        rowid = 1
+        my_scene = processing.scene(self.mydb, rowid=rowid)
+        # print("scene shape",my_scene.shape)
+        directions = self.mydb.viewing_directions
+        # print("directions",directions.shape)
+        my_pcv = processing.pcv(my_scene, directions)
+        # print("place code shape",my_pcv.shape)
+
+        self.assertIsNotNone(my_pcv)
+        self.assertFalse(sum(my_pcv.shape) == 0)
+        self.assertTrue(len(my_pcv.shape) == 4)
+        self.assertFalse(np.any(np.isnan(my_pcv)))
+        self.assertTrue(my_pcv.shape[3] == 3)
+        self.assertTrue(my_pcv.shape[2] == 4)
+        self.assertTrue(my_pcv.shape[0] > 0)
+        self.assertTrue(my_pcv.shape[1] > 0)
+
+        # not working cases doesnt match with shape of place code
+        testdirection = np.zeros((2, 4, 2))
+        with self.assertRaises(Exception) as cm:
+            my_pcv = processing.pcv(my_scene, testdirection)
+        print("wanted exception occured", cm.exception)
+
+        # not working cases wrong last dimension
+        testdirection = np.zeros((180, 360, 1))
+        with self.assertRaises(Exception) as cm:
+            my_pcv = processing.pcv(my_scene, testdirection)
+        print("wanted exception occured", cm.exception)
+
+        # not working cases too many dimensions
+        testdirection = np.zeros((180, 360, 2, 4))
+        with self.assertRaises(Exception) as cm:
+            my_pcv = processing.pcv(my_scene, testdirection)
+        print("wanted exception occured", cm.exception)
+
+        # not working cases empty
+        testdirection = np.zeros(())
+        with self.assertRaises(Exception) as cm:
+            my_pcv = processing.pcv(my_scene, testdirection)
+        print("wanted exception occured", cm.exception)
+
+        # not working cases nans
+        testdirection = np.zeros((180, 360, 2, 4))
+        testdirection[2, 3, 0] = np.nan
+        with self.assertRaises(Exception) as cm:
+            my_pcv = processing.pcv(my_scene, testdirection)
+        print("wanted exception occured", cm.exception)
+
+    def test_apcv(self):
+        # working case
+        rowid = 1
+        my_scene = processing.scene(self.mydb, rowid=rowid)
+        # print("scene shape",my_scene.shape)
+        directions = self.mydb.viewing_directions
+        # print("directions",directions.shape)
+        my_pcv = processing.apcv(my_scene, directions)
+        print("place code shape", my_pcv.shape)
+
+        self.assertIsNotNone(my_pcv)
+        self.assertFalse(sum(my_pcv.shape) == 0)
+        self.assertTrue(len(my_pcv.shape) == 4)
+        self.assertFalse(np.any(np.isnan(my_pcv)))
+        self.assertTrue(my_pcv.shape[3] == 3)
+        self.assertTrue(my_pcv.shape[2] == 4)
+        self.assertTrue(my_pcv.shape[0] == 1)
+        self.assertTrue(my_pcv.shape[1] == 1)
+
+        # not working cases doesnt match with shape of place code
+        testdirection = np.zeros((2, 4, 2))
+        with self.assertRaises(Exception) as cm:
+            my_pcv = processing.apcv(my_scene, testdirection)
+        print("wanted exception occured", cm.exception)
+
+        # not working cases wrong last dimension
+        testdirection = np.zeros((180, 360, 1))
+        with self.assertRaises(Exception) as cm:
+            my_pcv = processing.apcv(my_scene, testdirection)
+        print("wanted exception occured", cm.exception)
+
+        # not working cases too many dimensions
+        testdirection = np.zeros((180, 360, 2, 4))
+        with self.assertRaises(Exception) as cm:
+            my_pcv = processing.apcv(my_scene, testdirection)
+        print("wanted exception occured", cm.exception)
+
+        # not working cases empty
+        testdirection = np.zeros(())
+        with self.assertRaises(Exception) as cm:
+            my_pcv = processing.apcv(my_scene, testdirection)
+        print("wanted exception occured", cm.exception)
+
+        # not working cases nans
+        testdirection = np.zeros((180, 360, 2, 4))
+        testdirection[2, 3, 0] = np.nan
+        with self.assertRaises(Exception) as cm:
+            my_pcv = processing.apcv(my_scene, testdirection)
+        print("wanted exception occured", cm.exception)
+
+    def test_size(self):
+        # not working cases:
+        scene = processing.scene(self.mydb, rowid=1)
+        for size in [8, 1, 0, -4, 9.4, 'g', None, np.nan]:
+            with self.assertRaises(Exception) as cm:
+                contrast = processing.michelson_contrast(scene, size=size)
+            print("wanted error occured", cm.exception)
+
+        # working cases
+        for size in [2, 3, 4, 5]:
+            contrast = processing.michelson_contrast(scene, size=size)
+            self.assertIsNotNone(contrast)
+            self.assertFalse(sum(contrast.shape) == 0)
+            self.assertTrue(len(contrast.shape) == 4)
+            self.assertFalse(np.any(np.isnan(contrast)))
+            self.assertTrue(contrast.shape[3] == 1)
+            self.assertTrue(contrast.shape[2] == 4)
+            self.assertTrue(contrast.shape[0] > 0)
+            self.assertTrue(contrast.shape[1] > 0)
+
+    def test_michelsoncontrast_scene(self):
+
+        scene = processing.scene(self.mydb, rowid=1)
+
+        # working cases
+        contrast = processing.michelson_contrast(scene)
+        self.assertIsNotNone(contrast)
+        self.assertFalse(sum(contrast.shape) == 0)
+        self.assertTrue(len(contrast.shape) == 4)
+        self.assertFalse(np.any(np.isnan(contrast)))
+        self.assertTrue(contrast.shape[3] == 1)
+        self.assertTrue(contrast.shape[2] == 4)
+        self.assertTrue(contrast.shape[0] > 0)
+        self.assertTrue(contrast.shape[1] > 0)
+
+        # not working case
+        scene2 = scene.copy()
+        scene2[3, 2, 1, 0] = np.nan
+        scene3 = [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
+        scene3 = [scene3, scene3, scene3]
+        scene3 = np.array(scene3)
+        scene4 = np.zeros((3, 4, 5, 0))
+        for s in [scene2, scene3, scene4]:
+            with self.assertRaises(Exception) as cm:
+                contrast = processing.michelson_contrast(s,)
+            print("wanted exception occured", cm.exception)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/src/processing/tools.py b/src/processing/tools.py
index d77f133..d61aefa 100644
--- a/src/processing/tools.py
+++ b/src/processing/tools.py
@@ -1,4 +1,8 @@
-import processing.constants as prc
+from .constants import __ibpc_indeces__
+from .constants import __spherical_indeces__
+from .constants import __cartesian_indeces__
+from .constants import __obpc_indeces__
+from .constants import __eye_indeces__
 import numpy as np
 
 
@@ -12,7 +16,7 @@ def is_ibpc(place_code):
     """
     toreturn = isinstance(place_code, np.ndarray)
     toreturn = toreturn and (len(place_code.shape) ==
-                             len(prc.__ibpc_indeces__))
+                             len(__ibpc_indeces__))
     return toreturn
 
 
@@ -26,7 +30,7 @@ def is_obpc(place_code):
     """
     toreturn = isinstance(place_code, np.ndarray)
     toreturn = toreturn and (len(place_code.shape) ==
-                             len(prc.__obpc_indeces__))
+                             len(__obpc_indeces__))
     return toreturn
 
 
@@ -41,22 +45,22 @@ def ibs_to_obs(scene, eye_map):
     assert is_ibpc(scene),\
         'scene should be an ibs scene'
     assert isinstance(eye_map, np.ndarray), 'eye_map should be a numpy array'
-    assert len(eye_map.shape) == len(prc.__eye_indeces__),\
+    assert len(eye_map.shape) == len(__eye_indeces__),\
         'eye_map should have {} dimensions to be an ibs scene'.format(
-            len(prc.__eye_indeces__))
+            len(__eye_indeces__))
     for index_name in ['elevation', 'azimuth']:
-        index = prc.__ibpc_indeces__[index_name]
+        index = __ibpc_indeces__[index_name]
         assert eye_map.shape[index] == scene.shape[index],\
             'eye_map and scene should have the same number of {}'.format(
                 index_name)
-    obs_size = (scene.shape[prc.__ibpc_indeces__['elevation']] *
-                scene.shape[prc.__ibpc_indeces__['azimuth']],
-                scene.shape[prc.__ibpc_indeces__['channel']],
-                scene.shape[prc.__ibpc_indeces__['component']])
+    obs_size = (scene.shape[__ibpc_indeces__['elevation']] *
+                scene.shape[__ibpc_indeces__['azimuth']],
+                scene.shape[__ibpc_indeces__['channel']],
+                scene.shape[__ibpc_indeces__['component']])
     obs_scene = scene.reshape(obs_size)
-    omm_size = (eye_map.shape[prc.__ibpc_indeces__['elevation']] *
-                eye_map.shape[prc.__ibpc_indeces__['azimuth']],
-                eye_map.shape[prc.__ibpc_indeces__['component']])
+    omm_size = (eye_map.shape[__ibpc_indeces__['elevation']] *
+                eye_map.shape[__ibpc_indeces__['azimuth']],
+                eye_map.shape[__ibpc_indeces__['component']])
     ommatidia_map = eye_map.reshape(omm_size)
     return (obs_scene, ommatidia_map)
 
@@ -67,19 +71,19 @@ def cartesian_to_spherical(x, y, z):
     azimuth = np.arctan2(y, x)
     spherical = np.zeros_like(x)
     spherical = np.tile(spherical[..., np.newaxis], (3,))
-    spherical[..., prc.__spherical_indeces__['elevation']] = elevation
-    spherical[..., prc.__spherical_indeces__['azimuth']] = azimuth
-    spherical[..., prc.__spherical_indeces__['radius']] = radius
+    spherical[..., __spherical_indeces__['elevation']] = elevation
+    spherical[..., __spherical_indeces__['azimuth']] = azimuth
+    spherical[..., __spherical_indeces__['radius']] = radius
     return spherical
 
 
 def spherical_to_cartesian(elevation, azimuth, radius=1):
     cartesian = np.zeros_like(elevation)
     cartesian = np.tile(cartesian[..., np.newaxis], (3,))
-    cartesian[..., prc.__cartesian_indeces__['x']] = np.cos(
+    cartesian[..., __cartesian_indeces__['x']] = np.cos(
         elevation) * np.cos(azimuth)
-    cartesian[..., prc.__cartesian_indeces__['y']] = np.cos(
+    cartesian[..., __cartesian_indeces__['y']] = np.cos(
         elevation) * np.sin(azimuth)
-    cartesian[..., prc.__cartesian_indeces__['z']] = np.sin(elevation)
+    cartesian[..., __cartesian_indeces__['z']] = np.sin(elevation)
     cartesian = radius * cartesian
     return cartesian
-- 
GitLab