diff --git a/build/lib/navipy/__init__.py b/build/lib/navipy/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/build/lib/navipy/comparing/__init__.py b/build/lib/navipy/comparing/__init__.py deleted file mode 100644 index 703cb552f4d603eed2ebcc9feb4c6a68db04f59a..0000000000000000000000000000000000000000 --- a/build/lib/navipy/comparing/__init__.py +++ /dev/null @@ -1,143 +0,0 @@ -""" -The Place comparator list different methods to -compare a current place to a memorised place or -memorised places. -""" -import numpy as np -from navipy.processing.tools import is_ibpc, is_obpc -from navipy.processing.tools import check_scene - - -def simple_imagediff(current, memory): - """Compute the difference between -the current and memorised place code - - :param current: current place code - :param memory: memorised place code - :returns: the image difference - :rtype: float - - ..ref: Zeil, J., 2012. Visual homing: an insect perspective. - Current opinion in neurobiology - - """ - if not isinstance(current, np.ndarray): - raise TypeError('current place code should be a numpy array') - if not isinstance(memory, np.ndarray): - raise TypeError('memory place code should be a numpy array') - if not np.all(current.shape == memory.shape): - raise Exception('memory and current place code should\ - have the same shape') - check_scene(current) - check_scene(memory) - diff = current - memory - if is_ibpc(current): - return diff - elif is_obpc(current): - return diff - else: - raise TypeError('place code is neither an ibpc nor obpc') - - -def imagediff(current, memory): - """Compute the root mean square difference between -the current and memorised place code - - :param current: current place code - :param memory: memorised place code - :returns: the image difference - :rtype: float #array(1,4) for ibpc and float for obpc - - ..ref: Zeil, J., 2012. Visual homing: an insect perspective. - Current opinion in neurobiology - - """ - simple_diff = simple_imagediff(current, memory) - diff = np.power(simple_diff, 2) - if is_ibpc(current): - return np.sqrt(diff.mean(axis=0).mean(axis=0)) # 1 - elif is_obpc(current): - return np.sqrt(diff.mean(axis=0).mean(axis=0)) - else: - raise TypeError('place code is neither an ibpc nor obpc') - - -def rot_imagediff(current, memory): - """Compute the rotational image difference between -the current and memorised place code. - - :param current: current place code - :param memory: memorised place code - :returns: the rotational image difference - :rtype: (np.ndarray) - - ..ref: Zeil, J., 2012. Visual homing: an insect perspective. - Current opinion in neurobiology - ..note: assume that the image is periodic along the x axis - (the left-right axis) - """ - if not is_ibpc(current): # and not is_obpc(current): - raise TypeError('The current and memory place code\ - should be image based') - if not is_ibpc(memory): # and not is_obpc(memory): - raise TypeError('The current and memory place code\ - should be image based') - check_scene(current) - check_scene(memory) - ridf = np.zeros((current.shape[1], current.shape[2])) - for azimuth_i in range(0, current.shape[1]): - rot_im = np.roll(current, azimuth_i, axis=1) - ridf[azimuth_i, :] = np.squeeze(imagediff(rot_im, memory)) # rot_im - return ridf - - -def diff_optic_flow(current, memory): - """Computes the direction of motion from current -to memory by using the optic flow under the -constrain that the brightness is constant, (small movement), -using a taylor expansion and solving the equation: -0=I_t+\delta I*<u,v> or I_x+I_y+I_t=0 - -afterwards the aperture problem is solved by a -Matrix equation Ax=b, where x=(u,v) and -A=(I_x,I_y) and b = I_t - - :param current: current place code - :param memory: memorised place code - :returns: a directional vectors - :rtype: (np.ndarray) - - ..ref: aperture problem: - Shimojo, Shinsuke, Gerald H. Silverman, and Ken Nakayama: - "Occlusion and the solution to the aperture problem for motion." - Vision research 29.5 (1989): 619-626. - optic flow: - Horn, Berthold KP, and Brian G. Schunck.: - "Determining optical flow." - Artificial intelligence 17.1-3 (1981): 185-203. - """ - if not is_ibpc(current): # and not is_obpc(current): - raise TypeError('The current and memory place code\ - should be image based') - if not is_ibpc(memory): # and not is_obpc(memory): - raise TypeError('The current and memory place code\ - should be image based') - check_scene(current) - check_scene(memory) - currroll = np.roll(current, 1, axis=1) - dx = current - currroll - memroll = np.roll(memory, 1, axis=1) - dy = memory - memroll - dy = np.reshape(dy, (np.prod(dy.shape), 1)) - dx = np.reshape(dx, (np.prod(dx.shape), 1)) - di = current - memory - di = np.reshape(di, (np.prod(di.shape), 1)) - a_matrix = np.column_stack([dy, dx]) - a_matrix_sqr = np.dot(np.transpose(a_matrix), a_matrix) - b_vector = np.dot(np.transpose(a_matrix), di) - res = np.linalg.solve(a_matrix_sqr, b_vector) - return res - - -def gradient(current, memory): - return 0 diff --git a/build/lib/navipy/comparing/test.py b/build/lib/navipy/comparing/test.py deleted file mode 100644 index 7770aa46493072404e44960c6ce6d0f356f3e2d3..0000000000000000000000000000000000000000 --- a/build/lib/navipy/comparing/test.py +++ /dev/null @@ -1,220 +0,0 @@ -import unittest -import numpy as np -import navipy.database as database -import navipy.comparing as comparing -from navipy.processing.tools import is_numeric_array -import pkg_resources - - -class TestCase(unittest.TestCase): - def setUp(self): - self.mydb_filename = pkg_resources.resource_filename( - 'navipy', 'resources/database.db') - self.mydb = database.DataBaseLoad(self.mydb_filename) - - def test_imagediff_curr(self): - curr = self.mydb.scene(rowid=1) - mem = self.mydb.scene(rowid=2) - curr2 = curr.copy() - curr2[3, 5, 2, 0] = np.nan - curr3 = [[1, 2, 3], [1, 2, 3], [1, 2, 3]] - curr3 = [curr3, curr3, curr3] - curr3 = np.array(curr3) - curr4 = np.zeros((3, 4, 5, 0)) - - # put useless stuff here - with self.assertRaises(ValueError): - comparing.imagediff(curr2, mem) - with self.assertRaises(Exception): - comparing.imagediff(curr3, mem) - with self.assertRaises(Exception): - comparing.imagediff(curr4, mem) - - # should be working -> check if result is correct - for s in [curr]: - diff = comparing.imagediff(s, mem) - # self.assertTrue(diff.shape[1] == 1) - self.assertTrue(diff.shape[0] > 0) - self.assertFalse(np.any(np.isnan(diff))) - self.assertTrue(is_numeric_array(diff)) - - def test_imagediff_memory(self): - curr = self.mydb.scene(rowid=1) - mem = self.mydb.scene(rowid=2) - mem2 = curr.copy() - mem2[3, 5, 2] = np.nan - mem3 = [[1, 2], [1, 2], [1, 2]] - mem3 = [mem3, mem3, mem3] - mem3 = np.array(mem3) - mem4 = np.zeros((3, 4, 5)) - - with self.assertRaises(ValueError): - comparing.imagediff(curr, mem2) - with self.assertRaises(Exception): - comparing.imagediff(curr, mem3) - with self.assertRaises(Exception): - comparing.imagediff(curr, mem4) - - # should be working -> check if result is correct - for s in [mem]: - diff = comparing.imagediff(curr, s) - self.assertFalse(diff.shape[0] <= 0) - # self.assertTrue(diff.shape[1] == 1) - self.assertFalse(np.any(np.isnan(diff))) - self.assertTrue(is_numeric_array(diff)) - - def test_rot_imagediff_curr(self): - curr = self.mydb.scene(rowid=1) - mem = self.mydb.scene(rowid=2) - curr2 = curr.copy() - curr2[3, 5, 2] = np.nan - curr3 = [[1, 2, 3], [1, 2, 3], [1, 2, 3]] - curr3 = [curr3, curr3, curr3] - curr3 = np.array(curr3) - curr4 = np.zeros((3, 4, 5)) - - with self.assertRaises(ValueError): - comparing.rot_imagediff(curr2, mem) - with self.assertRaises(Exception): - comparing.rot_imagediff(curr3, mem) - with self.assertRaises(Exception): - comparing.rot_imagediff(curr4, mem) - - # should be working -> check if result is correct - for s in [curr]: - diff = comparing.rot_imagediff(s, mem) - self.assertFalse(diff.shape[0] <= 0) - self.assertTrue(diff.shape[1] == 4) - self.assertFalse(np.any(np.isnan(diff))) - self.assertTrue(is_numeric_array(diff)) - - def test_rotimagediff_memory(self): - curr = self.mydb.scene(rowid=1) - mem = self.mydb.scene(rowid=2) - mem2 = curr.copy() - mem2[3, 5, 2] = np.nan - mem3 = [[1, 2, 3], [1, 2, 3], [1, 2, 3]] - mem3 = [mem3, mem3, mem3] - mem3 = np.array(mem3) - mem4 = np.zeros((3, 4, 5)) - - with self.assertRaises(ValueError): - comparing.rot_imagediff(curr, mem2) - with self.assertRaises(Exception): - comparing.rot_imagediff(curr, mem3) - with self.assertRaises(Exception): - comparing.rot_imagediff(curr, mem4) - - # should be working -> check if result is correct - for s in [mem]: - diff = comparing.rot_imagediff(curr, s) - self.assertFalse(diff.shape[0] <= 0) - self.assertTrue(diff.shape[1] == 4) - self.assertFalse(np.any(np.isnan(diff))) - self.assertTrue(is_numeric_array(diff)) - - def test_simple_imagediff_curr(self): - curr = self.mydb.scene(rowid=1) - mem = self.mydb.scene(rowid=2) - curr2 = curr.copy() - curr2[3, 5, 2] = np.nan - curr3 = [[1, 2, 3], [1, 2, 3], [1, 2, 3]] - curr3 = [curr3, curr3, curr3] - curr3 = np.array(curr3) - curr4 = np.zeros((3, 4, 5)) - - with self.assertRaises(ValueError): - comparing.simple_imagediff(curr2, mem) - with self.assertRaises(Exception): - comparing.simple_imagediff(curr3, mem) - with self.assertRaises(Exception): - comparing.simple_imagediff(curr4, mem) - - # should be working -> check if result is correct - for s in [curr]: - diff = comparing.simple_imagediff(s, mem) - self.assertFalse(diff.shape[0] <= 0) - self.assertTrue(diff.shape[1] > 0) - self.assertFalse(np.any(np.isnan(diff))) - self.assertTrue(is_numeric_array(diff)) - self.assertTrue(diff.shape[2] == 4) - # self.assertTrue(diff.shape[3] == 1) - - def test_simple_imagediff_mem(self): - curr = self.mydb.scene(rowid=1) - mem = self.mydb.scene(rowid=2) - mem2 = curr.copy() - mem2[3, 5, 2] = np.nan - mem3 = [[1, 2, 3], [1, 2, 3], [1, 2, 3]] - mem3 = [mem3, mem3, mem3] - mem3 = np.array(mem3) - mem4 = np.zeros((3, 4, 5)) - - with self.assertRaises(ValueError): - comparing.simple_imagediff(curr, mem2) - with self.assertRaises(Exception): - comparing.simple_imagediff(curr, mem3) - with self.assertRaises(Exception): - comparing.simple_imagediff(curr, mem4) - - # should be working -> check if result is correct - for s in [mem]: - diff = comparing.simple_imagediff(curr, s) - self.assertFalse(diff.shape[0] <= 0) - self.assertTrue(diff.shape[1] > 0) - self.assertFalse(np.any(np.isnan(diff))) - self.assertTrue(is_numeric_array(diff)) - self.assertTrue(diff.shape[2] == 4) - # self.assertTrue(diff.shape[3] == 1) - - def test_diff_optic_flow_memory(self): - curr = self.mydb.scene(rowid=1) - mem = self.mydb.scene(rowid=2) - mem2 = curr.copy() - mem2[3, 5, 2] = np.nan - mem3 = [[1, 2, 3], [1, 2, 3], [1, 2, 3]] - mem3 = [mem3, mem3, mem3] - mem3 = np.array(mem3) - mem4 = np.zeros((3, 4, 5)) - - with self.assertRaises(ValueError): - comparing.diff_optic_flow(curr, mem2) - with self.assertRaises(Exception): - comparing.diff_optic_flow(curr, mem3) - with self.assertRaises(Exception): - comparing.diff_optic_flow(curr, mem4) - - # should be working -> check if result is correct - for s in [mem]: - vec = comparing.diff_optic_flow(curr, s) - self.assertFalse(vec.shape[1] == (1, 2)) - self.assertFalse(np.any(np.isnan(vec))) - self.assertTrue(is_numeric_array(vec)) - - def test_diff_optic_flow_curr(self): - curr = self.mydb.scene(rowid=1) - mem = self.mydb.scene(rowid=2) - curr2 = curr.copy() - curr2[3, 5, 2] = np.nan - curr3 = [[1, 2], [1, 2], [1, 2]] - curr3 = [curr3, curr3, curr3] - curr3 = np.array(curr3) - curr4 = np.zeros((3, 4, 5, 1)) - - with self.assertRaises(ValueError): - comparing.diff_optic_flow(curr2, mem) - with self.assertRaises(Exception): - comparing.diff_optic_flow(curr3, mem) - with self.assertRaises(Exception): - comparing.diff_optic_flow(curr4, mem) - - # should be working -> check if result is correct - for s in [mem]: - vec = comparing.diff_optic_flow(s, curr) - self.assertFalse(vec.shape[1] == (1, 2)) - self.assertFalse(np.any(np.isnan(vec))) - self.assertTrue(is_numeric_array(vec)) - - -if __name__ == '__main__': - unittest.main() diff --git a/build/lib/navipy/database/__init__.py b/build/lib/navipy/database/__init__.py deleted file mode 100644 index cd9019245cb2e5c807b10646f5b2d70cb9967c14..0000000000000000000000000000000000000000 --- a/build/lib/navipy/database/__init__.py +++ /dev/null @@ -1,626 +0,0 @@ -""" -Database are generated by the rendering module, and contains all \ -images and there corresponding position-orientations. - -* position_orientation: containing all position and orientation of where \ -images were rendered. The position-orientation is described by \ -['x','y','z','alpha_0','alpha_1','alpha_2'] -* image: containing all images ever rendered. Each channel of each image \ -are normalised, so to use the full coding range. -* normalisation: the normalisation constantes - - -How to load a database ----------------------- - -.. code-block:: python - - from database import DataBaseLoad - mydb_filename = 'database.db' - mydb = DataBaseLoad(mydb_filename) - -How to load all position-orientation ------------------------------------- - -The database contains all position-orientation \ -at which an image as been rendered. In certain \ -situation, it may be usefull to know all \ -position-orientation in the database. More technically \ -speaking, loading the full table of position-orientaiton. - -.. code-block:: python - - posorients = mydb.get_posorients() - posorients.head() - -How to load an image --------------------- - -The database contains images which can be processed differently \ -depending on the navigation strategy beeing used. - -Images are at given position-orientations. To load an image \ -the position-orientation can be given. The DataBaseLoader will \ -look if this position-orientation has been rendered. If it is \ -the case, the image will be returned. - -.. code-block:: python - - posorient = pd.Series(index=['x', 'y', 'z', - 'alpha_0', 'alpha_1', 'alpha_2']) - posorient.x = -0.6 - posorient.y = -7.2 - posorient.z = 2.35 - posorient.alpha_0 = np.pi / 2 - posorient.alpha_1 = 0 - posorient.alpha_2 = 0 - image = mydb.read_image(posorient=posorient) - -.. plot:: example/database/load_image_posorient.py - -However, looking in the database if an image has already been \ -rendered at a given position-orientation can cost time. To speed up \ -certain calculation, image can instead be access by row number. \ -Indeed each position-orientation can be identified by a unique row \ -number. This number is consistant through the entire database. Thus, \ -an image can be loaded by providing the row number. - -.. code-block:: python - - rowid = 1000 - image = mydb.read_image(rowid=rowid) - -.. plot:: example/database/load_image_rowid.py - - - -.. todo: channels as part of database - -""" - -import os -import numpy as np -import pandas as pd -import sqlite3 -import io -import warnings -import navipy.processing.tools as tools - - -def adapt_array(arr): - """ - http://stackoverflow.com/a/31312102/190597 (SoulNibbler) - """ - if arr is None: - raise ValueError('array must not be None') - out = io.BytesIO() - np.save(out, arr) - out.seek(0) - return sqlite3.Binary(out.read()) - - -def convert_array(text): - if text is None: - raise ValueError('text must not be None') - out = io.BytesIO(text) - out.seek(0) - return np.load(out) - - -# Converts np.array to TEXT when inserting -sqlite3.register_adapter(np.ndarray, adapt_array) -# Converts TEXT to np.array when selecting -sqlite3.register_converter("array", convert_array) - - -class DataBase(): - """DataBase is the parent class of DataBaseLoad and DataBaseSave. -It creates three sql table on initialisation. - """ - __float_tolerance = 1e-14 - - def __init__(self, filename, channels=['R', 'G', 'B', 'D']): - """Initialisation of the database """ - if not isinstance(filename, str): - raise TypeError('filename should be a string') - if not isinstance(channels, list): - raise TypeError('nb_channel should be a list or np array') - """for c in channels: - if not c in ['R','G','B','D']: - raise ValueError('channels - must be either R,G,B or D (Distance)')""" - self.filename = filename - self.channels = channels - self.normalisation_columns = list() - for chan_n in self.channels: - self.normalisation_columns.append(str(chan_n) + '_max') - self.normalisation_columns.append(str(chan_n) + '_min') - self.normalisation_columns.append(str(chan_n) + '_range') - - self.tablecolumns = dict() - self.tablecolumns['position_orientation'] = dict() - self.tablecolumns['position_orientation']['x'] = 'real' - self.tablecolumns['position_orientation']['y'] = 'real' - self.tablecolumns['position_orientation']['z'] = 'real' - self.tablecolumns['position_orientation']['alpha_0'] = 'real' - self.tablecolumns['position_orientation']['alpha_1'] = 'real' - self.tablecolumns['position_orientation']['alpha_2'] = 'real' - self.tablecolumns['image'] = dict() - self.tablecolumns['image']['data'] = 'array' - self.tablecolumns['normalisation'] = dict() - for col in self.normalisation_columns: - self.tablecolumns['normalisation'][col] = 'real' - - if os.path.exists(filename): - # Check database - self.db = sqlite3.connect( - 'file:' + filename + '?cache=shared', uri=True, - detect_types=sqlite3.PARSE_DECLTYPES, - timeout=10) - self.db_cursor = self.db.cursor() - for tablename, _ in self.tablecolumns.items(): - if not self.table_exist(tablename): - raise Exception('{} does not contain a table\ - named {}'.format(filename, tablename)) - elif self.create: - # Create database - self.db = sqlite3.connect( - filename, detect_types=sqlite3.PARSE_DECLTYPES) - self.db_cursor = self.db.cursor() - for key, val in self.tablecolumns.items(): - columns = "(id integer primary key autoincrement" - for colname, coltype in val.items(): - columns += ' , ' + colname + ' ' + coltype - columns += ')' - self.db_cursor.execute( - "create table {} {}".format(key, columns)) - self.db.commit() - else: - raise NameError('Database {} does not exist'.format(filename)) - - azimuth = np.linspace(-180, 180, 360) - elevation = np.linspace(-90, 90, 180) - [ma, me] = np.meshgrid(azimuth, elevation) - self.viewing_directions = np.zeros((ma.shape[0], ma.shape[1], 2)) - self.viewing_directions[..., 0] = me - self.viewing_directions[..., 1] = ma - - def table_exist(self, tablename): - if not isinstance(tablename, str): - raise TypeError('tablename should be a string') - self.db_cursor.execute( - """ - SELECT count(*) - FROM sqlite_master - WHERE type='table' and name=?; - """, (tablename,)) - return bool(self.db_cursor.fetchone()) - - def check_data_validity(self, rowid): - if not isinstance(rowid, int): - raise TypeError('rowid must be an integer') - if rowid <= 0: - raise ValueError('rowid must be greater zero') - if rowid is np.nan: - raise ValueError('rowid must not be nan') - self.db_cursor.execute( - """ - SELECT count(*) - FROM position_orientation - WHERE rowid=?; - """, (rowid,)) - valid = bool(self.db_cursor.fetchone()[0]) - self.db_cursor.execute( - """ - SELECT count(*) - FROM normalisation - WHERE rowid=?; - """, (rowid,)) - valid = valid and bool(self.db_cursor.fetchone()[0]) - self.db_cursor.execute( - """ - SELECT count(*) - FROM image - WHERE rowid=?; - """, (rowid,)) - valid = valid and bool(self.db_cursor.fetchone()[0]) - return valid - - def get_posid(self, posorient): - if not isinstance(posorient, pd.Series): - raise TypeError('posorient should be a pandas Series') - if posorient is not None: - if not isinstance(posorient, pd.Series): - raise TypeError('posorient should be a pandas Series') - if posorient.empty: - raise Exception('position must not be empty') - if 'x' not in posorient.index: - raise ValueError('missing index x') - if 'y' not in posorient.index: - raise ValueError('missing index y') - if 'z' not in posorient.index: - raise ValueError('missing index z') - if 'alpha_0' not in posorient.index: - raise ValueError('missing index alpha_0') - if 'alpha_1' not in posorient.index: - raise ValueError('missing index alpha_1') - if 'alpha_2' not in posorient.index: - raise ValueError('missing index alpha_2') - if np.any(pd.isnull(posorient)): - raise ValueError('posorient must not contain nan') - where = """x>=? and x<=?""" - where += """and y>=? and y<=?""" - where += """and z>=? and z<=?""" - where += """and alpha_0>=? and alpha_0<=?""" - where += """and alpha_1>=? and alpha_1<=?""" - where += """and alpha_2>=? and alpha_2<=?""" - params = ( - posorient['x'] - self.__float_tolerance, - posorient['x'] + self.__float_tolerance, - posorient['y'] - self.__float_tolerance, - posorient['y'] + self.__float_tolerance, - posorient['z'] - self.__float_tolerance, - posorient['z'] + self.__float_tolerance, - posorient['alpha_0'] - self.__float_tolerance, - posorient['alpha_0'] + self.__float_tolerance, - posorient['alpha_1'] - self.__float_tolerance, - posorient['alpha_1'] + self.__float_tolerance, - posorient['alpha_2'] - self.__float_tolerance, - posorient['alpha_2'] + self.__float_tolerance) - self.db_cursor.execute( - """ - SELECT count(*) - FROM position_orientation - WHERE {};""".format(where), params) - exist = self.db_cursor.fetchone()[0] # [0] because of tupple - if bool(exist): - self.db_cursor.execute( - """ - SELECT rowid - FROM position_orientation - WHERE {}; - """.format(where), params) - return self.db_cursor.fetchone()[0] - elif self.create: - self.db_cursor.execute( - """ - INSERT - INTO position_orientation(x,y,z,alpha_0,alpha_1,alpha_2) - VALUES (?,?,?,?,?,?) - """, ( - posorient['x'], - posorient['y'], - posorient['z'], - posorient['alpha_0'], - posorient['alpha_1'], - posorient['alpha_2'])) - rowid = self.db_cursor.lastrowid - self.db.commit() - return rowid - else: - print(posorient) - raise ValueError('posorient not found') - - @property - def create(self): - return False - - -class DataBaseLoad(DataBase): - """A database generated by the rendering module is based on sqlite3. - """ - - def __init__(self, filename, channels=['R', 'G', 'B', 'D']): - """Initialise the DataBaseLoader""" - if not isinstance(filename, str): - raise TypeError('filename should be a string') - if not isinstance(channels, list): - raise TypeError('nb_channel should be a list or np array') - for c in channels: - if c not in ['R', 'G', 'B', 'D']: - raise ValueError('channels must be either\ - R,G,B or D (Distance)') - DataBase.__init__(self, filename, channels=channels) - - @property - def create(self): - """use to decide weather to alter the database or not - return False because we do not want - to write on database (Load class)""" - return False - - def iter_posorients(self): - """Iter through all position orientation in the database - """ - self.db_cursor.execute( - """ - SELECT * - FROM position_orientation - """) - - columns_names = [] - for col in self.db_cursor.description: - columns_names.append(col[0]) - for row in self.db_cursor: - toyield = pd.Series(data=row, index=columns_names) - toyield.name = toyield.id - toyield.drop('id', inplace=True) - yield toyield - - @property - def posorients(self): - """Return the position orientations of all points in the \ -database - """ - posorient = pd.read_sql_query( - "select * from position_orientation;", self.db) - posorient.set_index('id', inplace=True) - return posorient - - def read_posorient(self, posorient=None, rowid=None): - if not isinstance(posorient, pd.Series): - ('posorient should be a pandas Series') - if posorient is not None: - if not isinstance(posorient, pd.Series): - raise TypeError('posorient should be a pandas Series') - if posorient.empty: - raise Exception('position must not be empty') - if 'x' not in posorient.index: - raise ValueError('missing index x') - if 'y' not in posorient.index: - raise ValueError('missing index y') - if 'z' not in posorient.index: - raise ValueError('missing index z') - if 'alpha_0' not in posorient.index: - raise ValueError('missing index alpha_0') - if 'alpha_1' not in posorient.index: - raise ValueError('missing index alpha_1') - if 'alpha_2' not in posorient.index: - raise ValueError('missing index alpha_2') - if np.any(pd.isnull(posorient)): - raise ValueError('posorient must not contain nan') - if not isinstance(rowid, int): - raise TypeError('rowid must be an integer') - if rowid <= 0: - raise ValueError('rowid must be greater zero') - if rowid is np.nan: - raise ValueError('rowid must not be nan') - if (posorient is None) and (rowid is None): - Exception('posorient and rowid can not be both None') - if posorient is not None: - rowid = self.get_posid(posorient) - # Read images - tablename = 'position_orientation' - toreturn = pd.read_sql_query( - """ - SELECT * - FROM {} - WHERE (rowid={}) - """.format(tablename, rowid), self.db) - toreturn = toreturn.loc[0, :] - toreturn.name = toreturn.id - toreturn.drop('id') - toreturn = toreturn.astype(float) - return toreturn - - 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: - if not isinstance(posorient, pd.Series): - raise TypeError('posorient should be a pandas Series') - if posorient.empty: - raise Exception('position must not be empty') - if 'x' not in posorient.index: - raise ValueError('missing index x') - if 'y' not in posorient.index: - raise ValueError('missing index y') - if 'z' not in posorient.index: - raise ValueError('missing index z') - if 'alpha_0' not in posorient.index: - raise ValueError('missing index alpha_0') - if 'alpha_1' not in posorient.index: - raise ValueError('missing index alpha_1') - if 'alpha_2' not in posorient.index: - raise ValueError('missing index alpha_2') - if np.any(pd.isnull(posorient)): - raise ValueError('posorient must not contain nan') - if rowid is not None: - if not isinstance(rowid, int): - raise TypeError('rowid must be an integer') - if rowid <= 0: - raise ValueError('rowid must be greater zero') - if rowid is np.nan: - raise ValueError('rowid must not be nan') - if (posorient is None) and (rowid is None): - raise Exception('posorient and rowid can not be both None') - if posorient is not None: - rowid = self.get_posid(posorient) - if (posorient is None) and (rowid is None): - Exception('posorient and rowid can not be both None') - if posorient is not None: - rowid = self.get_posid(posorient) - # Read images - tablename = 'image' - self.db_cursor.execute( - """ - SELECT data - FROM {} - WHERE (rowid=?) - """.format(tablename), (rowid,)) - image = self.db_cursor.fetchone()[0] - # Read cmaxminrange - tablename = 'normalisation' - cmaxminrange = pd.read_sql_query( - """ - SELECT * - FROM {} - WHERE (rowid={}) - """.format(tablename, rowid), self.db) - if cmaxminrange.shape[0] != 1: - raise Exception('Error while reading normalisation factors') - cmaxminrange = cmaxminrange.iloc[0, :] - cmaxminrange.name = cmaxminrange.id - cmaxminrange.drop('id') - cmaxminrange = cmaxminrange.astype(float) - toreturn = self.denormalise_image(image, cmaxminrange) - toreturn = toreturn[..., np.newaxis] - return toreturn - - def denormalise_image(self, image, cmaxminrange): - if len(image.shape) != 3: - raise Exception('image should be 3D array') - if image.shape[2] != len(self.channels): - raise Exception('image does not have the required\ - number of channels {}'.format( - len(self.channels))) - if not isinstance(cmaxminrange, pd.Series): - raise Exception('cmaxminrange should be a pandas Series') - if cmaxminrange.empty: - raise Exception('cmaxminrange must not be empty') - for chan_n in self.channels: - if str(chan_n) + '_max' not in cmaxminrange.index: - raise ValueError('cminmax range is missing index ' - + str(chan_n) + '_max') - if str(chan_n) + '_min' not in cmaxminrange.index: - raise ValueError('cminmax range is missing index ' - + str(chan_n) + '_min') - if str(chan_n) + '_range' not in cmaxminrange.index: - raise ValueError('cminmax range is missing index ' - + str(chan_n) + '_range') - if np.any(np.isnan(cmaxminrange.loc[str(chan_n) + '_max'])): - raise ValueError('cmaxminrange contains nans') - if np.any(np.isnan(cmaxminrange.loc[str(chan_n) + '_min'])): - raise ValueError('cmaxminrange contains nans') - if np.any(np.isnan(cmaxminrange.loc[str(chan_n) + '_range'])): - raise ValueError('cmaxminrange contains nans') - denormed_im = np.zeros(image.shape, dtype=np.float) - maxval_nim = np.iinfo(image.dtype).max - # - for chan_i, chan_n in enumerate(self.channels): - cimage = image[:, :, chan_i].astype(float) - cmax = cmaxminrange.loc[str(chan_n) + '_max'] - cmin = cmaxminrange.loc[str(chan_n) + '_min'] - crange = cmaxminrange.loc[str(chan_n) + '_range'] - cimage /= maxval_nim - cimage *= crange - cimage += cmin - denormed_im[:, :, chan_i] = cimage - if np.max(cimage) != cmax: - print(cmaxminrange.name) - # raise ValueError( - # 'denormalisation failed {}!={} - # '.format(np.max(cimage), cmax)) - return denormed_im - - -class DataBaseSave(DataBase): - def __init__(self, filename, channels=['R', 'G', 'B', 'D'], - arr_dtype=np.uint8): - """ - """ - DataBase.__init__(self, filename, channels=channels) - self.arr_dtype = arr_dtype - - def create(self): - """use to decide weather to alter the database or not - return True because we will need - to write on database (Save class)""" - return True - - def write_image(self, posorient, image): - normed_im, cmaxminrange = self.normalise_image(image, self.arr_dtype) - rowid = self.get_posid(posorient) - # Write image - tablename = 'image' - params = dict() - params['rowid'] = rowid - params['data'] = normed_im - self.insert_replace(tablename, params) - # - tablename = 'normalisation' - params = dict() - params['rowid'] = rowid - for chan_n in self.normalisation_columns: - params[chan_n] = cmaxminrange.loc[chan_n] - self.insert_replace(tablename, params) - - def insert_replace(self, tablename, params): - if not isinstance(tablename, str): - raise ValueError('table are named by string') - if not isinstance(params, dict): - raise ValueError('params should be dictionary columns:val') - params_list = list() - columns_str = '' - for key, val in params.items(): - columns_str += key + ',' - params_list.append(val) - columns_str = columns_str[:-1] # remove last comma - if len(params_list) == 0: - warnings.warn('nothing to be done in {}'.format(tablename)) - return - questionsmarks = '?' - for _ in range(1, len(params_list)): - questionsmarks += ',?' - self.db_cursor.execute( - """ - INSERT OR REPLACE - INTO {} ({}) - VALUES ({}) - """.format(tablename, - columns_str, - questionsmarks), - tuple(params_list) - ) - self.db.commit() - - def normalise_image(self, image, dtype=np.uint8): - if not isinstance(image, np.ndarray): - raise TypeError('image must be np.array') - if np.any(np.isnan(image)): - raise ValueError('image must not contain nan values') - if image.shape[0] <= 0 or image.shape[1] <= 0: - raise Exception('image dimensions incorrect') - if image.shape[2] != len(self.channels): - raise Exception('image channels number differs from\ - given channel number') - if not tools.is_numeric_array(image): - raise TypeError('scene is of non numeric type') - normed_im = np.zeros(image.shape, dtype=dtype) - maxval_nim = np.iinfo(normed_im.dtype).max - # - columns = list() - for chan_n in self.channels: - columns.append(str(chan_n) + '_max') - columns.append(str(chan_n) + '_min') - columns.append(str(chan_n) + '_range') - - cmaxminrange = pd.Series(index=columns) - for chan_i, chan_n in enumerate(self.channels): - cimage = image[:, :, chan_i].astype(float) - cmax = cimage.max() - cmin = cimage.min() - crange = cmax - cmin - cimage -= cmin - if np.isclose(crange, 0): - # cimage should be equal to 0 - # so crange is irelevant we can assign it to 1 - crange = 1 - cimage /= crange - cimage *= maxval_nim - cimage = cimage.astype(normed_im.dtype) - normed_im[:, :, chan_i] = cimage - cmaxminrange.loc[str(chan_n) + '_max'] = cmax - cmaxminrange.loc[str(chan_n) + '_min'] = cmin - cmaxminrange.loc[str(chan_n) + '_range'] = crange - return normed_im, cmaxminrange diff --git a/build/lib/navipy/database/tools.py b/build/lib/navipy/database/tools.py deleted file mode 100644 index 2233ea63a9d565fd05d2afc2c393e2b84e63a5c6..0000000000000000000000000000000000000000 --- a/build/lib/navipy/database/tools.py +++ /dev/null @@ -1,21 +0,0 @@ -""" -Some tools to work with databases -""" -from navipy.database import DataBaseLoad, DataBaseSave - - -def copy(filename_in, filename_out): - """ Copy database until in crashed or finish - - :param filename_in: Path to the input database - :param filename_out: Path to the output database - """ - dbin = DataBaseLoad(filename_in) - dbout = DataBaseSave(filename_out) - for i, posorient in dbin.get_posorients().iterrows(): - print(posorient) - try: - image = dbin.read_image(posorient) - except ValueError: - break - dbout.write_image(posorient, image) diff --git a/build/lib/navipy/moving/__init__.py b/build/lib/navipy/moving/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/build/lib/navipy/moving/agent.py b/build/lib/navipy/moving/agent.py deleted file mode 100644 index 3a13cc2eb3dac580baa1c90ff26bcb667a34ba9a..0000000000000000000000000000000000000000 --- a/build/lib/navipy/moving/agent.py +++ /dev/null @@ -1,424 +0,0 @@ -""" - -""" -import numpy as np -import pandas as pd -import networkx as nx -import multiprocessing -from multiprocessing import Queue, JoinableQueue, Process -import inspect -from navipy.database import DataBaseLoad -import navipy.moving.maths as navimomath - - -def defaultcallback(*args, **kwargs): - """default call back""" - 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): - 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): - """ - 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, - 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._posorients = self.db.posorients - self._sensors = self.db.scene - - @AbstractAgent.motion.setter - def motion(self, motion): - self._motion = motion - - @property - def mode_of_motion(self): - """ - """ - toreturn = self._mode_move - toreturn['describe'] = \ - navimomath.mode_moves_supported()[ - self._mode_move['mode']]['describe'] - return toreturn - - @mode_of_motion.setter - def mode_of_motion(self, mode): - """ - - """ - if not isinstance(mode, dict): - raise TypeError('Mode is not a dictionary') - if 'mode' not in mode: - raise KeyError("'mode' is not a key of mode") - if 'param' not in mode: - raise KeyError("'param' is not a key of mode") - if mode['mode'] in navimomath.mode_moves_supported().keys(): - for param in navimomath.mode_moves_supported()[ - mode['mode']]['param']: - if param not in mode['param']: - raise KeyError( - "'{}' is not in mode['param']".format(param)) - 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']) - 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 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: - 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) - 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.move() - next_posorient = self._posorientvel - - self._posorients_queue.task_done() - self._results_queue.put((start_posorient, next_posorient)) - self._posorients_queue.task_done() - print('Process {} done'.format(proc_name)) - - -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): - self.db = DataBaseLoad(database_filename) - # Init the graph - 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) - - @property - def graph(self): - 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.check_graph() - - def build_graph(self, callback_function, - ncpu=5, - timeout=1): - # Build a list of nodes - results_edges = [] - posorients_queue = JoinableQueue() - results_queue = Queue() - for node in self._graph.nodes: - posorients_queue.put(self._graph.nodes[node]['posorient']) - - # Start ndatabase loader - num_agents = ncpu - 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 - w.start() - - # Add a poison pill for each agent - for _ in range(num_agents): - posorients_queue.put(None) - - # Wait for all of the tasks to finish - # posorients_queue.join() - - 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.check_graph() - - def check_graph(self): - self.check_single_target() - - def check_single_target(self): - for node in self._graph.nodes: - # not connected -> loop not ran - for count, _ in enumerate(self._graph.neighbors(node)): - # count == 0 -> connected to one node - # count == 1 -> connected to two nodes - if count > 0: - raise ValueError( - 'Node {} leads to several locations'.format(node)) - - def find_attractors(self): - """Return a list of node going to each attractor in a graph - """ - attractors = list() - for attractor in nx.attracting_components(self._graph): - att = dict() - att['attractor'] = attractor - attractors.append(att) - return attractors - - def find_attractors_sources(self, attractors=None): - """Find all sources going to each attractors - """ - if attractors is None: - attractors = self.find_attractors() - - if isinstance(attractors, list) is False: - raise TypeError('Attractors should be a list of dict') - elif len(attractors) == 0: - raise ValueError('No attractors found') - - # Check attractor - for att in attractors: - keyatt = att.keys() - if 'attractor' not in keyatt: - raise ValueError( - 'Each attractors should contain the key attractor') - - # Calculate connection - for att_i, att in enumerate(attractors): - - # [0] because one node of the attractor is enough - # all other node of the attractor are connected to this one - target = list(att['attractor'])[0] - attractors[att_i]['paths'] = \ - nx.shortest_path(self.graph, target=target) - attractors[att_i]['sources'] = \ - list(attractors[att_i]['paths'].keys()) - return attractors - - def catchment_area(self, attractors=None): - """Return the catchment area for attractors - """ - if attractors is None: - attractors = self.find_attractors_sources() - - if isinstance(attractors, list) is False: - raise TypeError('Attractors should be a list of dict') - elif len(attractors) == 0: - raise ValueError('No attractors found') - - # Check attractor - for att in attractors: - keyatt = att.keys() - if 'sources' not in keyatt: - raise ValueError( - 'Each attractors should contains a list of sources') - - return [len(att['sources']) for att in attractors] - - def reach_goals(self, goals): - """ Return all paths to the 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) - neighbors = tmpgraph.neighbors(target) - return neighbors diff --git a/build/lib/navipy/moving/maths.py b/build/lib/navipy/moving/maths.py deleted file mode 100644 index 630225562d11688a7b17814237fcd3e77a4940fd..0000000000000000000000000000000000000000 --- a/build/lib/navipy/moving/maths.py +++ /dev/null @@ -1,100 +0,0 @@ -""" -Mathematical computation are done in this module. Those involve mostly -geometry, and predefined grids shapes -""" -import numpy as np -import pandas as pd - - -def mode_moves_supported(): - return { - 'on_cubic_grid': { - 'param': - ['grid_spacing'], - 'describe': - "Agent restricted to move on a grid"}, - 'free_run': { - 'param': [], - 'describe': - "Freely moving agent, pos(t+dt)=pos+speed (dt=1)"}} - - -def next_pos(motion_vec, move_mode, move_param=None): - """return the future position knowing speed and current position - - :param motion_vec: the position and speed of the agent -(pandas Series with columns ['x','y','z','dx','dy','dz']) - :param grid_spacing: the spacing between two grid points -(only relevant for regular grids) - :param grid_mode: the type of grid. - - ..todo: add literal include for supported_grid_mode - """ - if isinstance(motion_vec, pd.Series) is False: - raise TypeError('motion vector must be a pandas Series') - if move_mode not in mode_moves_supported().keys(): - raise KeyError( - 'move mode must is not supported {}'.format(move_mode)) - - speed = motion_vec.loc[['dx', 'dy', 'dz']] - if move_mode == 'on_cubic_grid': - # speed in spherical coord - epsilon = np.arctan2(speed.dz, np.sqrt(speed.dx**2 + speed.dy**2)) - phi = np.arctan2(speed.dy, speed.dx) - radius = np.sqrt(np.sum(speed**2)) - if np.isclose(radius, 0): - scaling = 0 - speed = 0 * speed - else: - deltas = pd.Series(index=['dx', 'dy', 'dz']) - deltas.dz = epsilon > (np.pi / 8) - epsilon < (np.pi / 8) - edgecases = np.linspace(-np.pi, np.pi, 9) - case_i = np.argmin(np.abs(phi - edgecases)) - if case_i == 8 or case_i == 0 or case_i == 1 or case_i == 7: - deltas.dx = -1 - elif case_i == 3 or case_i == 4 or case_i == 5: - deltas.dx = 1 - else: - deltas.dx = 0 - - if case_i == 1 or case_i == 2 or case_i == 3: - deltas.dy = -1 - elif case_i == 5 or case_i == 6 or case_i == 7: - deltas.dy = 1 - else: - deltas.dy = 0 - scaling = 1 - speed = move_param['grid_spacing'] * deltas - elif move_mode is 'free_run': - scaling = 1 # <=> dt = 1, user need to scale speed in dt units - else: - raise ValueError('grid_mode is not supported') - toreturn = motion_vec - toreturn.loc[['x', 'y', 'z']] += speed.rename({'dx': 'x', - 'dy': 'y', - 'dz': 'z'}) * scaling - return toreturn - - -def closest_pos(pos, positions): - """Return the closest position from a list of positions - - :param pos: the position to find (a pandas Series with ['x','y','z'] - :param positions: the possible closest positions - (a pandas dataframe with ['x','y','z']) - """ - euclidian_dist = np.sqrt( - (pos.x - positions.x)**2 - + (pos.y - positions.y)**2 - + (pos.z - positions.z)**2) - return positions.loc[euclidian_dist.idxmin(), :] - - -def closest_pos_memory_friendly(pos, database): - """Return the closest position from a list of positions - - :param pos: the position to find (a pandas Series with ['x','y','z'] - :param database: the possible closest positions - (a pandas dataframe with ['x','y','z']) - """ - raise NameError('Not implemated') diff --git a/build/lib/navipy/moving/test_agent.py b/build/lib/navipy/moving/test_agent.py deleted file mode 100644 index 65f2df4aceccb4a63e83b335fe5a542f89c44fc8..0000000000000000000000000000000000000000 --- a/build/lib/navipy/moving/test_agent.py +++ /dev/null @@ -1,234 +0,0 @@ -""" -Test of agent -""" -import numpy as np -import pandas as pd -import networkx as nx -import navipy.moving.agent as naviagent -import navipy.database as navidb -import pkg_resources - -import unittest - - -class TestNavipyMovingAgent(unittest.TestCase): - - def setUp(self): - 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) - - # - # 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) - - # - # GridAgent - # - 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 - self.assertTrue(np.allclose(obtained, - initposorient.loc[obtained.index])) - - # - # GraphAgent - # - - 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.GraphAgent(self.mydb_filename) - graph_nodes = list(agent.graph.nodes) - graph_edges = list() - for gnode in graph_nodes[1:]: - graph_edges.append((gnode, graph_nodes[0])) - - graph = nx.DiGraph() - graph.add_nodes_from(graph_nodes) - graph.add_edges_from(graph_edges) - agent.graph = graph - - graph_edges.append((graph_nodes[2], graph_nodes[1])) - graph = nx.DiGraph() - graph.add_nodes_from(graph_nodes) - graph.add_edges_from(graph_edges) - with self.assertRaises(ValueError): - agent.graph = graph - - def test_catchment_area(self): - """ - 1 Test all node to first - 2 Test 11 nodes to first, 14 to 12th - 3 Two loops attractors - """ - # Test all node to first - agent = naviagent.GraphAgent(self.mydb_filename) - - graph_nodes = list(agent.graph.nodes) - graph_edges = list() - for gnode in graph_nodes[1:]: - graph_edges.append((gnode, graph_nodes[0])) - - graph = nx.DiGraph() - graph.add_nodes_from(graph_nodes) - graph.add_edges_from(graph_edges) - agent.graph = graph - attractors = agent.find_attractors() - self.assertEqual(len(attractors), 1, 'Too many or too few attractors') - attractors = agent.find_attractors_sources(attractors) - catchment_area = agent.catchment_area(attractors) - self.assertEqual(catchment_area, [len(graph_nodes)], - 'Too big or too short catchment area') - - # Test 11 nodes to first, 14 to 12th - graph_edges = list() - for gnode in graph_nodes[1:11]: - graph_edges.append((gnode, graph_nodes[0])) - for gnode in graph_nodes[11:]: - graph_edges.append((gnode, graph_nodes[11])) - - graph = nx.DiGraph() - graph.add_nodes_from(graph_nodes) - graph.add_edges_from(graph_edges) - agent.graph = graph - attractors = agent.find_attractors() - self.assertEqual(len(attractors), 2, 'Too many or too few attractors') - attractors = agent.find_attractors_sources(attractors) - catchment_area = agent.catchment_area(attractors) - self.assertEqual(sorted(catchment_area), [11, 14], - 'Too big or too short catchment area') - - # Two loops attractors - graph_edges = list() - for snode, enode in zip(graph_nodes[:11], - np.roll(graph_nodes[:11], 1)): - graph_edges.append((snode, enode)) - for snode, enode in zip(graph_nodes[11:], - np.roll(graph_nodes[11:], 1)): - graph_edges.append((snode, enode)) - - graph = nx.DiGraph() - graph.add_nodes_from(graph_nodes) - graph.add_edges_from(graph_edges) - agent.graph = graph - attractors = agent.find_attractors() - self.assertEqual(len(attractors), 2, 'Too many or too few attractors') - attractors = agent.find_attractors_sources(attractors) - catchment_area = agent.catchment_area(attractors) - self.assertEqual(sorted(catchment_area), [11, 14], - 'Too big or too short catchment area') - - def test_neighboring_nodes(self): - """ Counting neighnoring nodes for 3 situations - 1. Local maxima - 2. Saddle points - 3. Local minima - """ - agent = naviagent.GraphAgent(self.mydb_filename) - # Local maxima - graph_nodes = list(agent.graph.nodes) - graph_edges = list() - graph_edges.append((graph_nodes[0], - graph_nodes[1])) - - graph = nx.DiGraph() - graph.add_nodes_from(graph_nodes) - graph.add_edges_from(graph_edges) - agent.graph = graph - neighbors = agent.neighboring_nodes(graph_nodes[0]) - expected_nbh = [] - obtained_nbh = [a for a in neighbors] - self.assertEqual(sorted(expected_nbh), - sorted(obtained_nbh), - 'Problem neighbors maxima') - - # Saddle points - graph_edges.append((graph_nodes[1], - graph_nodes[2])) - - graph = nx.DiGraph() - graph.add_nodes_from(graph_nodes) - graph.add_edges_from(graph_edges) - agent.graph = graph - neighbors = agent.neighboring_nodes(graph_nodes[1]) - expected_nbh = [graph_nodes[0]] - obtained_nbh = [a for a in neighbors] - self.assertEqual(sorted(expected_nbh), - sorted(obtained_nbh), - 'Problem neighbors saddle') - - # Local maxima points - graph_edges.append((graph_nodes[3], - graph_nodes[2])) - - graph = nx.DiGraph() - graph.add_nodes_from(graph_nodes) - graph.add_edges_from(graph_edges) - agent.graph = graph - neighbors = agent.neighboring_nodes(graph_nodes[2]) - expected_nbh = [graph_nodes[3], graph_nodes[1]] - obtained_nbh = [a for a in neighbors] - self.assertEqual(sorted(expected_nbh), - sorted(obtained_nbh), - 'Problem neighbors minima') - - -if __name__ == '__main__': - unittest.main() diff --git a/build/lib/navipy/moving/test_maths.py b/build/lib/navipy/moving/test_maths.py deleted file mode 100644 index 0917850568097bd3d22ee8d154a20dfc188cd7ac..0000000000000000000000000000000000000000 --- a/build/lib/navipy/moving/test_maths.py +++ /dev/null @@ -1,108 +0,0 @@ -""" -Test of maths -""" -import numpy as np -import pandas as pd -import navipy.moving.maths as navimaths -import unittest - - -class TestNavipyMovingMaths(unittest.TestCase): - """ A class to test some mathy function of the toolbox - """ - - def test_motion_vec_pandas(self): - """ Test that a TypeError is correctly raised - """ - motion_vec = 'NotPandas' - move_mode = 'on_cubic_grid' - mode_param = dict() - mode_param['grid_spacing'] = 1 - with self.assertRaises(TypeError): - navimaths.next_pos(motion_vec, - move_mode, - move_mode) - - def test_notsupported_mofm(self): - """ Test that a TypeError is correctly raised - """ - motion_vec = pd.Series(data=0, - index=['x', 'y', 'z', 'dx', 'dy', 'dz']) - move_mode = 'NotSupportedMode' - mode_param = dict() - mode_param['grid_spacing'] = 1 - with self.assertRaises(KeyError): - navimaths.next_pos(motion_vec, - move_mode, - move_mode) - - def test_null_velocity(self): - """ Test null velocity - - When the agent has a null velocity, the next postion - should be equal to the current position. Here, we - test this by series equality. - """ - # Test if stay at same position. - motion_vec = pd.Series(data=0, - index=['x', 'y', 'z', 'dx', 'dy', 'dz']) - move_mode = 'on_cubic_grid' - mode_param = dict() - mode_param['grid_spacing'] = 1 - new_pos = navimaths.next_pos(motion_vec, move_mode, mode_param) - self.assertTrue(new_pos.equals(motion_vec), - 'At null velocity the agent should not move') - - def test_closest_cubic(self): - """ Test if the snaping to cubic is correct - - When the agent move on the grid, its position has to be snapped - to the grid position. On a cubic grid, the instability is at - 22.5 degrees modulo 45 degrees. We therefore test the functions - close to each instability. - """ - positions = pd.DataFrame({'x': [0, 0, 0, 1, 1, 1, 2, 2, 2], - 'y': [0, 1, 2, 0, 1, 2, 0, 1, 2], - 'z': [0, 0, 0, 0, 0, 0, 0, 0, 0]}, - dtype=np.float) - move_mode = 'on_cubic_grid' - move_param = dict() - move_param['grid_spacing'] = pd.Series(data=1, - index=['dx', 'dy', 'dz']) - expected_dict = dict() - expected_dict[-22] = 7 # [2,1] - expected_dict[22] = 7 - expected_dict[24] = 8 # [2,2] - expected_dict[67] = 8 - expected_dict[68] = 5 # [1,2] - expected_dict[112] = 5 - expected_dict[113] = 2 # [0,2] - expected_dict[157] = 2 - expected_dict[158] = 1 # [0, 1] - expected_dict[202] = 1 - expected_dict[204] = 0 # [0, 0] - expected_dict[247] = 0 - expected_dict[248] = 3 # [1, 0] - expected_dict[292] = 3 - expected_dict[293] = 6 # [2, 0] - expected_dict[337] = 6 - expected_dict[338] = 7 # equivalent to -22 - - for angle, exp_i in expected_dict.items(): - alpha = np.deg2rad(angle) - motion_vec = pd.Series( - data=[1, 1, 0, - np.cos(alpha), np.sin(alpha), 0], - index=['x', 'y', 'z', - 'dx', 'dy', 'dz'], - dtype=np.float) - newpos = navimaths.next_pos(motion_vec, - move_mode, - move_param) - snappos = navimaths.closest_pos(newpos, positions) - self.assertEqual(snappos.name, exp_i, - 'closest pos is not correctly snapped') - - -if __name__ == '__main__': - unittest.main() diff --git a/build/lib/navipy/processing/__init__.py b/build/lib/navipy/processing/__init__.py deleted file mode 100644 index 180241d76893c51ab29b067d4bf020009eb01fa4..0000000000000000000000000000000000000000 --- a/build/lib/navipy/processing/__init__.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -The scene processing part of the toolbox defines methodes -to transform an image into a place code in the sense -of Basten and Mallot (2010). - -The scene is either - -* a 4d numpy array, used when the image is a equirectangular \ -projection, i.e. a panoramic image. -* a 3d numpy array, used when the viewing direction can not \ -be mapped/projected on a regular image (e.g. insect eye). - -We thus define the following for a scene: - -image based scene (IBS) - A classical image. Each pixel is viewed in a direction - (elevation,azimuth) in a regular manner. - In that case the scene is a 4d numpy array - [elevation-index,azimuth-index,channel-index,1]. - -Omatidium based scene (OBS) - In an ommatidia based scene, the viewing direction - do not need to be regularally spaced. - In that case the scene is a 3d numpy array - [ommatidia-index, channel-index,1]. - -By extension a place-code is either image based or ommatidium based. -The number of dimension of an ib-place-code is always 4, and of an -ob-place-code always 3. - -image based place-code (IBPC) - A place code derived from IBS. Each pixel is viewed in a direction - (elevation,azimuth) in a regular manner. - In that case the scene is a 4d numpy array - [elevation-index,azimuth-index,channel-index,component-index]. - -Omatidium based place-code (OBPC) - A place code derived from OBS, the viewing direction - do not need to be regularally spaced. - In that case the scene is a 3d numpy array - [ommatidia-index, channel-index,component-index]. - - -Abusing the terminology of a place-code, a scene can be a place-code. -Therefore ibs and obs have 4 and 3 dimension, respectively. -""" diff --git a/build/lib/navipy/processing/constants.py b/build/lib/navipy/processing/constants.py deleted file mode 100644 index b2570be93b5c89e30db43b797d4f15476d8a8625..0000000000000000000000000000000000000000 --- a/build/lib/navipy/processing/constants.py +++ /dev/null @@ -1,22 +0,0 @@ -""" -Define some constant -""" - -__spherical_indeces__ = {'elevation': 0, - 'azimuth': 1, - 'radius': 2} -__cartesian_indeces__ = {'x': 0, - 'y': 1, - 'z': 2} -__ibpc_indeces__ = {'elevation': 0, - 'azimuth': 1, - 'channel': 2, - 'component': 3} -__obpc_indeces__ = {'ommatidia': 0, - 'channel': 1, - 'component': 2} -__eye_indeces__ = {'elevation': 0, - 'azimuth': 1, - 'component': 2} -__ommadia_indeces__ = {'ommatidia': 0, - 'component': 1} diff --git a/build/lib/navipy/processing/mcode.py b/build/lib/navipy/processing/mcode.py deleted file mode 100644 index 7eb14619b1754d4ea70ffe5c934e16c034252329..0000000000000000000000000000000000000000 --- a/build/lib/navipy/processing/mcode.py +++ /dev/null @@ -1,15 +0,0 @@ -""" -Motion code -""" -from .tools import check_scene - - -def optic_flow(scene, viewing_directions, - velocity, distance_channel=3): - """ optic flow """ - check_scene(scene) - if distance_channel not in range(4): - raise ValueError('distance channel out of range') - distance = scene[..., distance_channel, 0] - distance += distance - raise NameError('Not Implemented') diff --git a/build/lib/navipy/processing/pcode.py b/build/lib/navipy/processing/pcode.py deleted file mode 100644 index 24bea9c826059f1edfbc21ef6728588c324f87bb..0000000000000000000000000000000000000000 --- a/build/lib/navipy/processing/pcode.py +++ /dev/null @@ -1,193 +0,0 @@ -""" -place code derived from scene -""" -import numpy as np -from scipy.ndimage import maximum_filter, minimum_filter -from .constants import __spherical_indeces__ -from .constants import __ibpc_indeces__ -from .constants import __obpc_indeces__ -from .tools import is_ibpc -from .tools import is_obpc -from .tools import spherical_to_cartesian -from .tools import check_scene -from .tools import check_viewing_direction - - -def skyline(scene): - """Return the average along the elevation of a scene - :param scene: the scenery at a given location (a 4d numpy array) - :returns: the skyline [1,azimuth,channel,1] - :rtype: np.ndarray - - .. literalinclude:: example/processing/skyline.py - :lines: 12-14 - - .. plot:: example/processing/skyline.py - - """ - if not is_ibpc(scene): - raise TypeError('scene should be image based to compute a skyline') - check_scene(scene) - skyline = scene.mean(axis=__ibpc_indeces__['elevation']) - return skyline[np.newaxis, :] - - -def michelson_contrast(scene, size=3): - """Return the michelson constrast - - .. math:: - - \\frac{I_\\text{max}-I_\\text{min}}{I_\\text{max}+I_\\text{min}} - - with :math:`I_\\text{max}` and :math:`I_\\text{min}` representing the \ -highest and lowest luminance in an image region around each pixel. - - :param scene: an image based scene - :param size: the size of the region to calculate the maximum \ -and minimum of the local image intensity - :returns: the michelson-contrast - :rtype: np.ndarray - - .. literalinclude:: example/processing/michelson_contrast.py - :lines: 12-14 - - .. plot:: example/processing/michelson_contrast.py - - """ - check_scene(scene) - if not is_ibpc(scene): - raise TypeError('scene should be image based\ - to compute the michelson constrast') - if not isinstance(size, int): - raise TypeError('size must be integer') - if (size < 2 or size > 5): - raise ValueError('size must be between 2 and 5') - contrast = np.zeros_like(scene) - for channel in range(scene.shape[__ibpc_indeces__['channel']]): - i_max = maximum_filter(scene[..., channel, 0], - size=size, mode='wrap') - i_min = minimum_filter(scene[..., channel, 0], - size=size, mode='wrap') - divider = i_max + i_min - nonzero = divider != 0 - eqzero = divider == 0 - i_min = i_min[nonzero] - i_max = i_max[nonzero] - divider = divider[nonzero] - contrast[nonzero, channel, 0] = (i_max - i_min) / divider - contrast[eqzero, channel, 0] = 0 - return contrast - - -def contrast_weighted_nearness(scene, contrast_size=3, distance_channel=3): - """Return the michelson contrast wheighted nearness - - :param scene: an image based scene - :param contrast_size: the size of the region to calculate the maximum \ -and minimum of the local image intensity in the michelson-contrast. - :param distance_channel: the index of the distance-channel. - - .. literalinclude:: example/processing/contrast_weighted_nearness.py - :lines: 13-15 - - .. plot:: example/processing/contrast_weighted_nearness.py - - """ - check_scene(scene) - if not isinstance(contrast_size, int): - raise TypeError('constrast size must be of type integer') - if not isinstance(distance_channel, int): - raise TypeError('distance channel must be of type integer') - if contrast_size not in range(2, 6): - raise ValueError('contrast size out of range') - if distance_channel not in range(4): - raise ValueError('distance channel out of range') - if not is_ibpc(scene): - raise TypeError('scene should be image based to\ - compute the contrast weighted nearness') - contrast = michelson_contrast(scene, size=contrast_size) - distance = scene[..., distance_channel, 0] - distance = distance[..., np.newaxis, np.newaxis] - distance = np.tile(distance, (1, 1, scene.shape[-2], 1)) - return contrast / distance - - -def pcv(place_code, viewing_directions): - """Place code vectors - - :param place_code: the place code at a given location (e.g. an ibs scene) - :param viewing_directions: viewing direction of each pixel - :returns: the place code vectors in cartesian coordinates - :rtype: (np.ndarray) - - .. literalinclude:: example/processing/pcv.py - :lines: 13-15 - - .. plot:: example/processing/pcv.py - - """ - # print("place code shape",place_code.shape) - if is_ibpc(place_code): - component_dim = __ibpc_indeces__['component'] - channel_dim = __ibpc_indeces__['channel'] - elif is_obpc(place_code): - component_dim = __obpc_indeces__['component'] - channel_dim = __obpc_indeces__['channel'] - else: - raise TypeError('place code should be either an ibpc or obpc') - - check_scene(place_code) - check_viewing_direction(viewing_directions) - if not place_code.shape[0] == viewing_directions.shape[0]: - raise Exception('dimensions of place code and viewing\ - direction do not match') - if not place_code.shape[1] == viewing_directions.shape[1]: - raise Exception('dimensions of place code and viewing\ - direction do not match') - if not isinstance(viewing_directions, np.ndarray): - raise TypeError('viewing_directions should be a numpy array') - if not place_code.shape[component_dim] == 1: - raise Exception('the last dimension ({}) of the place-code\ - should be 1'.format(place_code.shape[component_dim])) - elevation = viewing_directions[..., __spherical_indeces__['elevation']] - azimuth = viewing_directions[..., __spherical_indeces__['azimuth']] - unscaled_lv = spherical_to_cartesian(elevation, azimuth, radius=1) - scaled_lv = np.zeros_like(place_code) - # (3,) -> (1,1,3) or (1,1,1,3) see numpy.tile - scaled_lv = np.tile(scaled_lv, (unscaled_lv.shape[-1],)) - for channel_index in range(0, scaled_lv.shape[channel_dim]): - radius = np.tile(place_code[..., channel_index, 0] - [..., np.newaxis], (scaled_lv.shape[-1],)) - scaled_lv[..., channel_index, :] = unscaled_lv * radius - return scaled_lv - - -def apcv(place_code, viewing_directions): - """Calculate the average scene vector - - :param place_code: the place code at a given location (e.g. an ibs scene) - :param viewing_directions: viewing direction of each pixel - :returns: the average place-code vector - :rtype: (np.ndarray) - - .. literalinclude:: example/processing/apcv.py - :lines: 13-15 - - .. plot:: example/processing/apcv.py - - """ - check_scene(place_code) - check_viewing_direction(viewing_directions) - if not place_code.shape[0] == viewing_directions.shape[0]: - raise Exception('dimensions of place code and viewing\ - direction do not match') - if not place_code.shape[1] == viewing_directions.shape[1]: - raise Exception('dimensions of place code and viewing\ - direction do not match') - scaled_lv = pcv(place_code, viewing_directions) - if is_ibpc(place_code): - return (scaled_lv.sum(axis=0).sum(axis=0))[np.newaxis, np.newaxis, ...] - elif is_obpc(place_code): - return (scaled_lv.sum(axis=0))[np.newaxis, ...] - else: - raise TypeError('place code is neither an ibpc nor obpc') diff --git a/build/lib/navipy/processing/test.py b/build/lib/navipy/processing/test.py deleted file mode 100644 index 1722cae04be61dd17d64ff6ec233d390628f535e..0000000000000000000000000000000000000000 --- a/build/lib/navipy/processing/test.py +++ /dev/null @@ -1,358 +0,0 @@ -import unittest -import sqlite3 -import numpy as np -import pandas as pd -import navipy.database as database -import navipy.processing.pcode as pcode -from navipy.processing.tools import is_numeric_array -import pkg_resources - - -class TestCase(unittest.TestCase): - def setUp(self): - self.mydb_filename = pkg_resources.resource_filename( - 'navipy', 'resources/database.db') - self.mydb = database.DataBaseLoad(self.mydb_filename) - - def test_scene_posorient(self): - conn = sqlite3.connect(self.mydb_filename) - c = conn.cursor() - c.execute(""" SELECT * FROM position_orientation WHERE (rowid=1) """) - rows = c.fetchall()[0] - # 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] - image = self.mydb.scene(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): - image = self.mydb.scene(posorient=posorient2) - - # 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(ValueError): - image = self.mydb.scene(posorient=posorient2) - - # 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(ValueError): - image = self.mydb.scene(posorient=posorient2) - - # 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(TypeError): - image = self.mydb.scene(posorient=posorient2) - - # not working case empty - posorient2 = pd.Series(index=['x', 'y', 'z', - 'alpha_0', 'alpha_1', 'alpha_2']) - - with self.assertRaises(Exception): - image = self.mydb.scene(posorient=posorient2) - - def test_skyline_scene(self): - scene = self.mydb.scene(rowid=1) - 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)) - - # put useless stuff here - with self.assertRaises(ValueError): - pcode.skyline(scene2) - with self.assertRaises(TypeError): - pcode.skyline(scene3) - with self.assertRaises(Exception): - pcode.skyline(scene4) - - # should be working -> check if result(skyline) is correct - for s in [scene]: - skyline = pcode.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): - for rowid in [0, -2]: - with self.assertRaises(ValueError): - # print("rowid",rowid) - self.mydb.scene(rowid=rowid) - with self.assertRaises(TypeError): - self.mydb.scene(rowid='T') - with self.assertRaises(TypeError): - self.mydb.scene(rowid=None) - with self.assertRaises(TypeError): - self.mydb.scene(rowid=np.nan) - with self.assertRaises(TypeError): - self.mydb.scene(rowid=4.5) - - for rowid in [1, 2, 3, 4, 5]: - image = self.mydb.scene(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 = self.mydb.scene(rowid=1) - - # should not be working - for d in ['g', None, np.nan, 8.4]: - with self.assertRaises(TypeError): - pcode.contrast_weighted_nearness(scene, - distance_channel=d) - with self.assertRaises(ValueError): - pcode.contrast_weighted_nearness(scene, - distance_channel=-1) - - # should work - d = 3 - weighted_scene = \ - pcode.contrast_weighted_nearness(scene, - distance_channel=d) - # print("last channel",d) - self.assertTrue(is_numeric_array(weighted_scene)) - self.assertTrue(~np.any(np.isnan(weighted_scene))) - self.assertEqual(weighted_scene.shape, scene.shape) - - def test_contr_weight_scene(self): - scene = self.mydb.scene(rowid=1) - - # working cases - contrast = pcode.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)) - with self.assertRaises(ValueError): - contrast = pcode.contrast_weighted_nearness(scene2) - with self.assertRaises(Exception): - contrast = pcode.contrast_weighted_nearness(scene3) - with self.assertRaises(Exception): - contrast = pcode.contrast_weighted_nearness(scene4) - - def test_contr_weight_contrast(self): - scene = self.mydb.scene(rowid=1) - for size in [9.4, 'g', None, np.nan]: - with self.assertRaises(TypeError): - contrast = pcode.contrast_weighted_nearness( - scene, contrast_size=size) - for size in [8, 1, 0, -4]: - with self.assertRaises(ValueError): - contrast = \ - pcode.contrast_weighted_nearness( - scene, contrast_size=size) - - # working cases - for size in [2, 3, 4, 5]: - contrast = pcode.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.assertEqual(contrast.shape[3], 1) - self.assertEqual(contrast.shape[2], scene.shape[2]) - self.assertEqual(contrast.shape[0], scene.shape[0]) - self.assertEqual(contrast.shape[1], scene.shape[1]) - - def test_pcv(self): - # working case - rowid = 1 - my_scene = self.mydb.scene(rowid=rowid) - directions = self.mydb.viewing_directions - my_pcv = pcode.pcv(my_scene, directions) - 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): - my_pcv = pcode.pcv(my_scene, testdirection) - - # not working cases wrong last dimension - testdirection = np.zeros((180, 360, 1)) - with self.assertRaises(Exception): - my_pcv = pcode.pcv(my_scene, testdirection) - - # not working cases too many dimensions - testdirection = np.zeros((180, 360, 2, 4)) - with self.assertRaises(Exception): - my_pcv = pcode.pcv(my_scene, testdirection) - - # not working cases empty - testdirection = np.zeros(()) - with self.assertRaises(Exception): - my_pcv = pcode.pcv(my_scene, testdirection) - - # not working cases nans - testdirection = np.zeros((180, 360, 2, 4)) - testdirection[2, 3, 0] = np.nan - with self.assertRaises(ValueError): - my_pcv = pcode.pcv(my_scene, testdirection) - - def test_apcv(self): - # working case - rowid = 1 - my_scene = self.mydb.scene(rowid=rowid) - # print("scene shape",my_scene.shape) - directions = self.mydb.viewing_directions - my_pcv = pcode.apcv(my_scene, directions) - - 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): - my_pcv = pcode.apcv(my_scene, testdirection) - - # not working cases wrong last dimension - testdirection = np.zeros((180, 360, 1)) - with self.assertRaises(Exception): - my_pcv = pcode.apcv(my_scene, testdirection) - - # not working cases too many dimensions - testdirection = np.zeros((180, 360, 2, 4)) - with self.assertRaises(Exception): - my_pcv = pcode.apcv(my_scene, testdirection) - - # not working cases empty - testdirection = np.zeros(()) - with self.assertRaises(Exception): - my_pcv = pcode.apcv(my_scene, testdirection) - - # not working cases nans - testdirection = np.zeros((180, 360, 2, 4)) - testdirection[2, 3, 0] = np.nan - with self.assertRaises(ValueError): - my_pcv = pcode.apcv(my_scene, testdirection) - - def test_size(self): - # not working cases: - scene = self.mydb.scene(rowid=1) - - for size in [8, 1, 0, -4]: - with self.assertRaises(ValueError): - contrast = pcode.michelson_contrast( - scene, size=size) - for size in [9.4, 'g', None, np.nan]: - with self.assertRaises(TypeError): - contrast = pcode.michelson_contrast( - scene, size=size) - - # working cases - for size in [2, 3, 4, 5]: - contrast = pcode.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 = self.mydb.scene(rowid=1) - - # working cases - contrast = pcode.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): - contrast = pcode.michelson_contrast(s,) - - -if __name__ == '__main__': - unittest.main() diff --git a/build/lib/navipy/processing/tools.py b/build/lib/navipy/processing/tools.py deleted file mode 100644 index 42e0cc8de33ee128ce9353d095412b1f32fbc87a..0000000000000000000000000000000000000000 --- a/build/lib/navipy/processing/tools.py +++ /dev/null @@ -1,165 +0,0 @@ -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 - - -def check_scene(scene): - if is_ibpc(scene): - # print("normal") - if not is_numeric_array(scene): - raise TypeError('scene is of non numeric type') - if not ~np.any(np.isnan(scene)): - raise ValueError('scene contains nans') - if not len(scene.shape) == 4: - raise Exception('scene has wrong shape, must have 4 dimensions') - if not (scene.shape[1] > 0): - raise Exception('scenes first dimension is empty') - if not (scene.shape[0] > 0): - raise Exception('scenes second dimension is empty') - if not (scene.shape[2] == 4): - raise Exception('3rd dimension of scene must be four') - if not (scene.shape[3] == 1): - raise Exception('4rd dimension of scene must be one') - # assert ~(np.any(np.isNone(scene))) - return True - - elif is_obpc(scene): - if not is_numeric_array(scene): - raise TypeError('scene is of non numeric type') - if not ~np.any(np.isnan(scene)): - raise ValueError('scene contains nans') - if not len(scene.shape) == 3: - raise Exception('scene has wrong shape, must have 4 dimensions') - if not ~(scene.shape[1] <= 0): - raise Exception('scenes first dimension is empty') - if not ~(scene.shape[0] <= 0): - raise Exception('scenes second dimension is empty') - if not (scene.shape[2] == 4): - raise Exception('3rd dimension of scene must be four') - # assert ~(np.any(np.isNone(scene))) - return True - - -def check_viewing_direction(viewing_direction): - if not is_numeric_array(viewing_direction): - raise TypeError('viewing direction is of non numeric type') - if not ~np.any(np.isnan(viewing_direction)): - raise ValueError('viewing direction contains nans') - if len(viewing_direction.shape) < 3: - raise Exception('viewing direction must have at least 3 dimensions') - if not (viewing_direction.shape[1] > 0): - raise Exception('viewing direction has empty second dimension') - if not (viewing_direction.shape[0] > 0): - raise Exception('viewing direction has empty first dimension') - if not (viewing_direction.shape[-1] == 2): - raise Exception(' last dimension of viewing direction must equal 2') - return True - - -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. - - :param array : `numpy.ndarray`-like The array to check. - :returns: True if it is a recognized numerical and False \ - if object or string. - :rtype:bool - """ - 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 is_ibpc(place_code): - """Test if a place code is image based - - :param place_code: a place-code - :returns: True if image based place-code - :rtype: bool - - """ - toreturn = isinstance(place_code, np.ndarray) - toreturn = toreturn and (len(place_code.shape) == - len(__ibpc_indeces__)) - return toreturn - - -def is_obpc(place_code): - """Test if a place code is ommatidia based - - :param place_code: a place-code - :returns: True if ommatidia based place-code - :rtype: bool - - """ - toreturn = isinstance(place_code, np.ndarray) - toreturn = toreturn and (len(place_code.shape) == - len(__obpc_indeces__)) - return toreturn - - -def ibs_to_obs(scene, eye_map): - """Convert an image based scene to an ommatidium based scene. - - :param scene: The scene to be converted - :param eye_map: The eye_map to use - :returns: (obs_scene,ommatidia_map) - :rtype: (np.ndarray,np.ndarray) - """ - 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(__eye_indeces__),\ - 'eye_map should have {} dimensions to be an ibs scene'.format( - len(__eye_indeces__)) - for index_name in ['elevation', 'azimuth']: - 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[__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[__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) - - -def cartesian_to_spherical(x, y, z): - radius = np.sqrt(x**2 + y**2 + z**2) - elevation = np.arctan2(z, np.sqrt(x**2 + y**2)) - azimuth = np.arctan2(y, x) - spherical = np.zeros_like(x) - spherical = np.tile(spherical[..., np.newaxis], (3,)) - 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[..., __cartesian_indeces__['x']] = np.cos( - elevation) * np.cos(azimuth) - cartesian[..., __cartesian_indeces__['y']] = np.cos( - elevation) * np.sin(azimuth) - cartesian[..., __cartesian_indeces__['z']] = np.sin(elevation) - cartesian = radius * cartesian - return cartesian diff --git a/build/lib/navipy/python_test.py b/build/lib/navipy/python_test.py deleted file mode 100644 index 9ee1cb9f6b284340ad3570cdfb2a6a679877ce15..0000000000000000000000000000000000000000 --- a/build/lib/navipy/python_test.py +++ /dev/null @@ -1,5 +0,0 @@ -""" - -""" -x = 0 -print('blabla') diff --git a/build/lib/navipy/rendering/__init__.py b/build/lib/navipy/rendering/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/build/lib/navipy/rendering/bee_sampling.py b/build/lib/navipy/rendering/bee_sampling.py deleted file mode 100644 index 817ae03ec11cb75bbb7208238190feb7800023d7..0000000000000000000000000000000000000000 --- a/build/lib/navipy/rendering/bee_sampling.py +++ /dev/null @@ -1,167 +0,0 @@ -""" -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, np.ndarray) or isinstance(x, list)): - raise TypeError('x must be list or np.array') - if not (isinstance(y, np.ndarray) or isinstance(y, list)): - raise TypeError('y must be list or np.array') - if not (isinstance(z, np.ndarray) or isinstance(z, list)): - raise TypeError('z must be list or np.array') - if not (isinstance(alpha1, np.ndarray) or - isinstance(alpha1, list)): - raise TypeError('alpha1 must be list or np.array') - if not (isinstance(alpha2, np.ndarray) or - isinstance(alpha2, list)): - raise TypeError('alpha2 must be list or np.array') - if not (isinstance(alpha3, np.ndarray) or - isinstance(alpha3, list)): - raise TypeError('alpha3 must be list or np.array') - [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() - - def set_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.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.distance - distance[distance > self.world_dim] = self.world_dim - image = self.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.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.cycle_samples(samples=5) - with tempfile.TemporaryDirectory() as folder: - bee_samp.render(folder + '/database.db') diff --git a/build/lib/navipy/rendering/cyber_bee.py b/build/lib/navipy/rendering/cyber_bee.py deleted file mode 100644 index 530a11b38698a1608a72c506c7e711aeed2ca974..0000000000000000000000000000000000000000 --- a/build/lib/navipy/rendering/cyber_bee.py +++ /dev/null @@ -1,408 +0,0 @@ -""" - 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 -import pandas as pd - - -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.camera_rotation_mode = 'XYZ' - self.camera_fov = [[-90, 90], [-180, 180]] - self.camera_gaussian_width = 1.5 - self.camera_resolution = [360, 180] - self.cycle_samples = 30 - # 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, resolution=[[-90, 90], [-180, 180]]): - """change the field of view of the panoramic camera - - :param resolution: [[minimum latitude, maximum latitude], - [minimum longitude, maximum longitude]] - (in deg) - :type latmin: 2x2 float array or list - - ..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(resolution, tuple) or - isinstance(resolution, list) or - isinstance(resolution, np.ndarray)): - raise TypeError('resolution must be list, array, or tuple') - 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( - resolution[0][0]) - self.camera.data.cycles.latitude_max = np.deg2rad( - resolution[0][1]) - self.camera.data.cycles.longitude_min = np.deg2rad( - resolution[1][0]) - self.camera.data.cycles.longitude_max = np.deg2rad( - resolution[1][1]) - - @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=[360, 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, list) or - isinstance(resolution, np.ndarray)): - raise TypeError('resolution list or array') - bpy.context.scene.render.resolution_x = resolution[0] - bpy.context.scene.render.resolution_y = resolution[1] - 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 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 - """ - print(posorient) - if (isinstance(posorient, np.ndarray) or - isinstance(posorient, list)): - - if len(posorient) != 6: - raise Exception('posorient should be a 1x6 double array') - self.camera.location = posorient[:3] - self.camera.rotation_euler = posorient[3:] - elif isinstance(posorient, pd.Series): - self.camera.location = posorient.loc[['x', 'y', 'z']].values - self.camera.rotation_euler = \ - posorient.loc[['alpha_0', 'alpha_1', 'alpha_2']].values - else: - raise TypeError( - 'posorient must be of type array, list, or pandas Series') - # 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.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.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 - - 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 - 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.image - # Test distance - distance = mybee.distance - print('Cyberbee OK') diff --git a/build/lib/navipy/resources/database.db b/build/lib/navipy/resources/database.db deleted file mode 100644 index 450fe54728c12e42263541e1541b71d2e9e2a815..0000000000000000000000000000000000000000 Binary files a/build/lib/navipy/resources/database.db and /dev/null differ diff --git a/dist/navipy-0.1-py3.5.egg b/dist/navipy-0.1-py3.5.egg deleted file mode 100644 index a3b260f5a72083304e1e67d1cfb94960293f27ce..0000000000000000000000000000000000000000 Binary files a/dist/navipy-0.1-py3.5.egg and /dev/null differ diff --git a/navipy.egg-info/PKG-INFO b/navipy.egg-info/PKG-INFO deleted file mode 100644 index fd0fcd430303ba44bb65b7ecc5a9c0ec68094e90..0000000000000000000000000000000000000000 --- a/navipy.egg-info/PKG-INFO +++ /dev/null @@ -1,15 +0,0 @@ -Metadata-Version: 1.1 -Name: navipy -Version: 0.1 -Summary: Insect Navigation Toolbox -Home-page: UNKNOWN -Author: Olivier J.N. Bertrand -Author-email: olivier.bertrand@uni-bielefeld.de -License: UNKNOWN -Description-Content-Type: UNKNOWN -Description: UNKNOWN -Platform: UNKNOWN -Requires: numpy -Requires: pandas -Requires: matplotlib -Requires: scipy diff --git a/navipy.egg-info/SOURCES.txt b/navipy.egg-info/SOURCES.txt deleted file mode 100644 index fac8f815f529879e696ebbd5fe66152fd9f0625e..0000000000000000000000000000000000000000 --- a/navipy.egg-info/SOURCES.txt +++ /dev/null @@ -1,28 +0,0 @@ -README.md -setup.py -navipy/__init__.py -navipy/python_test.py -navipy.egg-info/PKG-INFO -navipy.egg-info/SOURCES.txt -navipy.egg-info/dependency_links.txt -navipy.egg-info/requires.txt -navipy.egg-info/top_level.txt -navipy/comparing/__init__.py -navipy/comparing/test.py -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 -navipy/processing/__init__.py -navipy/processing/constants.py -navipy/processing/mcode.py -navipy/processing/pcode.py -navipy/processing/test.py -navipy/processing/tools.py -navipy/rendering/__init__.py -navipy/rendering/bee_sampling.py -navipy/rendering/cyber_bee.py \ No newline at end of file diff --git a/navipy.egg-info/dependency_links.txt b/navipy.egg-info/dependency_links.txt deleted file mode 100644 index 8b137891791fe96927ad78e64b0aad7bded08bdc..0000000000000000000000000000000000000000 --- a/navipy.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/navipy.egg-info/requires.txt b/navipy.egg-info/requires.txt deleted file mode 100644 index 6e27488c3669fe064238d31c089c1a764ffe3239..0000000000000000000000000000000000000000 --- a/navipy.egg-info/requires.txt +++ /dev/null @@ -1,4 +0,0 @@ -numpy -pandas -matplotlib -scipy diff --git a/navipy.egg-info/top_level.txt b/navipy.egg-info/top_level.txt deleted file mode 100644 index c5f564d1a1a80b6f4fdf3a52d9be71e527d727f9..0000000000000000000000000000000000000000 --- a/navipy.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -navipy