Semapp 1.0.5__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.
@@ -0,0 +1,498 @@
1
+ """
2
+ Module for renaming TIFF files based on coordinates from KLARF files.
3
+ Supports KRONOS, COMPLUS4T, and normal modes.
4
+ """
5
+
6
+ import os
7
+
8
+ # Try to import QApplication for processEvents (optional, won't break if not available)
9
+ try:
10
+ from PyQt5.QtWidgets import QApplication
11
+ HAS_QT = True
12
+ except ImportError:
13
+ HAS_QT = False
14
+
15
+
16
+ def rename_files(output_dir, coordinates, settings, is_kronos=False, is_complus4t=False):
17
+ """
18
+ Rename TIFF files based on coordinates.
19
+ Main function that detects the mode and calls the appropriate renamer.
20
+
21
+ Args:
22
+ output_dir: Directory containing the TIFF files to rename
23
+ coordinates: DataFrame with columns ["defect_id", "X", "Y", "defect_size"]
24
+ settings: List of settings dictionaries (for normal mode)
25
+ is_kronos: Boolean indicating if this is KRONOS mode
26
+ is_complus4t: Boolean indicating if this is COMPLUS4T mode
27
+
28
+ Returns:
29
+ int: Number of files renamed
30
+ """
31
+ if is_kronos:
32
+ return _rename_kronos(output_dir, coordinates)
33
+ elif is_complus4t:
34
+ return _rename_complus4t(output_dir, coordinates)
35
+ else:
36
+ return _rename_normal(output_dir, coordinates, settings)
37
+
38
+
39
+ def rename_files_all(dirname, coordinates_dict, settings, is_kronos=False, is_complus4t=False):
40
+ """
41
+ Rename all TIFF files in all subdirectories based on coordinates.
42
+ Main function that detects the mode and calls the appropriate renamer.
43
+
44
+ Args:
45
+ dirname: Base directory containing subdirectories
46
+ coordinates_dict: Dictionary mapping wafer_num to coordinates DataFrame
47
+ settings: List of settings dictionaries (for normal mode)
48
+ is_kronos: Boolean indicating if this is KRONOS mode
49
+ is_complus4t: Boolean indicating if this is COMPLUS4T mode
50
+
51
+ Returns:
52
+ int: Total number of files renamed across all directories
53
+ """
54
+ if is_kronos:
55
+ return _rename_all_kronos(dirname, coordinates_dict)
56
+ elif is_complus4t:
57
+ return _rename_all_complus4t(dirname, coordinates_dict)
58
+ else:
59
+ return _rename_all_normal(dirname, coordinates_dict, settings)
60
+
61
+
62
+ def _rename_kronos(output_dir, coordinates):
63
+ """
64
+ Rename TIFF files for KRONOS mode.
65
+
66
+ Args:
67
+ output_dir: Directory containing the TIFF files to rename
68
+ coordinates: DataFrame with columns ["defect_id", "X", "Y", "defect_size"]
69
+
70
+ Returns:
71
+ int: Number of files renamed
72
+ """
73
+ if not os.path.exists(output_dir):
74
+ print(f"[DEBUG] output_dir does not exist: {output_dir}")
75
+ return 0
76
+
77
+ tiff_files = [f for f in os.listdir(output_dir)
78
+ if "page" in f and f.lower().endswith(('.tiff', '.tif'))]
79
+ tiff_files.sort()
80
+
81
+ print(f"[DEBUG] KRONOS: Found {len(tiff_files)} TIFF files in output_dir")
82
+
83
+ has_qt = HAS_QT
84
+
85
+ renamed_count = 0
86
+ for idx, file in enumerate(tiff_files):
87
+ if has_qt and idx % 10 == 0:
88
+ QApplication.processEvents()
89
+
90
+ try:
91
+ file_number = int(file.split('_')[2].split('.')[0])
92
+ except (ValueError, IndexError) as e:
93
+ print(f"[DEBUG] Error extracting file_number from {file}: {e}")
94
+ continue
95
+
96
+ # KRONOS: file_number directly corresponds to the row index (0-based)
97
+ csv_row_index = file_number - 1
98
+
99
+ if csv_row_index >= len(coordinates):
100
+ print(f"[DEBUG] Warning: csv_row_index {csv_row_index} is out of bounds. Total defects: {len(coordinates)}")
101
+ continue
102
+
103
+ x = coordinates.iloc[csv_row_index, 1] # Column 1 is X
104
+ y = coordinates.iloc[csv_row_index, 2] # Column 2 is Y
105
+ new_name = f"{x}_{y}.tif"
106
+
107
+ old_path = os.path.join(output_dir, file)
108
+ new_path = os.path.join(output_dir, new_name)
109
+
110
+ # Handle file name collisions
111
+ if os.path.exists(new_path):
112
+ base_name = new_name.rsplit('.', 1)[0]
113
+ extension = new_name.rsplit('.', 1)[1] if '.' in new_name else 'tif'
114
+ counter = 1
115
+ while os.path.exists(new_path):
116
+ new_name = f"{base_name}_{counter}.{extension}"
117
+ new_path = os.path.join(output_dir, new_name)
118
+ counter += 1
119
+
120
+ try:
121
+ os.rename(old_path, new_path)
122
+ renamed_count += 1
123
+ except Exception as e:
124
+ print(f"[DEBUG] Error renaming {file}: {e}")
125
+
126
+ return renamed_count
127
+
128
+
129
+ def _rename_complus4t(output_dir, coordinates):
130
+ """
131
+ Rename TIFF files for COMPLUS4T mode.
132
+
133
+ Args:
134
+ output_dir: Directory containing the TIFF files to rename
135
+ coordinates: DataFrame with columns ["defect_id", "X", "Y", "defect_size"]
136
+
137
+ Returns:
138
+ int: Number of files renamed
139
+ """
140
+ if not os.path.exists(output_dir):
141
+ print(f"[DEBUG] output_dir does not exist: {output_dir}")
142
+ return 0
143
+
144
+ tiff_files = [f for f in os.listdir(output_dir)
145
+ if "page" in f and f.lower().endswith(('.tiff', '.tif'))]
146
+ tiff_files.sort()
147
+
148
+ print(f"[DEBUG] COMPLUS4T: Found {len(tiff_files)} TIFF files in output_dir")
149
+
150
+ has_qt = HAS_QT
151
+
152
+ renamed_count = 0
153
+ for idx, file in enumerate(tiff_files):
154
+ if has_qt and idx % 10 == 0:
155
+ QApplication.processEvents()
156
+
157
+ try:
158
+ file_number = int(file.split('_')[2].split('.')[0])
159
+ except (ValueError, IndexError) as e:
160
+ print(f"[DEBUG] Error extracting file_number from {file}: {e}")
161
+ continue
162
+
163
+ # COMPLUS4T: file_number is the defect_id
164
+ matching_rows = coordinates[coordinates['defect_id'] == file_number]
165
+
166
+ if matching_rows.empty:
167
+ print(f"[DEBUG] Warning: defect_id {file_number} not found in coordinates")
168
+ continue
169
+
170
+ row = matching_rows.iloc[0]
171
+ x = row['X']
172
+ y = row['Y']
173
+ new_name = f"{x}_{y}.tif"
174
+
175
+ old_path = os.path.join(output_dir, file)
176
+ new_path = os.path.join(output_dir, new_name)
177
+
178
+ # Handle file name collisions
179
+ if os.path.exists(new_path):
180
+ base_name = new_name.rsplit('.', 1)[0]
181
+ extension = new_name.rsplit('.', 1)[1] if '.' in new_name else 'tif'
182
+ counter = 1
183
+ while os.path.exists(new_path):
184
+ new_name = f"{base_name}_{counter}.{extension}"
185
+ new_path = os.path.join(output_dir, new_name)
186
+ counter += 1
187
+
188
+ try:
189
+ os.rename(old_path, new_path)
190
+ renamed_count += 1
191
+ except Exception as e:
192
+ print(f"[DEBUG] Error renaming {file}: {e}")
193
+
194
+ return renamed_count
195
+
196
+
197
+ def _rename_normal(output_dir, coordinates, settings):
198
+ """
199
+ Rename TIFF files for normal mode.
200
+
201
+ Args:
202
+ output_dir: Directory containing the TIFF files to rename
203
+ coordinates: DataFrame with columns ["defect_id", "X", "Y", "defect_size"]
204
+ settings: List of settings dictionaries
205
+
206
+ Returns:
207
+ int: Number of files renamed
208
+ """
209
+ if not os.path.exists(output_dir):
210
+ print(f"[DEBUG] output_dir does not exist: {output_dir}")
211
+ return 0
212
+
213
+ tiff_files = [f for f in os.listdir(output_dir)
214
+ if "page" in f and f.lower().endswith(('.tiff', '.tif'))]
215
+ tiff_files.sort()
216
+
217
+ print(f"[DEBUG] Normal: Found {len(tiff_files)} TIFF files in output_dir")
218
+
219
+ has_qt = HAS_QT
220
+
221
+ renamed_count = 0
222
+ for idx, file in enumerate(tiff_files):
223
+ if has_qt and idx % 10 == 0:
224
+ QApplication.processEvents()
225
+
226
+ try:
227
+ file_number = int(file.split('_')[2].split('.')[0])
228
+ except (ValueError, IndexError) as e:
229
+ print(f"[DEBUG] Error extracting file_number from {file}: {e}")
230
+ continue
231
+
232
+ # Normal mode: calculate row using settings
233
+ csv_row_index = (file_number - 1) // len(settings)
234
+ remainder = (file_number - 1) % len(settings)
235
+
236
+ if csv_row_index >= len(coordinates):
237
+ print(f"[DEBUG] Warning: csv_row_index {csv_row_index} is out of bounds. Total defects: {len(coordinates)}")
238
+ continue
239
+
240
+ x = coordinates.iloc[csv_row_index, 1] # Column 1 is X
241
+ y = coordinates.iloc[csv_row_index, 2] # Column 2 is Y
242
+
243
+ scale = settings[remainder]["Scale"]
244
+ image_type = settings[remainder]["Image Type"]
245
+ new_name = f"{scale}_{x}_{y}_{image_type}.tif"
246
+
247
+ old_path = os.path.join(output_dir, file)
248
+ new_path = os.path.join(output_dir, new_name)
249
+
250
+ # Handle file name collisions
251
+ if os.path.exists(new_path):
252
+ base_name = new_name.rsplit('.', 1)[0]
253
+ extension = new_name.rsplit('.', 1)[1] if '.' in new_name else 'tif'
254
+ counter = 1
255
+ while os.path.exists(new_path):
256
+ new_name = f"{base_name}_{counter}.{extension}"
257
+ new_path = os.path.join(output_dir, new_name)
258
+ counter += 1
259
+
260
+ try:
261
+ os.rename(old_path, new_path)
262
+ renamed_count += 1
263
+ except Exception as e:
264
+ print(f"[DEBUG] Error renaming {file}: {e}")
265
+
266
+ return renamed_count
267
+
268
+
269
+ def _rename_all_kronos(dirname, coordinates_dict):
270
+ """
271
+ Rename all TIFF files for KRONOS mode across all subdirectories.
272
+
273
+ Args:
274
+ dirname: Base directory containing subdirectories
275
+ coordinates_dict: Dictionary mapping wafer_num to coordinates DataFrame
276
+
277
+ Returns:
278
+ int: Total number of files renamed
279
+ """
280
+ total_renamed = 0
281
+ has_qt = HAS_QT
282
+
283
+ for subdir, _, _ in os.walk(dirname):
284
+ if subdir == dirname:
285
+ continue
286
+
287
+ output_dir = os.path.join(dirname, os.path.basename(subdir))
288
+
289
+ try:
290
+ wafer_num = int(os.path.basename(subdir))
291
+ except ValueError:
292
+ continue
293
+
294
+ if wafer_num not in coordinates_dict:
295
+ continue
296
+
297
+ coordinates = coordinates_dict[wafer_num]
298
+
299
+ tiff_files = [f for f in os.listdir(output_dir)
300
+ if "page" in f and f.lower().endswith(('.tiff', '.tif'))]
301
+ tiff_files.sort()
302
+
303
+ renamed_in_dir = 0
304
+ for idx, file in enumerate(tiff_files):
305
+ if has_qt and idx % 10 == 0:
306
+ QApplication.processEvents()
307
+
308
+ try:
309
+ file_number = int(file.split('_')[2].split('.')[0])
310
+ except (ValueError, IndexError):
311
+ continue
312
+
313
+ csv_row_index = file_number - 1
314
+
315
+ if csv_row_index >= len(coordinates):
316
+ continue
317
+
318
+ x = coordinates.iloc[csv_row_index, 1]
319
+ y = coordinates.iloc[csv_row_index, 2]
320
+ new_name = f"{x}_{y}.tif"
321
+
322
+ old_path = os.path.join(output_dir, file)
323
+ new_path = os.path.join(output_dir, new_name)
324
+
325
+ if os.path.exists(new_path):
326
+ base_name = new_name.rsplit('.', 1)[0]
327
+ extension = new_name.rsplit('.', 1)[1] if '.' in new_name else 'tif'
328
+ counter = 1
329
+ while os.path.exists(new_path):
330
+ new_name = f"{base_name}_{counter}.{extension}"
331
+ new_path = os.path.join(output_dir, new_name)
332
+ counter += 1
333
+
334
+ try:
335
+ os.rename(old_path, new_path)
336
+ renamed_in_dir += 1
337
+ total_renamed += 1
338
+ except Exception:
339
+ pass
340
+
341
+ return total_renamed
342
+
343
+
344
+ def _rename_all_complus4t(dirname, coordinates_dict):
345
+ """
346
+ Rename all TIFF files for COMPLUS4T mode across all subdirectories.
347
+
348
+ Args:
349
+ dirname: Base directory containing subdirectories
350
+ coordinates_dict: Dictionary mapping wafer_num to coordinates DataFrame
351
+
352
+ Returns:
353
+ int: Total number of files renamed
354
+ """
355
+ total_renamed = 0
356
+ has_qt = HAS_QT
357
+
358
+ for subdir, _, _ in os.walk(dirname):
359
+ if subdir == dirname:
360
+ continue
361
+
362
+ output_dir = os.path.join(dirname, os.path.basename(subdir))
363
+
364
+ try:
365
+ wafer_num = int(os.path.basename(subdir))
366
+ except ValueError:
367
+ continue
368
+
369
+ if wafer_num not in coordinates_dict:
370
+ continue
371
+
372
+ coordinates = coordinates_dict[wafer_num]
373
+
374
+ tiff_files = [f for f in os.listdir(output_dir)
375
+ if "page" in f and f.lower().endswith(('.tiff', '.tif'))]
376
+ tiff_files.sort()
377
+
378
+ renamed_in_dir = 0
379
+ for idx, file in enumerate(tiff_files):
380
+ if has_qt and idx % 10 == 0:
381
+ QApplication.processEvents()
382
+
383
+ try:
384
+ file_number = int(file.split('_')[2].split('.')[0])
385
+ except (ValueError, IndexError):
386
+ continue
387
+
388
+ matching_rows = coordinates[coordinates['defect_id'] == file_number]
389
+
390
+ if matching_rows.empty:
391
+ continue
392
+
393
+ row = matching_rows.iloc[0]
394
+ x = row['X']
395
+ y = row['Y']
396
+ new_name = f"{x}_{y}.tif"
397
+
398
+ old_path = os.path.join(output_dir, file)
399
+ new_path = os.path.join(output_dir, new_name)
400
+
401
+ if os.path.exists(new_path):
402
+ base_name = new_name.rsplit('.', 1)[0]
403
+ extension = new_name.rsplit('.', 1)[1] if '.' in new_name else 'tif'
404
+ counter = 1
405
+ while os.path.exists(new_path):
406
+ new_name = f"{base_name}_{counter}.{extension}"
407
+ new_path = os.path.join(output_dir, new_name)
408
+ counter += 1
409
+
410
+ try:
411
+ os.rename(old_path, new_path)
412
+ renamed_in_dir += 1
413
+ total_renamed += 1
414
+ except Exception:
415
+ pass
416
+
417
+ return total_renamed
418
+
419
+
420
+ def _rename_all_normal(dirname, coordinates_dict, settings):
421
+ """
422
+ Rename all TIFF files for normal mode across all subdirectories.
423
+
424
+ Args:
425
+ dirname: Base directory containing subdirectories
426
+ coordinates_dict: Dictionary mapping wafer_num to coordinates DataFrame
427
+ settings: List of settings dictionaries
428
+
429
+ Returns:
430
+ int: Total number of files renamed
431
+ """
432
+ total_renamed = 0
433
+ has_qt = HAS_QT
434
+
435
+ for subdir, _, _ in os.walk(dirname):
436
+ if subdir == dirname:
437
+ continue
438
+
439
+ output_dir = os.path.join(dirname, os.path.basename(subdir))
440
+
441
+ try:
442
+ wafer_num = int(os.path.basename(subdir))
443
+ except ValueError:
444
+ continue
445
+
446
+ if wafer_num not in coordinates_dict:
447
+ continue
448
+
449
+ coordinates = coordinates_dict[wafer_num]
450
+
451
+ tiff_files = [f for f in os.listdir(output_dir)
452
+ if "page" in f and f.lower().endswith(('.tiff', '.tif'))]
453
+ tiff_files.sort()
454
+
455
+ renamed_in_dir = 0
456
+ for idx, file in enumerate(tiff_files):
457
+ if has_qt and idx % 10 == 0:
458
+ QApplication.processEvents()
459
+
460
+ try:
461
+ file_number = int(file.split('_')[2].split('.')[0])
462
+ except (ValueError, IndexError):
463
+ continue
464
+
465
+ csv_row_index = (file_number - 1) // len(settings)
466
+ remainder = (file_number - 1) % len(settings)
467
+
468
+ if csv_row_index >= len(coordinates):
469
+ continue
470
+
471
+ x = coordinates.iloc[csv_row_index, 1]
472
+ y = coordinates.iloc[csv_row_index, 2]
473
+
474
+ scale = settings[remainder]["Scale"]
475
+ image_type = settings[remainder]["Image Type"]
476
+ new_name = f"{scale}_{x}_{y}_{image_type}.tif"
477
+
478
+ old_path = os.path.join(output_dir, file)
479
+ new_path = os.path.join(output_dir, new_name)
480
+
481
+ if os.path.exists(new_path):
482
+ base_name = new_name.rsplit('.', 1)[0]
483
+ extension = new_name.rsplit('.', 1)[1] if '.' in new_name else 'tif'
484
+ counter = 1
485
+ while os.path.exists(new_path):
486
+ new_name = f"{base_name}_{counter}.{extension}"
487
+ new_path = os.path.join(output_dir, new_name)
488
+ counter += 1
489
+
490
+ try:
491
+ os.rename(old_path, new_path)
492
+ renamed_in_dir += 1
493
+ total_renamed += 1
494
+ except Exception:
495
+ pass
496
+
497
+ return total_renamed
498
+