def __init__(self, MBD_system, parent=None, flags=0):
        """
        Constructor
        """
        super(SimulationControlWidget, self).__init__(parent)
        self._parent = parent
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        self.ui.simulationStopButton.setEnabled(False)
        self.ui.simulationResetButton.setEnabled(False)
        
        self.ui.forwardButton.setEnabled(False)
        self.ui.backwardButton.setEnabled(False)
        self.ui.playButton.setEnabled(False)
        
        self.MBD_system = MBD_system

        #   when simulation is finishes
        #   automatically load solution file
        self.ui.loadSolutionFileStatus.setChecked(self.MBD_system.loadSolutionFileWhenFinished)
        #   restore initial conditions
        self.ui.restoreInitialConditionsStatus.setChecked(self.MBD_system.restoreInitialConditionsWhenFinished)

        #    sets opengl widget in central widget position
        self.opengl_widget = OpenGLWidget(MBD_system=MBD_system, parent=self._parent)
        
        self._status = "simulation"  # simulation or animation

        #   set integration method to display
        try:
            _index = self.ui.integrationMethodComboBox.findText(QtCore.QString(self.MBD_system.integrationMethod.title()))
        except:
            _index = 0

        if _index != -1:
            self.ui.integrationMethodComboBox.setCurrentIndex(_index)
        else:
            self.ui.integrationMethodComboBox.setCurrentIndex(_index)
        
        #    signals
        self.step_num_signal = stepSignal()
        self.energy_signal = EnergySignal()
        self.status_signal = StatusSignal()
        
#         self.graphWidget = None
#         self.graphWidget = GraphWidget(MBD_system=MBD_system_, parent=parent)
#         self.graphWidget.setWindowFlags(parent.windowFlags())
#         self.graphWidget.show()

        #    set validators to limit user input
        __validator_dbl = QtGui.QDoubleValidator()
        __validator_int = QtGui.QIntValidator()
        
        #    predefined values
        #    end time
        self.ui.endTime.setText(str(self.MBD_system.t_n))
        self.ui.endTime.setValidator(__validator_dbl)

        # self.ui.simulation_progressBar.setMinimum(0)
        # self.ui.simulation_progressBar.setMaximum(int(1/self.MBD_system.t_n))
        # self.ui.simulation_progressBar.setValue(0)
        
        #    Hmax
        if self.MBD_system.t_n/100 < self.MBD_system.Hmax:
            self.MBD_system.Hmax = 0.01*self.MBD_system.t_n

        #   Hmin
        self.MBD_system.evaluate_Hmin()

        self.ui.Hmax.setText(str(self.MBD_system.Hmax))
        self.ui.Hmax.setValidator(__validator_dbl)
        
        #    Hmin
        self.ui.Hmin.setText(str(self.MBD_system.Hmin))
        self.ui.Hmin.setValidator(__validator_dbl)
        #    abs tol
        self.ui.absTol.setText(str(self.MBD_system.absTol))
        self.ui.absTol.setValidator(__validator_dbl)
        #    rel tol
        self.ui.relTol.setText(str(self.MBD_system.relTol))
        self.ui.relTol.setValidator(__validator_dbl)
        #   tolerance for newton differences
        self.ui.TOL_dq_i.setText(str(self.MBD_system.TOL_dq_i))
        #   tolerance for constraint equations C
        self.ui.TOL_C.setText(str(self.MBD_system.TOL_C))
        #    create solver thread
        self.solver = Solver(MBD_system=MBD_system, parent=self)#parent
        self._solver_thread = QThread()
        self._solver_thread.start()
        self.solver.moveToThread(self._solver_thread)

        #   display update
        self._update_display_type = "dt"
        #   available options
        self._update_display_types = ["dt",
                              "step"]
        #   update display on every i-th simulation step
        self.ui.updateStep_lineEdit.setText(str(int(self.solver.analysis.update_opengl_widget_every_Nth_step)))
        self.ui.updateStep_lineEdit.setValidator(__validator_int)
        self._delta_step = self.solver.analysis.update_opengl_widget_every_Nth_step
        #   update display on dt of simulation time
        #   default value
        self._dt = self.MBD_system.t_n / 100.


        self.ui.currentStep_lineEdit.setEnabled(False)
        self.ui.currentStep_lineEdit.setValidator(__validator_int)

        #    connections and signals
        self.ui.simulationStartButton.clicked.connect(self.simulationStart)
        self.ui.simulationStartButton.clicked.connect(self.solver.start_solver)
        
        self.ui.simulationStopButton.clicked.connect(self.simulationStop)
        self.ui.simulationStopButton.clicked.connect(self.solver.stop_solver)

        
        self.solver.analysis.finished_signal.signal_finished.connect(self.simulationFinished)
        self.solver.analysis.filename_signal.signal_filename.connect(self.__automaticaly_load_solution_file)

        self.solver.analysis.solution_signal.solution_data.connect(self.__automaticaly_load_solution_file)
        self.solver.analysis.solution_signal.solution_data.connect(self._parent.TreeViewWidget.add_solution_data)


        self.ui.simulationResetButton.clicked.connect(self.simulationReset)

        self.ui.Hmax.textChanged.connect(self.__update_Hmax)
        self.ui.Hmin.textChanged.connect(self.__update_Hmin)
        
        self.ui.loadSolutionFileStatus.stateChanged.connect(self.__update_loadSolutionFileWhenFinished)
        
        self.ui.currentStep_lineEdit.textChanged.connect(self.__update_currentStep)
        self.ui.updateStep_lineEdit.textChanged.connect(self.__update_updateStep)
        self.ui.endTime.textChanged.connect(self.__update_endTime)


        self.ui.backwardButton.clicked.connect(self.animation_backward) #clicked
        self.ui.forwardButton.clicked.connect(self.animation_forward)
        self.ui.playButton.clicked.connect(self.animationPlay)
        

        #    signal repaintGL.signal_repaintGL from self.solver triggers self.opengl_widget.repaintGL
        self.solver.analysis.repaintGL_signal.signal_repaintGL.connect(self.opengl_widget.repaintGL)

        #   signal for take a snapshot
        self.solver.analysis.save_screenshot_signal.signal_saveScreenshot.connect(self.take_snapshot)

        #   signal time integration error
        self.solver.analysis.error_time_integration_signal.signal_time_integration_error.connect(self._time_integration_error)

        #   change integration method
        self.ui.integrationMethodComboBox.currentIndexChanged.connect(self.selectedIntegrationMethod)

        self._parent.TreeViewWidget.create_animation_file.signal_createAnimationFile.connect(self._create_animation_file)

        #   profiler
        self.profile = cProfile.Profile()

        #   analysis type
        self.ui.analysisTypeComboBox.currentIndexChanged.connect(self._analysis_type_changed)

        #   set analysis type to display it in combobox
        if self.MBD_system.analysis_type is not None:
            _index = self.ui.analysisTypeComboBox.findText(QtCore.QString(self.MBD_system.analysis_type.title()))
            self.ui.analysisTypeComboBox.setCurrentIndex(_index)


        #   video maker thread to create video
        self.video_maker = VideoMaker(parent=self)
class SimulationControlWidget(QtGui.QWidget):
    """
    Control panel GUI
    """
    def __init__(self, MBD_system, parent=None, flags=0):
        """
        Constructor
        """
        super(SimulationControlWidget, self).__init__(parent)
        self._parent = parent
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        self.ui.simulationStopButton.setEnabled(False)
        self.ui.simulationResetButton.setEnabled(False)
        
        self.ui.forwardButton.setEnabled(False)
        self.ui.backwardButton.setEnabled(False)
        self.ui.playButton.setEnabled(False)
        
        self.MBD_system = MBD_system

        #   when simulation is finishes
        #   automatically load solution file
        self.ui.loadSolutionFileStatus.setChecked(self.MBD_system.loadSolutionFileWhenFinished)
        #   restore initial conditions
        self.ui.restoreInitialConditionsStatus.setChecked(self.MBD_system.restoreInitialConditionsWhenFinished)

        #    sets opengl widget in central widget position
        self.opengl_widget = OpenGLWidget(MBD_system=MBD_system, parent=self._parent)
        
        self._status = "simulation"  # simulation or animation

        #   set integration method to display
        try:
            _index = self.ui.integrationMethodComboBox.findText(QtCore.QString(self.MBD_system.integrationMethod.title()))
        except:
            _index = 0

        if _index != -1:
            self.ui.integrationMethodComboBox.setCurrentIndex(_index)
        else:
            self.ui.integrationMethodComboBox.setCurrentIndex(_index)
        
        #    signals
        self.step_num_signal = stepSignal()
        self.energy_signal = EnergySignal()
        self.status_signal = StatusSignal()
        
#         self.graphWidget = None
#         self.graphWidget = GraphWidget(MBD_system=MBD_system_, parent=parent)
#         self.graphWidget.setWindowFlags(parent.windowFlags())
#         self.graphWidget.show()

        #    set validators to limit user input
        __validator_dbl = QtGui.QDoubleValidator()
        __validator_int = QtGui.QIntValidator()
        
        #    predefined values
        #    end time
        self.ui.endTime.setText(str(self.MBD_system.t_n))
        self.ui.endTime.setValidator(__validator_dbl)

        # self.ui.simulation_progressBar.setMinimum(0)
        # self.ui.simulation_progressBar.setMaximum(int(1/self.MBD_system.t_n))
        # self.ui.simulation_progressBar.setValue(0)
        
        #    Hmax
        if self.MBD_system.t_n/100 < self.MBD_system.Hmax:
            self.MBD_system.Hmax = 0.01*self.MBD_system.t_n

        #   Hmin
        self.MBD_system.evaluate_Hmin()

        self.ui.Hmax.setText(str(self.MBD_system.Hmax))
        self.ui.Hmax.setValidator(__validator_dbl)
        
        #    Hmin
        self.ui.Hmin.setText(str(self.MBD_system.Hmin))
        self.ui.Hmin.setValidator(__validator_dbl)
        #    abs tol
        self.ui.absTol.setText(str(self.MBD_system.absTol))
        self.ui.absTol.setValidator(__validator_dbl)
        #    rel tol
        self.ui.relTol.setText(str(self.MBD_system.relTol))
        self.ui.relTol.setValidator(__validator_dbl)
        #   tolerance for newton differences
        self.ui.TOL_dq_i.setText(str(self.MBD_system.TOL_dq_i))
        #   tolerance for constraint equations C
        self.ui.TOL_C.setText(str(self.MBD_system.TOL_C))
        #    create solver thread
        self.solver = Solver(MBD_system=MBD_system, parent=self)#parent
        self._solver_thread = QThread()
        self._solver_thread.start()
        self.solver.moveToThread(self._solver_thread)

        #   display update
        self._update_display_type = "dt"
        #   available options
        self._update_display_types = ["dt",
                              "step"]
        #   update display on every i-th simulation step
        self.ui.updateStep_lineEdit.setText(str(int(self.solver.analysis.update_opengl_widget_every_Nth_step)))
        self.ui.updateStep_lineEdit.setValidator(__validator_int)
        self._delta_step = self.solver.analysis.update_opengl_widget_every_Nth_step
        #   update display on dt of simulation time
        #   default value
        self._dt = self.MBD_system.t_n / 100.


        self.ui.currentStep_lineEdit.setEnabled(False)
        self.ui.currentStep_lineEdit.setValidator(__validator_int)

        #    connections and signals
        self.ui.simulationStartButton.clicked.connect(self.simulationStart)
        self.ui.simulationStartButton.clicked.connect(self.solver.start_solver)
        
        self.ui.simulationStopButton.clicked.connect(self.simulationStop)
        self.ui.simulationStopButton.clicked.connect(self.solver.stop_solver)

        
        self.solver.analysis.finished_signal.signal_finished.connect(self.simulationFinished)
        self.solver.analysis.filename_signal.signal_filename.connect(self.__automaticaly_load_solution_file)

        self.solver.analysis.solution_signal.solution_data.connect(self.__automaticaly_load_solution_file)
        self.solver.analysis.solution_signal.solution_data.connect(self._parent.TreeViewWidget.add_solution_data)


        self.ui.simulationResetButton.clicked.connect(self.simulationReset)

        self.ui.Hmax.textChanged.connect(self.__update_Hmax)
        self.ui.Hmin.textChanged.connect(self.__update_Hmin)
        
        self.ui.loadSolutionFileStatus.stateChanged.connect(self.__update_loadSolutionFileWhenFinished)
        
        self.ui.currentStep_lineEdit.textChanged.connect(self.__update_currentStep)
        self.ui.updateStep_lineEdit.textChanged.connect(self.__update_updateStep)
        self.ui.endTime.textChanged.connect(self.__update_endTime)


        self.ui.backwardButton.clicked.connect(self.animation_backward) #clicked
        self.ui.forwardButton.clicked.connect(self.animation_forward)
        self.ui.playButton.clicked.connect(self.animationPlay)
        

        #    signal repaintGL.signal_repaintGL from self.solver triggers self.opengl_widget.repaintGL
        self.solver.analysis.repaintGL_signal.signal_repaintGL.connect(self.opengl_widget.repaintGL)

        #   signal for take a snapshot
        self.solver.analysis.save_screenshot_signal.signal_saveScreenshot.connect(self.take_snapshot)

        #   signal time integration error
        self.solver.analysis.error_time_integration_signal.signal_time_integration_error.connect(self._time_integration_error)

        #   change integration method
        self.ui.integrationMethodComboBox.currentIndexChanged.connect(self.selectedIntegrationMethod)

        self._parent.TreeViewWidget.create_animation_file.signal_createAnimationFile.connect(self._create_animation_file)

        #   profiler
        self.profile = cProfile.Profile()

        #   analysis type
        self.ui.analysisTypeComboBox.currentIndexChanged.connect(self._analysis_type_changed)

        #   set analysis type to display it in combobox
        if self.MBD_system.analysis_type is not None:
            _index = self.ui.analysisTypeComboBox.findText(QtCore.QString(self.MBD_system.analysis_type.title()))
            self.ui.analysisTypeComboBox.setCurrentIndex(_index)


        #   video maker thread to create video
        self.video_maker = VideoMaker(parent=self)

    def _analysis_type_changed(self):
        """
        Function assignes new value to object attribute if it is changed by user in combo box
        :return:
        """
        self.MBD_system.analysis_type = self.ui.analysisTypeComboBox.currentText().toLower()
        
        if str(self.ui.analysisTypeComboBox.currentText()).lower() == "kinematic":
            self.ui.integrationMethodComboBox.setEnabled(False)
        else:
            self.ui.integrationMethodComboBox.setEnabled(True)

    @pyqtSlot()
    def profile_functions(self):
        """
        Function profiles main functions that are used in numerical integration
        :return:
        """
        print "profile here"
        self.profile.enable()
        self.solver.analysis.DAE_fun.evaluate_M()
        self.profile.disable()
        self.profile.print_stats()

    def _time_integration_error(self):
        """

        :return:
        """
        QtGui.QMessageBox.critical(self._parent, "Error!", "Hmin exceeded! Procedure failed!",QtGui.QMessageBox.Ok, QtGui.QMessageBox.NoButton,QtGui.QMessageBox.NoButton)

    def __update_loadSolutionFileWhenFinished(self):
        """
        
        """

        if self.ui.loadSolutionFileStatus.isChecked():
            self.MBD_system.loadSolutionFileWhenFinished = True
        else:
            self.MBD_system.loadSolutionFileWhenFinished = False

    def __update_currentStep(self):
        """
        
        """
        try:
            self._step = int(self.ui.currentStep_lineEdit.text())
            self.MBD_system.update_coordinates_and_angles_of_all_bodies(self.q[self._step, :])
            self.MBD_system.update_simulation_properties(time=self.t[self._step], step_num=self._step)
            self.step_num_signal.signal_step.emit(self._step)
            self._update_GL()
        except:
            pass

    def __automaticaly_load_solution_file(self, solution_data_object_ID=None, filename=None):
        """
        Function loads solution data from input:
        if input is filename solution data is read from specified file
        if input is solution data object, solution is read from object attribute solution_data
        :param filename:                a filename of the solution data file
        :param solution_data_object:    a solution data object with attribute solution_data
        :return: None
        """
        if self.MBD_system.loadSolutionFileWhenFinished:
            self.load_solution_file(solution_data_object_ID, filename)

    def load_solution_file(self, solution_object_id=None, filename=None):
        """
        Function loads solution data from object (first) or from file (second)
        """
        if solution_object_id is None:
            #   assign solution data from solution data object to ne variable
            solution_data = self.solver.analysis._solution_data.load_solution_data()
        elif filename is not None:
            pass
        else:
            print "Solution data not loaded!"

        # if filename is not None and solution_object_id is None:
        #     solution_data = self.solver.analysis.load_simulation_solution_from_file(filename)

        #   assign a solution data object to pointer of object attribute
        for sol in self.MBD_system.solutions:
            if id(sol) == solution_object_id:
                self.MBD_system.loaded_solution = sol
                solution_data = sol.solution_data

        self.step = solution_data[:, 0]
        self.energy = solution_data[:, 1]
        self.error = solution_data[:, 2]
        self.dt = solution_data[:, 3]
        self.t = solution_data[:, 4]
        self.q = solution_data[:, 5:]

        self._step = 0
        
        self._status = "animation"
        
        self.ui.forwardButton.setEnabled(True)
        self.ui.backwardButton.setEnabled(False)
        self.ui.playButton.setEnabled(True)
        self.ui.currentStep_lineEdit.setEnabled(True)
        
        self.ui.currentStep_lineEdit.setText(str(int(self._step)))
        
        self.ui.solutionFileLoaded_display.setText(filename)
        self.ui.numberOfSteps_lineEdit.setText(str(int(len(self.step)-1)))
        self._update_GL()
        
        # self.status_signal.signal_status.emit("Animation")

        if self.MBD_system.restoreInitialConditionsWhenFinished:
            self.simulationReset()

    def _update_GL(self):
        """
        
        """
        self.ui.currentStep_lineEdit.setText(str(int(self._step)))
        self.MBD_system.update_coordinates_and_angles_of_all_bodies(self.q[int(self._step), :])
        self.opengl_widget.repaintGL(int(self._step))
        
        #    energy data signal
        _energy = self.energy[self._step]
        _energy_delta = _energy - self.energy[int(self._step)-1]
        self.energy_signal.signal_energy.emit(_energy, _energy_delta)

    def animation_forward(self):
        """
        Go to next solution time step
        """
        if (self._step + self._delta_step) <= self.step[-1]:
            self._step += int(self._delta_step)
            self._update_GL()
            self.ui.backwardButton.setEnabled(True)
        else:
            self.ui.forwardButton.setEnabled(False)

    def animation_backward(self):
        """
        Return to prevouos solution time step
        """
        if (self._step - self._delta_step) >= self.step[0]:
            self._step -= int(self._delta_step)
            self._update_GL()
            self.ui.forwardButton.setEnabled(True)
        else:
            self.ui.backwardButton.setEnabled(False)

    def take_snapshot(self):
        """
        Create a snapshot
        """
        captured_figure = self.opengl_widget.takeSnapShot()
        captured_figure.save(self.solver.analysis.screenshot_filename_abs_path + '.png', 'png')

    def selectedIntegrationMethod(self, int):
        """
        Assign a selected integration method to object attribute
        """
        self.MBD_system.integrationMethod = str(self.ui.integrationMethodComboBox.currentText())
    
    def __update_updateStep(self):
        """

        :return:
        """
        self.solver.analysis.update_opengl_widget_every_Nth_step = int(self.ui.updateStep_lineEdit.text())
        self._delta_step = int(self.ui.updateStep_lineEdit.text())
        self.MBD_system.updateEveryIthStep = self._delta_step

    def __update_Hmax(self):
        """

        :return:
        """
        try:
            self.Hmax = float(self.ui.Hmax.text()) 
            self.MBD_system.Hmax = self.Hmax
#             self.solver.update_simulation_control_parameters(dt_=self.stepSize)
        except:
            None

    def __update_Hmin(self):
        try:
            self.Hmin = float(self.ui.Hmin.text())
            self.MBD_system.Hmin = self.Hmin
            self.solver.update_simulation_control_parameters(dt_=self.stepSize)
        except:
            None

    def __update_endTime(self):
        """

        :return:
        """
        self.endTime = float(self.ui.endTime.text())
        self.MBD_system.t_n = self.endTime

    def setWindowFlags(self, flags):
        super(SimulationControlWidget, self).setWindowFlags(flags)

    def simulationStart(self):
        if not self.solver.analysis.running:
            self.job_info_time_started = time.clock()
            self.solver.analysis.running = True
            self.solver.analysis.stopped = False
            self.solver.analysis.finished = False

            self.ui.simulationStartButton.setEnabled(False)
            self.ui.simulationResetButton.setEnabled(False)
            self.ui.simulationStopButton.setEnabled(True)
            
    def simulationStop(self):
        if self.solver.analysis.running:
            self.solver.analysis.stopped = True
            
            self.ui.simulationStartButton.setEnabled(True)
            self.ui.simulationStopButton.setEnabled(False)
            self.ui.simulationResetButton.setEnabled(True)

    def simulationFinished(self):
        self.ui.simulationStopButton.setEnabled(False)
        self.ui.simulationResetButton.setEnabled(True)
        self.job_info_time_finished = time.clock()

    def simulationReset(self):
        self.solver.analysis.restore_initial_condition()
        # self.ui.simulationResetButton.setEnabled(False)
        self.ui.simulationStartButton.setEnabled(True)

    def animationPlay(self):
        """
        Function plays animation when solution data is loaded
        :return:
        """
        if self._update_display_type == "step":
            for _step in xrange(0, len(self.step), int(self._delta_step)):
                self._step = int(_step)
                self._update_GL()

                time.sleep(self.ui.playbackSpeed_doubleSpinBox.value()*1E-2)

        if self._update_display_type == "dt":
            _t = np.arange(0, self.t[-1], self._dt)
            for i in xrange(0, len(_t)):
                indx = np.argmin(abs(self.t - _t[i]))
                self._step = self.step[indx]
                self._update_GL()

                time.sleep(self.ui.playbackSpeed_doubleSpinBox.value()*1E-2)

    def _create_animation_file(self):
        """
        Function creates video file of animation
        :return:
        """
        #   starts video maker in new thread
        self.video_maker.start()