Skip to content

Commit

Permalink
Added final test (final version of user script before I leave) (#158)
Browse files Browse the repository at this point in the history
* camera test scripts for TRR

* Converted test_scripts submodule to a regular directory (ignore previous 2 commits)

* Delete src/nectarchain/user_scripts/dmousadi/test_scripts/requirements.txt

* added trigger timing

* removed unknown property

* ridmi

* Remove empty file

* lint

* Update test_tools_components.py

---------

Co-authored-by: MOUSADI Despoina <[email protected]>
  • Loading branch information
dmousadi and MOUSADI Despoina authored Nov 6, 2024
1 parent 845b3c0 commit 8a02577
Show file tree
Hide file tree
Showing 4 changed files with 458 additions and 76 deletions.
6 changes: 0 additions & 6 deletions src/nectarchain/user_scripts/dmousadi/test_scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,6 @@ Automated tests from the Test Readiness Review document for the CTA NectarCAM ba

## Installation

Instructions on how to install and set up the project:
```
git clone https://drf-gitlab.cea.fr/dmousadi/camera-test-scripts
cd camera-test-scripts
pip install -r requirements.txt
```
If you want to automatically download your data, one of the requirements is also DIRAC, for which you need to have a grid certificate. It is not necessary for this repo, if you have your NectarCAM runs (fits files) locally stored. You can find more information about DIRAC [here](https://gitlab.cta-observatory.org/cta-computing/dpps/workload/CTADIRAC). If you are installing these packages for the first time and getting 'error building wheel', you might need to (re)install some of these: swig, ca-certificates, openssl, boost, protobuff, cmake.

Once you have set up your environment, if you're not already a nectarchain user you need to set the NECTARCAMDATA environment variable to the directory where you have the NectarCAM runs:
Expand Down
144 changes: 100 additions & 44 deletions src/nectarchain/user_scripts/dmousadi/test_scripts/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
The class uses the PyQt5 library for the GUI implementation and the Matplotlib library for plotting the test results.
"""


import argparse
import os
import pickle
Expand All @@ -38,6 +37,7 @@
QTextEdit,
QVBoxLayout,
QWidget,
QWidgetItem,
)

# Ensure the tests directory is in sys.path
Expand All @@ -52,9 +52,19 @@
import pedestal_test
import pix_couple_tim_uncertainty_test
import pix_tim_uncertainty_test
import trigger_timing_test


class TestRunner(QWidget):
test_modules = {
"Linearity Test": linearity_test,
"Deadtime Test": deadtime_test,
"Pedestal Test": pedestal_test,
"Pixel Time Uncertainty Test": pix_tim_uncertainty_test,
"Time Uncertainty Between Couples of Pixels": pix_couple_tim_uncertainty_test,
"Trigger Timing Test": trigger_timing_test,
}

def __init__(self):
super().__init__()
self.params = {}
Expand Down Expand Up @@ -89,25 +99,13 @@ def init_ui(self):
color: #ffffff; /* Light text */
border: 1px solid #888888; /* Light border */
padding: 5px; /* Add padding */
fixed-height: 30px; /* Set a fixed height */
min-width: 200px; /* Fixed width */
}
QPushButton {
background-color: #4caf50; /* Green button */
color: white; /* White text */
border: none; /* No border */
padding: 10px; /* Add padding */
border-radius: 5px; /* Rounded corners */
}
QPushButton:hover {
background-color: #45a049; /* Darker green on hover */
}
QTextEdit {
background-color: #1e1e1e; /* Dark output box */
color: #ffffff; /* Light text */
border: 1px solid #888888; /* Light border */
padding: 5px; /* Add padding */
fixed-height: 150px; /* Set a fixed height */
min-width: 800px; /* Set a minimum width to match the canvas */
}
QTextEdit:focus {
Expand Down Expand Up @@ -144,13 +142,15 @@ def init_ui(self):
controls_layout.addWidget(self.label)

self.test_selector = QComboBox(self)
self.test_selector.addItem("Select Test")
self.test_selector.addItems(
[
"Linearity Test",
"Deadtime Test",
"Pedestal Test",
"Pixel Time Uncertainty Test",
"Time Uncertainty Between Couples of Pixels",
"Trigger Timing Test",
]
)
self.test_selector.setFixedWidth(400) # Fixed width for the dropdown
Expand All @@ -165,6 +165,8 @@ def init_ui(self):

# Button to run the test
self.run_button = QPushButton("Run Test", self)
# Disable the run button initially
self.run_button.setEnabled(False)
self.run_button.clicked.connect(self.run_test)
controls_layout.addWidget(self.run_button)

Expand Down Expand Up @@ -240,11 +242,14 @@ def get_parameters_from_module(self, module):
# Fetch parameters from the module
if hasattr(module, "get_args"):
parser = module.get_args()
return {
arg.dest: arg.default
for arg in parser._actions
if isinstance(arg, argparse._StoreAction)
}
params = {}
for arg in parser._actions:
if isinstance(arg, argparse._StoreAction):
params[arg.dest] = {
"default": arg.default,
"help": arg.help, # Store the help text
}
return params
else:
raise RuntimeError("No get_args function found in module.")

Expand All @@ -258,32 +263,83 @@ def debug_layout(self):
def update_parameters(self):
# Clear existing parameter fields
for i in reversed(range(self.param_layout.count())):
widget = self.param_layout.itemAt(i).widget()
if widget:
widget.deleteLater()
item = self.param_layout.itemAt(i)

if isinstance(
item, QHBoxLayout
): # Check if the item is a QHBoxLayout (contains label and help button)
for j in reversed(range(item.count())):
widget = item.itemAt(j).widget()
if widget:
widget.deleteLater()
elif isinstance(item, QWidgetItem): # For direct widgets like QLineEdit
widget = item.widget()
if widget:
widget.deleteLater()

# Remove the item itself from the layout
self.param_layout.removeItem(item)

# Get the selected test and corresponding module
selected_test = self.test_selector.currentText()
test_modules = {
"Linearity Test": linearity_test,
"Deadtime Test": deadtime_test,
"Pedestal Test": pedestal_test,
"Pixel Time Uncertainty Test": pix_tim_uncertainty_test,
"Time Uncertainty Between Couples of Pixels": pix_couple_tim_uncertainty_test,
}

module = test_modules.get(selected_test)

# If the placeholder is selected, do nothing
if selected_test == "Select Test":
self.run_button.setEnabled(False)
return

module = self.test_modules.get(selected_test)
if module:
try:
self.params = self.get_parameters_from_module(module)
for param, default in self.params.items():
if param == "temp_output":

for param, param_info in self.params.items():
if param == "temp_output": # Skip temp_output
continue

# Create a horizontal layout for the label and help button
param_layout = QHBoxLayout()

# Create label
label = QLabel(f"{param}:", self)
self.param_layout.addWidget(label)
param_layout.addWidget(label)

# Create tiny grey circle help button with a white question mark
help_button = QPushButton("?", self)
help_button.setFixedSize(16, 16) # Smaller button size
help_button.setStyleSheet(
"""
QPushButton {
background-color: grey;
color: white;
border-radius: 8px; /* Circular button */
font-weight: bold;
font-size: 10px; /* Smaller font size */
}
QPushButton:hover {
background-color: darkgrey; /* Change color on hover */
}
"""
)
help_button.setToolTip(param_info["help"])

# # Use lambda to capture the current param's help text
# help_button.clicked.connect(lambda _, p=param_info["help"]: self.show_help(p))

# Add the help button to the layout (next to the label)
param_layout.addWidget(help_button)
param_layout.addStretch() # Add stretch to push the help button to the right

# Add the horizontal layout (label + help button) to the main layout
self.param_layout.addLayout(param_layout)

# Create the input field for the parameter
entry = QLineEdit(self)
entry.setText(
str(default).replace("[", "").replace("]", "").replace(",", "")
str(param_info["default"])
.replace("[", "")
.replace("]", "")
.replace(",", "")
)
entry.setObjectName(param)
entry.setFixedWidth(400) # Set fixed width for QLineEdit
Expand All @@ -294,24 +350,24 @@ def update_parameters(self):
QTimer.singleShot(
0, self.param_widgets.update
) # Ensures the layout is updated

self.run_button.setEnabled(True)
except Exception as e:
QMessageBox.critical(self, "Error", f"Failed to fetch parameters: {e}")

else:
QMessageBox.critical(self, "Error", "No test selected or test not found")

def show_help(self, help_text):
QMessageBox.information(self, "Parameter Help", help_text)

def run_test(self):
# Clean up old plot files to avoid loading leftover files
self.cleanup_tempdir()

selected_test = self.test_selector.currentText()
test_modules = {
"Linearity Test": linearity_test,
"Deadtime Test": deadtime_test,
"Pedestal Test": pedestal_test,
"Pixel Time Uncertainty Test": pix_tim_uncertainty_test,
"Time Uncertainty Between Couples of Pixels": pix_couple_tim_uncertainty_test,
}
module = test_modules.get(selected_test)

module = self.test_modules.get(selected_test)

if module:
params = []
Expand All @@ -320,9 +376,9 @@ def run_test(self):

# Generate temporary output path
self.temp_output = tempfile.gettempdir()
print(f"Temporary output dir: {self.temp_output}") # Debug print
# print(f"Temporary output dir: {self.temp_output}") # Debug print

for param, default in self.params.items():
for param, _ in self.params.items():
widget_list = self.param_widgets.findChildren(QLineEdit, param)
if widget_list:
widget = widget_list[0]
Expand Down
Loading

0 comments on commit 8a02577

Please sign in to comment.