driftlessmap 1.1.0__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.
Files changed (210) hide show
  1. driftlessmap/__init__.py +16 -0
  2. driftlessmap/__main__.py +5 -0
  3. driftlessmap/about.py +24 -0
  4. driftlessmap/allen_downloader.py +908 -0
  5. driftlessmap/app.py +8085 -0
  6. driftlessmap/atlas_downloader.py +370 -0
  7. driftlessmap/atlas_loader.py +526 -0
  8. driftlessmap/atlas_processor.py +784 -0
  9. driftlessmap/atlas_transform.py +111 -0
  10. driftlessmap/atlas_view.py +1435 -0
  11. driftlessmap/cell_detection.py +27 -0
  12. driftlessmap/coordinate_validation.py +19 -0
  13. driftlessmap/czi_reader.py +236 -0
  14. driftlessmap/data/WHS_atlas_labels.pkl +0 -0
  15. driftlessmap/data/allen_mice_atlas_labels.pkl +0 -0
  16. driftlessmap/data/atlas_labels.pkl +0 -0
  17. driftlessmap/data/query.csv +1328 -0
  18. driftlessmap/download_utils.py +85 -0
  19. driftlessmap/herbs.png +0 -0
  20. driftlessmap/icons/backward.svg +15 -0
  21. driftlessmap/icons/dot.svg +11 -0
  22. driftlessmap/icons/down-arrow.svg +10 -0
  23. driftlessmap/icons/fast_backward.svg +14 -0
  24. driftlessmap/icons/fast_forward.svg +14 -0
  25. driftlessmap/icons/forward.svg +14 -0
  26. driftlessmap/icons/layers/add.png +0 -0
  27. driftlessmap/icons/layers/ai.png +0 -0
  28. driftlessmap/icons/layers/eye_off.png +0 -0
  29. driftlessmap/icons/layers/eye_on.png +0 -0
  30. driftlessmap/icons/layers/eye_white.png +0 -0
  31. driftlessmap/icons/layers/hi.png +0 -0
  32. driftlessmap/icons/layers/trash.png +0 -0
  33. driftlessmap/icons/object.svg +22 -0
  34. driftlessmap/icons/sidebar/add.png +0 -0
  35. driftlessmap/icons/sidebar/atlascontrol.png +0 -0
  36. driftlessmap/icons/sidebar/atlascontrol.svg +32 -0
  37. driftlessmap/icons/sidebar/bnd.svg +14 -0
  38. driftlessmap/icons/sidebar/c_section.png +0 -0
  39. driftlessmap/icons/sidebar/c_section2.png +0 -0
  40. driftlessmap/icons/sidebar/cell.svg +24 -0
  41. driftlessmap/icons/sidebar/check.svg +9 -0
  42. driftlessmap/icons/sidebar/compare.svg +18 -0
  43. driftlessmap/icons/sidebar/contour.svg +14 -0
  44. driftlessmap/icons/sidebar/h_section.png +0 -0
  45. driftlessmap/icons/sidebar/info.svg +14 -0
  46. driftlessmap/icons/sidebar/layers.png +0 -0
  47. driftlessmap/icons/sidebar/layers.svg +23 -0
  48. driftlessmap/icons/sidebar/line.svg +10 -0
  49. driftlessmap/icons/sidebar/link.svg +18 -0
  50. driftlessmap/icons/sidebar/link_off.svg +18 -0
  51. driftlessmap/icons/sidebar/merge.svg +11 -0
  52. driftlessmap/icons/sidebar/object.svg +13 -0
  53. driftlessmap/icons/sidebar/probe.png +0 -0
  54. driftlessmap/icons/sidebar/probe.svg +23 -0
  55. driftlessmap/icons/sidebar/rotation_horizontal.svg +14 -0
  56. driftlessmap/icons/sidebar/rotation_vertical.svg +14 -0
  57. driftlessmap/icons/sidebar/s_section.png +0 -0
  58. driftlessmap/icons/sidebar/tool.png +0 -0
  59. driftlessmap/icons/sidebar/tool.svg +19 -0
  60. driftlessmap/icons/sidebar/trash.png +0 -0
  61. driftlessmap/icons/sidebar/tree_checked.svg +10 -0
  62. driftlessmap/icons/sidebar/treeview.png +0 -0
  63. driftlessmap/icons/sidebar/treeview.svg +10 -0
  64. driftlessmap/icons/sidebar/treeview2.png +0 -0
  65. driftlessmap/icons/sidebar/virus.svg +24 -0
  66. driftlessmap/icons/tdown.svg +16 -0
  67. driftlessmap/icons/toolbar/accept.svg +18 -0
  68. driftlessmap/icons/toolbar/accept2.svg +24 -0
  69. driftlessmap/icons/toolbar/aim.svg +44 -0
  70. driftlessmap/icons/toolbar/aim_not.svg +28 -0
  71. driftlessmap/icons/toolbar/anchor.svg +14 -0
  72. driftlessmap/icons/toolbar/anticlockwise_rotation.svg +12 -0
  73. driftlessmap/icons/toolbar/atlas_icon.png +0 -0
  74. driftlessmap/icons/toolbar/boundary_register.svg +18 -0
  75. driftlessmap/icons/toolbar/cancel.svg +32 -0
  76. driftlessmap/icons/toolbar/cell_select.svg +22 -0
  77. driftlessmap/icons/toolbar/cell_select_not.svg +12 -0
  78. driftlessmap/icons/toolbar/check.svg +9 -0
  79. driftlessmap/icons/toolbar/clockwise_rotation.svg +11 -0
  80. driftlessmap/icons/toolbar/closed_path.svg +16 -0
  81. driftlessmap/icons/toolbar/closed_path2 copy.svg +19 -0
  82. driftlessmap/icons/toolbar/closed_path2.svg +20 -0
  83. driftlessmap/icons/toolbar/eraser.png +0 -0
  84. driftlessmap/icons/toolbar/eraser.svg +19 -0
  85. driftlessmap/icons/toolbar/eye.svg +17 -0
  86. driftlessmap/icons/toolbar/eye_closed.svg +19 -0
  87. driftlessmap/icons/toolbar/fill.svg +12 -0
  88. driftlessmap/icons/toolbar/gps.svg +15 -0
  89. driftlessmap/icons/toolbar/h_flip.png +0 -0
  90. driftlessmap/icons/toolbar/handle.png +0 -0
  91. driftlessmap/icons/toolbar/image_icon.png +0 -0
  92. driftlessmap/icons/toolbar/image_icon.svg +25 -0
  93. driftlessmap/icons/toolbar/info.svg +14 -0
  94. driftlessmap/icons/toolbar/inpart.png +0 -0
  95. driftlessmap/icons/toolbar/inpart.svg +17 -0
  96. driftlessmap/icons/toolbar/lasso.png +0 -0
  97. driftlessmap/icons/toolbar/lasso.svg +14 -0
  98. driftlessmap/icons/toolbar/left90.png +0 -0
  99. driftlessmap/icons/toolbar/line.svg +10 -0
  100. driftlessmap/icons/toolbar/line_sites.svg +11 -0
  101. driftlessmap/icons/toolbar/linear_silicon.png +0 -0
  102. driftlessmap/icons/toolbar/linear_silicon.svg +88 -0
  103. driftlessmap/icons/toolbar/list.svg +14 -0
  104. driftlessmap/icons/toolbar/location.svg +14 -0
  105. driftlessmap/icons/toolbar/magic-wand.svg +16 -0
  106. driftlessmap/icons/toolbar/magic_white.png +0 -0
  107. driftlessmap/icons/toolbar/mask.svg +10 -0
  108. driftlessmap/icons/toolbar/match.svg +20 -0
  109. driftlessmap/icons/toolbar/matchbnd.svg +18 -0
  110. driftlessmap/icons/toolbar/matching.svg +36 -0
  111. driftlessmap/icons/toolbar/merge.svg +11 -0
  112. driftlessmap/icons/toolbar/move_down.png +0 -0
  113. driftlessmap/icons/toolbar/move_left.png +0 -0
  114. driftlessmap/icons/toolbar/move_right.png +0 -0
  115. driftlessmap/icons/toolbar/move_up.png +0 -0
  116. driftlessmap/icons/toolbar/moving.png +0 -0
  117. driftlessmap/icons/toolbar/multi-probe.svg +119 -0
  118. driftlessmap/icons/toolbar/multi_pencil.svg +23 -0
  119. driftlessmap/icons/toolbar/multi_probe.png +0 -0
  120. driftlessmap/icons/toolbar/object.svg +13 -0
  121. driftlessmap/icons/toolbar/open_path.svg +22 -0
  122. driftlessmap/icons/toolbar/outpart.png +0 -0
  123. driftlessmap/icons/toolbar/outpart.svg +26 -0
  124. driftlessmap/icons/toolbar/pencil.png +0 -0
  125. driftlessmap/icons/toolbar/pencil.svg +19 -0
  126. driftlessmap/icons/toolbar/plasso.png +0 -0
  127. driftlessmap/icons/toolbar/probe.svg +19 -0
  128. driftlessmap/icons/toolbar/radar.svg +32 -0
  129. driftlessmap/icons/toolbar/rotation.svg +45 -0
  130. driftlessmap/icons/toolbar/rotation_clockwise.svg +18 -0
  131. driftlessmap/icons/toolbar/rotation_counter_clockwise.svg +18 -0
  132. driftlessmap/icons/toolbar/ruler.svg +27 -0
  133. driftlessmap/icons/toolbar/separate_sites.svg +13 -0
  134. driftlessmap/icons/toolbar/single_pencil.svg +16 -0
  135. driftlessmap/icons/toolbar/toa.svg +11 -0
  136. driftlessmap/icons/toolbar/toa_delete.svg +36 -0
  137. driftlessmap/icons/toolbar/toaa.svg +11 -0
  138. driftlessmap/icons/toolbar/toh.svg +11 -0
  139. driftlessmap/icons/toolbar/toh_delete.svg +36 -0
  140. driftlessmap/icons/toolbar/tohh.svg +11 -0
  141. driftlessmap/icons/toolbar/trans.png +0 -0
  142. driftlessmap/icons/toolbar/trans.svg +16 -0
  143. driftlessmap/icons/toolbar/triangulation.svg +10 -0
  144. driftlessmap/icons/toolbar/two_window.png +0 -0
  145. driftlessmap/icons/toolbar/unmerge.svg +16 -0
  146. driftlessmap/icons/toolbar/v_flip.png +0 -0
  147. driftlessmap/icons/toolbar/virus.svg +24 -0
  148. driftlessmap/icons/toolbar/virus_register.svg +31 -0
  149. driftlessmap/icons/toolbar/vis2d.svg +29 -0
  150. driftlessmap/icons/toolbar/window2.png +0 -0
  151. driftlessmap/icons/toolbar/window3.png +0 -0
  152. driftlessmap/icons/toolbar/window4.png +0 -0
  153. driftlessmap/icons/tree_close.svg +14 -0
  154. driftlessmap/icons/tree_open.svg +14 -0
  155. driftlessmap/icons/up-arrow.svg +10 -0
  156. driftlessmap/image_curves.py +579 -0
  157. driftlessmap/image_reader.py +186 -0
  158. driftlessmap/image_stacks.py +359 -0
  159. driftlessmap/image_view.py +646 -0
  160. driftlessmap/images_reader.py +5 -0
  161. driftlessmap/label_tree.py +278 -0
  162. driftlessmap/layer_validation.py +25 -0
  163. driftlessmap/layers_control.py +554 -0
  164. driftlessmap/main_window.ui +883 -0
  165. driftlessmap/movable_points.py +254 -0
  166. driftlessmap/obj_items.py +122 -0
  167. driftlessmap/object_control.py +1762 -0
  168. driftlessmap/persistence.py +376 -0
  169. driftlessmap/popup_message.py +16 -0
  170. driftlessmap/probe_csv.py +319 -0
  171. driftlessmap/probe_reconstruction.py +409 -0
  172. driftlessmap/probe_utiles.py +1442 -0
  173. driftlessmap/qss/atlas_view_group_box.qss +15 -0
  174. driftlessmap/qss/box_label.qss +7 -0
  175. driftlessmap/qss/channel_selector.qss +19 -0
  176. driftlessmap/qss/color_combo.qss +121 -0
  177. driftlessmap/qss/decor_label.qss +9 -0
  178. driftlessmap/qss/dialogs.qss +11 -0
  179. driftlessmap/qss/hidden_line_edit.qss +5 -0
  180. driftlessmap/qss/label_tree.qss +123 -0
  181. driftlessmap/qss/main_window.qss +243 -0
  182. driftlessmap/qss/menu_bar.qss +42 -0
  183. driftlessmap/qss/multi_handle_slider.qss +14 -0
  184. driftlessmap/qss/obj_ctrl_bottom_button.qss +29 -0
  185. driftlessmap/qss/object_text_button.qss +19 -0
  186. driftlessmap/qss/page_control.qss +36 -0
  187. driftlessmap/qss/rotation_button.qss +9 -0
  188. driftlessmap/qss/side_bar.qss +23 -0
  189. driftlessmap/qss/spinbox.qss +106 -0
  190. driftlessmap/qss/tabs.qss +211 -0
  191. driftlessmap/qss/tool_bar.qss +77 -0
  192. driftlessmap/resources.py +34 -0
  193. driftlessmap/roi_analysis.py +375 -0
  194. driftlessmap/run_driftlessmap.py +4 -0
  195. driftlessmap/slice_stacks.py +268 -0
  196. driftlessmap/slice_validation.py +20 -0
  197. driftlessmap/toolbox.py +569 -0
  198. driftlessmap/triangulation.py +517 -0
  199. driftlessmap/triangulation_points.py +108 -0
  200. driftlessmap/user_settings.py +92 -0
  201. driftlessmap/uuuuuu.py +1168 -0
  202. driftlessmap/version.py +3 -0
  203. driftlessmap/widgets_utils.py +140 -0
  204. driftlessmap/wtiles.py +715 -0
  205. driftlessmap-1.1.0.dist-info/METADATA +186 -0
  206. driftlessmap-1.1.0.dist-info/RECORD +210 -0
  207. driftlessmap-1.1.0.dist-info/WHEEL +5 -0
  208. driftlessmap-1.1.0.dist-info/entry_points.txt +2 -0
  209. driftlessmap-1.1.0.dist-info/licenses/LICENSE.txt +23 -0
  210. driftlessmap-1.1.0.dist-info/top_level.txt +1 -0
driftlessmap/wtiles.py ADDED
@@ -0,0 +1,715 @@
1
+ from PyQt6.QtWidgets import *
2
+ from PyQt6.QtCore import *
3
+ from PyQt6.QtGui import *
4
+ import numpy as np
5
+ from .uuuuuu import read_qss_file
6
+ from .resources import resource_path
7
+
8
+ dialog_style = '''
9
+ QDialog {
10
+ background-color: rgb(50, 50, 50);
11
+ color: white;
12
+ font-size: 12px;
13
+ width: 50px;
14
+ }
15
+
16
+ QLabel {
17
+ color: white;
18
+ width: 50px;
19
+ }
20
+ '''
21
+
22
+
23
+ class LayerSettingDialog(QDialog):
24
+ def __init__(self, window_name, min_val, max_val, val):
25
+ super().__init__()
26
+
27
+ self.setWindowTitle(window_name)
28
+ self.setStyleSheet(dialog_style)
29
+
30
+ self.val = val
31
+
32
+ self.val_slider = QSlider(Qt.Orientation.Horizontal)
33
+ self.val_slider.setValue(val)
34
+ self.val_slider.setMinimum(min_val)
35
+ self.val_slider.setMaximum(max_val)
36
+ self.val_slider.setSingleStep(1)
37
+ self.val_slider.sliderMoved.connect(self.val_spinbox_changed)
38
+
39
+ self.val_spinbox = QSpinBox()
40
+ self.val_spinbox.setValue(val)
41
+ self.val_spinbox.setMaximum(max_val)
42
+ self.val_spinbox.setMinimum(min_val)
43
+ self.val_spinbox.setSingleStep(1)
44
+ self.val_spinbox.valueChanged.connect(self.value_changed)
45
+
46
+ # ok button, used to close window
47
+ ok_btn = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok)
48
+ ok_btn.accepted.connect(self.accept)
49
+
50
+ # add widget to layout
51
+ layout = QHBoxLayout()
52
+ layout.addWidget(self.val_slider)
53
+ layout.addWidget(self.val_spinbox)
54
+ layout.addSpacing(10)
55
+ layout.addWidget(ok_btn)
56
+ self.setLayout(layout)
57
+
58
+ def accept(self) -> None:
59
+ self.close()
60
+
61
+ def val_spinbox_changed(self):
62
+ val = self.val_slider.value()
63
+ self.val = val
64
+ self.val_spinbox.setValue(val)
65
+
66
+ def value_changed(self):
67
+ val = self.val_spinbox.value()
68
+ self.val = val
69
+ self.val_slider.setValue(val)
70
+
71
+
72
+ class SliceSettingDialog(QDialog):
73
+ def __init__(self):
74
+ super().__init__()
75
+
76
+ self.setWindowTitle('Current Slice Settings')
77
+ self.setStyleSheet(dialog_style)
78
+
79
+ self.cut = 'Coronal'
80
+ self.width = 0
81
+ self.height = 0
82
+ self.distance = 0
83
+
84
+ self.cut_combo = QComboBox()
85
+ self.cut_combo.addItems(['Coronal', 'Sagittal', 'Horizontal'])
86
+ self.cut_combo.currentIndexChanged.connect(self.cut_changed)
87
+
88
+ width_label = QLabel('Width (mm):')
89
+ height_label = QLabel('Height (mm):')
90
+ distance_label = QLabel('Distance w.r.t. Bregma (mm):')
91
+
92
+ self.width_val = QDoubleSpinBox()
93
+ self.width_val.setValue(0)
94
+ self.width_val.setRange(-50, 50)
95
+ self.width_val.valueChanged.connect(self.width_val_changed)
96
+ self.height_val = QDoubleSpinBox()
97
+ self.height_val.setValue(0)
98
+ self.height_val.setRange(-50, 50)
99
+ self.height_val.valueChanged.connect(self.height_val_changed)
100
+ self.distance_val = QDoubleSpinBox()
101
+ self.distance_val.setValue(0)
102
+ self.distance_val.setRange(-50, 50)
103
+ self.distance_val.valueChanged.connect(self.distance_val_changed)
104
+
105
+ # ok button, used to close window
106
+ ok_btn = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok)
107
+ ok_btn.accepted.connect(self.accept)
108
+
109
+ # add widget to layout
110
+ content_frame = QFrame()
111
+ content_layout = QGridLayout(content_frame)
112
+ content_layout.addWidget(self.cut_combo, 0, 0, 1, 2)
113
+ content_layout.addWidget(width_label, 1, 0, 1, 1)
114
+ content_layout.addWidget(self.width_val, 1, 1, 1, 1)
115
+ content_layout.addWidget(height_label, 2, 0, 1, 1)
116
+ content_layout.addWidget(self.height_val, 2, 1, 1, 1)
117
+ content_layout.addWidget(distance_label, 3, 0, 1, 1)
118
+ content_layout.addWidget(self.distance_val, 3, 1, 1, 1)
119
+
120
+ layout = QVBoxLayout()
121
+ layout.addWidget(content_frame)
122
+ layout.addWidget(ok_btn)
123
+ self.setLayout(layout)
124
+
125
+ def accept(self) -> None:
126
+ self.close()
127
+
128
+ def cut_changed(self):
129
+ self.cut = self.cut_combo.currentText()
130
+
131
+ def width_val_changed(self):
132
+ self.width = self.width_val.value()
133
+
134
+ def height_val_changed(self):
135
+ self.height = self.height_val.value()
136
+
137
+ def distance_val_changed(self):
138
+ self.distance = self.distance_val.value()
139
+
140
+
141
+ class QDoubleButton(QPushButton):
142
+ right_clicked = pyqtSignal()
143
+ left_clicked = pyqtSignal()
144
+ double_clicked = pyqtSignal()
145
+
146
+ def __init__(self, *args, **kwargs):
147
+ super(QDoubleButton, self).__init__(*args, **kwargs)
148
+
149
+ btn_style = read_qss_file('qss/object_text_button.qss')
150
+ self.setStyleSheet(btn_style)
151
+
152
+ self.timer = QTimer()
153
+ self.timer.setSingleShot(True)
154
+ self.timer.setInterval(150)
155
+ self.timer.timeout.connect(self.timeout)
156
+
157
+ self.is_double = False
158
+ self.is_left_click = True
159
+
160
+ self.installEventFilter(self)
161
+
162
+ def eventFilter(self, obj, event):
163
+ if event.type() == QEvent.Type.MouseButtonPress:
164
+ if not self.timer.isActive():
165
+ self.timer.start()
166
+
167
+ self.is_left_click = False
168
+ if event.button() == Qt.MouseButton.LeftButton:
169
+ self.is_left_click = True
170
+
171
+ return True
172
+
173
+ elif event.type() == QEvent.Type.MouseButtonDblClick:
174
+ self.is_double = True
175
+ return True
176
+
177
+ return False
178
+
179
+ def timeout(self):
180
+ if self.is_double:
181
+ self.double_clicked.emit()
182
+ else:
183
+ if self.is_left_click:
184
+ self.left_clicked.emit()
185
+ else:
186
+ self.right_clicked.emit()
187
+
188
+ self.is_double = False
189
+
190
+
191
+ class QLabelClickable(QLabel):
192
+ # doubleClicked = pyqtSignal(object)
193
+ clicked = pyqtSignal(object)
194
+
195
+ def __init__(self, parent=None):
196
+ super(QLabelClickable, self).__init__(parent)
197
+
198
+ def mousePressEvent(self, event):
199
+ self.ultimo = 'Click'
200
+
201
+ def mouseReleaseEvent(self, event):
202
+ if self.ultimo == 'Click':
203
+ QTimer.singleShot(QApplication.instance().doubleClickInterval(),
204
+ self.performSingleClickAction)
205
+ else:
206
+ self.ultimo = 'doubleClick'
207
+ self.clicked.emit(self.ultimo)
208
+
209
+ def mouseDoubleClickEvent(self, event):
210
+ self.ultimo = 'doubleClick'
211
+
212
+ def performSingleClickAction(self):
213
+ if self.ultimo == 'Click':
214
+ self.clicked.emit(self.ultimo)
215
+ self.update()
216
+
217
+
218
+ class QFrameClickable(QFrame):
219
+ clicked = pyqtSignal(object)
220
+
221
+ def __init__(self, parent=None):
222
+ super(QFrameClickable, self).__init__(parent)
223
+
224
+ # def mousePressEvent(self, QMouseEvent):
225
+ # if QMouseEvent.button() == Qt.MouseButton.LeftButton:
226
+ # self.clicked.emit()
227
+ # elif QMouseEvent.button() == Qt.MouseButton.RightButton:
228
+ # self.clicked.emit()
229
+ # self.update()
230
+
231
+ def mousePressEvent(self, event):
232
+ self.ultimo = 'Click'
233
+
234
+ def mouseReleaseEvent(self, event):
235
+ if self.ultimo == 'Click':
236
+ QTimer.singleShot(QApplication.instance().doubleClickInterval(),
237
+ self.performSingleClickAction)
238
+ else:
239
+ self.ultimo = 'doubleClick'
240
+ self.clicked.emit(self.ultimo)
241
+
242
+ def mouseDoubleClickEvent(self, event):
243
+ self.ultimo = 'doubleClick'
244
+
245
+ def performSingleClickAction(self):
246
+ if self.ultimo == 'Click':
247
+ self.clicked.emit(self.ultimo)
248
+ self.update()
249
+
250
+
251
+ class LineEditEntered(QLineEdit):
252
+ sig_return_pressed = pyqtSignal()
253
+
254
+ def __init__(self):
255
+ QLineEdit.__init__(self)
256
+
257
+ def keyPressEvent(self, event):
258
+ super(LineEditEntered, self).keyPressEvent(event)
259
+
260
+ if event.key() == Qt.Key.Key_Return or event.key() == Qt.Key.Key_Enter:
261
+ self.sig_return_pressed.emit()
262
+
263
+
264
+ class IntLineEdit(QLineEdit):
265
+ sig_text_changed = pyqtSignal(object)
266
+ def __init__(self, w_id, text=None, parent=None):
267
+ QLineEdit.__init__(self)
268
+ self.id = w_id
269
+ if text is not None:
270
+ self.setText(text)
271
+ self.setValidator(QIntValidator())
272
+ self.textChanged.connect(self.editing_text)
273
+
274
+ def editing_text(self, text_val):
275
+ self.sig_text_changed.emit((self.id, text_val))
276
+
277
+
278
+ class FaceCombo(QComboBox):
279
+ sig_text_changed = pyqtSignal(object)
280
+ def __init__(self, w_id, parent=None):
281
+ QComboBox.__init__(self)
282
+ self.id = w_id
283
+ self.currentIndexChanged.connect(self.index_changed)
284
+
285
+ def index_changed(self, index):
286
+ self.sig_text_changed.emit((self.id, index))
287
+
288
+
289
+ class LinearSiliconInfoDialog(QDialog):
290
+ def __init__(self, pss):
291
+ super().__init__()
292
+
293
+ self.setWindowTitle('Linear Silicon Probe Geometry Setting Window')
294
+ self.setStyleSheet(dialog_style)
295
+
296
+ btn_box = QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
297
+
298
+ self.button_box = QDialogButtonBox(btn_box)
299
+ self.button_box.accepted.connect(self.accept)
300
+ self.button_box.rejected.connect(self.reject)
301
+
302
+ if pss is None:
303
+ self.probe_settings = {'probe_length': 0,
304
+ 'probe_thickness': 0,
305
+ 'tip_length': 0,
306
+ 'site_height': 0,
307
+ 'site_width': 0,
308
+ 'per_max_sites': [0],
309
+ 'sites_distance': [0],
310
+ 'x_bias': [0],
311
+ 'y_bias': [0]}
312
+ else:
313
+ self.probe_settings = pss
314
+
315
+ n_column = len(self.probe_settings['x_bias'])
316
+
317
+ fig_label = QLabel()
318
+ pixmap = QPixmap(resource_path('icons/toolbar/linear_silicon.png'))
319
+ fig_label.setPixmap(pixmap)
320
+ fig_label.setFixedHeight(300)
321
+
322
+ right_frame = QFrame()
323
+ self.right_layout = QGridLayout(right_frame)
324
+
325
+ probe_length_label = QLabel('A Probe Length (um): ')
326
+ self.probe_length_input = IntLineEdit(0, str(self.probe_settings['probe_length']))
327
+ self.probe_length_input.sig_text_changed.connect(self.probe_length_changed)
328
+
329
+ thickness_label = QLabel('Probe Thickness (um): ')
330
+ self.thickness_input = IntLineEdit(0, str(self.probe_settings['probe_thickness']))
331
+ self.thickness_input.sig_text_changed.connect(self.probe_thickness_changed)
332
+
333
+ tip_length_label = QLabel('B Tip Length (um): ')
334
+ self.tip_length_input = IntLineEdit(0, str(self.probe_settings['tip_length']))
335
+ self.tip_length_input.sig_text_changed.connect(self.tip_length_changed)
336
+
337
+ site_height_label = QLabel('Site Height (um): ')
338
+ self.site_height_input = IntLineEdit(0, str(self.probe_settings['site_height']))
339
+ self.site_height_input.sig_text_changed.connect(self.site_height_changed)
340
+
341
+ site_width_label = QLabel('Site Width (um): ')
342
+ self.site_width_input = IntLineEdit(0, str(self.probe_settings['site_width']))
343
+ self.site_width_input.sig_text_changed.connect(self.site_width_changed)
344
+
345
+ n_column_label = QLabel('Number of columns: ')
346
+ self.n_column_spinbox = QSpinBox()
347
+ self.n_column_spinbox.setRange(1, 10)
348
+ self.n_column_spinbox.setValue(n_column)
349
+
350
+ row_names = [QLabel('Number of Sites: '), QLabel('C Sites Distance (um): '),
351
+ QLabel('D X Bias (um): '), QLabel('E Y Bias (um): ')]
352
+
353
+ self.sites_distance_wl = []
354
+ self.per_max_sites_wl = []
355
+ self.x_bias_wl = []
356
+ self.y_bias_wl = []
357
+ for i in range(n_column):
358
+ self.sites_distance_wl.append(IntLineEdit(i, str(self.probe_settings['sites_distance'][i])))
359
+ self.per_max_sites_wl.append(IntLineEdit(i, str(self.probe_settings['per_max_sites'][i])))
360
+ self.x_bias_wl.append(IntLineEdit(i, str(self.probe_settings['x_bias'][i])))
361
+ self.y_bias_wl.append(IntLineEdit(i, str(self.probe_settings['y_bias'][i])))
362
+ self.sites_distance_wl[-1].sig_text_changed.connect(self.sites_distance_changed)
363
+ self.per_max_sites_wl[-1].sig_text_changed.connect(self.per_max_sites_changed)
364
+ self.x_bias_wl[-1].sig_text_changed.connect(self.x_bias_changed)
365
+ self.y_bias_wl[-1].sig_text_changed.connect(self.y_bias_changed)
366
+
367
+ # connect
368
+ self.n_column_spinbox.valueChanged.connect(self.n_column_changed)
369
+
370
+ self.right_layout.addWidget(probe_length_label, 0, 0, 1, 1)
371
+ self.right_layout.addWidget(self.probe_length_input, 0, 1, 1, 1)
372
+ self.right_layout.addWidget(thickness_label, 1, 0, 1, 1)
373
+ self.right_layout.addWidget(self.thickness_input, 1, 1, 1, 1)
374
+ self.right_layout.addWidget(tip_length_label, 2, 0, 1, 1)
375
+ self.right_layout.addWidget(self.tip_length_input, 2, 1, 1, 1)
376
+ self.right_layout.addWidget(site_height_label, 3, 0, 1, 1)
377
+ self.right_layout.addWidget(self.site_height_input, 3, 1, 1, 1)
378
+ self.right_layout.addWidget(site_width_label, 4, 0, 1, 1)
379
+ self.right_layout.addWidget(self.site_width_input, 4, 1, 1, 1)
380
+
381
+ self.right_layout.addWidget(n_column_label, 5, 0, 1, 1)
382
+ self.right_layout.addWidget(self.n_column_spinbox, 5, 1, 1, 1)
383
+
384
+ for i in range(len(row_names)):
385
+ self.right_layout.addWidget(row_names[i], 6 + i, 0, 1, 1)
386
+
387
+ for j in range(n_column):
388
+ self.right_layout.addWidget(self.per_max_sites_wl[j], 6, j + 1, 1, 1)
389
+ self.right_layout.addWidget(self.sites_distance_wl[j], 7, j + 1, 1, 1)
390
+ self.right_layout.addWidget(self.x_bias_wl[j], 8, j + 1, 1, 1)
391
+ self.right_layout.addWidget(self.y_bias_wl[j], 9, j + 1, 1, 1)
392
+
393
+ out_frame = QFrame()
394
+ out_layout = QHBoxLayout(out_frame)
395
+ out_layout.addWidget(fig_label)
396
+ out_layout.addWidget(right_frame)
397
+
398
+ # add widget to layout
399
+ layout = QVBoxLayout()
400
+ layout.addWidget(out_frame)
401
+ layout.addSpacing(10)
402
+ layout.addWidget(self.button_box)
403
+ self.setLayout(layout)
404
+
405
+ def n_column_changed(self):
406
+ print('gjgjhgjhg')
407
+ n_column = self.n_column_spinbox.value()
408
+ exist_column = len(self.x_bias_wl)
409
+ if n_column == exist_column:
410
+ return
411
+
412
+ if n_column < exist_column:
413
+ del_index = np.arange(n_column, exist_column)[::-1]
414
+ for da_ind in del_index:
415
+ self.sites_distance_wl[da_ind].sig_text_changed.disconnect(self.sites_distance_changed)
416
+ self.per_max_sites_wl[da_ind].sig_text_changed.disconnect(self.per_max_sites_changed)
417
+ self.x_bias_wl[da_ind].sig_text_changed.disconnect(self.x_bias_changed)
418
+ self.y_bias_wl[da_ind].sig_text_changed.disconnect(self.y_bias_changed)
419
+
420
+ self.right_layout.removeWidget(self.sites_distance_wl[da_ind])
421
+ self.right_layout.removeWidget(self.per_max_sites_wl[da_ind])
422
+ self.right_layout.removeWidget(self.x_bias_wl[da_ind])
423
+ self.right_layout.removeWidget(self.y_bias_wl[da_ind])
424
+ self.sites_distance_wl[da_ind].deleteLater()
425
+ self.per_max_sites_wl[da_ind].deleteLater()
426
+ self.x_bias_wl[da_ind].deleteLater()
427
+ self.y_bias_wl[da_ind].deleteLater()
428
+ del self.sites_distance_wl[da_ind]
429
+ del self.per_max_sites_wl[da_ind]
430
+ del self.x_bias_wl[da_ind]
431
+ del self.y_bias_wl[da_ind]
432
+
433
+ del self.probe_settings['sites_distance'][da_ind]
434
+ del self.probe_settings['per_max_sites'][da_ind]
435
+ del self.probe_settings['x_bias'][da_ind]
436
+ del self.probe_settings['y_bias'][da_ind]
437
+ else:
438
+ for da_ind in range(exist_column, n_column):
439
+ self.sites_distance_wl.append(IntLineEdit(da_ind, str(0)))
440
+ self.per_max_sites_wl.append(IntLineEdit(da_ind, str(0)))
441
+ self.x_bias_wl.append(IntLineEdit(da_ind, str(0)))
442
+ self.y_bias_wl.append(IntLineEdit(da_ind, str(0)))
443
+
444
+ self.sites_distance_wl[-1].sig_text_changed.connect(self.sites_distance_changed)
445
+ self.per_max_sites_wl[-1].sig_text_changed.connect(self.per_max_sites_changed)
446
+ self.x_bias_wl[-1].sig_text_changed.connect(self.x_bias_changed)
447
+ self.y_bias_wl[-1].sig_text_changed.connect(self.y_bias_changed)
448
+
449
+ self.right_layout.addWidget(self.sites_distance_wl[-1], 6, da_ind + 1, 1, 1)
450
+ self.right_layout.addWidget(self.per_max_sites_wl[-1], 7, da_ind + 1, 1, 1)
451
+ self.right_layout.addWidget(self.x_bias_wl[-1], 8, da_ind + 1, 1, 1)
452
+ self.right_layout.addWidget(self.y_bias_wl[-1], 9, da_ind + 1, 1, 1)
453
+
454
+ self.probe_settings['sites_distance'].append(0)
455
+ self.probe_settings['per_max_sites'].append(0)
456
+ self.probe_settings['x_bias'].append(0)
457
+ self.probe_settings['y_bias'].append(0)
458
+
459
+ def probe_length_changed(self, obj):
460
+ text_val = obj[1]
461
+ if text_val in ['', '-', '+']:
462
+ self.button_box.setEnabled(False)
463
+ else:
464
+ self.probe_settings['probe_length'] = int(text_val)
465
+ if float(text_val) < 1e-4:
466
+ self.button_box.setEnabled(False)
467
+ else:
468
+ self.button_box.setEnabled(True)
469
+
470
+ def probe_thickness_changed(self, obj):
471
+ text_val = obj[1]
472
+ if text_val in ['', '-', '+']:
473
+ self.button_box.setEnabled(False)
474
+ else:
475
+ self.probe_settings['probe_thickness'] = int(text_val)
476
+ if float(text_val) < 0:
477
+ self.button_box.setEnabled(False)
478
+ else:
479
+ self.button_box.setEnabled(True)
480
+
481
+ def tip_length_changed(self, obj):
482
+ text_val = obj[1]
483
+ if text_val in ['', '-', '+']:
484
+ self.button_box.setEnabled(False)
485
+ else:
486
+ self.probe_settings['tip_length'] = int(text_val)
487
+ if float(text_val) < 0 or float(text_val) > self.probe_settings['probe_length']:
488
+ self.button_box.setEnabled(False)
489
+ else:
490
+ self.button_box.setEnabled(True)
491
+
492
+ def site_width_changed(self, obj):
493
+ text_val = obj[1]
494
+ if text_val in ['', '-', '+']:
495
+ self.button_box.setEnabled(False)
496
+ else:
497
+ self.probe_settings['site_width'] = int(text_val)
498
+ if float(text_val) < 1e-4:
499
+ self.button_box.setEnabled(False)
500
+ else:
501
+ self.button_box.setEnabled(True)
502
+
503
+ def site_height_changed(self, obj):
504
+ text_val = obj[1]
505
+ if text_val in ['', '-', '+']:
506
+ self.button_box.setVisible(False)
507
+ else:
508
+ self.probe_settings['site_height'] = int(text_val)
509
+ if float(text_val) < 1e-4:
510
+ self.button_box.setEnabled(False)
511
+ else:
512
+ self.button_box.setEnabled(True)
513
+
514
+ #
515
+ def sites_distance_changed(self, obj):
516
+ w_id = obj[0]
517
+ text_val = obj[1]
518
+ if text_val in ['', '-', '+']:
519
+ self.button_box.setEnabled(False)
520
+ else:
521
+ self.probe_settings['sites_distance'][w_id] = int(text_val)
522
+ if float(text_val) < 1e-4:
523
+ self.button_box.setEnabled(False)
524
+ else:
525
+ self.button_box.setEnabled(True)
526
+
527
+ def per_max_sites_changed(self, obj):
528
+ w_id = obj[0]
529
+ text_val = obj[1]
530
+ if text_val in ['', '-', '+']:
531
+ self.button_box.setEnabled(False)
532
+ else:
533
+ self.probe_settings['per_max_sites'][w_id] = int(text_val)
534
+ if float(text_val) < 1e-4:
535
+ self.button_box.setEnabled(False)
536
+ else:
537
+ self.button_box.setEnabled(True)
538
+
539
+ def x_bias_changed(self, obj):
540
+ w_id = obj[0]
541
+ text_val = obj[1]
542
+ # text_val = self.x_bias_wl[index].text()
543
+ if text_val in ['', '-', '+']:
544
+ self.button_box.setEnabled(False)
545
+ else:
546
+ self.probe_settings['x_bias'][w_id] = int(text_val)
547
+ self.button_box.setEnabled(True)
548
+
549
+ def y_bias_changed(self, obj):
550
+ w_id = obj[0]
551
+ text_val = obj[1]
552
+ if text_val in ['', '-', '+']:
553
+ self.button_box.setEnabled(False)
554
+ else:
555
+ self.probe_settings['y_bias'][w_id] = int(text_val)
556
+ if float(text_val) < 0:
557
+ self.button_box.setEnabled(False)
558
+ else:
559
+ self.button_box.setEnabled(True)
560
+
561
+
562
+ class MultiProbePlanningDialog(QDialog):
563
+ def __init__(self, multi_settings):
564
+ super().__init__()
565
+
566
+ self.setWindowTitle('Multi-Probe Geometry Setting Window')
567
+ self.setStyleSheet(dialog_style)
568
+
569
+ btn_box = QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
570
+
571
+ self.button_box = QDialogButtonBox(btn_box)
572
+ self.button_box.accepted.connect(self.accept)
573
+ self.button_box.rejected.connect(self.reject)
574
+
575
+ fig_label = QLabel()
576
+ pixmap = QPixmap(resource_path('icons/toolbar/multi_probe.png'))
577
+ fig_label.setPixmap(pixmap)
578
+ fig_label.setFixedHeight(300)
579
+
580
+ # initial values
581
+ if multi_settings is None:
582
+ self.multi_settings = {}
583
+ self.multi_settings['x_vals'] = [-300, 300, -100, -300, 300]
584
+ self.multi_settings['y_vals'] = [-100, -100, 0, 100, 100]
585
+ self.multi_settings['faces'] = [0, 0, 0, 0, 0]
586
+
587
+ else:
588
+ self.multi_settings = multi_settings
589
+
590
+ n_probe = len(self.multi_settings['x_vals'])
591
+
592
+ # initial widgets
593
+ n_probe_label = QLabel('Number of Probes (stk): ')
594
+ self.n_probe_spinbox = QSpinBox()
595
+ self.n_probe_spinbox.setMinimum(2)
596
+ self.n_probe_spinbox.setValue(n_probe)
597
+
598
+ row_names = [QLabel('X Coordinates (um): '), QLabel('Y Coordinates (um): '),
599
+ QLabel('Probe Faces: ')]
600
+
601
+ self.x_val_wl = []
602
+ self.y_val_wl = []
603
+ self.faces_wl = []
604
+ # self.types_wl = []
605
+ for i in range(n_probe):
606
+ self.x_val_wl.append(IntLineEdit(i, str(self.multi_settings['x_vals'][i])))
607
+ self.y_val_wl.append(IntLineEdit(i, str(self.multi_settings['y_vals'][i])))
608
+ self.faces_wl.append(FaceCombo(i))
609
+ self.faces_wl[-1].addItems(['Out', 'In', 'Left', 'Right'])
610
+ self.faces_wl[-1].setCurrentText(str(self.multi_settings['faces'][i]))
611
+ self.x_val_wl[-1].sig_text_changed.connect(self.x_vals_changed)
612
+ self.y_val_wl[-1].sig_text_changed.connect(self.y_vals_changed)
613
+ self.faces_wl[-1].sig_text_changed.connect(self.faces_changed)
614
+
615
+ # connect
616
+ self.n_probe_spinbox.valueChanged.connect(self.n_probe_changed)
617
+
618
+ # add widgets to layout
619
+ right_frame = QFrame()
620
+ self.right_layout = QGridLayout(right_frame)
621
+ self.right_layout.addWidget(n_probe_label, 0, 0, 1, 1)
622
+ self.right_layout.addWidget(self.n_probe_spinbox, 0, 1, 1, 1)
623
+
624
+ for i in range(len(row_names)):
625
+ self.right_layout.addWidget(row_names[i], 1 + i, 0, 1, 1)
626
+
627
+ for j in range(n_probe):
628
+ self.right_layout.addWidget(self.x_val_wl[j], 1, j + 1, 1, 1)
629
+ self.right_layout.addWidget(self.y_val_wl[j], 2, j + 1, 1, 1)
630
+ self.right_layout.addWidget(self.faces_wl[j], 3, j + 1, 1, 1)
631
+
632
+ #
633
+ out_frame = QFrame()
634
+ out_layout = QHBoxLayout(out_frame)
635
+ out_layout.addWidget(fig_label)
636
+ out_layout.addWidget(right_frame)
637
+
638
+ # add widget to layout
639
+ layout = QVBoxLayout()
640
+ layout.addWidget(out_frame)
641
+ layout.addSpacing(10)
642
+ layout.addWidget(self.button_box)
643
+ self.setLayout(layout)
644
+
645
+ def n_probe_changed(self):
646
+ n_probe = self.n_probe_spinbox.value()
647
+ exist_probe = len(self.x_val_wl)
648
+ if n_probe == exist_probe:
649
+ return
650
+
651
+ if n_probe < exist_probe:
652
+ del_index = np.arange(n_probe, exist_probe)[::-1]
653
+ for da_ind in del_index:
654
+ self.x_val_wl[da_ind].sig_text_changed.disconnect(self.x_vals_changed)
655
+ self.y_val_wl[da_ind].sig_text_changed.disconnect(self.y_vals_changed)
656
+ self.faces_wl[da_ind].sig_text_changed.disconnect(self.faces_changed)
657
+
658
+ self.right_layout.removeWidget(self.x_val_wl[da_ind])
659
+ self.right_layout.removeWidget(self.y_val_wl[da_ind])
660
+ self.right_layout.removeWidget(self.faces_wl[da_ind])
661
+ self.x_val_wl[da_ind].deleteLater()
662
+ self.y_val_wl[da_ind].deleteLater()
663
+ self.faces_wl[da_ind].deleteLater()
664
+ del self.x_val_wl[da_ind]
665
+ del self.y_val_wl[da_ind]
666
+ del self.faces_wl[da_ind]
667
+
668
+ del self.multi_settings['x_vals'][da_ind]
669
+ del self.multi_settings['y_vals'][da_ind]
670
+ del self.multi_settings['faces'][da_ind]
671
+ else:
672
+ for da_ind in range(exist_probe, n_probe):
673
+ self.x_val_wl.append(IntLineEdit(da_ind, str(0)))
674
+ self.y_val_wl.append(IntLineEdit(da_ind, str(0)))
675
+ self.faces_wl.append(FaceCombo(da_ind))
676
+ self.faces_wl[-1].addItems(['Out', 'In', 'Left', 'Right'])
677
+
678
+ self.x_val_wl[-1].sig_text_changed.connect(self.x_vals_changed)
679
+ self.y_val_wl[-1].sig_text_changed.connect(self.y_vals_changed)
680
+ self.faces_wl[-1].sig_text_changed.connect(self.faces_changed)
681
+
682
+ self.right_layout.addWidget(self.x_val_wl[-1], 1, da_ind + 1, 1, 1)
683
+ self.right_layout.addWidget(self.y_val_wl[-1], 2, da_ind + 1, 1, 1)
684
+ self.right_layout.addWidget(self.faces_wl[-1], 3, da_ind + 1, 1, 1)
685
+
686
+ self.multi_settings['x_vals'].append(0)
687
+ self.multi_settings['y_vals'].append(0)
688
+ self.multi_settings['faces'].append(0)
689
+
690
+ #
691
+ def x_vals_changed(self, obj):
692
+ w_id = obj[0]
693
+ text_val = obj[1]
694
+ if text_val in ['', '-', '+']:
695
+ self.button_box.setEnabled(False)
696
+ else:
697
+ self.multi_settings['x_vals'][w_id] = int(text_val)
698
+ self.button_box.setEnabled(True)
699
+
700
+ def y_vals_changed(self, obj):
701
+ w_id = obj[0]
702
+ text_val = obj[1]
703
+ if text_val in ['', '-', '+']:
704
+ self.button_box.setEnabled(False)
705
+ else:
706
+ self.multi_settings['y_vals'][w_id] = int(text_val)
707
+ self.button_box.setEnabled(True)
708
+
709
+ def faces_changed(self, obj):
710
+ w_id = obj[0]
711
+ index_val = obj[1]
712
+ self.multi_settings['faces'][w_id] = index_val
713
+
714
+
715
+