diff --git a/gui_config_tool/Slit_Config_tool_Preview.pdf b/gui_config_tool/Slit_Config_tool_Preview.pdf new file mode 100644 index 0000000..ba5b59d Binary files /dev/null and b/gui_config_tool/Slit_Config_tool_Preview.pdf differ diff --git a/gui_config_tool/app.py b/gui_config_tool/app.py new file mode 100644 index 0000000..5881688 --- /dev/null +++ b/gui_config_tool/app.py @@ -0,0 +1,86 @@ +""" +The GUI is in its very early stages. Its current features are the ability to take in a starlist file +and then display that file in a list +and a menu that doesn't do anything. 7/9/25 +""" +""" +random stuff +GUI has to be able to send a command with the target lists to the mask back end +to call the slit mask algorithm with the code from the backend + +the back end kind of already parses through a file that sorts all of the objects so I will +just take that and display that instead of through my awful input targets function +(they also have a function to view the list) +""" + + +#just importing everything for now. When on the final stages I will not import what I don't need +from targetListWidget import TargetDisplayWidget +from importTargetListandRun import MaskGenWidget +from menuBar import MenuBar +from maskConfigurations import MaskConfigurationsWidget +from PyQt6.QtCore import Qt +from PyQt6.QtWidgets import ( + QApplication, + QMainWindow, + QVBoxLayout, + QHBoxLayout, + QWidget, + QLabel, +) + +class TempWidgets(QLabel): + def __init__(self,w,h,text:str="hello"): + super().__init__() + self.setFixedSize(w,h) + self.setText(text) + self.setAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter) + self.setStyleSheet("border: 2px solid black;") + +class MainWindow(QMainWindow): + def __init__(self): + super().__init__() + self.setWindowTitle("LRIS-2 Slit Configuration Tool") + self.setGeometry(100,100,1000,700) + self.setMenuBar(MenuBar()) #sets the menu bar + + main_layout = QHBoxLayout() + layoutH1 = QHBoxLayout() + layoutV1 = QVBoxLayout() #left side + layoutV2 = QVBoxLayout() #right side + + mask_config_widget = MaskConfigurationsWidget() + mask_config_widget.setMaximumHeight(200) + import_target_list_display = MaskGenWidget() + sample_data = [[0,1,1,1],[1,0,1,1]] + + target_display = TargetDisplayWidget(sample_data) + + #temp_widget1 = TempWidgets(250,300,"Mask Configurations\nWill display a list of\nall previous configurations") + temp_widget2 = TempWidgets(200,500,"This will display\nall of the widths\nand positions of\nthe bar pairs") + temp_widget3 = TempWidgets(500,500,"This will display the current Mask Configuration") + + + import_target_list_display.change_data.connect(target_display.change_data) + + layoutV2.addWidget(mask_config_widget)#temp_widget1 + layoutV2.addWidget(import_target_list_display) + + layoutH1.addWidget(temp_widget2) + layoutH1.addWidget(temp_widget3) + + layoutV1.addLayout(layoutH1) + layoutV1.addWidget(target_display) + + main_layout.addLayout(layoutV1) + main_layout.addLayout(layoutV2) + + widget = QWidget() + widget.setLayout(main_layout) + self.setCentralWidget(widget) + + +app = QApplication([]) +window = MainWindow() +window.show() +app.exec() \ No newline at end of file diff --git a/gui_config_tool/importTargetListandRun.py b/gui_config_tool/importTargetListandRun.py new file mode 100644 index 0000000..be36e06 --- /dev/null +++ b/gui_config_tool/importTargetListandRun.py @@ -0,0 +1,80 @@ + +from inputTargets import TargetList +from targetListWidget import TargetDisplayWidget +from PyQt6.QtCore import QObject, pyqtSignal, Qt +from PyQt6.QtWidgets import ( + QFileDialog, + QVBoxLayout, + QWidget, + QPushButton, + QStackedLayout, + QLineEdit, + QFormLayout, + QGroupBox, + QBoxLayout + +) + + + +class MaskGenWidget(QWidget): + change_data = pyqtSignal(list) + def __init__(self): + super().__init__() + + + #self.setFixedSize(200,400) + #self.setStyleSheet("border: 2px solid black;") + import_target_list_button = QPushButton(text = "Import Target List") + name_of_mask = QLineEdit() + name_of_mask.setAlignment(Qt.AlignmentFlag.AlignTop) + import_target_list_button.setFixedSize(150,40) + + group_box = QGroupBox() + main_layout = QVBoxLayout() + secondary_layout = QFormLayout() + group_layout = QVBoxLayout() + group_layout.setAlignment(Qt.AlignmentFlag.AlignTop) + #group_box.setStyleSheet("border: 2px solid black;") + + + + import_target_list_button.clicked.connect(self.starlist_file_button_clicked) + + + #layout.addWidget(main_widget) + + secondary_layout.addRow("Mask Name:",name_of_mask) + group_layout.addLayout(secondary_layout) + + group_layout.addWidget(import_target_list_button) + group_box.setLayout(group_layout) + main_layout.addWidget(group_box) + + #xwidget.setLayout(layout) + + + self.setLayout(main_layout) + #self.show() + + + def starlist_file_button_clicked(self): + text_file_path, _ = QFileDialog.getOpenFileName( + self, + "Select a File", + "", + "All files (*)" + ) + + if text_file_path: + print(f"Selected file: {text_file_path}") + target_list = TargetList(text_file_path) + #self.new_data_list.emit(target_list.send_list()) + self.change_data.emit(target_list.send_list()) + + #TargetDisplayWidget(target_list.send_list()) + + + + + \ No newline at end of file diff --git a/gui_config_tool/inputTargets.py b/gui_config_tool/inputTargets.py new file mode 100644 index 0000000..e5a612d --- /dev/null +++ b/gui_config_tool/inputTargets.py @@ -0,0 +1,61 @@ +''' +the file format is a starlist: https://www2.keck.hawaii.edu/observing/starlist.html + +''' + +import numpy as np + + +keywords = ( + "pmra", + "pmdec", + "dra", + "ddec", + "vmag", + "rotmode", + "rotdest", + "wrap", + "raoffset", + "decoffset" + ) + +class TargetList: + + def __init__(self,file_path): + + self.file_path = file_path + ''' + reads a starlist file and returns a list [name: Ra,Dec,equinox,[other]] + ''' + self.target_list = [] + with open(self.file_path) as file: + for line in file: + if line[0] != "#" and line.split(): + + name = line[0:15].rstrip() #gets the name + line = line.replace(line[0:15],"") #removes the name from the line + line = line.replace(line[line.find("#"):],"") #takes out any end comments + + line = line.split(" ") #seperates all the items in the list + line = [x for x in line if x != ""]#takes out all the extra spaces + + Ra = "".join(x+" " for x in line[0:3]).strip() #defines the Ra + Dec = "".join(x+" " for x in line[3:6]).strip() #defines the Dec + equinox = line[6] #defines the equinox + + del line[:7] #deletes the ra, dec, and equinox from the list + if line == []: del line #deletes empty lists + + try: + self.target_list.append([name,Ra,Dec,equinox,line]) #add the Ra, Dec, and equinox to the dicitonary + except: + self.target_list.append([name,Ra,Dec,equinox]) + + def send_list(self): + return self.target_list + + + + + + diff --git a/gui_config_tool/maskConfigurations.py b/gui_config_tool/maskConfigurations.py new file mode 100644 index 0000000..44eaec3 --- /dev/null +++ b/gui_config_tool/maskConfigurations.py @@ -0,0 +1,95 @@ +""" +This is a widget that will display all the masks that have been imported and if they have been saved. +A button at the bottom to save the mask, and one right next to it to save all the masks +3 buttons on the top: open, copy, close +""" + +from PyQt6.QtCore import Qt, QAbstractTableModel +from PyQt6.QtWidgets import ( + QApplication, + QMainWindow, + QVBoxLayout, + QHBoxLayout, + QWidget, + QLabel, + QPushButton, + QGroupBox, + QTableView, +) + +class Button(QPushButton): + def __init__(self,w,h,text): + super().__init__() + self.setText(text) + self.setFixedSize(w,h) + +class TableModel(QAbstractTableModel): + def __init__(self, data=[]): + super().__init__() + self._data = data + def headerData(self, section, orientation, role = ...): + if role == Qt.ItemDataRole.DisplayRole: + #should add something about whether its vertical or horizontal + if orientation == Qt.Orientation.Horizontal: + return ["Status","Name"][section] + if orientation == Qt.Orientation.Vertical: + return None + return super().headerData(section, orientation, role) + + def data(self, index, role): + if role == Qt.ItemDataRole.DisplayRole: + return self._data[index.row()][index.column()] + + def rowCount(self, index): + return len(self._data) + + def columnCount(self, index): + return len(self._data[0]) + + +#I am unsure of whether to go with a abstract table model or an abstract list model +class MaskConfigurationsWidget(QWidget): + def __init__(self): + super().__init__() + #self.setStyleSheet("border: 2px solid black;") + + temp_data = [["saved","batmask"],["unsaved","spidermask"]] + + open_button = Button(80,30,"Open") + copy_button = Button(80,30,"Copy") + close_button = Button(80,30,"Close") + + save_button = Button(120,30,"Save") + save_all_button = Button(120,30,"Save All") + + group_box = QGroupBox("MASK CONFIGURATIONS") + + table = QTableView() + model = TableModel(temp_data) + table.setModel(model) + table.setBaseSize(200,200) + + main_layout = QVBoxLayout() + group_layout = QVBoxLayout() + top_hori_layout = QHBoxLayout() + bot_hori_layout = QHBoxLayout() + + top_hori_layout.addWidget(open_button) + top_hori_layout.addWidget(copy_button) + top_hori_layout.addWidget(close_button) + + bot_hori_layout.addWidget(save_button) + bot_hori_layout.addWidget(save_all_button) + + group_layout.addLayout(top_hori_layout) + group_layout.addWidget(table) + group_layout.addLayout(bot_hori_layout) + + group_box.setLayout(group_layout) + + main_layout.addWidget(group_box) + + self.setLayout(main_layout) + + + diff --git a/gui_config_tool/menuBar.py b/gui_config_tool/menuBar.py new file mode 100644 index 0000000..e3780eb --- /dev/null +++ b/gui_config_tool/menuBar.py @@ -0,0 +1,27 @@ + + +from PyQt6.QtGui import QAction +#from inputTargets import TargetList +from PyQt6.QtWidgets import QMenuBar + +''' +menu bar will have a file option, and a help option for now +the file option will have import section and export section seperated by a line +''' + +class MenuBar(QMenuBar): + def __init__(self): + super().__init__() + import_button = QAction("&import",self) + export_button = QAction("&export",self) + help_button = QAction("&No Help",self) + + file_menu = self.addMenu("&File") + file_menu.addAction(import_button) + file_menu.addSeparator() + file_menu.addAction(export_button) + + help_menu = self.addMenu("&Help") + help_menu.addAction(help_button) + + \ No newline at end of file diff --git a/gui_config_tool/targetListWidget.py b/gui_config_tool/targetListWidget.py new file mode 100644 index 0000000..eb0ef4d --- /dev/null +++ b/gui_config_tool/targetListWidget.py @@ -0,0 +1,69 @@ + +#from inputTargets import TargetList +from menuBar import MenuBar +from PyQt6.QtCore import Qt, QAbstractTableModel, pyqtSlot +from PyQt6.QtWidgets import ( + QWidget, + QTableView, + QVBoxLayout, + QTableWidget + + +) +class TableModel(QAbstractTableModel): + def __init__(self, data=[]): + self + super().__init__() + self._data = data + def headerData(self, section, orientation, role = ...): + if role == Qt.ItemDataRole.DisplayRole: + #should add something about whether its vertical or horizontal + if orientation == Qt.Orientation.Horizontal: + return ["Name","Ra","Dec","equinox"][section] + return super().headerData(section, orientation, role) + + + def data(self, index, role): + if role == Qt.ItemDataRole.DisplayRole: + + return self._data[index.row()][index.column()] + + def rowCount(self, index): + + return len(self._data) + + def columnCount(self, index): + + return len(self._data[0]) + + +class TargetDisplayWidget(QWidget): + def __init__(self,data=[]): + super().__init__() + #self.setGeometry(600,600,100,500) + self.setFixedSize(700,200) + #self.setStyleSheet("border: 2px solid black;") + self.data = data + + self.table = QTableView() + + self.model = TableModel(self.data) + + self.table.setModel(self.model) + + layout = QVBoxLayout() + + layout.addWidget(self.table) + self.setLayout(layout) + #self.table.setModel(self.table) + @pyqtSlot(list) + def change_data(self,data): + self.data = data + self.model = TableModel(self.data) + self.table.setModel(self.model) + + + + + +