Semapp 1.0.2__py3-none-any.whl → 1.0.3__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.

@@ -36,19 +36,20 @@ class Process:
36
36
  self.output_dir = None
37
37
  self.load_json()
38
38
  def load_json(self):
39
+
39
40
  """Load the settings data from a JSON file."""
40
41
  try:
41
42
  with open(self.scale_data, "r", encoding="utf-8") as file:
42
43
  self.settings = json.load(file)
43
- print("Settings data loaded successfully.")
44
+ pass # Settings loaded
44
45
  except FileNotFoundError:
45
- print("Settings file not found. Starting fresh.")
46
+ # Settings file not found, starting fresh
46
47
  self.settings = []
47
48
  except json.JSONDecodeError as error:
48
- print(f"JSON decoding error: {error}")
49
+ # JSON decoding error
49
50
  self.settings = []
50
51
  except OSError as error:
51
- print(f"OS error when reading file: {error}")
52
+ # OS error when reading file
52
53
  self.settings = []
53
54
  def extract_positions(self, filepath):
54
55
  '''Function to extract positions from a 001 file.'''
@@ -132,7 +133,7 @@ class Process:
132
133
  self.output_dir = os.path.join(self.dirname, self.wafer_number)
133
134
 
134
135
  if not os.path.exists(self.output_dir):
135
- print(f"Directory not found: {self.output_dir}")
136
+ pass # Directory not found
136
137
  return
137
138
 
138
139
  matching_files = glob.glob(os.path.join(self.output_dir, '*.001'))
@@ -153,8 +154,6 @@ class Process:
153
154
  for file in tiff_files:
154
155
  # Extract page number from the file name (e.g., data_page_1.tiff)
155
156
  file_number = int(file.split('_')[2].split('.')[0])
156
- print(f"Processing {file}: Page number {file_number}, Total "
157
- f"settings {len(self.settings)}")
158
157
 
159
158
  # Calculate the corresponding row in the CSV
160
159
  csv_row_index = (file_number - 1) // len(self.settings)
@@ -176,7 +175,6 @@ class Process:
176
175
 
177
176
  # Rename the file
178
177
  os.rename(old_path, new_path)
179
- print(f"Renamed: {file} -> {new_name}")
180
178
 
181
179
  def split_tiff(self):
182
180
  """
@@ -193,7 +191,6 @@ class Process:
193
191
  output_files = []
194
192
  page_index = 0
195
193
  if not os.path.exists(self.tiff_path):
196
- print(f"TIFF file not found: {self.tiff_path}")
197
194
  return []
198
195
 
199
196
  try:
@@ -224,7 +221,6 @@ class Process:
224
221
  self.output_dir = os.path.join(self.dirname, self.wafer_number)
225
222
 
226
223
  if not os.path.exists(self.output_dir):
227
- print(f"Error: Directory does not exist: {self.output_dir}")
228
224
  return
229
225
 
230
226
  tiff_files = [f for f in os.listdir(self.output_dir)
@@ -235,7 +231,6 @@ class Process:
235
231
  if not file_name.startswith("data") or "page" in file_name.lower() or file_name.endswith("001"):
236
232
  file_path = os.path.join(self.output_dir, file_name)
237
233
  os.remove(file_path)
238
- print(f"Deleted: {file_path}")
239
234
 
240
235
  def split_tiff_all(self):
241
236
  """
@@ -248,13 +243,10 @@ class Process:
248
243
  for subdir, _, _ in os.walk(self.dirname):
249
244
  if subdir != self.dirname:
250
245
  self.tiff_path = os.path.join(subdir, "data.tif")
251
- print(f"Processing directory: {subdir}, "
252
- f"TIFF path: {self.tiff_path}")
253
246
 
254
247
  output_files = []
255
248
  page_index = 0
256
249
  if not os.path.exists(self.tiff_path):
257
- print(f"TIFF file not found: {self.tiff_path}")
258
250
  continue
259
251
 
260
252
  try:
@@ -287,7 +279,6 @@ class Process:
287
279
  if subdir != self.dirname:
288
280
  self.output_dir = os.path.join(self.dirname,
289
281
  os.path.basename(subdir))
290
- print(f"Renaming files in: {self.output_dir}")
291
282
 
292
283
  matching_files = glob.glob(os.path.join(self.output_dir, '*.001'))
293
284
 
@@ -307,8 +298,6 @@ class Process:
307
298
 
308
299
  for file in tiff_files:
309
300
  file_number = int(file.split('_')[2].split('.')[0])
310
- print(f"Processing {file}: Page number {file_number}, "
311
- f"Total settings {len(self.settings)}")
312
301
 
313
302
  csv_row_index = (file_number - 1) // len(self.settings)
314
303
  remainder = (file_number - 1) % len(self.settings)
@@ -324,7 +313,6 @@ class Process:
324
313
  new_path = os.path.join(self.output_dir, new_name)
325
314
 
326
315
  os.rename(old_path, new_path)
327
- print(f"Renamed: {file} -> {new_name}")
328
316
 
329
317
  def clean_all(self):
330
318
  """
@@ -337,10 +325,8 @@ class Process:
337
325
  if subdir != self.dirname:
338
326
  self.output_dir = os.path.join(self.dirname,
339
327
  os.path.basename(subdir))
340
- print(f"Cleaning directory: {self.output_dir}")
341
328
 
342
329
  if not os.path.exists(self.output_dir):
343
- print(f"Error: Directory does not exist: {self.output_dir}")
344
330
  continue
345
331
 
346
332
  tiff_files = [f for f in os.listdir(self.output_dir)
@@ -350,7 +336,6 @@ class Process:
350
336
  "page" in file_name.lower() or file_name.endswith("001"):
351
337
  file_path = os.path.join(self.output_dir, file_name)
352
338
  os.remove(file_path)
353
- print(f"Deleted: {file_path}")
354
339
 
355
340
  def organize_and_rename_files(self):
356
341
  """
@@ -359,16 +344,22 @@ class Process:
359
344
  and rename the files to 'data.tif' in their respective subfolders.
360
345
  """
361
346
  if not os.path.exists(self.dirname):
362
- print(f"Error: The folder {self.dirname} does not exist.")
363
347
  return
364
348
 
349
+ # Check if there are subdirectories
350
+ subdirs = [d for d in os.listdir(self.dirname) if
351
+ os.path.isdir(os.path.join(self.dirname, d))]
352
+
353
+ # Check if there are .tif files
354
+ tif_files = [f for f in os.listdir(self.dirname)
355
+ if f.lower().endswith(".tif") and os.path.isfile(os.path.join(self.dirname, f))]
356
+
365
357
  # Iterate through files in the directory
366
358
  for file_name in os.listdir(self.dirname):
367
359
  if file_name.lower().endswith(".tif"):
368
360
  parts = file_name.rsplit("_", 1)
369
361
  if len(parts) < 2:
370
- print(
371
- f"Skipping file with unexpected format: {file_name}")
362
+ # Skip file with unexpected format
372
363
  continue
373
364
 
374
365
  # Use the last part (before extension) as the subfolder name
@@ -383,14 +374,11 @@ class Process:
383
374
  destination_path = os.path.join(subfolder_path, "data.tif")
384
375
  shutil.move(source_path, destination_path)
385
376
 
386
- print(
387
- f"Moved and renamed: {file_name} -> {destination_path}")
388
377
 
389
378
  if file_name.lower().endswith(".001"):
390
379
  parts = file_name.rsplit("_", 1)
391
380
  if len(parts) < 2:
392
- print(
393
- f"Skipping file with unexpected format: {file_name}")
381
+ # Skip file with unexpected format
394
382
  continue
395
383
 
396
384
  # Use the last part (before extension) as the subfolder name
@@ -405,8 +393,53 @@ class Process:
405
393
  destination_path = os.path.join(subfolder_path, file_name)
406
394
  shutil.move(source_path, destination_path)
407
395
 
408
- print(
409
- f"Moved and renamed: {file_name} -> {destination_path}")
396
+
397
+ # If no subdirectories and no .tif files, create folders from KLARF files
398
+ if not subdirs and not tif_files:
399
+ wafer_ids = self.extract_wafer_ids_from_klarf()
400
+
401
+ if wafer_ids:
402
+ for wafer_id in wafer_ids:
403
+ subfolder_path = os.path.join(self.dirname, str(wafer_id))
404
+ os.makedirs(subfolder_path, exist_ok=True)
405
+
406
+ def extract_wafer_ids_from_klarf(self):
407
+ """Extract wafer IDs from KLARF files (.001) that contain COMPLUS4T."""
408
+ wafer_ids = []
409
+
410
+ if not self.dirname:
411
+ return wafer_ids
412
+
413
+ # Chercher les fichiers .001
414
+ try:
415
+ files = [f for f in os.listdir(self.dirname)
416
+ if f.endswith('.001') and os.path.isfile(os.path.join(self.dirname, f))]
417
+
418
+ for file in files:
419
+ file_path = os.path.join(self.dirname, file)
420
+ try:
421
+ with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
422
+ content = f.read()
423
+
424
+ # Check if file contains "COMPLUS4T"
425
+ if 'COMPLUS4T' in content:
426
+ # Search for all lines with WaferID
427
+ # Pattern to extract number in quotes after WaferID
428
+ pattern = r'WaferID\s+"@(\d+)"'
429
+ matches = re.findall(pattern, content)
430
+
431
+ # Add found IDs (converted to int)
432
+ for match in matches:
433
+ wafer_id = int(match)
434
+ if wafer_id not in wafer_ids and 1 <= wafer_id <= 26:
435
+ wafer_ids.append(wafer_id)
436
+ except Exception as e:
437
+ pass # Error reading file
438
+
439
+ except Exception as e:
440
+ pass # Error listing files
441
+
442
+ return wafer_ids
410
443
 
411
444
  def rename_wo_legend_all(self):
412
445
  """
@@ -421,19 +454,15 @@ class Process:
421
454
  if file.endswith(".001"):
422
455
  folder_names.append(subdir)
423
456
 
424
- print(folder_names) # debug print
425
457
 
426
458
  # Process each folder found
427
459
  for folder in folder_names:
428
460
  for subdir, _, files in os.walk(folder):
429
461
  for file in files:
430
462
  if file.endswith(".tiff"):
431
- print(subdir)
432
- print(f"Processing: {file}")
433
463
  old_filepath = os.path.join(subdir, file)
434
464
 
435
465
  matching_files = glob.glob(os.path.join(folder, '*.001'))
436
- print("Found .001 files:", matching_files) # debug print
437
466
 
438
467
  if matching_files:
439
468
  recipe_path = matching_files[0]
@@ -442,14 +471,11 @@ class Process:
442
471
  return
443
472
 
444
473
 
445
- print(self.coordinates)
446
474
 
447
475
  try:
448
476
  defect_part = int(file.split("_")[1]) - 1
449
- print(f"Defect part index: {defect_part}")
450
477
  except (IndexError, ValueError):
451
- print(
452
- f"Skipping file due to unexpected format: {file}")
478
+ # Error parsing defect part index, skip file
453
479
  continue
454
480
 
455
481
  # Check if defect part is within the valid range
@@ -459,9 +485,7 @@ class Process:
459
485
 
460
486
 
461
487
  if defect_part >= len(self.coordinates):
462
- print(
463
- f"Skipping file {file} due to out-of-bounds "
464
- f"defect part.")
488
+ # Error: defect part out of bounds, skip file
465
489
  continue
466
490
 
467
491
  x = self.coordinates.iloc[defect_part, 0]
@@ -483,7 +507,6 @@ class Process:
483
507
  # Construct the new file path and rename
484
508
  new_filepath = os.path.join(subdir, new_filename)
485
509
  os.rename(old_filepath, new_filepath)
486
- print(f"Renamed: {old_filepath} -> {new_filepath}")
487
510
 
488
511
  def rename_wo_legend(self):
489
512
  """
@@ -493,27 +516,22 @@ class Process:
493
516
  """
494
517
  wafer_path = os.path.join(self.dirname, self.wafer_number)
495
518
  if not os.path.exists(wafer_path):
496
- print(f"Error: The wafer folder {wafer_path} does not exist.")
497
519
  return
498
520
 
499
521
  for subdir, _, files in os.walk(wafer_path):
500
522
  for file in files:
501
523
  if file.endswith(".tiff"):
502
- print(f"Processing: {file}")
503
524
 
504
525
  old_filepath = os.path.join(subdir, file)
505
526
 
506
527
  try:
507
528
  defect_part = int(file.split("_")[1]) - 1
508
- print(f"Defect part index: {defect_part}")
509
529
  except (IndexError, ValueError):
510
- print(
511
- f"Skipping file due to unexpected format: {file}")
530
+ # Error parsing defect part, skip file
512
531
  continue
513
532
 
514
533
  matching_files = glob.glob(os.path.join(wafer_path, '*.001'))
515
534
 
516
- print("Found .001 files:", matching_files) # debug print
517
535
 
518
536
  if matching_files:
519
537
  recipe_path = matching_files[0]
@@ -523,9 +541,7 @@ class Process:
523
541
 
524
542
  # Check if defect part is within the valid range
525
543
  if defect_part >= len(self.coordinates):
526
- print(
527
- f"Skipping file {file} "
528
- f"due to out-of-bounds defect part.")
544
+ # Error: defect part out of bounds, skip file
529
545
  continue
530
546
 
531
547
  x = self.coordinates.iloc[defect_part, 0]
@@ -540,14 +556,12 @@ class Process:
540
556
  0] # Extract Topography number
541
557
  new_filename += f"_SE{topo_number}.tiff"
542
558
  else:
543
- print(
544
- f"Skipping file due to unexpected format: {file}")
559
+ # Error: unexpected file format, skip file
545
560
  continue
546
561
 
547
562
  # Construct the new file path and rename
548
563
  new_filepath = os.path.join(subdir, new_filename)
549
564
  os.rename(old_filepath, new_filepath)
550
- print(f"Renamed: {old_filepath} -> {new_filepath}")
551
565
 
552
566
  def clean_folders_and_files(self):
553
567
  """
@@ -565,91 +579,75 @@ class Process:
565
579
  # Avoid name conflicts
566
580
  if not os.path.exists(new_path):
567
581
  os.rename(old_path, new_path)
568
- print(f"Renamed: {old_path} -> {new_path}")
569
582
  else:
570
- print(f"Conflict: {new_path} already exists. Skipped renaming.")
583
+ pass # Conflict: file already exists, skip
571
584
 
572
585
  for folder, subfolders, files in os.walk(self.dirname):
573
586
  # Delete .tiff files that contain "Raw" in their name
574
587
  for file in files:
575
588
  if file.endswith(".tiff") and "Raw" in file:
576
- print(file)
577
589
  file_path = os.path.join(folder, file)
578
590
  os.remove(file_path)
579
- print(f"Deleted: {file_path}")
580
591
 
581
592
 
582
593
  def ajouter_extension_tiff(self):
583
594
  """
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.
595
+ Add .tiff extension to all files in parent folder and subfolders,
596
+ EXCEPT those ending with .001.
597
+ Uses os.walk to traverse all subfolders.
587
598
  """
588
599
  fichiers_renommes = 0
589
600
 
590
- print(f"Scan du dossier parent: {self.dirname}")
591
-
592
- # Parcourir tous les sous-dossiers avec os.walk
601
+ # Traverse all subfolders with os.walk
593
602
  for root, dirs, files in os.walk(self.dirname):
594
- print(f"\nTraitement du dossier: {root}")
595
-
596
603
  for file in files:
597
- # Ignorer les fichiers qui se terminent par .001
604
+ # Ignore files ending with .001
598
605
  if file.endswith('.001'):
599
- print(f"Fichier ignoré (extension .001): {file}")
600
606
  continue
601
607
 
602
- # Vérifier si le fichier n'a pas d'extension ou a une extension différente de .tiff
608
+ # Check if file has no extension or has different extension than .tiff
603
609
  if '.' not in file or not file.endswith('.tiff'):
604
610
  old_filepath = os.path.join(root, file)
605
611
 
606
- # Si le fichier n'a pas d'extension, ajouter .tiff
612
+ # If file has no extension, add .tiff
607
613
  if '.' not in file:
608
614
  new_filename = file + '.tiff'
609
615
  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
616
+ # If file has different extension, replace with .tiff
617
+ base_name = file.rsplit('.', 1)[0] # Take everything except last extension
612
618
  new_filename = base_name + '.tiff'
613
619
 
614
620
  new_filepath = os.path.join(root, new_filename)
615
621
 
616
- # Vérifier que le nouveau nom n'existe pas déjà
622
+ # Check that new name doesn't already exist
617
623
  if not os.path.exists(new_filepath):
618
624
  try:
619
625
  os.rename(old_filepath, new_filepath)
620
- print(f"Extension ajoutée: '{file}' -> '{new_filename}'")
621
626
  fichiers_renommes += 1
622
627
  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}")
628
+ pass # Error renaming file
631
629
 
632
630
  return fichiers_renommes
633
631
 
634
632
 
635
633
  if __name__ == "__main__":
636
- DIRNAME = r"C:\Users\TM273821\Desktop\SEM\lD25S1556"
634
+ DIRNAME = r"C:\Users\TM273821\Desktop\SEM\D25S2039_200_MOS2_SIO2_API"
637
635
  SCALE = r"C:\Users\TM273821\SEM\settings_data.json"
638
636
 
639
637
  processor = Process(DIRNAME, wafer=18, scale=SCALE)
640
638
 
641
639
  # Process files
642
640
  # processor.organize_and_rename_files() # Organize and rename files
643
- processor.rename_wo_legend_all() # Preprocess all files in the directory
641
+ # processor.rename_wo_legend_all() # Preprocess all files in the directory
644
642
  # processor.clean_folders_and_files()
645
643
  # processor.rename_wo_legend() # Preprocess specific wafer
646
644
 
647
645
  # processor.split_tiff_all() # Preprocess specific wafer
648
646
  # processor.split_tiff_all() # Preprocess specific wafer
649
647
  # processor.split_tiff() # Preprocess specific wafer
650
- # processor.rename_all() # Preprocess specific wafer
648
+ processor.rename_all() # Preprocess specific wafer
651
649
 
652
- # Ajouter l'extension .tiff aux fichiers qui n'en ont pas
653
- processor.ajouter_extension_tiff()
650
+ # # Ajouter l'extension .tiff aux fichiers qui n'en ont pas
651
+ # processor.ajouter_extension_tiff()
654
652
 
655
653
 
semapp/__init__.py CHANGED
@@ -0,0 +1,10 @@
1
+ """
2
+ SEMapp - SEM Data Visualization Application
3
+
4
+ A PyQt5-based application for visualizing and analyzing Scanning Electron Microscope (SEM) data.
5
+ Supports both standard and COMPLUS4T KLARF file formats.
6
+ """
7
+
8
+ __version__ = "1.0.2"
9
+ __author__ = "Your Name"
10
+
semapp/main.py CHANGED
@@ -6,8 +6,13 @@ for the SEM data visualization application.
6
6
  """
7
7
 
8
8
  import sys
9
+ import os
9
10
  from PyQt5.QtCore import QTimer
10
11
  from PyQt5.QtWidgets import QApplication, QWidget, QGridLayout
12
+
13
+ # Add parent directory to path to allow imports
14
+ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
15
+
11
16
  from semapp.Layout.main_window_att import LayoutFrame
12
17
  from semapp.Layout.create_button import ButtonFrame
13
18
  from semapp.Plot.frame_attributes import PlotFrame
@@ -76,7 +81,11 @@ class MainWindow(QWidget): # pylint: disable=R0903
76
81
 
77
82
 
78
83
  def main():
79
- print("SEMapp launched")
84
+ """
85
+ Main entry point for the SEMapp application.
86
+
87
+ Creates and displays the main window, then starts the Qt event loop.
88
+ """
80
89
  app = QApplication(sys.argv)
81
90
  window = MainWindow()
82
91
  window.show()