Beispiel #1
0
class RunDialog(QDialog):
    simulation_done = Signal(bool, str)

    def __init__(self, config_file, run_model, arguments, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowFlags(Qt.Window)
        self.setWindowFlags(self.windowFlags()
                            & ~Qt.WindowContextHelpButtonHint)
        self.setModal(True)
        self.setWindowModality(Qt.WindowModal)
        self.setWindowTitle("Simulations - {}".format(config_file))

        assert isinstance(run_model, BaseRunModel)
        self._run_model = run_model

        ert = None
        if isinstance(run_model, BaseRunModel):
            ert = run_model.ert()

        self._simulations_argments = arguments

        self.simulations_tracker = create_tracker(
            run_model,
            qtimer_cls=QTimer,
            event_handler=self._on_tracker_event,
            num_realizations=arguments["active_realizations"].count())

        states = self.simulations_tracker.get_states()
        self.state_colors = {state.name: state.color for state in states}
        self.state_colors['Success'] = self.state_colors["Finished"]
        self.state_colors['Failure'] = self.state_colors["Failed"]

        self.total_progress = SimpleProgress()

        status_layout = QHBoxLayout()
        status_layout.addStretch()
        self.__status_label = QLabel()
        status_layout.addWidget(self.__status_label)
        status_layout.addStretch()
        status_widget_container = QWidget()
        status_widget_container.setLayout(status_layout)

        self.progress = Progress()
        self.progress.setIndeterminateColor(self.total_progress.color)
        for state in states:
            self.progress.addState(state.state, QColor(*state.color),
                                   100.0 * state.count / state.total_count)

        legend_layout = QHBoxLayout()
        self.legends = {}
        for state in states:
            self.legends[state] = Legend("%s (%d/%d)", QColor(*state.color))
            self.legends[state].updateLegend(state.name, 0, 0)
            legend_layout.addWidget(self.legends[state])

        legend_widget_container = QWidget()
        legend_widget_container.setLayout(legend_layout)

        self.running_time = QLabel("")

        self.plot_tool = PlotTool(config_file)
        self.plot_tool.setParent(self)
        self.plot_button = QPushButton(self.plot_tool.getName())
        self.plot_button.clicked.connect(self.plot_tool.trigger)
        self.plot_button.setEnabled(ert is not None)

        self.kill_button = QPushButton("Kill simulations")
        self.done_button = QPushButton("Done")
        self.done_button.setHidden(True)
        self.restart_button = QPushButton("Restart")
        self.restart_button.setHidden(True)
        self.show_details_button = QPushButton("Details")
        self.show_details_button.setCheckable(True)

        size = 20
        spin_movie = resourceMovie("ide/loading.gif")
        spin_movie.setSpeed(60)
        spin_movie.setScaledSize(QSize(size, size))
        spin_movie.start()

        self.processing_animation = QLabel()
        self.processing_animation.setMaximumSize(QSize(size, size))
        self.processing_animation.setMinimumSize(QSize(size, size))
        self.processing_animation.setMovie(spin_movie)

        button_layout = QHBoxLayout()
        button_layout.addWidget(self.processing_animation)
        button_layout.addWidget(self.running_time)
        button_layout.addStretch()
        button_layout.addWidget(self.show_details_button)
        button_layout.addWidget(self.plot_button)
        button_layout.addWidget(self.kill_button)
        button_layout.addWidget(self.done_button)
        button_layout.addWidget(self.restart_button)
        button_widget_container = QWidget()
        button_widget_container.setLayout(button_layout)

        self.detailed_progress = DetailedProgressWidget(
            self, self.state_colors)
        self.detailed_progress.setVisible(False)
        self.dummy_widget_container = QWidget(
        )  #Used to keep the other widgets from stretching

        layout = QVBoxLayout()
        layout.addWidget(self.total_progress)
        layout.addWidget(status_widget_container)
        layout.addWidget(self.progress)
        layout.addWidget(legend_widget_container)
        layout.addWidget(self.detailed_progress)
        layout.addWidget(self.dummy_widget_container)
        layout.addWidget(button_widget_container)

        layout.setStretch(0, 0)
        layout.setStretch(1, 0)
        layout.setStretch(2, 0)
        layout.setStretch(3, 0)
        layout.setStretch(4, 1)
        layout.setStretch(5, 1)
        layout.setStretch(6, 0)

        self.setLayout(layout)

        self.kill_button.clicked.connect(self.killJobs)
        self.done_button.clicked.connect(self.accept)
        self.restart_button.clicked.connect(self.restart_failed_realizations)
        self.show_details_button.clicked.connect(self.toggle_detailed_progress)
        self.simulation_done.connect(self._on_simulation_done)

    def reject(self):
        return

    def closeEvent(self, QCloseEvent):
        self.simulations_tracker.stop()
        if self._run_model.isFinished():
            self.simulation_done.emit(self._run_model.hasRunFailed(),
                                      self._run_model.getFailMessage())
        else:
            # Kill jobs if dialog is closed
            if self.killJobs() != QMessageBox.Yes:
                QCloseEvent.ignore()

    def startSimulation(self):
        self._run_model.reset()
        self.simulations_tracker.reset()

        def run():
            self._run_model.startSimulations(self._simulations_argments)

        simulation_thread = Thread(name="ert_gui_simulation_thread")
        simulation_thread.setDaemon(True)
        simulation_thread.run = run
        simulation_thread.start()

        self.simulations_tracker.track()

    def killJobs(self):

        msg = "Are you sure you want to kill the currently running simulations?"
        if self._run_model.getQueueStatus().get(
                JobStatusType.JOB_QUEUE_UNKNOWN, 0) > 0:
            msg += "\n\nKilling a simulation with unknown status will not kill the realizations already submitted!"
        kill_job = QMessageBox.question(self, "Kill simulations?", msg,
                                        QMessageBox.Yes | QMessageBox.No)

        if kill_job == QMessageBox.Yes:
            if self._run_model.killAllSimulations():
                self.reject()
        return kill_job

    @Slot(bool, str)
    def _on_simulation_done(self, failed, failed_msg):
        self.simulations_tracker.stop()
        self.processing_animation.hide()
        self.kill_button.setHidden(True)
        self.done_button.setHidden(False)
        self.restart_button.setVisible(self.has_failed_realizations())
        self.restart_button.setEnabled(self._run_model.support_restart)

        if failed:
            QMessageBox.critical(
                self, "Simulations failed!",
                "The simulation failed with the following " +
                "error:\n\n{}".format(failed_msg))

    @Slot(object)
    def _on_tracker_event(self, event):
        if isinstance(event, TickEvent):
            self.running_time.setText(format_running_time(event.runtime))

        if isinstance(event, GeneralEvent):
            self.total_progress.setProgress(event.progress)
            self.progress.setIndeterminate(event.indeterminate)

            if event.indeterminate:
                for state in event.sim_states:
                    self.legends[state].updateLegend(state.name, 0, 0)
            else:
                for state in event.sim_states:
                    self.progress.updateState(
                        state.state, 100.0 * state.count / state.total_count)
                    self.legends[state].updateLegend(state.name, state.count,
                                                     state.total_count)

        if isinstance(event, DetailedEvent):
            if not self.progress.get_indeterminate():
                self.detailed_progress.set_progress(event.details,
                                                    event.iteration)

        if isinstance(event, EndEvent):
            self.simulation_done.emit(event.failed, event.failed_msg)

    def has_failed_realizations(self):
        completed = self._run_model.completed_realizations_mask
        initial = self._run_model.initial_realizations_mask
        for (index, successful) in enumerate(completed):
            if initial[index] and not successful:
                return True
        return False

    def count_successful_realizations(self):
        """
        Counts the realizations completed in the prevoius ensemble run
        :return:
        """
        completed = self._run_model.completed_realizations_mask
        return completed.count(True)

    def create_mask_from_failed_realizations(self):
        """
        Creates a BoolVector mask representing the failed realizations
        :return: Type BoolVector
        """
        completed = self._run_model.completed_realizations_mask
        initial = self._run_model.initial_realizations_mask
        inverted_mask = BoolVector(default_value=False)
        for (index, successful) in enumerate(completed):
            inverted_mask[index] = initial[index] and not successful
        return inverted_mask

    def restart_failed_realizations(self):

        msg = QMessageBox(self)
        msg.setIcon(QMessageBox.Information)
        msg.setText(
            "Note that workflows will only be executed on the restarted realizations and that this might have unexpected consequences."
        )
        msg.setWindowTitle("Restart Failed Realizations")
        msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
        result = msg.exec_()

        if result == QMessageBox.Ok:
            self.restart_button.setVisible(False)
            self.kill_button.setVisible(True)
            self.done_button.setVisible(False)
            active_realizations = self.create_mask_from_failed_realizations()
            self._simulations_argments[
                'active_realizations'] = active_realizations
            self._simulations_argments[
                'prev_successful_realizations'] = self._simulations_argments.get(
                    'prev_successful_realizations', 0)
            self._simulations_argments[
                'prev_successful_realizations'] += self.count_successful_realizations(
                )
            self.startSimulation()

    def toggle_detailed_progress(self):

        self.detailed_progress.setVisible(not (
            self.detailed_progress.isVisible()))
        self.dummy_widget_container.setVisible(not (
            self.detailed_progress.isVisible()))
        self.adjustSize()
Beispiel #2
0
class RunDialog(QDialog):

    def __init__(self, run_model, parent):
        QDialog.__init__(self, parent)
        self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)
        self.setWindowFlags(self.windowFlags() & ~Qt.WindowCloseButtonHint)
        self.setModal(True)
        self.setWindowModality(Qt.WindowModal)
        self.setWindowTitle("Simulations")

        assert isinstance(run_model, BaseRunModel)
        self._run_model = run_model

        layout = QVBoxLayout()
        layout.setSizeConstraint(QLayout.SetFixedSize)

        self.simulations_tracker = SimulationsTracker()
        states = self.simulations_tracker.getStates()

        self.total_progress = SimpleProgress()
        layout.addWidget(self.total_progress)


        status_layout = QHBoxLayout()
        status_layout.addStretch()
        self.__status_label = QLabel()
        status_layout.addWidget(self.__status_label)
        status_layout.addStretch()
        layout.addLayout(status_layout)

        self.progress = Progress()
        self.progress.setIndeterminateColor(self.total_progress.color)
        for state in states:
            self.progress.addState(state.state, QColor(*state.color), 100.0 * state.count / state.total_count)

        layout.addWidget(self.progress)

        legend_layout = QHBoxLayout()
        self.legends = {}
        for state in states:
            self.legends[state] = Legend("%s (%d/%d)", QColor(*state.color))
            self.legends[state].updateLegend(state.name, 0, 0)
            legend_layout.addWidget(self.legends[state])

        layout.addLayout(legend_layout)

        self.running_time = QLabel("")

        ert = None
        if isinstance(run_model, BaseRunModel):
            ert = run_model.ert()

        self.plot_tool = PlotTool()
        self.plot_tool.setParent(None)
        self.plot_button = QPushButton(self.plot_tool.getName())
        self.plot_button.clicked.connect(self.plot_tool.trigger)
        self.plot_button.setEnabled(ert is not None)
        
        self.kill_button = QPushButton("Kill simulations")
        self.done_button = QPushButton("Done")
        self.done_button.setHidden(True)

        button_layout = QHBoxLayout()

        size = 20
        spin_movie = resourceMovie("ide/loading.gif")
        spin_movie.setSpeed(60)
        spin_movie.setScaledSize(QSize(size, size))
        spin_movie.start()

        self.processing_animation = QLabel()
        self.processing_animation.setMaximumSize(QSize(size, size))
        self.processing_animation.setMinimumSize(QSize(size, size))
        self.processing_animation.setMovie(spin_movie)

        button_layout.addWidget(self.processing_animation)
        button_layout.addWidget(self.running_time)
        button_layout.addStretch()
        button_layout.addWidget(self.plot_button)
        button_layout.addWidget(self.kill_button)
        button_layout.addWidget(self.done_button)

        layout.addStretch()
        layout.addLayout(button_layout)

        self.setLayout(layout)

        self.kill_button.clicked.connect(self.killJobs)
        self.done_button.clicked.connect(self.accept)

        self.__updating = False
        self.__update_queued = False
        self.__simulation_started = False

        self.__update_timer = QTimer(self)
        self.__update_timer.setInterval(500)
        self.__update_timer.timeout.connect(self.updateRunStatus)


    def startSimulation(self, arguments):
        self._run_model.reset()

        def run():
            self._run_model.startSimulations( arguments )

        simulation_thread = Thread(name="ert_gui_simulation_thread")
        simulation_thread.setDaemon(True)
        simulation_thread.run = run
        simulation_thread.start()

        self.__update_timer.start()


    def checkIfRunFinished(self):
        if self._run_model.isFinished():
            self.hideKillAndShowDone()

            if self._run_model.hasRunFailed():
                error = self._run_model.getFailMessage()
                QMessageBox.critical(self, "Simulations failed!", "The simulation failed with the following error:\n\n%s" % error)
                self.reject()


    def updateRunStatus(self):
        self.checkIfRunFinished()

        self.total_progress.setProgress(self._run_model.getProgress())

        self.__status_label.setText(self._run_model.getPhaseName())

        states = self.simulations_tracker.getStates()

        if self._run_model.isIndeterminate():
            self.progress.setIndeterminate(True)

            for state in states:
                self.legends[state].updateLegend(state.name, 0, 0)

        else:
            self.progress.setIndeterminate(False)
            total_count = self._run_model.getQueueSize()
            queue_status = self._run_model.getQueueStatus()

            for state in states:
                state.count = 0
                state.total_count = total_count

            for state in states:
                for queue_state in queue_status:
                    if queue_state in state.state:
                        state.count += queue_status[queue_state]

                self.progress.updateState(state.state, 100.0 * state.count / state.total_count)
                self.legends[state].updateLegend(state.name, state.count, state.total_count)

        self.setRunningTime()


    def setRunningTime(self):
        days = 0
        hours = 0
        minutes = 0
        seconds = self._run_model.getRunningTime()

        if seconds >= 60:
            minutes, seconds = divmod(seconds, 60)

        if minutes >= 60:
            hours, minutes = divmod(minutes, 60)

        if hours >= 24:
            days, hours = divmod(hours, 24)

        if days > 0:
            self.running_time.setText("Running time: %d days %d hours %d minutes %d seconds" % (days, hours, minutes, seconds))
        elif hours > 0:
            self.running_time.setText("Running time: %d hours %d minutes %d seconds" % (hours, minutes, seconds))
        elif minutes > 0:
            self.running_time.setText("Running time: %d minutes %d seconds" % (minutes, seconds))
        else:
            self.running_time.setText("Running time: %d seconds" % seconds)


    def killJobs(self):
        kill_job = QMessageBox.question(self, "Kill simulations?", "Are you sure you want to kill the currently running simulations?", QMessageBox.Yes | QMessageBox.No )

        if kill_job == QMessageBox.Yes:
            if self._run_model.killAllSimulations():
                self.reject()


    def hideKillAndShowDone(self):
        self.__update_timer.stop()
        self.processing_animation.hide()
        self.kill_button.setHidden(True)
        self.done_button.setHidden(False)
Beispiel #3
0
class RunDialog(QDialog):
    def __init__(self, run_model, parent):
        QDialog.__init__(self, parent)
        self.setWindowFlags(self.windowFlags()
                            & ~Qt.WindowContextHelpButtonHint)
        self.setWindowFlags(self.windowFlags() & ~Qt.WindowCloseButtonHint)
        self.setModal(True)
        self.setWindowModality(Qt.WindowModal)
        self.setWindowTitle("Simulations")

        assert isinstance(run_model, BaseRunModel)
        self._run_model = run_model

        layout = QVBoxLayout()
        layout.setSizeConstraint(QLayout.SetFixedSize)

        self.simulations_tracker = SimulationsTracker()
        states = self.simulations_tracker.getStates()

        self.total_progress = SimpleProgress()
        layout.addWidget(self.total_progress)

        status_layout = QHBoxLayout()
        status_layout.addStretch()
        self.__status_label = QLabel()
        status_layout.addWidget(self.__status_label)
        status_layout.addStretch()
        layout.addLayout(status_layout)

        self.progress = Progress()
        self.progress.setIndeterminateColor(self.total_progress.color)
        for state in states:
            self.progress.addState(state.state, QColor(*state.color),
                                   100.0 * state.count / state.total_count)

        layout.addWidget(self.progress)

        legend_layout = QHBoxLayout()
        self.legends = {}
        for state in states:
            self.legends[state] = Legend("%s (%d/%d)", QColor(*state.color))
            self.legends[state].updateLegend(state.name, 0, 0)
            legend_layout.addWidget(self.legends[state])

        layout.addLayout(legend_layout)

        self.running_time = QLabel("")

        ert = None
        if isinstance(run_model, BaseRunModel):
            ert = run_model.ert()

        self.plot_tool = PlotTool()
        self.plot_tool.setParent(None)
        self.plot_button = QPushButton(self.plot_tool.getName())
        self.plot_button.clicked.connect(self.plot_tool.trigger)
        self.plot_button.setEnabled(ert is not None)

        self.kill_button = QPushButton("Kill simulations")
        self.done_button = QPushButton("Done")
        self.done_button.setHidden(True)

        button_layout = QHBoxLayout()

        size = 20
        spin_movie = resourceMovie("ide/loading.gif")
        spin_movie.setSpeed(60)
        spin_movie.setScaledSize(QSize(size, size))
        spin_movie.start()

        self.processing_animation = QLabel()
        self.processing_animation.setMaximumSize(QSize(size, size))
        self.processing_animation.setMinimumSize(QSize(size, size))
        self.processing_animation.setMovie(spin_movie)

        button_layout.addWidget(self.processing_animation)
        button_layout.addWidget(self.running_time)
        button_layout.addStretch()
        button_layout.addWidget(self.plot_button)
        button_layout.addWidget(self.kill_button)
        button_layout.addWidget(self.done_button)

        layout.addStretch()
        layout.addLayout(button_layout)

        self.setLayout(layout)

        self.kill_button.clicked.connect(self.killJobs)
        self.done_button.clicked.connect(self.accept)

        self.__updating = False
        self.__update_queued = False
        self.__simulation_started = False

        self.__update_timer = QTimer(self)
        self.__update_timer.setInterval(500)
        self.__update_timer.timeout.connect(self.updateRunStatus)

    def startSimulation(self, arguments):
        self._run_model.reset()

        def run():
            self._run_model.startSimulations(arguments)

        simulation_thread = Thread(name="ert_gui_simulation_thread")
        simulation_thread.setDaemon(True)
        simulation_thread.run = run
        simulation_thread.start()

        self.__update_timer.start()

    def checkIfRunFinished(self):
        if self._run_model.isFinished():
            self.hideKillAndShowDone()

            if self._run_model.hasRunFailed():
                error = self._run_model.getFailMessage()
                QMessageBox.critical(
                    self, "Simulations failed!",
                    "The simulation failed with the following error:\n\n%s" %
                    error)
                self.reject()

    def updateRunStatus(self):
        self.checkIfRunFinished()

        self.total_progress.setProgress(self._run_model.getProgress())

        self.__status_label.setText(self._run_model.getPhaseName())

        states = self.simulations_tracker.getStates()

        if self._run_model.isIndeterminate():
            self.progress.setIndeterminate(True)

            for state in states:
                self.legends[state].updateLegend(state.name, 0, 0)

        else:
            self.progress.setIndeterminate(False)
            total_count = self._run_model.getQueueSize()
            queue_status = self._run_model.getQueueStatus()

            for state in states:
                state.count = 0
                state.total_count = total_count

            for state in states:
                for queue_state in queue_status:
                    if queue_state in state.state:
                        state.count += queue_status[queue_state]

                self.progress.updateState(
                    state.state, 100.0 * state.count / state.total_count)
                self.legends[state].updateLegend(state.name, state.count,
                                                 state.total_count)

        self.setRunningTime()

    def setRunningTime(self):
        days = 0
        hours = 0
        minutes = 0
        seconds = self._run_model.getRunningTime()

        if seconds >= 60:
            minutes, seconds = divmod(seconds, 60)

        if minutes >= 60:
            hours, minutes = divmod(minutes, 60)

        if hours >= 24:
            days, hours = divmod(hours, 24)

        if days > 0:
            self.running_time.setText(
                "Running time: %d days %d hours %d minutes %d seconds" %
                (days, hours, minutes, seconds))
        elif hours > 0:
            self.running_time.setText(
                "Running time: %d hours %d minutes %d seconds" %
                (hours, minutes, seconds))
        elif minutes > 0:
            self.running_time.setText("Running time: %d minutes %d seconds" %
                                      (minutes, seconds))
        else:
            self.running_time.setText("Running time: %d seconds" % seconds)

    def killJobs(self):
        kill_job = QMessageBox.question(
            self, "Kill simulations?",
            "Are you sure you want to kill the currently running simulations?",
            QMessageBox.Yes | QMessageBox.No)

        if kill_job == QMessageBox.Yes:
            if self._run_model.killAllSimulations():
                self.reject()

    def hideKillAndShowDone(self):
        self.__update_timer.stop()
        self.processing_animation.hide()
        self.kill_button.setHidden(True)
        self.done_button.setHidden(False)
Beispiel #4
0
class RunDialog(QDialog):
    def __init__(self, run_model, parent):
        QDialog.__init__(self, parent)
        self.setWindowFlags(self.windowFlags()
                            & ~Qt.WindowContextHelpButtonHint)
        self.setWindowFlags(self.windowFlags() & ~Qt.WindowCloseButtonHint)
        self.setModal(True)
        self.setWindowModality(Qt.WindowModal)
        self.setWindowTitle("Simulations")

        assert isinstance(run_model, BaseRunModel)
        self._run_model = run_model

        layout = QVBoxLayout()
        layout.setSizeConstraint(QLayout.SetFixedSize)

        self.simulations_tracker = SimulationsTracker()
        states = self.simulations_tracker.getStates()

        self.total_progress = SimpleProgress()
        layout.addWidget(self.total_progress)

        status_layout = QHBoxLayout()
        status_layout.addStretch()
        self.__status_label = QLabel()
        status_layout.addWidget(self.__status_label)
        status_layout.addStretch()
        layout.addLayout(status_layout)

        self.progress = Progress()
        self.progress.setIndeterminateColor(self.total_progress.color)
        for state in states:
            self.progress.addState(state.state, QColor(*state.color),
                                   100.0 * state.count / state.total_count)

        layout.addWidget(self.progress)

        self.detailed_progress = None

        legend_layout = QHBoxLayout()
        self.legends = {}
        for state in states:
            self.legends[state] = Legend("%s (%d/%d)", QColor(*state.color))
            self.legends[state].updateLegend(state.name, 0, 0)
            legend_layout.addWidget(self.legends[state])

        layout.addLayout(legend_layout)

        self.running_time = QLabel("")

        ert = None
        if isinstance(run_model, BaseRunModel):
            ert = run_model.ert()

        self.plot_tool = PlotTool()
        self.plot_tool.setParent(None)
        self.plot_button = QPushButton(self.plot_tool.getName())
        self.plot_button.clicked.connect(self.plot_tool.trigger)
        self.plot_button.setEnabled(ert is not None)

        self.kill_button = QPushButton("Kill simulations")
        self.done_button = QPushButton("Done")
        self.done_button.setHidden(True)
        self.restart_button = QPushButton("Restart")
        self.restart_button.setHidden(True)
        self.show_details_button = QPushButton("Details")

        self.realizations_view = QListView()
        self.realizations_view.setModel(
            QStandardItemModel(self.realizations_view))
        self.realizations_view.setVisible(False)

        button_layout = QHBoxLayout()

        size = 20
        spin_movie = resourceMovie("ide/loading.gif")
        spin_movie.setSpeed(60)
        spin_movie.setScaledSize(QSize(size, size))
        spin_movie.start()

        self.processing_animation = QLabel()
        self.processing_animation.setMaximumSize(QSize(size, size))
        self.processing_animation.setMinimumSize(QSize(size, size))
        self.processing_animation.setMovie(spin_movie)

        button_layout.addWidget(self.processing_animation)
        button_layout.addWidget(self.running_time)
        button_layout.addStretch()
        button_layout.addWidget(self.show_details_button)
        button_layout.addWidget(self.plot_button)
        button_layout.addWidget(self.kill_button)
        button_layout.addWidget(self.done_button)
        button_layout.addWidget(self.restart_button)

        layout.addStretch()
        layout.addLayout(button_layout)

        layout.addWidget(self.realizations_view)

        self.setLayout(layout)

        self.kill_button.clicked.connect(self.killJobs)
        self.done_button.clicked.connect(self.accept)
        self.restart_button.clicked.connect(self.restart_failed_realizations)
        self.show_details_button.clicked.connect(self.show_detailed_progress)

        self.__updating = False
        self.__update_queued = False
        self.__simulation_started = False

        self.__update_timer = QTimer(self)
        self.__update_timer.setInterval(500)
        self.__update_timer.timeout.connect(self.updateRunStatus)
        self._simulations_argments = {}

    def startSimulation(self, arguments):

        self._simulations_argments = arguments

        if not 'prev_successful_realizations' in self._simulations_argments:
            self._simulations_argments['prev_successful_realizations'] = 0
        self._run_model.reset()

        def run():
            self._run_model.startSimulations(self._simulations_argments)

        simulation_thread = Thread(name="ert_gui_simulation_thread")
        simulation_thread.setDaemon(True)
        simulation_thread.run = run
        simulation_thread.start()

        self.__update_timer.start()

    def checkIfRunFinished(self):
        if self._run_model.isFinished():

            self.update_realizations_view()
            self.hideKillAndShowDone()

            if self._run_model.hasRunFailed():
                error = self._run_model.getFailMessage()
                QMessageBox.critical(
                    self, "Simulations failed!",
                    "The simulation failed with the following error:\n\n%s" %
                    error)
                self.reject()

    def updateRunStatus(self):
        self.checkIfRunFinished()

        self.total_progress.setProgress(self._run_model.getProgress())

        self.__status_label.setText(self._run_model.getPhaseName())

        states = self.simulations_tracker.getStates()

        if self._run_model.isIndeterminate():
            self.progress.setIndeterminate(True)

            for state in states:
                self.legends[state].updateLegend(state.name, 0, 0)

        else:
            if self.detailed_progress:
                self.detailed_progress.set_progress(
                    *self._run_model.getDetailedProgress())

            self.progress.setIndeterminate(False)
            total_count = self._run_model.getQueueSize()
            queue_status = self._run_model.getQueueStatus()

            for state in states:
                state.count = 0
                state.total_count = total_count

            for state in states:
                for queue_state in queue_status:
                    if queue_state in state.state:
                        state.count += queue_status[queue_state]

                self.progress.updateState(
                    state.state, 100.0 * state.count / state.total_count)
                self.legends[state].updateLegend(state.name, state.count,
                                                 state.total_count)

        self.setRunningTime()

    def setRunningTime(self):
        days = 0
        hours = 0
        minutes = 0
        seconds = self._run_model.getRunningTime()

        if seconds >= 60:
            minutes, seconds = divmod(seconds, 60)

        if minutes >= 60:
            hours, minutes = divmod(minutes, 60)

        if hours >= 24:
            days, hours = divmod(hours, 24)

        if days > 0:
            self.running_time.setText(
                "Running time: %d days %d hours %d minutes %d seconds" %
                (days, hours, minutes, seconds))
        elif hours > 0:
            self.running_time.setText(
                "Running time: %d hours %d minutes %d seconds" %
                (hours, minutes, seconds))
        elif minutes > 0:
            self.running_time.setText("Running time: %d minutes %d seconds" %
                                      (minutes, seconds))
        else:
            self.running_time.setText("Running time: %d seconds" % seconds)

    def killJobs(self):
        kill_job = QMessageBox.question(
            self, "Kill simulations?",
            "Are you sure you want to kill the currently running simulations?",
            QMessageBox.Yes | QMessageBox.No)

        if kill_job == QMessageBox.Yes:
            if self._run_model.killAllSimulations():
                self.reject()

    def hideKillAndShowDone(self):
        self.__update_timer.stop()
        self.processing_animation.hide()
        self.kill_button.setHidden(True)
        self.done_button.setHidden(False)
        self.realizations_view.setVisible(True)
        self.restart_button.setVisible(self.has_failed_realizations())
        self.restart_button.setEnabled(self._run_model.support_restart)

    def has_failed_realizations(self):
        completed = self._run_model.completed_realizations_mask
        initial = self._run_model.initial_realizations_mask
        for (index, successful) in enumerate(completed):
            if initial[index] and not successful:
                return True
        return False

    def count_successful_realizations(self):
        """
        Counts the realizations completed in the prevoius ensemble run
        :return:
        """
        completed = self._run_model.completed_realizations_mask
        return completed.count(True)

    def create_mask_from_failed_realizations(self):
        """
        Creates a BoolVector mask representing the failed realizations
        :return: Type BoolVector
        """
        completed = self._run_model.completed_realizations_mask
        initial = self._run_model.initial_realizations_mask
        inverted_mask = BoolVector(default_value=False)
        for (index, successful) in enumerate(completed):
            inverted_mask[index] = initial[index] and not successful
        return inverted_mask

    def restart_failed_realizations(self):

        msg = QMessageBox(self)
        msg.setIcon(QMessageBox.Information)
        msg.setText(
            "Note that workflows will only be executed on the restarted realizations and that this might have unexpected consequences."
        )
        msg.setWindowTitle("Restart Failed Realizations")
        msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
        result = msg.exec_()

        if result == QMessageBox.Ok:
            active_realizations = self.create_mask_from_failed_realizations()
            self._simulations_argments[
                'active_realizations'] = active_realizations
            self._simulations_argments[
                'prev_successful_realizations'] += self.count_successful_realizations(
                )
            self.startSimulation(self._simulations_argments)

    def update_realizations_view(self):
        completed = self._run_model.completed_realizations_mask
        for (index, successful) in enumerate(completed):
            items = self.realizations_view.model().findItems(str(index))
            if not items:
                item = QStandardItem(str(index))
                self.realizations_view.model().appendRow(item)
            else:
                item = items[0]
            item.setCheckState(successful or item.checkState())

    def show_detailed_progress(self):
        if not self.detailed_progress:
            self.detailed_progress = DetailedProgressDialog(
                self, self.simulations_tracker.getStates())
        self.detailed_progress.set_progress(
            *self._run_model.getDetailedProgress())
        self.detailed_progress.show()
Beispiel #5
0
class RunDialog(QDialog):

    def __init__(self, run_model, parent):
        QDialog.__init__(self, parent)
        self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)
        self.setWindowFlags(self.windowFlags() & ~Qt.WindowCloseButtonHint)
        self.setModal(True)
        self.setWindowModality(Qt.WindowModal)
        self.setWindowTitle("Simulations")

        assert isinstance(run_model, BaseRunModel)
        self._run_model = run_model

        layout = QVBoxLayout()
        layout.setSizeConstraint(QLayout.SetFixedSize)

        self.simulations_tracker = SimulationsTracker()
        states = self.simulations_tracker.getStates()

        self.total_progress = SimpleProgress()
        layout.addWidget(self.total_progress)

        status_layout = QHBoxLayout()
        status_layout.addStretch()
        self.__status_label = QLabel()
        status_layout.addWidget(self.__status_label)
        status_layout.addStretch()
        layout.addLayout(status_layout)

        self.progress = Progress()
        self.progress.setIndeterminateColor(self.total_progress.color)
        for state in states:
            self.progress.addState(state.state, QColor(*state.color), 100.0 * state.count / state.total_count)

        layout.addWidget(self.progress)

        self.detailed_progress = None

        legend_layout = QHBoxLayout()
        self.legends = {}
        for state in states:
            self.legends[state] = Legend("%s (%d/%d)", QColor(*state.color))
            self.legends[state].updateLegend(state.name, 0, 0)
            legend_layout.addWidget(self.legends[state])

        layout.addLayout(legend_layout)

        self.running_time = QLabel("")

        ert = None
        if isinstance(run_model, BaseRunModel):
            ert = run_model.ert()

        self.plot_tool = PlotTool()
        self.plot_tool.setParent(None)
        self.plot_button = QPushButton(self.plot_tool.getName())
        self.plot_button.clicked.connect(self.plot_tool.trigger)
        self.plot_button.setEnabled(ert is not None)

        self.kill_button = QPushButton("Kill simulations")
        self.done_button = QPushButton("Done")
        self.done_button.setHidden(True)
        self.restart_button = QPushButton("Restart")
        self.restart_button.setHidden(True)
        self.show_details_button = QPushButton("Details")

        self.realizations_view = QListView()
        self.realizations_view.setModel(QStandardItemModel(self.realizations_view))
        self.realizations_view.setVisible(False)

        button_layout = QHBoxLayout()

        size = 20
        spin_movie = resourceMovie("ide/loading.gif")
        spin_movie.setSpeed(60)
        spin_movie.setScaledSize(QSize(size, size))
        spin_movie.start()

        self.processing_animation = QLabel()
        self.processing_animation.setMaximumSize(QSize(size, size))
        self.processing_animation.setMinimumSize(QSize(size, size))
        self.processing_animation.setMovie(spin_movie)

        button_layout.addWidget(self.processing_animation)
        button_layout.addWidget(self.running_time)
        button_layout.addStretch()
        button_layout.addWidget(self.show_details_button)
        button_layout.addWidget(self.plot_button)
        button_layout.addWidget(self.kill_button)
        button_layout.addWidget(self.done_button)
        button_layout.addWidget(self.restart_button)

        layout.addStretch()
        layout.addLayout(button_layout)

        layout.addWidget(self.realizations_view)

        self.setLayout(layout)

        self.kill_button.clicked.connect(self.killJobs)
        self.done_button.clicked.connect(self.accept)
        self.restart_button.clicked.connect(self.restart_failed_realizations)
        self.show_details_button.clicked.connect(self.show_detailed_progress)

        self.__updating = False
        self.__update_queued = False
        self.__simulation_started = False

        self.__update_timer = QTimer(self)
        self.__update_timer.setInterval(500)
        self.__update_timer.timeout.connect(self.updateRunStatus)
        self._simulations_argments = {}

    def startSimulation(self, arguments):

        self._simulations_argments = arguments

        if not 'prev_successful_realizations' in self._simulations_argments:
            self._simulations_argments['prev_successful_realizations'] = 0
        self._run_model.reset()

        def run():
            self._run_model.startSimulations( self._simulations_argments )

        simulation_thread = Thread(name="ert_gui_simulation_thread")
        simulation_thread.setDaemon(True)
        simulation_thread.run = run
        simulation_thread.start()

        self.__update_timer.start()


    def checkIfRunFinished(self):
        if self._run_model.isFinished():

            self.update_realizations_view()
            self.hideKillAndShowDone()

            if self._run_model.hasRunFailed():
                error = self._run_model.getFailMessage()
                QMessageBox.critical(self, "Simulations failed!", "The simulation failed with the following error:\n\n%s" % error)
                self.reject()


    def updateRunStatus(self):
        self.checkIfRunFinished()

        self.total_progress.setProgress(self._run_model.getProgress())

        self.__status_label.setText(self._run_model.getPhaseName())

        states = self.simulations_tracker.getStates()

        if self._run_model.isIndeterminate():
            self.progress.setIndeterminate(True)

            for state in states:
                self.legends[state].updateLegend(state.name, 0, 0)

        else:
            if self.detailed_progress:
                self.detailed_progress.set_progress(*self._run_model.getDetailedProgress())

            self.progress.setIndeterminate(False)
            total_count = self._run_model.getQueueSize()
            queue_status = self._run_model.getQueueStatus()

            for state in states:
                state.count = 0
                state.total_count = total_count

            for state in states:
                for queue_state in queue_status:
                    if queue_state in state.state:
                        state.count += queue_status[queue_state]

                self.progress.updateState(state.state, 100.0 * state.count / state.total_count)
                self.legends[state].updateLegend(state.name, state.count, state.total_count)

        self.setRunningTime()


    def setRunningTime(self):
        days = 0
        hours = 0
        minutes = 0
        seconds = self._run_model.getRunningTime()

        if seconds >= 60:
            minutes, seconds = divmod(seconds, 60)

        if minutes >= 60:
            hours, minutes = divmod(minutes, 60)

        if hours >= 24:
            days, hours = divmod(hours, 24)

        if days > 0:
            self.running_time.setText("Running time: %d days %d hours %d minutes %d seconds" % (days, hours, minutes, seconds))
        elif hours > 0:
            self.running_time.setText("Running time: %d hours %d minutes %d seconds" % (hours, minutes, seconds))
        elif minutes > 0:
            self.running_time.setText("Running time: %d minutes %d seconds" % (minutes, seconds))
        else:
            self.running_time.setText("Running time: %d seconds" % seconds)


    def killJobs(self):
        kill_job = QMessageBox.question(self, "Kill simulations?", "Are you sure you want to kill the currently running simulations?", QMessageBox.Yes | QMessageBox.No )

        if kill_job == QMessageBox.Yes:
            if self._run_model.killAllSimulations():
                self.reject()


    def hideKillAndShowDone(self):
        self.__update_timer.stop()
        self.processing_animation.hide()
        self.kill_button.setHidden(True)
        self.done_button.setHidden(False)
        self.realizations_view.setVisible(True)
        self.restart_button.setVisible(self.has_failed_realizations() )
        self.restart_button.setEnabled(self._run_model.support_restart)


    def has_failed_realizations(self):
        completed = self._run_model.completed_realizations_mask
        initial = self._run_model.initial_realizations_mask
        for (index, successful) in enumerate(completed):
            if initial[index] and not successful:
                return True
        return False


    def count_successful_realizations(self):
        """
        Counts the realizations completed in the prevoius ensemble run
        :return:
        """
        completed = self._run_model.completed_realizations_mask
        return completed.count(True)

    def create_mask_from_failed_realizations(self):
        """
        Creates a BoolVector mask representing the failed realizations
        :return: Type BoolVector
        """
        completed = self._run_model.completed_realizations_mask
        initial = self._run_model.initial_realizations_mask
        inverted_mask = BoolVector(  default_value = False )
        for (index, successful) in enumerate(completed):
            inverted_mask[index] = initial[index] and not successful
        return inverted_mask


    def restart_failed_realizations(self):

        msg = QMessageBox(self)
        msg.setIcon(QMessageBox.Information)
        msg.setText("Note that workflows will only be executed on the restarted realizations and that this might have unexpected consequences.")
        msg.setWindowTitle("Restart Failed Realizations")
        msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
        result = msg.exec_()

        if result == QMessageBox.Ok:
            active_realizations = self.create_mask_from_failed_realizations()
            self._simulations_argments['active_realizations'] = active_realizations
            self._simulations_argments['prev_successful_realizations'] += self.count_successful_realizations()
            self.startSimulation(self._simulations_argments)

    def update_realizations_view(self):
        completed = self._run_model.completed_realizations_mask
        for (index, successful) in enumerate(completed):
            items = self.realizations_view.model().findItems(str(index))
            if not items:
                item = QStandardItem(str(index))
                self.realizations_view.model().appendRow(item)
            else:
                item = items[0]
            item.setCheckState(successful or item.checkState())

    def show_detailed_progress(self):
        if not self.detailed_progress:
            self.detailed_progress = DetailedProgressDialog(self, self.simulations_tracker.getStates())
        self.detailed_progress.set_progress(*self._run_model.getDetailedProgress())
        self.detailed_progress.show()