예제 #1
0
    def take_screenshot_pos(flags):
        loop = QEventLoop()
        screen_shot = Screenshot(flags)
        screen_shot.show()
        screen_shot.widget_closed.connect(loop.quit)

        loop.exec_()
        pos = screen_shot.target_img_pos
        return pos
예제 #2
0
 def data_request(self, request, bparams):
     connection_loop = QEventLoop()
     QObject.connect(self.managerAccess,
                     SIGNAL("finished( QNetworkReply* )"), connection_loop,
                     SLOT("quit()"))
     reply = self.managerAccess.post(request, bparams)
     connection_loop.exec_()  #sleep
     #reply->bytesAvailable();
     #reply.deleteLater()
     return reply
예제 #3
0
 def run_leave_animation(self):
     """
     Runs the animation that represents execution leaving this item.
     Blocks until the animation is finished.
     """
     loop = QEventLoop()
     animation = self.make_execution_leave_animation()
     animation.finished.connect(loop.quit)
     animation.start()
     if animation.state() == QParallelAnimationGroup.Running:
         loop.exec_()
예제 #4
0
def event_loop(msec):
    """Event loop to show the GUI during a unit test. 
    
    https://www.qtcentre.org/threads/23541-Displaying-GUI-events-with-QtTest
    """
    loop = QEventLoop()
    timer = QTimer()
    timer.timeout.connect(loop.quit)
    timer.setSingleShot(True)
    timer.start(msec)
    loop.exec_()
예제 #5
0
 def _run_leave_animation(self, item_name, direction, engine_state):
     """
     Runs the animation that represents execution leaving this item.
     Blocks until the animation is finished.
     """
     if direction == ExecutionDirection.BACKWARD or engine_state != SpineEngineState.RUNNING:
         return
     loop = QEventLoop()
     animation = self._make_execution_leave_animation(item_name)
     animation.finished.connect(loop.quit)
     animation.start()
     if animation.state() == QParallelAnimationGroup.Running:
         loop.exec_()
예제 #6
0
def fix_pyside_exec(namespace):
    if namespace.get("__name__") == "AnyQt.QtWidgets":
        from PySide2.QtWidgets import QApplication, QDialog, QMenu
        if "exec" not in QApplication.__dict__:
            QApplication.exec = lambda self: QApplication.exec_()
        if not hasattr(QDialog, "exec"):
            QDialog.exec = lambda self: QDialog.exec_(self)
        if not hasattr(QMenu, "exec"):
            QMenu.exec = lambda self: QMenu.exec_(self)
    if namespace.get("__name__") == "AnyQt.QtGui":
        from PySide2.QtGui import QGuiApplication, QDrag
        if "exec" not in QGuiApplication.__dict__:
            QGuiApplication.exec = lambda self: QGuiApplication.exec_()
        if not hasattr(QDrag, "exec"):
            QDrag.exec = (lambda self, *args, **kwargs: QDrag.exec_(
                self, *args, **kwargs))
    elif namespace.get("__name__") == "AnyQt.QtCore":
        from PySide2.QtCore import QCoreApplication, QEventLoop, QThread
        if not hasattr(QCoreApplication, "exec"):
            QCoreApplication.exec = lambda self: QCoreApplication.exec_()
        if not hasattr(QEventLoop, "exec"):
            QEventLoop.exec = (lambda self, *args, **kwargs: QEventLoop.exec_(
                self, *args, **kwargs))
        if not hasattr(QThread, "exec"):
            QThread.exec = lambda self: QThread.exec_(self)
    elif namespace.get("__name__") == "AnyQt.QtPrintSupport":
        from PySide2.QtPrintSupport import QPageSetupDialog, QPrintDialog
        if "exec" not in QPageSetupDialog.__dict__:
            QPageSetupDialog.exec = lambda self: QPageSetupDialog.exec_(self)
        if "exec" not in QPrintDialog.__dict__:
            QPrintDialog.exec = lambda self: QPrintDialog.exec_(self)
예제 #7
0
class PlayerMoveSignal(QObject):
    def __init__(self, parent):
        super(PlayerMoveSignal, self).__init__()
        self.game = parent
        self.sig = Signal(str)
        self.eventLoop = QEventLoop(self)
        self.data = None

    @Slot(str)
    def stop_waiting(self, data):
        self.data = data
        self.eventLoop.exit()
        return

    def wait_for_move(self):
        self.eventLoop.exec_()
        return self.data
예제 #8
0
 def open(self, url, timeout=60):
     """Wait for download to complete and return result"""
     loop = QEventLoop()
     timer = QTimer()
     timer.setSingleShot(True)
     timer.timeout.connect(loop.quit)
     self.loadFinished.connect(loop.quit)
     self.load(QUrl(url))
     timer.start(timeout * 1000)
     loop.exec_()  # delay here until download finished
     if timer.isActive():
         # downloaded successfully
         timer.stop()
         return self.html()
     else:
         # timed out
         print('Request timed out:', url)
예제 #9
0
class EventLoop:
    def __init__(self, timeout_in_second: float = None):
        self.event = QEventLoop(None)
        self.timeout_in_second = timeout_in_second

    def quit(self):
        self.event.quit()

    def __enter__(self):
        return self

    def __exit__(self, *_):
        if self.timeout_in_second is not None:
            t = Timer()
            t.timeout.connect(self.quit)
            t.start(seconds=self.timeout_in_second)
        self.event.exec_()
예제 #10
0
def wait_signal(signal, timeout=1):
    """Block loop until signal emitted, or timeout (s) elapses."""
    loop = QEventLoop()
    signal.connect(loop.quit)

    yield

    timed_out = []
    if timeout is not None:

        def quit_with_error():
            timed_out.append(1)
            loop.quit()

        QTimer.singleShot(timeout * 1000, quit_with_error)
    loop.exec_()
    if timed_out:
        assert False, "Timeout while waiting for %s" % signal
예제 #11
0
 def open(self, url: str, timeout: int = 10):
     """Wait for download to complete and return result"""
     loop = QEventLoop()
     timer = QTimer()
     timer.setSingleShot(True)
     # noinspection PyUnresolvedReferences
     timer.timeout.connect(loop.quit)
     # noinspection PyUnresolvedReferences
     self.loadFinished.connect(loop.quit)
     self.load(QUrl(url))
     # noinspection PyArgumentList
     timer.start(timeout * 1000)
     loop.exec_()  # delay here until download finished
     if timer.isActive():
         # downloaded successfully
         timer.stop()
     else:
         logger.info('Request timed out: %s' % url)
예제 #12
0
 def _execute_forward(self, resources):
     """See base class."""
     if not self._settings:
         return True
     absolute_paths = _files_from_resources(resources)
     absolute_path_settings = dict()
     for label in self._settings:
         absolute_path = absolute_paths.get(label)
         if absolute_path is not None:
             absolute_path_settings[absolute_path] = self._settings[label]
     source_settings = {
         "GdxConnector": {
             "gams_directory": self._gams_system_directory()
         }
     }
     # Collect arguments for the importer_program
     import_args = [
         list(absolute_paths.values()),
         absolute_path_settings,
         source_settings,
         [
             r.url for r in self._resources_from_downstream
             if r.type_ == "database"
         ],
         self._logs_dir,
         self._cancel_on_error,
     ]
     if not self._prepare_importer_program(import_args):
         self._logger.msg_error.emit(
             f"Executing Importer {self.name} failed.")
         return False
     self._importer_process.start_execution()
     loop = QEventLoop()
     self.importing_finished.connect(loop.quit)
     # Wait for finished right here
     loop.exec_()
     # This should be executed after the import process has finished
     if not self._importer_process_successful:
         self._logger.msg_error.emit(
             f"Executing Importer {self.name} failed.")
     else:
         self._logger.msg_success.emit(
             f"Executing Importer {self.name} finished")
     return self._importer_process_successful
예제 #13
0
def wait_signal(signal, timeout=5000):
    """Block loop until signal emitted, or timeout (ms) elapses."""
    loop = QEventLoop()
    signal.connect(loop.quit)

    yield

    if timeout:
        timer = QTimer()
        timer.setInterval(timeout)
        timer.setSingleShot(True)
        timer.timeout.connect(loop.quit)
        timer.start()
    else:
        timer = None
    loop.exec_()
    signal.disconnect(loop.quit)
    if timer and timer.isActive():
        timer.stop()
예제 #14
0
class ReadSerialPortsThread(QThread):
    """ Find connected serial ports and send it to GUI """
    add_serial_port = Signal(str)
    remove_serial_port = Signal(str)

    def __init__(self, parent=None):
        QThread.__init__(self, parent)
        self.current_port = ''
        self.result = []
        self.loop = ""

        if _platform.startswith('linux'):
            self.ports = ['/dev/ttyS%s' % (i + 1) for i in range(256)]
        elif _platform.startswith('win32'):
            self.ports = ['COM%s' % (i + 1) for i in range(256)]
        elif _platform.startswith('darwin'):
            self.ports = ['/dev/cu.serial%s' % (i + 1) for i in range(256)]

    def run(self):
        """ DOCSTRING """
        while True:
            for port in self.ports:
                if port in self.result:
                    try:
                        serial_conn = serial.Serial(port)
                        serial_conn.close()
                    except (OSError, serial.SerialException):
                        if port != self.current_port:
                            self.result.remove(port)
                            self.remove_serial_port.emit(port)
                else:
                    try:
                        serial_conn = serial.Serial(port)
                        serial_conn.close()
                        if port not in self.result:
                            self.result.append(port)
                            self.add_serial_port.emit(port)
                    except (OSError, serial.SerialException):
                        pass
            self.loop = QEventLoop()
            QTimer.singleShot(50, self.loop.quit)
            self.loop.exec_()
예제 #15
0
 def testBlockingSignal(self):
     app = QCoreApplication.instance() or QCoreApplication([])
     eventloop = QEventLoop()
     emitter = Emitter()
     receiver = Receiver(eventloop)
     emitter.connect(emitter, SIGNAL("signal(int)"), receiver.receive,
                     Qt.BlockingQueuedConnection)
     emitter.start()
     retval = eventloop.exec_()
     emitter.wait(2000)
     self.assertEqual(retval, 0)
예제 #16
0
 def testBlockingSignal(self):
     app = QCoreApplication.instance() or QCoreApplication([])
     eventloop = QEventLoop()
     emitter = Emitter()
     receiver = Receiver(eventloop)
     emitter.connect(emitter, SIGNAL("signal(int)"),
                     receiver.receive, Qt.BlockingQueuedConnection)
     emitter.start()
     retval = eventloop.exec_()
     emitter.wait()
     self.assertEqual(retval, 0)
예제 #17
0
def main():
    app = QApplication([])
    webview = QWebEngineView()
    loop = QEventLoop()
    webview.loadFinished.connect(loop.quit)
    webview.load(QUrl('http://example.webscraping.com/places/default/search'))
    loop.exec_()

    webview.show()
    frame = webview.page().mainFrame()
    frame.findFirstElement('#search_term').setAttribute('value', '.')
    frame.findFirstElement('#page_size option:checked').setPlainText('1000')
    frame.findFirstElement('#search').evaluateJavaScript('this.click()')

    elements = None
    while not elements:
        app.processEvents()
        elements = frame.findAllElements('#results a')
    countries = [e.toPlainText().strip() for e in elements]
    print(countries)
예제 #18
0
    def _run_importer_program(self, args):
        """Starts and runs the importer program in a separate process.

        Args:
            args (list): List of arguments for the importer program
        """
        self.importer_process = QProcess()
        self.importer_process.readyReadStandardOutput.connect(self._log_importer_process_stdout)
        self.importer_process.readyReadStandardError.connect(self._log_importer_process_stderr)
        self.importer_process.finished.connect(self.importer_process.deleteLater)
        program_path = os.path.abspath(importer_program.__file__)
        self.importer_process.start(sys.executable, [program_path])
        self.importer_process.waitForStarted()
        self.importer_process.write(json.dumps(args).encode("utf-8"))
        self.importer_process.write(b'\n')
        self.importer_process.closeWriteChannel()
        if self.importer_process.state() == QProcess.Running:
            loop = QEventLoop()
            self.importer_process.finished.connect(loop.quit)
            loop.exec_()
        return self.importer_process.exitCode()
예제 #19
0
 def _execute_forward(self, resources):
     """See base class."""
     from_urls = self._urls_from_resources(resources)
     to_urls = self._urls_from_resources(self._resources_from_downstream)
     if not from_urls or not to_urls:
         # Moving on...
         return True
     combiner_args = [from_urls, to_urls, self._logs_dir, self._cancel_on_error]
     if not self._prepare_combiner_program(combiner_args):
         self._logger.msg_error.emit(f"Executing Combiner {self.name} failed.")
         return False
     self._combiner_process.start_execution()
     loop = QEventLoop()
     self.recombination_finished.connect(loop.quit)
     # Wait for finished right here
     loop.exec_()
     # This should be executed after the import process has finished
     if not self._combiner_process_successful:
         self._logger.msg_error.emit(f"Executing Combiner {self.name} failed.")
     else:
         self._logger.msg_success.emit(f"Executing Combiner {self.name} finished")
     return self._combiner_process_successful
예제 #20
0
    def wait():
        # loop = QEventLoop()
        # QTimer.singleShot(delay * 1000, loop.quit)
        # loop.exec_()

        loop = QEventLoop()
        timer = QTimer()
        timer.setSingleShot(True)
        timer.timeout.connect(loop.quit)

        if append:
            TIMER_RUNNING.append(timer)
            LOOP_RUNNING.append(loop)

            timer.start(delay * 1000)
            loop.exec_()

            TIMER_RUNNING.remove(timer)
            LOOP_RUNNING.remove(loop)
        else:
            timer.start(delay * 1000)
            loop.exec_()
예제 #21
0
    def initCamera(self,
                   resolution=(640, 480),
                   monochrome=False,
                   framerate=24,
                   effect='none',
                   use_video_port=True):
        # multiple streams are only possible eith the video port!
        self.msg(self.name + "Init: resolution = " + str(resolution))
        self.camera.resolution = resolution
        self.camera.image_effect = effect
        self.camera.image_effect_params = (2, )
        self.camera.iso = 100  # should force unity analog gain
        self.monochrome = monochrome  # spoils edges
        self.camera.framerate = framerate
        if self.monochrome:
            self.rawCapture = PiYArray(self.camera,
                                       size=self.camera.resolution)
            #             self.PreviewArray = PiYArray(self.camera, size=(640,480))
            self.stream = self.camera.capture_continuous(self.rawCapture,
                                                         format='yuv',
                                                         use_video_port=True,
                                                         splitter_port=0)
#             self.previewStream = self.camera.capture_continuous(output=self.PreviewArray, format='yuv', use_video_port=True, splitter_port=1, resize=(640,480))
        else:
            self.rawCapture = PiRGBArray(self.camera,
                                         size=self.camera.resolution)
            #             self.PreviewArray = PiRGBArray(self.camera, size=(640,480))
            self.stream = self.camera.capture_continuous(self.rawCapture,
                                                         format='bgr',
                                                         use_video_port=True,
                                                         splitter_port=0)
#             self.previewStream = self.camera.capture_continuous(output=self.PreviewArray, format='bgr', use_video_port=True, splitter_port=1, resize=(640,480))

        GeneralEventLoop = QEventLoop(self)
        QTimer.singleShot(2, GeneralEventLoop.exit)
        GeneralEventLoop.exec_()
 def test_duplicate_object_in_object_tree_model(self):
     data = dict()
     data["object_classes"] = ["fish", "dog"]
     data["relationship_classes"] = [("fish__dog", ("fish", "dog"))]
     data["objects"] = [("fish", "nemo"), ("dog", "pluto")]
     data["relationships"] = [("fish__dog", ("nemo", "pluto"))]
     data["object_parameters"] = [("fish", "color")]
     data["object_parameter_values"] = [("fish", "nemo", "color", "orange")]
     with mock.patch(
             "spinetoolbox.spine_db_manager.SpineDBManager.entity_class_icon"
     ) as mock_icon:
         mock_icon.return_value = None
         loop = QEventLoop()
         self.db_mngr.data_imported.connect(loop.quit)
         self.db_mngr.import_data({self.db_map: data})
         loop.exec_()
         loop.deleteLater()
         mock_icon.assert_called()
     self.fetch_object_tree_model()
     root_item = self.spine_db_editor.object_tree_model.root_item
     fish_item = next(
         iter(item for item in root_item.children
              if item.display_data == "fish"))
     nemo_item = fish_item.child(0)
     with mock.patch(
             "spinetoolbox.spine_db_editor.widgets.tree_view_mixin.QInputDialog"
     ) as mock_input_dialog:
         mock_input_dialog.getText.side_effect = lambda *args, **kwargs: (
             "nemo_copy", True)
         loop = QEventLoop()
         self.db_mngr.data_imported.connect(loop.quit)
         self.spine_db_editor.duplicate_object(nemo_item.index())
         loop.exec_()
         loop.deleteLater()
     nemo_dupe = fish_item.child(1)
     self.assertEqual(nemo_dupe.display_data, "nemo_copy")
예제 #23
0
class Page(QWebEnginePage):
    def __init__(self, view):
        super(Page, self).__init__()
        self.parent = view.parent
        self.view = view
        self.result = None
        self.fullView = QWebEngineView()
        self.exitFSAction = QAction(self.fullView)
        self.loop = None

    def javaScriptConsoleMessage(self, level, msg, line, sourceid):
        """Override javaScriptConsoleMessage to use debug log."""
        if level == QWebEnginePage.InfoMessageLevel:
            print("JS - INFO - Ligne {} : {}".format(line, msg))
        elif level == QWebEnginePage.WarningMessageLevel:
            print("JS - WARNING - Ligne {} : {}".format(line, msg))
        else:
            print("JS - ERROR - Ligne {} : {}".format(line, msg))

    def hittestcontent(self, pos):
        return WebHitTestResult(self, pos)

    def maptoviewport(self, pos):
        return QPointF(pos.x(), pos.y())

    def executejavascript(self, scriptsrc):
        self.loop = QEventLoop()
        self.result = None
        QTimer.singleShot(250, self.loop.quit)

        self.runJavaScript(scriptsrc, self.callbackjs)
        self.loop.exec_()
        self.loop = None
        return self.result

    def callbackjs(self, res):
        if self.loop is not None and self.loop.isRunning():
            self.result = res
            self.loop.quit()

    def vsource(self):
        if "view-source:http" in self.url().toString():
            self.load(QUrl(self.url().toString().split("view-source:")[1]))
        else:
            self.triggerAction(self.ViewSource)

    def makefullscreen(self, request):
        if request.toggleOn():
            self.fullView = QWebEngineView()
            self.exitFSAction = QAction(self.fullView)
            self.exitFSAction.setShortcut(Qt.Key_Escape)
            self.exitFSAction.triggered.connect(
                lambda: self.triggerAction(self.ExitFullScreen))

            self.fullView.addAction(self.exitFSAction)
            self.setView(self.fullView)
            self.fullView.showFullScreen()
            self.fullView.raise_()
        else:
            del self.fullView
            self.setView(self.view)
        request.accept()
class BatchProcessor():
    signals = signal.signalClass()
    GeneralEventLoop = None
    SnapshotEventLoop = None
    SnapshotTaken = False
    is_active = False
    well_positioner = None
    Well_Map = None
    Well_Targets = None
    ID = str
    info = str
    duration = 0
    interleave = 0
    start_time = 0
    end_time = 0
    logging = True

    ## @brief BatchProcessor()::__init__ sets the batch settings
    ## @param well_controller is the well positioning class instance used to position the wells under the camera.
    ## @param well_map is the list of target wells with their positions in mm of both row and column.
    ## @param well_targets is the list of the target wells with their column and row index positions and ID.
    ## @param ID is the batch ID.
    ## @param info is the batch information.
    ## @param dur is the batch duration.
    ## @param interl is the time between the photographing of each well.
    def __init__(self, well_controller, well_map, well_targets, ID, info, path,
                 dur, interl):
        #super().__init__()
        self.is_active = False
        self.well_positioner = well_controller
        self.Well_Map = well_map
        self.Well_Targets = well_targets
        self.batch_id = ID
        self.batch_info = info
        self.duration = dur
        self.interleave = interl
        self.path = os.path.sep.join([path, ID])
        if not os.path.exists(self.path):
            os.makedirs(self.path)

    ## @brief BatchProcessor()::msg emits the message signal. This emit will be catched by the logging slot function in main.py.
    ## @param message is the string message to be emitted.
    @Slot(str)
    def msg(self, message):
        if message:
            self.signals.mes.emit(self.__class__.__name__ + ": " +
                                  str(message))
        return

    ## @brief BatchProcessor()::updateBatchSettings(self, well_data, ID, info, dur, interl) can be called to update the batch settings during runtime.
    ## @todo well_data update in MainWindow.
    ## @depricated, BatchProcessor::updateBatchSettings not in use yet. Function might be usefull when updating the batch.ini via the GUI.
    ## @param well_data is the list of target wells with their positions/indexes.
    ## @param ID is the batch ID.
    ## @param info is the batch information.
    ## @param dur is the batch duration.
    ## @param interl is the time between the photographing of each well.
    def updateBatchSettings(self, well_map, well_targets, ID, info, dur,
                            interl):
        self.is_active = False
        self.Well_Map = well_map
        self.Well_Targets = well_targets
        self.batch_id = ID
        self.batch_info = info
        self.duration = dur
        self.interleave = interl
        return

    ## @brief BatchProcessor()::startBatch(self) starts the batch process by setting the current (start)time and the endtime.
    ## It disables the manual motor control and emits the batch_active signal
    ## @todo call updateBatchSettings function
    @Slot()
    def startBatch(self):
        self.start_time = current_milli_time()
        self.end_time = current_milli_time() + (self.duration * 1000)
        self.well_positioner.reset_current_well()
        self.signals.batch_active.emit()
        self.is_active = True
        self.msg("Batch process initialized and started with:\n\tDuration: " +
                 str(self.duration) + "\n\tInterleave: " +
                 str(self.interleave) + "\n\tStart_time: " +
                 str(self.start_time) + "\n\tEnd_time: " + str(self.end_time))
        print("Batch process initialized and started with:\n\tDuration: " +
              str(self.duration) + "\n\tInterleave: " + str(self.interleave) +
              "\n\tStart_time: " + str(self.start_time) + "\n\tEnd_time: " +
              str(self.end_time))
        self.runBatch()
        return

    ## @brief BatchProcessor()::runBatch(self) runs the batch after it is started.
    ## @note the interleave is actually the interleave + processingtime of the "for target in self.Well_Targets:" loop
    def runBatch(self):
        if self.logging:
            recording_file_name = os.path.sep.join(
                [self.path, 'batch_positioning_results.csv'])
            recording_file = open(recording_file_name, "w")

            # build csv file heading
            record_str = "run_start_time, run_time,"
            for target in self.Well_Targets:
                record_str += ',' + str(
                    self.Well_Map[target[0][1]][1][1]) + ',' + str(
                        self.Well_Map[1][target[0][0]][0])
            recording_file.write(record_str + "\n")
        else:
            recording_file = None

        first_run = True
        while True:
            print("BatchProcessor thread check: " +
                  str(QThread.currentThread()))
            ## Run start time
            run_start_time = current_milli_time()
            actual_postions = []

            # Home first on avery run
            self.well_positioner.stepper_control.homeXY()

            for target in self.Well_Targets:
                if not self.is_active:
                    self.signals.batch_inactive.emit()
                    self.msg("Batch stopped.")
                    print("Batch stopped.")
                    return

                else:
                    row = target[0][0]
                    column = target[0][1]
                    self.msg("Target: " + str(target[0][2]))
                    ##                    print("Target: at (" + str(self.Well_Map[column][1][1]) + ", " + str(self.Well_Map[1][row][0]) +")" + ", first run: " + str(first_run))
                    if (self.well_positioner.goto_well(
                            self.Well_Map[column][1][1],
                            self.Well_Map[1][row][0],
                            first_run)):  ## if found well
                        self.snapshot_request(
                            str(self.batch_id) + "/" + str(target[0][2]))
                        (self.Well_Map[1][row][0], self.Well_Map[column][1][1]
                         ) = self.well_positioner.get_current_well()
                        print("  Target adapted to (" +
                              str(self.Well_Map[column][1][1]) + ", " +
                              str(self.Well_Map[1][row][0]) + ")")
                        actual_postions.append(
                            self.well_positioner.get_current_well())

                    while self.SnapshotTaken is False:
                        if not self.is_active:
                            self.signals.batch_inactive.emit()
                            #self.msg("Batch stopped, breaking out of SnapshotTaken is False while loop.")
                            print(
                                "Batch stopped, breaking out of SnapshotTaken is False while loop."
                            )
                            return
                        print("Waiting in snapshot loop")
                        self.wait_ms(50)
                    self.msg(str(target) + " finished.")
                    print(str(target) + " finished.")

                if self.end_time < current_milli_time():
                    self.msg("batch completed")
                    print("batch completed")
                    self.signals.batch_inactive.emit()
                    self.stopBatch()
                    return
                else:
                    self.msg("Remaining time " +
                             str(self.end_time - current_milli_time()))
                    print("Remaining time " +
                          str(self.end_time - current_milli_time()) + " ms")

            # first run is completed, remove this statemant to adapt to well-position in stead of feedforward
            if actual_postions:
                first_run = False

            run_time = current_milli_time() - run_start_time
            self.msg("Run time: " + str(run_time))
            print("Run time: " + str(run_time) + "\nWaiting for " +
                  str(self.interleave * 1000 - run_time) + " ms")
            if self.interleave * 1000 - run_time < 0:
                self.msg(
                    "To short interleave, please increase the interleave to at least: "
                    + str(run_time))
                print(
                    "To short interleave, please increase the interleave to at least: "
                    + str(run_time))
            else:
                ## Wait for the specified interleave minus the run_time of one run
                self.msg("Waiting for: " +
                         str(self.interleave * 1000 - run_time) + " ms")
                print("Waiting for: " +
                      str(self.interleave * 1000 - run_time) + " ms")
                self.wait_ms(self.interleave * 1000 - run_time)

            if recording_file:
                record_str = str(run_start_time) + ',' + str(run_time)
                for actual_position in actual_postions:
                    record_str += ',' + str(actual_position[0]) + ',' + str(
                        actual_position[1])
                print(record_str)
                recording_file.write(record_str + "\n")

        if recording_file:
            recording_file.close()

        #self.msg("Breaking out batch process")
        print("Finishing batch process")
        return

    ## @brief BatchProcessor()::wait_ms(self, milliseconds) is a delay function.
    ## @param milliseconds is the number of milliseconds to wait.
    def wait_ms(self, milliseconds):
        self.GeneralEventLoop = QEventLoop()
        QTimer.singleShot(milliseconds, self.GeneralEventLoop.exit)
        self.GeneralEventLoop.exec_()
        return

    ## @brief BatchProcessor()::snapshot_request(self, message) emits the self.signals.snapshot_requested signal.
    ## @param message is the pathname of the desired snapshot
    def snapshot_request(self, message):
        self.msg("Requesting snapshot")
        self.signals.snapshot_requested.emit(message)
        self.snapshot_await()
        return

    ## @brief StepperWellPositioning()::snapshot_await(self) runs an eventloop while the new snapshot is not stored in self.image yet.
    def snapshot_await(self):
        self.SnapshotTaken = False
        while self.is_active and not self.SnapshotTaken:
            #self.msg("Waiting for snapshot")
            self.SnapshotEventLoop = QEventLoop()
            QTimer.singleShot(10, self.SnapshotEventLoop.exit)
            self.SnapshotEventLoop.exec_()
        return

    @Slot()
    def snapshot_confirmed(self):
        self.SnapshotTaken = True
        if not (self.SnapshotEventLoop is None):
            self.SnapshotEventLoop.exit()
        return

    ## @brief BatchProcessor()::stopBatch is a slot function which is called when the button stopBatch is pressed on the MainWindow GUI.
    ## It stops the batch process and resets the wait eventloop if running.
    @Slot()
    def stopBatch(self):
        #self.msg("Stopping Batch process")
        print("Stopping Batch process")
        self.signals.batch_inactive.emit()
        self.signals.process_inactive.emit(
        )  ## Used to stop positioning process of function StepperWellPositioning::goto_target
        self.is_active = False
        self.snapshot_confirmed()
        if not (self.GeneralEventLoop is None):
            self.GeneralEventLoop.exit()
            print("Exit BatchProcessor::GeneralEventloop")
        if not (self.SnapshotEventLoop is None):
            self.SnapshotEventLoop.exit()
            print("Exit BatchProcessor::SnapshotEventLoop")
        return

    @Slot()
    def close(self):
        self.stopBatch()
        return
예제 #25
0
 def wait_ms(self, milliseconds):
     GeneralEventLoop = QEventLoop()
     QTimer.singleShot(milliseconds, GeneralEventLoop.exit)
     GeneralEventLoop.exec_()
     return
예제 #26
0
class StepperWellPositioning():
    signals = signal.signalClass()
    process_activity = False
    stepper_control = None  ## object StepperControl instance
    current_well_row = None
    current_well_column = None
    Stopped = True
    GeneralEventLoop = None
    SnapshotEventLoop = None
    SnapshotTaken = False
    image = np.ndarray
    image_area = None
    WPE = None
    WPE_target = None
    WPE_targetRadius = None
    Well_Map = None
    diaphragm_diameter = 12.0  ## mm

    ## @brief StepperWellPositioning()::__init__ initialises the stepper objects for X and Y axis and initialises the gcodeSerial to the class member variable.
    ## @param steppers is the StepperControl object representing the X- and Y-axis
    ## @param Well_data contains the target well specified by the user in the batch.ini file
    def __init__(self, steppers, Well_data, record_path):
        self.stepper_control = steppers
        self.Well_Map = Well_data
        log_fine_tuning = False if record_path is None else True
        self.path = record_path
        return

    ## @brief StepperWellPositioning()::msg emits the message signal. This emit will be catched by the logging slot function in main.py.
    ## @param message is the string message to be emitted.
    @Slot(str)
    def msg(self, message):
        if message is not None:
            self.signals.mes.emit(self.__class__.__name__ + ": " +
                                  str(message))
        return

    ## @brief StepperWellPositioning()::reset_current_well(self) sets the current well position (XY) to None
    def reset_current_well(self):
        self.set_current_well(None, None)
        return

    ## @brief StepperWellPositioning()::set_current_well(self) sets the current well position.
    ## @param column is the column or x well coordinate
    ## @param row is the row or y well coordinate
    def set_current_well(self, column, row):
        self.current_well_column = column
        self.current_well_row = row
        return

    ## @brief StepperWellPositioning()::get_current_well(self) is the well position getter.
    ## @return current_well_column (x position in mm from home) and current_well_row (y position in mm from home).
    def get_current_well(self):
        if self.current_well_column == None or self.current_well_row == None:
            self.current_well_column = None
            self.current_well_row = None
        return self.current_well_column, self.current_well_row

    ## @brief StepperWellPositioning()::wait_ms(self, milliseconds) is a delay function.
    ## @param milliseconds is the number of milliseconds to wait.
    def wait_ms(self, milliseconds):
        GeneralEventLoop = QEventLoop()
        QTimer.singleShot(milliseconds, GeneralEventLoop.exit)
        GeneralEventLoop.exec_()
        return

    ## @brief StepperWellPositioning()::goto_well(self, row, column):
    ## @author Robin Meekers
    ## @author Gert van Lagen (ported to new prototype which makes use of the Wrecklab PrintHAT)
    @Slot()
    def goto_well(self, row, column, adapt_to_well=False):
        print("In goto_well function")
        print(" adapt to well is " + str(adapt_to_well))
        ##        self.stepper_control.enableMotors()
        self.signals.process_active.emit()
        self.Stopped = False
        self.stepper_control.setLightPWM(1.0)

        ## If the Well Position Evaluator is not initialized.
        if self.WPE is None:
            ## define the resolution of the received images to be entered into the evaluator.
            self.snapshot_request()
            self.snapshot_await()
            self.WPE_target = (int(self.image.shape[1] / 2),
                               int(self.image.shape[0] / 2))
            self.WPE = imageProcessor.WellPositionEvaluator(
                (self.image.shape[0], self.image.shape[1]))

        self.msg("Current well: " + str(self.get_current_well()))
        current_row, current_column = self.get_current_well()

        ## Position unknown
        if current_row is None or current_column is None:
            ## Need to go to home position first
            self.msg("Current position unknown. Moving to home...")
            self.stepper_control.homeXY()

            ## If homing is succeeded and confirmed by the STM of the Wrecklab PrintHAT
            if self.stepper_control.homing_confirmed:
                self.image = None
                self.snapshot_request()
                self.snapshot_await()
                self.wait_ms(
                    1000)  ## Wait for the snapshot to be stored in self.image

                ## Arrived at home, move to first well.
                ## The exact centre of the image can more easily be determined at the home position,
                ## as there is no distortion in the image by light refracting.
                self.msg("Looking for light source...")
                WPE_Error = self.WPE.evaluate(self.image, (int(
                    self.image.shape[1] / 2), int(self.image.shape[0] / 2)))
                self.msg("Found light-source at: (" + str(WPE_Error[0][0]) +
                         " | " + str(WPE_Error[0][1]) + "). Radius: " +
                         str(WPE_Error[2]))

                self.WPE_targetRadius = WPE_Error[2]
                self.WPE_target = (int(self.image.shape[1] / 2) +
                                   WPE_Error[0][0],
                                   int(self.image.shape[0] / 2) +
                                   WPE_Error[0][1])
                self.msg("WPE_target: " + str(self.WPE_target[0]) + " | " +
                         str(self.WPE_target[1]))

                self.signals.target_located.emit(
                    (self.WPE_target[0], self.WPE_target[1],
                     self.WPE_targetRadius))

                self.WPE.circle_minRadius = int(
                    self.WPE_targetRadius * 0.8
                )  ## Roughly the amount remaining if the target is on the edge between wells.
                self.WPE.circle_maxRadius = int(
                    self.WPE_targetRadius
                )  ## The well can never be larger than the diaphragm of the light source.

                ##                ## Homing succeeded, light source found, lets move to the first target of Well_map
                ##                self.set_current_well(column, row)
                ##                self.stepper_control.moveToWell(column, row)
                self.signals.first_move.emit()
            else:
                return False

        ## position known
        if self.process_activity:

            # JV: column and row is probably X and Y in Robin's functions, also in Gert's functions?
            self.stepper_control.moveToWell(column, row)

            ## Wait for ms depending on moving distance, JV:why?
            if self.current_well_column is None or self.current_well_row is None:
                dist = 60
            else:
                dist = math.sqrt(
                    float(
                        abs(float(column) - float(self.current_well_column)) *
                        abs(float(column) - float(self.current_well_column))) +
                    float(
                        abs(float(row) - float(self.current_well_row)) *
                        abs(float(row) - float(self.current_well_row))))
            self.msg("Moving distance: " + str(dist))
            if dist < 20:
                self.msg("Delay: 1999ms | dist: " + str(dist) + "mm")
                self.wait_ms(1999)
            elif dist < 50:
                self.msg("Delay: 3999ms | dist: " + str(dist) + "mm")
                self.wait_ms(3999)
            elif dist < 70:
                self.msg("Delay: 5999ms | dist: " + str(dist) + "mm")
                self.wait_ms(5999)
            elif dist < 85:
                self.msg("Delay: 8999ms | dist: " + str(dist) + "mm")
                self.wait_ms(8999)
            elif dist > 85:
                self.msg("Delay: 11999ms | dist: " + str(dist) + "mm")
                self.wait_ms(11999)
            else:
                self.msg("Delay: 4999ms | Unknown dist: " + str(dist) + "mm")
                self.wait_ms(4999)

            self.set_current_well(column, row)
            print(
                str(self.WPE_target[0]) + " | " + str(self.WPE_target[1]) +
                " first run " + str(adapt_to_well))

            if adapt_to_well:
                self.goto_target()
            else:
                self.wait_ms(
                    2000)  ## Wait for the snapshot to be stored in self.image
            self.msg("Well positioning succeeded.")
            ## Manual confirmation needed. STM is too fast for the software to catch the last confirmation.
            self.stepper_control.move_confirmed = True

##            if not self.goto_target():
##                self.msg("Well positioning not succeeded.")
##                self.set_current_well(None, None) ## Never reached reference point
##                self.Stopped = True
##                self.signals.process_inactive.emit()
##
##                ## Manual confirmation needed. STM is too fast for the software to catch the last confirmation.
##                self.stepper_control.move_confirmed = True
##                return False
##            else:
##                self.msg("Well positioning succeeded.")
##                ## Manual confirmation needed. STM is too fast for the software to catch the last confirmation.
##                self.stepper_control.move_confirmed = True

        else:
            print(
                "Positioning process inactive, cannot call goto_target positioning controller function."
            )
            self.msg(
                "Positioning process inactive, cannot call goto_target positioning controller function."
            )
        ## Different row?
        if row != self.current_well_row or column != self.current_well_column:
            self.msg("moving from: (" + str(self.current_well_row) + " | " +
                     str(self.current_well_column) + ") to: (" + str(row) +
                     " | " + str(column) + ")")

## why can we not re-enable motors during steps? Because M17 is not implemented by Klipper
##        self.stepper_control.disableMotors()
        self.stepper_control.setLightPWM(0.0)
        return True

    ## @brief StepperWellPositioning()::goto_target(self) evaluates the target circle using class Well_Position_Evaluator, updates the snapshot,
    ## and corrects the position of the well while not aligned with the light source.
    def goto_target(self):
        loops_ = 0
        error_count = 0
        WPE_Error = None
        new_column = 0
        new_row = 0
        error_threshold = 100  #50#120 # higher number means lower error...
        resolution = self.diaphragm_diameter / self.WPE_targetRadius  # [mm/px]

        run_start_time = current_milli_time()
        if self.path is not None:
            column, row = self.get_current_well()
            log_file_name = '_'.join([
                str(run_start_time), 'goto_target',
                str(round(column)),
                str(round(row))
            ])
            recording_file_name = os.path.sep.join([self.path, log_file_name])
            recording_file = open(recording_file_name, "w")
            record_str = "run_time, WPE_target[0], WPE_target[1], WPE_Error[0][0], WPE_Error[0][1]"
            recording_file.write(record_str + "\n")
        else:
            recording_file = None

        ## Do while the well is not aligned with the light source.
        while True:
            if (self.stepper_control.move_confirmed):
                if not self.process_activity:
                    #self.msg("!Returning from alignment controller loop in StepperWellPositioning::goto_target")
                    print(
                        "!Returning from alignment controller loop in StepperWellPositioning::goto_target"
                    )
                    return False
                ## Wait for image to stabilize and request new snapshot
                self.wait_ms(2000)
                self.snapshot_request()

                ## Wait for snapshot to be stored in self.image
                self.wait_ms(1000)

                ## Evaluate current wellposition relative to the light source.
                WPE_Error = self.WPE.evaluate(self.image, self.WPE_target)
                self.msg("WPE target at (" + str(self.WPE_target[0]) + " | " +
                         str(self.WPE_target[1]) + ")")

                ## Area error, surface smaller or equal to 0
                if WPE_Error[1] <= 0:
                    self.msg(
                        "Possibly something wrong with captured frame, retry with another snapshot"
                    )
                    error_count = error_count + 1
                    if (error_count >= 3):
                        self.msg("Error_count = " + str(error_count))
                        return False
                    continue
                else:
                    self.msg("Well found at offset (" + str(WPE_Error[0][0]) +
                             " | " + str(WPE_Error[0][1]) + ")")
                    self.signals.well_located.emit(
                        (self.WPE_target[0] + WPE_Error[0][0],
                         self.WPE_target[1] + WPE_Error[0][1], WPE_Error[2]))

#                     ## Some
#                     error_count = 0
#                     if (abs(WPE_Error[0][0]-30) < (self.image.shape[0] / error_threshold) and abs(WPE_Error[0][1]+30) < (self.image.shape[0] / error_threshold)) or (loops_ >20): ## No more adjustments to make or system is oscilating
#                         if loops_ > 20:loops_
#                             self.msg("More than 20 correction loops, return False")
#                             return False
#                         self.msg("Returning from positioner controller, loops: " + str(loops_))
#                         return True

## Define controller variables for column and row | x and y.

##                new_column = float(WPE_Error[0][0]) / ((loops_+1)*20.0)
##                new_row = float(WPE_Error[0][1]) / ((loops_+1)*15.0)
##                column, row = self.get_current_well()

                run_time = current_milli_time() - run_start_time
                if recording_file is not None:
                    record_str = str(run_time) + ',' + str(
                        self.WPE_target[0]) + ',' + str(
                            self.WPE_target[1]) + ',' + str(
                                WPE_Error[0][0]) + ',' + str(WPE_Error[0][1])
                    recording_file.write(record_str + "\n")

                error = np.sqrt(WPE_Error[0][0]**2 + WPE_Error[0][1]**2)
                threshold = min(self.image.shape[0:1]) / error_threshold
                print(" well placement error: {}, while acceptable error:{}".
                      format(error, threshold))

                if error > threshold:
                    # Decrease stepsize on each iteration for smooth convergence
                    new_column = float(
                        WPE_Error[0][0]) * resolution / (loops_ + 1)
                    new_row = float(
                        WPE_Error[0][1]) * resolution / (loops_ + 1)
                    column, row = self.get_current_well()
                    new_column += column
                    new_row += row
                    new_column = round(new_column, 1)
                    new_row = round(new_row, 1)
                    self.stepper_control.moveToWell(new_column, new_row)
                    self.set_current_well(new_column, new_row)
                else:
                    break
                loops_ += 1
                if loops_ > 5:
                    self.msg("Too many correction loops, giving up")
                    break
            if not self.process_activity:
                #self.msg("Returning from alignment controller loop in StepperWellPositioning::goto_target")
                print(
                    "Returning from alignment controller loop in StepperWellPositioning::goto_target"
                )
                return False

        if recording_file:
            recording_file.close()

        return True

    ## @brief StepperWellPositioning()::snapshot_request(self) emits the snapshot_request signal
    def snapshot_request(self):
        self.signals.snapshot_requested.emit(str((1, 1)))

    ## @brief StepperWellPositioning()::snapshot_awiat(self) runs an eventloop while the new snapshot is not stored in self.image yet.
    def snapshot_await(self):
        self.SnapshotTaken = False
        while not self.Stopped and not self.SnapshotTaken:
            self.SnapshotEventLoop = QEventLoop()
            QTimer.singleShot(10, self.SnapshotEventLoop.exit)
            self.SnapshotEventLoop.exec_()

    ## @brief StepperWellPositioning()::snapshot_confirmed(self, snapshot) exits the event loop of snapshot_await when the new image is arived.
    ## It updates the self.image variable with the new variable and defines the image area and WPE_target.
    @Slot(np.ndarray)
    def snapshot_confirmed(self, snapshot):
        self.image = snapshot
        #         self.WPE_target = (int(self.image.shape[1] / 2), int(self.image.shape[0] / 2))
        self.image_area = int((self.image.shape[0] * self.image.shape[1]))
        self.SnapshotTaken = True
        if not (self.SnapshotEventLoop is None):
            self.SnapshotEventLoop.exit()
        return

    ## @brief StepperWellPositioning()::setProcessInactive(self) disables the positionings process if the signal is emitted.
    @Slot()
    def setProcessInactive(self):
        #self.msg("Disabled positioning process activity")
        print("Disabled positioning process activity")
        self.process_activity = False
        self.Stopped = True
        if not (self.GeneralEventLoop is None):
            self.GeneralEventLoop.exit()
            #self.msg("Exit StepperWellPositioning::GeneralEventloop")
            print("Exit StepperWellPositioning::GeneralEventloop")
        if not (self.SnapshotEventLoop is None):
            self.SnapshotEventLoop.exit()
            #self.msg("Exit StepperWellPositioning::SnapshotEventLoop")
            print("Exit StepperWellPositioning::SnapshotEventLoop")
        return

    ## @brief StepperWellPositioning()::setProcessActive(self) enables the positionings process if the signal is emitted.
    @Slot()
    def setProcessActive(self):
        self.process_activity = True
        self.Stopped = False
        return

    @Slot()
    def close(self):
        self.stepper_control.setLightPWM(0.0)
        self.stepper_control.setFanPWM(0.0)
        self.process_activity = False
        self.Stopped = True
        return
예제 #27
0
class MakeSerialConnection(QThread):
    """ Connect to selected serial port, receive data and send it to proper tabs """
    start_btn_state = Signal(bool)
    stop_btn_state = Signal(bool)
    baud_box_state = Signal(bool)
    port_box_state = Signal(bool)
    board_box_state = Signal(bool)
    time_edit_state = Signal(bool)
    wifi_check_state = Signal(bool)
    blue_check_state = Signal(bool)
    serial_port_placeholder = Signal(str)
    serial_port_clear = Signal()
    send_text_signal = Signal(str)
    conn_stat_text = Signal(str)
    conn_stat_style = Signal(str)
    clear_wifi_list = Signal()
    clear_blue_list = Signal()
    append_wifi_list_item = Signal(QListWidgetItem)
    append_blue_list_item = Signal(QListWidgetItem)
    append_wifi_timeline_data = Signal(list)
    save_wifi_timeline_data = Signal(tuple)
    clear_wifi_series = Signal()
    add_wifi_series = Signal(QtCharts.QLineSeries)
    set_axis_y_series = Signal(QtCharts.QLineSeries)
    set_axis_x_series = Signal(QtCharts.QLineSeries)
    wifi_data_to_func = Signal(dict)
    wifi_data_to_func_graph = Signal(dict)
    wifi_data_to_func_time = Signal(dict)
    blue_data_to_func = Signal(dict)

    def __init__(self, parent=None):
        super(MakeSerialConnection, self).__init__(parent)
        self.current_port = ''
        self.current_baud = 9600
        self.current_board = 'ESP32'
        self.current_time = 10000
        self.wifi_scan_status = True
        self.blue_scan_status = False
        self.first_conn = True
        self.arduino = ''
        self.loop = ''
        self.reading = True
        self.data_collection = False
        self.blue_data_collection = False
        self.collected_data = {}
        self.collected_blue_data = {}
        self.default_array = []
        self.default_tupple = ()
        self.final_tuple = ()
        self.save_data_to_db = False
        self.channels_occ = {
            1: [1, 2],
            2: [1, 2, 3],
            3: [2, 3, 4],
            4: [3, 4, 5],
            5: [4, 5, 6],
            6: [5, 6, 7],
            7: [6, 7, 8],
            8: [7, 8, 9],
            10: [9, 10, 11],
            11: [10, 11, 12],
            12: [11, 12, 13],
            13: [12, 13]
        }
        self.current_lang = 'English'

    def run(self):
        """ DOCSTRING """
        if self.first_conn is True:
            self.arduino = serial.Serial(self.current_port,
                                         self.current_baud,
                                         write_timeout=1)
            self.disable_settings_options(False)
            self.send_config_to_esp()
        else:
            self.show_status_reconnect()
            self.disable_settings_options(False)
            self.loop = QEventLoop()
            QTimer.singleShot(5000, self.loop.quit)
            self.loop.exec_()
            self.arduino = serial.Serial(self.current_port,
                                         self.current_baud,
                                         write_timeout=1)
            self.send_config_to_esp()
            self.reading = True

        while self.reading is True:
            self.show_status_connected()
            try:
                data = self.arduino.readline()[:-1].decode(encoding='utf-8',
                                                           errors="replace")
                if data.split() == ['[CFG]BOARD_ERROR']:
                    self.show_status_wrong_board()
                    self.send_text_signal.emit(
                        'Selected wrong board! Disconnected')
                    self.stop_serial_communication()
                if data.split() == ['[SCN]WIFI_START_SCAN'
                                    ] or self.data_collection is True:
                    if self.data_collection is True and data.split() != [
                            '[SCN]WIFI_STOP_SCAN'
                    ]:
                        if len(data) > 1:
                            self.collected_data[str(data.split(" | ")[1])] = [
                                int(data.split(" | ")[2]),
                                int(data.split(" | ")[3]),
                                str(data.split(" | ")[4]),
                                str(data.split(" | ")[5]),
                                str(data.split(" | ")[6])
                            ]
                    elif data.split() == ['[SCN]WIFI_STOP_SCAN']:
                        self.data_collection = False
                        self.wifi_data_to_func.emit(self.collected_data)
                    else:
                        self.collected_data = {}
                        self.data_collection = True
                if data.split() == ['[SCN]BLUE_START_SCAN'
                                    ] or self.blue_data_collection is True:
                    if (self.blue_data_collection is True
                            and data.split() != ['[SCN]BLUE_STOP_SCAN']):
                        if data.split()[0] == 'DEV':
                            if len(data) > 1:
                                # Data template: DEV | Name | RSSI | MAC | MSG
                                self.collected_blue_data[str(
                                    data.split(" | ")[1])] = [
                                        str(data.split(" | ")[2]),
                                        int(data.split(" | ")[3]),
                                        str(data.split(" | ")[4])
                                    ]
                    elif data.split() == ['[SCN]BLUE_STOP_SCAN']:
                        self.blue_data_collection = False
                        self.blue_data_to_func.emit(self.collected_blue_data)
                    else:
                        self.blue_data_collection = True
                self.send_text_signal.emit(data)

            except serial.SerialException:
                self.show_status_uart_error()
                self.send_text_signal.emit(
                    'Disconnect of USB->UART occured.\nRestart needed!')
                self.stop_serial_communication()
        self.arduino.close()

    def send_config_to_esp(self):
        """send config to ESP"""
        self.arduino.write("[CFG]START".encode())
        self.arduino.write("\n".encode())
        self.arduino.write(
            str("[CFG]BOARD=" + self.current_board + "").encode())
        self.arduino.write("\n".encode())
        self.arduino.write(
            str("[CFG]TIME=" + str(self.current_time) + "").encode())
        self.arduino.write("\n".encode())
        self.arduino.write(
            str("[CFG]WIFI_SCAN=" + str(self.wifi_scan_status).upper() +
                "").encode())
        self.arduino.write("\n".encode())
        self.arduino.write(
            str("[CFG]BLUE_SCAN=" + str(self.blue_scan_status).upper() +
                "").encode())
        self.arduino.write("\n".encode())
        self.arduino.write("[CFG]STOP\n".encode())
        self.arduino.write("\n".encode())
        self.arduino.write("[SCN]START".encode())
        self.arduino.write("\n".encode())

    def stop_serial_communication(self):
        """ Stop reading from serial port """
        self.reading = False
        self.first_conn = False
        self.arduino.close()
        self.disable_settings_options(True)
        self.show_status_disconnected()

    def get_curr_port(self, port):
        """ Get selected serial port """
        self.current_port = str(port)

    def get_curr_baud(self, baud):
        """ DOCSTRING """
        self.current_baud = int(baud)

    def get_curr_board(self, board):
        """ DOCSTRING """
        self.current_board = str(board)

    def get_curr_time(self, user_time):
        """ DOCSTRING """
        self.current_time = (
            int(user_time.toString("m:ss").split(":")[0]) * 60 +
            int(user_time.toString("m:ss").split(":")[1])) * 1000

    def get_wifi_check(self, state):
        """ DOCSTRING """
        self.wifi_scan_status = state

    def get_blue_check(self, state):
        """ DOCSTRING """
        self.blue_scan_status = state

    def set_style_sheet(self, color):
        """ Set stylesheet for connection status label """

        return "background: " + color + "; color: white; font-size: 14px; border-width: 1px; \
            border-style: solid; border-radius: 2px; border-color: " + color + ";"

    def show_status_connected(self):
        """ Show connected status in MainWindow class """
        self.start_btn_state.emit(False)
        self.stop_btn_state.emit(True)
        if self.current_lang == "Polski":
            self.conn_stat_text.emit('Połączono')
        else:
            self.conn_stat_text.emit('Connected')
        self.conn_stat_style.emit(self.set_style_sheet('green'))

    def show_status_disconnected(self):
        """ Show disconnected status in MainWindow class """
        self.start_btn_state.emit(True)
        self.stop_btn_state.emit(False)
        if self.current_lang == "Polski":
            self.conn_stat_text.emit('Rozłączono')
        else:
            self.conn_stat_text.emit('Disconnected')
        self.conn_stat_style.emit(self.set_style_sheet('red'))

    def show_status_uart_error(self):
        """ Show UART error status in MainWindow """
        self.start_btn_state.emit(False)
        self.stop_btn_state.emit(True)
        if self.current_lang == "Polski":
            self.conn_stat_text.emit('Rozłączono. Wymagany restart')
        else:
            self.conn_stat_text.emit(
                'Disconnect of USB->UART occured. Need restart')
        self.conn_stat_style.emit(self.set_style_sheet('orange'))

    def show_status_wrong_board(self):
        """ Show selected wrong board status in MainWindow """
        self.start_btn_state.emit(False)
        self.stop_btn_state.emit(True)
        if self.current_lang == "Polski":
            self.conn_stat_text.emit('Wybrano złą płytkę!')
        else:
            self.conn_stat_text.emit('Selected wrong board!')
        self.conn_stat_style.emit(self.set_style_sheet('red'))

    def show_status_reconnect(self):
        """ Show reconnect status in MainWindow """
        self.start_btn_state.emit(False)
        self.stop_btn_state.emit(False)
        if self.current_lang == "Polski":
            self.conn_stat_text.emit('Ponowne łączenie... Czekaj 5s')
        else:
            self.conn_stat_text.emit('Reconnecting... Wait 5s')
        self.conn_stat_style.emit(self.set_style_sheet('orange'))

    @Slot(dict)
    def append_wifi_data(self, data):
        """ Append data to list in WiFi list tab """
        self.clear_wifi_list.emit()
        i = 1
        for i in data:
            if self.current_lang == "Polski":
                item = QListWidgetItem(
                    'BSID: ' + str(i) + ' \nKanał: ' + str(data[i][1]) +
                    ' \nRSSI: ' + str(data[i][0]) + ' dBm \nMAC: ' +
                    str(data[i][3]) + ' (Producent: ' +
                    str(manu.search_manufacturer_by_mac(str(data[i][3]))) +
                    ')')
            else:
                item = QListWidgetItem(
                    'BSID: ' + str(i) + ' \nChannel: ' + str(data[i][1]) +
                    ' \nRSSI: ' + str(data[i][0]) + ' dBm \nMAC: ' +
                    str(data[i][3]) + ' (Manufacturer: ' +
                    str(manu.search_manufacturer_by_mac(str(data[i][3]))) +
                    ')')
            if int(abs(data[i][0])) < 50:
                item.setIcon(QIcon('icons/icons8-no-connection-64-green.png'))
            elif int(abs(data[i][0])) >= 50 and int(abs(data[i][0])) < 70:
                item.setIcon(QIcon('icons/icons8-no-connection-64-blue.png'))
            elif int(abs(data[i][0])) >= 70 and int(abs(data[i][0])) < 80:
                item.setIcon(QIcon('icons/icons8-no-connection-64-orange.png'))
            elif int(abs(data[i][0])) >= 80 and int(abs(data[i][0])) < 90:
                item.setIcon(QIcon('icons/icons8-no-connection-64-red.png'))
            elif int(abs(data[i][0])) >= 90:
                item.setIcon(QIcon('icons/icons8-no-connection-64-black.png'))
            self.append_wifi_list_item.emit(item)
            self.loop = QEventLoop()
            QTimer.singleShot(50, self.loop.quit)
            self.loop.exec_()

    @Slot(dict)
    def append_blue_data(self, data):
        """ DOCSTRING """
        self.clear_blue_list.emit()
        i = 1
        for i in data:
            if self.current_lang == "Polski":
                item = QListWidgetItem('Nazwa: ' + str(i) + ' \nMAC: ' +
                                       str(data[i][0].upper()) + ' \nRSSI: ' +
                                       str(data[i][1]) + ' dBm\nProducent: ' +
                                       str(
                                           manu.search_manufacturer_by_mac(
                                               str(data[i][0].upper()))) + '')
            else:
                item = QListWidgetItem('Name: ' + str(i) + ' \nMAC: ' +
                                       str(data[i][0].upper()) + ' \nRSSI: ' +
                                       str(data[i][1]) +
                                       ' dBm\nManufacturer: ' + str(
                                           manu.search_manufacturer_by_mac(
                                               str(data[i][0].upper()))) + '')
            if int(abs(data[i][1])) < 50:
                item.setIcon(QIcon('icons/icons8-no-connection-64-green.png'))
            elif int(abs(data[i][1])) >= 50 and int(abs(data[i][1])) < 70:
                item.setIcon(QIcon('icons/icons8-no-connection-64-blue.png'))
            elif int(abs(data[i][1])) >= 70 and int(abs(data[i][1])) < 80:
                item.setIcon(QIcon('icons/icons8-no-connection-64-orange.png'))
            elif int(abs(data[i][1])) >= 80 and int(abs(data[i][1])) < 90:
                item.setIcon(QIcon('icons/icons8-no-connection-64-red.png'))
            elif int(abs(data[i][1])) >= 90:
                item.setIcon(QIcon('icons/icons8-no-connection-64-black.png'))
            self.append_blue_list_item.emit(item)
            self.loop = QEventLoop()
            QTimer.singleShot(50, self.loop.quit)
            self.loop.exec_()

    def disable_settings_options(self, state):
        """ DOCSTRING """
        self.port_box_state.emit(state)
        self.baud_box_state.emit(state)
        self.board_box_state.emit(state)
        self.time_edit_state.emit(state)
        self.wifi_check_state.emit(state)
        self.blue_check_state.emit(state)
        if state is False:
            self.serial_port_placeholder.emit(self.current_port)
        else:
            self.serial_port_clear.emit()

    @Slot(dict)
    def append_data_to_wifi_graph(self, wifi_dict):
        """DOCSTRING"""
        self.clear_wifi_series.emit()
        for var_x in wifi_dict:
            self.line_series = QtCharts.QLineSeries()
            self.line_series.setName(str(var_x))
            self.line_series.append(
                QPoint(2400 + (wifi_dict[var_x][1] * 5 - 4), -100))
            self.line_series.append(
                QPoint(2411 + (wifi_dict[var_x][1] * 5 - 9),
                       int(wifi_dict[var_x][0])))
            self.line_series.append(
                QPoint(2411 + (wifi_dict[var_x][1] * 5 + 1),
                       int(wifi_dict[var_x][0])))
            self.line_series.append(2422 + (wifi_dict[var_x][1] * 5 - 4), -100)
            self.add_wifi_series.emit(self.line_series)
            self.set_axis_x_series.emit(self.line_series)
            self.set_axis_y_series.emit(self.line_series)
            self.loop = QEventLoop()
            QTimer.singleShot(50, self.loop.quit)
            self.loop.exec_()

    @Slot(dict)
    def append_data_to_wifi_timeline(self, wifi_dict):
        """ DOCSTRING """
        self.default_array = [
            -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100,
            -100, -100
        ]
        for var_x in wifi_dict:
            self.append_lowest_rssi_to_array(wifi_dict[var_x][1],
                                             wifi_dict[var_x][0])
        self.append_wifi_timeline_data.emit(self.default_array)
        self.default_tupple = tuple(self.default_array)
        self.final_tuple = (datetime.datetime.now().strftime('%H:%M:%S'),
                            *self.default_tupple)
        self.save_wifi_timeline_data.emit(self.final_tuple)
        self.loop = QEventLoop()
        QTimer.singleShot(50, self.loop.quit)
        self.loop.exec_()

    def append_lowest_rssi_to_array(self, x, value):
        """ DOCSTRING """
        for i in self.channels_occ[int(x)]:
            if self.default_array[i - 1] < value:
                self.default_array[i - 1] = value

    def enable_saving_to_db(self, state):
        """ DOCSTRING """
        if state is True:
            self.save_data_to_db = True
        else:
            self.save_data_to_db = False

    def get_current_lang(self, lang):
        """ DOCSTRING """
        self.current_lang = lang
 def _wait_for_execution_finished(self):
     loop = QEventLoop()
     self.toolbox.project().project_execution_finished.connect(loop.quit)
     loop.exec_()
예제 #29
0
    def _execute_forward(self, resources):
        """
        Executes the Tool according to the Tool specification.

        Before launching the tool script in a separate instance,
        prepares the execution environment by creating all necessary directories
        and copying input files where needed.
        After execution archives the output files.

        Args:
            resources (list): a list of resources from direct predecessor items
        Returns:
            True if execution succeeded, False otherwise
        """
        if self._tool_specification is None:
            self._logger.msg_warning.emit(
                f"Tool <b>{self.name}</b> has no Tool specification to execute"
            )
            return False
        execution_dir = _execution_directory(self._work_dir,
                                             self._tool_specification)
        if execution_dir is None:
            return False
        if self._work_dir is not None:
            work_or_source = "work"
            # Make work directory anchor with path as tooltip
            work_anchor = ("<a style='color:#99CCFF;' title='" +
                           execution_dir + "' href='file:///" + execution_dir +
                           "'>work directory</a>")
            self._logger.msg.emit(
                f"*** Copying Tool specification <b>{self._tool_specification.name}"
                f"</b> source files to {work_anchor} ***")
            if not self._copy_program_files(execution_dir):
                self._logger.msg_error.emit(
                    "Copying program files to base directory failed.")
                return False
        else:
            work_or_source = "source"
        # Make source directory anchor with path as tooltip
        anchor = (
            f"<a style='color:#99CCFF;' title='{execution_dir}'"
            f"href='file:///{execution_dir}'>{work_or_source} directory</a>")
        self._logger.msg.emit(
            f"*** Executing Tool specification <b>{self._tool_specification.name}</b> in {anchor} ***"
        )
        # Find required input files for ToolInstance (if any)
        if self._tool_specification.inputfiles:
            self._logger.msg.emit(
                "*** Checking Tool specification requirements ***")
            n_dirs, n_files = _count_files_and_dirs(
                self._tool_specification.inputfiles)
            if n_files > 0:
                self._logger.msg.emit(
                    "*** Searching for required input files ***")
                file_paths = flatten_file_path_duplicates(
                    self._find_input_files(resources),
                    self._logger,
                    log_duplicates=True)
                not_found = [k for k, v in file_paths.items() if v is None]
                if not_found:
                    self._logger.msg_error.emit(
                        f"Required file(s) <b>{', '.join(not_found)}</b> not found"
                    )
                    return False
                self._logger.msg.emit(
                    f"*** Copying input files to {work_or_source} directory ***"
                )
                # Copy input files to ToolInstance work or source directory
                if not self._copy_input_files(file_paths, execution_dir):
                    self._logger.msg_error.emit(
                        "Copying input files failed. Tool execution aborted.")
                    return False
            if n_dirs > 0:
                self._logger.msg.emit(
                    f"*** Creating input subdirectories to {work_or_source} directory ***"
                )
                if not self._create_input_dirs(execution_dir):
                    # Creating directories failed -> abort
                    self._logger.msg_error.emit(
                        "Creating input subdirectories failed. Tool execution aborted."
                    )
                    return False
        optional_file_copy_paths = dict()
        if self._tool_specification.inputfiles_opt:
            self._logger.msg.emit("*** Searching for optional input files ***")
            optional_file_paths = self._find_optional_input_files(resources)
            for k, v in optional_file_paths.items():
                self._logger.msg.emit(
                    f"\tFound <b>{len(v)}</b> files matching pattern <b>{k}</b>"
                )
            optional_file_copy_paths = self._optional_output_destination_paths(
                optional_file_paths, execution_dir)
            self._copy_optional_input_files(optional_file_copy_paths)
        if not self._create_output_dirs(execution_dir):
            self._logger.msg_error.emit(
                "Creating output subdirectories failed. Tool execution aborted."
            )
            return False
        input_database_urls = _database_urls_from_resources(resources)
        output_database_urls = _database_urls_from_resources(
            self._downstream_resources)
        self._tool_instance = self._tool_specification.create_tool_instance(
            execution_dir)

        try:
            self._tool_instance.prepare(
                list(optional_file_copy_paths.values()), input_database_urls,
                output_database_urls, self._cmd_line_args)
        except RuntimeError as error:
            self._logger.msg_error.emit(
                f"Failed to prepare tool instance: {error}")
            return False
        execution_token = _ExecutionToken(self, execution_dir)
        self._tool_instance.instance_finished.connect(
            execution_token.handle_execution_finished)
        self._logger.msg.emit(
            f"*** Starting instance of Tool specification <b>{self._tool_specification.name}</b> ***"
        )
        # Wait for finished right here
        loop = QEventLoop()
        self._tool_instance.instance_finished.connect(loop.quit)
        self._tool_instance.execute()
        if self._tool_instance.is_running():
            loop.exec_()
        return self._last_return_code == 0
예제 #30
0
파일: cffex.py 프로젝트: zizle/ADSYSTEM
class CFFEXSpider(QObject):
    spider_finished = Signal(str, bool)

    def __init__(self, *args, **kwargs):
        super(CFFEXSpider, self).__init__(*args, **kwargs)
        self.date = None
        self.event_loop = QEventLoop(self)  # 用于网络请求同步事件阻塞

    def set_date(self, date):
        self.date = datetime.strptime(date, '%Y-%m-%d')

    def get_daily_source_file(self):
        """ 获取每日行情数据源文件保存至本地 """
        if self.date is None:
            raise DateValueError("请先使用`set_date`设置`CZCESpider`日期.")
        url = "http://www.cffex.com.cn/sj/hqsj/rtj/{}/{}/{}_1.csv".format(
            self.date.strftime('%Y%m'), self.date.strftime('%d'),
            self.date.strftime('%Y%m%d'))
        app = QApplication.instance()
        network_manager = getattr(app, "_network")

        request = QNetworkRequest(url=url)
        request.setHeader(QNetworkRequest.UserAgentHeader,
                          random.choice(USER_AGENTS))
        reply = network_manager.get(request)
        reply.finished.connect(self.daily_source_file_reply)

    def daily_source_file_reply(self):
        """ 获取日统计数据请求返回 """
        reply = self.sender()
        if reply.error():
            reply.deleteLater()
            self.spider_finished.emit("失败:" + str(reply.error()), True)
            return
        save_path = os.path.join(
            LOCAL_SPIDER_SRC,
            'cffex/daily/{}.csv'.format(self.date.strftime("%Y-%m-%d")))
        file_data = reply.readAll()
        file_obj = QFile(save_path)
        is_open = file_obj.open(QFile.WriteOnly)
        if is_open:
            file_obj.write(file_data)
            file_obj.close()
        reply.deleteLater()
        self.spider_finished.emit(
            "获取中金所{}日交易数据源文件成功!".format(self.date.strftime("%Y-%m-%d")), True)

    def get_rank_source_file(self):
        """ 获取日排名数据源文件 """
        base_url = "http://www.cffex.com.cn/sj/ccpm/{}/{}/{}_1.csv"
        app = QApplication.instance()
        network_manager = getattr(app, "_network")

        for variety in VARIETY_LIST:
            url = base_url.format(self.date.strftime("%Y%m"),
                                  self.date.strftime("%d"), variety)
            self.spider_finished.emit("准备获取{}的日排名数据文件...".format(variety),
                                      False)
            request = QNetworkRequest(url=url)
            request.setHeader(QNetworkRequest.UserAgentHeader,
                              random.choice(USER_AGENTS))
            reply = network_manager.get(request)
            reply.finished.connect(self.rank_source_file_reply)
            time.sleep(1)
            self.event_loop.exec_()

    def rank_source_file_reply(self):
        """ 获取日排名请求返回 """
        reply = self.sender()
        request_url = reply.request().url().url()
        # 解析出请求的品种
        request_filename = request_url.rsplit("/", 1)[1]
        request_variety = request_filename.split("_")[0]
        if reply.error():
            reply.deleteLater()
            self.spider_finished.emit(
                "获取{}排名数据文件。\n失败:{}".format(request_variety[:2],
                                            str(reply.error())), True)
            logger.error("获取{}排名数据文件失败了!".format(request_url[:2]))
            return
        save_path = os.path.join(
            LOCAL_SPIDER_SRC,
            'cffex/rank/{}_{}.csv'.format(request_variety,
                                          self.date.strftime("%Y-%m-%d")))
        file_data = reply.readAll()
        file_obj = QFile(save_path)
        is_open = file_obj.open(QFile.WriteOnly)
        if is_open:
            file_obj.write(file_data)
            file_obj.close()
        reply.deleteLater()
        tip = "获取中金所{}_{}日持仓排名数据保存到文件成功!".format(
            request_variety, self.date.strftime("%Y-%m-%d"))
        if request_variety == "T":
            tip = "获取中金所{}日所有品种持仓排名数据保存到文件成功!".format(
                self.date.strftime("%Y-%m-%d"))
        self.spider_finished.emit(tip, True)
        self.event_loop.quit()
예제 #31
0
 def startAnimation(self):
     self.startFadeIn()
     loop = QEventLoop()
     self.animation.finished.connect(loop.quit)
     loop.exec_()
     QTimer.singleShot(1000, self.startFadeOut)