From 138ec87cb707650cfebb0fdcbd45578abb386029 Mon Sep 17 00:00:00 2001
From: amitjans <amitjans@ethz.ch>
Date: Tue, 29 Jun 2021 11:52:21 +0200
Subject: [PATCH] Change memory. Now using most voted value along the alst
 NUM_ITERATION values

---
 tools.py | 158 +++++++++++++++++++++++++++++--------------------------
 1 file changed, 84 insertions(+), 74 deletions(-)

diff --git a/tools.py b/tools.py
index b10883b..73ba1c0 100644
--- a/tools.py
+++ b/tools.py
@@ -52,7 +52,6 @@ class Main:
 
         # Define class attributes
         self.init_time = time.time()
-        self.num = 0
         self.output = {}
 
     def start_thread(self):
@@ -102,7 +101,6 @@ class Main:
 
             # Save variables in self.memory
             self._save_in_memory(output)
-            self.num += 1
 
             # Delete unnecessary variables for html and put output in queue
             del output['num_ions']
@@ -143,11 +141,6 @@ class Main:
         num_dim_ions = np.sum(coord[:, 2] == 1).item()
         num_dark_ions = np.sum(coord[:, 2] == 2).item()
 
-        # Reset self.memory every NUM_ITERATIONS
-        if self.num > settings.NUM_ITERATIONS:
-            self.memory.reset_memory(coord)
-            self.num = 0
-
         return {
             'image': image,
             'coord': coord,
@@ -206,6 +199,8 @@ class Memory:
     Stores values in memory and counts how many times each value was stored.
     """
     def __init__(self):
+        self.i = 0
+        self.max_idx = 0
         self.memory = []
         self.count = []
 
@@ -216,7 +211,8 @@ class Memory:
         # If memory is empty, append new value
         if len(self.memory) == 0:
             self.memory.append(value)
-            self.count.append(1)
+            self.count.append([0])
+            self.i += 1
             return
 
         # If value has the same ion types as any element in memory, append abs(value - element)
@@ -232,14 +228,37 @@ class Memory:
         # If sum(abs(value - element)) is less than 10, consider as same distribution
         try:
             if 0 <= diff[:, 1].min() < 30:
-                self.memory[diff[np.argmin(diff[:, 1])][0]] = value
-                self.count[diff[np.argmin(diff[:, 1])][0]] += 1
+                idx = diff[np.argmin(diff[:, 1])][0]
+                self.memory[idx] = value
+                self.count[idx].append(self.i)
+                self.i += 1
             else:
                 self.memory.append(value)
-                self.count.append(1)
+                self.count.append([self.i])
+                self.i += 1
         except IndexError:
             self.memory.append(value)
-            self.count.append(1)
+            self.count.append([self.i])
+            self.i += 1
+
+        # When we reach NUM_ITERATIONS, we remove the 0 value and
+        # substract 1 for each value inside count list.
+
+        if self.i == settings.NUM_ITERATIONS:
+            list_len = []
+            count_copy = self.count.copy()
+            for i, val in enumerate(count_copy):
+                if 0 in val:
+                    val.remove(0)
+                if len(val) == 0:
+                    del self.memory[i]
+                    del self.count[i]
+                else:
+                    val = [val[i] - 1 for i in range(len(val))]
+                    self.count[i] = val
+                    list_len.append(len(val))
+            self.i -= 1
+            self.max_idx = np.argmax(list_len)
 
 
     def get_value(self):
@@ -248,22 +267,11 @@ class Memory:
         where this value was stored.
         """
         try:
-            max_idx = np.argmax(self.count)
-            max_value = self.memory[max_idx]
-        except ValueError:
-            max_idx = 0
+            max_value = self.memory[self.max_idx]
+        except IndexError:
             max_value = None
 
-        return max_value, max_idx
-
-    def reset_memory(self, value):
-        """
-        Delete memory and add new value.
-        """
-        del self.memory
-        del self.count
-        self.memory = [value]
-        self.count = [0]
+        return max_value, self.max_idx
 
 
 class MovingAverage:
@@ -437,6 +445,7 @@ def ion_roundness(image, center):
     image_copy = image_copy[c_x - 25 : c_x + 25, c_y - 25 : c_y + 25]  # crop the image
 
     # get coordinates of ion pixels
+    # TODO: fix this (sometimes the image_copy is empty)
     pca_input = np.swapaxes(np.stack(np.where(image_copy > image_copy.max()*0.5)), 0, 1)
     if len(pca_input) > 1:
         pca = PCA(n_components=2)  # compute PCA
@@ -538,54 +547,55 @@ def dark_ions(image, coord, dist_factor):
     mask_dist = (pd.read_csv("data/mask_dist.csv", index_col=0).to_numpy()*
     dist_factor)[low_idx : high_idx, :]
 
-    # Compute min error between every value of the mask and every value of the measured distances
-    comparison = np.full((3, mask.shape[0], mask.shape[1]), 100000, dtype=float)
-    for i in range(mask.shape[0]):
-        dist = x_dist.copy()
-        for j in range(mask.shape[1]):
-            val = mask[i, j]
-            val_dist = mask_dist[i, j]
-            if val >= 0:
-                comparison[:2, i, j] = np.min((x_pos - val)**2, axis=1)
-            if val_dist >= 0:
-                diff = (dist - val_dist)**2
-                comparison[2, i, j] = np.min(diff)
-                dist[np.argmin(diff)] = 0
-
-    comp = np.sort(comparison, axis=2)[:, :, :len(x_pos[1])]
-    # Set to 0 the last column of the comparison of the distances (they have 1 value less)
-    # This way the last column won't affect the loss
-    comp[2, :, -1] = 0
-    loss = np.sum(comp, axis=2)/len(x_pos)
-
-    idx = np.where(loss == np.min(loss))
-
-    if idx[0][0] == 1:  # if using "inverted positions", transform back
-        new_x_pos = np.abs(mask[idx[1][0], :][mask[idx[1][0], :] >= 0] - coord[-1, 1])
-    else:
-        new_x_pos = mask[idx[1][0], :][mask[idx[1][0], :] >= 0] + coord[0, 1]
-
-    diff_n = len(new_x_pos) - len(x_pos[0])
-    for i in range(diff_n):
-        mask2 = comparison[idx[0][0], idx[1][0], :] < 100000
-        idx2 = np.argsort(comparison[idx[0][0], idx[1][0], :][mask2])[-(diff_n - i)]
-        if idx2 != 0:
-            # If we are using the distances' loss, then we have to add 1 to the index
-            if idx[0][0] == 2:
-                idx2 += 1
-            coord = np.append(coord, np.array([[np.mean(coord[:, 0]),
-            new_x_pos[idx2], 2]]), axis=0)
-
-        elif idx2 == 0 and idx[0][0] == 2:
-            coord = np.append(coord, np.array([[np.mean(coord[:, 0]), new_x_pos[0] -
-                                                    comparison[2, idx[1][0], 0], 2]]), axis=0)
-
-    coord = coord[coord[:, 1].argsort()].astype(int)
-    coord = coord[coord[:, 1] < image.shape[1]]  # remove points outside the image
-
-    # if loss.min() > 20:
-    #     warnings.warn("Loss is too high... "
-    #     "Try calculating a new factor value using calibrate() function.")
+    if len(mask) > 0:
+        # Compute min error between every value of the mask and every value of the measured distances
+        comparison = np.full((3, mask.shape[0], mask.shape[1]), 100000, dtype=float)
+        for i in range(mask.shape[0]):
+            dist = x_dist.copy()
+            for j in range(mask.shape[1]):
+                val = mask[i, j]
+                val_dist = mask_dist[i, j]
+                if val >= 0:
+                    comparison[:2, i, j] = np.min((x_pos - val)**2, axis=1)
+                if val_dist >= 0:
+                    diff = (dist - val_dist)**2
+                    comparison[2, i, j] = np.min(diff)
+                    dist[np.argmin(diff)] = 0
+
+        comp = np.sort(comparison, axis=2)[:, :, :len(x_pos[1])]
+        # Set to 0 the last column of the comparison of the distances (they have 1 value less)
+        # This way the last column won't affect the loss
+        comp[2, :, -1] = 0
+        loss = np.sum(comp, axis=2)/len(x_pos)
+
+        idx = np.where(loss == np.min(loss))
+
+        if idx[0][0] == 1:  # if using "inverted positions", transform back
+            new_x_pos = np.abs(mask[idx[1][0], :][mask[idx[1][0], :] >= 0] - coord[-1, 1])
+        else:
+            new_x_pos = mask[idx[1][0], :][mask[idx[1][0], :] >= 0] + coord[0, 1]
+
+        diff_n = len(new_x_pos) - len(x_pos[0])
+        for i in range(diff_n):
+            mask2 = comparison[idx[0][0], idx[1][0], :] < 100000
+            idx2 = np.argsort(comparison[idx[0][0], idx[1][0], :][mask2])[-(diff_n - i)]
+            if idx2 != 0:
+                # If we are using the distances' loss, then we have to add 1 to the index
+                if idx[0][0] == 2:
+                    idx2 += 1
+                coord = np.append(coord, np.array([[np.mean(coord[:, 0]),
+                new_x_pos[idx2], 2]]), axis=0)
+
+            elif idx2 == 0 and idx[0][0] == 2:
+                coord = np.append(coord, np.array([[np.mean(coord[:, 0]), new_x_pos[0] -
+                                                        comparison[2, idx[1][0], 0], 2]]), axis=0)
+
+        coord = coord[coord[:, 1].argsort()].astype(int)
+        coord = coord[coord[:, 1] < image.shape[1]]  # remove points outside the image
+        # TODO: uncomment this!
+        # if loss.min() > 20:
+        #     warnings.warn("Loss is too high... "
+        #     "Try calculating a new factor value using calibrate() function.")
 
     return coord
 
-- 
GitLab