nettracer3d 0.8.0__py3-none-any.whl → 0.8.2__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.

@@ -0,0 +1,161 @@
1
+ import subprocess
2
+ import sys
3
+ import threading
4
+ from pathlib import Path
5
+ from PyQt6.QtWidgets import QMessageBox, QWidget
6
+
7
+ class CellposeGUILauncher:
8
+ """Simple launcher for cellpose GUI in PyQt6 applications."""
9
+
10
+ def __init__(self, parent_widget=None):
11
+ """
12
+ Initialize the launcher.
13
+
14
+ Args:
15
+ parent_widget: PyQt6 widget for showing message boxes (optional)
16
+ """
17
+ self.parent_widget = parent_widget
18
+ self.cellpose_process = None
19
+
20
+ def launch_cellpose_gui(self, image_path=None, working_directory=None):
21
+ """
22
+ Launch cellpose GUI in a separate thread.
23
+
24
+ Args:
25
+ image_path (str, optional): Path to image file to load automatically
26
+ working_directory (str, optional): Directory to start cellpose in
27
+
28
+ Returns:
29
+ bool: True if launch was initiated successfully
30
+ """
31
+ def run_cellpose():
32
+ """Function to run in separate thread."""
33
+ try:
34
+ # Build command
35
+ cmd = [sys.executable, "-m", "cellpose"]
36
+
37
+ # Add image path if provided
38
+ if image_path and Path(image_path).exists():
39
+ cmd.extend(["--image_path", str(image_path)])
40
+
41
+ # Set working directory
42
+ cwd = working_directory if working_directory else None
43
+
44
+ # Launch cellpose GUI
45
+ self.cellpose_process = subprocess.Popen(
46
+ cmd,
47
+ cwd=cwd,
48
+ stdout=subprocess.PIPE,
49
+ stderr=subprocess.PIPE
50
+ )
51
+
52
+ # Optional: wait for process to complete
53
+ # self.cellpose_process.wait()
54
+
55
+ except Exception as e:
56
+ if self.parent_widget:
57
+ # Show error in main thread
58
+ self.show_error(f"Failed to launch cellpose GUI: {str(e)}")
59
+ else:
60
+ print(f"Failed to launch cellpose GUI: {str(e)}")
61
+
62
+ try:
63
+ # Start cellpose in separate thread
64
+ thread = threading.Thread(target=run_cellpose, daemon=True)
65
+ thread.start()
66
+
67
+ if self.parent_widget:
68
+ self.show_info("Cellpose GUI launched!")
69
+ else:
70
+ print("Cellpose GUI launched!")
71
+
72
+ return True
73
+
74
+ except Exception as e:
75
+ if self.parent_widget:
76
+ self.show_error(f"Failed to start cellpose thread: {str(e)}")
77
+ else:
78
+ print(f"Failed to start cellpose thread: {str(e)}")
79
+ return False
80
+
81
+ def launch_with_directory(self, directory_path):
82
+ """
83
+ Launch cellpose GUI with a specific directory.
84
+
85
+ Args:
86
+ directory_path (str): Directory containing images
87
+ """
88
+ cmd_args = ["--dir", str(directory_path)]
89
+ return self.launch_cellpose_gui_with_args(cmd_args, working_directory=directory_path)
90
+
91
+ def launch_cellpose_gui_with_args(self, additional_args=None, working_directory=None):
92
+ """
93
+ Launch cellpose GUI with custom arguments.
94
+
95
+ Args:
96
+ additional_args (list): List of additional command line arguments
97
+ working_directory (str): Working directory for cellpose
98
+ """
99
+ def run_cellpose_custom():
100
+ try:
101
+ cmd = [sys.executable, "-m", "cellpose"]
102
+
103
+ if additional_args:
104
+ cmd.extend(additional_args)
105
+
106
+ cwd = working_directory if working_directory else None
107
+
108
+ self.cellpose_process = subprocess.Popen(
109
+ cmd,
110
+ cwd=cwd,
111
+ stdout=subprocess.PIPE,
112
+ stderr=subprocess.PIPE
113
+ )
114
+
115
+ except Exception as e:
116
+ if self.parent_widget:
117
+ self.show_error(f"Failed to launch cellpose GUI: {str(e)}")
118
+ else:
119
+ print(f"Failed to launch cellpose GUI: {str(e)}")
120
+
121
+ try:
122
+ thread = threading.Thread(target=run_cellpose_custom, daemon=True)
123
+ thread.start()
124
+ return True
125
+ except Exception as e:
126
+ if self.parent_widget:
127
+ self.show_error(f"Failed to start cellpose: {str(e)}")
128
+ return False
129
+
130
+ def is_cellpose_running(self):
131
+ """
132
+ Check if cellpose process is still running.
133
+
134
+ Returns:
135
+ bool: True if cellpose is still running
136
+ """
137
+ if self.cellpose_process is None:
138
+ return False
139
+
140
+ return self.cellpose_process.poll() is None
141
+
142
+ def close_cellpose(self):
143
+ """Terminate the cellpose process if running."""
144
+ if self.cellpose_process and self.is_cellpose_running():
145
+ try:
146
+ self.cellpose_process.terminate()
147
+ self.cellpose_process.wait(timeout=5) # Wait up to 5 seconds
148
+ except subprocess.TimeoutExpired:
149
+ self.cellpose_process.kill() # Force kill if it doesn't terminate
150
+ except Exception as e:
151
+ print(f"Error closing cellpose: {e}")
152
+
153
+ def show_info(self, message):
154
+ """Show info message if parent widget available."""
155
+ if self.parent_widget:
156
+ QMessageBox.information(self.parent_widget, "Cellpose Launcher", message)
157
+
158
+ def show_error(self, message):
159
+ """Show error message if parent widget available."""
160
+ if self.parent_widget:
161
+ QMessageBox.critical(self.parent_widget, "Cellpose Error", message)
@@ -393,28 +393,105 @@ def find_hub_nodes(G: nx.Graph, proportion: float = 0.1) -> List:
393
393
  return output
394
394
 
395
395
  def get_color_name_mapping():
396
- """Return a dictionary of common colors and their RGB values."""
396
+ """Return a dictionary of descriptive color names and their RGB values."""
397
397
  return {
398
- 'red': (255, 0, 0),
399
- 'green': (0, 255, 0),
400
- 'blue': (0, 0, 255),
401
- 'yellow': (255, 255, 0),
402
- 'cyan': (0, 255, 255),
398
+ # Reds
399
+ 'crimson_red': (220, 20, 60),
400
+ 'bright_red': (255, 0, 0),
401
+ 'dark_red': (139, 0, 0),
402
+ 'coral_red': (255, 127, 80),
403
+ 'rose_red': (255, 102, 102),
404
+ 'burgundy': (128, 0, 32),
405
+ 'cherry_red': (222, 49, 99),
406
+
407
+ # Greens
408
+ 'forest_green': (34, 139, 34),
409
+ 'lime_green': (50, 205, 50),
410
+ 'bright_green': (0, 255, 0),
411
+ 'dark_green': (0, 100, 0),
412
+ 'mint_green': (152, 255, 152),
413
+ 'sage_green': (159, 183, 121),
414
+ 'emerald_green': (80, 200, 120),
415
+ 'olive_green': (128, 128, 0),
416
+
417
+ # Blues
418
+ 'royal_blue': (65, 105, 225),
419
+ 'bright_blue': (0, 0, 255),
420
+ 'navy_blue': (0, 0, 128),
421
+ 'sky_blue': (135, 206, 235),
422
+ 'steel_blue': (70, 130, 180),
423
+ 'powder_blue': (176, 224, 230),
424
+ 'midnight_blue': (25, 25, 112),
425
+ 'cobalt_blue': (0, 71, 171),
426
+
427
+ # Purples
428
+ 'deep_purple': (75, 0, 130),
429
+ 'royal_purple': (120, 81, 169),
430
+ 'lavender': (230, 230, 250),
431
+ 'plum_purple': (221, 160, 221),
432
+ 'violet_purple': (238, 130, 238),
403
433
  'magenta': (255, 0, 255),
404
- 'purple': (128, 0, 128),
405
- 'orange': (255, 165, 0),
406
- 'brown': (165, 42, 42),
407
- 'pink': (255, 192, 203),
408
- 'navy': (0, 0, 128),
409
- 'teal': (0, 128, 128),
410
- 'olive': (128, 128, 0),
411
- 'maroon': (128, 0, 0),
412
- 'lime': (50, 205, 50),
413
- 'indigo': (75, 0, 130),
414
- 'violet': (238, 130, 238),
415
- 'coral': (255, 127, 80),
434
+ 'orchid': (218, 112, 214),
435
+
436
+ # Yellows & Golds
437
+ 'bright_yellow': (255, 255, 0),
438
+ 'golden_yellow': (255, 215, 0),
439
+ 'lemon_yellow': (255, 247, 0),
440
+ 'amber': (255, 191, 0),
441
+ 'mustard_yellow': (255, 219, 88),
442
+ 'cream': (255, 253, 208),
443
+ 'wheat': (245, 222, 179),
444
+
445
+ # Oranges
446
+ 'bright_orange': (255, 165, 0),
447
+ 'burnt_orange': (204, 85, 0),
448
+ 'peach': (255, 218, 185),
449
+ 'tangerine': (255, 163, 67),
450
+ 'pumpkin_orange': (255, 117, 24),
451
+ 'apricot': (251, 206, 177),
452
+
453
+ # Pinks
454
+ 'hot_pink': (255, 105, 180),
455
+ 'light_pink': (255, 192, 203),
456
+ 'deep_pink': (255, 20, 147),
457
+ 'salmon_pink': (250, 128, 114),
458
+ 'blush_pink': (255, 182, 193),
459
+ 'fuchsia': (255, 0, 255),
460
+
461
+ # Cyans & Teals
462
+ 'bright_cyan': (0, 255, 255),
463
+ 'dark_teal': (0, 128, 128),
416
464
  'turquoise': (64, 224, 208),
417
- 'gold': (255, 215, 0)
465
+ 'aqua': (0, 255, 255),
466
+ 'seafoam': (159, 226, 191),
467
+ 'teal_blue': (54, 117, 136),
468
+
469
+ # Browns & Earth Tones
470
+ 'chocolate_brown': (210, 105, 30),
471
+ 'saddle_brown': (139, 69, 19),
472
+ 'light_brown': (205, 133, 63),
473
+ 'tan': (210, 180, 140),
474
+ 'beige': (245, 245, 220),
475
+ 'coffee_brown': (111, 78, 55),
476
+ 'rust_brown': (183, 65, 14),
477
+
478
+ # Grays & Neutrals
479
+ 'charcoal_gray': (54, 69, 79),
480
+ 'light_gray': (211, 211, 211),
481
+ 'silver': (192, 192, 192),
482
+ 'slate_gray': (112, 128, 144),
483
+ 'ash_gray': (178, 190, 181),
484
+ 'smoke_gray': (152, 152, 152),
485
+
486
+ # Additional Distinctive Colors
487
+ 'lime_yellow': (191, 255, 0),
488
+ 'electric_blue': (125, 249, 255),
489
+ 'neon_green': (57, 255, 20),
490
+ 'wine_red': (114, 47, 55),
491
+ 'copper': (184, 115, 51),
492
+ 'ivory': (255, 255, 240),
493
+ 'periwinkle': (204, 204, 255),
494
+ 'mint': (189, 252, 201)
418
495
  }
419
496
 
420
497
  def rgb_to_color_name(rgb: Tuple[int, int, int]) -> str:
@@ -440,7 +517,7 @@ def rgb_to_color_name(rgb: Tuple[int, int, int]) -> str:
440
517
  distance = np.sqrt(np.sum((rgb_array - np.array(color_rgb)) ** 2))
441
518
  if distance < min_distance:
442
519
  min_distance = distance
443
- closest_color = color_name
520
+ closest_color = color_name + f" {str(rgb_array)}"
444
521
 
445
522
  return closest_color
446
523