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,323 @@
1
+ """
2
+ Module for splitting multi-page TIFF files into individual TIFF files.
3
+ Supports KRONOS, COMPLUS4T, and normal modes.
4
+ """
5
+
6
+ import os
7
+ import glob
8
+ from PIL import Image
9
+
10
+
11
+ def split_tiff(tiff_path, output_dir, coordinates=None, is_kronos=False, is_complus4t=False):
12
+ """
13
+ Split a merged TIFF file into individual TIFF files.
14
+ Main function that detects the mode and calls the appropriate splitter.
15
+
16
+ Args:
17
+ tiff_path: Path to the multi-page TIFF file
18
+ output_dir: Directory where split files will be saved
19
+ coordinates: DataFrame with columns ["defect_id", "X", "Y", "defect_size"] (for COMPLUS4T)
20
+ is_kronos: Boolean indicating if this is KRONOS mode
21
+ is_complus4t: Boolean indicating if this is COMPLUS4T mode
22
+
23
+ Returns:
24
+ list: List of file paths of the generated TIFF files
25
+ """
26
+ if is_complus4t:
27
+ return _split_tiff_complus4t(tiff_path, output_dir, coordinates)
28
+ elif is_kronos:
29
+ return _split_tiff_kronos(tiff_path, output_dir)
30
+ else:
31
+ return _split_tiff_normal(tiff_path, output_dir)
32
+
33
+
34
+ def split_tiff_all(dirname, coordinates_dict=None, is_kronos=False, is_complus4t=False):
35
+ """
36
+ Split all merged TIFF files in all subdirectories into individual TIFF files.
37
+ Main function that detects the mode and calls the appropriate splitter.
38
+
39
+ Args:
40
+ dirname: Base directory containing subdirectories
41
+ coordinates_dict: Dictionary mapping wafer_num to coordinates DataFrame (for COMPLUS4T)
42
+ is_kronos: Boolean indicating if this is KRONOS mode
43
+ is_complus4t: Boolean indicating if this is COMPLUS4T mode
44
+
45
+ Returns:
46
+ list: List of all generated TIFF file paths
47
+ """
48
+ if is_complus4t:
49
+ return _split_tiff_all_complus4t(dirname, coordinates_dict)
50
+ elif is_kronos:
51
+ return _split_tiff_all_kronos(dirname)
52
+ else:
53
+ return _split_tiff_all_normal(dirname)
54
+
55
+
56
+ def _split_tiff_kronos(tiff_path, output_dir):
57
+ """
58
+ Split TIFF file for KRONOS mode.
59
+ Splits all pages sequentially.
60
+
61
+ Args:
62
+ tiff_path: Path to the multi-page TIFF file
63
+ output_dir: Directory where split files will be saved
64
+
65
+ Returns:
66
+ list: List of file paths of the generated TIFF files
67
+ """
68
+ if not os.path.exists(tiff_path):
69
+ return []
70
+
71
+ os.makedirs(output_dir, exist_ok=True)
72
+ output_files = []
73
+
74
+ try:
75
+ img = Image.open(tiff_path)
76
+ page_index = 0
77
+
78
+ while True:
79
+ output_file = os.path.join(output_dir, f"data_page_{page_index + 1}.tiff")
80
+ img.save(output_file, format="TIFF")
81
+ output_files.append(output_file)
82
+
83
+ try:
84
+ img.seek(page_index + 1)
85
+ page_index += 1
86
+ except EOFError:
87
+ break
88
+ except Exception as error:
89
+ raise RuntimeError(f"Error splitting TIFF file: {error}") from error
90
+
91
+ return output_files
92
+
93
+
94
+ def _split_tiff_complus4t(tiff_path, output_dir, coordinates):
95
+ """
96
+ Split TIFF file for COMPLUS4T mode.
97
+ Only splits pages corresponding to defect_id from coordinates.
98
+
99
+ Args:
100
+ tiff_path: Path to the multi-page TIFF file
101
+ output_dir: Directory where split files will be saved
102
+ coordinates: DataFrame with columns ["defect_id", "X", "Y", "defect_size"]
103
+
104
+ Returns:
105
+ list: List of file paths of the generated TIFF files
106
+ """
107
+ if not os.path.exists(tiff_path):
108
+ return []
109
+
110
+ if coordinates is None or coordinates.empty:
111
+ print(f"Warning: No coordinates provided for COMPLUS4T split")
112
+ return []
113
+
114
+ os.makedirs(output_dir, exist_ok=True)
115
+ output_files = []
116
+
117
+ try:
118
+ img = Image.open(tiff_path)
119
+
120
+ # COMPLUS4T: only split pages corresponding to defect_id
121
+ # Pages in TIFF correspond to defect_id (331, 332, 333...)
122
+ # defect_id are 1-based in KLARF, but TIFF pages are 0-based
123
+ # So defect_id 331 = page index 330 (331 - 1)
124
+ for idx, row in coordinates.iterrows():
125
+ defect_id = int(row['defect_id'])
126
+ page_index = defect_id - 1 # Convert to 0-based index
127
+
128
+ try:
129
+ img.seek(page_index)
130
+ output_file = os.path.join(output_dir, f"data_page_{defect_id}.tiff")
131
+ img.save(output_file, format="TIFF")
132
+ output_files.append(output_file)
133
+ except EOFError:
134
+ print(f"Warning: Page {page_index} (defect_id {defect_id}) not found in TIFF")
135
+ continue
136
+ except Exception as error:
137
+ raise RuntimeError(f"Error splitting TIFF file: {error}") from error
138
+
139
+ return output_files
140
+
141
+
142
+ def _split_tiff_normal(tiff_path, output_dir):
143
+ """
144
+ Split TIFF file for normal mode.
145
+ Splits all pages sequentially.
146
+
147
+ Args:
148
+ tiff_path: Path to the multi-page TIFF file
149
+ output_dir: Directory where split files will be saved
150
+
151
+ Returns:
152
+ list: List of file paths of the generated TIFF files
153
+ """
154
+ if not os.path.exists(tiff_path):
155
+ return []
156
+
157
+ os.makedirs(output_dir, exist_ok=True)
158
+ output_files = []
159
+
160
+ try:
161
+ img = Image.open(tiff_path)
162
+ page_index = 0
163
+
164
+ while True:
165
+ output_file = os.path.join(output_dir, f"data_page_{page_index + 1}.tiff")
166
+ img.save(output_file, format="TIFF")
167
+ output_files.append(output_file)
168
+
169
+ try:
170
+ img.seek(page_index + 1)
171
+ page_index += 1
172
+ except EOFError:
173
+ break
174
+ except Exception as error:
175
+ raise RuntimeError(f"Error splitting TIFF file: {error}") from error
176
+
177
+ return output_files
178
+
179
+
180
+ def _split_tiff_all_kronos(dirname):
181
+ """
182
+ Split all TIFF files for KRONOS mode across all subdirectories.
183
+
184
+ Args:
185
+ dirname: Base directory containing subdirectories
186
+
187
+ Returns:
188
+ list: List of all generated TIFF file paths
189
+ """
190
+ all_output_files = []
191
+
192
+ for subdir, _, _ in os.walk(dirname):
193
+ if subdir == dirname:
194
+ continue
195
+
196
+ tiff_path = os.path.join(subdir, "data.tif")
197
+
198
+ if not os.path.exists(tiff_path):
199
+ continue
200
+
201
+ try:
202
+ img = Image.open(tiff_path)
203
+ page_index = 0
204
+
205
+ while True:
206
+ output_file = tiff_path.replace(".tif", "") + f"_page_{page_index + 1}.tiff"
207
+ img.save(output_file, format="TIFF")
208
+ all_output_files.append(output_file)
209
+
210
+ try:
211
+ img.seek(page_index + 1)
212
+ page_index += 1
213
+ except EOFError:
214
+ break
215
+ except Exception as error:
216
+ print(f"Error splitting TIFF file {tiff_path}: {error}")
217
+ continue
218
+
219
+ return all_output_files
220
+
221
+
222
+ def _split_tiff_all_complus4t(dirname, coordinates_dict):
223
+ """
224
+ Split all TIFF files for COMPLUS4T mode across all subdirectories.
225
+
226
+ Args:
227
+ dirname: Base directory containing subdirectories
228
+ coordinates_dict: Dictionary mapping wafer_num to coordinates DataFrame
229
+
230
+ Returns:
231
+ list: List of all generated TIFF file paths
232
+ """
233
+ all_output_files = []
234
+
235
+ # For COMPLUS4T, the TIFF file is in the parent directory
236
+ tiff_files = glob.glob(os.path.join(dirname, '*.tiff'))
237
+ if not tiff_files:
238
+ tiff_files = glob.glob(os.path.join(dirname, '*.tif'))
239
+
240
+ if not tiff_files:
241
+ print("Warning: No TIFF file found in parent directory for COMPLUS4T mode")
242
+ return []
243
+
244
+ parent_tiff_path = tiff_files[0]
245
+
246
+ for subdir, _, _ in os.walk(dirname):
247
+ if subdir == dirname:
248
+ continue
249
+
250
+ try:
251
+ wafer_num = int(os.path.basename(subdir))
252
+ except ValueError:
253
+ continue
254
+
255
+ if wafer_num not in coordinates_dict:
256
+ continue
257
+
258
+ coordinates = coordinates_dict[wafer_num]
259
+ output_dir = os.path.join(dirname, str(wafer_num))
260
+ os.makedirs(output_dir, exist_ok=True)
261
+
262
+ try:
263
+ img = Image.open(parent_tiff_path)
264
+
265
+ for idx, row in coordinates.iterrows():
266
+ defect_id = int(row['defect_id'])
267
+ page_index = defect_id - 1
268
+
269
+ try:
270
+ img.seek(page_index)
271
+ output_file = os.path.join(output_dir, f"data_page_{defect_id}.tiff")
272
+ img.save(output_file, format="TIFF")
273
+ all_output_files.append(output_file)
274
+ except EOFError:
275
+ print(f"Warning: Page {page_index} (defect_id {defect_id}) not found in TIFF for wafer {wafer_num}")
276
+ continue
277
+ except Exception as error:
278
+ print(f"Error splitting TIFF file for wafer {wafer_num}: {error}")
279
+ continue
280
+
281
+ return all_output_files
282
+
283
+
284
+ def _split_tiff_all_normal(dirname):
285
+ """
286
+ Split all TIFF files for normal mode across all subdirectories.
287
+
288
+ Args:
289
+ dirname: Base directory containing subdirectories
290
+
291
+ Returns:
292
+ list: List of all generated TIFF file paths
293
+ """
294
+ all_output_files = []
295
+
296
+ for subdir, _, _ in os.walk(dirname):
297
+ if subdir == dirname:
298
+ continue
299
+
300
+ tiff_path = os.path.join(subdir, "data.tif")
301
+
302
+ if not os.path.exists(tiff_path):
303
+ continue
304
+
305
+ try:
306
+ img = Image.open(tiff_path)
307
+ page_index = 0
308
+
309
+ while True:
310
+ output_file = tiff_path.replace(".tif", "") + f"_page_{page_index + 1}.tiff"
311
+ img.save(output_file, format="TIFF")
312
+ all_output_files.append(output_file)
313
+
314
+ try:
315
+ img.seek(page_index + 1)
316
+ page_index += 1
317
+ except EOFError:
318
+ break
319
+ except Exception as error:
320
+ print(f"Error splitting TIFF file {tiff_path}: {error}")
321
+ continue
322
+
323
+ return all_output_files