# coding=utf-8
# -----------------------------------------import libraries-------------------------------------------------------------

from PySide.QtGui import *
from PySide.QtCore import *
from forms.MainWindow import Ui_MainWindow  # Gui

from  math import *
import numpy as np
import pyqtgraph as pg
import matplotlib

matplotlib.use('Qt4Agg')
matplotlib.rcParams['backend.qt4'] = 'PySide'

from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import (
    FigureCanvasQTAgg as FigureCanvas,
    NavigationToolbar2QT as NavigationToolbar)

from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg  # Graph
import matplotlib.pyplot as plt

from xlwt import Workbook, Formula, easyxf  # work with Excel
import csv

import serial  # RS232
import socket  # Ethernet
import time
import os
import sqlite3  # Database
import pandas as pd  # Pandas structure
import operator
import pickle  # safe dict as bit file
from collections import defaultdict
from scipy.interpolate import InterpolatedUnivariateSpline


# ----------------------------------------------------------------------------------------------------------------------
# ---------------------------------------------mutex--------------------------------------------------------------------
# playback database
waitCondition = QWaitCondition()
mutex = QMutex()
# ttff
waitCondition_ttf = QWaitCondition()
mutex_ttf = QMutex()
# accuracy test
waitCondition_accu = QWaitCondition()
mutex_accu = QMutex()

# ----------------------------------------------------------------------------------------------------------------------
# -----------------------------------------global variables-------------------------------------------------------------
# Map position
TRX = -111.9740722  # top right longitude
TRY = 33.7242558  # top right latitude
BLX = -112.1986053  # bottom left longitude
BLY = 33.6555542  # bottom left latitude

# FIFO variables
FIFO_NMEA = []  # data for parsing
FIFO_POSITION = []  # data for position         / not use
FIFO_SATELLITE = []  # data for satellite        / not use
FIFO_DATABASE = []  # data for database
FIFO_PANDA = []  # data for panda structure  / not use
FIFO_MEMORY = []  # 10 s data memory

# Dictionary
globaListOfNmea = {}  # basic dictionary of nmea's sentence

# Indicate color
Red = ":/work_motive/ledred-icone-7702-16.png"
Yellow = ":/work_motive/ledyellow-icone-8018-16.png"
Green = ":/work_motive/ledgreen-icone-8390-16.png"

# Ttff columns
header = ["Number of measurements", "Number of cycle", " TTFF [ms]", "Position ok/nok", "Number of satellites",
          "2D drms", "Measurements status"]
data_list = []
# Sat columns
header_sat = ["Number of PRN", "SRN [dB]", "Elevace", "Azimut"]
data_list_sat = []
# Accu columns
header_accu = ["Name satellite", " TOW [s] ", "   PR [m]   ", " PR True [m] ", "PR Error [m]"]
data_list_accu = []

# Accu columns
header_accu_result = ["Number of samp.", "NIS", "RMS_PR [m]", " Pass threshold "]
data_list_accu_result = []


# ----------------------------------------------------------------------------------------------------------------------
# -----------------------------------------Main application-------------------------------------------------------------
class MainApp(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainApp, self).__init__(parent)
        self.initList()  # read setting list
        self.setup_Ui(self)  # Variable and modification
        self.setup_GUI_signals()  # Signals
        self.file_menu()

    def file_menu(self):
        self.file_menu = QMenu('&File', self)
        self.file_menu.addSeparator()
        self.file_menu.addAction('&Fast connect', self.menu_connect, Qt.CTRL + Qt.Key_R)
        self.file_menu.addAction('&Disconnect', self.menu_disconnect, Qt.CTRL + Qt.Key_S)
        self.file_menu.addSeparator()
        self.file_menu.addAction('&Connectivity', self.tabWidgetMain1, Qt.CTRL + Qt.Key_1)
        self.file_menu.addAction('&Filtr', self.tabWidgetMain2, Qt.CTRL + Qt.Key_2)
        self.file_menu.addAction('&Universal graph', self.tabWidgetMain3, Qt.CTRL + Qt.Key_3)
        self.file_menu.addAction('&Plot', self.tabWidgetMain4, Qt.CTRL + Qt.Key_4)
        self.file_menu.addAction('&TTFF', self.tabWidgetMain5, Qt.CTRL + Qt.Key_5)
        self.file_menu.addSeparator()
        self.file_menu.addAction('&Quit', self.fileQuit, Qt.CTRL + Qt.Key_Q)
        self.menuBar().addMenu(self.file_menu)

        self.help_menu = QMenu('&Help', self)
        self.menuBar().addSeparator()
        self.menuBar().addMenu(self.help_menu)

        self.help_menu.addAction('&About', self.about)

    def setup_Ui(self, parent):
        super(MainApp, self).setupUi(parent)
        # -----------------------------------object---------------------------------------------------------------------
        self.fileDialog = QFileDialog  # directory browser
        # -----------------------------------thread---------------------------------------------------------------------
        self.connectivity = Connectivity()  # connectivity thread
        self.parsingData = ParsingData()  # parsing thread
        self.database = Database()  # database thread
        self.ttff = TTFF()  # ttff thread
        self.export = Export(None, None)  # ttff thread
        self.interpolators = Interpolators()  # interpolates thread

        self.parsing_run = False  # parsing thread run or not
        self.database_run = False  # database thread run or not
        # -----------------------------------dictionary-----------------------------------------------------------------
        self.fig_dict = {}  # slovnik pro nazev grafu a graf
        self.filtr_dict = {}  # slovnik pro vetu NMEA a barvu / filtr
        self.status_connection = {}  # dictionary for connection, set comport,baudrate,path,port,host name...
        self.color = (Qt.blue, Qt.darkYellow, Qt.darkBlue, Qt.darkGreen, Qt.darkMagenta)  # colors
        # -------------------------------------ttff---------------------------------------------------------------------
        self.table_model = MyTableModel(self, data_list, header)  # table for ttff
        self.tableView_ttff.setModel(self.table_model)
        font = QFont("Calibri", 8)  # set font
        self.tableView_ttff.setFont(font)
        self.tableView_ttff.resizeColumnsToContents()  # resize columns
        self.tableView_ttff.setSortingEnabled(False)  # disable sorting
        self.tabWidgetTTFF.setEnabled(False)  # disable tab FFTT
        self.ttff_timer = QTimer(self)  # timer for rec_time on LCD
        # -------------------------------------accuracy test------------------------------------------------------------

        self.x_accu = []
        self.y_accu = []
        self.pw_accu = pg.PlotWidget(name="Accu")
        self.verticalLayout_accu.addWidget(self.pw_accu)
        self.p1_accu = self.pw_accu.plot(name="Accuracy test", title="Accuracy test", pen=None, symbolBrush=(255, 0, 0),
                                         symbolPen='w')
        self.pw_accu.setTitle("Accuracy test")
        self.pw_accu.setLabel('left', 'Pseoudorange error [m]', units=None)
        self.pw_accu.setLabel('bottom', 'TOW [s]', units=None)
        self.pw_accu.showGrid(x=True, y=True)

        self.num_row_accu = 0
        self.table_accu = MyTableModel(self, data_list_accu, header_accu)  # table for accu
        self.tableView_accu.setModel(self.table_accu)
        font = QFont("Calibri", 8)  # set font
        self.tableView_accu.setFont(font)
        # self.tableView_accu.resizeColumnsToContents()  # resize columns
        self.tableView_accu.setSortingEnabled(False)  # disable sorting

        self.table_accu_result = MyTableModel(self, data_list_accu_result, header_accu_result)  # table for accu
        self.tableView_accu_result.setModel(self.table_accu_result)
        font = QFont("Calibri", 8)  # set font
        self.tableView_accu_result.setFont(font)
        # self.tableView_accu.resizeColumnsToContents()  # resize columns
        self.tableView_accu_result.setSortingEnabled(False)  # disable sorting

        # -------------------------------------plot---------------------------------------------------------------------
        self.matplotlibWidget = MatplotlibWidget(self)  # show graph
        # self.matplotlibWidget.setFixedSize(900, 500)
        # self.verticalLayout_Plot.addWidget(self.matplotlibWidget)

        self.pw_pos = pg.PlotWidget(name="PosGraph")
        self.verticalLayout_Plot.addWidget(self.pw_pos)
        self.p1_pos = self.pw_pos.plot(name="PosGraph", title="PosGraph", pen=None, symbolBrush=(255, 0, 0),
                                       symbolPen='w')
        self.pw_pos.setTitle("Position graph")
        self.pw_pos.setLabel('left', 'Latitude [°]', units=None)
        self.pw_pos.setLabel('bottom', 'Longitude [°]', units=None)
        self.pw_pos.showGrid(x=True, y=True)

        self.pw_polar = pg.PlotWidget(name="PolarGraph")
        self.horizontalLayout_plot.addWidget(self.pw_polar)
        self.p1_polar = self.pw_polar.plot(title="UniGraph", pen=None, symbolBrush=(255, 0, 0), symbolPen='w')
        self.pw_polar.setTitle("Polar graph")
        self.pw_polar.setLabel('left', 'Value', units="")
        self.pw_polar.setLabel('bottom', 'Value', units="")
        self.pw_polar.showGrid(x=True, y=True)
        # Add polar grid lines
        self.pw_polar.addLine(x=0, pen=0.2)
        self.pw_polar.addLine(y=0, pen=0.2)
        for r in range(10, 100, 10):
            circle = pg.QtGui.QGraphicsEllipseItem(-r, -r, r * 2, r * 2)
            circle.setPen(pg.mkPen(0.2))
            self.pw_polar.addItem(circle)
        self.pw_polar.setRange(xRange=(-90, 90), yRange=(-90, 90))
        self.pw_polar.setAspectLocked()

        self.table_sat = MyTableModel(self, data_list_sat, header_sat)  # table for ttff
        self.tableView_plot.setModel(self.table_sat)
        font = QFont("Calibri", 9)  # set font
        self.tableView_plot.setFont(font)
        self.tableView_plot.resizeColumnsToContents()  # resize columns
        self.tableView_plot.setSortingEnabled(False)  # disable sorting

        # ----------------------------------universal plot--------------------------------------------------------------
        sentences = globaListOfNmea.keys()  # sentence as key
        self.comboBox_uni_sentence_x.addItems(sentences)  # show items
        self.comboBox_uni_item_x.setDisabled(True)  # disable
        self.comboBox_uni_sentence_y.addItems(sentences)  # show items
        self.comboBox_uni_item_y.setDisabled(True)  # disable

        self.universalGraph = UniversalGraph(self)  # show graph

        self.pw_uni = pg.PlotWidget(name="UniGraph")
        self.verticalLayout_uni.addWidget(self.pw_uni)
        self.p1_uni = self.pw_uni.plot(title="UniGraph", pen=None, symbolBrush=(255, 0, 0), symbolPen='w')
        self.pw_uni.setTitle("UniGraph")
        self.pw_uni.setLabel('left', 'Value', units="")
        self.pw_uni.setLabel('bottom', 'Value', units="")
        self.pw_uni.showGrid(x=True, y=True)

        # ---------------------------------gui modification-------------------------------------------------------------
        self.lineEdit_filtr_command.setPlaceholderText("e.g. $PHTX1; $PHTX2")  # help in lineEdit filer
        self.itemsForLineEditFiltr()  # prida seznam nmea vet z setting do filtru
        self.comboBox_serial_baudrate.addItems(
            "9600 2400 4800 9600 19200 38400 57600 115200".split())  # baudrate
        self.comboBox_ethernet_port.addItem("50007")
        self.lineEdit_serial_save_file.setPlaceholderText("default local time")
        self.lineEdit_ethernet_save_file.setPlaceholderText("default local time")
        self.lineEdit_database_import.setPlaceholderText("name.db")
        self.comboBox_serial_com_port.addItems("2 1 2 3 4 5 6 7 8 9 10".split())  # com ports
        self.statusBar_modifications(Red, False, "S/E/D", False, None, False, None)  # status bar init

    def setup_GUI_signals(self):
        # interation from GUI
        self.pushButton_connectivity_clear_window.clicked.connect(self.clearConnectivityWindow)
        self.pushButton_filtr_track.clicked.connect(self.filtr_track_last_data)
        self.pushButton_filtr_clear_window.clicked.connect(self.clearFiltrWindow)
        self.pushButton_connectivity_clear_window.clicked.connect(self.clearConnectivityWindow)
        self.pushButton_connectivity_track.clicked.connect(self.connectivity_track_last_data)
        self.pushButton_connectivity_connect.clicked.connect(self.connectConnectivity)
        self.pushButton_connectivity_disconnect.clicked.connect(self.disconnectConnectivity)
        self.toolButton_database_import.clicked.connect(self.database_chooseFile)
        self.toolButton_ethernet_save_file.clicked.connect(self.database_saveFile)
        self.toolButton_serial_save_file.clicked.connect(self.database_saveFile)
        self.pushButton_statusbar_faster_speed.clicked.connect(self.playBackFaster)
        self.pushButton_statusbar_play_pause.clicked.connect(self.playBackPlayPause)
        self.pushButton_statusbar_slower_speed.clicked.connect(self.playBackSlower)
        self.listWidget_filtr_items.itemDoubleClicked.connect(self.lineEdit_Filtr_Command_Add_Item)
        self.lineEdit_filtr_command.textChanged.connect(self.lineEdit_Filtr_Command_Active)
        # new data from source
        self.connect(self.connectivity, SIGNAL("connectivityData(QString)"), self.connectivityData)
        self.connect(self.connectivity, SIGNAL("timer()"), self.timer)
        self.connect(self.parsingData, SIGNAL("writeDatabase()"), self.wakeupDatabase)
        self.connect(self.connectivity, SIGNAL("connectivityData(QString)"), self.showFiltrData)
        # info to connectivity show area
        self.connect(self.connectivity, SIGNAL("connectivityInfoWrong(QString)"), self.connectivityInfoWrong)
        self.connect(self.database, SIGNAL("connectivityInfoWrong(QString)"), self.connectivityInfoWrong)
        self.connect(self, SIGNAL("connectivityInfoWrong(QString)"), self.connectivityInfoWrong)
        self.connect(self.connectivity, SIGNAL("connectivityInfo(QString)"), self.connectivityInfo)
        self.connect(self.database, SIGNAL("connectivityInfo(QString)"), self.connectivityInfo)
        self.connect(self, SIGNAL("connectivityInfo(QString)"), self.connectivityInfo)
        self.connect(self, SIGNAL("cancelConnectivity(QString)"), self.cancelConnectivity)
        # statusbar info
        self.connect(self.connectivity, SIGNAL("statusBarInfo(QString, QString)"), self.statusBarInfo)
        # thread start / stop
        self.connectivity.started.connect(self.started_connectivity)
        self.connectivity.finished.connect(self.finished_connectivity)
        self.parsingData.started.connect(self.started_parsingData)
        self.parsingData.finished.connect(self.finished_parsingData)
        self.database.started.connect(self.started_database)
        self.database.finished.connect(self.finished_database)
        # start parsing thread
        self.connect(self.connectivity, SIGNAL("start_parsing()"), self.parsing_start)
        # disconnect source
        self.connect(self.connectivity, SIGNAL("disconnect()"), self.disconnectConnectivity)
        # Accuracy test
        self.toolButton_accu_import.clicked.connect(self.accu_file)
        self.pushButton_accu_start.clicked.connect(self.accu_start)
        self.pushButton_accu_stop.clicked.connect(self.accu_stop)
        self.pushButton_accu_import.clicked.connect(self.accu_import)
        self.pushButton_accu_reset.clicked.connect(self.accu_reset)
        self.radioButton_accu_sigma_011.clicked.connect(self.set_sigma_011)
        self.radioButton_accu_sigma_015.clicked.connect(self.set_sigma_015)
        self.radioButton_threshold_110.clicked.connect(self.set_threshol_110)
        self.radioButton_threshold_125.clicked.connect(self.set_threshol_125)
        self.connect(self.interpolators, SIGNAL("progressBar(QString, QString, QString)"), self.progressBar_update_accu)
        self.connect(self.interpolators, SIGNAL("importDone()"), self.accu_import_done)
        self.database.database_newSample_accu.connect(self.on_accu_dat_newSample)
        self.interpolators.interpolators_newSample.connect(self.on_accu_newSample)
        self.interpolators.interpolators_result.connect(self.on_accu_result)
        self.tableView_accu.clicked.connect(self.viewClicked)
        self.pushButton_accu_export.clicked.connect(self.acc_export)


        # TTFF test
        self.connect(self.ttff, SIGNAL("reset_device()"), self.reset_device)
        self.connect(self.ttff, SIGNAL("result_cycle(QString, QString, QString, QString, QString, QString)"),
                     self.result_cycle)
        self.connect(self.ttff, SIGNAL("result_final(QString)"), self.result_final)
        self.connect(self.parsingData, SIGNAL("dataToTTFF(QString, QString, QString, QString)"), self.dataToTTFF)
        self.connect(self.ttff, SIGNAL("dataForTTFFstart()"), self.dataForTTFFstart)
        self.connect(self.ttff, SIGNAL("ref_position(QString, QString, QString)"), self.ref_pos_to_pars)
        self.connect(self.parsingData, SIGNAL("ttffTimer_start()"), self.ttffTimer_start)
        self.connect(self.parsingData, SIGNAL("ttffTimer_stop()"), self.ttffTimer_stop)
        self.pushButton_ttff_start.clicked.connect(self.ttff_start)
        self.pushButton_ttff_stop.clicked.connect(self.ttff_stop)
        self.pushButton_ttff_export.clicked.connect(self.ttff_export)
        # plot position
        self.parsingData.newSample_position.connect(self.on_position_newSample)
        self.parsingData.newSample_satellite.connect(self.on_satellite_newSample)
        self.pushButton_plot_start.clicked.connect(self.plot_start)
        self.pushButton_plot_stop.clicked.connect(self.plot_stop)
        self.pushButton_plot_clear.clicked.connect(self.plot_clear)
        self.checkBox_ecef.clicked.connect(self.plot_ecef)
        # Universal graph
        self.pushButton_uni_start.clicked.connect(self.uni_start)
        self.pushButton_uni_stop.clicked.connect(self.uni_stop)
        self.pushButton_uni_reset.clicked.connect(self.uni_reset)
        self.comboBox_uni_sentence_x.currentIndexChanged.connect(self.universal_set_sentence_x)
        self.comboBox_uni_sentence_y.currentIndexChanged.connect(self.universal_set_sentence_y)
        self.comboBox_uni_item_x.currentIndexChanged.connect(self.universal_set_item_x)
        self.comboBox_uni_item_y.currentIndexChanged.connect(self.universal_set_item_y)
        self.parsingData.newSample_uni.connect(self.on_uni_newSample)
        self.database.database_newSample_uni.connect(self.on_uni_newSample)

    # ------------------------------------------------Function----------------------------------------------------------
    def initList(self):
        """ Nacte do promene globaListOfNmea parametry vet z textoveho souboru """
        global globaListOfNmea
        path = os.path.normpath("\setting\Setting_parameters")
        path = os.path.normpath(os.getcwd()) + path
        try:
            with open(path, "r") as f:
                lines_infile = f.readlines()
                for line in lines_infile:
                    if line[0] == "#" or "":
                        continue
                    else:
                        globaListOfNmea[line.split(",")[0]] = line.rstrip()
        except Exception, e:
            self.emit(SIGNAL("connectivityInfoWrong(QString)"), "IinitList error:\n" + str(e))

    def statusBar_modifications(self, set_indication=None, enable_connection=None, set_connection_text=None,
                                enable_path=None, set_path_text=None, enable_playback=None, set_speed_text=None):
        """ Status bar modifications """
        if set_indication is not None:
            if set_indication == Red or Yellow or Green:
                self.statusbar_indicated_status.setPixmap(set_indication)
        if enable_connection is not None:
            self.label_statusbar_choosed_connection.setEnabled(enable_connection)
        if set_connection_text is not None:
            self.label_statusbar_choosed_connection.setText(set_connection_text)
        if enable_path is not None:
            self.label_statusbar_path.setEnabled(enable_path)
        if set_path_text is not None:
            self.label_statusbar_path.setText(str(set_path_text))
        if set_speed_text is not None:
            self.label_statusbar_speed.setText(set_speed_text)
        if enable_playback is not None:
            self.pushButton_statusbar_play_pause.setEnabled(enable_playback)
            self.pushButton_statusbar_slower_speed.setEnabled(enable_playback)
            self.pushButton_statusbar_faster_speed.setEnabled(enable_playback)
            self.label_statusbar_speed.setEnabled(enable_playback)

    def progressBar_update(self, text="", max_value=10, value=0):
        """ Progres bar modification """
        self.label_ttff_measure_number.setText(str(text))
        self.progressBar_ttff.setMaximum(max_value)
        self.progressBar_ttff.setValue(int(value))

    def progressBar_update_accu(self, text="", max_value=10, value=0):
        """ Progres bar modification """
        self.label_accu_bar.setText(str(text))
        self.progressBar_accu.setMaximum(int(max_value))
        self.progressBar_accu.setValue(int(value))

    # ------------------------------------------------Event-------------------------------------------------------------
    def closeEvent(self, ce):
        self.fileQuit()

    def menu_connect(self):
        if self.pushButton_connectivity_connect.isEnabled():
            self.connectConnectivity()

    def menu_disconnect(self):
        if self.pushButton_connectivity_disconnect.isEnabled():
            self.disconnectConnectivity()

    def tabWidgetMain1(self):
        self.tabWidgetMain.setCurrentIndex(0)

    def tabWidgetMain2(self):
        self.tabWidgetMain.setCurrentIndex(1)

    def tabWidgetMain3(self):
        self.tabWidgetMain.setCurrentIndex(2)

    def tabWidgetMain4(self):
        self.tabWidgetMain.setCurrentIndex(3)

    def tabWidgetMain5(self):
        self.tabWidgetMain.setCurrentIndex(4)

    def fileQuit(self):  # event close
        """ Safe close all thread """

        self.ttff_stop()  # stop ttff test
        self.disconnectConnectivity()  # disconnect connectivity
        self.database.exiting_database = True  # safe database
        self.interpolators.exiting = True  # safe database
        time.sleep(1)  # wait on everything

        # check all thread is running
        while self.connectivity.isRunning():
            time.sleep(0.1)
        while self.parsingData.isRunning():
            time.sleep(0.1)
        while self.ttff.isRunning():
            time.sleep(0.1)
        while self.export.isRunning():
            time.sleep(0.1)
        while self.database.isRunning():
            time.sleep(0.1)
        while self.interpolators.isRunning():
            time.sleep(0.1)
        self.close()

    def about(self):
        QMessageBox.about(self, "About", """GNSS prototype graphic show.

Copyright 2016 Martin Homolka.

This program is used for parsing and plotting data from GNSS prototype.""")

    # ------------------------------------------------Qthread-----------------------------------------------------------
    def started_connectivity(self):
        self.tabWidget_select_connection.setDisabled(True)
        return True

    def finished_connectivity(self):
        self.statusBar_modifications(Red, False, "S/E/D", False, "No sourse.", False, "Speed")  # status bar init
        self.tabWidget_select_connection.setDisabled(False)
        self.pushButton_connectivity_connect.setEnabled(True)
        self.pushButton_connectivity_disconnect.setEnabled(False)

    def started_database(self):
        self.database_run = True  # info database is running

    def finished_database(self):
        self.database_run = False  # info database is not running

    def started_parsingData(self):
        self.parsing_run = True  # info parsing is running

    def finished_parsingData(self):
        self.parsing_run = False  # info parsing is not running

    # ------------------------------------------------TTFF--------------------------------------------------------------

    def ttff_start(self):
        # push buttons
        self.pushButton_ttff_start.setEnabled(False)
        self.pushButton_ttff_stop.setEnabled(True)
        self.pushButton_ttff_export.setEnabled(False)
        self.ttff_menu(False)  # set menu

        # init data from user to ttff and parsing
        self.ttff.ref_pos_lat_deg = self.doubleSpinBox_lat_deg.value()  # ref. position latitude
        self.ttff.ref_pos_lat_min = self.doubleSpinBox_lat_min.value()  # ref. position latitude
        self.ttff.ref_pos_lat_sec = self.doubleSpinBox_lat_sec.value()  # ref. position latitude
        self.ttff.ref_pos_lat_side = self.comboBox_lat_side.currentText()  # ref. position latitude
        self.ttff.ref_pos_lon_deg = self.doubleSpinBox_lon_deg.value()  # ref. position longitude
        self.ttff.ref_pos_lon_min = self.doubleSpinBox_lon_min.value()  # ref. position longitude
        self.ttff.ref_pos_lon_sec = self.doubleSpinBox_lon_sec.value()  # ref. position longitude
        self.ttff.ref_pos_lon_side = self.comboBox_lon_side.currentText()  # ref. position longitude
        self.ttff.ref_pos_alt = self.doubleSpinBox_alt.value()  # ref. position altitude

        self.ttff.total_n_measurements = self.spinBox_ttff_numberOfMeasurements.value()  # ref. total measurements
        self.ttff.total_n_cycle = self.spinBox_ttff_numberOfCycles.value()  # ref. total cycle
        self.parsingData.ttff_time_control = self.spinBox_ttff_time_control.value() * 1000  # ref. time control

        # init gui and columns
        global data_list  # clear variable data_list and show area
        data_list = []
        self.table_model = MyTableModel(self, data_list, header)  # clear table for ttff
        self.tableView_ttff.setModel(self.table_model)
        self.progressBar_update("Measurements...", 0, self.ttff.total_n_cycle)  # init progress bar
        self.lcdNumber_ttff.display(0)  # reset rec stamp

        # start
        self.parsingData.ttff_stat = True  # enable data for TTFF from parsing thread
        self.ttff.start()  # start TTFF

    def ttff_stop(self):
        # push buttons
        self.pushButton_ttff_start.setEnabled(True)
        self.pushButton_ttff_stop.setEnabled(False)
        self.pushButton_ttff_export.setEnabled(True)
        self.ttff_menu(True)  # set menu

        # stop
        self.ttff_timer.stop()
        self.parsingData.exiting_ttff = True  # exiting parsing data
        self.ttff.exiting = True  # exiting ttff
        self.wakeupTTFF()

    def reset_device(self):
        self.connectivity.send_to_source = True  # reset device, one shot

    def dataForTTFFstart(self):
        self.parsingData.ttff_stat = True  # enable data for TTFF from parsing thread

    def ref_pos_to_pars(self, lat, lon, alt):
        self.parsingData.ref_pos_lat = float(lat)
        self.parsingData.ref_pos_lon = float(lon)
        self.parsingData.ref_pos_alt = float(alt)

    def result_cycle(self, number_measurements, number_cycle, ttff, position_stat, num_of_sat, rms2D):
        # add data to columns
        data_list.append((number_measurements, number_cycle, ttff, position_stat, num_of_sat, rms2D, ""))

        # show data
        self.table_model = MyTableModel(self, data_list, header)  # table for ttff
        self.tableView_ttff.setModel(self.table_model)
        self.progressBar_update("Measurements number: {}".format(str(number_measurements)), self.ttff.total_n_cycle,
                                number_cycle)

    def result_final(self, stat):
        """ Evaluation TTFF ok/continue/nok/break """
        if str(stat) == "ok":  # if test ok
            self.parsingData.ttff_stat = False  # disable data for ttff in parsing thread
            data_list.append(("", "", "", "", "", "", "Test successful."))  # result to data list
            self.progressBar_update("Test completed.", 10, 10)  # ttff bar graph
        elif str(stat) == "continue":  # test continue
            data_list.append(("", "", "", "", "", "", "Test continue."))
            self.parsingData.ttff_stat = True
            self.progressBar_update("Measurements continue.", 0, 10)
        elif str(stat) == "nok":  # test fail
            self.parsingData.ttff_stat = False
            data_list.append(("", "", "", "", "", "", "Test fail."))
            self.progressBar_update("Measurements close.", 10, 10)
        else:  # test fail
            data_list.append(("", "", "", "", "", "", "Test break."))
            self.progressBar_update("Measurements closed.", 10, 0)

        # show data
        self.table_model = MyTableModel(self, data_list, header)  # table for ttff
        self.tableView_ttff.setModel(self.table_model)

    def dataToTTFF(self, ttff, position_stat, num_of_sat, rms2D):
        """ Data for result to ttff thread """
        self.ttff.ttff = int(ttff)
        self.ttff.num_of_sat = int(num_of_sat)
        self.ttff.rms2D = float(rms2D)

        if str(position_stat) == "ok":
            self.ttff.position = True
        else:
            self.ttff.position = False
        self.wakeupTTFF()

    def ttff_export(self):
        """ Export tab to excel or cv with setting path """
        file_name = self.fileDialog.getSaveFileName(self, "Export TTFF", "", "Excel (*.xls)")
        self.export = Export(header, data_list)
        self.export.name = (str(file_name[0]))
        self.export.run()

    def ttffTimer_start(self):
        """ Start and update lcd in ttff by rec_time, check every 500 ms"""
        self.ttff_timer = QTimer(self)  # timer for rec_time on LCD
        self.ttff_timer.timeout.connect(self.update_lcd)  # LCD update (rec_time)
        self.ttff_timer.start(500)

    def ttffTimer_stop(self):
        """ Stop timer"""
        self.ttff_timer.stop()

    def update_lcd(self):
        """ Update lcd in ttff by rec_time """
        self.lcdNumber_ttff.display(int(self.parsingData.rec_time) / 1000)

    def ttff_menu(self, bol):
        self.spinBox_ttff_numberOfCycles.setEnabled(bol)
        self.spinBox_ttff_time_control.setEnabled(bol)
        self.spinBox_ttff_numberOfMeasurements.setEnabled(bol)
        self.doubleSpinBox_lat_deg.setEnabled(bol)
        self.doubleSpinBox_lat_min.setEnabled(bol)
        self.doubleSpinBox_lat_sec.setEnabled(bol)
        self.comboBox_lat_side.setEnabled(bol)
        self.doubleSpinBox_lon_deg.setEnabled(bol)
        self.doubleSpinBox_lon_min.setEnabled(bol)
        self.doubleSpinBox_lon_sec.setEnabled(bol)
        self.comboBox_lon_side.setEnabled(bol)
        self.doubleSpinBox_alt.setEnabled(bol)

    # ------------------------------------------------Accuracy test-----------------------------------------------------

    def on_accu_dat_newSample(self, multi_dic):
        self.interpolators.rec_data = multi_dic
        self.wakeupAccu()

    def on_accu_newSample(self, multi_dic):
        # tab columns
        data = []
        sat_tup = []
        tow = []
        pr = []
        pr_true = []
        pr_error = []
        for sat in multi_dic:
            tow_list = multi_dic[sat][0]
            pr_list = multi_dic[sat][1]
            pr_true_list = multi_dic[sat][2]
            pr_error_list = multi_dic[sat][3]
            sat_tup.append(str(sat))
            tow.append(str(tow_list[len(tow_list) - 1]))
            pr.append(str(pr_list[len(tow_list) - 1]))
            pr_true.append(str(pr_true_list[len(tow_list) - 1]))
            pr_error.append(str(pr_error_list[len(tow_list) - 1]))
        data = (zip(sat_tup, tow, pr, pr_true, pr_error))

        self.table_accu = MyTableModel(self, data, header_accu)  # table for
        self.tableView_accu.setModel(self.table_accu)

        try:
            self.x_accu.append(data[self.num_row_accu][1])
            self.y_accu.append(data[self.num_row_accu][4])
            if len(self.x_accu) > 100:
                self.x_accu.pop(0)
                self.y_accu.pop(0)
        except:
            pass

        label = str(data[self.num_row_accu][0]) + ' pseoudorange error [m]'
        self.pw_accu.setLabel('left', label, units=None)
        self.p1_accu.setData(x=self.x_accu, y=self.y_accu)

    def on_accu_result(self):

        self.table_accu_result = MyTableModel(self, data_list_accu_result, header_accu_result)  # table for accu
        self.tableView_accu_result.setModel(self.table_accu_result)

    def accu_start(self):
        self.pushButton_accu_start.setEnabled(False)
        self.pushButton_accu_stop.setEnabled(True)
        self.pushButton_accu_export.setEnabled(False)
        self.spinBox_accu.setEnabled(False)
        self.interpolators.exiting = False
        self.set_smooth_accu()
        self.set_accu_max_samples()
        self.interpolators.start()
        value = self.spinBox_accu.value()
        self.database.timebef_user = int(value)
        self.database.ps_range_query = True

    def accu_stop(self):
        self.doubleSpinBox_accu_smooth.setEnabled(True)
        self.spinBox_accu.setEnabled(True)
        self.spinBox_accu_m.setEnabled(True)
        self.pushButton_accu_start.setEnabled(True)
        self.pushButton_accu_stop.setEnabled(False)
        self.pushButton_accu_export.setEnabled(True)
        self.database.ps_range_query = False
        self.interpolators.exiting = True

    def accu_reset(self):
        self.toolButton_accu_import.setEnabled(True)
        self.doubleSpinBox_accu_smooth.setEnabled(True)
        self.spinBox_accu.setEnabled(True)
        self.spinBox_accu_m.setEnabled(True)
        self.pushButton_accu_import.setEnabled(False)
        self.pushButton_accu_start.setEnabled(False)
        self.pushButton_accu_stop.setEnabled(False)
        self.pushButton_accu_export.setEnabled(True)
        self.spinBox_accu.setEnabled(False)
        self.lineEdit_accu_import.setText("")
        self.progressBar_update_accu("Progress", 10, 0)

        self.interpolators.init_reset()
        self.interpolators.exiting = True
        self.wakeupAccu()
        self.interpolators.import_done = False
        self.interpolators.file_stat = True
        self.database.ps_range_query = False

    def accu_import(self):
        self.toolButton_accu_import.setEnabled(False)
        self.pushButton_accu_import.setEnabled(False)
        self.progressBar_update_accu("Start import...", 0, 0)
        self.interpolators.start()

    def accu_file(self):
        file_name = self.fileDialog.getOpenFileName(self, "Import file", "", "Interpolators (*.pickle);;"
                                                                             "CVS file (*.csv);;"
                                                                             "All files (*.*)")
        self.lineEdit_accu_import.setText(str(file_name[0]))
        if file_name[1] == "Interpolators (*.pickle)":
            self.interpolators.file_stat = False
            self.interpolators.file_interpolars = str(file_name[0])
            self.pushButton_accu_import.setEnabled(True)
        elif file_name[1] == "CVS file (*.csv)":
            self.interpolators.file_stat = True
            self.interpolators.file_csv = str(file_name[0])
            self.pushButton_accu_import.setEnabled(True)
        elif file_name[1] == "All files (*.*)":
            fil_typ = str(file_name[0])
            fil_typ = fil_typ.split(".")
            if fil_typ[1] == "csv":
                self.interpolators.file_stat = True
                self.interpolators.file_csv = str(file_name[0])
                self.pushButton_accu_import.setEnabled(True)
            elif fil_typ[1] == "pickle":
                self.interpolators.file_stat = True
                self.interpolators.file_csv = str(file_name[0])
                self.pushButton_accu_import.setEnabled(True)
            else:
                pass
        else:
            pass

    def accu_import_done(self):
        self.pushButton_accu_start.setEnabled(True)
        self.spinBox_accu.setEnabled(True)
        self.interpolators.import_done = True

    def viewClicked(self, clickedIndex):
        row = clickedIndex.row()
        self.num_row_accu = row
        self.x_accu = []
        self.y_accu = []
        self.p1_accu.setData(x=self.x_accu, y=self.y_accu)

        model = clickedIndex.model()
        columnsTotal = model.columnCount(None)
        for i in range(columnsTotal):
            self.tableView_accu.selectRow(row)

    def set_sigma_011(self):
        if  self.radioButton_accu_sigma_011.isChecked():
            self.radioButton_accu_sigma_015.setChecked(False)
            self.interpolators.sigma_noise_used = True
        else:
            self.radioButton_accu_sigma_011.setChecked(True)

    def set_sigma_015(self):
        if  self.radioButton_accu_sigma_015.isChecked():
            self.radioButton_accu_sigma_011.setChecked(False)
            self.interpolators.sigma_noise_used = False
        else:
            self.radioButton_accu_sigma_015.setChecked(True)

    def set_threshol_110(self):
        if  self.radioButton_threshold_110.isChecked():
            self.radioButton_threshold_125.setChecked(False)
            self.interpolators.threshold_used = False
        else:
            self.radioButton_threshold_110.setChecked(True)

    def set_threshol_125(self):
        if  self.radioButton_threshold_125.isChecked():
            self.radioButton_threshold_110.setChecked(False)
            self.interpolators.threshold_used = False
        else:
            self.radioButton_threshold_125.setChecked(True)

    def set_smooth_accu(self):
        value = self.doubleSpinBox_accu_smooth.value()
        if value == 0:
            value = 10
            self.doubleSpinBox_accu_smooth.setValue(value)
        else:
            pass
        self.interpolators.smooth_interval = value
        self.doubleSpinBox_accu_smooth.setEnabled(False)

    def set_accu_max_samples(self):
        self.interpolators.M_max = self.spinBox_accu_m.value()
        self.spinBox_accu_m.setEnabled(False)
        
    def acc_export(self):
        """ Export tab to excel or cv with setting path """
        file_name = self.fileDialog.getSaveFileName(self, "Export Accuracy test", "", "Excel (*.xls)")
        self.export = Export(header_accu_result, data_list_accu_result)
        self.export.name = (str(file_name[0]))
        self.export.run()

    # ------------------------------------------------Mutex-------------------------------------------------------------

    def wakeupDatabase(self):
        """ Pass mutex in database """
        waitCondition.wakeOne()

    def wakeupTTFF(self):
        """ Pass mutex in TTFF """
        waitCondition_ttf.wakeOne()

    def wakeupAccu(self):
        """ Pass mutex in Accuracy test """
        waitCondition_accu.wakeOne()

    # ------------------------------------------------Filtr-------------------------------------------------------------

    def itemsForLineEditFiltr(self):
        """ Projde setting parameters a preda seznam nmea vet do listu a priradi do slovniku [nmea veta] = [color]  """
        path = os.path.normpath("\setting\Setting_parameters")
        path = os.path.normpath(os.getcwd()) + path
        infile = open(path, "r")
        lines_infile = infile.readlines()  # Read Setting_parameters.txt
        infile.close()
        i = 0
        for line in lines_infile:
            if line[0] == "#" or "":  # Skip not important information
                continue
            line = line.rstrip()  # Parsing
            line = line.split(",")
            if line[0] == "$PHDBG":
                self.filtr_dict[line[0]] = Qt.red  # Debug messages are red
            else:
                self.filtr_dict[line[0]] = self.color[i]  # Other messages are colored

            self.listWidget_filtr_items.addItem(line[0])
            if i == (len(self.color) - 1):  # Colors repeat
                i = 0
            else:
                i += 1

    def lineEdit_Filtr_Command_Active(self):
        """ Neaktivni """
        self.checkBox_filtr_accept.setChecked(False)

    def lineEdit_Filtr_Command_Add_Item(self, item):
        """ item to filtr-lineEdit """

        itemText = item.text()
        comanLineText = self.lineEdit_filtr_command.text()
        comanLineText = comanLineText.replace(" ", "")

        if comanLineText == "":
            comanLineText = (comanLineText + itemText + ";")
        elif itemText in comanLineText:  # in line
            comanLineText = comanLineText.replace(itemText + ";", "")
        elif comanLineText[len(comanLineText) - 1] != ";":
            comanLineText = (comanLineText + ";" + itemText + ";")
        else:
            comanLineText = (comanLineText + itemText + ";")

        self.lineEdit_filtr_command.setText(comanLineText)
        self.checkBox_filtr_accept.setChecked(True)

    def showFiltrData(self, text):
        """ Data from source, filtr and color """

        comandLineText = self.lineEdit_filtr_command.text()
        comandLineText = comandLineText.upper()

        if self.checkBox_filtr_show.isChecked():
            if self.checkBox_filtr_accept.isChecked() and comandLineText == "":
                self.textEdit_filtr_show.setTextColor(Qt.black)
                self.textEdit_filtr_show.append(text)
            elif self.checkBox_filtr_accept.isChecked() and comandLineText != "":
                items = comandLineText.split(";")
                for item in items:
                    item = (str(item)).strip()
                    if item == "":
                        continue
                    if item in text:
                        if self.checkBox_filtr_different_colors.isChecked():
                            self.textEdit_filtr_show.setTextColor(self.filtr_dict[item])
                        self.textEdit_filtr_show.append(text)
            else:
                self.textEdit_filtr_show.setTextColor(Qt.black)
                self.textEdit_filtr_show.append(text)

    def filtr_track_last_data(self):
        """ Cursor on end show area"""
        self.textEdit_filtr_show.verticalScrollBar().setValue(
            self.textEdit_filtr_show.verticalScrollBar().maximum())

    def clearFiltrWindow(self):
        """ Clear show area """
        self.textEdit_filtr_show.clear()

    # ------------------------------------------------Connectivity------------------------------------------------------

    def connectConnectivity(self):
        """ Sourse choose from serial port / ethernet / database """
        if self.parsing_run is True:  # wait if parsing is still running
            self.cancelConnectivity()
        if self.database_run is True:  # wait if database is still running
            self.cancelConnectivity()
        else:  # init connectivity
            self.connectivity.exiting = False  # enable connectivity
            self.database.exiting_database = False  # enable database
            self.database.init_ready = False  # database init status
            self.pushButton_connectivity_connect.setDisabled(True)
            self.pushButton_connectivity_disconnect.setDisabled(False)
            # Serial port
            if self.tabWidget_select_connection.currentWidget() == self.tab_serial:
                self.tabWidgetTTFF.setEnabled(True)  # enable tab TTFF
                self.status_connection["Connection"] = "S"  # set status
                self.parsingData.source = self.status_connection["Connection"]  # set status
                if self.setComport() and self.setBaudrate():  # check Baudrate, COM port - TRUE
                    self.emit(SIGNAL("connectivityInfo(QString)"),
                              "Conecting to serial...\n")  # info to area
                    self.database.path_database = str(self.lineEdit_serial_save_file.text())  # save file for database
                    self.connectivity.init_connection = self.status_connection  # init data to connectivity thread
                    self.database.start()  # start database thread
                    while not self.database.init_ready:  # wait on database
                        time.sleep(0.1)
                    self.connectivity.start()  # start connectivity thread
                    self.statusBar_modifications(set_indication=Yellow,  # set status bar
                                                 set_connection_text=self.status_connection["Connection"],
                                                 set_path_text="COM" + str(self.status_connection["Comport"]),
                                                 enable_connection=True,
                                                 enable_path=True
                                                 )
            # Ethernet
            elif self.tabWidget_select_connection.currentWidget() == self.tab_ethernet:
                self.tabWidgetTTFF.setEnabled(True)  # enable tab TTFF
                self.status_connection["Connection"] = "E"  # set status
                self.parsingData.source = self.status_connection["Connection"]  # set status
                if self.hostName() and self.portEthernet():  # check (host name, port) TRUE
                    self.emit(SIGNAL("connectivityInfo(QString)"),
                              "Conecting to Ethernet...\n")  # info to show area
                    self.database.path_database = str(self.lineEdit_ethernet_save_file.text())  # save file for data
                    self.connectivity.init_connection = self.status_connection  # init data to connectivity thread
                    self.database.start()  # start database thread
                    while not self.database.init_ready:  # wait on database
                        time.sleep(0.1)
                    self.connectivity.start()  # start serial thread
                    self.statusBar_modifications(set_indication=Yellow,
                                                 set_connection_text=self.status_connection["Connection"],
                                                 set_path_text=self.status_connection["Hostname"],
                                                 enable_connection=True,
                                                 enable_path=True
                                                 )
            # Database
            elif self.tabWidget_select_connection.currentWidget() == self.tab_database:
                self.tabWidgetTTFF.setEnabled(False)  # disable tab TTFF
                self.pushButton_statusbar_play_pause.setChecked(True)  # play button
                self.emit(SIGNAL("connectivityInfo(QString)"),
                          "Conecting to database...\n")  # info to area
                self.status_connection["Connection"] = "D"  # set status
                self.parsingData.source = self.status_connection["Connection"]  # set status
                path = self.lineEdit_database_import.text()  # set path
                if path != "":
                    self.status_connection["Path_database"] = path  # set path
                    self.connectivity.init_connection = self.status_connection  # init data to connectivity thread
                    self.connectivity.speed = 1.0  # normal speed
                    self.connectivity.start()  # run serial thread
                    self.statusBar_modifications(set_indication=Yellow,  # set status bar
                                                 set_connection_text=self.status_connection["Connection"],
                                                 set_path_text=self.status_connection["Path_database"],
                                                 set_speed_text="Speed 1.0x",
                                                 enable_connection=True,
                                                 enable_path=True,
                                                 enable_playback=True
                                                 )
                else:  # cancel connectivity
                    self.emit(SIGNAL("connectivityInfoWrong(QString)"), "Error select and import database...\n")
                    self.emit(SIGNAL("cancelConnectivity()"))
            else:  # cancel connectivity
                self.emit(SIGNAL("connectivityInfoWrong(QString)"), "Error select source...\n")
                self.emit(SIGNAL("cancelConnectivity()"))

    def disconnectConnectivity(self):
        """ Disconnect connectivity """
        # the initial state of clicks, connectivity in not tun
        if self.pushButton_connectivity_connect.isEnabled() and self.connectivity.exiting is False:
            self.pushButton_connectivity_disconnect.setDisabled(True)  # buttons disable
            self.emit(SIGNAL("connectivityInfoWrong(QString)"), "Not connected yet...\n")  # info to gui
        # connectivity is run
        if not self.pushButton_connectivity_connect.isEnabled():
            self.connectivity.exiting = True  # exiting connectivity
            self.pushButton_connectivity_connect.setEnabled(False)  # buttons disable
            self.pushButton_connectivity_disconnect.setEnabled(False)  # buttons disable
            self.pushButton_statusbar_play_pause.setChecked(False)  # buttons disable
            self.lineEdit_serial_save_file.setText(None)  # init line edit
            self.lineEdit_ethernet_save_file.setText(None)  # init line edit
            self.tabWidgetTTFF.setEnabled(False)  # disable tab TTFF
            # stop ttff test
            if self.ttff.isRunning():
                self.ttff_stop()
                self.emit(SIGNAL("connectivityInfoWrong(QString)"), "FFTT test break...\n")

    def cancelConnectivity(self):
        """ Cancel connectivity, basic status """
        self.statusBar_modifications(Red, False, "S/E/D", False, "No sourse.", False, "Speed")  # status bar init
        self.pushButton_statusbar_play_pause.setChecked(False)
        self.tabWidget_select_connection.setDisabled(False)
        self.pushButton_connectivity_connect.setEnabled(True)
        self.pushButton_connectivity_disconnect.setEnabled(False)

    # Init data
    def setBaudrate(self):
        """ Import baudrate from GUI """
        baudrate_local = self.comboBox_serial_baudrate.currentText()
        try:
            self.status_connection["Baudrate"] = int(baudrate_local)
            return True
        except Exception, e:
            self.emit(SIGNAL("connectivityInfoWrong(QString)"),
                      "Error BAUDRATE is wrong:\n" + str(e) + "\n")  # info to textEdit_connectivity_show area
            self.emit(SIGNAL("cancelConnectivity()"))
            return False

    def setComport(self):
        """ Import comport from GUI """
        comport_local = self.comboBox_serial_com_port.currentText()
        try:
            self.status_connection["Comport"] = int(comport_local)
            return True
        except Exception, e:
            self.emit(SIGNAL("connectivityInfoWrong(QString)"),
                      "Error COM PORT is wrong!\n" + str(e) + "\n")  # info to textEdit_connectivity_show area
            self.emit(SIGNAL("cancelConnectivity()"))
            return False

    def hostName(self):
        """ Input data for ethernet from gui """
        hostname_local = self.comboBox_ethernet_host_name.currentText()
        if hostname_local == "":
            hostname_local = "localhost"
        try:
            self.status_connection["Hostname"] = str(hostname_local)
            return True
        except Exception, e:
            self.emit(SIGNAL("connectivityInfoWrong(QString)"),
                      "Error HOST NAME is wrong!\n" + str(e) + "\n")  # info to textEdit_connectivity_show area
            self.emit(SIGNAL("cancelConnectivity()"))
            return False

    def portEthernet(self):
        """ Input data for ethernet from gui """
        port_local = self.comboBox_ethernet_port.currentText()
        try:
            self.status_connection["Port"] = int(port_local)
            return True
        except Exception, e:
            self.emit(SIGNAL("connectivityInfoWrong(QString)"),
                      "Error PORT is wrong!\n" + str(e) + "\n")  # info to textEdit_connectivity_show area
            self.emit(SIGNAL("cancelConnectivity()"))
            return False

    def parsing_start(self):
        """ Start parsing """
        self.parsingData.start()

    def database_chooseFile(self):
        """ Widget for import file from database """
        file_name = self.fileDialog.getOpenFileName(self, "Import database", "", "Database (*.db);;All file (*.*)")
        self.lineEdit_database_import.setText(str(file_name[0]))

    def database_saveFile(self):
        """ Widget for set database's save file """
        file_name = self.fileDialog.getSaveFileName(self, "Export database", "", "Database (*.db)")
        self.lineEdit_ethernet_save_file.setText(str(file_name[0]))
        self.lineEdit_serial_save_file.setText(str(file_name[0]))

    # connectivity show area
    def connectivityData(self, text):
        """ Show data to show area, color black """
        if self.checkBox_connectivity_show_accept.isChecked():
            self.textEdit_connectivity_show.setTextColor(Qt.black)
            self.textEdit_connectivity_show.append(text)

    def connectivityInfoWrong(self, text):
        """ Show data to show area, color red """
        self.textEdit_connectivity_show.setTextColor(Qt.red)
        self.textEdit_connectivity_show.append(text)
        self.textEdit_connectivity_show.setTextColor(Qt.black)  # next color will be back

    def connectivityInfo(self, text):
        """ Show data to show area, color darkGreen """
        self.textEdit_connectivity_show.setTextColor(Qt.darkGreen)
        self.textEdit_connectivity_show.append(text)
        self.textEdit_connectivity_show.setTextColor(Qt.black)  # next color will be back

    def clearConnectivityWindow(self):
        """ Clear show area """
        self.textEdit_connectivity_show.clear()

    def connectivity_track_last_data(self):
        """ Cursor on end show area """
        self.textEdit_connectivity_show.verticalScrollBar().setValue(
            self.textEdit_connectivity_show.verticalScrollBar().maximum())

    # speed playback database
    def timer(self):
        """ Timer for speed in playback database  """
        if self.connectivity.current_timer:  # delete timer
            self.connectivity.current_timer.stop()
            self.connectivity.current_timer.deleteLater()
        self.connectivity.current_timer = QTimer()  # new timer
        self.connectivity.current_timer.timeout.connect(self.wakeupDatabase)
        self.connectivity.current_timer.setSingleShot(True)
        self.connectivity.current_timer.start(float(self.connectivity.rest))  # set delay

    def playBackFaster(self):
        """ Faster speed for playback database"""
        if self.connectivity.speed < 16:  # max speed
            self.connectivity.speed *= 2.0  # set speed *2
            self.wakeupDatabase()  # immediate change
            self.connectivity.current_timer.start(float(self.connectivity.rest))  # set delay
            self.pushButton_statusbar_play_pause.setChecked(True)  # play button
        self.label_statusbar_speed.setText("Speed: {}x".format(self.connectivity.speed))  # info to gui

    def playBackSlower(self):
        """ Slower speed for playback database"""
        if self.connectivity.speed > 0.125:  # min speed
            self.connectivity.speed /= 2.0  # set speed /2
            self.wakeupDatabase()  # immediate change
            self.connectivity.current_timer.start(float(self.connectivity.rest))  # set delay
            self.pushButton_statusbar_play_pause.setChecked(True)  # play button
        self.label_statusbar_speed.setText("Speed: {}x".format(self.connectivity.speed))  # info to gui

    def playBackPlayPause(self):
        """ Play/pause speed for playback database"""
        if not self.pushButton_statusbar_play_pause.isChecked():
            self.pushButton_statusbar_play_pause.setChecked(False)
            self.connectivity.current_timer.stop()
        else:
            self.pushButton_statusbar_play_pause.setChecked(True)
            self.connectivity.current_timer.start(float(self.connectivity.rest))  # set delay

    # status bar
    def statusBarInfo(self):
        """ Set status bar from threads """
        self.statusBar_modifications(set_indication=Green)

    # ------------------------------------------------plot--------------------------------------------------------------

    def on_position_newSample(self, multi_dic):
        self.matplotlibWidget.x.append(multi_dic["Longitude"])
        self.matplotlibWidget.y.append(multi_dic["Latitude"])
        if len(self.matplotlibWidget.x) > 1000:
            self.matplotlibWidget.x.pop(0)
            self.matplotlibWidget.y.pop(0)
        self.p1_pos.setData(x=self.matplotlibWidget.x, y=self.matplotlibWidget.y)
        self.label_latitude.setText(str(multi_dic["Latitude"]))
        self.label_longtitude.setText(str(multi_dic["Longitude"]))
        self.label_altitude.setText(str(multi_dic["Altitude"]))

        # if self.matplotlibWidget.background_position is None:
        #    self.matplotlibWidget.background_position = (
        #        self.matplotlibWidget.figure.canvas.copy_from_bbox(self.matplotlibWidget.axis.bbox))

        # if self.tabWidgetMain.currentIndex() == 3:
        #    self.matplotlibWidget.figure.canvas.restore_region(self.matplotlibWidget.background_position)
        #    self.matplotlibWidget.points.set_data(self.matplotlibWidget.x, self.matplotlibWidget.y)
        #    self.matplotlibWidget.axis.draw_artist(self.matplotlibWidget.points)
        #    self.matplotlibWidget.figure.canvas.blit(self.matplotlibWidget.axis.bbox)

    def on_satellite_newSample(self, multi_dic):
        # if self.matplotlibWidget.background_satellite is None:
        #    self.matplotlibWidget.background_satellite = (
        #        self.matplotlibWidget.figure.canvas.copy_from_bbox(self.matplotlibWidget.axis_satellite.bbox))
        self.matplotlibWidget.sat_el_1 = (multi_dic["Elevation_first"])
        self.matplotlibWidget.sat_az_1 = (multi_dic["Azimut_first"])
        self.matplotlibWidget.sat_el_2 = (multi_dic["Elevation_second"])
        self.matplotlibWidget.sat_az_2 = (multi_dic["Azimut_second"])
        self.matplotlibWidget.sat_el_3 = (multi_dic["Elevation_third"])
        self.matplotlibWidget.sat_az_3 = (multi_dic["Azimut_third"])
        self.matplotlibWidget.sat_el_4 = (multi_dic["Elevation_fourth"])
        self.matplotlibWidget.sat_az_4 = (multi_dic["Azimut_fourth"])
        sat_data_el = [self.matplotlibWidget.sat_el_1, self.matplotlibWidget.sat_el_2, self.matplotlibWidget.sat_el_3,
                       self.matplotlibWidget.sat_el_4]
        sat_data_az = [self.matplotlibWidget.sat_az_1, self.matplotlibWidget.sat_az_2, self.matplotlibWidget.sat_az_3,
                       self.matplotlibWidget.sat_az_4]
        sat_data_prn = [multi_dic["PRNNumber_first"], multi_dic["PRNNumber_second"], multi_dic["PRNNumber_third"],
                        multi_dic["PRNNumber_fourth"]]
        sat_data_srn = [multi_dic["SNR_first"], multi_dic["SNR_second"], multi_dic["SNR_third"],
                        multi_dic["SNR_fourth"]]
        for i in range(4):
            if sat_data_el[i] == "0" and sat_data_az[i] == "0" and sat_data_prn[i] == "0" and sat_data_srn[i] == "0":
                continue
            self.matplotlibWidget.sat_el.append(sat_data_el[i])
            self.matplotlibWidget.sat_az.append(sat_data_az[i])
            self.matplotlibWidget.sat_prn.append(sat_data_prn[i])
            self.matplotlibWidget.sat_srn.append(sat_data_srn[i])

        if multi_dic["Messagenumber"] == multi_dic["TotalNumberOfMessages"]:
            #    if self.tabWidgetMain.currentIndex() == 3:
            #        self.matplotlibWidget.figure.canvas.restore_region(self.matplotlibWidget.background_satellite)
            #        self.matplotlibWidget.points_satellite.set_data(
            #            self.matplotlibWidget.sat_el, self.matplotlibWidget.sat_az)
            #        self.matplotlibWidget.axis_satellite.draw_artist(self.matplotlibWidget.points_satellite)
            #        self.matplotlibWidget.figure.canvas.blit(self.matplotlibWidget.axis_satellite.bbox)
            x = []
            y = []
            for i in range(len(self.matplotlibWidget.sat_el)):
                if float(self.matplotlibWidget.sat_el[i]) == 0:
                    continue
                if float(self.matplotlibWidget.sat_az[i]) == 0:
                    continue
                x.append((float(self.matplotlibWidget.sat_el[i])) * np.cos(float(self.matplotlibWidget.sat_az[i])))
                y.append((float(self.matplotlibWidget.sat_el[i])) * np.sin(float(self.matplotlibWidget.sat_az[i])))

                # text = pg.TextItem(str(self.matplotlibWidget.sat_prn[i]))
                # self.pw_polar.addItem(text)
                # text.setPos(x_, y_)

            self.p1_polar.setData(x=x, y=y)

            data = zip(self.matplotlibWidget.sat_prn, self.matplotlibWidget.sat_srn, self.matplotlibWidget.sat_el,
                       self.matplotlibWidget.sat_az)
            self.table_sat = MyTableModel(self, data, header_sat)  # table for ttff
            self.tableView_plot.setModel(self.table_sat)
            self.tableView_plot.resizeColumnsToContents()  # resize columns

            self.matplotlibWidget.sat_el = []
            self.matplotlibWidget.sat_az = []
            self.matplotlibWidget.sat_prn = []
            self.matplotlibWidget.sat_srn = []

    def plot_stop(self):
        self.parsingData.graph_stat = False
        self.pushButton_plot_stop.setEnabled(False)
        self.pushButton_plot_start.setEnabled(True)
        self.pushButton_plot_clear.setEnabled(False)

    def plot_start(self):
        self.parsingData.graph_stat = True
        self.pushButton_plot_stop.setEnabled(True)
        self.pushButton_plot_start.setEnabled(False)
        self.pushButton_plot_clear.setEnabled(True)

    def plot_clear(self):
        self.matplotlibWidget.sat_el = []
        self.matplotlibWidget.sat_az = []
        self.matplotlibWidget.x = []
        self.matplotlibWidget.y = []
        self.p1_polar.setData()
        self.p1_pos.setData(x=self.matplotlibWidget.x, y=self.matplotlibWidget.y)

        # if arg == 3:
        #    self.matplotlibWidget.canvas.draw()
        #    self.matplotlibWidget.canvas.draw_idle()
        #    print(self.tabWidgetMain.currentWidget())

    def plot_ecef(self):
        if self.checkBox_ecef.isChecked():
            self.parsingData.ecef = True
        else:
            self.parsingData.ecef = False

    # ------------------------------------------------universal graph---------------------------------------------------
    def universal_set_sentence_x(self):
        """ Set comboBox x"""
        index = self.comboBox_uni_sentence_x.currentIndex()  # index of sentence
        sentence = self.comboBox_uni_sentence_x.currentText()
        self.universalGraph.title_x = sentence

        if index == 0:
            self.comboBox_uni_item_x.clear()  # clear box
            self.comboBox_uni_item_y.addItem("set item...")  # show items
            self.comboBox_uni_item_x.setDisabled(True)  # disable box
        else:
            sentences = globaListOfNmea.keys()  # sentence as key
            items = globaListOfNmea[sentences[index - 1]]  # current items
            self.comboBox_uni_item_x.clear()  # clear box
            self.comboBox_uni_item_x.setDisabled(False)  # enable box
            items = items.split(",")  # split
            self.comboBox_uni_item_x.addItem("set item from {}".format(items[0]))  # show items
            self.comboBox_uni_item_x.addItems(items[1:])  # show items

    def universal_set_sentence_y(self):
        """ Set comboBox y"""
        index = self.comboBox_uni_sentence_y.currentIndex()  # index of sentence
        sentence = self.comboBox_uni_sentence_y.currentText()
        self.universalGraph.title_y = sentence
        if index == 0:
            self.comboBox_uni_item_y.clear()  # clear box
            self.comboBox_uni_item_y.addItem("set item...")  # show items
            self.comboBox_uni_item_y.setDisabled(True)  # disable box
        else:
            sentences = globaListOfNmea.keys()  # sentence as key
            items = globaListOfNmea[sentences[index - 1]]  # current items
            self.comboBox_uni_item_y.clear()  # clear box
            self.comboBox_uni_item_y.setDisabled(False)  # enable box
            items = items.split(",")  # split
            self.comboBox_uni_item_y.addItem("set item from {}".format(items[0]))  # show items
            self.comboBox_uni_item_y.addItems(items[1:])  # show items

    def universal_set_item_x(self):

        item = self.comboBox_uni_item_x.currentText()
        # label
        self.universalGraph.x_label = item
        self.universalGraph.axis.set_xlabel(item)
        self.pw_uni.setLabel("bottom", item)
        # item
        self.parsingData.item_x = item
        self.database.item_x = item

    def universal_set_item_y(self):

        item = self.comboBox_uni_item_y.currentText()
        # label
        self.pw_uni.setLabel("left", item)
        # item
        self.parsingData.item_y = item
        self.database.item_y = item

    def uni_stop(self):
        self.parsingData.uni_graph_stat = False
        self.universalGraph.x = []
        self.universalGraph.y = []
        stat = True
        self.checkBox_uni_database_data.setEnabled(stat)
        self.spinBox_uni_timeBefore.setEnabled(stat)
        self.comboBox_uni_sentence_x.setEnabled(stat)
        self.comboBox_uni_sentence_y.setEnabled(stat)
        self.comboBox_uni_item_x.setEnabled(stat)
        self.comboBox_uni_item_y.setEnabled(stat)
        self.pushButton_uni_start.setEnabled(stat)

    def uni_start(self):

        self.database.timebef_user = self.spinBox_uni_timeBefore.value()
        self.parsingData.uni_graph_stat = True

        # choose load memory or database
        if self.checkBox_uni_database_data.isChecked():
            self.database.unigraph_query = True
        else:
            self.parsingData.mem = None

        stat = False
        self.checkBox_uni_database_data.setEnabled(stat)
        self.spinBox_uni_timeBefore.setEnabled(stat)
        self.comboBox_uni_sentence_x.setEnabled(stat)
        self.comboBox_uni_sentence_y.setEnabled(stat)
        self.comboBox_uni_item_x.setEnabled(stat)
        self.comboBox_uni_item_y.setEnabled(stat)
        self.pushButton_uni_start.setEnabled(stat)

    def uni_reset(self, arg=None):
        self.universalGraph.x = []
        self.universalGraph.y = []
        self.p1_uni.setData(y=self.universalGraph.y, x=self.universalGraph.x)

    def on_uni_newSample(self, x, y):

        for i in range(0, len(x)):
            self.universalGraph.x.append(float(x[i]))
            self.universalGraph.y.append(float(y[i]))
            if len(self.universalGraph.x) > 200:
                self.universalGraph.x.pop(0)
                self.universalGraph.y.pop(0)
        # use pyqtgraph
        self.p1_uni.setData(y=self.universalGraph.y, x=self.universalGraph.x)

        # use mathplotlib
        # self.universalGraph.points.set_data(self.universalGraph.x, self.universalGraph.y)
        # self.universalGraph.axis.relim()
        # self.universalGraph.axis.autoscale_view(True, True, True)
        # self.universalGraph.figure.canvas.draw()
        # if self.universalGraph.background_position is None:
        #    self.universalGraph.background_position = (
        #            self.universalGraph.figure.canvas.copy_from_bbox(self.universalGraph.axis.bbox))
        # self.universalGraph.figure.canvas.restore_region(self.universalGraph.background_position)
        # self.universalGraph.points.set_data(self.universalGraph.x, self.universalGraph.y)
        # self.universalGraph.axis.draw_artist(self.universalGraph.points)
        # self.universalGraph.figure.canvas.blit(self.universalGraph.axis.bbox)


# ----------------------------------------------------------------------------------------------------------------------
# ---------------------------------------------Threads------------------------------------------------------------------
class Connectivity(QThread):
    def __init__(self, parent=None):
        super(Connectivity, self).__init__(parent)
        self.init_connection = None  # init info from gui
        self.conn = None  # database connection
        self.cur = None  # database cursor
        self.speed = 1  # speed playback
        self.rest = None  # time to rest for playback
        self.current_timer = None  # timer for playback
        self.send_to_source = False  # enable send data to sources
        self.exiting = False  # enable exiting
        self.number_of_line = 0

    def run(self):  # run parallel thread
        self.number_of_line = 0
        if self.init_connection["Connection"] == "S":
            self.serialRead()  # do function serialRead
        elif self.init_connection["Connection"] == "E":
            self.server(self.init_connection)
        elif self.init_connection["Connection"] == "D":
            self.readDatabase()
        # end connection
        self.sendData("End connection")  # end sequence
        self.emit(SIGNAL("connectivityInfoWrong(QString)"),
                  "Connect break...\n")  # info to textEdit_connectivity_show area
        QThread.quit(self)

    def initSerial(self, init_connection):
        ser = serial.Serial()  # init ser
        port = "COM" + str(init_connection["Comport"])  # COM port
        ser.port = port  # set COM port
        ser.baudrate = int(init_connection["Baudrate"])  # set Baudrate
        ser.bytesize = serial.EIGHTBITS  # number of bits per bytes
        ser.parity = serial.PARITY_NONE  # set parity check: no parity
        ser.stopbits = serial.STOPBITS_ONE  # number of stop bits
        # ser.timeout = None            # block read
        # ser.timeout = 1               # non-block read
        # ser.timeout = 2               # timeout block read
        # ser.xonxoff = False           # disable software flow control
        # ser.rtscts = False            # disable hardware (RTS/CTS) flow control
        # ser.dsrdtr = False            # disable hardware (DSR/DTR) flow control
        # ser.writeTimeout = 2          # timeout for write
        self.emit(SIGNAL("connectivityInfo(QString)"),
                  "Serial parametr:\n" + str(ser) + "\n")  # info to textEdit_connectivity_show area
        # time.sleep(0.5)
        try:
            ser.open()  # open port
            ser.flushInput()
            ser.flushInput()
            self.emit(SIGNAL("connectivityInfo(QString)"),
                      "Connecting ready...\n")  # info to textEdit_connectivity_show area
            self.emit(SIGNAL("statusBarInfo(QString, QString)"), "S", str(port))  # info to statusbar line area
            return ser
        except Exception, e:
            ser = False
            self.emit(SIGNAL("connectivityInfoWrong(QString)"),
                      "Error open serial port:\n" + str(e) + "\n")  # info to textEdit_connectivity_show area
            self.emit(SIGNAL("disconnect()"))  # disconnect
            return ser

    def serialRead(self):

        ser = self.initSerial(self.init_connection)
        while ser:
            while ser.inWaiting() == 0:  # waiting on data true
                if self.exiting:  # control exiting, if no data
                    break
                else:
                    pass
            if self.exiting:  # control self.exiting, if data is available
                ser.close()  # close serial port and thread
                self.emit(SIGNAL("disconnect()"))  # disconnect
                break
            nmeafull = ser.readline()  # read one line
            self.sendData(nmeafull)  # data for gui
            if self.send_to_source:  # if send data to source is enable
                send_data = "reset device"  # massages
                ser.write(send_data)  # write dat to serial
                self.send_to_source = False  # disable sending to source

    def server(self, init_connection):

        hostname = init_connection["Hostname"]  # Symbolic name meaning all available interfaces
        port = init_connection["Port"]  # Arbitrary non-privileged port
        s = None
        # Datagram (udp) socket
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        except socket.error, msg:
            self.emit(SIGNAL("connectivityInfoWrong(QString)"),
                      "Could not open socket.\nError:" + str(msg) + "\n")  # info to textEdit_connectivity_show area
            self.emit(SIGNAL("disconnect()"))  # disconnect
        # Bind socket to local host and port
        try:
            send_data = "Start send"
            s.sendto(send_data, (hostname, port))
            self.emit(SIGNAL("statusBarInfo(QString, QString)"), "E", str(hostname))  # info to statusbar line area
            self.emit(SIGNAL("connectivityInfo(QString)"), "Wait for host...\n")
        except socket.error, e:
            self.exiting = True
            self.emit(SIGNAL("connectivityInfoWrong(QString)"),
                      "Could not open socket.\nError:" + str(e) + "\n")  # info to textEdit_connectivity_show area
            self.emit(SIGNAL("disconnect()"))  # disconnect
        while 1:
            try:
                s.settimeout(1)
                d = s.recvfrom(1024)
                data = d[0]
                if not data:
                    break
                self.sendData(data)
                if self.exiting:
                    self.emit(SIGNAL("disconnect()"))  # disconnect
                    break
                if self.send_to_source:
                    send_data = "reset device"
                    s.sendto(send_data, (hostname, port))
                    self.send_to_source = False
            except:
                if self.exiting:
                    self.emit(SIGNAL("disconnect()"))  # disconnect
                    break
        s.close()

    def readDatabase(self):
        try:
            self.conn = sqlite3.connect(str(self.init_connection["Path_database"]))
            self.cur = self.conn.cursor()
            self.cur.execute("SELECT Full_nmea, Local_time FROM NMEA")
            self.emit(SIGNAL("connectivityInfo(QString)"), "Opened database successfully...\n")
            self.emit(SIGNAL("statusBarInfo(QString, QString)"), "D",
                      str(self.init_connection["Path_database"]))  # info to status bar line area
            with self.conn:
                row_new = self.cur.fetchone()
                if row_new is not None:  # end of file
                    while True:
                        if self.exiting:  # disconnect
                            break
                        self.sendData(str(row_new[0]))  # send data
                        # calculate send time
                        row_old = row_new
                        row_new = self.cur.fetchone()
                        if row_new is None:  # end of file
                            break
                        self.playbackSpeed(row_new[1], row_old[1])
                        self.emit(SIGNAL("timer()"))
                        mutex.lock()
                        waitCondition.wait(mutex)
                        mutex.unlock()
                if not self.exiting:
                    self.emit(SIGNAL("connectivityInfo(QString)"), "Read all lines done.\n")
            if self.conn:
                self.cur.close()
                self.conn.close()
                self.emit(SIGNAL("disconnect()"))  # disconnect
        except Exception, e:  # info to textEdit_connectivity_show area
            if self.conn:
                self.conn.rollback()
            self.emit(SIGNAL("connectivityInfoWrong(QString)"), "Incompatible database.\n" + str(e) + "\n")
            self.emit(SIGNAL("disconnect()"))  # disconnect

    def sendData(self, nmeafull):
        nmeafull_ = nmeafull.rstrip(), time.time()  # cut white symbols
        FIFO_NMEA.append(nmeafull_)  # data for parsing
        self.number_of_line += 1  # number of line
        # print("Send data: {}".format(self.number_of_line))
        nmeafull_ = str(self.number_of_line) + ". " + nmeafull_[0]  # add number of sentence
        self.emit(SIGNAL("connectivityData(QString)"), nmeafull_)  # info to textEdit_connectivity_show area
        self.emit(SIGNAL("start_parsing()"))  # start parsing

    def playbackSpeed(self, local_time_new, local_time_old):
        rest = (float(local_time_new) - float(local_time_old)) * 1000  # rest time in millisecond
        self.rest = rest * (1.0 / self.speed)


class Database(QThread):
    database_newSample_uni = Signal(list, list)
    database_newSample_accu = Signal(dict)

    def __init__(self, parent=None):
        super(Database, self).__init__(parent)
        self.exiting_database = False
        self.init_ready = False
        self.conn = None
        self.cur = None
        self.path_database = ""
        self.number_of_line = 0
        # pseudo range query
        self.ps_range_query = False
        self.last_id = 0
        self.rec_data = defaultdict(dict)
        # uni graph
        self.unigraph_query = False  # enable query for data to unigraph
        self.item_x = None
        self.item_y = None
        self.timebef_user = 0
        self.x = []
        self.y = []

    def run(self):
        self.number_of_line = 0
        self.createDatabase()
        while True:
            #  mutex.lock()
            #  waitCondition.wait(mutex)    # write when new data is available
            #  mutex.unlock()
            time.sleep(1)  # write every second
            for i in range(0, len(FIFO_DATABASE)):
                nmea_dic = self.readFIFO_Database()
                if nmea_dic == "End connection":
                    self.number_of_line += 1
                    self.exiting_database = True
                    break
                self.number_of_line += 1
                self.addData(nmea_dic)
            if self.exiting_database:
                self.emit(SIGNAL("connectivityInfo(QString)"), "Close database successfully...\n")
                self.close()
                break

            # ---------------------query--------------------------------------------------------------------------------

            if self.ps_range_query:
                self.ps_range()

            if self.unigraph_query:  # universal graph load query
                self.unigraph()
        QThread.quit(self)

    def ps_range(self):
        SAT = {1: "GPS", 4: "GPS", 8: "GALILEO", 16: "GALILEO", 32: "SBAS"}
        timebef = time.time() - 6 - self.timebef_user
        self.timebef_user = 0
        query = "SELECT Id, GpsTimestamp, SignalIdBitmask, PRN, UsedPseudorange, PVTTOW FROM NMEA " \
                "WHERE Local_time > " + str(timebef) + \
                " AND NameSentence LIKE '$PHPRM'" + \
                " AND Id >= " + str(self.last_id)

        self.cur.execute(query)
        rows = self.cur.fetchall()
        if rows:
            rows_old = []
            syn_time_start = rows[0]["PVTTOW"]
            syn_time_old = rows[0]["PVTTOW"]
            for row_new in rows:
                if row_new["PVTTOW"] == syn_time_start:  # skip first time
                    continue

                syn_time_new = row_new["PVTTOW"]

                if syn_time_new != syn_time_old and len(rows_old) != 0:
                    for row in rows_old:
                        tow = float(row["PVTTOW"])
                        sat_name = SAT[int(row["SignalIdBitmask"])] + str(row["PRN"])
                        self.rec_data[sat_name][tow] = row["UsedPseudorange"]
                        self.last_id = int(row["Id"])
                    rows_old = []

                rows_old.append(row_new)
                syn_time_old = row_new["PVTTOW"]

            if self.rec_data:
                self.database_newSample_accu.emit(self.rec_data)  # data to gui graph [(x,y)]
            self.rec_data = {}
            self.rec_data = defaultdict(dict)

    def unigraph(self):
        timebef = time.time() - self.timebef_user
        query = "SELECT * FROM NMEA WHERE Local_time > " + str(timebef)
        # self.conn.row_factory = self.dict_factory       # return dic when is query
        self.cur.execute(query)
        # print self.cur.fetchone()["NameSentence"]
        rows = self.cur.fetchall()
        item_x = []
        item_y = []
        for row in rows:
            # update data
            try:
                self.x = float(row[self.item_x])  # update x
            except:
                pass
            try:
                self.y = float(row[self.item_y])  # update y
            except:
                pass

            if self.x != [] and self.x != None:
                if self.y != [] and self.y != None:  # if it will both update
                    item_x.append(self.x)  # list of x value
                    item_y.append(self.y)  # list of y value
                    self.x = []  # reset
                    self.y = []  # reset
            else:
                continue

        if self.item_x != [] and self.item_x != None:
            if self.item_y != [] and self.item_y != None:  # if it will both update
                self.database_newSample_uni.emit(item_x, item_y)  # data to gui graph [(x,y)]

        self.unigraph_query = False  # Only one shot

    def dict_from_row(self, row):
        return dict(zip(row.keys(), row))

    def dict_factory(self, cursor, row):
        d = {}
        for idx, col in enumerate(cursor.description):
            d[col[0]] = row[idx]
        return d

    def createDatabase(self):
        query = """CREATE TABLE NMEA (Id INTEGER PRIMARY KEY, Local_time INT, NameSentence TEXT, Full_nmea TEXT, Cksum INT,
                                     Cksum_cal INT, Sentence_message TXT, ReceiverMessage TXT)"""
        if self.path_database is "":
            self.path_database = time.localtime()
            self.path_database = "database/{}-{}-{}_{}-{}-{}.db".format(
                self.path_database[2], self.path_database[1], self.path_database[0], self.path_database[3],
                self.path_database[4], self.path_database[5])
        else:
            self.deleteFile(self.path_database)  # delete exist file
            length = str(self.path_database)
            length = len(length.split("/"))
            if length == 1:
                self.path_database = "database/" + str(self.path_database) + ".db"
            if length == 2 and length[0] == "":
                self.path_database = "database/" + str(self.path_database) + ".db"
            if length > 2:
                pass
            else:
                self.emit(SIGNAL("connectivityInfoWrong(QString)"),
                          "Database error name. Change the name.\n")
                self.emit(SIGNAL("disconnect()"))  # disconnect
        length = str(self.path_database)
        length = len(length.split("."))
        if length == 1:
            self.path_database = str(self.path_database) + ".db"
        try:
            self.conn = sqlite3.connect(str(self.path_database))
            self.conn.row_factory = self.dict_factory  # return dict when is query
            self.cur = self.conn.cursor()
            self.cur.execute(query)
            self.addColumn(globaListOfNmea)
            self.conn.commit()
            self.emit(SIGNAL("connectivityInfo(QString)"), "Opened database successfully...\n")
        except Exception, e:  # info to textEdit_connectivity_show area
            if self.conn:
                self.conn.rollback()
                self.emit(SIGNAL("connectivityInfoWrong(QString)"),
                          "Database already exists. Change the name.\n" + str(e) + "\n")
                self.emit(SIGNAL("disconnect()"))  # disconnect
        finally:
            self.init_ready = True
            # return self.conn, self.cur

    def addColumn(self, dictionary):
        keys = dictionary.keys()  # all keys
        for key in keys:
            columns = dictionary[key].split("*")
            columns = columns[0].split(",")
            for column in columns:
                try:
                    self.cur.execute('''ALTER TABLE NMEA ADD COLUMN '%s' TEXT''' % str(column))
                except Exception, e:  # info to textEdit_connectivity_show area
                    if "duplicate" in str(e):
                        pass
                    else:
                        self.emit(SIGNAL("connectivityInfoWrong(QString)"),
                                  "Database add column error:\n" + str(e) + "\n")

    def addData(self, dictionary):
        try:
            keys = ",".join(dictionary.keys())
            question_marks = ",".join(list("?" * len(dictionary)))
            items = tuple(dictionary.values())
            self.cur.execute('INSERT INTO NMEA (' + keys + ') VALUES (' + question_marks + ')', items)
        except Exception, e:  # info to textEdit_connectivity_show area
            if self.conn:
                self.conn.rollback()
                self.emit(SIGNAL("connectivityInfoWrong(QString)"),
                          "Database add data error:\n" + str(e) + "\n")
                self.exiting_database = True

    def readFIFO_Database(self):
        try:
            nmea_dic = FIFO_DATABASE.pop(0)
            return nmea_dic
        except Exception, e:
            self.emit(SIGNAL("connectivityInfoWrong(QString)"),
                      "Database read FIFO data error:\n" + str(e) + "\n")

    def deleteFile(self, path):
        try:
            os.remove(path)
        except Exception, e:
            self.emit(SIGNAL("connectivityInfoWrong(QString)"),
                      "Database already exists. Change the name.\n" + str(e) + "\n")

    def close(self):
        if self.conn:
            self.conn.commit()
            self.cur.close()
            self.conn.close()
            self.path_database = None
        QThread.quit(self)


class ParsingData(QThread):
    newSample_position = Signal(list)
    newSample_satellite = Signal(list)
    newSample_uni = Signal(list, list)

    def __init__(self, parent=None):
        super(ParsingData, self).__init__(parent)
        self.multi_dic = {}  # data after parsing
        self.source = None  # source of incoming data
        self.number_of_line = 0  # number of line
        # Graph
        self.nmea_dic = {}  # for graph
        self.graph_stat = False  # enable data for graph
        self.ecef = False
        # TTFF
        self.exiting_ttff = False  # disable position
        self.ttff_stat = False  # enable data for ttff test
        self.check_reset_device = True  # enable check reset device
        self.check_fix = False  # if was reset for ttff
        self.check_pos = False  # if was position for ttff
        self.fix = 0  # reset fix position
        self.num_of_sat = 0
        self.ttff_time_control = 3000  # default time control position for ttff
        self.rec_time = (-1)  # reset rec time
        self.ttff_dic = {}  # for TTFF
        self.ttff_pos_lat = []
        self.ttff_pos_lon = []
        self.ttff_pos_alt = []
        self.ttff_pos_hdop = []
        self.ref_pos_lat = 0
        self.ref_pos_lon = 0
        self.ref_pos_alt = 0
        # Database
        self.database_stat = True  # enable dota for database
        # Panda
        self.panda_stat = False  # enable data for panda
        self.df = pd.DataFrame([])
        # memory
        self.memory_stat = True  # enable data for memory dic
        self.uni_graph_stat = False
        self.mem = {}
        self.item_x = None  # name of item x
        self.item_y = None  # name of item y
        self.x = []  # value x
        self.y = []  # value y

    def run(self):
        for i in range(0, len(FIFO_NMEA)):
            self.multi_dic = {}  # clear dictionary
            nmea_line = self.readFIFO_NMEA()  # read data from stack
            if nmea_line == "End connection":  # if end connection
                self.endConnection(nmea_line)  # exiting
            else:
                self.parsing(nmea_line)  # parsing
                if self.database_stat:
                    self.dataForDatabase()  # data for DATABASE
                if self.ttff_stat:  # data for TTFF
                    self.dataForTTFF()
                if self.graph_stat:  # data for GRAPH
                    self.dataFofGraph()
                if self.panda_stat:  # data for pandas
                    self.dataForPanda()
                if self.memory_stat:  # data for memory
                    self.dataForMemory()
                if self.uni_graph_stat:  # data for universal graph
                    self.dataForUni()
            self.number_of_line += 1  # sentences counter
        QThread.quit(self)

    def readFIFO_NMEA(self):
        try:
            nmea_line, self.multi_dic["Local_time"] = FIFO_NMEA.pop(0)  # nmea sentence and local time
            return nmea_line
        except Exception, e:
            self.emit(SIGNAL("connectivityInfoWrong(QString)"),
                      "Parsing read FIFO data error:\n" + str(e) + "\n")

    def parsing(self, nmea_line):
        if nmea_line is None:
            pass
        elif nmea_line is "":
            pass
        elif nmea_line[0] == "$":
            nmea_, cksum, cksum_cal = self.checksum(nmea_line)
            self.multi_dic["Full_nmea"] = (str(nmea_line)).rstrip()
            self.multi_dic["Cksum"] = cksum
            self.multi_dic["Cksum_cal"] = cksum_cal
            nmea_ = nmea_.split(",")  # without cksum
            self.multi_dic["NameSentence"] = nmea_[0]
            try:
                nmea_global = globaListOfNmea[nmea_[0]]
                nmea_global = nmea_global.split("*")  # separate cksum
                nmea_global = nmea_global[0].split(",")
                for i in range(1, len(nmea_global), 1):
                    self.multi_dic[nmea_global[i]] = nmea_[i]
                self.nmea_dic = {nmea_[0]: nmea_line}
            except:
                pass
        elif len(nmea_line) > 1:  # message from receiver, no sentence NMEA
            self.multi_dic["ReceiverMessage"] = (str(nmea_line)).rstrip()
        else:
            pass

    def checksum(self, sentence):
        sentence = sentence.rstrip()
        l = sentence.split("*")
        if len(l) > 2:
            cksum = sentence[-2:]
            nmeadata = sentence[:-3]
        else:
            nmeadata, cksum = sentence.split("*")
        calc_cksum = 0
        for s in nmeadata[1:]:  # calculate XOR beside symbol $
            calc_cksum ^= ord(s)
        return nmeadata, hex(int(cksum, 16)), hex(calc_cksum)

    def dataForTTFF(self):
        # update data
        try:
            self.fix = self.multi_dic["FixQuality"]  # update fix quality
        except:
            pass
        try:
            self.rec_time = int(self.multi_dic["RecTimeStamp"])  # update rec_time
        except:
            pass
        try:
            self.num_of_sat = int(self.multi_dic["NumberOfSatellites"])  # update NumberOfSatellites
        except:
            pass

        # check measurement time <5min
        if self.rec_time > (5 * 60 * 1000):  # 5 min
            self.emit(SIGNAL("dataToTTFF(QString, QString, QString, QString)"), 0, "nok", 0, 0)
            self.exiting_ttff = True

        # find reset
        if self.check_reset_device:  # find reset (rec time = 0)
            if self.rec_time == 0:  # it was reset
                self.fix = 0  # reset fix quality
                self.emit(SIGNAL("ttffTimer_start()"))  # start timer for lcd
                self.check_fix = True  # enable find fix
                self.check_reset_device = False  # disable itself

        # find fix
        elif self.check_fix:
            if int(self.fix) == 1:  # it was fix
                self.ttff_dic["TTFF"] = self.rec_time  # safe rec_time
                self.ttff_dic["Position"] = "ok"  # position ok
                self.ttff_dic["Number_of_satellites"] = self.num_of_sat  # number_of_satellites
                self.check_pos = True  # enable check position
                self.check_fix = False  # disable itself

        # check position
        elif self.check_pos:
            ttff = self.ttff_dic["TTFF"]  # ttff
            if (self.rec_time - int(ttff)) <= int(self.ttff_time_control):  # testing position for n ms
                if int(self.fix) == 0:  # if fix is nok
                    self.ttff_dic["Position"] = "nok"  # position = nok
                if int(self.ttff_dic["Number_of_satellites"]) > self.num_of_sat:  # write smaller number of sat
                    self.ttff_dic["Number_of_satellites"] = self.num_of_sat

                try:
                    if self.multi_dic["NameSentence"] == "$GPGGA":
                        self.ttff_pos_lat.append(self.gps2geg(self.multi_dic["Latitude"]))
                        self.ttff_pos_lon.append(self.gps2geg(self.multi_dic["Longitude"]))
                        self.ttff_pos_alt.append(self.multi_dic["Altitude"])
                        self.ttff_pos_hdop.append(self.multi_dic["HDOP"])
                except:
                    pass
            # cycle end, info to gui (ttff and position(ok,nok) and min satellites)
            else:
                # compute horizontal accuracy
                if len(self.ttff_pos_hdop) == len(self.ttff_pos_alt) == len(self.ttff_pos_lon) == len(
                        self.ttff_pos_lat):
                    N = len(self.ttff_pos_lat)
                else:
                    N = 0
                suma = 0
                for i in range(0, N):
                    denu = self.ecef2enu(float(self.ref_pos_lat),
                                         float(self.ref_pos_lon),
                                         float(self.ref_pos_alt),
                                         float(self.ttff_pos_lat[i]),
                                         float(self.ttff_pos_lon[i]),
                                         float(self.ttff_pos_alt[i]))

                    # vyit horiyontalu * 1.5/hdop
                    de = denu[0]
                    suma += (de * (1.5 / float(self.ttff_pos_hdop[i]))) ** 2
                rms2D = 2 * (np.sqrt(suma / N))

                # result of position
                if rms2D > 15:
                    self.ttff_dic["Position"] = "nok"  # position = nok

                # data to gui
                self.emit(SIGNAL("dataToTTFF(QString, QString, QString, QString)"),
                          str(self.ttff_dic["TTFF"]),
                          self.ttff_dic["Position"],
                          str(self.ttff_dic["Number_of_satellites"]),
                          str(rms2D))

                # reset variables
                self.ttff_pos_lat = []
                self.ttff_pos_lon = []
                self.ttff_pos_alt = []
                self.ttff_pos_hdop = []

                self.emit(SIGNAL("ttffTimer_stop()"))  # stop timer for lcd
                self.exiting_ttff = True  # enable exiting_ttff

        if self.exiting_ttff:
            self.check_reset_device = True  # enable check reset device
            self.check_fix = False  # if was reset for ttff
            self.check_pos = False  # if was position for ttff
            self.fix = 0  # reset fix position
            self.rec_time = (-1)  # reset rec time
            self.ttff_dic = {}  # for TTFF
            self.ttff_stat = False  # enable data for ttff test
            self.exiting_ttff = False  # disable position

    def dataForDatabase(self):
        if self.source != "D":
            FIFO_DATABASE.append(self.multi_dic)  # data for parsing
            self.emit(SIGNAL("writeDatabase()"))  # wakeup database

    def dataFofGraph(self):
        """  Zasle surova data grafum,
            nmea je slovnik klic: nazev vety, promenna: cela veta
            zapise slovnik do prislusne fronty """
        # ------------------------ position graph-----------------------------------------------
        if "$GPGGA" in self.nmea_dic:
            try:
                # setting parameters
                varset = globaListOfNmea["$GPGGA"]
                varset = varset.split("*")
                varset = varset[0].split(",")
                lat_index = varset.index("Latitude")  # index pozice ve vete
                latside_index = varset.index("LatitudeSide")
                long_index = varset.index("Longitude")  # index pozice ve vete
                longside_index = varset.index("LongitudeSide")
                alt_index = varset.index("Altitude")
                # realne data
                vareal = self.nmea_dic["$GPGGA"]
                vareal = vareal.split("*")
                vareal = vareal[0].split(",")
                # uprava dat
                lats = str(vareal[lat_index])
                longs = str(vareal[long_index])
                # convert degrees,decimal minutes to decimal degrees
                lat1 = (float(lats[2] + lats[3] + lats[4] + lats[5] + lats[6] + lats[7] + lats[8])) / 60
                lat = (float(lats[0] + lats[1]) + lat1)
                long1 = (float(longs[3] + longs[4] + longs[5] + longs[6] + longs[7] + longs[8] + longs[9])) / 60
                lon = (float(longs[0] + longs[1] + longs[2]) + long1)

                if vareal[latside_index] == "S":
                    lat = -lat
                if vareal[longside_index] == "W":
                    lon = -lon
                print lat
                print lon
                print float(vareal[alt_index])
                # calc position
                if self.ecef:
                    lon, lat, vareal[alt_index] = self.ecef2enu(0,0,0,lat,lon,float(vareal[alt_index]))
                else:
                    pass
                vareal[lat_index] = lat
                vareal[long_index] = lon

                # naparovani
                vardic = {varset[lat_index]: vareal[lat_index],
                          varset[latside_index]: vareal[latside_index],
                          varset[long_index]: vareal[long_index],
                          varset[longside_index]: vareal[longside_index],
                          varset[alt_index]: vareal[alt_index]}
                self.newSample_position.emit(vardic)  # data to gui graph

                FIFO_POSITION.append(vardic)  # zaslani do fronty slovnik
            except Exception, e:
                print("Error data for graph. Position.")
                print(e)
                # ------------------------ sattelitte graph --------------------------------------------
        if "$GPGSV" in self.nmea_dic:
            try:
                # setting parameters
                varset = globaListOfNmea["$GPGSV"]
                varset = varset.split("*")
                varset = varset[0].split(",")
                msg_total_index = varset.index("TotalNumberOfMessages")  # index pozice ve vete
                msg_index = varset.index("Messagenumber")  # index pozice ve vete
                prn_index = varset.index("PRNNumber_first")
                elev_index = varset.index("Elevation_first")
                azim_index = varset.index("Azimut_first")  # index pozice ve vete
                snr_index = varset.index("SNR_first")
                # realne data
                vareal = self.nmea_dic["$GPGSV"]
                vareal = vareal.split("*")
                vareal = vareal[0].split(",")
                # naparovani
                vardic = {}
                vardic.update({varset[msg_total_index]: vareal[msg_total_index]})
                vardic.update({varset[msg_index]: vareal[msg_index]})
                for i in range(0, 4):  # ctyri zaznamy ve vete
                    vardic.update({varset[prn_index + i * 4]: vareal[prn_index + i * 4],
                                   varset[elev_index + i * 4]: vareal[elev_index + i * 4],
                                   varset[azim_index + i * 4]: vareal[azim_index + i * 4],
                                   varset[snr_index + i * 4]: vareal[snr_index + i * 4]})

                self.newSample_satellite.emit(vardic)  # data to gui graph
                FIFO_SATELLITE.append(vardic)  # zaslani do fronty slovnik
            except Exception, e:
                print("Error data for graph. Sattelite.")
                print(e)

    def dataForFiltr(self):
        pass

    def dataForPanda(self):
        while len(self.df.index) >= 3:
            self.df.drop(self.df.index[0], inplace=True)
        self.df = self.df.append([self.multi_dic], ignore_index=True)
        # print self.df["Local_time"][0]

    def dataForMemory(self):
        FIFO_MEMORY.append(self.multi_dic)
        if len(FIFO_MEMORY) > 1000:
            FIFO_MEMORY.pop(0)

    def dataForUni(self):
        item_x = []
        item_y = []
        if self.mem is None:  # load memory (last x sec)
            self.mem = FIFO_MEMORY[:]  # only true copy
            for i in range(0, len(self.mem)):  # go through memory
                line = self.mem.pop(0)
                # update data
                try:
                    self.x = float(line[self.item_x])  # update x
                except:
                    pass
                try:
                    self.y = float(line[self.item_y])  # update y
                except:
                    pass

                if self.x != []:
                    if self.y != []:  # if it will both update
                        item_x.append(self.x)  # list of x value
                        item_y.append(self.y)  # list of y value
                        self.x = []  # reset
                        self.y = []  # reset
                else:
                    continue

            self.mem = {}  # clear mem
            if item_x != []:
                if item_y != []:
                    self.newSample_uni.emit(item_x, item_y)  # data to gui graph [(x,y),(x+1,y+1),...]
        else:
            # update data
            try:
                self.x = float(self.multi_dic[self.item_x])  # update x
            except:
                pass
            try:
                self.y = float(self.multi_dic[self.item_y])  # update y
            except:
                pass

            if self.x != []:
                if self.y != []:  # if it will both update
                    item_x.append(self.x)
                    item_y.append(self.y)
                    self.x = []  # reset
                    self.y = []  # reset
                    self.newSample_uni.emit(item_x, item_y)  # data to gui graph [(x,y)]

    def ecef2enu(self, ref_lat, ref_lon, ref_alt, lat, lon, alt):
        """ Transformation gpd coordinate to enu coordinate """
        llh0 = [ref_lat, ref_lon, ref_alt]
        llh = [lat, lon, alt]
        # CONSTANTS
        a = 6378137
        b = 6356752.3142
        e2 = 1 - (b / a) ** 2
        # Location of reference point in radians
        phi = llh0[0] * np.pi / 180
        lam = llh0[1] * np.pi / 180
        h = llh0[2]
        # Location of data points in radians
        dphi = llh[0] * np.pi / 180 - phi
        dlam = llh[1] * np.pi / 180 - lam
        dh = llh[2] - h
        # Some useful definitions
        tmp1 = np.sqrt(1 - e2 * np.sin(phi) ** 2)
        cp = np.cos(phi)
        sp = np.sin(phi)
        # Transformations
        de = (a / tmp1 + h) * cp * dlam - (a * (1 - e2) / (tmp1 ** 3) + h) * sp * dphi * dlam + cp * dlam * dh
        dn = (a * (1 - e2) / tmp1 ** 3 + h) * dphi + 1.5 * cp * sp * a * e2 * dphi ** 2 + \
             sp ** 2 * dh * dphi + 0.5 * sp * cp * (a / tmp1 + h) * dlam ** 2
        du = dh - 0.5 * (a - 1.5 * a * e2 * cp ** 2 + 0.5 * a * e2 + h) * dphi ** 2 - 0.5 * cp ** 2 * (
            a / tmp1 - h) * dlam ** 2
        return [de, dn, du]

    def gps2geg(self, coordinate):
        """ Transform gps coordinate to degrees """
        coordinate = float(coordinate) / 100
        deg_ = int(coordinate)
        min_ = (coordinate - deg_) * 100

        deg = float(deg_) + (float(min_) / 60)

        return deg

    def endConnection(self, nmea_line):
        if self.source != "D":
            FIFO_DATABASE.append(nmea_line)  # data for parsing
            self.emit(SIGNAL("writeDatabase()"))  # wakeup to database


class TTFF(QThread):
    def __init__(self, parent=None):
        super(TTFF, self).__init__(parent)
        self.total_n_measurements = 3  # number of measurements
        self.total_n_cycle = 2  # number of cycle in measurements

        self.exiting = False  # enable exiting
        self.measure_cycle_error = True  # repeat measurements
        self.number_measurements = 0  # number of measurements
        self.number_cycle = 0  # number of cycle in measurements
        self.ttff = 0  # value of TTFF
        self.position = None  # ok/nok
        self.num_of_sat = None  # number of satellites
        self.result = None  # ok/nok
        self.rms2D = None  # position rms2D
        self.result_measure_dic = {}  # result dictionary
        self.result_final_dic = {}  # final result dictionary
        # parameters from gui
        self.ref_pos_lat_deg = None
        self.ref_pos_lat_min = None
        self.ref_pos_lat_sec = None
        self.ref_pos_lat_side = None
        self.ref_pos_lon_deg = None
        self.ref_pos_lon_min = None
        self.ref_pos_lon_sec = None
        self.ref_pos_lon_side = None

        self.ref_pos_lat = None
        self.ref_pos_lon = None
        self.ref_pos_alt = None

    def init_all(self):
        self.exiting = False  # enable exiting
        self.measure_cycle_error = True  # repeat measurements
        self.number_measurements = 0  # number of measurements
        self.number_cycle = 0  # number of cycle in measurements
        self.ttff = 0  # value of TTFF
        self.position = None  # ok/nok
        self.num_of_sat = None  # number of satellites
        self.rms2D = None  # position rms2D
        self.result = None  # ok/nok
        self.result_measure_dic = {}  # result dictionary
        self.result_final_dic = {}  # result dictionary

    def init_measure(self):
        self.number_cycle = 0  # number of cycle in measurements
        self.ttff = None  # value of TTFF
        self.position = None  # ok/nok
        self.num_of_sat = None  # number of satellites
        self.result = None  # ok/nok
        self.result_measure_dic = {}  # result dictionary

    def run(self):
        self.init_all()
        self.ref_position()  # get ref position
        while self.measure_cycle_error:
            self.init_measure()
            self.number_measurements += 1

            for i in range(1, self.total_n_cycle + 1, 1):
                self.measurements_cycle(i)
                if self.exiting:
                    break
                else:
                    self.result_cycle()
            self.result_final_cycle()
        self.result_final()
        QThread.quit(self)

    def resetDevice(self):
        self.emit(SIGNAL("reset_device()"))

    def waitForData(self):
        mutex_ttf.lock()
        waitCondition_ttf.wait(mutex_ttf)  # wait on TTFF
        mutex_ttf.unlock()

    def measurements_cycle(self, i):
        self.number_cycle = i
        self.emit(SIGNAL("dataForTTFFstart()"))  # enable stat in parsing thread
        self.resetDevice()  # reset device
        self.waitForData()  # wait on data

    def result_cycle(self):
        """ Info to gui (number measurement, number cycle, TTFF, position), safe this result to result_cycle_dic """
        # save result
        result_cycle_dic = {"TTFF": self.ttff, "Position": self.position, "NumberOfSatellites": self.num_of_sat}
        self.result_measure_dic[self.number_cycle] = result_cycle_dic
        # info to gui
        self.emit(SIGNAL("result_cycle(QString, QString, QString, QString, QString, QString)"),
                  str(self.number_measurements),
                  str(self.number_cycle),
                  str(result_cycle_dic["TTFF"]),
                  str(result_cycle_dic["Position"]),
                  str(self.num_of_sat),
                  str(self.rms2D))

    def result_final_cycle(self):
        """ Evaluation of this measurement, check all fix positions, return ok/nok/end and break/continue measurement"""
        if not self.exiting:
            # test all position of measurement (ok/nok)
            self.result_final_dic[self.number_measurements] = self.result_measure_dic
            stat_pos = True
            for i in range(1, self.number_cycle):
                stat_pos = stat_pos and self.result_measure_dic[i]["Position"]
            # result
            if stat_pos:  # position ok
                self.result = "ok"  # successful test
                self.measure_cycle_error = False  # end measurement
            elif self.number_measurements >= self.total_n_measurements:  # max measurement
                self.result = "nok"  # fail test
                self.measure_cycle_error = False  # end measurement
            else:  # position nok
                self.result = "continue"  # fail test
                self.measure_cycle_error = True  # continue measurement
                self.emit(SIGNAL("result_final(QString)"), str(self.result))  # info for GUI

        else:  # exiting
            self.result = "end"  # fail break test
            self.measure_cycle_error = False  # end measurement

    def result_final(self):
        """ Info to GUI """
        self.emit(SIGNAL("result_final(QString)"), str(self.result))  # total measure info for GUI, True=ok, False=Nok

    def ref_position(self):
        """ Get lat and lon from gui """
        # convert degrees,decimal minutes to decimal degrees
        lat1 = (float(self.ref_pos_lat_deg))  # deg
        lat2 = (float(self.ref_pos_lat_min)) / 60  # min
        lat3 = (float(self.ref_pos_lat_sec)) / (60 * 60)  # sec
        lat = (float(lat1 + lat2 + lat3))  # together
        if self.ref_pos_lat_side == "S (-)":
            lat *= -1
        self.ref_pos_lat = lat

        lon1 = (float(self.ref_pos_lon_deg))  # deg
        lon2 = (float(self.ref_pos_lon_min)) / 60  # min
        lon3 = (float(self.ref_pos_lon_sec)) / (60 * 60)  # sec
        lon = (float(lon1 + lon2 + lon3))  # together
        if self.ref_pos_lon_side == "W (-)":
            lon *= -1
        self.ref_pos_lon = lon
        # send data to parsing
        self.emit(SIGNAL("ref_position(QString, QString, QString)"), str(lat), str(lon), str(self.ref_pos_alt))


class Export(QThread):
    def __init__(self, header_, data_, parent=None):
        super(Export, self).__init__(parent)
        self.data_ = data_
        self.header_ = header_
        self.name = ""

    def run(self):
        self.write_data(self.data_, self.header_)
        QThread.quit(self)

    def write_data(self, data_, header_):
        wb = Workbook()
        sheet = wb.add_sheet("Measurement")
        style1 = easyxf("pattern: pattern solid, fore_colour red;")
        style2 = easyxf("pattern: pattern solid, fore_colour green;")

        for n in xrange(len(header_)):  # header
            sheet.write(0, n, header_[n], style2)
            sheet.col(n).width = 6000

        for n in xrange(len(data_) - 1):  # data
            for m in xrange(len(data_[n])):
                sheet.write(n + 1, m, data_[n][m])

        for n in xrange(len(data_[0])):  # end
            sheet.write(len(data_) + 1, n, data_[len(data_) - 1][n], style1)

        if self.name is "":
            self.name = time.localtime()
            self.name = "ttff/{}-{}-{}_{}-{}-{}.xsl".format(
                self.name[2], self.name[1], self.name[0], self.name[3],
                self.name[4], self.name[5])
        wb.save(self.name)


class Interpolators(QThread):
    interpolators_newSample = Signal(dict)
    interpolators_result = Signal()

    def __init__(self, parent=None):
        super(Interpolators, self).__init__(parent)
        self.interpolators = {}
        self.exiting = False
        #
        self.file_csv = None
        self.file_interpolars = None
        self.GNSS = {0: "GPS", 9: "GALILEO", 1: "SBAS"}
        self.path_database = None
        self.TOW_ref = 0
        self.file_stat = True
        self.import_done = False
        self.numb = 0
        # new data
        self.rec_data = defaultdict(dict)
        self.multi_dic = {}
        # sampling
        self.sampl_stat = False
        self.smooth_interval = 5    # Hz
        self.numb_sampl = 50
        self.sample_list_of_dic = []
        self.local_time = 0
        self.local_time_ref = 0
        self.init_time = 0  # in min
        # compute
        self.Zij = []
        self.M = 0
        self.M_max = 0
        self.NIS = 0
        self.threshold_used = False  # True = 125, False = 110
        self.sigma_noise_used = True  # true = 0.11, false = 0.15
        self.NIS_ref = [25, 50, 75, 100, 150, 200, 300, 400, 500, 750, 1000, 1250, 1500, 2000]
        self.threshold = [
            [0, 0, 0.954, 0.981, 0.998, 1.017, 1.028, 1.042, 1.050, 1.055, 1.063, 1.068, 1.072, 1.074, 1.078],
            [0, 1.084, 1.137, 1.159, 1.172, 1.187, 1.196, 1.206, 1.212, 1.216, 1.222, 1.226, 1.229, 1.231, 1.233]]

    def run(self):

        if self.file_stat and not self.import_done:  # if CSV file
            self.import_csv()
        elif not self.file_stat and not self.import_done:  # interpolators is exist
            self.import_interpolators()
        else:
            while not self.exiting:
                self.new_data()
                if self.exiting:
                    break
                self.sampling()
            self.init_reset()
        QThread.quit(self)


    def sampling(self):
        if self.local_time_ref == 0:
            self.local_time_ref = self.local_time

        diff_time = self.local_time - self.local_time_ref

        if diff_time >= (self.init_time * 60):  # pass init time
            self.sampl_stat = True

        if self.sampl_stat:
            if diff_time >= ((1 / self.smooth_interval) * 2):

                cdtj = 0
                i = self.multi_dic.keys()
                Nj = len(i)
                self.NIS += Nj - 1
                zi = []
                Zij_T = []

                for i in self.multi_dic:
                    sat_i_pserr = (float(self.multi_dic[i][3][len(self.multi_dic[i][3]) - 1]))
                    cdtj += float(sat_i_pserr)
                cdtj = cdtj / Nj

                for i in self.multi_dic:
                    sat_i_pserr = (float(self.multi_dic[i][3][len(self.multi_dic[i][3]) - 1]))
                    sat_i_pserr = float(sat_i_pserr) - cdtj
                    zi.append(float(sat_i_pserr))
                Zij_T.append(zi)
                self.M += 1
                self.Zij = np.matrix(Zij_T).T
                self.Zij = np.array(self.Zij)

                if self.sigma_noise_used:
                    Sigma_noise1 = 0.11
                else:
                    Sigma_noise1 = 0.15

                Sigma_norm = np.zeros(self.Zij.shape)
                Sigma_noise = Sigma_noise1 * np.ones(self.Zij.shape)

                for j in range(Sigma_norm.shape[1]):
                    for i in range(Sigma_norm.shape[0]):
                        Sigma_norm[i, j] = sqrt(((pow((Nj - 1), 2) * pow(Sigma_noise[i, j], 2) + np.sum(
                            np.power(Sigma_noise[:, j], 2)) - pow(Sigma_noise[i, j], 2)) / pow(Nj, 2)))

                temp1 = np.divide(np.power(self.Zij, 2), (np.power(Sigma_norm, 2) * Nj))
                temp2 = np.sum(temp1)  # sum of all elements in matrix
                RMS_PR = sqrt(temp2 / self.M)

                result = False
                for i in range(0, len(self.NIS_ref)):
                    if self.NIS < self.NIS_ref[i]:
                        if RMS_PR <= self.threshold[self.threshold_used][i]:
                            result = True
                            break
                        else:
                            result = False
                            break

                data = (self.M, self.NIS, RMS_PR, result)
                data_list_accu_result.insert(0, data)

                self.local_time_ref = self.local_time  # set next sample

                self.interpolators_result.emit()  # data to gui graph [(x,y)]
                if len(self.sample_list_of_dic) >= self.numb_sampl:
                    self.sampl_stat = False

    def new_data(self):
        self.waitForData()
        self.local_time = time.time()
        self.multi_dic = {}  # reset
        if not self.exiting:
            for sat in self.rec_data.keys():
                interpolator = self.interpolators[str(sat)]  # chose interpolator
                tows_dic = self.rec_data[sat]  # tow: pr,pr ,tow2: pr, pr
                tows = sorted(tows_dic.keys())  # TOW list
                psr_true = interpolator(tows)  # PSR_true list
                psr = []
                psr_error = []
                for tow in tows:
                    psr.append(float(tows_dic[tow]))  # PSR list
                for i in range(0, len(psr)):
                    error = (float(psr[i]) - float(psr_true[i]))
                    psr_error.append(error)  # PSR_error list
                # print sat
                # print tows
                # print psr
                # print psr_true
                # print psr_error
                self.multi_dic[str(sat)] = [list(tows), list(psr), list(psr_true), list(psr_error)]
                # print self.multi_dic
            self.interpolators_newSample.emit(self.multi_dic)  # data to gui graph [(x,y)]

    def import_csv(self):
        data = []
        query = """CREATE TABLE GEN (Id INTEGER PRIMARY KEY, TOW INT, Sat TEXT, TrPR INT)"""

        self.path_database = time.localtime()
        self.path_database = "data/accu_{}-{}-{}_{}-{}-{}.db".format(
            self.path_database[2], self.path_database[1], self.path_database[0], self.path_database[3],
            self.path_database[4], self.path_database[5])

        self.conn_accu = sqlite3.connect(str(self.path_database))
        self.conn_accu.row_factory = self.dict_factory  # return dict when is query

        self.emit(SIGNAL("progressBar(QString, QString, QString)"), "Opened database successfully...", "0", "0")
        with self.conn_accu:
            cur = self.conn_accu.cursor()
            cur.execute(query)
            with open(self.file_csv, 'rb') as f:
                reader = csv.reader(f)
                try:
                    self.emit(SIGNAL("progressBar(QString, QString, QString)"), "Read CSV file...", "0", "0")
                    for row in reader:
                        gps_time = row[1]
                        self.TOW_ref = float(gps_time) % 604800
                        break
                    for row in reader:
                        head = row
                        break
                    for row in reader:

                        TOW = self.TOW_ref + (float(row[0]) / 1000)
                        Sat_PRN = row[4]
                        Sat_type = row[2]
                        Range = row[14]
                        Sat = self.GNSS[int(Sat_type)] + str(Sat_PRN)
                        if str(Sat_PRN) == "0" and str(Range) == "0":
                            continue
                        data.append((None, float(TOW), str(Sat), float(Range)))

                        if len(data) > 10000:  # s = 102.7 s; bez = 99.7 s
                            cur.executemany("INSERT INTO GEN VALUES(?, ?, ?, ?)", data)
                            self.numb += len(data)
                            data = []

                    cur.executemany("INSERT INTO GEN VALUES(?, ?, ?, ?)", data)
                    self.numb += len(data)

                except csv.Error:
                    print "csv error"

                    # if self.file_stat:  # if CSV file
            query = "SELECT * FROM GEN"
            #    self.conn_accu = sqlite3.connect(str(self.path_database))
            #    self.conn_accu.row_factory = self.dict_factory  # return dict when is query
            self.emit(SIGNAL("progressBar(QString, QString, QString)"), "Database...", "0", "0")
            #    with self.conn_accu:
            #        cur = self.conn_accu.cursor()
            cur.execute(query)
            rows = cur.fetchall()
            a = 0
            b = 1
            for row in rows:
                # rec_data[row["TOW"]][row["Sat"]] = row["TrPR"]
                self.rec_data[row["Sat"]][row["TOW"]] = row["TrPR"]
                if a == ((self.numb / 20) * b):
                    self.emit(SIGNAL("progressBar(QString, QString, QString)"), "Prepare...", "10", str(b))
                    b += 1
                a += 1

            a = len(self.rec_data.keys())
            b = 0
            for sat in self.rec_data.keys():
                value = self.rec_data[sat]
                list_tow = sorted(value.keys())
                list_psr = []
                for tow in list_tow:
                    list_psr.append(value[tow])
                self.interpolators[sat] = InterpolatedUnivariateSpline(list_tow, list_psr, k=3)
                if a == ((a / 10) * b):
                    self.emit(SIGNAL("progressBar(QString, QString, QString)"), "Make interpolators...", str(a), str(b))
                b += 1
        self.rec_data = {}
        self.rec_data = defaultdict(dict)
        self.emit(SIGNAL("progressBar(QString, QString, QString)"), "Save as pickle file...", "0", "0")
        name = str(self.file_csv)
        name = name.split(".")
        with open(name[0] + '.pickle', 'wb') as f:
            pickle.dump(self.interpolators, f)
        self.emit(SIGNAL("progressBar(QString, QString, QString)"), "Import done...", "10", "10")
        self.emit(SIGNAL("importDone()"))

    def import_interpolators(self):
        self.emit(SIGNAL("progressBar(QString, QString, QString)"), "Load pickle file...", "0", "0")
        with open(self.file_interpolars, 'rb') as f:
            self.interpolators = pickle.load(f)
            self.emit(SIGNAL("progressBar(QString, QString, QString)"), "Import done...", "10", "10")
            self.emit(SIGNAL("importDone()"))

    def dict_factory(self, cursor, row):  # foe access to database with dick keys
        d = {}
        for idx, col in enumerate(cursor.description):
            d[col[0]] = row[idx]
        return d

    def waitForData(self):
        mutex_accu.lock()
        waitCondition_accu.wait(mutex_ttf)  # wait on TTFF
        mutex_accu.unlock()

    def init_reset(self):
        self.interpolators = {}
        #
        self.TOW_ref = 0
        self.file_stat = True
        self.import_done = False
        self.numb = 0
        # new data
        self.rec_data = defaultdict(dict)
        self.multi_dic = {}


# ----------------------------------------------------------------------------------------------------------------------
# ----------------------------------------------Objects-----------------------------------------------------------------
class MyTableModel(QAbstractTableModel):
    def __init__(self, parent, mylist, myheader, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.mylist = mylist
        self.header = myheader

    def rowCount(self, parent):
        return len(self.mylist)

    def columnCount(self, parent):
        return len(self.header)

    def data(self, index, role):
        if not index.isValid():
            return None
        elif role != Qt.DisplayRole:
            return None
        return self.mylist[index.row()][index.column()]

    def headerData(self, col, orientation, role):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self.header[col]
        return None

    def sort(self, col, order):
        """sort table by given column number col"""
        self.emit(SIGNAL("layoutAboutToBeChanged()"))
        self.mylist = sorted(self.mylist, key=operator.itemgetter(col))
        if order == Qt.DescendingOrder:
            self.mylist.reverse()
        self.emit(SIGNAL("layoutChanged()"))


class MatplotlibWidget(QWidget):
    def __init__(self, parent=None):
        super(MatplotlibWidget, self).__init__(parent)
        self.x = []
        self.y = []
        self.sat_el = []
        self.sat_az = []
        self.sat_prn = []
        self.sat_srn = []
        self.sat_el_1 = []
        self.sat_az_1 = []
        self.sat_el_2 = []
        self.sat_az_2 = []
        self.sat_el_3 = []
        self.sat_az_3 = []
        self.sat_el_4 = []
        self.sat_az_4 = []
        # self.sat_data_el = [self.sat_el_1, self.sat_el_2, self.sat_el_3, self.sat_el_4]
        # self.sat_data_az = [self.sat_az_1, self.sat_az_2, self.sat_az_3, self.sat_az_4]
        plt.ion()
        self.figure = Figure()

        self.axis = self.figure.add_subplot(121)
        self.axis.set_title("GPS location")
        self.axis.set_xlabel("Longitude [degrees]")
        self.axis.set_ylabel("Latitude [degrees]")
        self.axis.set_xlim(BLX, TRX)
        self.axis.set_ylim(BLY, TRY)
        self.axis.hold(True)
        self.axis.set_autoscale_on(False)
        path = os.path.normpath("\data\map.png")
        path = os.path.normpath(os.getcwd()) + path
        im = plt.imread(path)
        self.axis.imshow(im, extent=[BLX, TRX, BLY, TRY])
        self.points, = self.axis.plot(self.x, self.y, "o")
        self.background_position = None

        self.axis_satellite = self.figure.add_subplot(122, projection="polar")
        self.axis_satellite.set_title("GPS Satellite")
        for label in self.axis_satellite.xaxis.get_ticklabels():
            label.set_color("red")
            label.set_rotation(0)
            label.set_fontsize(10)
        self.axis_satellite.set_ylim(0, 90)
        self.axis_satellite.hold(True)
        self.points_satellite, = self.axis_satellite.plot(self.sat_el, self.sat_az, "o")
        self.background_satellite = None

        self.canvas = FigureCanvasQTAgg(self.figure)

        self.layoutVertical = QVBoxLayout(self)
        self.layoutVertical.addWidget(self.canvas)
        # self.canvas.show()
        # self.canvas.draw()


class UniversalGraph(QWidget):
    def __init__(self, parent=None):
        super(UniversalGraph, self).__init__(parent)
        self.x = []
        self.y = []
        self.title = "Graph "
        self.title_x = ""
        self.title_y = ""
        self.x_label = "x label"
        self.y_label = "y label"

        plt.ion()
        self.figure = Figure()
        self.axis = self.figure.add_subplot(111)
        self.axis.set_title(self.title)
        self.axis.set_xlabel(self.x_label)
        self.axis.set_ylabel(self.y_label)

        # self.axis.hold(False)
        self.axis.set_autoscale_on(True)
        self.axis.relim()
        self.axis.autoscale_view(True, True, True)

        self.points, = self.axis.plot(self.x, self.y, "o")

        self.background_position = None

        self.canvas = FigureCanvasQTAgg(self.figure)

        self.layoutVertical = QVBoxLayout(self)
        self.layoutVertical.addWidget(self.canvas)

        self.canvas.draw()
        self.canvas.show()
