HapticAnalyzer.py 5.06 KB
Newer Older
Hurstel's avatar
Hurstel committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
'''
Created on 28 august 2014

@author: hurstel
'''
from DataAnalyzer import DataAnalyzer
import bisect

class HapticAnalyzer(DataAnalyzer):
    """
    DataAnalyzer class specialisation
    for processing data looking for
    haptic 'spike' signals.
    """   
    def __init__(self, data):
        """
        Constructor - do not call directly
        """
        DataAnalyzer.__init__(self, data)
        
    def _getLocalGrowth(self, xstart):
        """
        Private method - do not call directly
        ----DEPRECATED---
        do not use
        """
        l = len(self._data)
        xcur = xstart
        if (xstart == (l - 1)):
            return None
        
        try:
            ystart = self._data[xstart]
        except IndexError:
            return None
        
        xcur += 1
        ycur = self._data[xcur]
        print 'ycur=%s ystart=%s' % (ycur, ystart)
        growth = ycur - ystart  # 0: constant; +:increase; -:decrease
        
        def __change(g, y0, y1):
            if ((g == 0 and y1 == y0) or (g >= 0 and y1 > y0) or (g <= 0 and y1 < y0)):
                return False
            else:
                return True
            
        while (xcur < (l - 1)):
            xnext = xcur + 1
            ynext = self._data[xnext]
            b = __change(growth, ycur, ynext);
            if b:
                return ((ycur - ystart), xstart, xcur)
            growth = ynext - ycur
            xcur = xnext
            ycur = ynext
            
            
        return ((ycur - ystart), xstart, xcur)
    
    def analyze(self, threshold=0.6):
        """
        DataAnalyzer.analyse() method overload
        --- Deprecated, do not use ---
        """
        lgList = []
        xcur = 0
        
        lg = self._getLocalGrowth(xcur)
        while (lg is not None) and (xcur < len(self._data)):
            try:
                g = lg[0] / float(lg[2] - lg[1])
            except ZeroDivisionError:
                xcur += 1
                lg = self._getLocalGrowth(xcur)
                print 'huh'
                continue
            cg = (g, xcur)
            bisect.insort(lgList, cg)
            xcur = lg[2] + 1
            print 'lg[2]+1= %d' % (lg[2] + 1)
            lg = self._getLocalGrowth(xcur)
            print 'newt lg none? %s with xcur= %s' % ((lg is None), xcur)
        
        lgList[:] = [v for v in lgList if v[0] > 0]
        print 'xcur %d' % xcur
        xgend = len(lgList) - 1
        tail = lgList[-1][0]
        while(xgend >= 1):
            if (lgList[xgend - 1][0] < (threshold * (tail))):
                break
            xgend -= 1
        
        return lgList[xgend:]

        
    def test_ab_value_find(self):
        """
        Test function
        Do not use
        """
        i = 0
        for d in self._data:
            if (d > (self.median + (3.0 * self.std_dev))):
                print 'here: data[%d]= %d' % (i, d)
            i += 1
        
    def findCluster(self, threshold=1500):
        """
        Public method
        DataAnalyzer.findCluster() method overload
        Locate the 'haptic spike' clusters among the dataset
        (_data).
        Returns the list of the detect clusters of interest.
        (Clusters are formed by 2-tuples: (a,b) with a the
         start occurrence and b the end occurrence)
         ----IMPORTANT----
         The compute method must be called before using this method,
         otherwise an error will be raised.
        """
        if not self._compute:
            raise DataAnalyzer.Error.CallFindButNoCompute
        
        lCluster = []
        i = 0
        cluster = [-1, -1]
        #looking for cluster in the data
        #if the data value is over 3 time the standard deviation
        #superior to the median value, the data is cluster data.
        #We consider that 2 haptic clusters are distinct if they are
        #at least sperate by 'threshold' (optional method parameter)
        #'regular' samples
        for d in self._data:
            if (d > (self.median + (3.0 * self.std_dev))):
                if (cluster[0] >= 0):
                    cluster[1] = i
                else:
                    cluster[0] = i
            elif(cluster[1] >= 0) and ((i - cluster[1]) > threshold):
                lCluster.append((cluster[0], cluster[1]))
                cluster = [-1, -1]
            i += 1
                
        return lCluster

    def probableSignalClusterSignificantPos(self, cluster):
        """
        Public method
        Return the occurrence of interest of an haptic signal data
        cluster. We consider this occurrence to be the highest data
        value of the cluster (top of the spike).
        Returns the occurrence of the highest data value in the data
        cluster
        """
        l = len(self._data)
        if not (cluster[0] < l and cluster[1] < l) :
            return -1
        
        maxV = self._data[cluster[0]]
        maxI = cluster[0]
        
        for i in range((maxI + 1), cluster[1]) :
            v = self._data[i]
            if (v > maxV) :
                maxV = v
                maxI = i
        
        return maxI