From 21c0c22651239a90bae4f42d2ed885b0f97b5c14 Mon Sep 17 00:00:00 2001
From: "Olivier J.N. Bertrand" <olivier.bertrand@uni-bielefeld.de>
Date: Mon, 18 Jun 2018 19:31:53 +0200
Subject: [PATCH] Add Image rotation difference function as in Zeil 2004

---
 navipy/comparing/__init__.py |  3 ++
 navipy/models/hafner_2000.py |  6 +--
 navipy/models/irdf_2003.py   | 79 ++++++++++++++++++++++++++++++++++++
 3 files changed, 85 insertions(+), 3 deletions(-)
 create mode 100644 navipy/models/irdf_2003.py

diff --git a/navipy/comparing/__init__.py b/navipy/comparing/__init__.py
index a918ca3..0899ac2 100644
--- a/navipy/comparing/__init__.py
+++ b/navipy/comparing/__init__.py
@@ -80,6 +80,9 @@ the current and memorised place code.
                        should be image based')
     check_scene(current)
     check_scene(memory)
+    # ridf is a NxM matrix,
+    # because one value per azimuth (N) and n values per channel
+    # (M)
     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)
diff --git a/navipy/models/hafner_2000.py b/navipy/models/hafner_2000.py
index 3c94b92..d2c3c92 100644
--- a/navipy/models/hafner_2000.py
+++ b/navipy/models/hafner_2000.py
@@ -18,12 +18,12 @@ def processing(scene, viewing_directions, channel):
     * Müller et al. 2018
     * Basten and Mallot 2010
     refer as COMANV in :
-    * Hafter 2000,
+    * Hafner 2000,
     * Bertrand 2015
     center of mass of average nearness vector
     """
     # Invert distance to nearness
-    scene[..., 3, :] = 1/scene[..., 3, :]
+    scene[..., 3, :] = 1 / scene[..., 3, :]
     # Calculate the skyline
     scene = skyline(scene)
     # skyline viewing direction
@@ -38,7 +38,7 @@ def comparing(current, memory):
 
     homing vector  = current vector - memory vector
     """
-    return current-memory
+    return current - memory
 
 
 class ASVBrain(Brain):
diff --git a/navipy/models/irdf_2003.py b/navipy/models/irdf_2003.py
new file mode 100644
index 0000000..a7c0918
--- /dev/null
+++ b/navipy/models/irdf_2003.py
@@ -0,0 +1,79 @@
+from navipy import Brain
+from navipy.comparing import rot_imagediff
+import pandas as pd
+import numpy as np
+from navipy.scene import __spherical_indeces__
+from navipy.maths.coordinates import spherical_to_cartesian
+# 0) Define a class heriting from Brain
+
+
+def processing(scene, channel):
+    """ Return the image difference
+
+    * inverse of distance (i.e. distance -> nearness)
+    """
+    # Invert distance to nearness
+    scene[..., 3, :] = 1 / scene[..., 3, :]
+    return scene[..., channel, :]
+
+
+def comparing(current, memory, viewing_directions):
+    """ Calculate homing vector with irdf
+
+    irdf: Image rotation difference function
+    The image difference is root mean square
+
+    Used in:
+    * Zeil, J., Hofmann, M., & Chahl, J. (2003). \
+      Catchment Areas of Panoramic Snapshots in Outdoor Scenes.
+    * Baddeley, B., Graham, P., Husbands, P., & Philippides, A. (2012).\
+      A Model of Ant Route Navigation Driven by Scene Familiarity.
+    * Ardin, P., Peng, F., Mangan, M., Lagogiannis, K., & Webb, B. (2016).\
+      Using an Insect Mushroom Body Circuit to Encode Route \
+      Memory in Complex Natural Environments.
+    """
+    if (current.shape[2] != 1) or (memory.shape[2] != 1):
+        msg = 'Current view {} and the memory {} \n'
+        msg += 'should be a NxMx1x1 matrix'
+        msg = msg.format(current.shape, memory.shape)
+        raise NameError(msg)
+    irdf = rot_imagediff(current, memory)
+    # [..., 0] because processing
+    # select one channel, and therefore
+    # irdf should is only a Nx1 matrix
+    idx = np.argmin(irdf[..., 0])
+    minval = np.min(irdf[..., 0])
+    direction = viewing_directions[idx,
+                                   __spherical_indeces__['azimuth']]
+    homing_vect = spherical_to_cartesian(elevation=0,
+                                         azimuth=direction,
+                                         radius=minval)
+    return homing_vect
+
+
+class IRDFBrain(Brain):
+    def __init__(self,
+                 memory,
+                 renderer=None,
+                 channel=0):
+        Brain.__init__(self, renderer=renderer)
+        # Init memory
+        self.channel = channel
+        self.memory = memory
+
+    def velocity(self):
+        index = self.posorient.index
+        convention = index.levels[0][-1]
+        current = processing(self.vision.scene,
+                             self.channel)
+        homing_vector = comparing(current,
+                                  self.memory,
+                                  self.vision.viewing_directions,
+                                  )
+        homing_vector = np.squeeze(homing_vector)
+        indeces = [('location', 'dx'), ('location', 'dy'),
+                   ('location', 'dz'), (convention, 'dalpha_0'),
+                   (convention, 'dalpha_1'), (convention, 'dalpha_2')]
+        velocity = pd.Series(data=0, index=pd.MultiIndex.from_tuples(indeces))
+        velocity.loc['location'] = homing_vector
+        return velocity
-- 
GitLab