nettracer3d 0.8.2__py3-none-any.whl → 0.8.4__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 nettracer3d might be problematic. Click here for more details.

@@ -462,7 +462,6 @@ def get_color_name_mapping():
462
462
  'bright_cyan': (0, 255, 255),
463
463
  'dark_teal': (0, 128, 128),
464
464
  'turquoise': (64, 224, 208),
465
- 'aqua': (0, 255, 255),
466
465
  'seafoam': (159, 226, 191),
467
466
  'teal_blue': (54, 117, 136),
468
467
 
@@ -517,21 +516,90 @@ def rgb_to_color_name(rgb: Tuple[int, int, int]) -> str:
517
516
  distance = np.sqrt(np.sum((rgb_array - np.array(color_rgb)) ** 2))
518
517
  if distance < min_distance:
519
518
  min_distance = distance
520
- closest_color = color_name + f" {str(rgb_array)}"
521
-
519
+ #closest_color = color_name + f" {str(rgb_array)}" # <- if we want RGB names
520
+ closest_color = color_name
521
+
522
522
  return closest_color
523
523
 
524
- def convert_node_colors_to_names(node_to_color: Dict[int, Tuple[int, int, int]]) -> Dict[int, str]:
524
+ def convert_node_colors_to_names(node_to_color: Dict[int, Tuple[int, int, int]],
525
+ show_legend: bool = True,
526
+ figsize: Tuple[int, int] = (10, 8),
527
+ save_path: str = None) -> Dict[int, str]:
525
528
  """
526
529
  Convert a dictionary of node-to-RGB mappings to node-to-color-name mappings.
530
+ Optionally displays a matplotlib legend showing the mappings.
527
531
 
528
532
  Args:
529
533
  node_to_color: Dictionary mapping node IDs to RGB tuples
534
+ show_legend: Whether to display the color legend plot
535
+ figsize: Figure size as (width, height) for the legend
536
+ save_path: Optional path to save the legend figure
530
537
 
531
538
  Returns:
532
539
  Dictionary mapping node IDs to color names
533
540
  """
534
- return {node: rgb_to_color_name(color) for node, color in node_to_color.items()}
541
+ # Convert colors to names
542
+ node_to_names = {node: rgb_to_color_name(color) for node, color in node_to_color.items()}
543
+
544
+ # Create legend if requested
545
+ if show_legend:
546
+ import matplotlib.pyplot as plt
547
+ from matplotlib.patches import Rectangle
548
+
549
+ num_entries = len(node_to_color)
550
+
551
+ # Calculate dynamic spacing based on number of entries
552
+ entry_height = 0.8
553
+ total_height = num_entries * entry_height + 1.5 # Extra space for title and margins
554
+
555
+ # Create figure and axis with proper scaling
556
+ fig, ax = plt.subplots(figsize=figsize)
557
+ ax.set_xlim(0, 10)
558
+ ax.set_ylim(0, total_height)
559
+ ax.axis('off')
560
+
561
+ # Title
562
+ ax.text(5, total_height - 0.5, 'Color Legend',
563
+ fontsize=16, fontweight='bold', ha='center')
564
+
565
+ # Sort nodes for consistent display
566
+ sorted_nodes = sorted(node_to_color.keys())
567
+
568
+ # Create legend entries
569
+ for i, node in enumerate(sorted_nodes):
570
+ y_pos = total_height - (i + 1) * entry_height - 0.8
571
+ rgb = node_to_color[node]
572
+ color_name = node_to_names[node]
573
+
574
+ # Normalize RGB values for matplotlib (0-1 range)
575
+ norm_rgb = tuple(c/255.0 for c in rgb)
576
+
577
+ # Draw color swatch (using actual RGB values)
578
+ swatch = Rectangle((1.0, y_pos - 0.15), 0.8, 0.3,
579
+ facecolor=norm_rgb, edgecolor='black', linewidth=1)
580
+ ax.add_patch(swatch)
581
+
582
+ # Node ID (exactly as it appears in dict keys)
583
+ ax.text(0.2, y_pos, str(node), fontsize=12, fontweight='bold',
584
+ va='center', ha='left')
585
+
586
+ # Color name (mapped name, nicely formatted)
587
+ ax.text(2.2, y_pos, color_name.replace('_', ' ').title(),
588
+ fontsize=11, va='center', ha='left')
589
+
590
+ # Add border around the legend
591
+ border = Rectangle((0.1, 0.1), 9.8, total_height - 0.2,
592
+ fill=False, edgecolor='gray', linewidth=2)
593
+ ax.add_patch(border)
594
+
595
+ plt.tight_layout()
596
+
597
+ if save_path:
598
+ plt.savefig(save_path, dpi=300, bbox_inches='tight')
599
+
600
+ plt.show()
601
+
602
+ return node_to_names
535
603
 
536
604
  def generate_distinct_colors(n_colors: int) -> List[Tuple[int, int, int]]:
537
605
  """
@@ -596,7 +664,7 @@ def assign_node_colors(node_list: List[int], labeled_array: np.ndarray) -> Tuple
596
664
 
597
665
  # Convert colors for naming
598
666
  node_to_color_rgb = {k: tuple(v[:3]) for k, v in node_to_color.items()}
599
- node_to_color_names = convert_node_colors_to_names(node_to_color_rgb)
667
+ node_to_color_names = convert_node_colors_to_names(node_to_color_rgb, show_legend = False)
600
668
 
601
669
  return rgba_array, node_to_color_names
602
670
 
nettracer3d/excelotron.py CHANGED
@@ -1238,7 +1238,7 @@ class TabbedIdentityWidget(QFrame):
1238
1238
 
1239
1239
  class ExcelToDictGUI(QMainWindow):
1240
1240
  # Add this signal
1241
- data_exported = pyqtSignal(dict, str) # dictionary, property_name
1241
+ data_exported = pyqtSignal(dict, str, bool) # dictionary, property_name, add_status
1242
1242
 
1243
1243
  def __init__(self):
1244
1244
  super().__init__()
@@ -1255,6 +1255,7 @@ class ExcelToDictGUI(QMainWindow):
1255
1255
 
1256
1256
  self.setWindowTitle("Excel to Python Dictionary Converter")
1257
1257
  self.setGeometry(100, 100, 1200, 800)
1258
+ self.add = False
1258
1259
 
1259
1260
  self.setup_ui()
1260
1261
 
@@ -1414,6 +1415,14 @@ class ExcelToDictGUI(QMainWindow):
1414
1415
  self.export_btn.clicked.connect(self.export_dictionary)
1415
1416
  export_layout.addWidget(self.export_btn)
1416
1417
 
1418
+ self.add_button = QPushButton("+")
1419
+ self.add_button.setFixedSize(20, 20)
1420
+ self.add_button.setCheckable(True)
1421
+ self.add_button.setChecked(False)
1422
+ self.add_button.clicked.connect(self.toggle_add)
1423
+ export_layout.addWidget(self.add_button)
1424
+
1425
+
1417
1426
  right_layout.addLayout(export_layout)
1418
1427
 
1419
1428
  right_widget.setLayout(right_layout)
@@ -1431,6 +1440,15 @@ class ExcelToDictGUI(QMainWindow):
1431
1440
  # Add splitter to main layout
1432
1441
  main_layout.addWidget(splitter)
1433
1442
 
1443
+ def toggle_add(self):
1444
+
1445
+ if self.add_button.isChecked():
1446
+ print("Exported Properties will be added onto existing ones")
1447
+ self.add = True
1448
+ else:
1449
+ print("Exported Properties will be override existing ones")
1450
+ self.add = False
1451
+
1434
1452
  def load_template(self, template_name):
1435
1453
  if template_name in self.templates:
1436
1454
  # Clear existing columns
@@ -1681,12 +1699,13 @@ class ExcelToDictGUI(QMainWindow):
1681
1699
  return
1682
1700
 
1683
1701
  # Emit signal to parent application
1684
- self.data_exported.emit(result_dict, property_name)
1702
+ self.data_exported.emit(result_dict, property_name, self.add)
1685
1703
 
1686
1704
  # Still store in global variables for backward compatibility
1687
1705
  import builtins
1688
1706
  builtins.excel_dict = result_dict
1689
1707
  builtins.target_property = property_name
1708
+ builtins.add = self.add
1690
1709
 
1691
1710
  # Show success message with preview
1692
1711
  preview = str(result_dict)