Semapp 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of Semapp might be problematic. Click here for more details.

@@ -0,0 +1,170 @@
1
+ """Module for settings window"""
2
+ # pylint: disable=no-name-in-module, trailing-whitespace, too-many-branches, too-many-statements
3
+ import os
4
+ import json
5
+ from PyQt5.QtWidgets import (
6
+ QDialog, QVBoxLayout, QTableWidget, QPushButton,
7
+ QTableWidgetItem
8
+ )
9
+ from PyQt5.QtCore import pyqtSignal
10
+
11
+ class SettingsWindow(QDialog):
12
+ """Class for settings window"""
13
+ data_updated = pyqtSignal() # Signal emitted when data is updated
14
+
15
+ def __init__(self):
16
+ super().__init__()
17
+ self.setWindowTitle("Settings")
18
+
19
+ # Get the user's folder path (C:\Users\XXXXX)
20
+ self.user_folder = os.path.expanduser("~")
21
+
22
+ # Define the new folder "SEM" and the file to store settings
23
+ self.new_folder = os.path.join(self.user_folder, "SEM")
24
+ self.data_file = os.path.join(self.new_folder, "settings_data.json")
25
+ self.data = [] # Structure to store the table data
26
+
27
+ # Set up the UI layout
28
+ self.layout = QVBoxLayout()
29
+ self.setLayout(self.layout)
30
+
31
+ # Create and add the table and buttons to the layout
32
+ self.create_table()
33
+ self.create_buttons()
34
+
35
+ # Load data from the settings file
36
+ self.load_data()
37
+
38
+ def create_table(self):
39
+ """Create the settings table."""
40
+ self.table = QTableWidget()
41
+ self.table.setColumnCount(2)
42
+ self.table.setHorizontalHeaderLabels(["Scale", "Image Type"])
43
+
44
+ # Temporarily block signals to prevent updates during initialization
45
+ self.table.blockSignals(True)
46
+
47
+ # Populate the table with existing data
48
+ for row_data in self.data:
49
+ if "Scale" in row_data and "Image Type" in row_data:
50
+ self.add_row(row_data["Scale"], row_data["Image Type"], update_data=False)
51
+ else:
52
+ print(f"Invalid row data: {row_data}")
53
+
54
+ # Re-enable signals after table population
55
+ self.table.blockSignals(False)
56
+
57
+ # Connect the itemChanged signal to update the data structure
58
+ self.table.itemChanged.connect(self.update_data)
59
+ self.layout.addWidget(self.table)
60
+
61
+ def create_buttons(self):
62
+ """Create buttons to add and remove rows."""
63
+ add_button = QPushButton("Add Row")
64
+ remove_button = QPushButton("Remove Selected Row")
65
+
66
+ add_button.clicked.connect(self.add_row)
67
+ remove_button.clicked.connect(self.remove_selected_row)
68
+
69
+ self.layout.addWidget(add_button)
70
+ self.layout.addWidget(remove_button)
71
+
72
+ def add_row(self, scale="5x5", image_type="Type", update_data=True):
73
+ """Add a new row to the table with default values."""
74
+ row_position = self.table.rowCount()
75
+ self.table.insertRow(row_position)
76
+
77
+ scale_item = QTableWidgetItem(scale)
78
+ image_type_item = QTableWidgetItem(image_type)
79
+
80
+ self.table.setItem(row_position, 0, scale_item)
81
+ self.table.setItem(row_position, 1, image_type_item)
82
+
83
+ if update_data:
84
+ self.data.append({"Scale": scale, "Image Type": image_type})
85
+ print("Row added:", self.data)
86
+
87
+ def remove_selected_row(self):
88
+ """Remove the currently selected row from the table."""
89
+ current_row = self.table.currentRow()
90
+ if current_row != -1:
91
+ self.table.removeRow(current_row)
92
+ del self.data[current_row]
93
+ print("Row removed:", self.data)
94
+
95
+ def update_data(self, item):
96
+ """Update the data structure when a cell value changes."""
97
+ try:
98
+ row = item.row()
99
+ column = item.column()
100
+ value = item.text().strip()
101
+
102
+ while len(self.data) <= row:
103
+ self.data.append({"Scale": "", "Image Type": ""})
104
+
105
+ if column == 0: # Update "Scale"
106
+ if not value.replace('.', '', 1).isdigit():
107
+ print(f"Invalid value for Scale: {value}")
108
+ return
109
+ self.data[row]["Scale"] = value
110
+ elif column == 1: # Update "Image Type"
111
+ self.data[row]["Image Type"] = value
112
+ else:
113
+ print(f"Unexpected column index: {column}")
114
+ return
115
+
116
+ self.save_data()
117
+ print(f"Data updated successfully: {self.data[row]}")
118
+ except Exception as e:
119
+ print(f"Error updating data: {e}")
120
+
121
+ def closeEvent(self, event):
122
+ """Save data to a file when the dialog is closed."""
123
+ self.save_data()
124
+ self.data_updated.emit()
125
+ super().closeEvent(event)
126
+
127
+ def normalize_data(self):
128
+ """Synchronize self.data with the actual table contents."""
129
+ self.data = self.get_table_data()
130
+
131
+ def save_data(self):
132
+ """Save the table data to a JSON file."""
133
+ self.normalize_data()
134
+ with open(self.data_file, "w") as file:
135
+ json.dump(self.data, file, indent=4)
136
+ print("Data saved successfully.")
137
+
138
+ def load_data(self):
139
+ """Load the table data from the JSON file."""
140
+ try:
141
+ with open(self.data_file, "r") as file:
142
+ self.data = json.load(file)
143
+ print("Data loaded successfully:", self.data)
144
+ except FileNotFoundError:
145
+ print("No previous data found. Starting fresh.")
146
+ self.data = []
147
+ except Exception as err:
148
+ print(f"Error loading data: {err}")
149
+ self.data = []
150
+
151
+ self.table.blockSignals(True)
152
+ self.table.setRowCount(0)
153
+ for row_data in self.data:
154
+ self.add_row(row_data.get("Scale", ""),
155
+ row_data.get("Image Type", ""), update_data=False)
156
+ self.table.blockSignals(False)
157
+
158
+ def get_table_data(self):
159
+ """Get the current data from the table as a list of dictionaries."""
160
+ table_data = []
161
+ for row in range(self.table.rowCount()):
162
+ scale_item = self.table.item(row, 0)
163
+ image_type_item = self.table.item(row, 1)
164
+
165
+ if scale_item and image_type_item:
166
+ scale = scale_item.text()
167
+ image_type = image_type_item.text()
168
+ table_data.append({"Scale": scale, "Image Type": image_type})
169
+
170
+ return table_data
@@ -0,0 +1,152 @@
1
+ """Module containing all styles for the GUI"""
2
+
3
+ # Radio button styles
4
+ RADIO_BUTTON_STYLE = """
5
+ QRadioButton {
6
+ spacing: 0px;
7
+ font-size: 14px;
8
+ }
9
+ QRadioButton::indicator {
10
+ width: 20px;
11
+ height: 20px;
12
+ }
13
+ QRadioButton::indicator:checked {
14
+ background-color: #f0ca41;
15
+ border: 2px solid black;
16
+ }
17
+ QRadioButton::indicator:unchecked {
18
+ background-color: white;
19
+ border: 2px solid #ccc;
20
+ }
21
+ """
22
+
23
+ # Settings button style
24
+ SETTINGS_BUTTON_STYLE = """
25
+ QPushButton {
26
+ font-size: 16px;
27
+ background-color: #b3e5fc;
28
+ border: 2px solid #8c8c8c;
29
+ border-radius: 10px;
30
+ padding: 5px;
31
+ height: 100px;
32
+ }
33
+ QPushButton:hover {
34
+ background-color: #64b5f6;
35
+ }
36
+ """
37
+
38
+ # Run button style
39
+ RUN_BUTTON_STYLE = """
40
+ QPushButton {
41
+ font-size: 16px;
42
+ background-color: #ffcc80;
43
+ border: 2px solid #8c8c8c;
44
+ border-radius: 10px;
45
+ padding: 5px;
46
+ height: 100px;
47
+ }
48
+ QPushButton:hover {
49
+ background-color: #ffb74d;
50
+ }
51
+ """
52
+
53
+ # Group box style
54
+ GROUP_BOX_STYLE = """
55
+ QGroupBox {
56
+ border: 1px solid black;
57
+ border-radius: 5px;
58
+ margin-top: 10px;
59
+ font-size: 20px;
60
+ font-weight: bold;
61
+ }
62
+ QGroupBox::title {
63
+ font-size: 14px;
64
+ font-weight: bold;
65
+ subcontrol-origin: margin;
66
+ subcontrol-position: top center;
67
+ }
68
+ """
69
+
70
+ # Wafer button styles
71
+ WAFER_BUTTON_DEFAULT_STYLE = """
72
+ QRadioButton {
73
+ spacing: 0px;
74
+ font-size: 16px;
75
+ }
76
+ QRadioButton::indicator {
77
+ width: 25px;
78
+ height: 25px;
79
+ }
80
+ QRadioButton::indicator:checked {
81
+ background-color: #ccffcc;
82
+ border: 2px solid black;
83
+ }
84
+ QRadioButton::indicator:unchecked {
85
+ background-color: white;
86
+ border: 2px solid #ccc;
87
+ }
88
+ """
89
+
90
+ WAFER_BUTTON_EXISTING_STYLE = """
91
+ QRadioButton {
92
+ spacing: 0px;
93
+ font-size: 16px;
94
+ }
95
+ QRadioButton::indicator {
96
+ width: 25px;
97
+ height: 25px;
98
+ border: 2px solid #ccc;
99
+ background-color: lightblue;
100
+ }
101
+ QRadioButton::indicator:checked {
102
+ background-color: #ccffcc;
103
+ border: 2px solid black;
104
+ }
105
+ QRadioButton::indicator:unchecked {
106
+ background-color: lightblue;
107
+ border: 2px solid #ccc;
108
+ }
109
+ """
110
+
111
+ WAFER_BUTTON_MISSING_STYLE = """
112
+ QRadioButton {
113
+ spacing: 0px;
114
+ font-size: 16px;
115
+ }
116
+ QRadioButton::indicator {
117
+ width: 25px;
118
+ height: 25px;
119
+ border: 2px solid #ccc;
120
+ background-color: lightcoral;
121
+ }
122
+ QRadioButton::indicator:checked {
123
+ background-color: #ccffcc;
124
+ border: 2px solid black;
125
+ }
126
+ QRadioButton::indicator:unchecked {
127
+ background-color: lightcoral;
128
+ border: 2px solid #ccc;
129
+ }
130
+ """
131
+
132
+ # Style pour les boutons de sélection de dossier/fichier
133
+ SELECT_BUTTON_STYLE = """
134
+ QPushButton {
135
+ font-size: 16px;
136
+ background-color: #b3e5fc;
137
+ border: 2px solid #8c8c8c;
138
+ border-radius: 10px;
139
+ padding: 10px;
140
+ }
141
+ QPushButton:hover {
142
+ background-color: #64b5f6;
143
+ }
144
+ """
145
+
146
+ # Style pour les labels de chemin
147
+ PATH_LABEL_STYLE = """
148
+ QLabel {
149
+ font-size: 14px;
150
+ padding: 5px;
151
+ }
152
+ """
@@ -0,0 +1,8 @@
1
+ """
2
+ Plot package initialization.
3
+ Contains SEM image processing functionality.
4
+ """
5
+
6
+ from .utils import*
7
+
8
+ __all__ = ['Process']