Semapp 1.0.1__tar.gz → 1.0.2__tar.gz
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.
- {semapp-1.0.1 → semapp-1.0.2}/PKG-INFO +1 -1
- {semapp-1.0.1 → semapp-1.0.2}/SEMapp.egg-info/PKG-INFO +1 -1
- {semapp-1.0.1 → semapp-1.0.2}/pyproject.toml +1 -1
- {semapp-1.0.1 → semapp-1.0.2}/semapp/Layout/create_button.py +1 -1
- {semapp-1.0.1 → semapp-1.0.2}/semapp/Plot/frame_attributes.py +61 -39
- {semapp-1.0.1 → semapp-1.0.2}/semapp/Processing/processing.py +76 -19
- {semapp-1.0.1 → semapp-1.0.2}/LICENSE +0 -0
- {semapp-1.0.1 → semapp-1.0.2}/README.md +0 -0
- {semapp-1.0.1 → semapp-1.0.2}/SEMapp.egg-info/SOURCES.txt +0 -0
- {semapp-1.0.1 → semapp-1.0.2}/SEMapp.egg-info/dependency_links.txt +0 -0
- {semapp-1.0.1 → semapp-1.0.2}/SEMapp.egg-info/entry_points.txt +0 -0
- {semapp-1.0.1 → semapp-1.0.2}/SEMapp.egg-info/requires.txt +0 -0
- {semapp-1.0.1 → semapp-1.0.2}/SEMapp.egg-info/top_level.txt +0 -0
- {semapp-1.0.1 → semapp-1.0.2}/semapp/Layout/__init__.py +0 -0
- {semapp-1.0.1 → semapp-1.0.2}/semapp/Layout/main_window_att.py +0 -0
- {semapp-1.0.1 → semapp-1.0.2}/semapp/Layout/settings.py +0 -0
- {semapp-1.0.1 → semapp-1.0.2}/semapp/Layout/styles.py +0 -0
- {semapp-1.0.1 → semapp-1.0.2}/semapp/Plot/__init__.py +0 -0
- {semapp-1.0.1 → semapp-1.0.2}/semapp/Plot/styles.py +0 -0
- {semapp-1.0.1 → semapp-1.0.2}/semapp/Plot/utils.py +0 -0
- {semapp-1.0.1 → semapp-1.0.2}/semapp/Processing/__init__.py +0 -0
- {semapp-1.0.1 → semapp-1.0.2}/semapp/__init__.py +0 -0
- {semapp-1.0.1 → semapp-1.0.2}/semapp/main.py +0 -0
- {semapp-1.0.1 → semapp-1.0.2}/setup.cfg +0 -0
|
@@ -63,7 +63,7 @@ class ButtonFrame(QWidget):
|
|
|
63
63
|
# Example of adding them to a layout
|
|
64
64
|
self.entries = {}
|
|
65
65
|
self.dirname = None
|
|
66
|
-
# self.dirname = r"C:\Users\TM273821\Desktop\SEM\
|
|
66
|
+
# self.dirname = r"C:\Users\TM273821\Desktop\SEM\TEst_complus"
|
|
67
67
|
|
|
68
68
|
|
|
69
69
|
max_characters = 30 # Set character limit
|
|
@@ -114,42 +114,49 @@ class PlotFrame(QWidget):
|
|
|
114
114
|
dans_defect_list = False
|
|
115
115
|
|
|
116
116
|
with open(filepath, "r", encoding="utf-8") as f:
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
117
|
+
lines = f.readlines()
|
|
118
|
+
|
|
119
|
+
for i, line in enumerate(lines):
|
|
120
|
+
line = line.strip()
|
|
121
|
+
|
|
122
|
+
if line.startswith("SampleSize"):
|
|
123
|
+
match = re.search(r"SampleSize\s+1\s+(\d+)", line)
|
|
124
|
+
if match:
|
|
125
|
+
data["SampleSize"] = int(match.group(1))
|
|
126
|
+
|
|
127
|
+
elif line.startswith("DiePitch"):
|
|
128
|
+
match = re.search(r"DiePitch\s+([0-9.e+-]+)\s+([0-9.e+-]+);", line)
|
|
129
|
+
if match:
|
|
130
|
+
data["DiePitch"]["X"] = float(match.group(1))
|
|
131
|
+
data["DiePitch"]["Y"] = float(match.group(2))
|
|
132
|
+
|
|
133
|
+
elif line.startswith("DieOrigin"):
|
|
134
|
+
match = re.search(r"DieOrigin\s+([0-9.e+-]+)\s+([0-9.e+-]+);", line)
|
|
135
|
+
if match:
|
|
136
|
+
data["DieOrigin"]["X"] = float(match.group(1))
|
|
137
|
+
data["DieOrigin"]["Y"] = float(match.group(2))
|
|
138
|
+
|
|
139
|
+
elif line.startswith("SampleCenterLocation"):
|
|
140
|
+
match = re.search(r"SampleCenterLocation\s+([0-9.e+-]+)\s+([0-9.e+-]+);", line)
|
|
141
|
+
if match:
|
|
142
|
+
data["SampleCenterLocation"]["X"] = float(match.group(1))
|
|
143
|
+
data["SampleCenterLocation"]["Y"] = float(match.group(2))
|
|
144
|
+
|
|
145
|
+
elif line.startswith("DefectList"):
|
|
146
|
+
dans_defect_list = True
|
|
147
|
+
continue
|
|
148
|
+
|
|
149
|
+
elif dans_defect_list:
|
|
150
|
+
if re.match(r"^\d+\s", line):
|
|
151
|
+
value = line.split()
|
|
152
|
+
if len(value) >= 12:
|
|
153
|
+
# Vérifier si la ligne suivante a exactement 2 colonnes
|
|
154
|
+
if i + 1 < len(lines):
|
|
155
|
+
next_line = lines[i + 1].strip()
|
|
156
|
+
next_values = next_line.split()
|
|
157
|
+
if len(next_values) == 2:
|
|
158
|
+
defect = {f"val{i+1}": float(val) for i, val in enumerate(value[:10])}
|
|
159
|
+
data["Defects"].append(defect)
|
|
153
160
|
|
|
154
161
|
pitch_x = data["DiePitch"]["X"]
|
|
155
162
|
pitch_y = data["DiePitch"]["Y"]
|
|
@@ -164,6 +171,7 @@ class PlotFrame(QWidget):
|
|
|
164
171
|
val3 = d["val3"]
|
|
165
172
|
val4_scaled = d["val4"] * pitch_x - Xcenter
|
|
166
173
|
val5_scaled = d["val5"] * pitch_y - Ycenter
|
|
174
|
+
defect_size = d["val9"]
|
|
167
175
|
|
|
168
176
|
x_corr = round((val2 + val4_scaled) / 10000, 1)
|
|
169
177
|
y_corr = round((val3 + val5_scaled) / 10000, 1)
|
|
@@ -171,11 +179,20 @@ class PlotFrame(QWidget):
|
|
|
171
179
|
corrected_positions.append({
|
|
172
180
|
"defect_id": val1,
|
|
173
181
|
"X": x_corr,
|
|
174
|
-
"Y": y_corr
|
|
182
|
+
"Y": y_corr,
|
|
183
|
+
"defect_size": defect_size
|
|
184
|
+
|
|
175
185
|
})
|
|
176
186
|
|
|
177
187
|
|
|
178
|
-
self.coordinates = pd.DataFrame(corrected_positions, columns=["X", "Y"])
|
|
188
|
+
self.coordinates = pd.DataFrame(corrected_positions, columns=["X", "Y", "defect_size"])
|
|
189
|
+
|
|
190
|
+
# Enregistrer le mapping en CSV dans le même dossier que filepath
|
|
191
|
+
import os
|
|
192
|
+
file_dir = os.path.dirname(filepath)
|
|
193
|
+
csv_path = os.path.join(file_dir, "mapping.csv")
|
|
194
|
+
self.coordinates.to_csv(csv_path, index=False)
|
|
195
|
+
print(f"Mapping saved to: {csv_path}")
|
|
179
196
|
|
|
180
197
|
return self.coordinates
|
|
181
198
|
|
|
@@ -302,6 +319,8 @@ class PlotFrame(QWidget):
|
|
|
302
319
|
if self.coordinates is not None:
|
|
303
320
|
x_coords = self.coordinates.iloc[:, 0]
|
|
304
321
|
y_coords = self.coordinates.iloc[:, 1]
|
|
322
|
+
defect_size = self.coordinates.iloc[:, 2]
|
|
323
|
+
print(f"defect_size: {defect_size}")
|
|
305
324
|
|
|
306
325
|
# Calculate the maximum value for scaling
|
|
307
326
|
max_val = max(abs(x_coords).max(), abs(y_coords).max())
|
|
@@ -319,7 +338,10 @@ class PlotFrame(QWidget):
|
|
|
319
338
|
|
|
320
339
|
self.radius = radius
|
|
321
340
|
|
|
322
|
-
|
|
341
|
+
# Create color array based on defect_size (values are in scientific notation)
|
|
342
|
+
colors = ['red' if size > 1.0e+01 else 'blue' for size in defect_size]
|
|
343
|
+
|
|
344
|
+
ax.scatter(x_coords, y_coords, color=colors, marker='o',
|
|
323
345
|
s=100, label='Positions')
|
|
324
346
|
|
|
325
347
|
# Set limits based on the radius
|
|
@@ -113,13 +113,13 @@ class Process:
|
|
|
113
113
|
val3 = d["val3"]
|
|
114
114
|
val4_scaled = d["val4"] * pitch_x - x_center
|
|
115
115
|
val5_scaled = d["val5"] * pitch_y - y_center
|
|
116
|
-
|
|
116
|
+
defect_size = d["val8"]
|
|
117
117
|
x_corr = round((val2 + val4_scaled) / 10000, 1)
|
|
118
118
|
y_corr = round((val3 + val5_scaled) / 10000, 1)
|
|
119
119
|
|
|
120
|
-
corrected_positions.append({"defect_id": val1, "X": x_corr,"Y": y_corr})
|
|
120
|
+
corrected_positions.append({"defect_id": val1, "X": x_corr,"Y": y_corr, "defect_size": defect_size})
|
|
121
121
|
|
|
122
|
-
self.coordinates = pd.DataFrame(corrected_positions, columns=["X", "Y"])
|
|
122
|
+
self.coordinates = pd.DataFrame(corrected_positions, columns=["X", "Y", "defect_size"])
|
|
123
123
|
|
|
124
124
|
return self.coordinates
|
|
125
125
|
def rename(self):
|
|
@@ -466,19 +466,19 @@ class Process:
|
|
|
466
466
|
|
|
467
467
|
x = self.coordinates.iloc[defect_part, 0]
|
|
468
468
|
y = self.coordinates.iloc[defect_part, 1]
|
|
469
|
-
new_filename = f"{x}_{y}"
|
|
470
|
-
|
|
471
|
-
# Add specific suffix based on the file type
|
|
472
|
-
if "_Class_1_Internal" in file:
|
|
473
|
-
|
|
474
|
-
elif "_Class_1_Topography" in file:
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
else:
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
469
|
+
new_filename = f"{x}_{y}.tiff"
|
|
470
|
+
|
|
471
|
+
# # Add specific suffix based on the file type
|
|
472
|
+
# if "_Class_1_Internal" in file:
|
|
473
|
+
# new_filename += "_BSE.tif"
|
|
474
|
+
# elif "_Class_1_Topography" in file:
|
|
475
|
+
# topo_number = file.split("_Class_1_merged")[1][
|
|
476
|
+
# 0] # Extract Topography number
|
|
477
|
+
# new_filename += f"_SE{topo_number}.tiff"
|
|
478
|
+
# else:
|
|
479
|
+
# print(
|
|
480
|
+
# f"Skipping file due to unexpected format: {file}")
|
|
481
|
+
# continue
|
|
482
482
|
|
|
483
483
|
# Construct the new file path and rename
|
|
484
484
|
new_filepath = os.path.join(subdir, new_filename)
|
|
@@ -578,21 +578,78 @@ class Process:
|
|
|
578
578
|
os.remove(file_path)
|
|
579
579
|
print(f"Deleted: {file_path}")
|
|
580
580
|
|
|
581
|
+
|
|
582
|
+
def ajouter_extension_tiff(self):
|
|
583
|
+
"""
|
|
584
|
+
Ajoute l'extension .tiff à tous les fichiers du dossier parent et ses sous-dossiers,
|
|
585
|
+
SAUF ceux qui se terminent par .001.
|
|
586
|
+
Utilise os.walk pour parcourir tous les sous-dossiers.
|
|
587
|
+
"""
|
|
588
|
+
fichiers_renommes = 0
|
|
589
|
+
|
|
590
|
+
print(f"Scan du dossier parent: {self.dirname}")
|
|
591
|
+
|
|
592
|
+
# Parcourir tous les sous-dossiers avec os.walk
|
|
593
|
+
for root, dirs, files in os.walk(self.dirname):
|
|
594
|
+
print(f"\nTraitement du dossier: {root}")
|
|
595
|
+
|
|
596
|
+
for file in files:
|
|
597
|
+
# Ignorer les fichiers qui se terminent par .001
|
|
598
|
+
if file.endswith('.001'):
|
|
599
|
+
print(f"Fichier ignoré (extension .001): {file}")
|
|
600
|
+
continue
|
|
601
|
+
|
|
602
|
+
# Vérifier si le fichier n'a pas d'extension ou a une extension différente de .tiff
|
|
603
|
+
if '.' not in file or not file.endswith('.tiff'):
|
|
604
|
+
old_filepath = os.path.join(root, file)
|
|
605
|
+
|
|
606
|
+
# Si le fichier n'a pas d'extension, ajouter .tiff
|
|
607
|
+
if '.' not in file:
|
|
608
|
+
new_filename = file + '.tiff'
|
|
609
|
+
else:
|
|
610
|
+
# Si le fichier a une extension différente, remplacer par .tiff
|
|
611
|
+
base_name = file.rsplit('.', 1)[0] # Prendre tout sauf la dernière extension
|
|
612
|
+
new_filename = base_name + '.tiff'
|
|
613
|
+
|
|
614
|
+
new_filepath = os.path.join(root, new_filename)
|
|
615
|
+
|
|
616
|
+
# Vérifier que le nouveau nom n'existe pas déjà
|
|
617
|
+
if not os.path.exists(new_filepath):
|
|
618
|
+
try:
|
|
619
|
+
os.rename(old_filepath, new_filepath)
|
|
620
|
+
print(f"Extension ajoutée: '{file}' -> '{new_filename}'")
|
|
621
|
+
fichiers_renommes += 1
|
|
622
|
+
except Exception as e:
|
|
623
|
+
print(f"Erreur lors du renommage de '{file}': {e}")
|
|
624
|
+
else:
|
|
625
|
+
print(f"Erreur: Le fichier '{new_filename}' existe déjà, impossible de renommer '{file}'")
|
|
626
|
+
|
|
627
|
+
print(f"\n{'='*50}")
|
|
628
|
+
print(f"RÉSUMÉ DE L'AJOUT D'EXTENSIONS")
|
|
629
|
+
print(f"{'='*50}")
|
|
630
|
+
print(f"Fichiers renommés: {fichiers_renommes}")
|
|
631
|
+
|
|
632
|
+
return fichiers_renommes
|
|
633
|
+
|
|
634
|
+
|
|
581
635
|
if __name__ == "__main__":
|
|
582
|
-
DIRNAME = r"C:\Users\TM273821\Desktop\SEM\
|
|
636
|
+
DIRNAME = r"C:\Users\TM273821\Desktop\SEM\lD25S1556"
|
|
583
637
|
SCALE = r"C:\Users\TM273821\SEM\settings_data.json"
|
|
584
638
|
|
|
585
639
|
processor = Process(DIRNAME, wafer=18, scale=SCALE)
|
|
586
640
|
|
|
587
641
|
# Process files
|
|
588
642
|
# processor.organize_and_rename_files() # Organize and rename files
|
|
589
|
-
|
|
643
|
+
processor.rename_wo_legend_all() # Preprocess all files in the directory
|
|
590
644
|
# processor.clean_folders_and_files()
|
|
591
|
-
processor.rename_wo_legend() # Preprocess specific wafer
|
|
645
|
+
# processor.rename_wo_legend() # Preprocess specific wafer
|
|
592
646
|
|
|
593
647
|
# processor.split_tiff_all() # Preprocess specific wafer
|
|
594
648
|
# processor.split_tiff_all() # Preprocess specific wafer
|
|
595
649
|
# processor.split_tiff() # Preprocess specific wafer
|
|
596
650
|
# processor.rename_all() # Preprocess specific wafer
|
|
597
651
|
|
|
652
|
+
# Ajouter l'extension .tiff aux fichiers qui n'en ont pas
|
|
653
|
+
processor.ajouter_extension_tiff()
|
|
654
|
+
|
|
598
655
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|