Skip to content

Commit

Permalink
Add the possibility to view the status of case-studies in the gui (#880)
Browse files Browse the repository at this point in the history
Co-authored-by: Sebastian Böhm <[email protected]>
  • Loading branch information
Sinerum and boehmseb committed Sep 3, 2024
1 parent 3b7db34 commit 88fb16d
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 25 deletions.
21 changes: 17 additions & 4 deletions uicomponents/CaseStudyGeneration.ui
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<x>0</x>
<y>0</y>
<width>760</width>
<height>443</height>
<height>491</height>
</rect>
</property>
<property name="sizePolicy">
Expand Down Expand Up @@ -150,6 +150,19 @@
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="case_study"/>
</item>
<item>
<widget class="QComboBox" name="experiment"/>
</item>
<item>
<widget class="QCheckBox" name="cs_filter">
<property name="text">
<string>Filter CaseStudy´</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="commit_search">
<property name="placeholderText">
Expand Down Expand Up @@ -358,8 +371,8 @@
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Noto Sans'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
Expand All @@ -374,7 +387,7 @@ p, li { white-space: pre-wrap; }
<x>0</x>
<y>0</y>
<width>760</width>
<height>22</height>
<height>34</height>
</rect>
</property>
</widget>
Expand Down
141 changes: 128 additions & 13 deletions varats/varats/gui/cs_gen/case_study_generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import benchbuild as bb
import pygit2
from benchbuild import Experiment
from benchbuild.experiment import ExperimentRegistry
from PyQt5.QtCore import (
QModelIndex,
QDateTime,
Expand All @@ -17,7 +19,10 @@
from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import QMainWindow, QApplication, QMessageBox

import varats.paper.paper_config as PC
from varats.base.sampling_method import NormalSamplingMethod
from varats.data.databases.file_status_database import FileStatusDatabase
from varats.experiments.discover_experiments import initialize_experiments
from varats.gui.cs_gen.case_study_generation_ui import Ui_MainWindow
from varats.mapping.commit_map import get_commit_map, CommitMap
from varats.paper.case_study import CaseStudy, store_case_study
Expand All @@ -33,8 +38,10 @@
get_primary_project_source,
)
from varats.projects.discover_projects import initialize_projects
from varats.report.report import FileStatusExtension
from varats.revision.revisions import is_revision_blocked
from varats.tools.research_tools.vara_manager import ProcessManager
from varats.ts_utils.click_param_types import is_experiment_excluded
from varats.utils import settings
from varats.utils.git_util import (
get_initial_commit,
Expand Down Expand Up @@ -95,7 +102,16 @@ def __init__(self):
self.commit_search.textChanged.connect(
self.proxy_model.setFilterFixedString
)
self.cs_filter.stateChanged.connect(self.proxy_model.setCsFilter)
self.case_study.currentIndexChanged.connect(
self.proxy_model.update_case_study
)
self.show()
initialize_experiments()
self.experiment.addItems([
k for k, v in ExperimentRegistry.experiments.items()
if not is_experiment_excluded(k)
])

def update_project_list(self, filter_string: str = "") -> None:
"""Update the project list when a filter is applied."""
Expand Down Expand Up @@ -202,6 +218,7 @@ def revisions_of_project(self) -> None:
GenerationStrategy.SELECT_REVISION.value
)
if self.selected_project != self.revision_list_project:
self.case_study.clear()
self.revision_details.setText("Loading Revisions")
self.revision_details.repaint()
# Update the local project git
Expand All @@ -224,8 +241,22 @@ def revisions_of_project(self) -> None:

cmap = get_commit_map(self.selected_project)
commit_model = CommitTableModel(
list(map(commit_lookup_helper, commits)), cmap, project
list(map(commit_lookup_helper, commits)), cmap, project,
ExperimentRegistry.experiments[self.experiment.currentText()]
)
self.proxy_model.setProject(project)
self.case_study.currentIndexChanged.connect(
commit_model.update_case_study
)
self.experiment.currentTextChanged.connect(
commit_model.update_experiment
)
current_config = PC.get_paper_config()
case_studies = current_config.get_all_case_studies()
self.case_study.addItems([
f"{cs.project_name}_{cs.version}" for cs in case_studies
if cs.project_name == self.selected_project
])
self.proxy_model.setSourceModel(commit_model)
self.revision_list_project = self.selected_project
self.revision_details.clear()
Expand All @@ -234,34 +265,57 @@ def revisions_of_project(self) -> None:
def show_revision_data(self, index: QModelIndex) -> None:
"""Update the revision data field."""
commit = self.revision_list.model().data(index, Qt.WhatsThisRole)
commit_info = f"{commit.hex}:\n" \
commit_info = f"{commit.id}:\n" \
f"{commit.author.name}, " \
f"<{commit.author.email}>\n\n" \
f"{commit.message}"
self.selected_commit = commit.hex
self.selected_commit = commit.id
self.revision_details.setText(commit_info)
self.revision_details.update()


class CommitTableFilterModel(QSortFilterProxyModel):
"""Filter Model for the revision table."""
filter_string = ""
cs_filter = False

def setFilterFixedString(self, pattern: str) -> None:
self.filter_string = pattern
self.invalidate()

def update_case_study(self, index: int) -> None:
current_config = PC.get_paper_config()
case_studies = [
cs for cs in current_config.get_all_case_studies()
if cs.project_name == self._project.NAME
]
self._case_study = case_studies[index]
self.invalidate()

def setProject(self, project: tp.Type['bb.Project']) -> None:
self._project = project

def setCsFilter(self, cs_filter: bool) -> None:
self.cs_filter = cs_filter
self.invalidate()

def filterAcceptsRow(
self, source_row: int, source_parent: QModelIndex
) -> bool:
commit_index = self.sourceModel().index(source_row, 0, source_parent)
author_index = self.sourceModel().index(source_row, 1, source_parent)
return self.sourceModel().data(commit_index,
Qt.DisplayRole).lower() \
.__contains__(self.filter_string.lower()) \
or self.sourceModel().data(author_index,
Qt.DisplayRole).lower() \
.__contains__(self.filter_string.lower())
hash_filter = self.sourceModel().data(
commit_index, Qt.DisplayRole
).lower().__contains__(self.filter_string.lower())
author_filter = self.sourceModel().data(
author_index, Qt.DisplayRole
).lower().__contains__(self.filter_string.lower())
case_study_filter = (
not self.cs_filter
) or FullCommitHash.from_pygit_commit(
self.sourceModel().data(commit_index, Qt.WhatsThisRole)
) in self._case_study.revisions
return case_study_filter and (hash_filter or author_filter)


class CommitTableModel(QAbstractTableModel):
Expand All @@ -270,13 +324,51 @@ class CommitTableModel(QAbstractTableModel):

def __init__(
self, data: tp.List[pygit2.Commit], cmap: CommitMap,
project: tp.Type['bb.Project']
project: tp.Type['bb.Project'], experiment_type: tp.Type[Experiment]
):
super().__init__()
self._project = project
self._data = data
self._case_study: tp.Optional[CaseStudy] = None
self._experiment_type = experiment_type
self._cmap = cmap

def update_case_study(self, index: int) -> None:
current_config = PC.get_paper_config()
case_studies = [
cs for cs in current_config.get_all_case_studies()
if cs.project_name == self._project.NAME
]
self._case_study = case_studies[index]
if self._experiment_type:
self._status_data = FileStatusDatabase.get_data_for_project(
self._case_study.project_name, ["revision", "file_status"],
self._cmap,
self._case_study,
experiment_type=self._experiment_type,
tag_blocked=False
)
self._status_data.set_index("revision", inplace=True)
self.dataChanged.emit(
self.index(0, 0), self.index(self.rowCount(), self.columnCount())
)

def update_experiment(self, index: str) -> None:
self._experiment_type = ExperimentRegistry.experiments[index]
if self._case_study:
self._status_data = FileStatusDatabase.get_data_for_project(
self._case_study.project_name, ["revision", "file_status"],
self._cmap,
self._case_study,
experiment_type=self._experiment_type,
tag_blocked=False
)
self._status_data.set_index("revision", inplace=True)

self.dataChanged.emit(
self.index(0, 0), self.index(self.rowCount(), self.columnCount())
)

def headerData(self, section, orientation, role=Qt.DisplayRole):
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
return self.header_labels[section]
Expand All @@ -292,25 +384,48 @@ def sort(self, column: int, order: Qt.SortOrder = ...) -> None:

def __split_commit_data(self, commit: pygit2.Commit, column: int) -> tp.Any:
if column == 0:
return ShortCommitHash(commit.hex).hash
return ShortCommitHash.from_pygit_commit(commit).hash
if column == 1:
return commit.author.name
if column == 2:
tzinfo = timezone(timedelta(minutes=commit.author.offset))
date = datetime.fromtimestamp(float(commit.author.time), tzinfo)
return QDateTime(date)
if column == 3:
return self._cmap.short_time_id(ShortCommitHash(commit.hex))
return self._cmap.time_id(FullCommitHash.from_pygit_commit(commit))

def data(self, index: QModelIndex, role: int = Qt.DisplayRole) -> tp.Any:
commit = self._data[index.row()]
chash = FullCommitHash.from_pygit_commit(commit)
if role == Qt.DisplayRole:
return self.__split_commit_data(commit, index.column())
if is_revision_blocked(FullCommitHash(commit.hex), self._project):
if is_revision_blocked(chash, self._project):
if role == Qt.ForegroundRole:
return QColor(50, 100, 255)
if role == Qt.ToolTipRole:
return "Blocked"
if self._case_study and self._experiment_type:
if role == Qt.ForegroundRole:
chash = chash.to_short_commit_hash()
if chash in self._status_data.index:
if self._status_data.loc[
chash, "file_status"
] == FileStatusExtension.SUCCESS.get_status_extension():
return QColor(0, 255, 0)
elif self._status_data.loc[
chash, "file_status"
] == FileStatusExtension.FAILED.get_status_extension():
return QColor(255, 0, 0)
elif self._status_data.loc[
chash, "file_status"
] == FileStatusExtension.COMPILE_ERROR.get_status_extension(
):
return QColor(255, 0, 0)
elif self._status_data.loc[
chash, "file_status"
] == FileStatusExtension.MISSING.get_status_extension():
return QColor(255, 255, 0)

if role == Qt.WhatsThisRole:
return commit

Expand Down
20 changes: 15 additions & 5 deletions varats/varats/gui/cs_gen/case_study_generation_ui.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file '../uicomponents/CaseStudyGeneration.ui'
# Form implementation generated from reading ui file 'VaRA-Tool-Suite/uicomponents/CaseStudyGeneration.ui'
#
# Created by: PyQt5 UI code generator 5.13.2
#
Expand All @@ -14,7 +14,7 @@ class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.setEnabled(True)
MainWindow.resize(760, 443)
MainWindow.resize(760, 491)
sizePolicy = QtWidgets.QSizePolicy(
QtWidgets.QSizePolicy.MinimumExpanding,
QtWidgets.QSizePolicy.MinimumExpanding
Expand Down Expand Up @@ -87,6 +87,15 @@ def setupUi(self, MainWindow):
self.revisions.setSizePolicy(sizePolicy)
self.revisions.setObjectName("revisions")
self.verticalLayout_3.addWidget(self.revisions)
self.case_study = QtWidgets.QComboBox(self.revisionsPage)
self.case_study.setObjectName("case_study")
self.verticalLayout_3.addWidget(self.case_study)
self.experiment = QtWidgets.QComboBox(self.revisionsPage)
self.experiment.setObjectName("experiment")
self.verticalLayout_3.addWidget(self.experiment)
self.cs_filter = QtWidgets.QCheckBox(self.revisionsPage)
self.cs_filter.setObjectName("cs_filter")
self.verticalLayout_3.addWidget(self.cs_filter)
self.commit_search = QtWidgets.QLineEdit(self.revisionsPage)
self.commit_search.setClearButtonEnabled(True)
self.commit_search.setObjectName("commit_search")
Expand Down Expand Up @@ -206,7 +215,7 @@ def setupUi(self, MainWindow):
self.gridLayout.addWidget(self.projects, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 760, 22))
self.menubar.setGeometry(QtCore.QRect(0, 0, 760, 34))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
Expand All @@ -229,6 +238,7 @@ def retranslateUi(self, MainWindow):
self.label_2.setText(_translate("MainWindow", "Casestudy Version"))
self.generate.setText(_translate("MainWindow", "Generate"))
self.revisions.setText(_translate("MainWindow", "Revisions"))
self.cs_filter.setText(_translate("MainWindow", "Filter CaseStudy´"))
self.commit_search.setPlaceholderText(
_translate("MainWindow", "Search")
)
Expand All @@ -253,8 +263,8 @@ def retranslateUi(self, MainWindow):
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Ubuntu\'; font-size:11pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>"
"</style></head><body style=\" font-family:\'Noto Sans\'; font-size:10pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'Ubuntu\'; font-size:11pt;\"><br /></p></body></html>"
)
)

Expand Down
6 changes: 3 additions & 3 deletions varats/varats/ts_utils/click_param_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def create_report_type_choice() -> TypedChoice[tp.Type[BaseReport]]:
return TypedChoice(BaseReport.REPORT_TYPES)


def __is_experiment_excluded(experiment_name: str) -> bool:
def is_experiment_excluded(experiment_name: str) -> bool:
"""Checks if an experiment should be excluded, as we don't want to show/use
standard BB experiments."""
if experiment_name in ('raw', 'empty', 'no-measurement'):
Expand All @@ -162,7 +162,7 @@ def create_experiment_type_choice(
return TypedChoice({
k: v
for k, v in ExperimentRegistry.experiments.items()
if not __is_experiment_excluded(k)
if not is_experiment_excluded(k)
})


Expand All @@ -178,7 +178,7 @@ def create_multi_experiment_type_choice(
value_dict = {
k: [v] # make value a list to be consistent with entry for 'all'
for k, v in ExperimentRegistry.experiments.items()
if not __is_experiment_excluded(k)
if not is_experiment_excluded(k)
}
value_dict["all"] = [
experiment for value in value_dict.values() for experiment in value
Expand Down

0 comments on commit 88fb16d

Please sign in to comment.