automod 0.0.1__tar.gz

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 (43) hide show
  1. automod-0.0.1/LICENSE.txt +19 -0
  2. automod-0.0.1/PKG-INFO +21 -0
  3. automod-0.0.1/README.md +2 -0
  4. automod-0.0.1/pyproject.toml +32 -0
  5. automod-0.0.1/src/automod/__init__.py +0 -0
  6. automod-0.0.1/src/automod/automod.py +25 -0
  7. automod-0.0.1/src/automod/csview.py +120 -0
  8. automod-0.0.1/src/automod/curvescene.py +37 -0
  9. automod-0.0.1/src/automod/curveview.py +326 -0
  10. automod-0.0.1/src/automod/gridline.py +103 -0
  11. automod-0.0.1/src/automod/gridpoint.py +100 -0
  12. automod-0.0.1/src/automod/helixpoint.py +240 -0
  13. automod-0.0.1/src/automod/icons/app_icon.png +0 -0
  14. automod-0.0.1/src/automod/icons/arrow_black.png +0 -0
  15. automod-0.0.1/src/automod/icons/arrow_blue.png +0 -0
  16. automod-0.0.1/src/automod/icons/arrow_green.png +0 -0
  17. automod-0.0.1/src/automod/icons/arrow_red.png +0 -0
  18. automod-0.0.1/src/automod/icons/connect.png +0 -0
  19. automod-0.0.1/src/automod/icons/disconnect_next.png +0 -0
  20. automod-0.0.1/src/automod/icons/disconnect_prev.png +0 -0
  21. automod-0.0.1/src/automod/icons/honeycomb.png +0 -0
  22. automod-0.0.1/src/automod/icons/import.png +0 -0
  23. automod-0.0.1/src/automod/icons/insert_plus.png +0 -0
  24. automod-0.0.1/src/automod/icons/interpolate.png +0 -0
  25. automod-0.0.1/src/automod/icons/json.png +0 -0
  26. automod-0.0.1/src/automod/icons/print.png +0 -0
  27. automod-0.0.1/src/automod/icons/renum.png +0 -0
  28. automod-0.0.1/src/automod/icons/restore.png +0 -0
  29. automod-0.0.1/src/automod/icons/rotate_black.png +0 -0
  30. automod-0.0.1/src/automod/icons/rotate_blue.png +0 -0
  31. automod-0.0.1/src/automod/icons/rotate_green.png +0 -0
  32. automod-0.0.1/src/automod/icons/rotate_red.png +0 -0
  33. automod-0.0.1/src/automod/icons/save.png +0 -0
  34. automod-0.0.1/src/automod/icons/square.png +0 -0
  35. automod-0.0.1/src/automod/icons/trash.png +0 -0
  36. automod-0.0.1/src/automod/icons/zoom.png +0 -0
  37. automod-0.0.1/src/automod/icons.py +5368 -0
  38. automod-0.0.1/src/automod/icons.qrc +27 -0
  39. automod-0.0.1/src/automod/mainwindow.py +1628 -0
  40. automod-0.0.1/src/automod/nodepoint.py +209 -0
  41. automod-0.0.1/src/automod/pathcurve.py +698 -0
  42. automod-0.0.1/src/automod/pathline.py +71 -0
  43. automod-0.0.1/src/automod/storage3d.py +1007 -0
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2025 Elina Heikkilä
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
automod-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,21 @@
1
+ Metadata-Version: 2.4
2
+ Name: automod
3
+ Version: 0.0.1
4
+ Summary: Automated modification and crossover placement for the design of curved DNA origami structures.
5
+ Project-URL: Homepage, https://github.com/AutoMod-DNA/automod
6
+ Project-URL: Issues, https://github.com/AutoMod-DNA/automod/issues
7
+ Author-email: Elina Heikkilä <elina.s.heikkila@aalto.fi>
8
+ License-Expression: MIT
9
+ License-File: LICENSE.txt
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Requires-Python: >=3.9
15
+ Requires-Dist: numpy
16
+ Requires-Dist: pyside6
17
+ Requires-Dist: scipy
18
+ Description-Content-Type: text/markdown
19
+
20
+ # AutoMod
21
+ *Auto*mated *Mod*ification and crossover placement for the design of curved DNA origami structures.
@@ -0,0 +1,2 @@
1
+ # AutoMod
2
+ *Auto*mated *Mod*ification and crossover placement for the design of curved DNA origami structures.
@@ -0,0 +1,32 @@
1
+ [build-system]
2
+ requires = ["hatchling >= 1.26"]
3
+ build-backend = "hatchling.build"
4
+ [project]
5
+ name = "automod"
6
+ version = "0.0.1"
7
+ authors = [
8
+ { name="Elina Heikkilä", email="elina.s.heikkila@aalto.fi" },
9
+ ]
10
+ description = "Automated modification and crossover placement for the design of curved DNA origami structures."
11
+ readme = "README.md"
12
+ requires-python = ">=3.9"
13
+ classifiers = [
14
+ "Development Status :: 4 - Beta",
15
+ "Programming Language :: Python :: 3",
16
+ "Operating System :: OS Independent",
17
+ "Intended Audience :: Science/Research",
18
+ ]
19
+ license = "MIT"
20
+ license-files = ["LICEN[CS]E*"]
21
+ dependencies = [
22
+ "PySide6",
23
+ "numpy",
24
+ "scipy",
25
+ ]
26
+
27
+ [project.urls]
28
+ Homepage = "https://github.com/AutoMod-DNA/automod"
29
+ Issues = "https://github.com/AutoMod-DNA/automod/issues"
30
+
31
+ [project.scripts]
32
+ automod = "automod:main"
File without changes
@@ -0,0 +1,25 @@
1
+ import sys
2
+
3
+ from PySide6.QtCore import Qt
4
+ from PySide6.QtGui import QIcon
5
+ from PySide6.QtWidgets import QApplication
6
+
7
+ from mainwindow import MainWindow
8
+
9
+
10
+ def main():
11
+ app = QApplication()
12
+ app.setApplicationDisplayName("AutoMod")
13
+ app.setDesktopFileName("AutoMod")
14
+ app.setLayoutDirection(Qt.LayoutDirection.LeftToRight)
15
+ app.setQuitOnLastWindowClosed(True)
16
+ app.setWindowIcon(QIcon("icons/app_icon.png"))
17
+
18
+ main_window = MainWindow()
19
+ main_window.show()
20
+
21
+ sys.exit(app.exec())
22
+
23
+
24
+ if __name__ == '__main__':
25
+ main()
@@ -0,0 +1,120 @@
1
+ import time
2
+
3
+ import numpy as np
4
+
5
+ from PySide6.QtWidgets import QGraphicsView
6
+ from PySide6.QtCore import Qt, QPointF
7
+
8
+ from helixpoint import HelixPoint
9
+
10
+
11
+ class CSView(QGraphicsView):
12
+
13
+ TIME: float = 0.2 * 10 ** 9
14
+ ZOOM_SENSITIVITY: int = 200
15
+
16
+ def __init__(self, parent=None):
17
+ super().__init__(parent)
18
+ self.zoom = False
19
+ self.translate_ref = False
20
+ self.rotate_lat = False
21
+ self.previous_mouse_pos = (0, 0, time.time_ns())
22
+ self.ref_point = None
23
+ self.rotation_amount = 0
24
+
25
+ def set_ref_point(self, point):
26
+ self.ref_point = point
27
+
28
+ def get_ref_point(self):
29
+ return self.ref_point
30
+
31
+ def get_rotation_amount(self):
32
+ return self.rotation_amount
33
+
34
+ def set_rotation_amount(self, theta):
35
+ self.rotation_amount = theta
36
+
37
+ def enable_helix_editing(self):
38
+ for item in self.scene().items():
39
+ if isinstance(item, HelixPoint):
40
+ item.enable_editing()
41
+
42
+ def disable_helix_editing(self):
43
+ for item in self.scene().items():
44
+ if isinstance(item, HelixPoint):
45
+ item.disable_editing()
46
+
47
+ def enable_helix_renumbering(self):
48
+ for item in self.scene().items():
49
+ if isinstance(item, HelixPoint):
50
+ item.enable_renumbering()
51
+
52
+ def disable_helix_renumbering(self):
53
+ for item in self.scene().items():
54
+ if isinstance(item, HelixPoint):
55
+ item.disable_renumbering()
56
+
57
+ def activate_zoom(self):
58
+ self.zoom = True
59
+ self.setMouseTracking(False)
60
+
61
+ def deactivate_zoom(self):
62
+ self.zoom = False
63
+ self.setMouseTracking(True)
64
+
65
+ def activate_translate_ref(self):
66
+ self.translate_ref = True
67
+ self.setMouseTracking(False)
68
+
69
+ def deactivate_translate_ref(self):
70
+ self.translate_ref = False
71
+ self.setMouseTracking(True)
72
+
73
+ def activate_rotate(self):
74
+ self.rotate_lat = True
75
+ self.setMouseTracking(False)
76
+
77
+ def deactivate_rotate(self):
78
+ self.rotate_lat = False
79
+ self.setMouseTracking(True)
80
+
81
+ def mouseMoveEvent(self, event):
82
+ event.accept()
83
+ if time.time_ns() - self.previous_mouse_pos[2] <= self.TIME:
84
+ dx = event.x() - self.previous_mouse_pos[0]
85
+ dy = event.y() - self.previous_mouse_pos[1]
86
+ d = np.sqrt(dx**2 + dy**2)
87
+ if self.zoom and event.buttons() != Qt.MouseButton.NoButton:
88
+ event.accept()
89
+ if dy <= 0:
90
+ self.scale(1 + d / self.ZOOM_SENSITIVITY, 1 + d / self.ZOOM_SENSITIVITY)
91
+ else:
92
+ self.scale(1 / (1 + d / self.ZOOM_SENSITIVITY), 1 / (1 + d / self.ZOOM_SENSITIVITY))
93
+ self.scene().update()
94
+ self.update()
95
+ elif self.translate_ref and event.buttons() != Qt.MouseButton.NoButton:
96
+ event.accept()
97
+ inverse, _ = self.transform().inverted()
98
+ mapped_move = inverse.map(QPointF(dx, dy))
99
+ self.ref_point.setPos(self.ref_point.x() + mapped_move.x(), self.ref_point.y() + mapped_move.y())
100
+ self.parent().parent().update_ref_point_value(self.ref_point.x(), self.ref_point.y())
101
+ self.scene().update()
102
+ self.update()
103
+ elif self.rotate_lat and event.buttons() != Qt.MouseButton.NoButton:
104
+ event.accept()
105
+ if dy <= 0:
106
+ self.rotate(d)
107
+ self.parent().parent().update_cs_angle(d)
108
+ self.rotation_amount += d
109
+ else:
110
+ self.rotate(-d)
111
+ self.parent().parent().update_cs_angle(-d)
112
+ self.rotation_amount -= d
113
+ for item in self.scene().items():
114
+ if isinstance(item, HelixPoint):
115
+ item.update_text_rotation()
116
+ self.scene().update()
117
+ self.update()
118
+ else:
119
+ super().mouseMoveEvent(event)
120
+ self.previous_mouse_pos = (event.x(), event.y(), time.time_ns())
@@ -0,0 +1,37 @@
1
+ from PySide6.QtWidgets import QGraphicsScene
2
+
3
+ from storage3d import Storage3D
4
+
5
+
6
+ class CurveScene(QGraphicsScene):
7
+
8
+ def __init__(self, size, w, parent=None):
9
+ super().__init__(parent=parent)
10
+ self.storage = Storage3D(self)
11
+ self.corners = [None for _ in range(8)]
12
+ self.size = size
13
+ self.w = w
14
+ self.storage.create_grid()
15
+ self.setSceneRect(-w/2, -w/2, w, w)
16
+
17
+ def remove_all_corners(self):
18
+ self.corners = [None for _ in range(8)]
19
+
20
+ def replace_corner(self, grid_corner, index):
21
+ self.corners[index] = grid_corner
22
+
23
+ def update_grid_scale(self):
24
+ self.size = 8 * self.parent().get_parameters()['gs']
25
+ self.w = self.parent().get_parameters()['gs']
26
+
27
+ def get_storage(self):
28
+ return self.storage
29
+
30
+ def get_corners(self):
31
+ return self.corners
32
+
33
+ def get_w(self):
34
+ return self.w
35
+
36
+ def get_size(self):
37
+ return self.size
@@ -0,0 +1,326 @@
1
+ import numpy as np
2
+ import time
3
+
4
+ from PySide6.QtCore import Qt, QPointF
5
+ from PySide6.QtGui import QTransform
6
+ from PySide6.QtWidgets import QGraphicsView
7
+
8
+ from nodepoint import NodePoint
9
+
10
+
11
+ class CurveView(QGraphicsView):
12
+
13
+ TIME: float = 0.2 * 10 ** 9
14
+ ZOOM_SENSITIVITY: int = 200
15
+ TRANSLATE_SENSITIVITY: int = 20
16
+ ROTATE_SENSITIVITY: int = 200
17
+
18
+ @staticmethod
19
+ def rotation_matrix_y(theta):
20
+ return np.array([[np.cos(theta), 0, np.sin(theta)], [0, 1, 0], [(-1)*np.sin(theta), 0, np.cos(theta)]])
21
+
22
+ @staticmethod
23
+ def rotation_matrix_x(theta):
24
+ return np.array([[1, 0, 0], [0, np.cos(theta), (-1)*np.sin(theta)], [0, np.sin(theta), np.cos(theta)]])
25
+
26
+ @staticmethod
27
+ def rotation_matrix_z(theta):
28
+ return np.array([[np.cos(theta), (-1)*np.sin(theta), 0], [np.sin(theta), np.cos(theta), 0], [0, 0, 1]])
29
+
30
+ def __init__(self, curve_scene, parent=None):
31
+ super().__init__(curve_scene, parent)
32
+ self.zoom = False
33
+ self.zoom_amount = 1.1
34
+ self.x_translation = False
35
+ self.y_translation = False
36
+ self.z_translation = False
37
+ self.x_rotation = False
38
+ self.y_rotation = False
39
+ self.z_rotation = False
40
+ self.add_points = False
41
+ self.connect_points = False
42
+ self.point_x_translation = False
43
+ self.point_y_translation = False
44
+ self.point_z_translation = False
45
+ self.def_transform = None
46
+ self.scene = curve_scene
47
+ self.setViewportUpdateMode(QGraphicsView.ViewportUpdateMode.FullViewportUpdate)
48
+ self.setSceneRect(-self.scene.size/2, -self.scene.size/2, self.scene.size, self.scene.size)
49
+ self.previous_mouse_pos = (0, 0, time.time_ns())
50
+ self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
51
+ self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
52
+ self.setMinimumWidth(500)
53
+ self.setMinimumHeight(500)
54
+ self.init_fit()
55
+ self.init_rotation()
56
+
57
+ def init_rotation(self):
58
+ R = self.rotation_matrix_x(0.05)
59
+ self.scene.get_storage().rotate_all_points(R)
60
+ R = self.rotation_matrix_z(0.05)
61
+ self.scene.get_storage().rotate_all_points(R)
62
+
63
+ def init_fit(self):
64
+ dx = 100 / self.parent().get_parameters()['gs']
65
+ dy = 100 / self.parent().get_parameters()['gs']
66
+ self.def_transform = QTransform.fromScale(dx, dy)
67
+ self.setTransform(self.def_transform)
68
+ self.scale(self.zoom_amount, self.zoom_amount)
69
+
70
+ def restore_view(self):
71
+ self.scene.get_storage().rotate_to_default()
72
+ self.scene.get_storage().translate_to_default()
73
+ self.zoom_amount = 1.1
74
+ self.init_fit()
75
+ self.init_rotation()
76
+ self.parent().deactivate_point_tools()
77
+ self.scene.update()
78
+ self.update()
79
+
80
+ def pre_translate(self, dx, dy):
81
+ delta = (np.dot(np.array([dx, dy]), np.array([0, -1])) /
82
+ (self.TRANSLATE_SENSITIVITY * self.parent().get_parameters()["ts"]))
83
+ w = self.scene.get_w()
84
+ if np.abs(delta) > w:
85
+ delta = (delta/np.abs(delta)) * w
86
+ return delta
87
+
88
+ def activate_add_points(self):
89
+ self.add_points = True
90
+ self.setMouseTracking(False)
91
+
92
+ def deactivate_add_points(self):
93
+ self.add_points = False
94
+ self.setMouseTracking(True)
95
+
96
+ def activate_zoom(self):
97
+ self.zoom = True
98
+ self.setMouseTracking(False)
99
+
100
+ def activate_x_translation(self):
101
+ self.x_translation = True
102
+ self.setMouseTracking(False)
103
+
104
+ def activate_y_translation(self):
105
+ self.y_translation = True
106
+ self.setMouseTracking(False)
107
+
108
+ def activate_z_translation(self):
109
+ self.z_translation = True
110
+ self.setMouseTracking(False)
111
+
112
+ def activate_x_rotation(self):
113
+ self.x_rotation = True
114
+ self.setMouseTracking(False)
115
+
116
+ def activate_y_rotation(self):
117
+ self.y_rotation = True
118
+ self.setMouseTracking(False)
119
+
120
+ def activate_z_rotation(self):
121
+ self.z_rotation = True
122
+ self.setMouseTracking(False)
123
+
124
+ def activate_point_x_translation(self):
125
+ self.point_x_translation = True
126
+ self.setMouseTracking(False)
127
+
128
+ def activate_point_y_translation(self):
129
+ self.point_y_translation = True
130
+ self.setMouseTracking(False)
131
+
132
+ def activate_point_z_translation(self):
133
+ self.point_z_translation = True
134
+ self.setMouseTracking(False)
135
+
136
+ def activate_connect_points(self):
137
+ self.connect_points = True
138
+ self.setMouseTracking(True)
139
+ self.scene.clearSelection()
140
+
141
+ def deactivate_connect_points(self):
142
+ self.connect_points = False
143
+ self.setMouseTracking(False)
144
+ self.scene.clearSelection()
145
+
146
+ def deactivate_zoom(self):
147
+ self.zoom = False
148
+ self.setMouseTracking(True)
149
+
150
+ def deactivate_x_translation(self):
151
+ self.x_translation = False
152
+ self.setMouseTracking(True)
153
+
154
+ def deactivate_y_translation(self):
155
+ self.y_translation = False
156
+ self.setMouseTracking(True)
157
+
158
+ def deactivate_z_translation(self):
159
+ self.z_translation = False
160
+ self.setMouseTracking(True)
161
+
162
+ def deactivate_x_rotation(self):
163
+ self.x_rotation = False
164
+ self.setMouseTracking(True)
165
+
166
+ def deactivate_y_rotation(self):
167
+ self.y_rotation = False
168
+ self.setMouseTracking(True)
169
+
170
+ def deactivate_z_rotation(self):
171
+ self.z_rotation = False
172
+ self.setMouseTracking(True)
173
+
174
+ def deactivate_point_x_translation(self):
175
+ self.point_x_translation = False
176
+ self.setMouseTracking(True)
177
+
178
+ def deactivate_point_y_translation(self):
179
+ self.point_y_translation = False
180
+ self.setMouseTracking(True)
181
+
182
+ def deactivate_point_z_translation(self):
183
+ self.point_z_translation = False
184
+ self.setMouseTracking(True)
185
+
186
+ def mouseMoveEvent(self, event):
187
+ if time.time_ns() - self.previous_mouse_pos[2] <= self.TIME:
188
+ dx = event.position().x() - self.previous_mouse_pos[0]
189
+ dy = event.position().y() - self.previous_mouse_pos[1]
190
+ d = np.sqrt(dx ** 2 + dy ** 2)
191
+ if self.zoom and event.buttons() != Qt.MouseButton.NoButton:
192
+ event.accept()
193
+ if dy <= 0:
194
+ delta = 1 + (d / (self.ZOOM_SENSITIVITY * self.parent().get_parameters()["zs"]))
195
+ self.scale(delta, delta)
196
+ self.zoom_amount = self.zoom_amount * delta
197
+ else:
198
+ delta = 1 / (1 + (d / (self.ZOOM_SENSITIVITY * self.parent().get_parameters()["zs"])))
199
+ self.scale(delta, delta)
200
+ self.zoom_amount = self.zoom_amount * delta
201
+ self.scene.update()
202
+ self.update()
203
+ elif (self.x_translation or self.y_translation or self.z_translation) and event.buttons() != Qt.MouseButton.NoButton:
204
+ event.accept()
205
+ delta = self.pre_translate(dx, dy)
206
+ if self.x_translation:
207
+ self.scene.get_storage().translate_all_points(delta, 0, 0)
208
+ elif self.y_translation:
209
+ self.scene.get_storage().translate_all_points(0, delta, 0)
210
+ else:
211
+ self.scene.get_storage().translate_all_points(0, 0, delta)
212
+ self.scene.get_storage().update_grid()
213
+ self.scene.update()
214
+ self.update()
215
+ elif (self.x_rotation or self.y_rotation or self.z_rotation) and event.buttons() != Qt.MouseButton.NoButton:
216
+ event.accept()
217
+ theta = d / (self.ROTATE_SENSITIVITY * self.parent().get_parameters()["rs"])
218
+ if self.y_rotation:
219
+ if dy > 0:
220
+ R = self.rotation_matrix_y(theta)
221
+ else:
222
+ R = self.rotation_matrix_y(-theta)
223
+ elif self.x_rotation:
224
+ if dy > 0:
225
+ R = self.rotation_matrix_x(theta)
226
+ else:
227
+ R = self.rotation_matrix_x(-theta)
228
+ else:
229
+ if dy > 0:
230
+ R = self.rotation_matrix_z(theta)
231
+ else:
232
+ R = self.rotation_matrix_z(-theta)
233
+ self.scene.get_storage().rotate_all_points(R)
234
+ self.scene.update()
235
+ self.update()
236
+ elif (self.point_x_translation or self.point_y_translation or self.point_z_translation) and event.buttons() != Qt.MouseButton.NoButton:
237
+ event.accept()
238
+ delta = self.pre_translate(dx, dy)
239
+ if self.point_x_translation:
240
+ self.scene.get_storage().translate_node(delta, 0, 0)
241
+ elif self.point_y_translation:
242
+ self.scene.get_storage().translate_node(0, delta, 0)
243
+ else:
244
+ self.scene.get_storage().translate_node(0, 0, delta)
245
+ self.scene.update()
246
+ self.update()
247
+
248
+ else:
249
+ super().mouseMoveEvent(event)
250
+ self.previous_mouse_pos = (event.position().x(), event.position().y(), time.time_ns())
251
+
252
+ def mousePressEvent(self, event):
253
+ if event.buttons() == Qt.MouseButton.LeftButton:
254
+ event_pos = QPointF(((event.x() - self.width()/2) / self.transform().m11()) / 2,
255
+ ((event.y() - self.height()/2) / self.transform().m22()) / 2)
256
+ if self.add_points:
257
+ self.scene.get_storage().add_node_point(event_pos)
258
+ elif self.connect_points and self.scene.get_storage().has_node_at(event_pos):
259
+ for item in self.scene.items():
260
+ if isinstance(item, NodePoint) and item.has_selection():
261
+ subseq_node = self.scene.get_storage().get_node_at(event_pos)
262
+ if ((item.get_next_node() is None) and (subseq_node.get_prev_node() is None) and
263
+ (item is not subseq_node)):
264
+ item.set_next_node(subseq_node)
265
+ subseq_node.set_prev_node(item)
266
+ self.scene.get_storage().add_path_line(item, subseq_node)
267
+ self.scene.get_storage().get_nodes()[item.get_node_index()][3] = subseq_node.get_node_index()
268
+ self.scene.get_storage().get_nodes()[subseq_node.get_node_index()][2] = item.get_node_index()
269
+ else:
270
+ self.scene.get_storage().get_node_at(event_pos).mousePressEvent(event)
271
+ elif self.point_x_translation or self.point_y_translation or self.point_z_translation:
272
+ pass
273
+ else:
274
+ if self.scene.get_storage().has_node_at(event_pos):
275
+ self.scene.get_storage().get_node_at(event_pos).mousePressEvent(event)
276
+
277
+ def resizeEvent(self, event):
278
+ w1, w2, w3, w4 = self.parent().get_tool_widths()
279
+ d = event.oldSize().width() - event.size().width()
280
+ if d in [w1 + i for i in range(-2, 2)] or d in [w2 + i for i in range(-2, 2)]\
281
+ or d in [-w1 + i for i in range(-2, 2)] or d in [-w2 + i for i in range(-2, 2)]:
282
+ dx_scene = (d / self.transform().m11()) / 4
283
+ dy_scene = ((event.oldSize().height() - event.size().height())/ self.transform().m22()) / 4
284
+ d_vec = np.array([-dx_scene, -dy_scene, 0])
285
+ x_hat = self.scene.get_storage().get_unit_x()
286
+ y_hat = self.scene.get_storage().get_unit_y()
287
+ z_hat = self.scene.get_storage().get_unit_z()
288
+ self.scene.get_storage().translate_all_points(np.dot(d_vec, x_hat), np.dot(d_vec, y_hat), np.dot(d_vec, z_hat))
289
+ elif d in [w3 + i for i in range(-8, 8)] or d in [w4 + i for i in range(-2, 2)]\
290
+ or d in [-w3 + i for i in range(-6, 6)] or d in [-w4 + i for i in range(-2, 2)]:
291
+ dx_scene = (d / self.transform().m11()) / 4
292
+ dy_scene = ((event.oldSize().height() - event.size().height()) / self.transform().m22()) / 4
293
+ d_vec = np.array([dx_scene, -dy_scene, 0])
294
+ x_hat = self.scene.get_storage().get_unit_x()
295
+ y_hat = self.scene.get_storage().get_unit_y()
296
+ z_hat = self.scene.get_storage().get_unit_z()
297
+ self.scene.get_storage().translate_all_points(np.dot(d_vec, x_hat), np.dot(d_vec, y_hat), np.dot(d_vec, z_hat))
298
+ elif d in [w2 + w3 + w4 + i for i in range(-6, 6)] or d in [-(w2 + w3 + w4) + i for i in range(-6, 6)]:
299
+ dx_scene_1 = (w2 / self.transform().m11()) / 4
300
+ dx_scene_2 = ((-d - w2) / self.transform().m11()) / 4
301
+ dy_scene = ((event.oldSize().height() - event.size().height()) / self.transform().m22()) / 4
302
+ d_vec_1 = np.array([dx_scene_1, -dy_scene, 0])
303
+ d_vec_2 = np.array([-dx_scene_2, -dy_scene, 0])
304
+ x_hat = self.scene.get_storage().get_unit_x()
305
+ y_hat = self.scene.get_storage().get_unit_y()
306
+ z_hat = self.scene.get_storage().get_unit_z()
307
+ self.scene.get_storage().translate_all_points(np.dot(d_vec_1, x_hat), np.dot(d_vec_1, y_hat), np.dot(d_vec_1, z_hat))
308
+ self.scene.get_storage().translate_all_points(np.dot(d_vec_2, x_hat), np.dot(d_vec_2, y_hat), np.dot(d_vec_2, z_hat))
309
+ elif d in [w3 + w4 + i for i in range(-6, 6)] or d in [-(w3 + w4) + i for i in range(-6, 6)]:
310
+ dx_scene = (d / self.transform().m11()) / 4
311
+ dy_scene = ((event.oldSize().height() - event.size().height()) / self.transform().m22()) / 4
312
+ d_vec = np.array([dx_scene, -dy_scene, 0])
313
+ x_hat = self.scene.get_storage().get_unit_x()
314
+ y_hat = self.scene.get_storage().get_unit_y()
315
+ z_hat = self.scene.get_storage().get_unit_z()
316
+ self.scene.get_storage().translate_all_points(np.dot(d_vec, x_hat), np.dot(d_vec, y_hat),
317
+ np.dot(d_vec, z_hat))
318
+ self.init_fit()
319
+ self.scene.update()
320
+ self.update()
321
+
322
+ def wheelEvent(self, event):
323
+ event.accept()
324
+
325
+ def keyPressEvent(self, event):
326
+ event.accept()