示例#1
0
 def onmove(self,event):
     #if self.active():
     if (event.button == 1):
         #self.y = event.y
         #self.x = event.x
         self.xdata = self.canvas.xdata
         self.ydata = self.canvas.ydata
         Cursor.onmove(self, event)
示例#2
0
 def onmove(self, event):
     #if self.active():
     if (event.button == 1):
         #self.y = event.y
         #self.x = event.x
         self.xdata = self.canvas.xdata
         self.ydata = self.canvas.ydata
         Cursor.onmove(self, event)
示例#3
0
class ECE4012:
    def __init__(self, figure, filename, toolbar):
        self.dfCal = None
        self.fig = figure
        self.toolbar = toolbar
        self.filename = filename
        self.rect = None

    # Function used to setup graph after class is created or after new data is loaded
    def initializer(self, type):
        self.fig.clear()
        print("clear figure")
        self.fig.subplots_adjust(hspace=1.0)
        self.annoteText = "annotated"
        self.isAnnotate = False
        self.fig.canvas.mpl_connect('button_release_event', self.onrelease)
        self.fig.canvas.mpl_connect('button_press_event', self.onclick)
        self.fig.canvas.mpl_connect('key_press_event', self.onpress)
        self.fig.canvas.mpl_connect('pick_event', self.onpick)

        if type == "DB":
            self.searchOpenCalibration(self.filename)
            self.conn = self.getConnection(self.filename)
            t = time.time()
            df = pd.read_sql_query("select * from  acc;", self.conn)
            elapsed = time.time() - t
            print("time taken to read data was {:f}".format(elapsed))
        elif type == "CSV":
            print("CSV getting Calibration")
            self.searchOpenCalibration(self.filename)
            print("CSV opening file")
            df = pd.read_csv(self.filename)
            print("CSV opened file")

        print("Starting")
        # Apply calibration if calibration data is loaded
        if self.dfCal is not None:
            df["valuex"] = np.subtract(df["valuex"], self.dfCal['Values'][
                self.XOffset]) / self.dfCal['Values'][self.XGain]
            df["valuey"] = np.subtract(df["valuey"], self.dfCal['Values'][
                self.YOffset]) / self.dfCal['Values'][self.YGain]
            df["valuez"] = np.subtract(df["valuez"], self.dfCal['Values'][
                self.ZOffset]) / self.dfCal['Values'][self.ZGain]

        self.fig.subplots_adjust(bottom=0.3, left=0.2, hspace=1.0)
        # setup some constants to be used in Scale Selection panel
        self.labels = ['30 sec', '5 min', '30 min', '1 hr', '2 hr']
        sec30 = pd.Timedelta(30, unit='s')
        min5 = pd.Timedelta(5, unit='m')
        min30 = pd.Timedelta(30, unit='m')
        hr1 = pd.Timedelta(1, unit='h')
        hr2 = pd.Timedelta(2, unit='h')

        # Scale Selection panel made from Radio Buttons
        self.scaleDeltaArray = [sec30, min5, min30, hr1, hr2]
        self.rax = self.fig.add_axes([0.02, 0.7, 0.11, 0.15])
        self.rax.set_title('Scale')
        self.check = RadioButtons(self.rax, self.labels)
        self.fig.canvas.mpl_connect('button_press_event', self.onclick)
        self.check.on_clicked(self.changeScale)

        # Data Set Selection Check Box
        self.rcbax = self.fig.add_axes([0.02, 0.25, 0.11, 0.15])
        self.rcbax.set_title('DataSet')
        self.checkBox = CheckButtons(self.rcbax,
                                     ('valuex', 'valuey', 'valuez', 'mag'),
                                     (True, True, True, True))
        self.checkBox.on_clicked(self.oncheck)
        xs = np.linspace(15, 21, 200)
        horiz_line_dataz = np.array([0.41 for i in range(len(xs))])
        self.rcbax.plot(xs, horiz_line_dataz, 'C3-')
        horiz_line_datam = np.array([0.26 for i in range(len(xs))])
        self.rcbax.plot(xs, horiz_line_datam, 'C0-')
        horiz_line_datay = np.array([0.58 for i in range(len(xs))])
        self.rcbax.plot(xs, horiz_line_datay, 'C2-')
        horiz_line_datax = np.array([0.73 for i in range(len(xs))])
        self.rcbax.plot(xs, horiz_line_datax, 'C1-')

        # Create magnitude value of acceleration data in a dataframe and substract 1g to eliminate gravity
        df["mag"] = np.sqrt(np.square(df["valuex"]) + np.square(df['valuey']) + \
                            np.square(df["valuez"]))-1.0
        print("Normalize")
        ya_min = df.loc[:, "mag"].min() - 0.1
        ya_max = df.loc[:, "mag"].max() + 0.1
        print("y limit (max={:f},min={:f})".format(ya_max, ya_min))

        print("Convert Date Time")
        print(df["epoch"].iloc[0])
        print(df["epoch"].iloc[1])
        # Convert epoch to datetime
        if type == "DB":
            print("epoch type", df.dtypes[0])
            df['epoch'] = pd.to_datetime(df['epoch'], unit='ms')
        elif type == "CSV":
            print("epoch type", df.dtypes[0])
            if 'annotated' not in df.columns:
                df['epoch'] = pd.to_datetime(df['epoch'], unit='ms')
            else:
                df['epoch'] = pd.to_datetime(df['epoch'])
        print("epoch type after", df.dtypes[0])

        # Adjusting epoch time to be in Eastern Time Zone
        df['epoch'] = df['epoch'].dt.tz_localize('UTC').dt.tz_convert(
            'America/New_York')
        # Create external numpy array to manage timestamp data to be sure that data will be datetime
        vepoch = df['epoch']
        self.datevalues = vepoch.dt.to_pydatetime()

        # Create annotated and colorHex columns in the dataframe for capturing annotation
        if 'annotated' not in df.columns:
            charArr = np.chararray((len(df["mag"], )), unicode=True)
            charArr[:] = ' '
            df["annotated"] = pd.DataFrame(charArr)
            df["colorHex"] = pd.DataFrame(charArr)
        # Define format for graph ticks
        self.hoursFmt = mdates.DateFormatter('%a-%m-%d %H:%M:%S')
        self.HMSFmt = mdates.DateFormatter('%H:%M:%S')
        # Get total time of the data in hours
        startDate = df["epoch"].iloc[0]
        self.startDate = startDate
        endDate = df["epoch"].iloc[-1]
        totaltime = int(endDate.timestamp() * 1000) - \
                    int(startDate.timestamp() * 1000)
        total_hours = totaltime / 1000 / 3600  #totaltime in hours
        total_minutes = total_hours * 60
        print("total hours {:f}".format(total_hours))

        # Create variable to track drag time
        self.timeTrack = 0
        # Create variable to track initial click xpos
        self.xpos = 0
        # Create class attribute with the data to be used in the rest of class functions
        self.df = df

        print("Creating Top Graph")
        # First axis  representing Top Graph
        self.ax = self.fig.add_subplot(2, 1, 1)
        # Second axis representing Bottom Graph
        print("Creating Bottom Graph")
        self.ax2 = self.fig.add_subplot(2, 1, 2)
        # Adjust distance between toolbar and graph to give more space
        self.fig.subplots_adjust(bottom=0.145)

        # Adjust distance between toolbar and graph if data is 24 hours or more
        if total_hours > 24:
            self.fig.subplots_adjust(hspace=1.3)
        print("Start Plot Setting")

        # Set axis titles to graphs
        self.ax.set_xlabel("Time")
        self.ax2.set_xlabel("Time")
        self.ax.set_ylabel("Acceleration (g)")
        self.ax2.set_ylabel("Acceleration (g)")
        # Adjust y-axis range to maximum and minimum of magnitude
        self.ax.set_ylim(ya_min, ya_max)
        self.ax2.set_ylim(ya_min, ya_max)
        # Set title with word Calibrated if calibration was applied
        bottomtitle = 'Magnitude Graph for Start Date ' + "{:%Y-%m-%d}".format(
            startDate)
        if self.dfCal is not None:
            bottomtitle = 'Calibrated ' + bottomtitle
        self.ax.set_title(bottomtitle)

        toptitle = 'Zoomed-In Graph for Start Date ' + "{:%Y-%m-%d}".format(
            startDate)
        if self.dfCal is not None:
            toptitle = 'Calibrated ' + toptitle
        self.ax2.set_title(toptitle)

        # Prepare x-axis range to display initially in bottom graph
        start_time = df["epoch"].iloc[0]
        print("start time={v}".format(v=start_time))
        # If data loaded is longer than 1 hour, GUI will show the first hour on bottom graph
        if total_hours > 1:
            end_time = start_time + hr1
        elif total_minutes > 30:
            end_time = start_time + min30
        elif total_minutes > 5:
            end_time = start_time + min5
        else:
            end_time = start_time + sec30
        print("end time={v}".format(v=end_time))
        self.startX = start_time
        self.endX = end_time

        # Set x-axis limit with previous selection
        self.ax2.set_xlim(start_time, end_time)
        print("Set Limit")
        # Create data mask with informaton being displayed
        mask = (df["epoch"] >= start_time) & (df["epoch"] <= end_time)
        print("Plotting")

        # Plot top graph
        t = time.time()
        # To increase speed to graph, only plot first 4 points and then
        # substitute the data with function set_data, this saves several seconds of load time
        self.plotTop, = self.ax.plot(df["epoch"].iloc[0:3],
                                     df["mag"].iloc[0:3],
                                     visible=True)
        self.plotTop.set_data(self.datevalues, df["mag"])
        self.ax.relim()
        self.ax.autoscale_view(True, True, True)
        self.fig.canvas.draw()
        elapsed = time.time() - t
        print("time taken to top graph magnitude was {:f}".format(elapsed))

        print(len(df.loc[mask, "epoch"]))
        # Plot bottom graph
        t = time.time()
        # Initially graphs only magnitude
        # To increase speed to graph, only plot first 4 points and then
        # substitute the data with function set_data, this saves several seconds of load time
        self.lm, = self.ax2.plot(df["epoch"].iloc[0:3],
                                 df["mag"].iloc[0:3],
                                 visible=True)
        self.lm.set_data(self.datevalues, df["mag"])
        self.ax2.relim()
        self.ax2.autoscale_view(True, True, True)
        self.fig.canvas.draw()
        elapsed = time.time() - t
        print("time taken to bottom graph magnitude was {:f}".format(elapsed))
        t = time.time()
        # Create thread to plot x value in the bottom graph in background mode
        # to avoid startup delay
        try:
            thread1 = myThread(1, "valuex", self)
            thread1.start()
        except:
            print("Error: unable to start thread")
        elapsed = time.time() - t
        print("time taken to bottom graph valuex was {:f}".format(elapsed))
        t = time.time()
        # Create thread to plot y value in the bottom graph in background mode
        # to avoid startup delay
        try:
            thread2 = myThread(2, "valuey", self)
            thread2.start()
        except:
            print("Error: unable to start thread")

        elapsed = time.time() - t
        print("time taken to bottom graph valuey was {:f}".format(elapsed))
        t = time.time()
        # Create thread to plot z value in the bottom graph in background mode
        # to avoid startup delay
        try:
            thread3 = myThread(3, "valuez", self)
            thread3.start()
        except:
            print("Error: unable to start thread")

        elapsed = time.time() - t
        print("time taken to bottom graph valuez was {:f}".format(elapsed))

        # x in the range
        tX = df.loc[mask, "epoch"]
        self.ax2.set_xlim(tX.iloc[0], tX.iloc[len(tX) - 1])
        # Set tick format and number on top graph
        self.ax.xaxis.set_major_formatter(self.HMSFmt)
        self.ax.get_xaxis().set_major_locator(LinearLocator(numticks=12))
        # Setup format of ticks to Weekday month/day if data is 24 hours or more
        if total_hours > 24:
            self.ax.xaxis.set_major_formatter(self.hoursFmt)

        # Rotate labels on x-axis 45 degrees and set font size to 8
        self.ax.tick_params(axis='x', labelsize=8, rotation=45)
        # Select initial random color for random annotation
        self.color = self.colorChoose(random.randint(0, 255),
                                      random.randint(0, 255),
                                      random.randint(0, 255))
        self.removedObj = None
        # Refresh the graph
        self.fig.canvas.draw()
        # Prepare graph to display red cursor on top graph
        self.fig.canvas.mpl_connect('motion_notify_event', self.onmouseover)
        self.cursor = Cursor(self.ax,
                             useblit=True,
                             horizOn=False,
                             color='red',
                             linewidth=2)
        self.cursor.connect_event('button_press_event', self.cursorOnclick)

        # Setup initial value for the scale to 30 seconds
        self.currentDelta = pd.Timedelta(30, unit='s')
        # Set tick format and number on bottom graph
        self.ax2.xaxis.set_major_formatter(self.HMSFmt)
        self.ax2.get_xaxis().set_major_locator(LinearLocator(numticks=7))

        # Set function to format coordinates to be displayed on bottom right corner
        self.ax.format_coord = self.format_coord
        # Call function to search for annotation in the data
        # if it was loaded from CSV file and graph them
        if type == "CSV" and 'annotated' in df.columns:
            print("calling searchForAnnotation")
            self.searchForAnnotation()

    # Function that derives values to be shown on bottom right corner.
    # It will display Timestamp and magnitude of where cursor is located
    def format_coord(self, x, y):
        dateclickOn = mdates.num2date(x)
        idx = self.df['epoch'].searchsorted(dateclickOn)
        idx = idx - 1
        vx = self.df['valuex'].values[idx][0]
        vy = self.df['valuey'].values[idx][0]
        vz = self.df['valuez'].values[idx][0]
        vm = self.df['mag'].values[idx][0]
        return "{:%H:%M:%S} M:{:1.3f}".format(dateclickOn, vm)

    # Function to read calibrationResultsXXXXXXXXXXXX.csv
    # to obtain offset and gain values of x,y, and z-axis
    # from MetaWear device
    def readCalibration(self, filename):
        self.dfCal = pd.read_csv(filename)
        print('Results: %s', self.dfCal)
        print('title: %s', self.dfCal['Titles'])
        print('values: %s', self.dfCal['Values'])
        print('ZGain: %s', self.dfCal['Values'][1])
        self.ZOffset = 0
        self.ZGain = 1
        self.YOffset = 2
        self.YGain = 3
        self.XOffset = 4
        self.XGain = 5

    # Function used to redraw top and bottom graphs
    # with calibrated values applied to x, y, and z values
    def redrawAfterCalibrate(self):

        print("Computing new data")

        #Computes new x, y, and z values with calibration
        if self.dfCal is not None:
            self.df["valuex"] = np.subtract(
                self.df["valuex"], self.dfCal['Values'][
                    self.XOffset]) / self.dfCal['Values'][self.XGain]
            self.df["valuey"] = np.subtract(
                self.df["valuey"], self.dfCal['Values'][
                    self.YOffset]) / self.dfCal['Values'][self.YGain]
            self.df["valuez"] = np.subtract(
                self.df["valuez"], self.dfCal['Values'][
                    self.ZOffset]) / self.dfCal['Values'][self.ZGain]
        print("Computing new mag")

        self.df["mag"] = np.sqrt(np.square(self.df["valuex"]) + np.square(self.df['valuey']) + \
                            np.square(self.df["valuez"]))-1.0
        print("setting titles")
        # Bottom Title changed to say Calibrated
        bottomtitle = 'Magnitude Graph for Start Date ' + "{:%Y-%m-%d}".format(
            self.startDate)
        if self.dfCal is not None:
            bottomtitle = 'Calibrated ' + bottomtitle
        self.ax.set_title(bottomtitle)

        # Top Title changed to say Calibrated
        toptitle = 'Zoomed-In Graph for Start Date ' + "{:%Y-%m-%d}".format(
            self.startDate)
        if self.dfCal is not None:
            toptitle = 'Calibrated ' + toptitle
        self.ax2.set_title(toptitle)

        print("redraw graph")

        # Refreshes graphs with new data values
        self.plotTop.set_ydata(self.df["mag"])
        self.lm.set_ydata(self.df["mag"])
        self.lx.set_ydata(self.df["valuex"])
        self.ly.set_ydata(self.df["valuey"])
        self.lz.set_ydata(self.df["valuez"])
        self.fig.canvas.draw()

    # Function used to determine where mouse event occurs
    def onmouseover(self, event):

        if event.inaxes == self.rax:
            None

        if event.inaxes == self.ax:
            self.cursor.onmove(event)

    # Function used to determine if calibration file is found in same directory
    # as GUI application
    def searchOpenCalibration(self, filename):
        directory = os.path.dirname(filename)
        print("directory=" + directory)
        tosearch = re.compile('^calibrationResults.*')
        for sChild in os.listdir(directory):
            print("file=" + sChild)
            if tosearch.match(sChild) is not None:
                if directory == "":
                    directory = "."
                calibfilename = directory + "/" + sChild
                print("calibfilename=" + calibfilename)
                self.readCalibration(calibfilename)
                break

    # Function used to determine if annotations have been applied to
    # recently opened csv file
    def searchForAnnotation(self):
        colorKick = self.colorChoose(255, 0, 0)
        colorSleep = self.colorChoose(0, 0, 255)
        colorRandom = self.colorChoose(0, 255, 0)
        randomColor = self.color

        maskKick = self.df['annotated'] == "Kick"
        maskSleep = self.df['annotated'] == "Sleep"
        maskRandom = self.df['annotated'] == "Random"
        maskColorRandom = self.df['annotated'] == "annotated"

        print("masked found")

        # Creates mask of locations of annotations
        # Calls reDrawAnnotation to replot rectangles on graphs
        if len(self.df.loc[maskKick, 'epoch']) > 0:
            self.reDrawAnnotation(maskKick, colorKick)
        if len(self.df.loc[maskSleep, 'epoch']) > 0:
            self.reDrawAnnotation(maskSleep, colorSleep)
        if len(self.df.loc[maskRandom, 'epoch']) > 0:
            self.reDrawAnnotation(maskRandom, colorRandom)
        if len(self.df.loc[maskColorRandom, 'epoch']) > 0:
            self.reDrawAnnotation(maskColorRandom, randomColor)

    # Function used to redraw all annotations seen when
    # opening csv file that has annotations
    def reDrawAnnotation(self, mask, color):

        [ymin, ymax] = self.ax.get_ylim()
        height = ymax - ymin

        # Determines index positions of annotations
        positionKick = np.array(self.df.index[mask].tolist())

        # Determines where gaps between annotations occur
        diff = np.subtract(positionKick[1:-1], positionKick[0:-2])

        maskcuts = diff > 1
        posInCuts = np.where(maskcuts)
        arrposcut = posInCuts[0]
        arrpostcut1 = arrposcut + 1

        # Initializes first seen annotation
        xmin = self.df.loc[mask, 'epoch'].iloc[0]
        xmax = self.df.loc[mask, 'epoch'].iloc[-1]
        xmin = xmin.to_pydatetime()
        xmax = xmax.to_pydatetime()

        # converts values to proper time format
        print("xmin={v1} xmax={v2}".format(v1=xmin, v2=xmax))
        xmin = mdates.date2num(xmin)
        xmax = mdates.date2num(xmax)
        print("len(posInCuts)", len(posInCuts[0]))
        print("xmin={v1} xmax={v2}".format(v1=xmin, v2=xmax))

        # For loop used to run through and create rectangles to plot for annotations
        for idx in range(len(posInCuts[0])):
            print("idx=", idx)
            print("xmin={v1} xmax={v2}".format(
                v1=xmin,
                v2=self.df['epoch'].iloc[positionKick[arrposcut[idx]]]))

            rectmin = xmin
            rectmax = self.df['epoch'].iloc[positionKick[arrposcut[idx]]]
            rectmax = rectmax.to_pydatetime()
            rectmax = mdates.date2num(rectmax)

            width = rectmax - rectmin
            rect = ECERectangle(rectmin,
                                ymin,
                                width,
                                height,
                                color=color,
                                index=1)
            rect2 = ECERectangle(xmin,
                                 ymin,
                                 width,
                                 height,
                                 color=color,
                                 index=2)
            rect.setNext(rect2)
            rect2.setPrev(rect)
            self.ax.add_patch(rect)
            self.ax2.add_patch(rect2)
            self.fig.canvas.draw()
            xmin = self.df['epoch'].iloc[positionKick[arrpostcut1[idx]]]
            xmin = xmin.to_pydatetime()
            xmin = mdates.date2num(xmin)

        rectmin = xmin
        rectmax = xmax

        width = rectmax - rectmin
        rect = ECERectangle(rectmin, ymin, width, height, color=color, index=1)
        rect2 = ECERectangle(xmin, ymin, width, height, color=color, index=2)
        rect.setNext(rect2)
        rect2.setPrev(rect)
        self.ax.add_patch(rect)
        self.ax2.add_patch(rect2)
        print("xmin={v1} xmax={v2}".format(v1=xmin, v2=xmax))
        self.fig.canvas.draw()

    # Sets up sqlite3 connection to database file
    def getConnection(self, filename):
        """
        get the connection of sqlite given file name
        :param filename:
        :return: sqlite3 connection
        """

        conn = sqlite3.connect(filename)
        return conn

    # Old Function used to read calibration file. No longer relevant
    def readCalibration(self, filename):
        self.dfCal = pd.read_csv(filename)
        print('Results: %s', self.dfCal)
        print('title: %s', self.dfCal['Titles'])
        print('values: %s', self.dfCal['Values'])
        print('ZGain: %s', self.dfCal['Values'][1])
        self.ZOffset = 0
        self.ZGain = 1
        self.YOffset = 2
        self.YGain = 3
        self.XOffset = 4
        self.XGain = 5

    # Function used to create calibration button. No longer relevant
    def createCalibrationAction(self):
        image_file = 'square-upload'
        callback = self.toolbar.importCal
        text = "Calibrate"
        tooltip_text = "Calibrate"
        a = self.toolbar.addAction(self.toolbar._icon(image_file + '.png'),
                                   text, callback)
        print("action created")
        self.toolbar._actions[callback] = a
        print("action added to array")

        a.setToolTip(tooltip_text)

    # Function to execute query
    def executeQuery(self, query):
        return None

    # Function used to set range of colors
    def colorChoose(self, r, g, b):
        """
        create a normalized color map give r, g, b in 0-255 scale
        :param r: red
        :param g: green
        :param b: blue
        :return: tuple of color that can be used for matplotlib
        """
        if self.rangeOff(r) or self.rangeOff(g) or self.rangeOff(r):
            return (0, 0, 0)
        return r / 255.0, g / 255.0, b / 255.0

    # Function to set range off
    def rangeOff(self, val):
        return (val > 255) or (val < 0)

    # Function to determine event of creating annotations
    def onpick(self, event):
        print("pick event")
        if isinstance(event.artist, Rectangle):
            patch = event.artist
            # patch.remove()
            self.removedObj = patch
            print('onpick1 patch:', patch.get_path())
        else:
            print(event.artist.get_xdata())
            print(event.artist.get_xdata())
            print(len(event.artist.get_ydata()))

    # Function used to check if annotation is selected
    def onclick(self, event):
        if not self.toolbar._actions['zoom'].isChecked(
        ) and event.button == 1:  # left = 1, middle = 2, right = 3
            self.timeTrack = time.time()
            print("clicked {}".format(self.timeTrack))
            print("clicked X: {}".format(event.xdata))
            self.xpos = event.xdata

    # Function used to determine when annotation event occurs
    def onrelease(self, event):
        if not self.toolbar._actions['zoom'].isChecked() \
                and event.button == 1 and self.isAnnotate:

            curTime = time.time()
            if (curTime - self.timeTrack) > PRE_DEF_CLICK_TIME:
                print("dragged")
                xmin = self.xpos
                xmax = event.xdata
                width = xmax - xmin

                [ymin, ymax] = self.ax.get_ylim()
                height = ymax - ymin

                self.create_annotation(xmin, xmax)

                rect = ECERectangle(xmin,
                                    ymin,
                                    width,
                                    height,
                                    color=self.color,
                                    index=1)
                rect2 = ECERectangle(xmin,
                                     ymin,
                                     width,
                                     height,
                                     color=self.color,
                                     index=2)

                rect.setNext(rect2)
                rect2.setPrev(rect)
                self.ax.add_patch(rect)
                self.ax2.add_patch(rect2)

                self.fig.canvas.draw()

    # Key commands running from keyboard
    def onpress(self, event):
        # print(event.key())
        print(event.key)
        if event.key == 'r':
            self.annoteText = "Kick"
            self.color = self.colorChoose(255, 0, 0)
        elif event.key == 'b':
            self.annoteText = "Sleep"
            self.color = self.colorChoose(0, 0, 255)
        elif event.key == 'g':
            self.annoteText = "Random"
            self.color = self.colorChoose(0, 255, 0)
        elif event.key == "right":
            print("right pressed")
            self.startX += self.currentDelta
            self.endX += self.currentDelta
            self.ax2.set_xlim(self.startX, self.endX)

            self.run()
        elif event.key == "left":
            # TODO check left and right limit
            print("left pressed")
            self.startX -= self.currentDelta
            self.endX -= self.currentDelta
            self.ax2.set_xlim(self.startX, self.endX)

            self.run()
        elif event.key == "delete":
            print("delete")
            if self.removedObj is not None:
                if isinstance(self.removedObj, ECERectangle):
                    print("deleting ECERect")
                    rect_min_x = self.removedObj.get_x()
                    rect_max_x = rect_min_x + self.removedObj.get_width()
                    self.remove_annotation(rect_min_x, rect_max_x)
                    ind = self.removedObj.getIndex()
                    self.removedObj.remove()
                    if ind == 1:
                        nextRect = self.removedObj.getNext()
                    else:
                        nextRect = self.removedObj.getPrev()
                    self.removedObj = None

                    if nextRect.axes is not None:
                        nextRect.remove()
                    self.fig.canvas.draw()

    # Redraws graphs
    def run(self):
        self.fig.canvas.draw()

    # Creates annotation to dataframe
    def create_annotation(self, xmin, xmax):
        print("Annoated")
        cond = self.get_x_in_ranges(xmin, xmax)
        self.df.loc[cond, 'annotated'] = self.annoteText
        self.df.loc[cond, 'colorHex'] = self.get_color_in_hex()

    # Deletes annotation labels
    def remove_annotation(self, xmin, xmax):
        cond = self.get_x_in_ranges(xmin, xmax)
        self.df.loc[cond, 'annotated'] = " "
        self.df.loc[cond, 'colorHex'] = " "

    # Obtain mask of range of x values
    def get_x_in_ranges(self, xmin, xmax):
        return (self.df["epoch"] <= mdates.num2date(xmax)) \
               & (self.df["epoch"] >= mdates.num2date(xmin))

    # Get hexdecimal color
    def get_color_in_hex(self):
        return "#{:02X}{:02X}{:02X}".format(int(self.color[0] * 255),
                                            int(self.color[1] * 255),
                                            int(self.color[2] * 255))

    # Unselect annotation when not active
    def setSelect(self):
        self.isAnnotate = not self.isAnnotate

    # Function used to determine what click and hold effect does for annotations
    def cursorOnclick(self, event):
        'on button press we will see if the mouse is over us '
        if (self.ax == event.inaxes) and (not self.isAnnotate):
            xdata = event.xdata
            dateclicked = mdates.num2date(xdata)
            self.startX = dateclicked
            dateEnd = dateclicked + self.currentDelta
            self.endX = dateEnd

            mask = (self.df["epoch"] >= dateclicked) & (self.df["epoch"] <=
                                                        dateEnd)
            tX = self.df.loc[mask, "epoch"]

            self.ax2.set_xlim(tX.iloc[0], tX.iloc[len(tX) - 1])

            self.ax2.get_xaxis().set_major_locator(LinearLocator(numticks=12))

            self.ax2.autoscale_view(True, True, True)

            width = mdates.date2num(dateEnd) - xdata
            [ymin, ymax] = self.ax.get_ylim()
            height = ymax - ymin
            if self.rect is not None:
                self.rect.remove()
            self.rect = Rectangle((xdata, ymin),
                                  width,
                                  height,
                                  fill=True,
                                  alpha=0.4,
                                  color=(1, 0, 0),
                                  picker=False)

            self.ax.add_patch(self.rect)

            self.fig.canvas.draw()

    # Sets checks on visibility of x,y, and z -axis plots
    def oncheck(self, label):
        if label == 'valuex':
            self.lx.set_visible(not self.lx.get_visible())
        elif label == 'valuey':
            self.ly.set_visible(not self.ly.get_visible())
        elif label == 'valuez':
            self.lz.set_visible(not self.lz.get_visible())
        elif label == 'mag':
            self.lm.set_visible(not self.lm.get_visible())
        self.fig.canvas.draw()

    # Adjust time scale values to plot on bottom graph
    def changeScale(self, label):
        index = self.labels.index(label)
        self.currentDelta = self.scaleDeltaArray[index]
 def onmove(self, event):
     self.visible = True
     self.vertOn = True
     self.horizOn = True
     Cursor.onmove( self, event )
示例#5
0
class xsection_viewer(object):
    def __init__(self, fig, init_image,
                 cmap=None,
                 norm=None,
                 clim_percentile=None):
        """
        Sets up figure with cross section viewer

        Parameters
        ----------
        fig : matplotlib.figure.Figure
            The figure object to build the class on, will clear
            current contents

        init_image : 2d ndarray
            The initial image

        cmap : str,  colormap, or None
           color map to use.  Defaults to gray

        clim_percentile : float or None
           percentile away from 0, 100 to put the max/min limits at
           ie, clim_percentile=5 -> vmin=5th percentile vmax=95th percentile

        norm : Normalize or None
           Normalization function to us
        """
        self._active = True
        self._clim_pct = clim_percentile
        if cmap is None:
            cmap = 'gray'
        # this needs to respect percentile
        self.vmin, self.vmax = _compute_limit(init_image, self._clim_pct)
        # stash the figure
        self.fig = fig
        # clean it
        self.fig.clf()
        # make the main axes
        self._im_ax = fig.add_subplot(1, 1, 1)
        self._im_ax.set_aspect('equal')
        self._im_ax.xaxis.set_major_locator(NullLocator())
        self._im_ax.yaxis.set_major_locator(NullLocator())
        self._imdata = init_image
        self._im = self._im_ax.imshow(init_image, cmap=cmap, norm=norm,
                                      interpolation='none', aspect='equal')

        # make it dividable
        divider = make_axes_locatable(self._im_ax)

        # set up all the other axes
        self._ax_h = divider.append_axes('top', .5, pad=0.1,
                                         sharex=self._im_ax)
        self._ax_h.yaxis.set_major_locator(NullLocator())
        self._ax_v = divider.append_axes('left', .5, pad=0.1,
                                         sharey=self._im_ax)
        self._ax_v.xaxis.set_major_locator(NullLocator())
        self._ax_cb = divider.append_axes('right', .2, pad=.5)
        # add the color bar
        self._cb = fig.colorbar(self._im, cax=self._ax_cb)

        # print out the pixel value
        def format_coord(x, y):
            numrows, numcols = self._imdata.shape
            col = int(x+0.5)
            row = int(y+0.5)
            if col >= 0 and col < numcols and row >= 0 and row < numrows:
                z = self._imdata[row, col]
                return "X: {x:d} Y: {y:d} I: {i:.2f}".format(x=col, y=row, i=z)
            else:
                return "X: {x:d} Y: {y:d}".format(x=col, y=row)
        self._im_ax.format_coord = format_coord

        # add the cursor
        self.cur = Cursor(self._im_ax, useblit=True, color='red', linewidth=2)

        self._ax_h.set_ylim(self.vmin, self.vmax)
        self._ax_h.autoscale(enable=False)

        self._ax_v.set_xlim(self.vmin, self.vmax)
        self._ax_v.autoscale(enable=False)

        # add lines
        self._ln_v, = self._ax_v.plot(np.zeros(self._imdata.shape[1]),
                                np.arange(self._imdata.shape[1]), 'k-',
                                animated=True,
                                visible=False)

        self._ln_h, = self._ax_h.plot(np.arange(self._imdata.shape[0]),
                                np.zeros(self._imdata.shape[0]), 'k-',
                                animated=True,
                                visible=False)

        # backgrounds for blitting
        self._ax_v_bk = None
        self._ax_h_bk = None

        # stash last-drawn row/col to skip if possible
        self._row = None
        self._col = None

        # set up the call back for the updating the side axes
        def move_cb(event):
            if not self._active:
                return

            # short circuit on other axes
            if event.inaxes is not self._im_ax:
                return
            numrows, numcols = self._imdata.shape
            x, y = event.xdata, event.ydata
            if x is not None and y is not None:
                self._ln_h.set_visible(True)
                self._ln_v.set_visible(True)
                col = int(x+0.5)
                row = int(y+0.5)
                if row != self._row and col != self._col:
                    if (col >= 0 and col < numcols and
                            row >= 0 and row < numrows):
                        self._col = col
                        self._row = row
                        for data, ax, bkg, art, set_fun in zip(
                                (self._imdata[row, :], self._imdata[:, col]),
                                (self._ax_h, self._ax_v),
                                (self._ax_h_bk, self._ax_v_bk),
                                (self._ln_h, self._ln_v),
                                (self._ln_h.set_ydata, self._ln_v.set_xdata)):
                            self.fig.canvas.restore_region(bkg)
                            set_fun(data)
                            ax.draw_artist(art)
                            self.fig.canvas.blit(ax.bbox)

        def click_cb(event):
            if event.inaxes is not self._im_ax:
                return
            self.active = not self.active
            if self.active:
                self.cur.onmove(event)
                move_cb(event)

        self.move_cid = self.fig.canvas.mpl_connect('motion_notify_event',
                                        move_cb)

        self.click_cid = self.fig.canvas.mpl_connect('button_press_event',
                                        click_cb)

        self.clear_cid = self.fig.canvas.mpl_connect('draw_event', self.clear)
        self.fig.tight_layout()
        self.fig.canvas.draw()

    def clear(self, event):
        self._ax_v_bk = self.fig.canvas.copy_from_bbox(self._ax_v.bbox)
        self._ax_h_bk = self.fig.canvas.copy_from_bbox(self._ax_h.bbox)
        self._ln_h.set_visible(False)
        self._ln_v.set_visible(False)

    @property
    def active(self):
        return self._active

    @active.setter
    def active(self, val):
        self._active = val
        self.cur.active = val

    def update_image(self, new_image):
        """
        Update the image displayed by the main axes

        Parameters
        ----------
        new_image : 2D ndarray
           The new image to use
        """
        self.vmin, self.vmax = _compute_limit(new_image, self._clim_pct)
        self._ax_v.set_xlim(self.vmin, self.vmax)
        self._ax_h.set_ylim(self.vmin, self.vmax)
        self._imdata = new_image
        self._im.set_data(new_image)
        self._im.set_clim((self.vmin, self.vmax))
        self.fig.canvas.draw()
        pass

    def update_colormap(self, new_cmap):
        """
        Update the color map used to display the image


        """
        self._im.set_cmap(new_cmap)
        self.fig.canvas.draw()

    def update_norm(self, new_norm):
        """
        Update the norm used

        """
        self._im.set_norm(new_norm)
        self.fig.canvas.draw()
示例#6
0
class ECE4012:
    def __init__(self, figure, filename, toolbar):
        self.dfCal = None
        self.fig = figure
        self.toolbar = toolbar
        self.filename = filename
        self.rect = None

    def initializer(self, type):
        self.fig.clear()
        print("celar figure")
        self.fig.subplots_adjust(hspace=1.0)
        self.annoteText = "annotated"
        #self.fig = figure
        #self.toolbar = toolbar
        self.isAnnotate = False
        self.fig.canvas.mpl_connect('button_release_event', self.onrelease)
        self.fig.canvas.mpl_connect('button_press_event', self.onclick)
        self.fig.canvas.mpl_connect('key_press_event', self.onpress)
        self.fig.canvas.mpl_connect('pick_event', self.onpick)
        # print(self.fig)
        if type == "DB":
            self.searchOpenCalibration(self.filename)
            self.conn = self.getConnection(self.filename)
            # df = pd.read_sql_query("select * from  acc LIMIT 100000;", self.conn)
            t = time.time()
            df = pd.read_sql_query("select * from  acc;", self.conn)
            elapsed = time.time() - t
            print("time taken to read data was {:f}".format(elapsed))
        elif type == "CSV":
            print("CSV getting Calibration")
            self.searchOpenCalibration(self.filename)
            print("CSV opening file")
            df = pd.read_csv(self.filename)
            print("CSV opened file")

        print("Starting")

        if self.dfCal is not None:
            df["valuex"] = np.subtract(df["valuex"], self.dfCal['Values'][
                self.XOffset]) / self.dfCal['Values'][self.XGain]
            df["valuey"] = np.subtract(df["valuey"], self.dfCal['Values'][
                self.YOffset]) / self.dfCal['Values'][self.YGain]
            df["valuez"] = np.subtract(df["valuez"], self.dfCal['Values'][
                self.ZOffset]) / self.dfCal['Values'][self.ZGain]

        # DONE !!TODO this calibartion should change to either actual calibration from
        # metawear C
        # print(len(df["valuex"]))
        # avgX = np.sum(df["valuex"]) / len(df["valuex"])
        # avgY = np.sum(df["valuey"]) / len(df["valuey"])
        # avgZ = np.sum(df["valuez"]) / len(df["valuez"])
        # df["valuex"] = np.subtract(df["valuex"], avgX)
        # df["valuey"] = np.subtract(df["valuey"], avgY)
        # df["valuez"] = np.subtract(df["valuez"], avgZ)
        #self.axTop = self.fig.add_subplot(2, 1, 1)
        #self.axBottom = self.fig.add_subplot(2, 1, 2)
        self.fig.subplots_adjust(bottom=0.3, left=0.2, hspace=1.0)
        self.labels = ['30 sec', '5 min', '30 min', '1 hr', '2 hr']
        sec30 = pd.Timedelta(30, unit='s')
        min5 = pd.Timedelta(5, unit='m')
        min30 = pd.Timedelta(30, unit='m')
        hr1 = pd.Timedelta(1, unit='h')
        hr2 = pd.Timedelta(2, unit='h')

        # Scale Radio Buttons for Zoom
        self.scaleDeltaArray = [sec30, min5, min30, hr1, hr2]
        self.rax = self.fig.add_axes([0.02, 0.7, 0.11, 0.15])
        self.rax.set_title('Scale')
        self.check = RadioButtons(self.rax, self.labels)
        self.fig.canvas.mpl_connect('button_press_event', self.onclick)

        # Data Set Selection Check Box
        self.rcbax = self.fig.add_axes([0.02, 0.25, 0.11, 0.15])
        self.rcbax.set_title('DataSet')
        self.checkBox = CheckButtons(self.rcbax,
                                     ('valuex', 'valuey', 'valuez', 'mag'),
                                     (True, True, True, True))
        self.checkBox.on_clicked(self.oncheck)
        xs = np.linspace(15, 21, 200)
        horiz_line_dataz = np.array([0.41 for i in range(len(xs))])
        self.rcbax.plot(xs, horiz_line_dataz, 'C3-')
        horiz_line_datam = np.array([0.26 for i in range(len(xs))])
        self.rcbax.plot(xs, horiz_line_datam, 'C0-')
        horiz_line_datay = np.array([0.58 for i in range(len(xs))])
        self.rcbax.plot(xs, horiz_line_datay, 'C2-')
        horiz_line_datax = np.array([0.73 for i in range(len(xs))])
        self.rcbax.plot(xs, horiz_line_datax, 'C1-')

        self.check.on_clicked(self.changeScale)
        df["mag"] = np.sqrt(np.square(df["valuex"]) + np.square(df['valuey']) + \
                            np.square(df["valuez"]))-1.0
        print("Normalize")
        ya_min = df.loc[:, "mag"].min() - 0.1
        ya_max = df.loc[:, "mag"].max() + 0.1
        print("y limit (max={:f},min={:f})".format(ya_max, ya_min))
        # print("Normalized")
        # print(type(ya_min))
        # print(ya_max)

        # print(df["mag"])
        # df["mag"] = df["mag"] - 1 # subtract 1g

        #Convert epoch to datetime to see the right value
        print("Convert Date Time")
        print(df["epoch"].iloc[0])
        print(df["epoch"].iloc[1])
        if type == "DB":
            print("epoch type", df.dtypes[0])
            df['epoch'] = pd.to_datetime(df['epoch'], unit='ms')
        elif type == "CSV":
            print("epoch type", df.dtypes[0])
            if 'annotated' not in df.columns:
                df['epoch'] = pd.to_datetime(df['epoch'], unit='ms')
            else:
                df['epoch'] = pd.to_datetime(df['epoch'])
        print("epoch type after", df.dtypes[0])

        # Adjusting epoch time to be on Eastern Time Zone
        df['epoch'] = df['epoch'].dt.tz_localize('UTC').dt.tz_convert(
            'America/New_York')
        vepoch = df['epoch']
        self.datevalues = vepoch.dt.to_pydatetime()

        if 'annotated' not in df.columns:
            charArr = np.chararray((len(df["mag"], )), unicode=True)
            charArr[:] = ' '
            df["annotated"] = pd.DataFrame(charArr)
            df["colorHex"] = pd.DataFrame(charArr)

        # print(df["epoch"])
        # print(type(df['epoch'][0]))
        #Definition of x-axis formatter of tick
        # self.hoursFmt = mdates.DateFormatter('%Y-%m-%d %H:%M:%S') #Week Month/Day H:M:S
        self.hoursFmt = mdates.DateFormatter('%a-%m-%d %H:%M:%S')
        self.HMSFmt = mdates.DateFormatter('%H:%M:%S')
        #Get total time of the data in hours
        startDate = df["epoch"].iloc[0]
        self.startDate = startDate
        endDate = df["epoch"].iloc[-1]
        totaltime = int(endDate.timestamp() * 1000) - \
                    int(startDate.timestamp() * 1000)
        total_hours = totaltime / 1000 / 3600  #totaltime in hours
        total_minutes = total_hours * 60
        print("total hours {:f}".format(total_hours))

        #create variable to track drag time
        self.timeTrack = 0
        #create variable to track initial click xpos
        self.xpos = 0
        self.df = df

        print("Creating Top Graph")

        self.ax = self.fig.add_subplot(2, 1, 1)
        # second axis
        print("Creating Bottom Graph")
        self.ax2 = self.fig.add_subplot(2, 1, 2)
        #adjust distance between toolbar and graph to give more space
        self.fig.subplots_adjust(bottom=0.145)

        #adjust distance between toolbar and graph if data is 24 hours or more
        if total_hours > 24:
            self.fig.subplots_adjust(hspace=1.3)
        print("Start Plot Setting")

        # Set default values for x aixs
        ##changed temporary pls ignore
        # self.ax.set_ylim(1, 1.1)
        # self.ax2.set_ylim(1, 1.1)
        #self.ax.set_ylim(0, 8)
        #self.ax2.set_ylim(0, 8)
        self.ax.set_xlabel("Time (H:M:S)")
        self.ax2.set_xlabel("Time (H:M:S)")
        self.ax.set_ylabel("Acceleration (g)")
        self.ax2.set_ylabel("Acceleration (g)")
        #self.ax.set_title('Scale')
        self.ax.set_ylim(ya_min, ya_max)
        self.ax2.set_ylim(ya_min, ya_max)
        bottomtitle = 'Magnitude Graph for Start Date ' + "{:%Y-%m-%d}".format(
            startDate)
        if self.dfCal is not None:
            bottomtitle = 'Calibrated ' + bottomtitle
        self.ax.set_title(bottomtitle)

        toptitle = 'Zoomed-In Graph for Start Date ' + "{:%Y-%m-%d}".format(
            startDate)
        if self.dfCal is not None:
            toptitle = 'Calibrated ' + toptitle
        self.ax2.set_title(toptitle)

        # self.ya_min = ya_min
        # self.ya_max = ya_max
        # start date
        # print(type(df["epoch"]))
        # print(len(df["epoch"]))
        # print(df["epoch"])
        # print()
        # TODO we assume time is not empty but it could be good to chek empty
        start_time = df["epoch"].iloc[0]
        print("start time={v}".format(v=start_time))
        # print(type(start_time))
        if total_hours > 1:
            end_time = start_time + hr1
        elif total_minutes > 30:
            end_time = start_time + min30
        elif total_minutes > 5:
            end_time = start_time + min5
        else:
            end_time = start_time + sec30
        print("end time={v}".format(v=end_time))
        # print(type(start_time))
        #end_time = start_time + pd.Timedelta(hours=1)
        #print(end_time)
        self.startX = start_time
        self.endX = end_time

        # set axis 2
        self.ax2.set_xlim(start_time, end_time)
        print("Set Limit")
        # print(type(df["epoch"].iloc[0]))
        mask = (df["epoch"] >= start_time) & (df["epoch"] <= end_time)
        print("Plotting")
        # print(mask)
        # print(df.loc[mask, "epoch"])
        # plot
        t = time.time()
        self.plotTop, = self.ax.plot(df["epoch"].iloc[0:3],
                                     df["mag"].iloc[0:3],
                                     visible=True)
        self.plotTop.set_data(self.datevalues, df["mag"])
        self.ax.relim()
        self.ax.autoscale_view(True, True, True)
        self.fig.canvas.draw()

        #self.ax.plot(df["epoch"], df["mag"])
        elapsed = time.time() - t
        print("time taken to top graph magnitud was {:f}".format(elapsed))
        # print(df.loc[mask, "epoch"])
        print(len(df.loc[mask, "epoch"]))
        t = time.time()
        self.lm, = self.ax2.plot(df["epoch"].iloc[0:3],
                                 df["mag"].iloc[0:3],
                                 visible=True)
        self.lm.set_data(self.datevalues, df["mag"])
        self.ax2.relim()
        self.ax2.autoscale_view(True, True, True)
        self.fig.canvas.draw()
        #self.lm,  = self.ax2.plot(df["epoch"], df["mag"],visible=True)
        elapsed = time.time() - t
        print("time taken to bottom graph magnitud was {:f}".format(elapsed))
        t = time.time()
        try:
            thread1 = myThread(1, "valuex", self)
            thread1.start()
        except:
            print("Error: unable to start thread")
        #self.lx,  = self.ax2.plot(df["epoch"], df["valuex"],visible=False)
        elapsed = time.time() - t
        print("time taken to bottom graph valuex was {:f}".format(elapsed))
        t = time.time()
        try:
            thread2 = myThread(2, "valuey", self)
            thread2.start()
        except:
            print("Error: unable to start thread")
        #self.ly,  = self.ax2.plot(df["epoch"], df["valuey"],visible=False)
        elapsed = time.time() - t
        print("time taken to bottom graph valuey was {:f}".format(elapsed))
        t = time.time()
        try:
            thread3 = myThread(3, "valuez", self)
            thread3.start()
        except:
            print("Error: unable to start thread")
        #self.lz,  = self.ax2.plot(df["epoch"], df["valuez"],visible=False)
        elapsed = time.time() - t
        print("time taken to bottom graph valuez was {:f}".format(elapsed))
        # x in the range
        tX = df.loc[mask, "epoch"]
        self.ax2.set_xlim(tX.iloc[0], tX.iloc[len(tX) - 1])
        # self.ax.xaxis.set_major_formatter(self.hoursFmt)
        self.ax.xaxis.set_major_formatter(self.HMSFmt)
        self.ax.get_xaxis().set_major_locator(LinearLocator(numticks=12))
        #setup format of ticks to Weekday month/day if data is 24 hours or more
        if total_hours > 24:
            self.ax.xaxis.set_major_formatter(self.hoursFmt)

        #Rotate labels on x-axis 45 degrees and set font size to 8
        self.ax.tick_params(axis='x', labelsize=8, rotation=45)
        # self.ax.title("Magnitude")
        # self.ax2.plot(df["epoch"], df["valuex"],
        #               color=self.colorChoose(255, 0, 255))
        # self.ax2.plot(df["epoch"], df["valuey"],
        #               color=self.colorChoose(255, 0, 0))
        # self.ax2.plot(df["epoch"], df["valuez"],
        #               color=self.colorChoose(255, 255, 0))
        self.color = self.colorChoose(random.randint(0, 255),
                                      random.randint(0, 255),
                                      random.randint(0, 255))
        self.removedObj = None
        # self.ax.add_patch(rect)
        self.fig.canvas.draw()
        self.fig.canvas.mpl_connect('motion_notify_event', self.onmouseover)
        self.cursor = Cursor(self.ax,
                             useblit=True,
                             horizOn=False,
                             color='red',
                             linewidth=2)
        self.cursor.connect_event('button_press_event', self.cursorOnclick)
        self.currentDelta = pd.Timedelta(30, unit='s')
        self.ax2.xaxis.set_major_formatter(self.HMSFmt)
        self.ax2.get_xaxis().set_major_locator(LinearLocator(numticks=7))

        #data text axes
        #self.txtax = self.fig.add_axes([0.75, 0.85, 0.11, 0.05])
        #self.txtax.axis('off')

        self.ax.format_coord = self.format_coord
        if type == "CSV" and 'annotated' in df.columns:
            print("calling searchForAnnotation")
            self.searchForAnnotation()

        #self.txt = self.ax.text(0.8, 1.05, 'X,Y,Z Values', transform=self.ax.transAxes)
        #self.txt = self.txtax.text(0.05, 0.05, 'X,Y,Z Values', transform=self.txtax.transAxes)

    def format_coord(self, x, y):
        dateclickOn = mdates.num2date(x)
        idx = self.df['epoch'].searchsorted(dateclickOn)
        idx = idx - 1
        #logger.debug("dateclickOn:%s idx=%s", dateclickOn,idx)
        vx = self.df['valuex'].values[idx][0]
        vy = self.df['valuey'].values[idx][0]
        vz = self.df['valuez'].values[idx][0]
        vm = self.df['mag'].values[idx][0]
        #print("d: {:%H:%M:%S} vx:{:1.5f} vy:{:1.5f} vz:{:1.5f}".format(dateclickOn,vx,vy,vz))
        #self.txt.set_text('%H:%M:%S x=%1.3f, y=%1.3f, z=%1.3f' % (dateclickOn,vx, vy,vz))
        return "{:%H:%M:%S} M:{:1.3f}".format(dateclickOn, vm)

    def readCalibration(self, filename):
        self.dfCal = pd.read_csv(filename)
        print('Results: %s', self.dfCal)
        print('title: %s', self.dfCal['Titles'])
        print('values: %s', self.dfCal['Values'])
        print('ZGain: %s', self.dfCal['Values'][1])
        self.ZOffset = 0
        self.ZGain = 1
        self.YOffset = 2
        self.YGain = 3
        self.XOffset = 4
        self.XGain = 5

    def redrawAfterCalibrate(self):

        print("Computing new data")

        if self.dfCal is not None:
            self.df["valuex"] = np.subtract(
                self.df["valuex"], self.dfCal['Values'][
                    self.XOffset]) / self.dfCal['Values'][self.XGain]
            self.df["valuey"] = np.subtract(
                self.df["valuey"], self.dfCal['Values'][
                    self.YOffset]) / self.dfCal['Values'][self.YGain]
            self.df["valuez"] = np.subtract(
                self.df["valuez"], self.dfCal['Values'][
                    self.ZOffset]) / self.dfCal['Values'][self.ZGain]
        print("Computing new mag")

        self.df["mag"] = np.sqrt(np.square(self.df["valuex"]) + np.square(self.df['valuey']) + \
                            np.square(self.df["valuez"]))-1.0
        print("setting titles")
        bottomtitle = 'Magnitude Graph for Start Date ' + "{:%Y-%m-%d}".format(
            self.startDate)
        if self.dfCal is not None:
            bottomtitle = 'Calibrated ' + bottomtitle
        self.ax.set_title(bottomtitle)

        toptitle = 'Zoomed-In Graph for Start Date ' + "{:%Y-%m-%d}".format(
            self.startDate)
        if self.dfCal is not None:
            toptitle = 'Calibrated ' + toptitle
        self.ax2.set_title(toptitle)

        print("redraw graph")

        self.plotTop.set_ydata(self.df["mag"])
        self.lm.set_ydata(self.df["mag"])
        self.lx.set_ydata(self.df["valuex"])
        self.ly.set_ydata(self.df["valuey"])
        self.lz.set_ydata(self.df["valuez"])
        self.fig.canvas.draw()

    def onmouseover(self, event):

        if event.inaxes == self.rax:
            None
            #logger.debug("click on radiobutton")
            #self.check._clicked(event)
        if event.inaxes == self.ax:
            self.cursor.onmove(event)

    def searchOpenCalibration(self, filename):
        directory = os.path.dirname(filename)
        print("directory=" + directory)
        tosearch = re.compile('^calibrationResults.*')
        for sChild in os.listdir(directory):
            print("file=" + sChild)
            if tosearch.match(sChild) is not None:
                if directory == "":
                    directory = "."
                calibfilename = directory + "/" + sChild
                print("calibfilename=" + calibfilename)
                self.readCalibration(calibfilename)
                break

    def searchForAnnotation(self):
        colorKick = self.colorChoose(255, 0, 0)
        colorSleep = self.colorChoose(0, 0, 255)
        colorRandom = self.colorChoose(0, 255, 0)
        randomColor = self.color

        maskKick = self.df['annotated'] == "Kick"
        maskSleep = self.df['annotated'] == "Sleep"
        maskRandom = self.df['annotated'] == "Random"
        maskColorRandom = self.df['annotated'] == "annotated"

        print("masked found")

        if len(self.df.loc[maskKick, 'epoch']) > 0:
            self.reDrawAnnotation(maskKick, colorKick)
        if len(self.df.loc[maskSleep, 'epoch']) > 0:
            self.reDrawAnnotation(maskSleep, colorSleep)
        if len(self.df.loc[maskRandom, 'epoch']) > 0:
            self.reDrawAnnotation(maskRandom, colorRandom)
        if len(self.df.loc[maskColorRandom, 'epoch']) > 0:
            self.reDrawAnnotation(maskColorRandom, randomColor)

    def reDrawAnnotation(self, mask, color):

        [ymin, ymax] = self.ax.get_ylim()
        height = ymax - ymin

        positionKick = np.array(self.df.index[mask].tolist())

        diff = np.subtract(positionKick[1:-1], positionKick[0:-2])

        maskcuts = diff > 1
        posInCuts = np.where(maskcuts)
        arrposcut = posInCuts[0]
        arrpostcut1 = arrposcut + 1

        xmin = self.df.loc[mask, 'epoch'].iloc[0]
        xmax = self.df.loc[mask, 'epoch'].iloc[-1]
        xmin = xmin.to_pydatetime()
        xmax = xmax.to_pydatetime()
        #xmin=int(xmin.timestamp() * 1000)/1000
        #xmax=int(xmax.timestamp() * 1000)/1000
        print("xmin={v1} xmax={v2}".format(v1=xmin, v2=xmax))
        xmin = mdates.date2num(xmin)
        xmax = mdates.date2num(xmax)
        print("len(posInCuts)", len(posInCuts[0]))
        print("xmin={v1} xmax={v2}".format(v1=xmin, v2=xmax))
        for idx in range(len(posInCuts[0])):
            print("idx=", idx)
            print("xmin={v1} xmax={v2}".format(
                v1=xmin,
                v2=self.df['epoch'].iloc[positionKick[arrposcut[idx]]]))

            rectmin = xmin
            rectmax = self.df['epoch'].iloc[positionKick[arrposcut[idx]]]
            rectmax = rectmax.to_pydatetime()
            rectmax = mdates.date2num(rectmax)
            #rectmax=int(rectmax.timestamp() * 1000)/1000
            #rectmax=mdates.num2date(rectmax)
            width = rectmax - rectmin
            rect = ECERectangle(rectmin,
                                ymin,
                                width,
                                height,
                                color=color,
                                index=1)
            rect2 = ECERectangle(xmin,
                                 ymin,
                                 width,
                                 height,
                                 color=color,
                                 index=2)
            rect.setNext(rect2)
            rect2.setPrev(rect)
            self.ax.add_patch(rect)
            self.ax2.add_patch(rect2)
            self.fig.canvas.draw()
            xmin = self.df['epoch'].iloc[positionKick[arrpostcut1[idx]]]
            xmin = xmin.to_pydatetime()
            xmin = mdates.date2num(xmin)
            #xmin=int(xmin.timestamp() * 1000)/1000
            #xmin=mdates.num2date(xmin)

        rectmin = xmin
        rectmax = xmax
        #rectmax=int(rectmax.timestamp() * 1000)/1000
        width = rectmax - rectmin
        rect = ECERectangle(rectmin, ymin, width, height, color=color, index=1)
        rect2 = ECERectangle(xmin, ymin, width, height, color=color, index=2)
        rect.setNext(rect2)
        rect2.setPrev(rect)
        self.ax.add_patch(rect)
        self.ax2.add_patch(rect2)
        print("xmin={v1} xmax={v2}".format(v1=xmin, v2=xmax))
        self.fig.canvas.draw()

    def getConnection(self, filename):
        """
        get the connection of sqlite given file name
        :param filename:
        :return: sqlite3 connection
        """

        conn = sqlite3.connect(filename)
        return conn

    def readCalibration(self, filename):
        self.dfCal = pd.read_csv(filename)
        print('Results: %s', self.dfCal)
        print('title: %s', self.dfCal['Titles'])
        print('values: %s', self.dfCal['Values'])
        print('ZGain: %s', self.dfCal['Values'][1])
        self.ZOffset = 0
        self.ZGain = 1
        self.YOffset = 2
        self.YGain = 3
        self.XOffset = 4
        self.XGain = 5

    def createCalibrationAction(self):
        image_file = 'square-upload'
        callback = self.toolbar.importCal
        text = "Calibrate"
        tooltip_text = "Calibrate"
        a = self.toolbar.addAction(self.toolbar._icon(image_file + '.png'),
                                   text, callback)
        print("action created")
        self.toolbar._actions[callback] = a
        print("action added to array")

        a.setToolTip(tooltip_text)

    def executeQuery(self, query):
        return None

    def colorChoose(self, r, g, b):
        """
        create a normalized color map give r, g, b in 0-255 scale
        :param r: red
        :param g: green
        :param b: blue
        :return: tuple of color that can be used for matplotlib
        """
        if self.rangeOff(r) or self.rangeOff(g) or self.rangeOff(r):
            return (0, 0, 0)
        return r / 255.0, g / 255.0, b / 255.0

    def rangeOff(self, val):
        return (val > 255) or (val < 0)

    def onpick(self, event):
        print("pick event")
        if isinstance(event.artist, Rectangle):
            patch = event.artist
            # patch.remove()
            self.removedObj = patch
            print('onpick1 patch:', patch.get_path())
        else:
            print(event.artist.get_xdata())
            print(event.artist.get_xdata())
            print(len(event.artist.get_ydata()))
            # self.fig.canvas.draw()

    # def onselect(self, xmin, xmax):
    #     print(xmin)
    #     print(xmax)
    #     width = xmax - xmin
    #     [ymin, ymax] = self.ax.get_ylim()
    #     height = ymax - ymin
    #
    #     rect = matpat.Rectangle((xmin, ymin), width, height,
    #                             fill=True, alpha=0.4,
    #                             color=self.color)
    #     self.ax.add_patch(rect)

    def onclick(self, event):
        if not self.toolbar._actions['zoom'].isChecked(
        ) and event.button == 1:  # left = 1, middle = 2, right = 3
            self.timeTrack = time.time()
            print("clicked {}".format(self.timeTrack))
            print("clicked X: {}".format(event.xdata))
            self.xpos = event.xdata
            # [ymin, ymax] = self.ax.get_ylim()
            # self.ax.annotate('sth', xy=(event.xdata, event.ydata),
            #                  xytext=(event.xdata, ymax),
            #                  arrowprops=dict(facecolor='black', shrink=0.05),)
            # self.fig.canvas.draw()

    def onrelease(self, event):
        if not self.toolbar._actions['zoom'].isChecked() \
                and event.button == 1 and self.isAnnotate:
            #and not self.toolbar._actions['pan'].isChecked() \

            curTime = time.time()
            if (curTime - self.timeTrack) > PRE_DEF_CLICK_TIME:
                print("dragged")
                xmin = self.xpos
                xmax = event.xdata
                width = xmax - xmin
                # print(xmin)
                # print(xmax)
                # print(type(xmin))
                # print(mdates.num2date(xmin))
                # print(mdates.num2date(xmax))
                # print(type(xmax))
                # print(width)
                [ymin, ymax] = self.ax.get_ylim()
                height = ymax - ymin

                #annotation problem temporary
                # print(any(cond))
                self.create_annotation(xmin, xmax)
                # print(height)
                rect = ECERectangle(xmin,
                                    ymin,
                                    width,
                                    height,
                                    color=self.color,
                                    index=1)
                rect2 = ECERectangle(xmin,
                                     ymin,
                                     width,
                                     height,
                                     color=self.color,
                                     index=2)
                # Rectangle((xmin, ymin), width, height,
                #                     fill=True, alpha=0.4,
                #                     color=self.color, picker=True)
                rect.setNext(rect2)
                rect2.setPrev(rect)
                self.ax.add_patch(rect)
                self.ax2.add_patch(rect2)

                # self.ax2.add_patch(rect)
                self.fig.canvas.draw()

    def onpress(self, event):
        # print(event.key())
        print(event.key)
        if event.key == 'r':
            self.annoteText = "Kick"
            self.color = self.colorChoose(255, 0, 0)
        elif event.key == 'b':
            self.annoteText = "Sleep"
            self.color = self.colorChoose(0, 0, 255)
        elif event.key == 'g':
            self.annoteText = "Random"
            self.color = self.colorChoose(0, 255, 0)
        elif event.key == "right":
            print("right pressed")
            self.startX += self.currentDelta
            self.endX += self.currentDelta
            self.ax2.set_xlim(self.startX, self.endX)
            # mask = (self.df["epoch"] >= self.startX) & \
            #        (self.df["epoch"] <= self.endX)
            # self.ax2.plot(self.df.loc[mask, "epoch"],
            #               self.df.loc[mask, "mag"], '#1f77b4')
            self.run()
        elif event.key == "left":
            # TODO check left and right limit
            print("left pressed")
            self.startX -= self.currentDelta
            self.endX -= self.currentDelta
            self.ax2.set_xlim(self.startX, self.endX)
            # mask = (self.df["epoch"] >= self.startX) & \
            #        (self.df["epoch"] <= self.endX)
            # self.ax2.plot(self.df.loc[mask, "epoch"],
            #               self.df.loc[mask, "mag"], '#1f77b4')
            self.run()
        elif event.key == "delete":
            print("delete")
            if self.removedObj is not None:
                if isinstance(self.removedObj, ECERectangle):
                    print("deleting ECERect")
                    rect_min_x = self.removedObj.get_x()
                    rect_max_x = rect_min_x + self.removedObj.get_width()
                    self.remove_annotation(rect_min_x, rect_max_x)
                    ind = self.removedObj.getIndex()
                    self.removedObj.remove()
                    if ind == 1:
                        nextRect = self.removedObj.getNext()
                    else:
                        nextRect = self.removedObj.getPrev()
                    self.removedObj = None
                    # print(type())
                    if nextRect.axes is not None:
                        nextRect.remove()
                    self.fig.canvas.draw()

    def run(self):
        self.fig.canvas.draw()

    def create_annotation(self, xmin, xmax):
        print("Annoated")
        cond = self.get_x_in_ranges(xmin, xmax)
        self.df.loc[cond, 'annotated'] = self.annoteText
        self.df.loc[cond, 'colorHex'] = self.get_color_in_hex()

    def remove_annotation(self, xmin, xmax):
        cond = self.get_x_in_ranges(xmin, xmax)
        self.df.loc[cond, 'annotated'] = " "
        self.df.loc[cond, 'colorHex'] = " "

    def get_x_in_ranges(self, xmin, xmax):
        return (self.df["epoch"] <= mdates.num2date(xmax)) \
               & (self.df["epoch"] >= mdates.num2date(xmin))

    def get_color_in_hex(self):
        return "#{:02X}{:02X}{:02X}".format(int(self.color[0] * 255),
                                            int(self.color[1] * 255),
                                            int(self.color[2] * 255))

    def setSelect(self):
        self.isAnnotate = not self.isAnnotate

    def cursorOnclick(self, event):
        'on button press we will see if the mouse is over us '
        if (self.ax == event.inaxes) and (not self.isAnnotate):
            xdata = event.xdata
            dateclicked = mdates.num2date(xdata)
            self.startX = dateclicked
            dateEnd = dateclicked + self.currentDelta
            self.endX = dateEnd
            # df2,epoch,endDate=self.createBottomGraph(dateclicked)

            # mask = (df2["epoch"] >= dateclicked) & (df2["epoch"] <= endDate)
            # self.ax2.clear()
            # self.ax2.set_ylim(1, 1.1)
            # self.ax2.plot(df2.loc[mask, "epoch"], df2.loc[mask, "mag"])
            mask = (self.df["epoch"] >= dateclicked) & (self.df["epoch"] <=
                                                        dateEnd)
            tX = self.df.loc[mask, "epoch"]
            # print(tX)
            self.ax2.set_xlim(tX.iloc[0], tX.iloc[len(tX) - 1])
            # locator = mdates.SecondLocator(interval=120)
            self.ax2.get_xaxis().set_major_locator(LinearLocator(numticks=12))
            # self.ax2.xaxis.set_major_locator(locator)
            # self.ax2.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M:%S'))

            # self.ax2.relim()
            self.ax2.autoscale_view(True, True, True)
            #
            # x_ticks = np.append(self.ax2.get_xticks(), mdates.date2num(df2.iloc[0,0]))
            # x_ticks = np.append(x_ticks,mdates.date2num(df2.iloc[-1,0]))
            #self.ax2.set_xticks(x_ticks)
            # #self.ax2.tick_params(axis='x', labelsize=8,rotation=45)
            #
            width = mdates.date2num(dateEnd) - xdata
            [ymin, ymax] = self.ax.get_ylim()
            height = ymax - ymin
            if self.rect is not None:
                self.rect.remove()
            self.rect = Rectangle((xdata, ymin),
                                  width,
                                  height,
                                  fill=True,
                                  alpha=0.4,
                                  color=(1, 0, 0),
                                  picker=False)

            self.ax.add_patch(self.rect)

            self.fig.canvas.draw()

    def oncheck(self, label):
        if label == 'valuex':
            self.lx.set_visible(not self.lx.get_visible())
        elif label == 'valuey':
            self.ly.set_visible(not self.ly.get_visible())
        elif label == 'valuez':
            self.lz.set_visible(not self.lz.get_visible())
        elif label == 'mag':
            self.lm.set_visible(not self.lm.get_visible())
        self.fig.canvas.draw()

    def changeScale(self, label):
        index = self.labels.index(label)
        self.currentDelta = self.scaleDeltaArray[index]