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.

Files changed (24) hide show
  1. {semapp-1.0.1 → semapp-1.0.2}/PKG-INFO +1 -1
  2. {semapp-1.0.1 → semapp-1.0.2}/SEMapp.egg-info/PKG-INFO +1 -1
  3. {semapp-1.0.1 → semapp-1.0.2}/pyproject.toml +1 -1
  4. {semapp-1.0.1 → semapp-1.0.2}/semapp/Layout/create_button.py +1 -1
  5. {semapp-1.0.1 → semapp-1.0.2}/semapp/Plot/frame_attributes.py +61 -39
  6. {semapp-1.0.1 → semapp-1.0.2}/semapp/Processing/processing.py +76 -19
  7. {semapp-1.0.1 → semapp-1.0.2}/LICENSE +0 -0
  8. {semapp-1.0.1 → semapp-1.0.2}/README.md +0 -0
  9. {semapp-1.0.1 → semapp-1.0.2}/SEMapp.egg-info/SOURCES.txt +0 -0
  10. {semapp-1.0.1 → semapp-1.0.2}/SEMapp.egg-info/dependency_links.txt +0 -0
  11. {semapp-1.0.1 → semapp-1.0.2}/SEMapp.egg-info/entry_points.txt +0 -0
  12. {semapp-1.0.1 → semapp-1.0.2}/SEMapp.egg-info/requires.txt +0 -0
  13. {semapp-1.0.1 → semapp-1.0.2}/SEMapp.egg-info/top_level.txt +0 -0
  14. {semapp-1.0.1 → semapp-1.0.2}/semapp/Layout/__init__.py +0 -0
  15. {semapp-1.0.1 → semapp-1.0.2}/semapp/Layout/main_window_att.py +0 -0
  16. {semapp-1.0.1 → semapp-1.0.2}/semapp/Layout/settings.py +0 -0
  17. {semapp-1.0.1 → semapp-1.0.2}/semapp/Layout/styles.py +0 -0
  18. {semapp-1.0.1 → semapp-1.0.2}/semapp/Plot/__init__.py +0 -0
  19. {semapp-1.0.1 → semapp-1.0.2}/semapp/Plot/styles.py +0 -0
  20. {semapp-1.0.1 → semapp-1.0.2}/semapp/Plot/utils.py +0 -0
  21. {semapp-1.0.1 → semapp-1.0.2}/semapp/Processing/__init__.py +0 -0
  22. {semapp-1.0.1 → semapp-1.0.2}/semapp/__init__.py +0 -0
  23. {semapp-1.0.1 → semapp-1.0.2}/semapp/main.py +0 -0
  24. {semapp-1.0.1 → semapp-1.0.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Semapp
3
- Version: 1.0.1
3
+ Version: 1.0.2
4
4
  Summary: Package for SEM visualization
5
5
  Author-email: Thibaut Meyer <thibaut.meyer3@gmail.com>
6
6
  License-Expression: GPL-3.0-or-later
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Semapp
3
- Version: 1.0.1
3
+ Version: 1.0.2
4
4
  Summary: Package for SEM visualization
5
5
  Author-email: Thibaut Meyer <thibaut.meyer3@gmail.com>
6
6
  License-Expression: GPL-3.0-or-later
@@ -4,7 +4,7 @@ build-backend = 'setuptools.build_meta'
4
4
 
5
5
  [project]
6
6
  name = "Semapp"
7
- version = "1.0.1"
7
+ version = "1.0.2"
8
8
  authors = [
9
9
  { name="Thibaut Meyer", email="thibaut.meyer3@gmail.com" },
10
10
  ]
@@ -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\Amel"
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
- for line in f:
118
- line = line.strip()
119
-
120
- if line.startswith("SampleSize"):
121
- match = re.search(r"SampleSize\s+1\s+(\d+)", line)
122
- if match:
123
- data["SampleSize"] = int(match.group(1))
124
-
125
- elif line.startswith("DiePitch"):
126
- match = re.search(r"DiePitch\s+([0-9.]+)\s+([0-9.]+);", line)
127
- if match:
128
- data["DiePitch"]["X"] = float(match.group(1))
129
- data["DiePitch"]["Y"] = float(match.group(2))
130
-
131
- elif line.startswith("DieOrigin"):
132
- match = re.search(r"DieOrigin\s+([0-9.]+)\s+([0-9.]+);", line)
133
- if match:
134
- data["DieOrigin"]["X"] = float(match.group(1))
135
- data["DieOrigin"]["Y"] = float(match.group(2))
136
-
137
- elif line.startswith("SampleCenterLocation"):
138
- match = re.search(r"SampleCenterLocation\s+([0-9.]+)\s+([0-9.]+);", line)
139
- if match:
140
- data["SampleCenterLocation"]["X"] = float(match.group(1))
141
- data["SampleCenterLocation"]["Y"] = float(match.group(2))
142
-
143
- elif line.startswith("DefectList"):
144
- dans_defect_list = True
145
- continue
146
-
147
- elif dans_defect_list:
148
- if re.match(r"^\d+\s", line):
149
- value = line.split()
150
- if len(value) >= 18:
151
- defect = {f"val{i+1}": float(val) for i, val in enumerate(value[:18])}
152
- data["Defects"].append(defect)
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
- ax.scatter(x_coords, y_coords, color='blue', marker='o',
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
- new_filename += "_BSE.tif"
474
- elif "_Class_1_Topography" in file:
475
- topo_number = file.split("_Class_1_Topography")[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
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\RAW"
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
- # processor.rename_wo_legend_all() # Preprocess all files in the directory
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