iam-git / WellMet (public) (License: MIT) (since 2021-08-31) (hash sha1)
WellMet is pure Python framework for spatial structural reliability analysis. Or, more specifically, for "failure probability estimation and detection of failure surfaces by adaptive sequential decomposition of the design domain".
List of commits:
Subject Hash Author Date (UTC)
qt_gui: introduce reworked matrix view window e28b95c5f418a7a3cea0cb84ca82b40275a71061 I am 2022-11-07 02:20:45
introduce wireframe module for the contacts finding functionality b6068dd92663699859ea7cbf3aac00178d120e0f I am 2022-10-25 14:24:37
voronoi.TwoPoints: atleast_2d() one line fix 9f8bd9e5370ccf30887b6218331ee664788a3b91 I am 2022-10-25 07:09:57
voronoi: implement faster TwoPoints class. c0af78f64bc78a6b8cf06e3ea244339549318b66 I am 2022-10-24 13:03:26
voronoi: implement TwoHorses class. Třída je, bohužel, bezcenná :( 4f6fe186f3f344fa7ee9e518798499099615b466 I am 2022-10-23 10:00:43
voronoi: WIP 23c63ede5bc2ec51d25aed850dc59299db438e34 I am 2022-10-21 12:27:01
IS_stat.sample_alike: use any possible fallback options to sample 80fb6d086e9f17350a1725a319e40bf29591869e I am 2022-10-20 08:56:42
voronoi: WIP ba912d406de12142f2e15a73090118184a0166a4 I am 2022-10-20 02:43:12
IS_stat: add sample_alike() function 2e5394d264b7aaaf5f2486c736ed8cc37afbd030 I am 2022-10-19 13:00:17
voronoi: WIP c3bfa60b6db2042df11528fe95a51d7cc88d3c6b I am 2022-10-19 11:18:13
voronoi: WIP baff3c5ccaf857f60194917fe5d6e33c40b01265 I am 2022-10-19 09:28:33
voronoi.ConvexSpline: little fix of np.sign() for better sleep 968f649e54d97abd596cd60749872fa3ef788c06 I am 2022-10-19 06:28:46
implement even more optimized Convex.. now ConvexSpline class c08511aecb32b880e73c9f10d07feff4dc588e8b I am 2022-10-19 04:11:13
voronoi: WIP cbb61d4544367a67c9a5c3fe6d64a9dc284eb364 I am 2022-10-18 05:05:44
voronoi: WIP e9c247fef30cfb678bad9b955d6f6a94a0ff61e7 I am 2022-10-18 01:02:30
candynodex: hotfix to support numpy masking indexing f359123b72a3d998d5eed4b9e611a5e402a18c8d I am 2022-10-17 09:02:33
add new lightweight candynodes module to replace old heavy ugly candybox ca97509f47c100df90e1e06d82ed7c759627bfd0 I am 2022-10-17 06:31:33
qt_gui: move CandyBox creating to the individual DiceBox widgets 29253625129219b5e550f82cae3da0e53ef5bd47 I am 2022-10-16 03:17:55
voronoi: WIP 4855190869e06df740cc05c64e8b27b2c3c5a88d I am 2022-10-15 22:46:51
voronoi: WIP 0298b3a0563587ea4fc24fa99b51d2e01d517203 I am 2022-10-15 20:00:25
Commit e28b95c5f418a7a3cea0cb84ca82b40275a71061 - qt_gui: introduce reworked matrix view window
Author: I am
Author date (UTC): 2022-11-07 02:20
Committer name: I am
Committer date (UTC): 2022-11-07 02:20
Parent(s): b6068dd92663699859ea7cbf3aac00178d120e0f
Signer:
Signing key:
Signing status: N
Tree: c43728982d867cea9dd1903404030319afee976d
File Lines added Lines deleted
wellmet/qt_gui/qt_gui.py 4 84
wellmet/qt_gui/qt_pairwise.py 184 335
File wellmet/qt_gui/qt_gui.py changed (mode: 100644) (index bc51b7f..2bc8dc6)
... ... from pyqtgraph.Qt import QtCore
8 8 from pyqtgraph import console from pyqtgraph import console
9 9
10 10 import numpy as np import numpy as np
11 from scipy import spatial # for distance matrix
12 11 from . import qt_graph_widgets from . import qt_graph_widgets
13 from ..voronoi import ConvexSpline
12 from . import qt_pairwise
14 13 from .. import reader from .. import reader
15 14
16 15
 
... ... class QtGuiWindow(QtWidgets.QMainWindow):
105 104 self.batch_run_action = QtGui.QAction("Batch run", self) self.batch_run_action = QtGui.QAction("Batch run", self)
106 105 self.batch_run_action.triggered.connect(self.batch_run) self.batch_run_action.triggered.connect(self.batch_run)
107 106 self.graph_menu.addAction(self.batch_run_action) self.graph_menu.addAction(self.batch_run_action)
108 self.gen_dmatrix_action = QtGui.QAction("Generate distance matrix...", self)
107 self.gen_dmatrix_action = QtGui.QAction("Matrix view...", self)
109 108 self.gen_dmatrix_action.triggered.connect(self.gen_dmatrix) self.gen_dmatrix_action.triggered.connect(self.gen_dmatrix)
110 109 self.graph_menu.addAction(self.gen_dmatrix_action) self.graph_menu.addAction(self.gen_dmatrix_action)
111 110
 
... ... class QtGuiWindow(QtWidgets.QMainWindow):
238 237 self.btn_continue.hide() self.btn_continue.hide()
239 238 self.continue_label.hide() self.continue_label.hide()
240 239
241 self.statusBar.showMessage("Vitáme vás u nás!")
240 #self.statusBar.showMessage("Vitáme vás u nás!")
242 241
243 242
244 243
 
... ... class QtGuiWindow(QtWidgets.QMainWindow):
527 526
528 527
529 528 def gen_dmatrix(self): def gen_dmatrix(self):
530 self.distance_matrix()
529 qt_pairwise.MatrixWindow(self.sample_box, self.space, parent=self)
531 530
532 def distance_matrix(self, p=2):
533 nsim = self.slider.value()
534
535 sample_box = self.sample_box[:nsim]
536 if nsim > 0:
537 sample_space = getattr(sample_box, self.space)
538 dmatrix = spatial.distance_matrix(sample_space, sample_space, p=p)
539 mask = np.zeros((nsim, nsim))
540
541 failure_points = self.sample_box[:nsim].failure_points
542 mask[failure_points] += 0.5
543 mask[:, failure_points] += 0.5
544 #č vůbec nechápu, jak to numpy rozřezavá
545 #č nedavá mi to smysl
546 #č takhle funguje, jinak nefunguje
547 #mask[failure_points][:,failure_points] = 0
548
549 CS = ConvexSpline(sample_space)
550 contacts = np.zeros((nsim, nsim), dtype=np.bool8)
551 for i in range(nsim):
552 for j in range(i):
553 contacts[i, j] = CS.is_couple((i, j))
554
555 #pg.image(data, levelMode='rgba', title="Distance matrix, p=%s" % p)
556 w = DMView(dmatrix, mask, contacts)
557 w.setWindowTitle("Distance matrix, p=%s" % p)
558
559
560
561
562
563 531
564 532
565 533
 
... ... E Miscellaneous
572 540 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
573 541 """ """
574 542
575 #č pg trik, aby GC nám nevymazal paměť
576 images = []
577
578 class DMView(pg.ImageView):
579 def __init__(self, dmatrix, mask, contacts, *args, **kwargs):
580 self.dmatrix = dmatrix
581 self.contacts = contacts
582 self.nsim = nsim = len(dmatrix)
583 data = np.empty((nsim, nsim, 3))
584 data[:,:,0] = dmatrix * mask
585 data[:,:,1] = dmatrix * (1 - mask)
586 data[:,:,2] = contacts
587
588 self.pi = pg.PlotItem()
589 super().__init__(*args, view=self.pi, **kwargs)
590 #č pg trik, aby GC nám nevymazal paměť
591 images.append(self)
592
593 self.show()
594 self.setImage(data, levelMode='rgba')
595
596 self.proxy = pg.SignalProxy(self.pi.scene().sigMouseMoved,
597 rateLimit=60, slot=self.mouse_moved)
598
599
600 def mouse_moved(self, evt):
601 pos = evt[0] ## using signal proxy turns original arguments into a tuple
602 if self.pi.sceneBoundingRect().contains(pos):
603 mousePoint = self.pi.vb.mapSceneToView(pos)
604 x = int(mousePoint.x())
605 y = int(mousePoint.y())
606 nsim = self.nsim
607 if x >= 0 and x < nsim and y >= 0 and y < nsim:
608 val = self.dmatrix[x,y]
609 msg = "distance between %d and %d is %g\n" % (x, y, val)
610 if self.contacts[max(x,y), min(x,y)]:
611 msg += "There is contact between them"
612 else:
613 msg += "There is no contact between them"
614
615 self.pi.setTitle(msg)
616
617
618
619
620
621
622
623 543 class BoxTreeWidget(pg.LayoutWidget): class BoxTreeWidget(pg.LayoutWidget):
624 544 """ """
625 545 """ """
File wellmet/qt_gui/qt_pairwise.py copied from file wellmet/qt_gui/qt_gui.py (similarity 50%) (mode: 100644) (index bc51b7f..40e542c)
... ... import pyqtgraph as pg
5 5 from pyqtgraph.Qt import QtGui, QtWidgets from pyqtgraph.Qt import QtGui, QtWidgets
6 6 from pyqtgraph.Qt import QtCore from pyqtgraph.Qt import QtCore
7 7
8 from pyqtgraph import console
9
10 8 import numpy as np import numpy as np
11 9 from scipy import spatial # for distance matrix from scipy import spatial # for distance matrix
12 from . import qt_graph_widgets
13 from ..voronoi import ConvexSpline
10 #from ..wireframe import ConvexSpline
14 11 from .. import reader from .. import reader
15 12
16 13
14 #č pg trik, aby GC nám nevymazal paměť
15 windows = set()
16
17 17 ### Define a top-level widget to hold everything ### Define a top-level widget to hold everything
18 class QtGuiWindow(QtWidgets.QMainWindow):
18 class MatrixWindow(QtWidgets.QMainWindow):
19 19 #č box_runned dublikuje slice_changed #č box_runned dublikuje slice_changed
20 20 # do not redraw twice! # do not redraw twice!
21 21 box_runned = QtCore.pyqtSignal() box_runned = QtCore.pyqtSignal()
22 space_changed = QtCore.pyqtSignal()
23 slice_changed = QtCore.pyqtSignal()
22 space_changed = QtCore.pyqtSignal(str)
23 metric_changed = QtCore.pyqtSignal(str)
24 slice_changed = QtCore.pyqtSignal(int)
24 25 redraw_called = QtCore.pyqtSignal() redraw_called = QtCore.pyqtSignal()
25 estimation_added = QtCore.pyqtSignal()
26 26
27 # INHERITED by gl_plot
28 # snad pri vykreslování argy-kvargy nevádí
29 def __init__(self, sample_box, space='R', *args, **kwargs):
30
31 #E former self.w = QtGui.QMainWindow()
32 self.app = pg.mkQApp()
27
28 def __init__(self, sample_box, space='R', parent=None, *args, **kwargs):
29 try:
30 self.box_runned = parent.box_runned
31 self.app = parent.app
32 except:
33 self.app = pg.mkQApp() #оӵ кулэ-а?
34 ## Start the Qt event loop
35 self.app.exec_()
36
33 37 super().__init__() super().__init__()
38
39 #č pg trik, aby GC nám nevymazal paměť
40 windows.add(self)
41
42
43
34 44 try: try:
35 45 self.setWindowTitle("%sD: %s" %(sample_box.nvar, sample_box.gm_signature)) self.setWindowTitle("%sD: %s" %(sample_box.nvar, sample_box.gm_signature))
36 46 except: except:
 
... ... class QtGuiWindow(QtWidgets.QMainWindow):
43 53
44 54 self.kwargs = kwargs self.kwargs = kwargs
45 55 self.sample_box = sample_box self.sample_box = sample_box
46 #sample_box.sample_box._log = self.logger
47 self.last_shot = None
48 try:
49 self.space = self.sample_box.tri_space
50 except AttributeError:
51 self.space = space
56 self.space = space
57 self.metric = 'euclidean'
52 58
53 59 # "zapnuté" prostory # "zapnuté" prostory
54 60 #self.spaces = ['R', 'aR', 'Rn', 'aRn', 'P', 'aP', 'GK', 'aGK', 'G', 'aG', 'U', 'aU'] #self.spaces = ['R', 'aR', 'Rn', 'aRn', 'P', 'aP', 'GK', 'aGK', 'G', 'aG', 'U', 'aU']
55 61 self.spaces = ['R', 'aR', 'Rn', 'aRn', 'P', 'GK', 'G', 'aG', 'U', 'aU'] self.spaces = ['R', 'aR', 'Rn', 'aRn', 'P', 'GK', 'G', 'aG', 'U', 'aU']
56
57 # initialize central widget
58 self.initialize_central_widget()
62
63 #self.metrics = ['1', '2', 'inf']
64 self.metrics = ['euclidean', 'cityblock', 'chebyshev',
65 'seuclidean', 'sqeuclidean', 'cosine',
66 'correlation',
67 'canberra', 'braycurtis', 'mahalanobis' ]
59 68
60 69 # common setup # common setup
61 70 self.setup() self.setup()
62
63 self.plot_setup()
64 71
65 72 ## Display the widget as a new window ## Display the widget as a new window
66 73 self.show() self.show()
 
... ... class QtGuiWindow(QtWidgets.QMainWindow):
68 75 # #
69 76 self.redraw_called.emit() self.redraw_called.emit()
70 77
71 ## Start the Qt event loop
72 self.app.exec_()
78
79
80 def closeEvent(self, event):
81 #č nejsem 100% jist co dělám.
82 #č Ale když už ImageView API
83 #č vysloveně nabízí "korektní" .close()
84 #č tak deme do toho
85 self.image_view.close()
86 windows.discard(self)
87 event.accept() # let the window close
88
73 89
74 90 def setup_menubar(self): def setup_menubar(self):
75 91 self.bar = self.menuBar() self.bar = self.menuBar()
 
... ... class QtGuiWindow(QtWidgets.QMainWindow):
105 121 self.batch_run_action = QtGui.QAction("Batch run", self) self.batch_run_action = QtGui.QAction("Batch run", self)
106 122 self.batch_run_action.triggered.connect(self.batch_run) self.batch_run_action.triggered.connect(self.batch_run)
107 123 self.graph_menu.addAction(self.batch_run_action) self.graph_menu.addAction(self.batch_run_action)
108 self.gen_dmatrix_action = QtGui.QAction("Generate distance matrix...", self)
109 self.gen_dmatrix_action.triggered.connect(self.gen_dmatrix)
110 self.graph_menu.addAction(self.gen_dmatrix_action)
111
112 # optional feature
113 self.initialize_matplotlib_menu()
114
115 # should be INHERITED by gl_plot
116 def initialize_matplotlib_menu(self):
117 try: # entire optional functionality
118 from ..mplot import show_ax, show_ax3d, show_fig
119 from ..mplot import maxes
120 from ..mplot import maxes3d
121 from ..mplot import mfigs
122 from ..mplot import misc as mmisc
123 self.matplotlib_menu = self.bar.addMenu("Matplotlib")
124 self.matplotlib_actions = []
125
126 self.matplotlib_2D_menu = self.matplotlib_menu.addMenu("2D plots")
127 self._setup_mpl_submenu(self.matplotlib_2D_menu, maxes, show_ax)
128
129 self.matplotlib_3D_menu = self.matplotlib_menu.addMenu("3D plots")
130 self._setup_mpl_submenu(self.matplotlib_3D_menu, maxes3d, show_ax3d)
131
132 self.matplotlib_figs_menu = self.matplotlib_menu.addMenu("Complex plots")
133 self._setup_mpl_submenu(self.matplotlib_figs_menu, mfigs, show_fig)
134
135 self.matplotlib_misc_menu = self.matplotlib_menu.addMenu("Others")
136 for smthng in mmisc.__all__:
137 mpl_action = QtGui.QAction(smthng, self)
138 show_mpl = self._mpl_prepare_fn(getattr(mmisc, smthng))
139 mpl_action.triggered.connect(show_mpl)
140 self.matplotlib_misc_menu.addAction(mpl_action)
141 # prevent GC from wiping out both Qt object and our function
142 self.matplotlib_actions.append((mpl_action, show_mpl))
143
144 except ImportError as e:
145 msg = "Matplotlib related features are unavailiable"
146 print(self.__class__.__name__ + ":", msg, repr(e))
147
148 def _setup_mpl_submenu(self, menu, module, handler):
149 for drawing in module.__all__:
150 mpl_action = QtGui.QAction(drawing, self)
151 # do not really understand what I am doing :(
152 # try to show_mpl remember its actual drawing string
153 show_mpl = self._mpl_prepare_show_fn(handler, getattr(module, drawing))
154 mpl_action.triggered.connect(show_mpl)
155 menu.addAction(mpl_action)
156 # prevent GC from wiping out both Qt object and our function
157 self.matplotlib_actions.append((mpl_action, show_mpl))
158
159 def _mpl_prepare_show_fn(self, show, to_draw):
160 return lambda: show(to_draw, self.get_sample_box(), space=self.space)
161 124
162 def _mpl_prepare_fn(self, fn):
163 return lambda: fn(sample_box=self.get_sample_box(), space=self.space)
164 125
165 126 def get_sample_box(self): def get_sample_box(self):
166 127 nsim = self.slider.value() nsim = self.slider.value()
 
... ... class QtGuiWindow(QtWidgets.QMainWindow):
169 130 else: else:
170 131 return self.sample_box[:nsim] return self.sample_box[:nsim]
171 132
172 # INHERITED by gl_plot
133
173 134 # intended as a common setup function # intended as a common setup function
174 135 def setup(self): def setup(self):
175
176
177 136 self.setup_menubar() self.setup_menubar()
178 137
179 138 ### Create some widgets to be placed inside ### Create some widgets to be placed inside
139 self.combo_metric = pg.ComboBox(items=self.metrics, default=self.metric)
140 self.combo_metric.activated[str].connect(self.change_metric)
141
180 142 self.combo_space = pg.ComboBox(items=self.spaces, default=self.space) self.combo_space = pg.ComboBox(items=self.spaces, default=self.space)
181 143 self.combo_space.activated[str].connect(self.change_space) self.combo_space.activated[str].connect(self.change_space)
182 144
 
... ... class QtGuiWindow(QtWidgets.QMainWindow):
186 148
187 149 self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
188 150 self.slider.valueChanged.connect(self._slider_chainged) self.slider.valueChanged.connect(self._slider_chainged)
189 self.slider.sliderReleased.connect(lambda:self.slice_changed.emit())
151 self.slider.sliderReleased.connect(lambda:self.slice_changed.emit(self.slider.value()))
190 152 self.slider.setMaximum(self.sample_box.nsim) self.slider.setMaximum(self.sample_box.nsim)
191 153 self.slider.setValue(self.sample_box.nsim) self.slider.setValue(self.sample_box.nsim)
192 154
 
... ... class QtGuiWindow(QtWidgets.QMainWindow):
200 162 # self.btn2 = QtWidgets.QPushButton('connect/disconnect') # self.btn2 = QtWidgets.QPushButton('connect/disconnect')
201 163 # self.btn2.setCheckable(True) # self.btn2.setCheckable(True)
202 164 # self.btn2.clicked.connect(self.bx_connect) # self.btn2.clicked.connect(self.bx_connect)
203
204 self.btn3 = QtWidgets.QPushButton('redraw')
205 self.btn3.clicked.connect(lambda:self.redraw_called.emit())
206
207
165
208 166 ## Create a grid layout to manage the widgets size and position ## Create a grid layout to manage the widgets size and position
209 167 self.layout = pg.LayoutWidget() self.layout = pg.LayoutWidget()
210 168 self.setCentralWidget(self.layout) self.setCentralWidget(self.layout)
211 #self.w.setLayout(self.layout)
212 169
213 #
214 self.list_view = QtWidgets.QListWidget()
170 self.image_view = MView(self, parent=self.layout)
171
172 self.btn3 = QtWidgets.QPushButton('auto levels')
173 self.btn3.clicked.connect(lambda:self.image_view.autoLevels())
174
175
176
177
178
215 179
216 180 ## Add widgets to the layout in their proper positions ## Add widgets to the layout in their proper positions
217 181 #self.layout.addWidget(self.list_view, 0, 0, 2, 1) #self.layout.addWidget(self.list_view, 0, 0, 2, 1)
218 self.layout.addWidget(self.combo_space, 0, 0)
219 self.layout.addWidget(self.slider, 0, 1)
220 self.layout.addWidget(self.label_nsim, 0, 2)
221 self.layout.addWidget(self.btn, 0, 3)
182 self.layout.addWidget(self.combo_metric, 0, 0)
183 self.layout.addWidget(self.combo_space, 0, 1)
184 self.layout.addWidget(self.slider, 0, 2)
185 self.layout.addWidget(self.label_nsim, 0, 3)
186 self.layout.addWidget(self.btn, 0, 4)
222 187 #self.layout.addWidget(self.btn2, 0, 4) #self.layout.addWidget(self.btn2, 0, 4)
223 self.layout.addWidget(self.btn3, 0, 4)
224 self.layout.addWidget(self.central_widget, 1, 0, 1, 5)
188 self.layout.addWidget(self.btn3, 0, 5)
189 self.layout.addWidget(self.image_view, 1, 0, 1, 6)
225 190
226 191
227 192
228 193 # status bar, mainly to observe BlackBox # status bar, mainly to observe BlackBox
229 194 self.statusBar = QtWidgets.QStatusBar() self.statusBar = QtWidgets.QStatusBar()
230 195 self.setStatusBar(self.statusBar) self.setStatusBar(self.statusBar)
231 self.btn_continue = QtWidgets.QPushButton('continue')
232 self.continue_label = QtWidgets.QLabel()
233 # self.continue_layout = QtGui.QHBoxLayout()
234 # self.continue_layout.addWidget(self.btn_continue)
235 # self.continue_layout.addWidget(self.continue_label)
236 self.statusBar.addWidget(self.btn_continue)
237 self.statusBar.addWidget(self.continue_label)
238 self.btn_continue.hide()
239 self.continue_label.hide()
240
241 self.statusBar.showMessage("Vitáme vás u nás!")
242
243
244 196
197 self.dm = DistanceMatrix(self)
245 198
246 199 # Dockables, najzajimavejší věc # Dockables, najzajimavejší věc
247 200 self.dockables = [] self.dockables = []
248 201
249 202
250 dock = QtWidgets.QDockWidget("Interactive python console", self)
251 dock.setWidget(console.ConsoleWidget(namespace={**locals(), **globals()}))
252 self.dockables.append(dock)
253 self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, dock)
254
255
256 dock = QtWidgets.QDockWidget("BlackBox output", self)
257 self.output_label = QtWidgets.QLabel()
258 dock.setWidget(self.output_label)
259 self.dockables.append(dock)
260 self.tabifyDockWidget(self.dockables[0], dock)
261
262 self.simplex_data = qt_graph_widgets.SimplexEstimationData(self.sample_box, self)
263 #č graphy už nemusí jít po stm widgetech
264 dock = QtWidgets.QDockWidget("TRI_overall estimation graph", self)
265 dock.setWidget(qt_graph_widgets.TriEstimationGraph(self.sample_box, 'TRI_overall_estimations', self, dock))
266 self.dockables.append(dock)
267 self.tabifyDockWidget(self.dockables[0], dock)
268
269 dock = QtWidgets.QDockWidget("Simplex estimation graph", self)
270 dock.setWidget(qt_graph_widgets.SimpleSimplexEstimationGraph(self.sample_box, self, dock))
271 self.dockables.append(dock)
272 self.tabifyDockWidget(self.dockables[0], dock)
273
274 dock = QtWidgets.QDockWidget("Simplex error graph", self)
275 dock.setWidget(qt_graph_widgets.SimplexErrorGraph(self.simplex_data, dock))
276 self.dockables.append(dock)
277 self.tabifyDockWidget(self.dockables[0], dock)
278
279 dock = QtWidgets.QDockWidget("Voronoi estimation graph", self)
280 dock.setWidget(qt_graph_widgets.VoronoiEstimationGraph(self.sample_box, self, dock))
281 self.dockables.append(dock)
282 self.tabifyDockWidget(self.dockables[0], dock)
283
284 dock = QtWidgets.QDockWidget("GRaph", self)
285 dock.setWidget(qt_graph_widgets.GRaph(self, dock))
286 self.dockables.append(dock)
287 self.tabifyDockWidget(self.dockables[0], dock)
288
289
290
291 dock = dock_l = QtWidgets.QDockWidget("Box tree", self)
292 dock.setWidget(BoxTreeWidget(self, dock))
293 self.dockables.append(dock)
294 self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, dock)
295
296
203 #self.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock)
297 204
298 dock = QtWidgets.QDockWidget("View", self)
299 dock.setWidget(self.list_view)
300 self.dockables.append(dock)
301 self.tabifyDockWidget(dock_l, dock)
302 205
303 206
304 207
 
... ... class QtGuiWindow(QtWidgets.QMainWindow):
311 214
312 215
313 216
314
315 217 csv_filter = "CSV files (*.csv)" csv_filter = "CSV files (*.csv)"
316 218 npy_filter = "NumPy binary files (*.npy)" npy_filter = "NumPy binary files (*.npy)"
317 219 txt_filter = "Text files (*.txt)" txt_filter = "Text files (*.txt)"
 
... ... class QtGuiWindow(QtWidgets.QMainWindow):
439 341 self.slider.setMaximum(self.sample_box.nsim) self.slider.setMaximum(self.sample_box.nsim)
440 342 self.label_nsim.setText(str(value)) self.label_nsim.setText(str(value))
441 343 if not self.slider.isSliderDown(): # co to vůbec děla? if not self.slider.isSliderDown(): # co to vůbec děla?
442 self.slice_changed.emit()
344 self.slice_changed.emit(value)
443 345
444 # INHERITED by gl_plot
346
445 347 def change_space(self, space): def change_space(self, space):
446 348 self.space = space self.space = space
447 self.space_changed.emit()
448 #self.plot_widget_2d()
449 #self.slice_plot_data()
349 self.space_changed.emit(space)
350
351 def change_metric(self, metric):
352 self.metric = metric
353 self.metric_changed.emit(metric)
450 354
451 355 # INHERITED by gl_plot # INHERITED by gl_plot
452 356 def run_sb(self): def run_sb(self):
453 357 with pg.BusyCursor(): with pg.BusyCursor():
454 358 self.last_shot = self.sample_box() self.last_shot = self.sample_box()
455 359 self.box_runned.emit() self.box_runned.emit()
456
360
361
457 362 def wake_up_slider(self): def wake_up_slider(self):
458 363 # slider # slider
459 364 #č zpusobí slice_changed #č zpusobí slice_changed
460 365 self.slider.setMaximum(self.sample_box.nsim) self.slider.setMaximum(self.sample_box.nsim)
461 366 self.slider.setValue(self.sample_box.nsim) self.slider.setValue(self.sample_box.nsim)
462 367
463 # INHERITED by gl_plot
464 def bx_connect(self):
465 if self.btn2.isChecked():
466 try:
467 self.sample_box.connect(self.logger)
468 except BaseException as e:
469 print(self.__class__.__name__ + ":", "connection to BlackBox failed", repr(e))
470 else:
471 try:
472 self.sample_box.disconnect()
473 except BaseException as e:
474 print(self.__class__.__name__ + ":", "error while disconnecting of BlackBox", repr(e))
475
476 # INHERITED by gl_plot
477 def logger(self, *args, msg="", indent=0, **kwargs):
478 self.continue_label.setText("BlackBox: " + msg)
479 self.output_label.setText(str(args) + str(kwargs))
480
481 loop = QtCore.QEventLoop()
482 self.btn_continue.clicked.connect(loop.quit)
483 self.btn_continue.show()
484 self.continue_label.show()
485 # i want to clear status bar temporaly
486 status = self.statusBar.currentMessage()
487 self.statusBar.clearMessage()
488
489 loop.exec_() # Execution stops here until finished called
490
491 self.btn_continue.hide()
492 self.continue_label.hide()
493 self.statusBar.showMessage(status)
494
495 368 def add_random_points(self): def add_random_points(self):
496 369 ns, ok = QtWidgets.QInputDialog.getInt( ns, ok = QtWidgets.QInputDialog.getInt(
497 370 self,"Add random points","number", value=1, min=1) self,"Add random points","number", value=1, min=1)
 
... ... class QtGuiWindow(QtWidgets.QMainWindow):
525 398 if dlg.wasCanceled(): if dlg.wasCanceled():
526 399 break break
527 400
528
529 def gen_dmatrix(self):
530 self.distance_matrix()
531
532 def distance_matrix(self, p=2):
533 nsim = self.slider.value()
534
535 sample_box = self.sample_box[:nsim]
536 if nsim > 0:
537 sample_space = getattr(sample_box, self.space)
538 dmatrix = spatial.distance_matrix(sample_space, sample_space, p=p)
539 mask = np.zeros((nsim, nsim))
540
541 failure_points = self.sample_box[:nsim].failure_points
542 mask[failure_points] += 0.5
543 mask[:, failure_points] += 0.5
544 #č vůbec nechápu, jak to numpy rozřezavá
545 #č nedavá mi to smysl
546 #č takhle funguje, jinak nefunguje
547 #mask[failure_points][:,failure_points] = 0
548
549 CS = ConvexSpline(sample_space)
550 contacts = np.zeros((nsim, nsim), dtype=np.bool8)
551 for i in range(nsim):
552 for j in range(i):
553 contacts[i, j] = CS.is_couple((i, j))
554
555 #pg.image(data, levelMode='rgba', title="Distance matrix, p=%s" % p)
556 w = DMView(dmatrix, mask, contacts)
557 w.setWindowTitle("Distance matrix, p=%s" % p)
558 401
559 402
560 403
561 404
562 405
563
564
565
566 """
567 ===========
568 ♥ Чыры-пыры
569 č Jiné
570 E Miscellaneous
571 ===============
572 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
573 """
574
575 #č pg trik, aby GC nám nevymazal paměť
576 images = []
577
578 class DMView(pg.ImageView):
579 def __init__(self, dmatrix, mask, contacts, *args, **kwargs):
580 self.dmatrix = dmatrix
581 self.contacts = contacts
582 self.nsim = nsim = len(dmatrix)
583 data = np.empty((nsim, nsim, 3))
584 data[:,:,0] = dmatrix * mask
585 data[:,:,1] = dmatrix * (1 - mask)
586 data[:,:,2] = contacts
587
406 class MView(pg.ImageView):
407 mouse_moved = QtCore.pyqtSignal(int, int)
408
409 def __init__(self, w, *args, **kwargs):
588 410 self.pi = pg.PlotItem() self.pi = pg.PlotItem()
589 super().__init__(*args, view=self.pi, **kwargs)
590 #č pg trik, aby GC nám nevymazal paměť
591 images.append(self)
411 super().__init__(*args, view=self.pi, **kwargs) #axisOrder='row-major',
412
413 w.slice_changed.connect(self.on_slice_changed)
414
415 self.nsim = nsim = w.slider.value()
416
417 self.data = np.empty((3, nsim, nsim))
418 self.data[2] = 0
592 419
593 420 self.show() self.show()
594 self.setImage(data, levelMode='rgba')
421 #self.setImage(data, levelMode='rgba')
422 #self.setBackground('w')
595 423
596 self.proxy = pg.SignalProxy(self.pi.scene().sigMouseMoved,
597 rateLimit=60, slot=self.mouse_moved)
598 424
599
600 def mouse_moved(self, evt):
425 self.proxy = pg.SignalProxy(self.pi.scene().sigMouseMoved,
426 rateLimit=60, slot=self._mouse_moved)
427
428
429 def __setattr__(self, attr, value):
430 if attr == 'red':
431 self.data[0] = value
432 elif attr == 'green':
433 self.data[1] = value
434 elif attr == 'blue':
435 self.data[2] = value
436 else:
437 self.__dict__[attr] = value
438
439
440
441 def __getattr__(self, attr):
442 if attr == 'red':
443 return data[0]
444 if attr == 'green':
445 return data[1]
446 if attr == 'blue':
447 return data[2]
448 raise AttributeError(attr)
449
450
451 def on_slice_changed(self, nsim):
452 #č resize nejde. Asi pyqtgraph drží referenci
453 #č i když já pekně vím, že ta data kopíruje a pro Qt normalizuje
454 self.data = np.empty((3, nsim, nsim))
455 #č zelené-červené barvy přepíše distance matrix
456 #č za modrou ale nikdo zodpovednost nenese
457 self.data[2] = 0
458 self.nsim = nsim
459
460
461 def update(self):
462 self.setImage(self.data.T, levelMode='rgba')
463
464 def _mouse_moved(self, evt):
601 465 pos = evt[0] ## using signal proxy turns original arguments into a tuple pos = evt[0] ## using signal proxy turns original arguments into a tuple
602 466 if self.pi.sceneBoundingRect().contains(pos): if self.pi.sceneBoundingRect().contains(pos):
603 467 mousePoint = self.pi.vb.mapSceneToView(pos) mousePoint = self.pi.vb.mapSceneToView(pos)
604 468 x = int(mousePoint.x()) x = int(mousePoint.x())
605 469 y = int(mousePoint.y()) y = int(mousePoint.y())
606 nsim = self.nsim
607 if x >= 0 and x < nsim and y >= 0 and y < nsim:
608 val = self.dmatrix[x,y]
609 msg = "distance between %d and %d is %g\n" % (x, y, val)
610 if self.contacts[max(x,y), min(x,y)]:
611 msg += "There is contact between them"
612 else:
613 msg += "There is no contact between them"
614
615 self.pi.setTitle(msg)
616
617
618
619
470 if (x >= 0) and (x < self.nsim) and (y >= 0) and (y < self.nsim):
471 self.mouse_moved.emit(x, y)
620 472
621 473
622 474
623 class BoxTreeWidget(pg.LayoutWidget):
624 """
625 """
626 # I'd like to get access to the samplebox stuff via the container's reference,
627 # but relying to Qt's parent mechanism makes me worry.
628 def __init__(self, samplebox_item, parent=None, *args, **kwargs):
629 super().__init__(parent)
630 # sb like samplebox, of course
631 self.sb_item = samplebox_item
632
633
634 self.btn = QtWidgets.QPushButton('update')
635 self.addWidget(self.btn, row=0, col=0)
636 self.btn.clicked.connect(self.update)
637
638 #self.tree = pg.DataTreeWidget(self, data=self.get_data(samplebox_item))
639 self.tree = pg.DataTreeWidget(self, data=dict())
640 self.addWidget(self.tree, row=1, col=0)
641 475
642 def update(self, *args, **kwargs):
643 try:
644 self.tree.setData(self.get_data(self.sb_item), hideRoot=True)
645 except BaseException as e:
646 msg = ""
647 error_msg = self.__class__.__name__ + ": " + msg + repr(e)
648 print(error_msg)
476 class DistanceMatrix:
477 def __init__(self, w):
478 self.w = w
479
480 w.image_view.mouse_moved.connect(self.on_mouse_moved)
481
482 w.metric_changed.connect(self.on_some_stuff_changed)
483 w.space_changed.connect(self.on_some_stuff_changed)
484 w.slice_changed.connect(self.on_nsim_changed)
485 w.redraw_called.connect(self.on_some_stuff_changed)
486
487 n = w.slider.value()
488 self.condensed_matrix = np.empty(n * (n - 1) // 2)
489 self.nsim = n
490
491 def on_nsim_changed(self, n):
492 self.condensed_matrix.resize(n * (n - 1) // 2)
493 self.nsim = n
494
495 self.on_some_stuff_changed()
496
497 def on_some_stuff_changed(self, *args, **kwargs):
498 sample_box = self.w.get_sample_box()
499 nsim = sample_box.nsim
500 if nsim > 0:
501 X = getattr(sample_box, self.w.space)
502 spatial.distance.pdist(X, self.w.metric, out=self.condensed_matrix)
649 503
650 @staticmethod
651 def get_data(self): #č nenechej si splest tím "self", je to prostě reference na QtGuiPlot2D
652 data_tree = dict()
653 data_tree['self.sample_box'] = self.sample_box.__dict__
654 try: # shapeshare
655 data_tree['self.sample_box.shapeshare'] = self.sample_box.shapeshare.__dict__
656 except AttributeError:
657 pass
658 try:
659 data_tree['self.sample_box.dicebox'] = self.sample_box.dicebox.__dict__
660 except AttributeError:
661 pass
662 try:
663 data_tree['self.sample_box.reader'] = self.sample_box.reader.__dict__
664 except AttributeError:
665 pass
666 try:
667 data_tree['self.sample_box.samplebox'] = self.sample_box.samplebox.__dict__
668 except AttributeError:
669 pass
670 try:
671 data_tree['self.sample_box.candybox'] = self.sample_box.candybox.__dict__
672 except AttributeError:
673 pass
674 try:
675 data_tree['self.sample_box.f_model'] = self.sample_box.f_model.__dict__
676 except AttributeError:
677 pass
504 mask = np.zeros((nsim, nsim))
678 505
679 return data_tree
506 failure_points = sample_box.failure_points
507 mask[failure_points] += 0.5
508 mask[:, failure_points] += 0.5
509
510 dmatrix = spatial.distance.squareform(self.condensed_matrix)
511
512 self.w.image_view.red = dmatrix * mask
513 self.w.image_view.green = dmatrix * (1 - mask)
514 self.w.image_view.update()
515
516 self.w.statusBar.showMessage("")
517
518
519 def on_mouse_moved(self, x, y):
520 if x != y:
521 m = self.nsim
522 i, j = min(x, y), max(x, y)
523 entry = m * i + j - ((i + 2) * (i + 1)) // 2
524 val = self.condensed_matrix[entry]
525 else:
526 val = 0
527 msg = "distance between %d and %d is %g" % (x, y, val)
528 self.w.statusBar.showMessage(msg)
529
680 530
681 531
682
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/iam-git/WellMet

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/iam-git/WellMet

Clone this repository using git:
git clone git://git.rocketgit.com/user/iam-git/WellMet

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main