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.
- nettracer3d/community_extractor.py +74 -6
- nettracer3d/excelotron.py +21 -2
- nettracer3d/nettracer.py +506 -79
- nettracer3d/nettracer_gui.py +605 -139
- nettracer3d/network_analysis.py +90 -29
- nettracer3d/node_draw.py +6 -2
- nettracer3d/proximity.py +50 -101
- nettracer3d/smart_dilate.py +44 -10
- {nettracer3d-0.8.2.dist-info → nettracer3d-0.8.4.dist-info}/METADATA +3 -8
- nettracer3d-0.8.4.dist-info/RECORD +24 -0
- nettracer3d-0.8.2.dist-info/RECORD +0 -24
- {nettracer3d-0.8.2.dist-info → nettracer3d-0.8.4.dist-info}/WHEEL +0 -0
- {nettracer3d-0.8.2.dist-info → nettracer3d-0.8.4.dist-info}/entry_points.txt +0 -0
- {nettracer3d-0.8.2.dist-info → nettracer3d-0.8.4.dist-info}/licenses/LICENSE +0 -0
- {nettracer3d-0.8.2.dist-info → nettracer3d-0.8.4.dist-info}/top_level.txt +0 -0
|
@@ -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]]
|
|
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
|
-
|
|
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)
|