File qt_gui/qt_graph_widgets.py added (mode: 100644) (index 0000000..669c87a) |
|
1 |
|
#!/usr/bin/env python |
|
2 |
|
# coding: utf-8 |
|
3 |
|
|
|
4 |
|
import pyqtgraph as pg |
|
5 |
|
from pyqtgraph.Qt import QtGui |
|
6 |
|
from pyqtgraph.Qt import QtCore |
|
7 |
|
|
|
8 |
|
import numpy as np |
|
9 |
|
import pandas as pd # required for estimation graph |
|
10 |
|
|
|
11 |
|
|
|
12 |
|
|
|
13 |
|
from .. import stm_df |
|
14 |
|
""" |
|
15 |
|
============= |
|
16 |
|
График виӝет |
|
17 |
|
Grafy |
|
18 |
|
Estimation graph widgets |
|
19 |
|
======================== |
|
20 |
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
21 |
|
""" |
|
22 |
|
|
|
23 |
|
|
|
24 |
|
def get_estimation_data(estimations, metric): |
|
25 |
|
metric_dict = dict() |
|
26 |
|
# new-style: šecko leží dohromady a každý z toho |
|
27 |
|
# bere co chce a jak chce |
|
28 |
|
# ne že by to bylo nějak šetrný |
|
29 |
|
# estimation je slovníkem |
|
30 |
|
for estimation in estimations: |
|
31 |
|
# nsim musí mäť každej odhad |
|
32 |
|
# pokud nemá - je třeba jej prostě opravit |
|
33 |
|
nsim = estimation['nsim'] |
|
34 |
|
try: |
|
35 |
|
metric_dict[nsim] = estimation[metric] |
|
36 |
|
except KeyError as e: |
|
37 |
|
pass #print(self.__class__.__name__ + ":", repr(e)) |
|
38 |
|
|
|
39 |
|
# nikdo neslibil, že budou v pořadí |
|
40 |
|
x = np.sort(tuple(metric_dict.keys())) |
|
41 |
|
y = np.array(tuple(metric_dict.values()))[np.argsort(tuple(metric_dict.keys()))] |
|
42 |
|
return x, y |
|
43 |
|
|
|
44 |
|
|
|
45 |
|
class SimplexEstimationData(QtCore.QObject): |
|
46 |
|
#š budeme mӓť svůj vlastní signaľčík |
|
47 |
|
simplex_estimation_updated = QtCore.pyqtSignal() |
|
48 |
|
|
|
49 |
|
def __init__(self, dice_box, stream=None, *args, **kwargs): |
|
50 |
|
super().__init__(stream, *args, **kwargs) |
|
51 |
|
self.dice_box = dice_box |
|
52 |
|
#č je zřejmě, že tím potokem bylo myšleno hlavní okínko |
|
53 |
|
#č asi aby nepadalo, když nenajde signaly |
|
54 |
|
self.stream = stream |
|
55 |
|
if stream is not None: |
|
56 |
|
self.stream.box_runned.connect(self.recalculate) |
|
57 |
|
self.stream.estimation_added.connect(self.recalculate) |
|
58 |
|
|
|
59 |
|
self.setup_context_menu() |
|
60 |
|
self.recalculate() |
|
61 |
|
|
|
62 |
|
|
|
63 |
|
def setup_context_menu(self): |
|
64 |
|
# simplex_data_menu |
|
65 |
|
self.TRI_menu = QtGui.QMenu("TRI sources", self.stream) |
|
66 |
|
|
|
67 |
|
self.TRI_overall_chk = QtGui.QAction("TRI_overall_estimations", self.TRI_menu) |
|
68 |
|
self.TRI_overall_chk.setCheckable(True) |
|
69 |
|
self.TRI_overall_chk.setChecked(True) |
|
70 |
|
self.TRI_overall_chk.triggered.connect(self.recalculate) |
|
71 |
|
self.TRI_menu.addAction(self.TRI_overall_chk) |
|
72 |
|
|
|
73 |
|
self.simplex_chk = QtGui.QAction("Simplex estimations", self.TRI_menu) |
|
74 |
|
self.simplex_chk.setCheckable(True) |
|
75 |
|
self.simplex_chk.setChecked(True) |
|
76 |
|
self.simplex_chk.triggered.connect(self.recalculate) |
|
77 |
|
self.TRI_menu.addAction(self.simplex_chk) |
|
78 |
|
|
|
79 |
|
# year, it was |
|
80 |
|
## hope, it is temporary |
|
81 |
|
#self.sources_action_group = QtGui.QActionGroup(self.TRI_menu) |
|
82 |
|
#self.sources_action_group.addAction(self.TRI_overall_chk) |
|
83 |
|
#self.sources_action_group.addAction(self.simplex_chk) |
|
84 |
|
|
|
85 |
|
self.TRI_menu.addSeparator() |
|
86 |
|
|
|
87 |
|
self.proxy_chk = QtGui.QAction("Proxy", self.TRI_menu) |
|
88 |
|
self.proxy_chk.setCheckable(True) |
|
89 |
|
self.proxy_chk.setChecked(hasattr(self.dice_box, 'proxy')) |
|
90 |
|
self.proxy_chk.triggered.connect(self.recalculate) |
|
91 |
|
self.TRI_menu.addAction(self.proxy_chk) |
|
92 |
|
|
|
93 |
|
self.TRI_menu.addSeparator() |
|
94 |
|
|
|
95 |
|
self.reaction = QtGui.QAction("Update", self.TRI_menu) |
|
96 |
|
self.reaction.triggered.connect(self.recalculate) |
|
97 |
|
self.TRI_menu.addAction(self.reaction) |
|
98 |
|
|
|
99 |
|
self.excelaction = QtGui.QAction("Export to Excel", self.TRI_menu) |
|
100 |
|
self.excelaction.triggered.connect(self.export_to_excel) |
|
101 |
|
self.TRI_menu.addAction(self.excelaction) |
|
102 |
|
|
|
103 |
|
|
|
104 |
|
def export_to_excel(self): |
|
105 |
|
#č já bych nechtěl, aby mně export najednou spadl |
|
106 |
|
#č z jakéhokoliv důvodu |
|
107 |
|
try: |
|
108 |
|
proposal_filename = self.dice_box.guessbox.filename |
|
109 |
|
if proposal_filename: |
|
110 |
|
proposal_filename += '.xlsx' |
|
111 |
|
else: |
|
112 |
|
proposal_filename = self.dice_box.gm_signature + '.xlsx' |
|
113 |
|
filename, *__ = pg.FileDialog.getSaveFileName(self.stream, 'Export to Excel',\ |
|
114 |
|
proposal_filename, initialFilter='*.xlsx') |
|
115 |
|
self.df.to_excel(filename) |
|
116 |
|
except BaseException as e: |
|
117 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
118 |
|
|
|
119 |
|
|
|
120 |
|
def recalculate(self): |
|
121 |
|
try: |
|
122 |
|
# sources=['box', 'user'] |
|
123 |
|
sources = list() |
|
124 |
|
if self.TRI_overall_chk.isChecked(): |
|
125 |
|
sources.append('box') |
|
126 |
|
if self.simplex_chk.isChecked(): |
|
127 |
|
sources.append('user') |
|
128 |
|
|
|
129 |
|
self.df = stm_df.get_tri_data_frame(self.dice_box, sources=sources,\ |
|
130 |
|
apply_proxy=self.proxy_chk.isChecked()) |
|
131 |
|
self.simplex_estimation_updated.emit() |
|
132 |
|
|
|
133 |
|
except BaseException as e: |
|
134 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
135 |
|
|
|
136 |
|
|
|
137 |
|
|
|
138 |
|
class SimplexEstimationGraph(pg.PlotWidget): |
|
139 |
|
def __init__(self, dice_box, stream=None, parent=None, *args, **kwargs): |
|
140 |
|
super().__init__(parent, *args, **kwargs) |
|
141 |
|
#č je zřejmě, že tím potokem bylo myšleno hlavní okínko |
|
142 |
|
#č asi aby nepadalo, když nenajde signaly |
|
143 |
|
self.stream = stream |
|
144 |
|
if stream is not None: |
|
145 |
|
self.stream.box_runned.connect(self.redraw) |
|
146 |
|
self.stream.estimation_added.connect(self.redraw) |
|
147 |
|
|
|
148 |
|
self.dice_box = dice_box |
|
149 |
|
|
|
150 |
|
self.setup_context_menu() |
|
151 |
|
self.setup() |
|
152 |
|
self.replot() |
|
153 |
|
|
|
154 |
|
def setup_context_menu(self): |
|
155 |
|
# creates instance of LegendItem |
|
156 |
|
# and saves it into plotItem.legend |
|
157 |
|
self.legend = self.addLegend() |
|
158 |
|
|
|
159 |
|
self.plotItem.ctrl.xGridCheck.setChecked(True) |
|
160 |
|
self.plotItem.ctrl.yGridCheck.setChecked(True) |
|
161 |
|
|
|
162 |
|
# delete build-in Transforms (with Log_x and Log_y) options, |
|
163 |
|
# they can cause uncachable exception (on any zero in data) and crash |
|
164 |
|
self.plotItem.ctrlMenu.removeAction(self.plotItem.ctrlMenu.actions()[0]) |
|
165 |
|
|
|
166 |
|
#č já se bojím. radší to uložím |
|
167 |
|
self.custom_menu = self.plotItem.vb.menu.addMenu("TRI options") |
|
168 |
|
|
|
169 |
|
self.plotItem.vb.menu.addMenu(self.stream.simplex_data.TRI_menu) |
|
170 |
|
|
|
171 |
|
self.legend_chk = QtGui.QAction("Legend", self.custom_menu) |
|
172 |
|
self.legend_chk.setCheckable(True) |
|
173 |
|
self.legend_chk.triggered.connect(lambda: self.legend.setVisible(self.legend_chk.isChecked())) |
|
174 |
|
self.custom_menu.addAction(self.legend_chk) |
|
175 |
|
# apply custom menu option |
|
176 |
|
self.legend.setVisible(self.legend_chk.isChecked()) |
|
177 |
|
|
|
178 |
|
self.log_x_chk = QtGui.QAction("Log X", self.custom_menu) |
|
179 |
|
self.log_x_chk.setCheckable(True) |
|
180 |
|
self.log_x_chk.triggered.connect(lambda: self.setLogMode(x=self.log_x_chk.isChecked())) |
|
181 |
|
self.custom_menu.addAction(self.log_x_chk) |
|
182 |
|
|
|
183 |
|
self.log_y_chk = QtGui.QAction("Log Y", self.custom_menu) |
|
184 |
|
self.log_y_chk.setCheckable(True) |
|
185 |
|
self.log_y_chk.setChecked(True) |
|
186 |
|
self.log_y_chk.triggered.connect(self.replot) |
|
187 |
|
self.custom_menu.addAction(self.log_y_chk) |
|
188 |
|
|
|
189 |
|
self.laction = QtGui.QAction("Show labels", self.custom_menu) |
|
190 |
|
self.laction.triggered.connect(self.show_labels) |
|
191 |
|
self.custom_menu.addAction(self.laction) |
|
192 |
|
|
|
193 |
|
|
|
194 |
|
def show_labels(self): |
|
195 |
|
self.setLabel('left', "Probability measure") |
|
196 |
|
self.setLabel('bottom', "Number of simulations") |
|
197 |
|
|
|
198 |
|
|
|
199 |
|
|
|
200 |
|
# self.legend.addItem(self.pen_success, "success domain estimation") |
|
201 |
|
# self.legend.addItem(self.pen_outside, "out of sampling domain estimation") |
|
202 |
|
# self.legend.addItem(self.pen_mix, "mixed simplices measure") |
|
203 |
|
# self.legend.addItem(self.pen_f, "failure domain estimation") |
|
204 |
|
|
|
205 |
|
def setup(self, *args, **kwargs): |
|
206 |
|
self.clear() |
|
207 |
|
self.setBackground('w') |
|
208 |
|
x = y = () # zde jen vytvoříme kostru, nakrmime daty v .redraw() |
|
209 |
|
|
|
210 |
|
#xkcd_green = (167, 255, 181) # xkcd:light seafoam green #a7ffb5 |
|
211 |
|
green = (0, 255, 38, 96) |
|
212 |
|
#xkcd_red = (253, 193, 197) # xkcd: pale rose (#fdc1c5) |
|
213 |
|
red = (253, 0, 17, 96) |
|
214 |
|
#xkcd_cream = (255, 243, 154) # let's try xkcd: dark cream (#fff39a) |
|
215 |
|
cream = (255, 221, 0, 96) |
|
216 |
|
grey = (196, 196, 196, 96) |
|
217 |
|
|
|
218 |
|
self.pen_f = self.plot(x, y, brush=red)#, name="failure domain estimation") |
|
219 |
|
self.pen_f.setZValue(-100) |
|
220 |
|
|
|
221 |
|
self.pen_success = self.plot(x, y, brush=green) #, name="success domain estimation") |
|
222 |
|
self.pen_success.setZValue(-100) |
|
223 |
|
|
|
224 |
|
self.pen_outmix = self.plot(x, y) |
|
225 |
|
|
|
226 |
|
self.fill_mix = pg.FillBetweenItem(self.pen_f, self.pen_outmix) |
|
227 |
|
#self.fill_mix.setData(name="mixed simplices measure") |
|
228 |
|
self.fill_mix.setBrush(cream) |
|
229 |
|
self.fill_mix.setZValue(-100) |
|
230 |
|
self.addItem(self.fill_mix) |
|
231 |
|
|
|
232 |
|
#self.pen_outside = self.plot(x, y) |
|
233 |
|
self.fill_outside = pg.FillBetweenItem(self.pen_outmix, self.pen_success) |
|
234 |
|
#self.fill_outside.setData(name="out of sampling domain estimation") |
|
235 |
|
self.fill_outside.setBrush(grey) |
|
236 |
|
self.fill_outside.setZValue(-100) |
|
237 |
|
self.addItem(self.fill_outside) |
|
238 |
|
|
|
239 |
|
self.one_ruler = self.addLine(y=1, pen='k') |
|
240 |
|
self.zero_ruler = self.addLine(y=0, pen='k') |
|
241 |
|
|
|
242 |
|
|
|
243 |
|
try: |
|
244 |
|
exact_name = self.dice_box.pf_exact_method |
|
245 |
|
pen = pg.mkPen(color='b', width=1.5) # blue |
|
246 |
|
self.pen_exact = self.addLine(y=self.dice_box.pf_exact, pen=pen, name=exact_name) |
|
247 |
|
#č aby se nám něco zobrazovalo v legendu |
|
248 |
|
self.pen_exact_PR = self.plot(x, y, pen=pen, name=exact_name) |
|
249 |
|
except: |
|
250 |
|
pass |
|
251 |
|
|
|
252 |
|
pen = pg.mkPen(color='m', width=2) |
|
253 |
|
self.pen_vertex = self.plot(x, y, pen=pen, name="simple pf estimation") |
|
254 |
|
pen = pg.mkPen(color='r', width=2) #(118, 187, 255) |
|
255 |
|
self.pen_weighted_vertex = self.plot(x, y, pen=pen, name="weighted pf estimation") |
|
256 |
|
|
|
257 |
|
|
|
258 |
|
|
|
259 |
|
|
|
260 |
|
|
|
261 |
|
def replot(self, *args, **kwargs): |
|
262 |
|
if self.log_y_chk.isChecked(): |
|
263 |
|
self.one_ruler.hide() |
|
264 |
|
try: |
|
265 |
|
#č try nás nezáchraní protí odloženému spádnutí pyqtgraph |
|
266 |
|
if self.dice_box.pf_exact > 0: |
|
267 |
|
self.pen_exact.setPos(np.log10(self.dice_box.pf_exact)) |
|
268 |
|
self.pen_exact.show() |
|
269 |
|
else: |
|
270 |
|
self.pen_exact.hide() |
|
271 |
|
except: |
|
272 |
|
pass |
|
273 |
|
self.setLogMode(y=True) |
|
274 |
|
#self.pen_f.setPen(pg.mkPen(color=(255, 0, 0), width=3)) #, style=QtCore.Qt.DashLine) |
|
275 |
|
self.pen_f.setPen(None) |
|
276 |
|
self.pen_f.setFillLevel(None) |
|
277 |
|
self.pen_success.setFillLevel(0) |
|
278 |
|
|
|
279 |
|
else: |
|
280 |
|
self.one_ruler.show() |
|
281 |
|
try: |
|
282 |
|
self.pen_exact.setPos(self.dice_box.pf_exact) |
|
283 |
|
self.pen_exact.show() |
|
284 |
|
except: |
|
285 |
|
pass |
|
286 |
|
self.setLogMode(y=False) |
|
287 |
|
self.pen_f.setPen(None) |
|
288 |
|
self.pen_f.setFillLevel(0) |
|
289 |
|
self.pen_success.setFillLevel(1) |
|
290 |
|
|
|
291 |
|
self.redraw() |
|
292 |
|
|
|
293 |
|
|
|
294 |
|
#č když se někde objeví nula se zapnutým LogModem - |
|
295 |
|
#č qtpygraph hned spadne a není možne ten pad zachytit |
|
296 |
|
def zerosafe(self, x, y, fallback_y=None): |
|
297 |
|
if self.log_y_chk.isChecked(): |
|
298 |
|
x = np.array(x) |
|
299 |
|
y = np.array(y) |
|
300 |
|
if fallback_y is None: |
|
301 |
|
fallback_y = y |
|
302 |
|
y = np.where(y > 0, y, fallback_y) |
|
303 |
|
mask = y > 0 |
|
304 |
|
return x[mask], y[mask] |
|
305 |
|
else: |
|
306 |
|
return x, y |
|
307 |
|
|
|
308 |
|
def proxy(self, nsim): |
|
309 |
|
if self.proxy_chk.isChecked(): |
|
310 |
|
proxy = self.dice_box.proxy |
|
311 |
|
index = np.array(nsim)-1 |
|
312 |
|
#č indexy musíme o jedničku změnšit |
|
313 |
|
#č výsledek nikoliv. Takže v cajku. |
|
314 |
|
return np.cumsum(~proxy)[index] |
|
315 |
|
else: |
|
316 |
|
return nsim |
|
317 |
|
|
|
318 |
|
|
|
319 |
|
def _pens_data_update(self): |
|
320 |
|
df = self.df |
|
321 |
|
nsim = df.nsim.to_numpy() |
|
322 |
|
if self.proxy_chk.isChecked(): |
|
323 |
|
x = self.proxy(nsim) |
|
324 |
|
df.insert(loc=0, column='nsim (proxy)', value=x) |
|
325 |
|
else: |
|
326 |
|
x = nsim |
|
327 |
|
# (in case of LogPlot) fallback values also used |
|
328 |
|
success_values = df.failure+df.mix+df.out |
|
329 |
|
outmix_values = df.failure+df.mix |
|
330 |
|
failure_fallback = np.where(outmix_values > 0, outmix_values, success_values) |
|
331 |
|
self.pen_f.setData(*self.zerosafe(x, df.failure, failure_fallback)) |
|
332 |
|
self.pen_outmix.setData(*self.zerosafe(x, outmix_values, success_values)) |
|
333 |
|
self.pen_success.setData(*self.zerosafe(x, success_values)) |
|
334 |
|
|
|
335 |
|
|
|
336 |
|
def redraw(self): |
|
337 |
|
xmin = np.inf |
|
338 |
|
xmax = -np.inf |
|
339 |
|
tri_estimation = dict() |
|
340 |
|
try: # тут всё что угодно может пойти не так |
|
341 |
|
# kruci, ještě navic i generovať pokažde znovu... |
|
342 |
|
|
|
343 |
|
# new-style: šecko leží dohromady a každý si z toho |
|
344 |
|
# bere co chce a jak chce |
|
345 |
|
# ne že by to bylo nějak šetrný |
|
346 |
|
# estimation je slovníkem |
|
347 |
|
for estimation in self.dice_box.estimations: |
|
348 |
|
# nsim musí mäť každej odhad |
|
349 |
|
# pokud nemá - je třeba jej prostě opravit |
|
350 |
|
nsim = estimation['nsim'] |
|
351 |
|
try: |
|
352 |
|
tri_estimation[nsim] = estimation['TRI_estimation'] |
|
353 |
|
if nsim > xmax: |
|
354 |
|
xmax = nsim |
|
355 |
|
if nsim < xmin: |
|
356 |
|
xmin = nsim |
|
357 |
|
|
|
358 |
|
except KeyError as e: |
|
359 |
|
pass #print(self.__class__.__name__ + ":", repr(e)) |
|
360 |
|
|
|
361 |
|
#č neotravuj uživatele chybovejma hlaškama |
|
362 |
|
if tri_estimation: |
|
363 |
|
# it can be effectively done with pandas |
|
364 |
|
self.df = df = pd.DataFrame(tuple(tri_estimation.values())) |
|
365 |
|
# -1 = 'out', 0=success, 1=failure, 2=mix |
|
366 |
|
df.rename(columns={-1:'out', 0:'success', 1:'failure', 2:'mix'}, inplace=True) |
|
367 |
|
df.insert(loc=0, column='nsim', value=tuple(tri_estimation.keys()), allow_duplicates=False) |
|
368 |
|
df.sort_values('nsim', inplace=True) |
|
369 |
|
|
|
370 |
|
self._pens_data_update() |
|
371 |
|
|
|
372 |
|
nsim, y = get_estimation_data(self.dice_box.estimations, 'vertex_estimation') |
|
373 |
|
df['vertex_estimation'] = y #č spolehám na konzistenci odhadů (ne úplně) |
|
374 |
|
self.pen_vertex.setData(*self.zerosafe(self.proxy(nsim), y)) |
|
375 |
|
|
|
376 |
|
nsim, y = get_estimation_data(self.dice_box.estimations, 'weighted_vertex_estimation') |
|
377 |
|
df['weighted_vertex_estimation'] = y #č spolehám na konzistenci odhadů (ne úplně) |
|
378 |
|
self.pen_weighted_vertex.setData(*self.zerosafe(self.proxy(nsim), y)) |
|
379 |
|
|
|
380 |
|
|
|
381 |
|
except BaseException as e: |
|
382 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
383 |
|
|
|
384 |
|
|
|
385 |
|
|
|
386 |
|
class SimplexErrorGraph(pg.PlotWidget): |
|
387 |
|
def __init__(self, simplex_data, parent=None, *args, **kwargs): |
|
388 |
|
super().__init__(parent, *args, **kwargs) |
|
389 |
|
self.simplex_data = simplex_data |
|
390 |
|
self.simplex_data.simplex_estimation_updated.connect(self.redraw) |
|
391 |
|
|
|
392 |
|
self.setup_context_menu() |
|
393 |
|
self.setup() |
|
394 |
|
|
|
395 |
|
def setup_context_menu(self): |
|
396 |
|
# creates instance of LegendItem |
|
397 |
|
# and saves it into plotItem.legend |
|
398 |
|
self.legend = self.addLegend() |
|
399 |
|
|
|
400 |
|
self.plotItem.ctrl.xGridCheck.setChecked(True) |
|
401 |
|
self.plotItem.ctrl.yGridCheck.setChecked(True) |
|
402 |
|
|
|
403 |
|
# menu of SimplexEstimationData |
|
404 |
|
self.plotItem.vb.menu.addMenu(self.simplex_data.TRI_menu) |
|
405 |
|
|
|
406 |
|
#č já se bojím. radší to uložím |
|
407 |
|
self.custom_menu = self.plotItem.vb.menu.addMenu("Error graph") |
|
408 |
|
|
|
409 |
|
self.legend_chk = QtGui.QAction("Legend", self.custom_menu) |
|
410 |
|
self.legend_chk.setCheckable(True) |
|
411 |
|
self.legend_chk.triggered.connect(lambda: self.legend.setVisible(self.legend_chk.isChecked())) |
|
412 |
|
self.custom_menu.addAction(self.legend_chk) |
|
413 |
|
# apply custom menu option |
|
414 |
|
self.legend.setVisible(self.legend_chk.isChecked()) |
|
415 |
|
|
|
416 |
|
self.laction = QtGui.QAction("Show labels", self.custom_menu) |
|
417 |
|
self.laction.triggered.connect(self.show_labels) |
|
418 |
|
self.custom_menu.addAction(self.laction) |
|
419 |
|
|
|
420 |
|
|
|
421 |
|
def show_labels(self): |
|
422 |
|
self.setLabel('left', "Failure probability estimation error") |
|
423 |
|
self.setLabel('bottom', "Number of simulations") |
|
424 |
|
|
|
425 |
|
|
|
426 |
|
def setup(self, *args, **kwargs): |
|
427 |
|
self.clear() |
|
428 |
|
self.setBackground('w') |
|
429 |
|
x = y = () # zde jen vytvoříme kostru, nakrmime daty v .redraw() |
|
430 |
|
|
|
431 |
|
# We will use logMode by default |
|
432 |
|
self.setLogMode(y=True) |
|
433 |
|
|
|
434 |
|
#xkcd_red = (253, 193, 197) # xkcd: pale rose (#fdc1c5) |
|
435 |
|
#red = (253, 0, 17, 96) |
|
436 |
|
|
|
437 |
|
#self.pen_f = self.plot(x, y, brush=red)#, name="failure domain estimation") |
|
438 |
|
#self.pen_f.setZValue(-100) |
|
439 |
|
|
|
440 |
|
|
|
441 |
|
pen = pg.mkPen(color='m', width=2) |
|
442 |
|
self.pen_vertex = self.plot(x, y, pen=pen, name="simple pf estimation") |
|
443 |
|
pen = pg.mkPen(color='r', width=2) #(118, 187, 255) |
|
444 |
|
self.pen_weighted_vertex = self.plot(x, y, pen=pen, name="weighted pf estimation") |
|
445 |
|
|
|
446 |
|
|
|
447 |
|
|
|
448 |
|
#č když se někde objeví nula se zapnutým LogModem - |
|
449 |
|
#č qtpygraph hned spadne a není možne ten pad zachytit |
|
450 |
|
def zerosafe(self, x, y, fallback_y=None): |
|
451 |
|
x = np.array(x) |
|
452 |
|
y = np.array(y) |
|
453 |
|
if fallback_y is None: |
|
454 |
|
fallback_y = y |
|
455 |
|
y = np.where(y > 0, y, fallback_y) |
|
456 |
|
mask = y > 0 |
|
457 |
|
return x[mask], y[mask] |
|
458 |
|
|
|
459 |
|
|
|
460 |
|
def redraw(self): |
|
461 |
|
#č neotravujme uživatele chybovejma hlaškama |
|
462 |
|
if hasattr(self.simplex_data.dice_box, 'pf_exact'): |
|
463 |
|
try: #ё тут всё что угодно может пойти не так |
|
464 |
|
pf_exact = self.simplex_data.dice_box.pf_exact |
|
465 |
|
|
|
466 |
|
df = self.simplex_data.df |
|
467 |
|
#č zapíšeme do data rámu, snad nikomu nebude vadit |
|
468 |
|
df['vertex_estimation_error'] = df['vertex_estimation'] - pf_exact |
|
469 |
|
df['weighted_vertex_estimation_error'] = df['weighted_vertex_estimation'] - pf_exact |
|
470 |
|
|
|
471 |
|
v = df['vertex_estimation_error'].abs() |
|
472 |
|
wv = df['weighted_vertex_estimation_error'].abs() |
|
473 |
|
|
|
474 |
|
x, y = self.zerosafe(v.index, v.to_numpy()) |
|
475 |
|
self.pen_vertex.setData(x, y) |
|
476 |
|
|
|
477 |
|
x, y = self.zerosafe(wv.index, wv.to_numpy()) |
|
478 |
|
self.pen_weighted_vertex.setData(x, y) |
|
479 |
|
|
|
480 |
|
|
|
481 |
|
except BaseException as e: |
|
482 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
483 |
|
|
|
484 |
|
|
|
485 |
|
|
|
486 |
|
|
|
487 |
|
|
|
488 |
|
|
|
489 |
|
|
|
490 |
|
# DEPRECATED |
|
491 |
|
class SimpleSimplexEstimationGraph(pg.PlotWidget): |
|
492 |
|
def __init__(self, dice_box, stream=None, parent=None, *args, **kwargs): |
|
493 |
|
super().__init__(parent, *args, **kwargs) |
|
494 |
|
#č je zřejmě, že tím potokem bylo myšleno hlavní okínko |
|
495 |
|
#č asi aby nepadalo, když nenajde signaly |
|
496 |
|
self.stream = stream |
|
497 |
|
if stream is not None: |
|
498 |
|
self.stream.box_runned.connect(self.redraw) |
|
499 |
|
self.stream.estimation_added.connect(self.redraw) |
|
500 |
|
|
|
501 |
|
self.dice_box = dice_box |
|
502 |
|
|
|
503 |
|
self.setup_context_menu() |
|
504 |
|
self.setup() |
|
505 |
|
self.replot() |
|
506 |
|
|
|
507 |
|
def setup_context_menu(self): |
|
508 |
|
# creates instance of LegendItem |
|
509 |
|
# and saves it into plotItem.legend |
|
510 |
|
self.legend = self.addLegend() |
|
511 |
|
|
|
512 |
|
self.plotItem.ctrl.xGridCheck.setChecked(True) |
|
513 |
|
self.plotItem.ctrl.yGridCheck.setChecked(True) |
|
514 |
|
|
|
515 |
|
# delete build-in Transforms (with Log_x and Log_y) options, |
|
516 |
|
# they can cause uncachable exception (on any zero in data) and crash |
|
517 |
|
self.plotItem.ctrlMenu.removeAction(self.plotItem.ctrlMenu.actions()[0]) |
|
518 |
|
|
|
519 |
|
#č já se bojím. radší to uložím |
|
520 |
|
self.custom_menu = self.plotItem.vb.menu.addMenu("TRI options") |
|
521 |
|
|
|
522 |
|
self.legend_chk = QtGui.QAction("Legend", self.custom_menu) |
|
523 |
|
self.legend_chk.setCheckable(True) |
|
524 |
|
self.legend_chk.triggered.connect(lambda: self.legend.setVisible(self.legend_chk.isChecked())) |
|
525 |
|
self.custom_menu.addAction(self.legend_chk) |
|
526 |
|
# apply custom menu option |
|
527 |
|
self.legend.setVisible(self.legend_chk.isChecked()) |
|
528 |
|
|
|
529 |
|
self.proxy_chk = QtGui.QAction("Proxy", self.custom_menu) |
|
530 |
|
self.proxy_chk.setCheckable(True) |
|
531 |
|
self.proxy_chk.triggered.connect(self.redraw) |
|
532 |
|
self.custom_menu.addAction(self.proxy_chk) |
|
533 |
|
|
|
534 |
|
self.log_x_chk = QtGui.QAction("Log X", self.custom_menu) |
|
535 |
|
self.log_x_chk.setCheckable(True) |
|
536 |
|
self.log_x_chk.triggered.connect(lambda: self.setLogMode(x=self.log_x_chk.isChecked())) |
|
537 |
|
self.custom_menu.addAction(self.log_x_chk) |
|
538 |
|
|
|
539 |
|
self.log_y_chk = QtGui.QAction("Log Y", self.custom_menu) |
|
540 |
|
self.log_y_chk.setCheckable(True) |
|
541 |
|
self.log_y_chk.setChecked(True) |
|
542 |
|
self.log_y_chk.triggered.connect(self.replot) |
|
543 |
|
self.custom_menu.addAction(self.log_y_chk) |
|
544 |
|
|
|
545 |
|
self.reaction = QtGui.QAction("Redraw", self.custom_menu) |
|
546 |
|
self.reaction.triggered.connect(self.redraw) |
|
547 |
|
self.custom_menu.addAction(self.reaction) |
|
548 |
|
|
|
549 |
|
self.laction = QtGui.QAction("Show labels", self.custom_menu) |
|
550 |
|
self.laction.triggered.connect(self.show_labels) |
|
551 |
|
self.custom_menu.addAction(self.laction) |
|
552 |
|
|
|
553 |
|
self.excelaction = QtGui.QAction("Export to Excel", self.custom_menu) |
|
554 |
|
self.excelaction.triggered.connect(self.export_to_excel) |
|
555 |
|
self.custom_menu.addAction(self.excelaction) |
|
556 |
|
|
|
557 |
|
|
|
558 |
|
def export_to_excel(self): |
|
559 |
|
#č já bych nechtěl, aby mně export najednou spadl |
|
560 |
|
#č z jakéhokoliv důvodu |
|
561 |
|
try: |
|
562 |
|
proposal_filename = self.dice_box.guessbox.filename |
|
563 |
|
if proposal_filename: |
|
564 |
|
proposal_filename += '.xlsx' |
|
565 |
|
else: |
|
566 |
|
proposal_filename = self.dice_box.gm_signature + '.xlsx' |
|
567 |
|
filename, *__ = pg.FileDialog.getSaveFileName(self, 'Export to Excel',\ |
|
568 |
|
proposal_filename, initialFilter='*.xlsx') |
|
569 |
|
self.df.to_excel(filename) |
|
570 |
|
except BaseException as e: |
|
571 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
572 |
|
|
|
573 |
|
def show_labels(self): |
|
574 |
|
self.setLabel('left', "Probability measure") |
|
575 |
|
self.setLabel('bottom', "Number of simulations") |
|
576 |
|
|
|
577 |
|
|
|
578 |
|
|
|
579 |
|
# self.legend.addItem(self.pen_success, "success domain estimation") |
|
580 |
|
# self.legend.addItem(self.pen_outside, "out of sampling domain estimation") |
|
581 |
|
# self.legend.addItem(self.pen_mix, "mixed simplices measure") |
|
582 |
|
# self.legend.addItem(self.pen_f, "failure domain estimation") |
|
583 |
|
|
|
584 |
|
def setup(self, *args, **kwargs): |
|
585 |
|
self.clear() |
|
586 |
|
self.setBackground('w') |
|
587 |
|
x = y = () # zde jen vytvoříme kostru, nakrmime daty v .redraw() |
|
588 |
|
|
|
589 |
|
#xkcd_green = (167, 255, 181) # xkcd:light seafoam green #a7ffb5 |
|
590 |
|
green = (0, 255, 38, 96) |
|
591 |
|
#xkcd_red = (253, 193, 197) # xkcd: pale rose (#fdc1c5) |
|
592 |
|
red = (253, 0, 17, 96) |
|
593 |
|
#xkcd_cream = (255, 243, 154) # let's try xkcd: dark cream (#fff39a) |
|
594 |
|
cream = (255, 221, 0, 96) |
|
595 |
|
grey = (196, 196, 196, 96) |
|
596 |
|
|
|
597 |
|
self.pen_f = self.plot(x, y, brush=red)#, name="failure domain estimation") |
|
598 |
|
self.pen_f.setZValue(-100) |
|
599 |
|
|
|
600 |
|
self.pen_success = self.plot(x, y, brush=green) #, name="success domain estimation") |
|
601 |
|
self.pen_success.setZValue(-100) |
|
602 |
|
|
|
603 |
|
self.pen_outmix = self.plot(x, y) |
|
604 |
|
|
|
605 |
|
self.fill_mix = pg.FillBetweenItem(self.pen_f, self.pen_outmix) |
|
606 |
|
#self.fill_mix.setData(name="mixed simplices measure") |
|
607 |
|
self.fill_mix.setBrush(cream) |
|
608 |
|
self.fill_mix.setZValue(-100) |
|
609 |
|
self.addItem(self.fill_mix) |
|
610 |
|
|
|
611 |
|
#self.pen_outside = self.plot(x, y) |
|
612 |
|
self.fill_outside = pg.FillBetweenItem(self.pen_outmix, self.pen_success) |
|
613 |
|
#self.fill_outside.setData(name="out of sampling domain estimation") |
|
614 |
|
self.fill_outside.setBrush(grey) |
|
615 |
|
self.fill_outside.setZValue(-100) |
|
616 |
|
self.addItem(self.fill_outside) |
|
617 |
|
|
|
618 |
|
self.one_ruler = self.addLine(y=1, pen='k') |
|
619 |
|
self.zero_ruler = self.addLine(y=0, pen='k') |
|
620 |
|
|
|
621 |
|
|
|
622 |
|
try: |
|
623 |
|
exact_name = self.dice_box.pf_exact_method |
|
624 |
|
pen = pg.mkPen(color='b', width=1.5) # blue |
|
625 |
|
self.pen_exact = self.addLine(y=self.dice_box.pf_exact, pen=pen, name=exact_name) |
|
626 |
|
#č aby se nám něco zobrazovalo v legendu |
|
627 |
|
self.pen_exact_PR = self.plot(x, y, pen=pen, name=exact_name) |
|
628 |
|
except: |
|
629 |
|
pass |
|
630 |
|
|
|
631 |
|
pen = pg.mkPen(color='m', width=2) |
|
632 |
|
self.pen_vertex = self.plot(x, y, pen=pen, name="simple pf estimation") |
|
633 |
|
pen = pg.mkPen(color='r', width=2) #(118, 187, 255) |
|
634 |
|
self.pen_weighted_vertex = self.plot(x, y, pen=pen, name="weighted pf estimation") |
|
635 |
|
|
|
636 |
|
|
|
637 |
|
|
|
638 |
|
|
|
639 |
|
|
|
640 |
|
def replot(self, *args, **kwargs): |
|
641 |
|
if self.log_y_chk.isChecked(): |
|
642 |
|
self.one_ruler.hide() |
|
643 |
|
try: |
|
644 |
|
#č try nás nezáchraní protí odloženému spádnutí pyqtgraph |
|
645 |
|
if self.dice_box.pf_exact > 0: |
|
646 |
|
self.pen_exact.setPos(np.log10(self.dice_box.pf_exact)) |
|
647 |
|
self.pen_exact.show() |
|
648 |
|
else: |
|
649 |
|
self.pen_exact.hide() |
|
650 |
|
except: |
|
651 |
|
pass |
|
652 |
|
self.setLogMode(y=True) |
|
653 |
|
#self.pen_f.setPen(pg.mkPen(color=(255, 0, 0), width=3)) #, style=QtCore.Qt.DashLine) |
|
654 |
|
self.pen_f.setPen(None) |
|
655 |
|
self.pen_f.setFillLevel(None) |
|
656 |
|
self.pen_success.setFillLevel(0) |
|
657 |
|
|
|
658 |
|
else: |
|
659 |
|
self.one_ruler.show() |
|
660 |
|
try: |
|
661 |
|
self.pen_exact.setPos(self.dice_box.pf_exact) |
|
662 |
|
self.pen_exact.show() |
|
663 |
|
except: |
|
664 |
|
pass |
|
665 |
|
self.setLogMode(y=False) |
|
666 |
|
self.pen_f.setPen(None) |
|
667 |
|
self.pen_f.setFillLevel(0) |
|
668 |
|
self.pen_success.setFillLevel(1) |
|
669 |
|
|
|
670 |
|
self.redraw() |
|
671 |
|
|
|
672 |
|
|
|
673 |
|
#č když se někde objeví nula se zapnutým LogModem - |
|
674 |
|
#č qtpygraph hned spadne a není možne ten pad zachytit |
|
675 |
|
def zerosafe(self, x, y, fallback_y=None): |
|
676 |
|
if self.log_y_chk.isChecked(): |
|
677 |
|
x = np.array(x) |
|
678 |
|
y = np.array(y) |
|
679 |
|
if fallback_y is None: |
|
680 |
|
fallback_y = y |
|
681 |
|
y = np.where(y > 0, y, fallback_y) |
|
682 |
|
mask = y > 0 |
|
683 |
|
return x[mask], y[mask] |
|
684 |
|
else: |
|
685 |
|
return x, y |
|
686 |
|
|
|
687 |
|
def proxy(self, nsim): |
|
688 |
|
if self.proxy_chk.isChecked(): |
|
689 |
|
proxy = self.dice_box.proxy |
|
690 |
|
index = np.array(nsim)-1 |
|
691 |
|
#č indexy musíme o jedničku změnšit |
|
692 |
|
#č výsledek nikoliv. Takže v cajku. |
|
693 |
|
return np.cumsum(~proxy)[index] |
|
694 |
|
else: |
|
695 |
|
return nsim |
|
696 |
|
|
|
697 |
|
|
|
698 |
|
def _pens_data_update(self): |
|
699 |
|
df = self.df |
|
700 |
|
nsim = df.nsim.to_numpy() |
|
701 |
|
if self.proxy_chk.isChecked(): |
|
702 |
|
x = self.proxy(nsim) |
|
703 |
|
df.insert(loc=0, column='nsim (proxy)', value=x) |
|
704 |
|
else: |
|
705 |
|
x = nsim |
|
706 |
|
# (in case of LogPlot) fallback values also used |
|
707 |
|
success_values = df.failure+df.mix+df.out |
|
708 |
|
outmix_values = df.failure+df.mix |
|
709 |
|
failure_fallback = np.where(outmix_values > 0, outmix_values, success_values) |
|
710 |
|
self.pen_f.setData(*self.zerosafe(x, df.failure, failure_fallback)) |
|
711 |
|
self.pen_outmix.setData(*self.zerosafe(x, outmix_values, success_values)) |
|
712 |
|
self.pen_success.setData(*self.zerosafe(x, success_values)) |
|
713 |
|
|
|
714 |
|
|
|
715 |
|
def redraw(self): |
|
716 |
|
xmin = np.inf |
|
717 |
|
xmax = -np.inf |
|
718 |
|
tri_estimation = dict() |
|
719 |
|
try: # тут всё что угодно может пойти не так |
|
720 |
|
# kruci, ještě navic i generovať pokažde znovu... |
|
721 |
|
|
|
722 |
|
# new-style: šecko leží dohromady a každý si z toho |
|
723 |
|
# bere co chce a jak chce |
|
724 |
|
# ne že by to bylo nějak šetrný |
|
725 |
|
# estimation je slovníkem |
|
726 |
|
for estimation in self.dice_box.estimations: |
|
727 |
|
# nsim musí mäť každej odhad |
|
728 |
|
# pokud nemá - je třeba jej prostě opravit |
|
729 |
|
nsim = estimation['nsim'] |
|
730 |
|
try: |
|
731 |
|
tri_estimation[nsim] = estimation['TRI_estimation'] |
|
732 |
|
if nsim > xmax: |
|
733 |
|
xmax = nsim |
|
734 |
|
if nsim < xmin: |
|
735 |
|
xmin = nsim |
|
736 |
|
|
|
737 |
|
except KeyError as e: |
|
738 |
|
pass #print(self.__class__.__name__ + ":", repr(e)) |
|
739 |
|
|
|
740 |
|
#č neotravuj uživatele chybovejma hlaškama |
|
741 |
|
if tri_estimation: |
|
742 |
|
# it can be effectively done with pandas |
|
743 |
|
self.df = df = pd.DataFrame(tuple(tri_estimation.values())) |
|
744 |
|
# -1 = 'out', 0=success, 1=failure, 2=mix |
|
745 |
|
df.rename(columns={-1:'out', 0:'success', 1:'failure', 2:'mix'}, inplace=True) |
|
746 |
|
df.insert(loc=0, column='nsim', value=tuple(tri_estimation.keys()), allow_duplicates=False) |
|
747 |
|
df.sort_values('nsim', inplace=True) |
|
748 |
|
|
|
749 |
|
self._pens_data_update() |
|
750 |
|
|
|
751 |
|
nsim, y = get_estimation_data(self.dice_box.estimations, 'vertex_estimation') |
|
752 |
|
df['vertex_estimation'] = y #č spolehám na konzistenci odhadů (ne úplně) |
|
753 |
|
self.pen_vertex.setData(*self.zerosafe(self.proxy(nsim), y)) |
|
754 |
|
|
|
755 |
|
nsim, y = get_estimation_data(self.dice_box.estimations, 'weighted_vertex_estimation') |
|
756 |
|
df['weighted_vertex_estimation'] = y #č spolehám na konzistenci odhadů (ne úplně) |
|
757 |
|
self.pen_weighted_vertex.setData(*self.zerosafe(self.proxy(nsim), y)) |
|
758 |
|
|
|
759 |
|
|
|
760 |
|
except BaseException as e: |
|
761 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
762 |
|
|
|
763 |
|
|
|
764 |
|
# DEPRECATED |
|
765 |
|
class TriEstimationGraph(SimpleSimplexEstimationGraph): |
|
766 |
|
def __init__(self, dice_box, tri_estimation_name='TRI_overall_estimations', stream=None, parent=None, *args, **kwargs): |
|
767 |
|
self.tri_estimation_name = tri_estimation_name |
|
768 |
|
super().__init__(dice_box, stream, parent, *args, **kwargs) |
|
769 |
|
|
|
770 |
|
|
|
771 |
|
|
|
772 |
|
def redraw(self): |
|
773 |
|
try: # тут всё что угодно может пойти не так |
|
774 |
|
data = self.dice_box.guessbox.estimations[self.tri_estimation_name] |
|
775 |
|
nsim, tri_data = data |
|
776 |
|
# it can be effectively done with pandas |
|
777 |
|
self.df = df = pd.DataFrame(tri_data) |
|
778 |
|
# -1 = 'out', 0=success, 1=failure, 2=mix |
|
779 |
|
df.rename(columns={-1:'out', 0:'success', 1:'failure', 2:'mix'}, inplace=True) |
|
780 |
|
df.insert(loc=0, column='nsim', value=nsim) |
|
781 |
|
|
|
782 |
|
# Update the data |
|
783 |
|
self._pens_data_update() |
|
784 |
|
|
|
785 |
|
if 'vertex_estimation' in self.dice_box.guessbox.estimations: |
|
786 |
|
data = self.dice_box.guessbox.estimations['vertex_estimation'] |
|
787 |
|
nsim, y = data |
|
788 |
|
# Update the data |
|
789 |
|
#č spolehám na konzistenci blackboxu, ne však úplně |
|
790 |
|
self.pen_vertex.setData(*self.zerosafe(self.proxy(nsim), np.array(y))) |
|
791 |
|
df['vertex_estimation'] = y |
|
792 |
|
|
|
793 |
|
if 'weighted_vertex_estimation' in self.dice_box.guessbox.estimations: |
|
794 |
|
data = self.dice_box.guessbox.estimations['weighted_vertex_estimation'] |
|
795 |
|
nsim, y = data |
|
796 |
|
# Update the data |
|
797 |
|
#č spolehám na konzistenci blackboxu, ne však úplně |
|
798 |
|
self.pen_weighted_vertex.setData(*self.zerosafe(self.proxy(nsim), np.array(y))) |
|
799 |
|
df['weighted_vertex_estimation'] = y |
|
800 |
|
|
|
801 |
|
|
|
802 |
|
# BaseException |
|
803 |
|
except BaseException as e: |
|
804 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
805 |
|
|
|
806 |
|
|
|
807 |
|
|
|
808 |
|
|
|
809 |
|
|
|
810 |
|
|
|
811 |
|
|
|
812 |
|
class VoronoiEstimationGraph(pg.PlotWidget): |
|
813 |
|
def __init__(self, black_box, samplebox_item, parent=None, *args, **kwargs): |
|
814 |
|
super().__init__(parent) |
|
815 |
|
self.sb_item = samplebox_item |
|
816 |
|
self.sb_item.box_runned.connect(self.redraw) |
|
817 |
|
self.sb_item.estimation_added.connect(self.redraw) |
|
818 |
|
|
|
819 |
|
self.black_box = black_box |
|
820 |
|
self.setBackground('w') |
|
821 |
|
|
|
822 |
|
|
|
823 |
|
self.reaction = QtGui.QAction("Redraw", self.plotItem.ctrlMenu) |
|
824 |
|
self.reaction.triggered.connect(self.redraw) |
|
825 |
|
self.plotItem.ctrlMenu.insertAction(self.plotItem.ctrlMenu.actions()[0], self.reaction) |
|
826 |
|
|
|
827 |
|
|
|
828 |
|
|
|
829 |
|
# implicitně Y je v logaritmickem měřítku |
|
830 |
|
self.setLogMode(False, True) |
|
831 |
|
|
|
832 |
|
x = y = () # zde jen vytvoříme kostru, nakrmíme daty v .redraw() |
|
833 |
|
|
|
834 |
|
|
|
835 |
|
# nechapu, proč těm Itemům ríkám "propíska" |
|
836 |
|
# propíska? Их есть у нас! |
|
837 |
|
|
|
838 |
|
self.Voronoi_2_point_upper_bound = self.plot(x, y, pen='y') |
|
839 |
|
self.Voronoi_2_point_lower_bound = self.plot(x, y, pen='y') |
|
840 |
|
|
|
841 |
|
fill_color = (255, 243, 154) # let's try xkcd: dark cream (#fff39a) |
|
842 |
|
self.fill = pg.FillBetweenItem(self.Voronoi_2_point_upper_bound, self.Voronoi_2_point_lower_bound, fill_color) |
|
843 |
|
self.addItem(self.fill) |
|
844 |
|
|
|
845 |
|
self.Voronoi_2_point_failure_rate = self.plot(x, y, pen=(195,46,212)) |
|
846 |
|
self.Voronoi_2_point_pure_failure_rate = self.plot(x, y, pen='m') |
|
847 |
|
self.Voronoi_failure_rate = self.plot(x, y, pen='r') |
|
848 |
|
|
|
849 |
|
self.pen_exact = self.plot(x, y, pen='b') # blue |
|
850 |
|
self.pen_one = self.plot(x, y, pen='k') # black |
|
851 |
|
|
|
852 |
|
self.redraw() |
|
853 |
|
|
|
854 |
|
|
|
855 |
|
def redraw(self): |
|
856 |
|
# kruci, ještě navic i generovať pokažde znovu... |
|
857 |
|
metrics = {'Voronoi_2_point_upper_bound':{},\ |
|
858 |
|
'Voronoi_2_point_lower_bound':{},\ |
|
859 |
|
'Voronoi_2_point_failure_rate':{},\ |
|
860 |
|
'Voronoi_2_point_pure_failure_rate':{},\ |
|
861 |
|
'Voronoi_failure_rate':{},} |
|
862 |
|
xmin = np.inf |
|
863 |
|
xmax = -np.inf |
|
864 |
|
try: # тут всё что угодно может пойти не так |
|
865 |
|
# new-style: šecko leží dohromady a každý z toho |
|
866 |
|
# bere co chce a jak chce |
|
867 |
|
# ne že by to bylo nějak šetrný |
|
868 |
|
# estimation je slovníkem |
|
869 |
|
for estimation in self.black_box.estimations: |
|
870 |
|
# nsim musí mäť každej odhad |
|
871 |
|
# pokud nemá - je třeba jej prostě opravit |
|
872 |
|
nsim = estimation['nsim'] |
|
873 |
|
|
|
874 |
|
|
|
875 |
|
for metric, metric_dict in metrics.items(): |
|
876 |
|
try: |
|
877 |
|
if estimation[metric] > 0: |
|
878 |
|
metric_dict[nsim] = estimation[metric] |
|
879 |
|
if nsim > xmax: |
|
880 |
|
xmax = nsim |
|
881 |
|
if nsim < xmin: |
|
882 |
|
xmin = nsim |
|
883 |
|
except KeyError as e: |
|
884 |
|
pass #print(self.__class__.__name__ + ":", repr(e)) |
|
885 |
|
|
|
886 |
|
for metric, metric_dict in metrics.items(): |
|
887 |
|
pen = getattr(self, metric) |
|
888 |
|
# nikdo neslibil, že budou v pořadí |
|
889 |
|
x = np.sort(tuple(metric_dict.keys())) |
|
890 |
|
y = np.array(tuple(metric_dict.values()))[np.argsort(tuple(metric_dict.keys()))] |
|
891 |
|
pen.setData(x, y) |
|
892 |
|
|
|
893 |
|
if (xmax - xmin) > 0: |
|
894 |
|
self.pen_one.setData((xmin,xmax), (1, 1)) |
|
895 |
|
if hasattr(self.black_box, 'pf_exact'): |
|
896 |
|
# poslední. I když spadne, tak už nikomu moc nevadí |
|
897 |
|
self.pen_exact.setData((xmin,xmax), (self.black_box.pf_exact, self.black_box.pf_exact)) |
|
898 |
|
|
|
899 |
|
except BaseException as e: |
|
900 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
901 |
|
|
|
902 |
|
|
|
903 |
|
# pen_f.opts['logMode'] |
|
904 |
|
# pen_outside.setLogMode(False, False) |
|
905 |
|
#setLogMode(False, False) |
|
906 |
|
#f = pg.FillBetweenItem(curves[i], curves[i+1], brushes[i]) |
|
907 |
|
#win.addItem(f) |
|
908 |
|
|
|
909 |
|
|
|
910 |
|
|
|
911 |
|
|
File qt_gui/qt_gui.py changed (mode: 100644) (index 8aa7ad5..6de39b3) |
... |
... |
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 |
|
import pandas as pd # required for estimation graph |
|
|
11 |
|
from . import qt_graph_widgets |
|
12 |
|
from .. import reader |
12 |
13 |
|
|
13 |
|
#č vzdávám se. |
|
14 |
|
#č quadpy tak se stavá povinnou závislostí |
|
15 |
|
#č potrebuju pro HullEstimation widget |
|
16 |
|
import quadpy |
|
17 |
|
|
|
18 |
|
|
|
19 |
|
from .. import estimation as stm |
|
20 |
|
from .. import misc |
|
21 |
|
from .. import stm_df |
|
22 |
|
from .. import sball |
|
23 |
|
from .. import schemes |
|
24 |
|
from .. import convex_hull as khull |
|
25 |
|
#č pro mě je zvykem jako ghull označovat objekt třídy Ghull |
|
26 |
|
#č nikoliv čerstvě oddelený modul |
|
27 |
|
from ..ghull import Ghull, Shell_MC, Shell_IS, Shell_1DS |
|
28 |
|
|
|
29 |
|
|
|
30 |
14 |
|
|
31 |
15 |
### Define a top-level widget to hold everything |
### Define a top-level widget to hold everything |
32 |
|
class QtGuiPlot2D(QtGui.QMainWindow): |
|
|
16 |
|
class QtGuiWindow(QtGui.QMainWindow): |
33 |
17 |
#č box_runned dublikuje slice_changed |
#č box_runned dublikuje slice_changed |
34 |
18 |
# do not redraw twice! |
# do not redraw twice! |
35 |
19 |
box_runned = QtCore.pyqtSignal() |
box_runned = QtCore.pyqtSignal() |
|
... |
... |
class QtGuiPlot2D(QtGui.QMainWindow): |
84 |
68 |
|
|
85 |
69 |
## Start the Qt event loop |
## Start the Qt event loop |
86 |
70 |
self.app.exec_() |
self.app.exec_() |
|
71 |
|
|
|
72 |
|
def setup_menubar(self): |
|
73 |
|
self.bar = self.menuBar() |
|
74 |
|
self.file_menu = self.bar.addMenu("File") |
|
75 |
|
#č kontejner jen aby Python mně Cečkové objekty nevymazal |
|
76 |
|
self.file_actions = [] |
|
77 |
|
load_coordinates_action = QtGui.QAction("Load coordinates", self) |
|
78 |
|
load_coordinates_action.triggered.connect(self.load_coordinates) |
|
79 |
|
self.file_menu.addAction(load_coordinates_action) |
|
80 |
|
self.file_actions.append(load_coordinates_action) |
|
81 |
|
|
|
82 |
|
export_coordinates_action = QtGui.QAction("Export coordinates", self) |
|
83 |
|
export_coordinates_action.triggered.connect(self.export_coordinates) |
|
84 |
|
self.file_menu.addAction(export_coordinates_action) |
|
85 |
|
self.file_actions.append(export_coordinates_action) |
|
86 |
|
|
|
87 |
|
import_samples_action = QtGui.QAction("Import samples", self) |
|
88 |
|
import_samples_action.triggered.connect(self.import_samples) |
|
89 |
|
self.file_menu.addAction(import_samples_action) |
|
90 |
|
self.file_actions.append(import_samples_action) |
|
91 |
|
|
|
92 |
|
export_samples_action = QtGui.QAction("Export samples", self) |
|
93 |
|
export_samples_action.triggered.connect(self.export_samples) |
|
94 |
|
self.file_menu.addAction(export_samples_action) |
|
95 |
|
self.file_actions.append(export_samples_action) |
87 |
96 |
|
|
88 |
|
|
|
89 |
|
def initialize_central_widget(self): |
|
90 |
|
self.central_widget = pg.PlotWidget() |
|
91 |
|
self.central_widget.setBackground('w') |
|
92 |
|
self.px_size = 3.5 |
|
93 |
|
self.ncircles = 5 |
|
94 |
|
self.redraw_called.connect(self.central_widget.clear) |
|
|
97 |
|
self.view = self.bar.addMenu("View") |
|
98 |
|
|
|
99 |
|
self.graph_menu = self.bar.addMenu("Box") |
|
100 |
|
self.batch_run_action = QtGui.QAction("Batch run", self) |
|
101 |
|
self.batch_run_action.triggered.connect(self.batch_run) |
|
102 |
|
self.graph_menu.addAction(self.batch_run_action) |
|
103 |
|
|
|
104 |
|
# optional feature |
|
105 |
|
self.initialize_matplotlib_menu() |
95 |
106 |
|
|
96 |
107 |
# should be INHERITED by gl_plot |
# should be INHERITED by gl_plot |
97 |
108 |
def initialize_matplotlib_menu(self): |
def initialize_matplotlib_menu(self): |
|
... |
... |
class QtGuiPlot2D(QtGui.QMainWindow): |
154 |
165 |
# intended as a common setup function |
# intended as a common setup function |
155 |
166 |
def setup(self): |
def setup(self): |
156 |
167 |
|
|
157 |
|
self.bar = self.menuBar() |
|
158 |
|
self.view = self.bar.addMenu("View") |
|
159 |
|
|
|
160 |
|
self.graph_menu = self.bar.addMenu("Box") |
|
161 |
|
self.batch_run_action = QtGui.QAction("Batch run", self) |
|
162 |
|
self.batch_run_action.triggered.connect(self.batch_run) |
|
163 |
|
self.graph_menu.addAction(self.batch_run_action) |
|
164 |
168 |
|
|
165 |
|
# optional feature |
|
166 |
|
self.initialize_matplotlib_menu() |
|
|
169 |
|
self.setup_menubar() |
167 |
170 |
|
|
168 |
171 |
### Create some widgets to be placed inside |
### Create some widgets to be placed inside |
169 |
172 |
self.combo_space = pg.ComboBox(items=self.spaces, default=self.space) |
self.combo_space = pg.ComboBox(items=self.spaces, default=self.space) |
|
... |
... |
class QtGuiPlot2D(QtGui.QMainWindow): |
180 |
183 |
self.slider.setValue(self.sample_box.nsim) |
self.slider.setValue(self.sample_box.nsim) |
181 |
184 |
|
|
182 |
185 |
#č jen aby se slider probral, když uživatel ručně přídá bodíky |
#č jen aby se slider probral, když uživatel ručně přídá bodíky |
183 |
|
self.redraw_called.connect(lambda:self.slider.setMaximum(self.sample_box.nsim)) |
|
|
186 |
|
self.redraw_called.connect(self.wake_up_slider) |
|
187 |
|
self.box_runned.connect(self.wake_up_slider) |
184 |
188 |
|
|
185 |
189 |
self.btn = QtGui.QPushButton('run box') |
self.btn = QtGui.QPushButton('run box') |
186 |
190 |
self.btn.clicked.connect(self.run_sb) |
self.btn.clicked.connect(self.run_sb) |
|
... |
... |
class QtGuiPlot2D(QtGui.QMainWindow): |
247 |
251 |
self.dockables.append(dock) |
self.dockables.append(dock) |
248 |
252 |
self.tabifyDockWidget(self.dockables[0], dock) |
self.tabifyDockWidget(self.dockables[0], dock) |
249 |
253 |
|
|
250 |
|
self.simplex_data = SimplexEstimationData(self.sample_box, self) |
|
|
254 |
|
self.simplex_data = qt_graph_widgets.SimplexEstimationData(self.sample_box, self) |
251 |
255 |
#č graphy už nemusí jít po stm widgetech |
#č graphy už nemusí jít po stm widgetech |
252 |
256 |
dock = QtGui.QDockWidget("TRI_overall estimation graph", self) |
dock = QtGui.QDockWidget("TRI_overall estimation graph", self) |
253 |
|
dock.setWidget(TriEstimationGraph(self.sample_box, 'TRI_overall_estimations', self, dock)) |
|
|
257 |
|
dock.setWidget(qt_graph_widgets.TriEstimationGraph(self.sample_box, 'TRI_overall_estimations', self, dock)) |
254 |
258 |
self.dockables.append(dock) |
self.dockables.append(dock) |
255 |
259 |
self.tabifyDockWidget(self.dockables[0], dock) |
self.tabifyDockWidget(self.dockables[0], dock) |
256 |
260 |
|
|
257 |
261 |
dock = QtGui.QDockWidget("Simplex estimation graph", self) |
dock = QtGui.QDockWidget("Simplex estimation graph", self) |
258 |
|
dock.setWidget(SimpleSimplexEstimationGraph(self.sample_box, self, dock)) |
|
|
262 |
|
dock.setWidget(qt_graph_widgets.SimpleSimplexEstimationGraph(self.sample_box, self, dock)) |
259 |
263 |
self.dockables.append(dock) |
self.dockables.append(dock) |
260 |
264 |
self.tabifyDockWidget(self.dockables[0], dock) |
self.tabifyDockWidget(self.dockables[0], dock) |
261 |
265 |
|
|
262 |
266 |
dock = QtGui.QDockWidget("Simplex error graph", self) |
dock = QtGui.QDockWidget("Simplex error graph", self) |
263 |
|
dock.setWidget(SimplexErrorGraph(self.simplex_data, dock)) |
|
|
267 |
|
dock.setWidget(qt_graph_widgets.SimplexErrorGraph(self.simplex_data, dock)) |
264 |
268 |
self.dockables.append(dock) |
self.dockables.append(dock) |
265 |
269 |
self.tabifyDockWidget(self.dockables[0], dock) |
self.tabifyDockWidget(self.dockables[0], dock) |
266 |
270 |
|
|
267 |
271 |
|
|
268 |
272 |
dock = QtGui.QDockWidget("Voronoi estimation graph", self) |
dock = QtGui.QDockWidget("Voronoi estimation graph", self) |
269 |
|
dock.setWidget(VoronoiEstimationGraph(self.sample_box, self, dock)) |
|
|
273 |
|
dock.setWidget(qt_graph_widgets.VoronoiEstimationGraph(self.sample_box, self, dock)) |
270 |
274 |
self.dockables.append(dock) |
self.dockables.append(dock) |
271 |
275 |
self.tabifyDockWidget(self.dockables[0], dock) |
self.tabifyDockWidget(self.dockables[0], dock) |
272 |
276 |
|
|
|
... |
... |
class QtGuiPlot2D(QtGui.QMainWindow): |
293 |
297 |
#dock.setFloating(True) |
#dock.setFloating(True) |
294 |
298 |
|
|
295 |
299 |
#self.w.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.items) |
#self.w.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.items) |
|
300 |
|
|
|
301 |
|
|
|
302 |
|
|
|
303 |
|
|
|
304 |
|
csv_filter = "CSV files (*.csv)" |
|
305 |
|
npy_filter = "NumPy binary files (*.npy)" |
|
306 |
|
txt_filter = "Text files (*.txt)" |
|
307 |
|
gz_filter = "Compressed text files (*.gz)" |
|
308 |
|
|
|
309 |
|
def load_coordinates(self): |
|
310 |
|
""" |
|
311 |
|
Loads numpy data and adds them to the sample_box |
|
312 |
|
""" |
|
313 |
|
nodes = None |
|
314 |
|
filter = self.npy_filter + ';;' + self.txt_filter + ';;' + self.gz_filter |
|
315 |
|
wt = self.sample_box |
296 |
316 |
|
|
|
317 |
|
try: |
|
318 |
|
filename, filter = pg.FileDialog.getOpenFileName( |
|
319 |
|
parent=self, |
|
320 |
|
caption="Load coordinates", |
|
321 |
|
directory="store/%s_%sD.npy" % (wt.gm_signature, wt.nvar), |
|
322 |
|
filter=filter, |
|
323 |
|
initialFilter=self.npy_filter, |
|
324 |
|
#options=pg.FileDialog.Option.DontConfirmOverwrite |
|
325 |
|
) |
|
326 |
|
if filename: |
|
327 |
|
if filter == self.npy_filter: |
|
328 |
|
raw_nodes = np.load(filename) |
|
329 |
|
else: |
|
330 |
|
raw_nodes = np.loadtxt(filename) |
|
331 |
|
|
|
332 |
|
# create sample |
|
333 |
|
nodes = wt.f_model.new_sample(sample=raw_nodes, \ |
|
334 |
|
space=self.space, extend=False) |
|
335 |
|
|
|
336 |
|
except BaseException as e: |
|
337 |
|
print(self.__class__.__name__ + ":", \ |
|
338 |
|
" coordinates loading failed", repr(e)) |
|
339 |
|
|
|
340 |
|
#č zde jíž nemá cenu chytat chyby. Sbohem! |
|
341 |
|
if nodes is not None: |
|
342 |
|
# run! |
|
343 |
|
wt.run_sample(nodes) |
|
344 |
|
self.box_runned.emit() |
297 |
345 |
|
|
298 |
346 |
|
|
|
347 |
|
def export_coordinates(self): |
|
348 |
|
""" |
|
349 |
|
Exports current sample box coordinates |
|
350 |
|
""" |
|
351 |
|
filter = self.npy_filter + ';;' + self.txt_filter + ';;' + self.gz_filter |
|
352 |
|
wt = self.sample_box |
|
353 |
|
|
|
354 |
|
filename, filter = pg.FileDialog.getSaveFileName( |
|
355 |
|
parent=self, |
|
356 |
|
caption="Export coordinates", |
|
357 |
|
directory="store/%s_%sD.npy" % (wt.gm_signature, wt.nvar), |
|
358 |
|
#filter=csv_filter, |
|
359 |
|
filter=filter, |
|
360 |
|
initialFilter=self.npy_filter, |
|
361 |
|
#options=pg.FileDialog.Option.DontConfirmOverwrite |
|
362 |
|
) |
|
363 |
|
if filename: |
|
364 |
|
nsim = self.slider.value() |
|
365 |
|
nodes = self.sample_box.f_model[:nsim] |
|
366 |
|
raw_nodes = getattr(nodes, self.space) |
|
367 |
|
try: |
|
368 |
|
if filter == self.npy_filter: |
|
369 |
|
np.save(filename, raw_nodes, allow_pickle=False) |
|
370 |
|
else: |
|
371 |
|
np.savetxt(filename, raw_nodes) |
|
372 |
|
except BaseException as e: |
|
373 |
|
print(self.__class__.__name__ + ":", \ |
|
374 |
|
" coordinates export failed", repr(e)) |
|
375 |
|
|
|
376 |
|
|
|
377 |
|
|
|
378 |
|
def import_samples(self): |
|
379 |
|
wt = self.sample_box |
|
380 |
|
|
|
381 |
|
filename, __filter = pg.FileDialog.getOpenFileName( |
|
382 |
|
parent=self, |
|
383 |
|
caption="Import samples", |
|
384 |
|
directory="store/%s_%sD.csv" % (wt.gm_signature, wt.nvar), |
|
385 |
|
#filter=csv_filter, |
|
386 |
|
filter=self.csv_filter, # + ";;All files(*)", |
|
387 |
|
initialFilter=self.csv_filter, |
|
388 |
|
#options=pg.FileDialog.Option.DontConfirmOverwrite |
|
389 |
|
) |
|
390 |
|
if filename and (filename[-4:]=='.csv'): |
|
391 |
|
#č Reader vždy dopíše '.csv' na konci souboru |
|
392 |
|
#č nechcu to teď měnit |
|
393 |
|
filename = filename[:-4] |
|
394 |
|
|
|
395 |
|
#č nechcu chytat žádné chyby. Sbohem! |
|
396 |
|
sample_box = reader.reader(filename, f_model=wt.f_model) |
|
397 |
|
wt.add_sample(sample_box) |
|
398 |
|
self.box_runned.emit() |
299 |
399 |
|
|
300 |
|
|
|
301 |
|
def plot_setup(self): |
|
302 |
|
self.view_items = [] |
|
303 |
|
self.view_items.append(BasePlotting(self)) |
|
304 |
|
self.view_items.append(UnitCube(self)) |
|
305 |
|
self.view_items.append(AspectLock(self)) |
|
306 |
|
self.view_items.append(LastShot(self)) |
|
307 |
|
self.view_items.append(Circles(self)) |
|
308 |
|
self.view_items.append(Isocurves(self)) |
|
309 |
|
self.view_items.append(Boundaries(self)) |
|
310 |
|
self.view_items.append(ConvexHull2D(self)) |
|
311 |
|
self.view_items.append(Triangulation(self)) |
|
312 |
|
|
|
313 |
|
|
|
314 |
|
|
|
315 |
|
|
|
316 |
|
dock = dock_r = QtGui.QDockWidget("Simplex-based pf estimation", self) |
|
317 |
|
dock.setWidget(FastSimplexEstimationWidget(self, dock)) |
|
318 |
|
self.view.addAction(dock.toggleViewAction()) |
|
319 |
|
self.dockables.append(dock) |
|
320 |
|
self.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock) |
|
321 |
|
|
|
322 |
|
|
|
323 |
|
dock = QtGui.QDockWidget("Tesselation-based pf estimation", self) |
|
324 |
|
dock.setWidget(VoronoiEstimationWidget(self, dock)) |
|
325 |
|
self.view.addAction(dock.toggleViewAction()) |
|
326 |
|
self.dockables.append(dock) |
|
327 |
|
#self.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock) |
|
328 |
|
self.tabifyDockWidget(dock_r, dock) |
|
329 |
|
|
|
330 |
|
|
|
331 |
|
dock = QtGui.QDockWidget("Ghull", self) |
|
332 |
|
dock.setWidget(HullEstimationWidget(self, dock)) |
|
333 |
|
self.view.addAction(dock.toggleViewAction()) |
|
334 |
|
self.dockables.append(dock) |
|
335 |
|
self.tabifyDockWidget(dock_r, dock) |
|
336 |
|
|
|
337 |
|
dock = QtGui.QDockWidget("Blackbox's candidates", self) |
|
338 |
|
dock.setWidget(CandidatesWidget(self, dock)) |
|
339 |
|
self.view.addAction(dock.toggleViewAction()) |
|
340 |
|
self.dockables.append(dock) |
|
341 |
|
self.tabifyDockWidget(dock_r, dock) |
|
|
400 |
|
def export_samples(self): |
|
401 |
|
wt = self.sample_box |
|
402 |
|
|
|
403 |
|
filename, __filter = pg.FileDialog.getSaveFileName( |
|
404 |
|
parent=self, |
|
405 |
|
caption="Export samples", |
|
406 |
|
directory="store/%s_%sD.csv" % (wt.gm_signature, wt.nvar), |
|
407 |
|
#filter=csv_filter, |
|
408 |
|
filter=self.csv_filter, # + ";;All files(*)", |
|
409 |
|
initialFilter=self.csv_filter, |
|
410 |
|
#options=pg.FileDialog.Option.DontConfirmOverwrite |
|
411 |
|
) |
|
412 |
|
if filename: |
|
413 |
|
#č Reader vždy dopíše '.csv' na konci souboru |
|
414 |
|
#č nechcu to teď měnit |
|
415 |
|
if filename[-4:]=='.csv': |
|
416 |
|
filename = filename[:-4] |
|
417 |
|
nsim = self.slider.value() |
|
418 |
|
reader.export(filename, wt[:nsim]) |
342 |
419 |
|
|
343 |
420 |
|
|
344 |
421 |
# |
# |
|
... |
... |
class QtGuiPlot2D(QtGui.QMainWindow): |
364 |
441 |
def run_sb(self): |
def run_sb(self): |
365 |
442 |
with pg.BusyCursor(): |
with pg.BusyCursor(): |
366 |
443 |
self.last_shot = self.sample_box() |
self.last_shot = self.sample_box() |
367 |
|
|
|
368 |
|
# slider |
|
369 |
|
#č zpusobí slice_changed |
|
370 |
|
self.slider.setMaximum(self.sample_box.nsim) |
|
371 |
|
self.slider.setValue(self.sample_box.nsim) |
|
372 |
|
|
|
373 |
444 |
self.box_runned.emit() |
self.box_runned.emit() |
374 |
445 |
|
|
375 |
|
|
|
|
446 |
|
def wake_up_slider(self): |
|
447 |
|
# slider |
|
448 |
|
#č zpusobí slice_changed |
|
449 |
|
self.slider.setMaximum(self.sample_box.nsim) |
|
450 |
|
self.slider.setValue(self.sample_box.nsim) |
376 |
451 |
|
|
377 |
452 |
# INHERITED by gl_plot |
# INHERITED by gl_plot |
378 |
453 |
def bx_connect(self): |
def bx_connect(self): |
|
... |
... |
class QtGuiPlot2D(QtGui.QMainWindow): |
434 |
509 |
|
|
435 |
510 |
|
|
436 |
511 |
|
|
437 |
|
|
|
438 |
|
""" |
|
439 |
|
============== |
|
440 |
|
оӵ Суред люкет |
|
441 |
|
č Kreslicí prvky |
|
442 |
|
E Drawing items |
|
443 |
|
================= |
|
444 |
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
445 |
|
""" |
|
446 |
|
|
|
447 |
|
|
|
448 |
|
class Series: |
|
449 |
|
def __init__(self, w, autoredraw=True): |
|
450 |
|
self.w = w |
|
451 |
|
self.w.space_changed.connect(self.space_update) |
|
452 |
|
self.w.redraw_called.connect(self._redraw) |
|
453 |
|
# redraw policy |
|
454 |
|
self.autoredraw = autoredraw |
|
455 |
|
self.items = {} |
|
456 |
|
|
|
457 |
|
|
|
458 |
|
def add_serie(self, sample, index=None, **plot_kwargs): |
|
459 |
|
plot_item = self._draw(sample, plot_kwargs) |
|
460 |
|
|
|
461 |
|
if index is None: |
|
462 |
|
index = len(self.items) |
|
463 |
|
elif index in self.items: |
|
464 |
|
# kind of update, then |
|
465 |
|
#č musíme korektně odebrat předchozí kresbu |
|
466 |
|
self.remove_item(index) |
|
467 |
|
|
|
468 |
|
self.items[index] = [sample, plot_item, plot_kwargs] |
|
469 |
|
return plot_item |
|
470 |
|
|
|
471 |
|
|
|
472 |
|
def _draw(self, sample, plot_dict): |
|
473 |
|
pos = getattr(sample, self.w.space)[:,:2] |
|
474 |
|
mask = np.all(np.isfinite(pos), axis=1) |
|
475 |
|
return self.w.central_widget.plot(pos[mask], **plot_dict) |
|
476 |
|
|
|
477 |
|
|
|
478 |
|
def clear(self): |
|
479 |
|
for item in self.items.values(): |
|
480 |
|
__sample, plot_item, __plot_dict = item |
|
481 |
|
self.w.central_widget.removeItem(plot_item) |
|
482 |
|
self.items.clear() |
|
483 |
|
|
|
484 |
|
def remove_item(self, index): |
|
485 |
|
__sample, plot_item, __plot_dict = self.items.pop(index) |
|
486 |
|
self.w.central_widget.removeItem(plot_item) |
|
487 |
|
|
|
488 |
|
|
|
489 |
|
def hide(self, index=None): |
|
490 |
|
if index is None: |
|
491 |
|
for item in self.items.values(): |
|
492 |
|
__sample, plot_item, __plot_dict = item |
|
493 |
|
plot_item.hide() |
|
494 |
|
else: |
|
495 |
|
__sample, plot_item, __plot_dict = self.items[index] |
|
496 |
|
plot_item.hide() |
|
497 |
|
|
|
498 |
|
def show(self, index=None): |
|
499 |
|
if index is None: |
|
500 |
|
for item in self.items.values(): |
|
501 |
|
__sample, plot_item, __plot_dict = item |
|
502 |
|
plot_item.show() |
|
503 |
|
else: |
|
504 |
|
__sample, plot_item, __plot_dict = self.items[index] |
|
505 |
|
plot_item.show() |
|
506 |
|
|
|
507 |
|
|
|
508 |
|
def _redraw(self): |
|
509 |
|
if self.autoredraw: |
|
510 |
|
for item in self.items.values(): |
|
511 |
|
sample, _invalid_plot_item, plot_dict = item |
|
512 |
|
item[1] = self._draw(sample, plot_dict) |
|
513 |
|
else: |
|
514 |
|
self.items.clear() |
|
515 |
|
|
|
516 |
|
|
|
517 |
|
def space_update(self): |
|
518 |
|
for item in self.items.values(): |
|
519 |
|
sample, plot_item, __plot_dict = item |
|
520 |
|
|
|
521 |
|
pos = getattr(sample, self.w.space)[:,:2] |
|
522 |
|
mask = np.all(np.isfinite(pos), axis=1) |
|
523 |
|
plot_item.setData(pos[mask]) |
|
524 |
|
|
|
525 |
|
|
|
526 |
|
|
|
527 |
|
#č Kružničky chcete? |
|
528 |
|
#ё Кружочки ннада? |
|
529 |
|
#оӵ Гаусслэн котыресез |
|
530 |
|
class Giracles(Series): |
|
531 |
|
def __init__(self, w, autoredraw=True, nrod=200): |
|
532 |
|
super().__init__(w, autoredraw) |
|
533 |
|
|
|
534 |
|
self.setup(nrod) |
|
535 |
|
|
|
536 |
|
def setup(self, nrod): |
|
537 |
|
phi = np.linspace(0, 6.283185307, nrod, endpoint=True) |
|
538 |
|
cos_phi = np.cos(phi) |
|
539 |
|
sin_phi = np.sin(phi) |
|
540 |
|
|
|
541 |
|
self.prebound = np.array((cos_phi, sin_phi)).T |
|
542 |
|
|
|
543 |
|
|
|
544 |
|
def add_circle(self, r=1, index=None, **plot_kwargs): |
|
545 |
|
f_model = self.w.sample_box.f_model |
|
546 |
|
sample_G = self.prebound * r |
|
547 |
|
sample = f_model.new_sample(sample_G, space='G', extend=True) |
|
548 |
|
return self.add_serie(sample, index=index, **plot_kwargs) |
|
549 |
512 |
|
|
550 |
513 |
|
|
551 |
514 |
|
|
552 |
515 |
|
|
553 |
|
class InfiniteLines(Series): |
|
554 |
516 |
|
|
555 |
|
def add_line(self, space='G', index=None, **plot_kwargs): |
|
556 |
|
plot_item = self.w.central_widget.addLine(**plot_kwargs) |
|
557 |
|
if space == self.w.space: |
|
558 |
|
plot_item.show() |
|
559 |
|
else: |
|
560 |
|
plot_item.hide() |
|
561 |
|
|
|
562 |
|
if index is None: |
|
563 |
|
index = len(self.items) |
|
564 |
|
elif index in self.items: |
|
565 |
|
# kind of update, then |
|
566 |
|
#č musíme korektně odebrat předchozí kresbu |
|
567 |
|
self.remove_item(index) |
|
568 |
|
|
|
569 |
|
self.items[index] = [space, plot_item, plot_kwargs] |
|
570 |
|
return plot_item |
|
571 |
|
|
|
572 |
|
def _redraw(self): |
|
573 |
|
if self.autoredraw: |
|
574 |
|
for item in self.items.values(): |
|
575 |
|
space, _invalid_plot_item, plot_dict = item |
|
576 |
|
item[1] = self.w.central_widget.addLine(**plot_dict) |
|
577 |
|
else: |
|
578 |
|
self.items.clear() |
|
579 |
|
|
|
580 |
|
|
|
581 |
|
def space_update(self): |
|
582 |
|
for item in self.items.values(): |
|
583 |
|
space, plot_item, __plot_dict = item |
|
584 |
|
if space == self.w.space: |
|
585 |
|
plot_item.show() |
|
586 |
|
else: |
|
587 |
|
plot_item.hide() |
|
588 |
517 |
|
|
589 |
518 |
|
|
590 |
519 |
""" |
""" |
591 |
|
============== |
|
592 |
|
у График люкет |
|
593 |
|
č Grafické prvky |
|
594 |
|
E Drawing modules |
|
595 |
|
================= |
|
|
520 |
|
=========== |
|
521 |
|
♥ Чыры-пыры |
|
522 |
|
č Jiné |
|
523 |
|
E Miscellaneous |
|
524 |
|
=============== |
596 |
525 |
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
597 |
526 |
""" |
""" |
598 |
527 |
|
|
599 |
528 |
|
|
600 |
|
class BasePlotting: |
|
601 |
|
def __init__(self, w): |
|
602 |
|
self.w = w |
|
603 |
|
#self.w.box_runned.connect(self.redraw) #č dublikuje slice_changed |
|
604 |
|
self.w.space_changed.connect(self.plot) |
|
605 |
|
self.w.slice_changed.connect(self.plot) |
|
606 |
|
self.w.redraw_called.connect(self.redraw) |
|
607 |
|
|
|
608 |
|
|
|
609 |
|
def redraw(self): |
|
610 |
|
plot_widget = self.w.central_widget |
|
611 |
|
#size=self.w.px_size*1.5 |
|
612 |
|
pos = () #np.empty((nsim, 4)) |
|
613 |
|
size = self.w.px_size * 2 |
|
614 |
|
self.failures = plot_widget.plot(pos, pen=None, symbol='x', symbolPen='r',\ |
|
615 |
|
symbolSize=size*1.5, name='Failures') # symbolBrush=0.2, |
|
616 |
|
self.failures.setZValue(100) |
|
617 |
|
|
|
618 |
|
self.proxy_failures = plot_widget.plot(pos, pen=None, symbol='p', symbolPen=0.5,\ |
|
619 |
|
symbolSize=size, symbolBrush=(217,83,25), name='Proxy failures') |
|
620 |
|
self.proxy_failures.setZValue(95) |
|
621 |
|
|
|
622 |
|
self.successes = plot_widget.plot(pos, pen=None, symbol='+', \ |
|
623 |
|
symbolSize=size*1.5, symbolPen='g', name='Successes') |
|
624 |
|
self.successes.setZValue(90) |
|
625 |
|
|
|
626 |
|
self.proxy_successes = plot_widget.plot(pos, pen=None, symbol='p', symbolPen=0.5, \ |
|
627 |
|
symbolSize=size, symbolBrush=(119,172,48), name='Proxy successes') |
|
628 |
|
self.proxy_successes.setZValue(85) |
|
629 |
|
|
|
630 |
|
|
|
631 |
|
self.nodes = plot_widget.plot(pos, pen=None, symbol='o', symbolPen=0.5, \ |
|
632 |
|
symbolSize=size, name='Nodes') |
|
633 |
|
self.nodes.setZValue(80) |
|
634 |
|
|
|
635 |
|
self.plot() |
|
636 |
|
|
|
637 |
|
def plot(self): |
|
638 |
|
nsim = self.w.slider.value() |
|
639 |
|
|
|
640 |
|
sample_box = self.w.sample_box[:nsim] |
|
641 |
|
|
|
642 |
|
pos = getattr(sample_box, self.w.space)[:,:2] |
|
643 |
|
if hasattr(sample_box, 'failsi'): #č to je normálně sample_box |
|
644 |
|
failsi = sample_box.failsi |
|
645 |
|
|
|
646 |
|
try: # proxy denotes to implicitly-known values |
|
647 |
|
proxy = sample_box.proxy |
|
648 |
|
except AttributeError: |
|
649 |
|
proxy = np.full(nsim, False, dtype=np.bool) |
|
650 |
|
|
|
651 |
|
mask = np.all((failsi, ~proxy), axis=0) |
|
652 |
|
self.draw(self.failures, pos[mask]) |
|
653 |
|
|
|
654 |
|
mask = np.all((~failsi, ~proxy), axis=0) |
|
655 |
|
self.draw(self.successes, pos[mask]) |
|
656 |
|
|
|
657 |
|
mask = np.all((failsi, proxy), axis=0) |
|
658 |
|
self.draw(self.proxy_failures, pos[mask]) |
|
659 |
|
|
|
660 |
|
mask = np.all((~failsi, proxy), axis=0) |
|
661 |
|
self.draw(self.proxy_successes, pos[mask]) |
|
662 |
|
|
|
663 |
|
else: #č není to teda sample_box... |
|
664 |
|
#č snad se nám povede nakreslit aspoň tečky? |
|
665 |
|
self.draw(self.nodes, pos) |
|
666 |
|
|
|
667 |
|
|
|
668 |
|
@staticmethod |
|
669 |
|
def draw(plot_item, data): |
|
670 |
|
#č musím to udělat takhle |
|
671 |
|
#č jinač to zlobí při posunutích slajderu |
|
672 |
|
if len(data): |
|
673 |
|
plot_item.setData(data) |
|
674 |
|
plot_item.show() |
|
675 |
|
else: |
|
676 |
|
plot_item.hide() |
|
677 |
|
|
|
678 |
|
|
|
679 |
|
class UnitCube: |
|
680 |
|
def __init__(self, w): |
|
681 |
|
self.w = w |
|
682 |
|
self.w.space_changed.connect(self.plot) |
|
683 |
|
self.w.redraw_called.connect(self.redraw) |
|
684 |
|
|
|
685 |
|
|
|
686 |
|
def redraw(self): |
|
687 |
|
plot_widget = self.w.central_widget |
|
688 |
|
self.frame = plot_widget.plot(pos=(), pen='k') |
|
689 |
|
self.plot() |
|
690 |
|
|
|
691 |
|
|
|
692 |
|
def plot(self): |
|
693 |
|
if self.w.space in ('P', 'U'): |
|
694 |
|
self.frame.setData((0,0,1,1,0), (0,1,1,0,0)) |
|
695 |
|
self.frame.show() |
|
696 |
|
elif self.w.space in ('aP', 'aU'): |
|
697 |
|
x, y, *__ = (*self.w.sample_box.alpha,) |
|
698 |
|
self.frame.setData((0,0,x,x,0), (0,y,y,0,0)) |
|
699 |
|
self.frame.show() |
|
700 |
|
else: |
|
701 |
|
self.frame.hide() |
|
702 |
|
|
|
703 |
|
|
|
704 |
|
|
|
705 |
|
|
|
706 |
|
|
|
707 |
|
|
|
708 |
|
class AspectLock: |
|
709 |
|
def __init__(self, w): |
|
710 |
|
self.w = w |
|
711 |
|
|
|
712 |
|
self.item = QtGui.QListWidgetItem('Equal aspect') |
|
713 |
|
self.item.setFlags(self.item.flags() | QtCore.Qt.ItemIsUserCheckable) |
|
714 |
|
self.item.setCheckState(QtCore.Qt.Unchecked) |
|
715 |
|
self.w.list_view.addItem(self.item) |
|
716 |
|
self.w.list_view.itemChanged.connect(self.set_aspect) |
|
717 |
|
|
|
718 |
|
def set_aspect(self): |
|
719 |
|
plot_widget = self.w.central_widget |
|
720 |
|
if self.item.checkState(): |
|
721 |
|
plot_widget.setAspectLocked(lock=True, ratio=1) |
|
722 |
|
else: |
|
723 |
|
plot_widget.setAspectLocked(lock=False, ratio=1) |
|
724 |
|
|
|
725 |
|
|
|
726 |
|
|
|
727 |
|
|
|
728 |
|
class LastShot: |
|
729 |
|
def __init__(self, w): |
|
730 |
|
self.w = w |
|
731 |
|
self.w.box_runned.connect(self.plot) |
|
732 |
|
self.w.space_changed.connect(self.plot) |
|
733 |
|
self.w.redraw_called.connect(self.redraw) |
|
734 |
|
|
|
735 |
|
self.item = QtGui.QListWidgetItem('Last shot') |
|
736 |
|
self.item.setFlags(self.item.flags() | QtCore.Qt.ItemIsUserCheckable) |
|
737 |
|
self.item.setCheckState(QtCore.Qt.Checked) |
|
738 |
|
self.w.list_view.addItem(self.item) |
|
739 |
|
self.w.list_view.itemChanged.connect(self.show_slot) |
|
740 |
|
|
|
741 |
|
def show_slot(self, item): |
|
742 |
|
if item is self.item: |
|
743 |
|
self.plot() |
|
744 |
|
|
|
745 |
|
def redraw(self): |
|
746 |
|
pos = () |
|
747 |
|
plot_widget = self.w.central_widget |
|
748 |
|
self.last = plot_widget.plot(pos, pen=None, symbol='o', symbolPen='c', name='Last shot', symbolBrush=None) |
|
749 |
|
self.shot = plot_widget.plot(pos, pen=None, symbol='+', symbolPen='c', name='Last shot') |
|
750 |
|
self.last.setZValue(110) |
|
751 |
|
self.shot.setZValue(110) |
|
752 |
|
|
|
753 |
|
self.plot() |
|
754 |
|
|
|
755 |
|
def plot(self): |
|
756 |
|
if self.item.checkState() and (self.w.last_shot is not None): |
|
757 |
|
pos = getattr(self.w.last_shot, self.w.space)[:,:2] |
|
758 |
|
self.last.setData(pos) |
|
759 |
|
self.shot.setData(pos) |
|
760 |
|
self.last.show() |
|
761 |
|
self.shot.show() |
|
762 |
|
else: |
|
763 |
|
self.last.hide() |
|
764 |
|
self.shot.hide() |
|
765 |
|
|
|
766 |
|
|
|
767 |
|
|
|
768 |
|
#č Kružničky chcete? |
|
769 |
|
#ё Кружочки ннада? |
|
770 |
|
class Circles: |
|
771 |
|
def __init__(self, w): |
|
772 |
|
self.w = w |
|
773 |
|
self.w.space_changed.connect(self.plot) |
|
774 |
|
self.w.redraw_called.connect(self.redraw) |
|
775 |
|
|
|
776 |
|
self.name = 'Circles' |
|
777 |
|
self.item = QtGui.QListWidgetItem(self.name) |
|
778 |
|
self.item.setFlags(self.item.flags() | QtCore.Qt.ItemIsUserCheckable) |
|
779 |
|
self.item.setCheckState(QtCore.Qt.Checked) |
|
780 |
|
self.w.list_view.addItem(self.item) |
|
781 |
|
self.w.list_view.itemChanged.connect(self.show_slot) |
|
782 |
|
|
|
783 |
|
self.color = 'k' |
|
784 |
|
self.z_value = -1 |
|
785 |
|
|
|
786 |
|
def redraw(self): |
|
787 |
|
pos = () |
|
788 |
|
plot_widget = self.w.central_widget |
|
789 |
|
|
|
790 |
|
self.circles = [] |
|
791 |
|
ncircles = self.w.ncircles |
|
792 |
|
for r in range(ncircles): |
|
793 |
|
pen = pg.mkPen(color=self.color, width=self.w.px_size*(1-r/ncircles)) |
|
794 |
|
circle = plot_widget.plot(pos=pos, pen=pen, name=self.name) |
|
795 |
|
circle.setZValue(self.z_value) |
|
796 |
|
self.circles.append(circle) |
|
797 |
|
|
|
798 |
|
self.plot() |
|
799 |
|
|
|
800 |
|
def show_slot(self, item): |
|
801 |
|
if item is self.item: |
|
802 |
|
self.plot() |
|
803 |
|
|
|
804 |
|
def plot(self): |
|
805 |
|
if self.item.checkState(): |
|
806 |
|
|
|
807 |
|
f_model = self.w.sample_box.f_model |
|
808 |
|
|
|
809 |
|
nrod = 200 |
|
810 |
|
phi = np.linspace(0, 6.283185307, nrod, endpoint=True) |
|
811 |
|
cos_phi = np.cos(phi) |
|
812 |
|
sin_phi = np.sin(phi) |
|
813 |
|
for r in range(len(self.circles)): |
|
814 |
|
bound_x = r * cos_phi |
|
815 |
|
bound_y = r * sin_phi |
|
816 |
|
|
|
817 |
|
|
|
818 |
|
#оӵ малы транспонировать кароно? Озьы кулэ! |
|
819 |
|
bound = np.array((bound_x, bound_y)).T |
|
820 |
|
f = f_model.new_sample(bound, space='G', extend=True) |
|
821 |
|
pos = getattr(f, self.w.space)[:,:2] |
|
822 |
|
self.circles[r].setData(pos) |
|
823 |
|
self.circles[r].show() |
|
824 |
|
|
|
825 |
|
else: |
|
826 |
|
for circle in self.circles: |
|
827 |
|
circle.hide() |
|
828 |
|
|
|
829 |
|
|
|
830 |
|
class Isocurves: |
|
831 |
|
def __init__(self, w): |
|
832 |
|
self.w = w |
|
833 |
|
self.w.space_changed.connect(self.on_space_changed) |
|
834 |
|
self.w.redraw_called.connect(self.redraw) |
|
835 |
|
|
|
836 |
|
self.contour_item = QtGui.QListWidgetItem('Isolevels') # Density contours |
|
837 |
|
self.contour_item.setFlags(self.contour_item.flags() | QtCore.Qt.ItemIsUserCheckable) |
|
838 |
|
self.contour_item.setCheckState(QtCore.Qt.Unchecked) |
|
839 |
|
self.w.list_view.addItem(self.contour_item) |
|
840 |
|
|
|
841 |
|
self.isocurve_item = QtGui.QListWidgetItem('Isocurves') |
|
842 |
|
self.isocurve_item.setFlags(self.isocurve_item.flags() | QtCore.Qt.ItemIsUserCheckable) |
|
843 |
|
self.isocurve_item.setCheckState(QtCore.Qt.Unchecked) |
|
844 |
|
self.w.list_view.addItem(self.isocurve_item) |
|
845 |
|
|
|
846 |
|
self.w.list_view.itemChanged.connect(self.show_slot) |
|
847 |
|
|
|
848 |
|
self.z_value = 1 |
|
849 |
|
self.ngrid = 300 |
|
850 |
|
|
|
851 |
|
def redraw(self): |
|
852 |
|
self.curves = [] |
|
853 |
|
if self.contour_item.checkState() or self.isocurve_item.checkState(): |
|
854 |
|
#č nejdřív data |
|
855 |
|
f_model = self.w.sample_box.f_model |
|
856 |
|
|
|
857 |
|
ns = 100 #č levný IS |
|
858 |
|
sample = np.random.randn(ns, 2)*3 |
|
859 |
|
self.f = f_model.new_sample(sample, space='G', extend=True) |
|
860 |
|
|
|
861 |
|
self.on_space_changed() |
|
862 |
|
|
|
863 |
|
def on_space_changed(self): |
|
864 |
|
if self.contour_item.checkState() or self.isocurve_item.checkState(): |
|
865 |
|
points = getattr(self.f, self.w.space) |
|
866 |
|
|
|
867 |
|
#č valčím s nekoněčno |
|
868 |
|
mask = np.all(np.isfinite(points), axis=1) |
|
869 |
|
|
|
870 |
|
self.max = np.max(points[mask], axis=0) |
|
871 |
|
self.min = np.min(points[mask], axis=0) |
|
872 |
|
|
|
873 |
|
ngrid = self.ngrid |
|
874 |
|
grid = np.mgrid[0:ngrid,0:ngrid].T.reshape(-1, 2) |
|
875 |
|
# scale |
|
876 |
|
grid = self.grid_scale(grid) |
|
877 |
|
|
|
878 |
|
f_model = self.w.sample_box.f_model |
|
879 |
|
self.pdf = f_model.sample_pdf(grid, space=self.w.space) |
|
880 |
|
#č pokud tam budou nanka, pak nikdo nic nedostane |
|
881 |
|
#č u současných f_modelů však nemají být |
|
882 |
|
self.pdf = np.nan_to_num(self.pdf, copy=False) |
|
883 |
|
#č reshape, flip a rot90 dle dokumentaci vracej view |
|
884 |
|
#č povede-li to numpy, data nebudou žrat další místo v paměti |
|
885 |
|
self.data = self.pdf.reshape((ngrid, ngrid)) |
|
886 |
|
#č bůhví co ta pomocná funkce očekává za vstup |
|
887 |
|
#č a co je zvykem u těch borců co pracujou s obrázky |
|
888 |
|
#č zkrátka, empiricky - buď zde flipnout a pootočit |
|
889 |
|
#č nebo tam dále prohodit souřadnice |
|
890 |
|
self.data = np.flip(self.data, axis=0) |
|
891 |
|
self.data = np.rot90(self.data, k=-1) |
|
892 |
|
|
|
893 |
|
|
|
894 |
|
self.plot() |
|
895 |
|
|
|
896 |
|
|
|
897 |
|
def show_slot(self, item): |
|
898 |
|
#č ne že by to bylo úplně ideální, ale ponechám dva druhy isočár sdruženými |
|
899 |
|
#č společný plot, společný redraw a společné self.curves |
|
900 |
|
if (item is self.contour_item) or (item is self.isocurve_item): |
|
901 |
|
if 'f' in self.__dict__: |
|
902 |
|
self.plot() |
|
903 |
|
else: |
|
904 |
|
self.redraw() |
|
905 |
|
|
|
906 |
|
def grid_scale(self, grid): |
|
907 |
|
# scale |
|
908 |
|
_grid = grid * (self.max - self.min) / (self.ngrid-1) |
|
909 |
|
# loc |
|
910 |
|
_grid = _grid + self.min |
|
911 |
|
return _grid |
|
912 |
|
|
|
913 |
|
def plot(self): |
|
914 |
|
#č zejmena tady je to nepříjemný |
|
915 |
|
#č třeba bude překreslovat jednu položky |
|
916 |
|
#č když jen odcvaknutá druhá |
|
917 |
|
for curve in self.curves: |
|
918 |
|
self.w.central_widget.removeItem(curve) |
|
919 |
|
|
|
920 |
|
ncurves = self.w.ncircles |
|
921 |
|
if self.contour_item.checkState(): |
|
922 |
|
levels = np.linspace(self.pdf.max(), 0, ncurves+1, endpoint=False)[1:] |
|
923 |
|
self._draw_curves(levels, 'Isolevels', (170, 85, 0)) |
|
924 |
|
|
|
925 |
|
if self.isocurve_item.checkState(): |
|
926 |
|
const = 1 / np.prod(self.max - self.min) |
|
927 |
|
r_levels = np.arange(ncurves) + 1 |
|
928 |
|
#č P prostor doopravdy zlobí, takže nějak tak |
|
929 |
|
levels = misc.isolevels_2d(self.pdf, const, r_levels, from_top=False) |
|
930 |
|
self._draw_curves(levels, 'Isocurves', (100, 45, 0)) |
|
931 |
|
|
|
932 |
|
def _draw_curves(self, levels, name, color): |
|
933 |
|
ncurves = self.w.ncircles |
|
934 |
|
plot_widget = self.w.central_widget |
|
935 |
|
for r in range(ncurves): |
|
936 |
|
pen = pg.mkPen(color=color, width=self.w.px_size*(1-r/ncurves)) |
|
937 |
|
|
|
938 |
|
v = levels[r] |
|
939 |
|
|
|
940 |
|
#č vrací souřadnice v prostoru "gridu" |
|
941 |
|
lines = pg.functions.isocurve(self.data, v, connected=True) |
|
942 |
|
for line in lines: |
|
943 |
|
grid = np.array(line) |
|
944 |
|
#grid = np.flip(grid, axis=1) |
|
945 |
|
|
|
946 |
|
#č tady mám výsledek dvouletého výzkumu |
|
947 |
|
grid = grid - 0.5 |
|
948 |
|
|
|
949 |
|
# scale |
|
950 |
|
grid = self.grid_scale(grid) |
|
951 |
|
curve = plot_widget.plot(grid, pen=pen, name=name) |
|
952 |
|
curve.setZValue(self.z_value) |
|
953 |
|
self.curves.append(curve) |
|
954 |
|
|
|
955 |
|
|
|
956 |
|
|
|
957 |
|
class Boundaries: |
|
958 |
|
def __init__(self, w): |
|
959 |
|
self.w = w |
|
960 |
|
self.w.space_changed.connect(self.plot) |
|
961 |
|
self.w.redraw_called.connect(self.redraw) |
|
962 |
|
|
|
963 |
|
self.item = QtGui.QListWidgetItem('Boundaries') |
|
964 |
|
self.item.setFlags(self.item.flags() | QtCore.Qt.ItemIsUserCheckable) |
|
965 |
|
self.item.setCheckState(QtCore.Qt.Checked) |
|
966 |
|
self.w.list_view.addItem(self.item) |
|
967 |
|
self.w.list_view.itemChanged.connect(self.show_slot) |
|
968 |
|
|
|
969 |
|
|
|
970 |
|
def redraw(self): |
|
971 |
|
pos = () |
|
972 |
|
plot_widget = self.w.central_widget |
|
973 |
|
|
|
974 |
|
self.bounds = [] |
|
975 |
|
# ne všichni majó definované hranice |
|
976 |
|
try: |
|
977 |
|
for bound in self.w.sample_box.get_2D_boundary(nrod=1000): |
|
978 |
|
item = plot_widget.plot(pos=pos, pen='b', name='Boundaries') |
|
979 |
|
item.setZValue(70) |
|
980 |
|
self.bounds.append((bound, item)) |
|
981 |
|
except AttributeError: |
|
982 |
|
pass #print("čo sa děje?") |
|
983 |
|
|
|
984 |
|
self.plot() |
|
985 |
|
|
|
986 |
|
def show_slot(self, item): |
|
987 |
|
if item is self.item: |
|
988 |
|
self.plot() |
|
989 |
|
|
|
990 |
|
def plot(self): |
|
991 |
|
if self.item.checkState(): |
|
992 |
|
for bound, item in self.bounds: |
|
993 |
|
pos = getattr(bound, self.w.space)[:,:2] |
|
994 |
|
mask = np.all(np.isfinite(pos), axis=1) |
|
995 |
|
item.setData(pos[mask]) |
|
996 |
|
item.show() |
|
997 |
|
|
|
998 |
|
else: |
|
999 |
|
for bound, item in self.bounds: |
|
1000 |
|
item.hide() |
|
1001 |
|
|
|
1002 |
|
|
|
1003 |
|
|
|
1004 |
|
|
|
1005 |
|
class Triangulation: |
|
1006 |
|
def __init__(self, w): |
|
1007 |
|
|
|
1008 |
|
self.w = w |
|
1009 |
|
if self.w.sample_box.nvar == 2: |
|
1010 |
|
self.w.box_runned.connect(self.update) |
|
1011 |
|
self.w.space_changed.connect(self.replot) |
|
1012 |
|
self.w.redraw_called.connect(self.redraw) |
|
1013 |
|
|
|
1014 |
|
self.item = QtGui.QListWidgetItem('Triangulation') |
|
1015 |
|
self.item.setFlags(self.item.flags() | QtCore.Qt.ItemIsUserCheckable) |
|
1016 |
|
self.item.setCheckState(QtCore.Qt.Unchecked) |
|
1017 |
|
self.w.list_view.addItem(self.item) |
|
1018 |
|
|
|
1019 |
|
|
|
1020 |
|
self.w.list_view.itemChanged.connect(self.show_slot) |
|
1021 |
|
|
|
1022 |
|
self.spatial = 'tri' |
|
1023 |
|
|
|
1024 |
|
|
|
1025 |
|
|
|
1026 |
|
def redraw(self): |
|
1027 |
|
self.simplices = np.empty((0,3), dtype=np.int) |
|
1028 |
|
self.plot_items = [] |
|
1029 |
|
self.replot() |
|
1030 |
|
|
|
1031 |
|
|
|
1032 |
|
def show_slot(self, item): |
|
1033 |
|
if item is self.item: |
|
1034 |
|
if (self.w.sample_box.nvar==2) and self.item.checkState(): |
|
1035 |
|
#for item in self.plot_items: |
|
1036 |
|
# item.show() |
|
1037 |
|
|
|
1038 |
|
#оӵ Мед сюредалоз! |
|
1039 |
|
self.replot() |
|
1040 |
|
|
|
1041 |
|
else: #оӵ Медам сюреда! |
|
1042 |
|
for item in self.plot_items: |
|
1043 |
|
item.hide() |
|
1044 |
|
|
|
1045 |
|
|
|
1046 |
|
|
|
1047 |
|
def replot(self): |
|
1048 |
|
""" |
|
1049 |
|
on space_chainged |
|
1050 |
|
or something like this |
|
1051 |
|
when we need to completely |
|
1052 |
|
redraw the triangulation |
|
1053 |
|
""" |
|
1054 |
|
if self.item.checkState(): |
|
1055 |
|
try: |
|
1056 |
|
spatial = getattr(self.w.sample_box, self.spatial) |
|
1057 |
|
self.simplices = spatial.simplices |
|
1058 |
|
for item in self.plot_items: |
|
1059 |
|
item.hide() |
|
1060 |
|
self.draw_simplices(range(len(self.simplices))) |
|
1061 |
|
|
|
1062 |
|
except BaseException as e: |
|
1063 |
|
msg = "error during replot" |
|
1064 |
|
print(self.__class__.__name__ + ":",msg, repr(e)) |
|
1065 |
|
|
|
1066 |
|
|
|
1067 |
|
|
|
1068 |
|
def update(self): |
|
1069 |
|
# update triangulation |
|
1070 |
|
if self.item.checkState(): |
|
1071 |
|
try: #оӵ Мед сюредалоз! |
|
1072 |
|
former_simplices = self.simplices |
|
1073 |
|
spatial = getattr(self.w.sample_box, self.spatial) |
|
1074 |
|
self.simplices = spatial.simplices |
|
1075 |
|
|
|
1076 |
|
#č počet simplexů může se přidaním bodů změnšit |
|
1077 |
|
#č (hlavně u ConvexHull, ale coplanar taky může vyskočit) |
|
1078 |
|
if len(self.simplices) < len(former_simplices): |
|
1079 |
|
self.replot() |
|
1080 |
|
else: |
|
1081 |
|
#č zkontrolujeme co se změnilo |
|
1082 |
|
equal_mask = former_simplices == self.simplices[:len(former_simplices)] |
|
1083 |
|
changed_simplices_ids = np.argwhere(~equal_mask.all(axis=1)).flatten() |
|
1084 |
|
self.draw_simplices(changed_simplices_ids) |
|
1085 |
|
|
|
1086 |
|
#č teď nové simplexy |
|
1087 |
|
#ё simplexy свежего разлива |
|
1088 |
|
self.draw_simplices(range(len(former_simplices), len(self.simplices))) |
|
1089 |
|
|
|
1090 |
|
except BaseException as e: |
|
1091 |
|
msg = "error during update" |
|
1092 |
|
print(self.__class__.__name__ + ":",msg, repr(e)) |
|
1093 |
|
|
|
1094 |
|
|
|
1095 |
|
|
|
1096 |
|
|
|
1097 |
|
def set_plot_data(self, pos, simplex_id): |
|
1098 |
|
if simplex_id < len(self.plot_items): |
|
1099 |
|
# Update the data |
|
1100 |
|
plot_item = self.plot_items[simplex_id] |
|
1101 |
|
plot_item.setData(pos) |
|
1102 |
|
plot_item.show() |
|
1103 |
|
else: #č spolehám na korektnost volajícího kódu |
|
1104 |
|
#оӵ Суредасько |
|
1105 |
|
plot_widget = self.w.central_widget |
|
1106 |
|
plot_item = plot_widget.plot(pos, pen=0.7) |
|
1107 |
|
self.plot_items.append(plot_item) |
|
1108 |
|
|
|
1109 |
|
|
|
1110 |
|
#č já jsem tu všecko překopal protože .plot() a .setData() jsou nejžravejší na čas |
|
1111 |
|
#č a nemá žádnou cenu je provadet hned vedle sebe (spouští totéž dvakrát) |
|
1112 |
|
def draw_simplices(self, simplex_ids): |
|
1113 |
|
# take coordinates in the space, where triangulation has been performed |
|
1114 |
|
sampled_plan_tri = getattr(self.w.sample_box, self.w.sample_box.tri_space) |
|
1115 |
|
|
|
1116 |
|
if self.w.space == self.w.sample_box.tri_space: |
|
1117 |
|
for simplex_id in simplex_ids: |
|
1118 |
|
triangle = self.simplices[simplex_id] |
|
1119 |
|
pos = sampled_plan_tri[triangle[[0,1,2,0]]] |
|
1120 |
|
|
|
1121 |
|
self.set_plot_data(pos, simplex_id) |
|
1122 |
|
|
|
1123 |
|
else: |
|
1124 |
|
ns = 100 |
|
1125 |
|
with pg.BusyCursor(): |
|
1126 |
|
for simplex_id in simplex_ids: |
|
1127 |
|
triangle = self.simplices[simplex_id] |
|
1128 |
|
# keep the GUI responsive :) |
|
1129 |
|
# it was quite slow on my target machine |
|
1130 |
|
self.w.app.processEvents() |
|
1131 |
|
|
|
1132 |
|
x_tri_1 = np.linspace(sampled_plan_tri[triangle[0],0], sampled_plan_tri[triangle[1],0], ns, endpoint=False) |
|
1133 |
|
y_tri_1 = np.linspace(sampled_plan_tri[triangle[0],1], sampled_plan_tri[triangle[1],1], ns, endpoint=False) |
|
1134 |
|
x_tri_2 = np.linspace(sampled_plan_tri[triangle[1],0], sampled_plan_tri[triangle[2],0], ns, endpoint=False) |
|
1135 |
|
y_tri_2 = np.linspace(sampled_plan_tri[triangle[1],1], sampled_plan_tri[triangle[2],1], ns, endpoint=False) |
|
1136 |
|
x_tri_3 = np.linspace(sampled_plan_tri[triangle[2],0], sampled_plan_tri[triangle[0],0], ns, endpoint=True) |
|
1137 |
|
y_tri_3 = np.linspace(sampled_plan_tri[triangle[2],1], sampled_plan_tri[triangle[0],1], ns, endpoint=True) |
|
1138 |
|
|
|
1139 |
|
tri_bound_tri = np.concatenate(((x_tri_1, y_tri_1), (x_tri_2, y_tri_2), (x_tri_3, y_tri_3)), axis=1).T |
|
1140 |
|
#č vytvořme sample |
|
1141 |
|
tri_bound = self.w.sample_box.f_model.new_sample(tri_bound_tri, space=self.w.sample_box.tri_space) |
|
1142 |
|
pos = getattr(tri_bound, self.w.space) |
|
1143 |
|
|
|
1144 |
|
self.set_plot_data(pos, simplex_id) |
|
1145 |
|
|
|
1146 |
|
|
|
1147 |
|
|
|
1148 |
|
|
|
1149 |
|
class ConvexHull2D(Triangulation): |
|
1150 |
|
def __init__(self, w): |
|
1151 |
|
|
|
1152 |
|
self.w = w |
|
1153 |
|
if self.w.sample_box.nvar == 2: |
|
1154 |
|
self.w.box_runned.connect(self.update) |
|
1155 |
|
self.w.space_changed.connect(self.replot) |
|
1156 |
|
self.w.redraw_called.connect(self.redraw) |
|
1157 |
|
|
|
1158 |
|
self.item = QtGui.QListWidgetItem('Convex hull') |
|
1159 |
|
self.item.setFlags(self.item.flags() | QtCore.Qt.ItemIsUserCheckable) |
|
1160 |
|
self.item.setCheckState(QtCore.Qt.Checked) |
|
1161 |
|
self.w.list_view.addItem(self.item) |
|
1162 |
|
|
|
1163 |
|
|
|
1164 |
|
self.w.list_view.itemChanged.connect(self.show_slot) |
|
1165 |
|
|
|
1166 |
|
self.spatial = 'convex_hull' |
|
1167 |
|
|
|
1168 |
|
|
|
1169 |
|
|
|
1170 |
|
def redraw(self): |
|
1171 |
|
self.simplices = np.empty((0,2), dtype=np.int) |
|
1172 |
|
self.plot_items = [] |
|
1173 |
|
self.replot() |
|
1174 |
|
|
|
1175 |
|
|
|
1176 |
|
|
|
1177 |
|
|
|
1178 |
|
|
|
1179 |
|
#č já jsem tu všecko překopal protože .plot() a .setData() jsou nejžravejší na čas |
|
1180 |
|
#č a nemá žádnou cenu je provadet hned vedle sebe (spouští totéž dvakrát) |
|
1181 |
|
def draw_simplices(self, simplex_ids): |
|
1182 |
|
|
|
1183 |
|
# convex hull should be made in the same space as triangulation, I guess |
|
1184 |
|
# take coordinates in the triangulation space |
|
1185 |
|
sampled_plan_tri = getattr(self.w.sample_box, self.w.sample_box.tri_space) |
|
1186 |
|
|
|
1187 |
|
plot_widget = self.w.central_widget |
|
1188 |
|
|
|
1189 |
|
if self.w.space == self.w.sample_box.tri_space: |
|
1190 |
|
for simplex_id in simplex_ids: |
|
1191 |
|
pos = sampled_plan_tri[self.simplices[simplex_id]] |
|
1192 |
|
|
|
1193 |
|
self.set_plot_data(pos, simplex_id) |
|
1194 |
|
|
|
1195 |
|
else: |
|
1196 |
|
ns = 100 |
|
1197 |
|
#оӵ кулэ ӧвӧл обновлять экран карыны |
|
1198 |
|
for simplex_id in simplex_ids: |
|
1199 |
|
start_id, end_id = self.simplices[simplex_id] |
|
1200 |
|
|
|
1201 |
|
x_bound = np.linspace(sampled_plan_tri[start_id,0], sampled_plan_tri[end_id,0], ns, endpoint=True) |
|
1202 |
|
y_bound = np.linspace(sampled_plan_tri[start_id,1], sampled_plan_tri[end_id,1], ns, endpoint=True) |
|
1203 |
|
|
|
1204 |
|
# sample compatible |
|
1205 |
|
#оӵ малы транспонировать кароно? Озьы кулэ! |
|
1206 |
|
bound_tri = np.vstack((x_bound, y_bound)).T |
|
1207 |
|
#č vytvořme sample |
|
1208 |
|
bound = self.w.sample_box.f_model.new_sample(bound_tri, space=self.w.sample_box.tri_space) |
|
1209 |
|
pos = getattr(bound, self.w.space) |
|
1210 |
|
|
|
1211 |
|
self.set_plot_data(pos, simplex_id) |
|
1212 |
|
|
|
1213 |
|
|
|
1214 |
|
|
|
1215 |
|
|
|
1216 |
|
|
|
1217 |
|
""" |
|
1218 |
|
============= |
|
1219 |
|
График виӝет |
|
1220 |
|
Grafy |
|
1221 |
|
Estimation graph widgets |
|
1222 |
|
======================== |
|
1223 |
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
1224 |
|
""" |
|
1225 |
|
|
|
1226 |
|
|
|
1227 |
|
def get_estimation_data(estimations, metric): |
|
1228 |
|
metric_dict = dict() |
|
1229 |
|
# new-style: šecko leží dohromady a každý z toho |
|
1230 |
|
# bere co chce a jak chce |
|
1231 |
|
# ne že by to bylo nějak šetrný |
|
1232 |
|
# estimation je slovníkem |
|
1233 |
|
for estimation in estimations: |
|
1234 |
|
# nsim musí mäť každej odhad |
|
1235 |
|
# pokud nemá - je třeba jej prostě opravit |
|
1236 |
|
nsim = estimation['nsim'] |
|
1237 |
|
try: |
|
1238 |
|
metric_dict[nsim] = estimation[metric] |
|
1239 |
|
except KeyError as e: |
|
1240 |
|
pass #print(self.__class__.__name__ + ":", repr(e)) |
|
1241 |
|
|
|
1242 |
|
# nikdo neslibil, že budou v pořadí |
|
1243 |
|
x = np.sort(tuple(metric_dict.keys())) |
|
1244 |
|
y = np.array(tuple(metric_dict.values()))[np.argsort(tuple(metric_dict.keys()))] |
|
1245 |
|
return x, y |
|
1246 |
|
|
|
1247 |
|
|
|
1248 |
|
class SimplexEstimationData(QtCore.QObject): |
|
1249 |
|
#š budeme mӓť svůj vlastní signaľčík |
|
1250 |
|
simplex_estimation_updated = QtCore.pyqtSignal() |
|
1251 |
|
|
|
1252 |
|
def __init__(self, dice_box, stream=None, *args, **kwargs): |
|
1253 |
|
super().__init__(stream, *args, **kwargs) |
|
1254 |
|
self.dice_box = dice_box |
|
1255 |
|
#č je zřejmě, že tím potokem bylo myšleno hlavní okínko |
|
1256 |
|
#č asi aby nepadalo, když nenajde signaly |
|
1257 |
|
self.stream = stream |
|
1258 |
|
if stream is not None: |
|
1259 |
|
self.stream.box_runned.connect(self.recalculate) |
|
1260 |
|
self.stream.estimation_added.connect(self.recalculate) |
|
1261 |
|
|
|
1262 |
|
self.setup_context_menu() |
|
1263 |
|
self.recalculate() |
|
1264 |
|
|
|
1265 |
|
|
|
1266 |
|
def setup_context_menu(self): |
|
1267 |
|
# simplex_data_menu |
|
1268 |
|
self.TRI_menu = QtGui.QMenu("TRI sources", self.stream) |
|
1269 |
|
|
|
1270 |
|
self.TRI_overall_chk = QtGui.QAction("TRI_overall_estimations", self.TRI_menu) |
|
1271 |
|
self.TRI_overall_chk.setCheckable(True) |
|
1272 |
|
self.TRI_overall_chk.setChecked(True) |
|
1273 |
|
self.TRI_overall_chk.triggered.connect(self.recalculate) |
|
1274 |
|
self.TRI_menu.addAction(self.TRI_overall_chk) |
|
1275 |
|
|
|
1276 |
|
self.simplex_chk = QtGui.QAction("Simplex estimations", self.TRI_menu) |
|
1277 |
|
self.simplex_chk.setCheckable(True) |
|
1278 |
|
self.simplex_chk.setChecked(True) |
|
1279 |
|
self.simplex_chk.triggered.connect(self.recalculate) |
|
1280 |
|
self.TRI_menu.addAction(self.simplex_chk) |
|
1281 |
|
|
|
1282 |
|
# year, it was |
|
1283 |
|
## hope, it is temporary |
|
1284 |
|
#self.sources_action_group = QtGui.QActionGroup(self.TRI_menu) |
|
1285 |
|
#self.sources_action_group.addAction(self.TRI_overall_chk) |
|
1286 |
|
#self.sources_action_group.addAction(self.simplex_chk) |
|
1287 |
|
|
|
1288 |
|
self.TRI_menu.addSeparator() |
|
1289 |
|
|
|
1290 |
|
self.proxy_chk = QtGui.QAction("Proxy", self.TRI_menu) |
|
1291 |
|
self.proxy_chk.setCheckable(True) |
|
1292 |
|
self.proxy_chk.setChecked(hasattr(self.dice_box, 'proxy')) |
|
1293 |
|
self.proxy_chk.triggered.connect(self.recalculate) |
|
1294 |
|
self.TRI_menu.addAction(self.proxy_chk) |
|
1295 |
|
|
|
1296 |
|
self.TRI_menu.addSeparator() |
|
1297 |
|
|
|
1298 |
|
self.reaction = QtGui.QAction("Update", self.TRI_menu) |
|
1299 |
|
self.reaction.triggered.connect(self.recalculate) |
|
1300 |
|
self.TRI_menu.addAction(self.reaction) |
|
1301 |
|
|
|
1302 |
|
self.excelaction = QtGui.QAction("Export to Excel", self.TRI_menu) |
|
1303 |
|
self.excelaction.triggered.connect(self.export_to_excel) |
|
1304 |
|
self.TRI_menu.addAction(self.excelaction) |
|
1305 |
|
|
|
1306 |
|
|
|
1307 |
|
def export_to_excel(self): |
|
1308 |
|
#č já bych nechtěl, aby mně export najednou spadl |
|
1309 |
|
#č z jakéhokoliv důvodu |
|
1310 |
|
try: |
|
1311 |
|
proposal_filename = self.dice_box.guessbox.filename |
|
1312 |
|
if proposal_filename: |
|
1313 |
|
proposal_filename += '.xlsx' |
|
1314 |
|
else: |
|
1315 |
|
proposal_filename = self.dice_box.gm_signature + '.xlsx' |
|
1316 |
|
filename, *__ = pg.FileDialog.getSaveFileName(self.stream, 'Export to Excel',\ |
|
1317 |
|
proposal_filename, initialFilter='*.xlsx') |
|
1318 |
|
self.df.to_excel(filename) |
|
1319 |
|
except BaseException as e: |
|
1320 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
1321 |
|
|
|
1322 |
|
|
|
1323 |
|
def recalculate(self): |
|
1324 |
|
try: |
|
1325 |
|
# sources=['box', 'user'] |
|
1326 |
|
sources = list() |
|
1327 |
|
if self.TRI_overall_chk.isChecked(): |
|
1328 |
|
sources.append('box') |
|
1329 |
|
if self.simplex_chk.isChecked(): |
|
1330 |
|
sources.append('user') |
|
1331 |
|
|
|
1332 |
|
self.df = stm_df.get_tri_data_frame(self.dice_box, sources=sources,\ |
|
1333 |
|
apply_proxy=self.proxy_chk.isChecked()) |
|
1334 |
|
self.simplex_estimation_updated.emit() |
|
1335 |
|
|
|
1336 |
|
except BaseException as e: |
|
1337 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
1338 |
|
|
|
1339 |
|
|
|
1340 |
|
|
|
1341 |
|
class SimplexEstimationGraph(pg.PlotWidget): |
|
1342 |
|
def __init__(self, dice_box, stream=None, parent=None, *args, **kwargs): |
|
1343 |
|
super().__init__(parent, *args, **kwargs) |
|
1344 |
|
#č je zřejmě, že tím potokem bylo myšleno hlavní okínko |
|
1345 |
|
#č asi aby nepadalo, když nenajde signaly |
|
1346 |
|
self.stream = stream |
|
1347 |
|
if stream is not None: |
|
1348 |
|
self.stream.box_runned.connect(self.redraw) |
|
1349 |
|
self.stream.estimation_added.connect(self.redraw) |
|
1350 |
|
|
|
1351 |
|
self.dice_box = dice_box |
|
1352 |
|
|
|
1353 |
|
self.setup_context_menu() |
|
1354 |
|
self.setup() |
|
1355 |
|
self.replot() |
|
1356 |
|
|
|
1357 |
|
def setup_context_menu(self): |
|
1358 |
|
# creates instance of LegendItem |
|
1359 |
|
# and saves it into plotItem.legend |
|
1360 |
|
self.legend = self.addLegend() |
|
1361 |
|
|
|
1362 |
|
self.plotItem.ctrl.xGridCheck.setChecked(True) |
|
1363 |
|
self.plotItem.ctrl.yGridCheck.setChecked(True) |
|
1364 |
|
|
|
1365 |
|
# delete build-in Transforms (with Log_x and Log_y) options, |
|
1366 |
|
# they can cause uncachable exception (on any zero in data) and crash |
|
1367 |
|
self.plotItem.ctrlMenu.removeAction(self.plotItem.ctrlMenu.actions()[0]) |
|
1368 |
|
|
|
1369 |
|
#č já se bojím. radší to uložím |
|
1370 |
|
self.custom_menu = self.plotItem.vb.menu.addMenu("TRI options") |
|
1371 |
|
|
|
1372 |
|
self.plotItem.vb.menu.addMenu(self.stream.simplex_data.TRI_menu) |
|
1373 |
|
|
|
1374 |
|
self.legend_chk = QtGui.QAction("Legend", self.custom_menu) |
|
1375 |
|
self.legend_chk.setCheckable(True) |
|
1376 |
|
self.legend_chk.triggered.connect(lambda: self.legend.setVisible(self.legend_chk.isChecked())) |
|
1377 |
|
self.custom_menu.addAction(self.legend_chk) |
|
1378 |
|
# apply custom menu option |
|
1379 |
|
self.legend.setVisible(self.legend_chk.isChecked()) |
|
1380 |
|
|
|
1381 |
|
self.log_x_chk = QtGui.QAction("Log X", self.custom_menu) |
|
1382 |
|
self.log_x_chk.setCheckable(True) |
|
1383 |
|
self.log_x_chk.triggered.connect(lambda: self.setLogMode(x=self.log_x_chk.isChecked())) |
|
1384 |
|
self.custom_menu.addAction(self.log_x_chk) |
|
1385 |
|
|
|
1386 |
|
self.log_y_chk = QtGui.QAction("Log Y", self.custom_menu) |
|
1387 |
|
self.log_y_chk.setCheckable(True) |
|
1388 |
|
self.log_y_chk.setChecked(True) |
|
1389 |
|
self.log_y_chk.triggered.connect(self.replot) |
|
1390 |
|
self.custom_menu.addAction(self.log_y_chk) |
|
1391 |
|
|
|
1392 |
|
self.laction = QtGui.QAction("Show labels", self.custom_menu) |
|
1393 |
|
self.laction.triggered.connect(self.show_labels) |
|
1394 |
|
self.custom_menu.addAction(self.laction) |
|
1395 |
|
|
|
1396 |
|
|
|
1397 |
|
def show_labels(self): |
|
1398 |
|
self.setLabel('left', "Probability measure") |
|
1399 |
|
self.setLabel('bottom', "Number of simulations") |
|
1400 |
|
|
|
1401 |
|
|
|
1402 |
|
|
|
1403 |
|
# self.legend.addItem(self.pen_success, "success domain estimation") |
|
1404 |
|
# self.legend.addItem(self.pen_outside, "out of sampling domain estimation") |
|
1405 |
|
# self.legend.addItem(self.pen_mix, "mixed simplices measure") |
|
1406 |
|
# self.legend.addItem(self.pen_f, "failure domain estimation") |
|
1407 |
|
|
|
1408 |
|
def setup(self, *args, **kwargs): |
|
1409 |
|
self.clear() |
|
1410 |
|
self.setBackground('w') |
|
1411 |
|
x = y = () # zde jen vytvoříme kostru, nakrmime daty v .redraw() |
|
1412 |
|
|
|
1413 |
|
#xkcd_green = (167, 255, 181) # xkcd:light seafoam green #a7ffb5 |
|
1414 |
|
green = (0, 255, 38, 96) |
|
1415 |
|
#xkcd_red = (253, 193, 197) # xkcd: pale rose (#fdc1c5) |
|
1416 |
|
red = (253, 0, 17, 96) |
|
1417 |
|
#xkcd_cream = (255, 243, 154) # let's try xkcd: dark cream (#fff39a) |
|
1418 |
|
cream = (255, 221, 0, 96) |
|
1419 |
|
grey = (196, 196, 196, 96) |
|
1420 |
|
|
|
1421 |
|
self.pen_f = self.plot(x, y, brush=red)#, name="failure domain estimation") |
|
1422 |
|
self.pen_f.setZValue(-100) |
|
1423 |
|
|
|
1424 |
|
self.pen_success = self.plot(x, y, brush=green) #, name="success domain estimation") |
|
1425 |
|
self.pen_success.setZValue(-100) |
|
1426 |
|
|
|
1427 |
|
self.pen_outmix = self.plot(x, y) |
|
1428 |
|
|
|
1429 |
|
self.fill_mix = pg.FillBetweenItem(self.pen_f, self.pen_outmix) |
|
1430 |
|
#self.fill_mix.setData(name="mixed simplices measure") |
|
1431 |
|
self.fill_mix.setBrush(cream) |
|
1432 |
|
self.fill_mix.setZValue(-100) |
|
1433 |
|
self.addItem(self.fill_mix) |
|
1434 |
|
|
|
1435 |
|
#self.pen_outside = self.plot(x, y) |
|
1436 |
|
self.fill_outside = pg.FillBetweenItem(self.pen_outmix, self.pen_success) |
|
1437 |
|
#self.fill_outside.setData(name="out of sampling domain estimation") |
|
1438 |
|
self.fill_outside.setBrush(grey) |
|
1439 |
|
self.fill_outside.setZValue(-100) |
|
1440 |
|
self.addItem(self.fill_outside) |
|
1441 |
|
|
|
1442 |
|
self.one_ruler = self.addLine(y=1, pen='k') |
|
1443 |
|
self.zero_ruler = self.addLine(y=0, pen='k') |
|
1444 |
|
|
|
1445 |
|
|
|
1446 |
|
try: |
|
1447 |
|
exact_name = self.dice_box.pf_exact_method |
|
1448 |
|
pen = pg.mkPen(color='b', width=1.5) # blue |
|
1449 |
|
self.pen_exact = self.addLine(y=self.dice_box.pf_exact, pen=pen, name=exact_name) |
|
1450 |
|
#č aby se nám něco zobrazovalo v legendu |
|
1451 |
|
self.pen_exact_PR = self.plot(x, y, pen=pen, name=exact_name) |
|
1452 |
|
except: |
|
1453 |
|
pass |
|
1454 |
|
|
|
1455 |
|
pen = pg.mkPen(color='m', width=2) |
|
1456 |
|
self.pen_vertex = self.plot(x, y, pen=pen, name="simple pf estimation") |
|
1457 |
|
pen = pg.mkPen(color='r', width=2) #(118, 187, 255) |
|
1458 |
|
self.pen_weighted_vertex = self.plot(x, y, pen=pen, name="weighted pf estimation") |
|
1459 |
|
|
|
1460 |
|
|
|
1461 |
|
|
|
1462 |
|
|
|
1463 |
|
|
|
1464 |
|
def replot(self, *args, **kwargs): |
|
1465 |
|
if self.log_y_chk.isChecked(): |
|
1466 |
|
self.one_ruler.hide() |
|
1467 |
|
try: |
|
1468 |
|
#č try nás nezáchraní protí odloženému spádnutí pyqtgraph |
|
1469 |
|
if self.dice_box.pf_exact > 0: |
|
1470 |
|
self.pen_exact.setPos(np.log10(self.dice_box.pf_exact)) |
|
1471 |
|
self.pen_exact.show() |
|
1472 |
|
else: |
|
1473 |
|
self.pen_exact.hide() |
|
1474 |
|
except: |
|
1475 |
|
pass |
|
1476 |
|
self.setLogMode(y=True) |
|
1477 |
|
#self.pen_f.setPen(pg.mkPen(color=(255, 0, 0), width=3)) #, style=QtCore.Qt.DashLine) |
|
1478 |
|
self.pen_f.setPen(None) |
|
1479 |
|
self.pen_f.setFillLevel(None) |
|
1480 |
|
self.pen_success.setFillLevel(0) |
|
1481 |
|
|
|
1482 |
|
else: |
|
1483 |
|
self.one_ruler.show() |
|
1484 |
|
try: |
|
1485 |
|
self.pen_exact.setPos(self.dice_box.pf_exact) |
|
1486 |
|
self.pen_exact.show() |
|
1487 |
|
except: |
|
1488 |
|
pass |
|
1489 |
|
self.setLogMode(y=False) |
|
1490 |
|
self.pen_f.setPen(None) |
|
1491 |
|
self.pen_f.setFillLevel(0) |
|
1492 |
|
self.pen_success.setFillLevel(1) |
|
1493 |
|
|
|
1494 |
|
self.redraw() |
|
1495 |
|
|
|
1496 |
|
|
|
1497 |
|
#č když se někde objeví nula se zapnutým LogModem - |
|
1498 |
|
#č qtpygraph hned spadne a není možne ten pad zachytit |
|
1499 |
|
def zerosafe(self, x, y, fallback_y=None): |
|
1500 |
|
if self.log_y_chk.isChecked(): |
|
1501 |
|
x = np.array(x) |
|
1502 |
|
y = np.array(y) |
|
1503 |
|
if fallback_y is None: |
|
1504 |
|
fallback_y = y |
|
1505 |
|
y = np.where(y > 0, y, fallback_y) |
|
1506 |
|
mask = y > 0 |
|
1507 |
|
return x[mask], y[mask] |
|
1508 |
|
else: |
|
1509 |
|
return x, y |
|
1510 |
|
|
|
1511 |
|
def proxy(self, nsim): |
|
1512 |
|
if self.proxy_chk.isChecked(): |
|
1513 |
|
proxy = self.dice_box.proxy |
|
1514 |
|
index = np.array(nsim)-1 |
|
1515 |
|
#č indexy musíme o jedničku změnšit |
|
1516 |
|
#č výsledek nikoliv. Takže v cajku. |
|
1517 |
|
return np.cumsum(~proxy)[index] |
|
1518 |
|
else: |
|
1519 |
|
return nsim |
|
1520 |
|
|
|
1521 |
|
|
|
1522 |
|
def _pens_data_update(self): |
|
1523 |
|
df = self.df |
|
1524 |
|
nsim = df.nsim.to_numpy() |
|
1525 |
|
if self.proxy_chk.isChecked(): |
|
1526 |
|
x = self.proxy(nsim) |
|
1527 |
|
df.insert(loc=0, column='nsim (proxy)', value=x) |
|
1528 |
|
else: |
|
1529 |
|
x = nsim |
|
1530 |
|
# (in case of LogPlot) fallback values also used |
|
1531 |
|
success_values = df.failure+df.mix+df.out |
|
1532 |
|
outmix_values = df.failure+df.mix |
|
1533 |
|
failure_fallback = np.where(outmix_values > 0, outmix_values, success_values) |
|
1534 |
|
self.pen_f.setData(*self.zerosafe(x, df.failure, failure_fallback)) |
|
1535 |
|
self.pen_outmix.setData(*self.zerosafe(x, outmix_values, success_values)) |
|
1536 |
|
self.pen_success.setData(*self.zerosafe(x, success_values)) |
|
1537 |
|
|
|
1538 |
|
|
|
1539 |
|
def redraw(self): |
|
1540 |
|
xmin = np.inf |
|
1541 |
|
xmax = -np.inf |
|
1542 |
|
tri_estimation = dict() |
|
1543 |
|
try: # тут всё что угодно может пойти не так |
|
1544 |
|
# kruci, ještě navic i generovať pokažde znovu... |
|
1545 |
|
|
|
1546 |
|
# new-style: šecko leží dohromady a každý si z toho |
|
1547 |
|
# bere co chce a jak chce |
|
1548 |
|
# ne že by to bylo nějak šetrný |
|
1549 |
|
# estimation je slovníkem |
|
1550 |
|
for estimation in self.dice_box.estimations: |
|
1551 |
|
# nsim musí mäť každej odhad |
|
1552 |
|
# pokud nemá - je třeba jej prostě opravit |
|
1553 |
|
nsim = estimation['nsim'] |
|
1554 |
|
try: |
|
1555 |
|
tri_estimation[nsim] = estimation['TRI_estimation'] |
|
1556 |
|
if nsim > xmax: |
|
1557 |
|
xmax = nsim |
|
1558 |
|
if nsim < xmin: |
|
1559 |
|
xmin = nsim |
|
1560 |
|
|
|
1561 |
|
except KeyError as e: |
|
1562 |
|
pass #print(self.__class__.__name__ + ":", repr(e)) |
|
1563 |
|
|
|
1564 |
|
#č neotravuj uživatele chybovejma hlaškama |
|
1565 |
|
if tri_estimation: |
|
1566 |
|
# it can be effectively done with pandas |
|
1567 |
|
self.df = df = pd.DataFrame(tuple(tri_estimation.values())) |
|
1568 |
|
# -1 = 'out', 0=success, 1=failure, 2=mix |
|
1569 |
|
df.rename(columns={-1:'out', 0:'success', 1:'failure', 2:'mix'}, inplace=True) |
|
1570 |
|
df.insert(loc=0, column='nsim', value=tuple(tri_estimation.keys()), allow_duplicates=False) |
|
1571 |
|
df.sort_values('nsim', inplace=True) |
|
1572 |
|
|
|
1573 |
|
self._pens_data_update() |
|
1574 |
|
|
|
1575 |
|
nsim, y = get_estimation_data(self.dice_box.estimations, 'vertex_estimation') |
|
1576 |
|
df['vertex_estimation'] = y #č spolehám na konzistenci odhadů (ne úplně) |
|
1577 |
|
self.pen_vertex.setData(*self.zerosafe(self.proxy(nsim), y)) |
|
1578 |
|
|
|
1579 |
|
nsim, y = get_estimation_data(self.dice_box.estimations, 'weighted_vertex_estimation') |
|
1580 |
|
df['weighted_vertex_estimation'] = y #č spolehám na konzistenci odhadů (ne úplně) |
|
1581 |
|
self.pen_weighted_vertex.setData(*self.zerosafe(self.proxy(nsim), y)) |
|
1582 |
|
|
|
1583 |
|
|
|
1584 |
|
except BaseException as e: |
|
1585 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
1586 |
|
|
|
1587 |
|
|
|
1588 |
|
|
|
1589 |
|
class SimplexErrorGraph(pg.PlotWidget): |
|
1590 |
|
def __init__(self, simplex_data, parent=None, *args, **kwargs): |
|
1591 |
|
super().__init__(parent, *args, **kwargs) |
|
1592 |
|
self.simplex_data = simplex_data |
|
1593 |
|
self.simplex_data.simplex_estimation_updated.connect(self.redraw) |
|
1594 |
|
|
|
1595 |
|
self.setup_context_menu() |
|
1596 |
|
self.setup() |
|
1597 |
|
|
|
1598 |
|
def setup_context_menu(self): |
|
1599 |
|
# creates instance of LegendItem |
|
1600 |
|
# and saves it into plotItem.legend |
|
1601 |
|
self.legend = self.addLegend() |
|
1602 |
|
|
|
1603 |
|
self.plotItem.ctrl.xGridCheck.setChecked(True) |
|
1604 |
|
self.plotItem.ctrl.yGridCheck.setChecked(True) |
|
1605 |
|
|
|
1606 |
|
# menu of SimplexEstimationData |
|
1607 |
|
self.plotItem.vb.menu.addMenu(self.simplex_data.TRI_menu) |
|
1608 |
|
|
|
1609 |
|
#č já se bojím. radší to uložím |
|
1610 |
|
self.custom_menu = self.plotItem.vb.menu.addMenu("Error graph") |
|
1611 |
|
|
|
1612 |
|
self.legend_chk = QtGui.QAction("Legend", self.custom_menu) |
|
1613 |
|
self.legend_chk.setCheckable(True) |
|
1614 |
|
self.legend_chk.triggered.connect(lambda: self.legend.setVisible(self.legend_chk.isChecked())) |
|
1615 |
|
self.custom_menu.addAction(self.legend_chk) |
|
1616 |
|
# apply custom menu option |
|
1617 |
|
self.legend.setVisible(self.legend_chk.isChecked()) |
|
1618 |
|
|
|
1619 |
|
self.laction = QtGui.QAction("Show labels", self.custom_menu) |
|
1620 |
|
self.laction.triggered.connect(self.show_labels) |
|
1621 |
|
self.custom_menu.addAction(self.laction) |
|
1622 |
|
|
|
1623 |
|
|
|
1624 |
|
def show_labels(self): |
|
1625 |
|
self.setLabel('left', "Failure probability estimation error") |
|
1626 |
|
self.setLabel('bottom', "Number of simulations") |
|
1627 |
|
|
|
1628 |
|
|
|
1629 |
|
def setup(self, *args, **kwargs): |
|
1630 |
|
self.clear() |
|
1631 |
|
self.setBackground('w') |
|
1632 |
|
x = y = () # zde jen vytvoříme kostru, nakrmime daty v .redraw() |
|
1633 |
|
|
|
1634 |
|
# We will use logMode by default |
|
1635 |
|
self.setLogMode(y=True) |
|
1636 |
|
|
|
1637 |
|
#xkcd_red = (253, 193, 197) # xkcd: pale rose (#fdc1c5) |
|
1638 |
|
#red = (253, 0, 17, 96) |
|
1639 |
|
|
|
1640 |
|
#self.pen_f = self.plot(x, y, brush=red)#, name="failure domain estimation") |
|
1641 |
|
#self.pen_f.setZValue(-100) |
|
1642 |
|
|
|
1643 |
|
|
|
1644 |
|
pen = pg.mkPen(color='m', width=2) |
|
1645 |
|
self.pen_vertex = self.plot(x, y, pen=pen, name="simple pf estimation") |
|
1646 |
|
pen = pg.mkPen(color='r', width=2) #(118, 187, 255) |
|
1647 |
|
self.pen_weighted_vertex = self.plot(x, y, pen=pen, name="weighted pf estimation") |
|
1648 |
|
|
|
1649 |
|
|
|
1650 |
|
|
|
1651 |
|
#č když se někde objeví nula se zapnutým LogModem - |
|
1652 |
|
#č qtpygraph hned spadne a není možne ten pad zachytit |
|
1653 |
|
def zerosafe(self, x, y, fallback_y=None): |
|
1654 |
|
x = np.array(x) |
|
1655 |
|
y = np.array(y) |
|
1656 |
|
if fallback_y is None: |
|
1657 |
|
fallback_y = y |
|
1658 |
|
y = np.where(y > 0, y, fallback_y) |
|
1659 |
|
mask = y > 0 |
|
1660 |
|
return x[mask], y[mask] |
|
1661 |
|
|
|
1662 |
|
|
|
1663 |
|
def redraw(self): |
|
1664 |
|
#č neotravujme uživatele chybovejma hlaškama |
|
1665 |
|
if hasattr(self.simplex_data.dice_box, 'pf_exact'): |
|
1666 |
|
try: #ё тут всё что угодно может пойти не так |
|
1667 |
|
pf_exact = self.simplex_data.dice_box.pf_exact |
|
1668 |
|
|
|
1669 |
|
df = self.simplex_data.df |
|
1670 |
|
#č zapíšeme do data rámu, snad nikomu nebude vadit |
|
1671 |
|
df['vertex_estimation_error'] = df['vertex_estimation'] - pf_exact |
|
1672 |
|
df['weighted_vertex_estimation_error'] = df['weighted_vertex_estimation'] - pf_exact |
|
1673 |
|
|
|
1674 |
|
v = df['vertex_estimation_error'].abs() |
|
1675 |
|
wv = df['weighted_vertex_estimation_error'].abs() |
|
1676 |
|
|
|
1677 |
|
x, y = self.zerosafe(v.index, v.to_numpy()) |
|
1678 |
|
self.pen_vertex.setData(x, y) |
|
1679 |
|
|
|
1680 |
|
x, y = self.zerosafe(wv.index, wv.to_numpy()) |
|
1681 |
|
self.pen_weighted_vertex.setData(x, y) |
|
1682 |
|
|
|
1683 |
|
|
|
1684 |
|
except BaseException as e: |
|
1685 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
1686 |
|
|
|
1687 |
|
|
|
1688 |
|
|
|
1689 |
|
|
|
1690 |
|
|
|
1691 |
|
|
|
1692 |
|
|
|
1693 |
|
# DEPRECATED |
|
1694 |
|
class SimpleSimplexEstimationGraph(pg.PlotWidget): |
|
1695 |
|
def __init__(self, dice_box, stream=None, parent=None, *args, **kwargs): |
|
1696 |
|
super().__init__(parent, *args, **kwargs) |
|
1697 |
|
#č je zřejmě, že tím potokem bylo myšleno hlavní okínko |
|
1698 |
|
#č asi aby nepadalo, když nenajde signaly |
|
1699 |
|
self.stream = stream |
|
1700 |
|
if stream is not None: |
|
1701 |
|
self.stream.box_runned.connect(self.redraw) |
|
1702 |
|
self.stream.estimation_added.connect(self.redraw) |
|
1703 |
|
|
|
1704 |
|
self.dice_box = dice_box |
|
1705 |
|
|
|
1706 |
|
self.setup_context_menu() |
|
1707 |
|
self.setup() |
|
1708 |
|
self.replot() |
|
1709 |
|
|
|
1710 |
|
def setup_context_menu(self): |
|
1711 |
|
# creates instance of LegendItem |
|
1712 |
|
# and saves it into plotItem.legend |
|
1713 |
|
self.legend = self.addLegend() |
|
1714 |
|
|
|
1715 |
|
self.plotItem.ctrl.xGridCheck.setChecked(True) |
|
1716 |
|
self.plotItem.ctrl.yGridCheck.setChecked(True) |
|
1717 |
|
|
|
1718 |
|
# delete build-in Transforms (with Log_x and Log_y) options, |
|
1719 |
|
# they can cause uncachable exception (on any zero in data) and crash |
|
1720 |
|
self.plotItem.ctrlMenu.removeAction(self.plotItem.ctrlMenu.actions()[0]) |
|
1721 |
|
|
|
1722 |
|
#č já se bojím. radší to uložím |
|
1723 |
|
self.custom_menu = self.plotItem.vb.menu.addMenu("TRI options") |
|
1724 |
|
|
|
1725 |
|
self.legend_chk = QtGui.QAction("Legend", self.custom_menu) |
|
1726 |
|
self.legend_chk.setCheckable(True) |
|
1727 |
|
self.legend_chk.triggered.connect(lambda: self.legend.setVisible(self.legend_chk.isChecked())) |
|
1728 |
|
self.custom_menu.addAction(self.legend_chk) |
|
1729 |
|
# apply custom menu option |
|
1730 |
|
self.legend.setVisible(self.legend_chk.isChecked()) |
|
1731 |
|
|
|
1732 |
|
self.proxy_chk = QtGui.QAction("Proxy", self.custom_menu) |
|
1733 |
|
self.proxy_chk.setCheckable(True) |
|
1734 |
|
self.proxy_chk.triggered.connect(self.redraw) |
|
1735 |
|
self.custom_menu.addAction(self.proxy_chk) |
|
1736 |
|
|
|
1737 |
|
self.log_x_chk = QtGui.QAction("Log X", self.custom_menu) |
|
1738 |
|
self.log_x_chk.setCheckable(True) |
|
1739 |
|
self.log_x_chk.triggered.connect(lambda: self.setLogMode(x=self.log_x_chk.isChecked())) |
|
1740 |
|
self.custom_menu.addAction(self.log_x_chk) |
|
1741 |
|
|
|
1742 |
|
self.log_y_chk = QtGui.QAction("Log Y", self.custom_menu) |
|
1743 |
|
self.log_y_chk.setCheckable(True) |
|
1744 |
|
self.log_y_chk.setChecked(True) |
|
1745 |
|
self.log_y_chk.triggered.connect(self.replot) |
|
1746 |
|
self.custom_menu.addAction(self.log_y_chk) |
|
1747 |
|
|
|
1748 |
|
self.reaction = QtGui.QAction("Redraw", self.custom_menu) |
|
1749 |
|
self.reaction.triggered.connect(self.redraw) |
|
1750 |
|
self.custom_menu.addAction(self.reaction) |
|
1751 |
|
|
|
1752 |
|
self.laction = QtGui.QAction("Show labels", self.custom_menu) |
|
1753 |
|
self.laction.triggered.connect(self.show_labels) |
|
1754 |
|
self.custom_menu.addAction(self.laction) |
|
1755 |
|
|
|
1756 |
|
self.excelaction = QtGui.QAction("Export to Excel", self.custom_menu) |
|
1757 |
|
self.excelaction.triggered.connect(self.export_to_excel) |
|
1758 |
|
self.custom_menu.addAction(self.excelaction) |
|
1759 |
|
|
|
1760 |
|
|
|
1761 |
|
def export_to_excel(self): |
|
1762 |
|
#č já bych nechtěl, aby mně export najednou spadl |
|
1763 |
|
#č z jakéhokoliv důvodu |
|
1764 |
|
try: |
|
1765 |
|
proposal_filename = self.dice_box.guessbox.filename |
|
1766 |
|
if proposal_filename: |
|
1767 |
|
proposal_filename += '.xlsx' |
|
1768 |
|
else: |
|
1769 |
|
proposal_filename = self.dice_box.gm_signature + '.xlsx' |
|
1770 |
|
filename, *__ = pg.FileDialog.getSaveFileName(self, 'Export to Excel',\ |
|
1771 |
|
proposal_filename, initialFilter='*.xlsx') |
|
1772 |
|
self.df.to_excel(filename) |
|
1773 |
|
except BaseException as e: |
|
1774 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
1775 |
|
|
|
1776 |
|
def show_labels(self): |
|
1777 |
|
self.setLabel('left', "Probability measure") |
|
1778 |
|
self.setLabel('bottom', "Number of simulations") |
|
1779 |
|
|
|
1780 |
|
|
|
1781 |
|
|
|
1782 |
|
# self.legend.addItem(self.pen_success, "success domain estimation") |
|
1783 |
|
# self.legend.addItem(self.pen_outside, "out of sampling domain estimation") |
|
1784 |
|
# self.legend.addItem(self.pen_mix, "mixed simplices measure") |
|
1785 |
|
# self.legend.addItem(self.pen_f, "failure domain estimation") |
|
1786 |
|
|
|
1787 |
|
def setup(self, *args, **kwargs): |
|
1788 |
|
self.clear() |
|
1789 |
|
self.setBackground('w') |
|
1790 |
|
x = y = () # zde jen vytvoříme kostru, nakrmime daty v .redraw() |
|
1791 |
|
|
|
1792 |
|
#xkcd_green = (167, 255, 181) # xkcd:light seafoam green #a7ffb5 |
|
1793 |
|
green = (0, 255, 38, 96) |
|
1794 |
|
#xkcd_red = (253, 193, 197) # xkcd: pale rose (#fdc1c5) |
|
1795 |
|
red = (253, 0, 17, 96) |
|
1796 |
|
#xkcd_cream = (255, 243, 154) # let's try xkcd: dark cream (#fff39a) |
|
1797 |
|
cream = (255, 221, 0, 96) |
|
1798 |
|
grey = (196, 196, 196, 96) |
|
1799 |
|
|
|
1800 |
|
self.pen_f = self.plot(x, y, brush=red)#, name="failure domain estimation") |
|
1801 |
|
self.pen_f.setZValue(-100) |
|
1802 |
|
|
|
1803 |
|
self.pen_success = self.plot(x, y, brush=green) #, name="success domain estimation") |
|
1804 |
|
self.pen_success.setZValue(-100) |
|
1805 |
|
|
|
1806 |
|
self.pen_outmix = self.plot(x, y) |
|
1807 |
|
|
|
1808 |
|
self.fill_mix = pg.FillBetweenItem(self.pen_f, self.pen_outmix) |
|
1809 |
|
#self.fill_mix.setData(name="mixed simplices measure") |
|
1810 |
|
self.fill_mix.setBrush(cream) |
|
1811 |
|
self.fill_mix.setZValue(-100) |
|
1812 |
|
self.addItem(self.fill_mix) |
|
1813 |
|
|
|
1814 |
|
#self.pen_outside = self.plot(x, y) |
|
1815 |
|
self.fill_outside = pg.FillBetweenItem(self.pen_outmix, self.pen_success) |
|
1816 |
|
#self.fill_outside.setData(name="out of sampling domain estimation") |
|
1817 |
|
self.fill_outside.setBrush(grey) |
|
1818 |
|
self.fill_outside.setZValue(-100) |
|
1819 |
|
self.addItem(self.fill_outside) |
|
1820 |
|
|
|
1821 |
|
self.one_ruler = self.addLine(y=1, pen='k') |
|
1822 |
|
self.zero_ruler = self.addLine(y=0, pen='k') |
|
1823 |
|
|
|
1824 |
|
|
|
1825 |
|
try: |
|
1826 |
|
exact_name = self.dice_box.pf_exact_method |
|
1827 |
|
pen = pg.mkPen(color='b', width=1.5) # blue |
|
1828 |
|
self.pen_exact = self.addLine(y=self.dice_box.pf_exact, pen=pen, name=exact_name) |
|
1829 |
|
#č aby se nám něco zobrazovalo v legendu |
|
1830 |
|
self.pen_exact_PR = self.plot(x, y, pen=pen, name=exact_name) |
|
1831 |
|
except: |
|
1832 |
|
pass |
|
1833 |
|
|
|
1834 |
|
pen = pg.mkPen(color='m', width=2) |
|
1835 |
|
self.pen_vertex = self.plot(x, y, pen=pen, name="simple pf estimation") |
|
1836 |
|
pen = pg.mkPen(color='r', width=2) #(118, 187, 255) |
|
1837 |
|
self.pen_weighted_vertex = self.plot(x, y, pen=pen, name="weighted pf estimation") |
|
1838 |
|
|
|
1839 |
|
|
|
1840 |
|
|
|
1841 |
|
|
|
1842 |
|
|
|
1843 |
|
def replot(self, *args, **kwargs): |
|
1844 |
|
if self.log_y_chk.isChecked(): |
|
1845 |
|
self.one_ruler.hide() |
|
1846 |
|
try: |
|
1847 |
|
#č try nás nezáchraní protí odloženému spádnutí pyqtgraph |
|
1848 |
|
if self.dice_box.pf_exact > 0: |
|
1849 |
|
self.pen_exact.setPos(np.log10(self.dice_box.pf_exact)) |
|
1850 |
|
self.pen_exact.show() |
|
1851 |
|
else: |
|
1852 |
|
self.pen_exact.hide() |
|
1853 |
|
except: |
|
1854 |
|
pass |
|
1855 |
|
self.setLogMode(y=True) |
|
1856 |
|
#self.pen_f.setPen(pg.mkPen(color=(255, 0, 0), width=3)) #, style=QtCore.Qt.DashLine) |
|
1857 |
|
self.pen_f.setPen(None) |
|
1858 |
|
self.pen_f.setFillLevel(None) |
|
1859 |
|
self.pen_success.setFillLevel(0) |
|
1860 |
|
|
|
1861 |
|
else: |
|
1862 |
|
self.one_ruler.show() |
|
1863 |
|
try: |
|
1864 |
|
self.pen_exact.setPos(self.dice_box.pf_exact) |
|
1865 |
|
self.pen_exact.show() |
|
1866 |
|
except: |
|
1867 |
|
pass |
|
1868 |
|
self.setLogMode(y=False) |
|
1869 |
|
self.pen_f.setPen(None) |
|
1870 |
|
self.pen_f.setFillLevel(0) |
|
1871 |
|
self.pen_success.setFillLevel(1) |
|
1872 |
|
|
|
1873 |
|
self.redraw() |
|
1874 |
|
|
|
1875 |
|
|
|
1876 |
|
#č když se někde objeví nula se zapnutým LogModem - |
|
1877 |
|
#č qtpygraph hned spadne a není možne ten pad zachytit |
|
1878 |
|
def zerosafe(self, x, y, fallback_y=None): |
|
1879 |
|
if self.log_y_chk.isChecked(): |
|
1880 |
|
x = np.array(x) |
|
1881 |
|
y = np.array(y) |
|
1882 |
|
if fallback_y is None: |
|
1883 |
|
fallback_y = y |
|
1884 |
|
y = np.where(y > 0, y, fallback_y) |
|
1885 |
|
mask = y > 0 |
|
1886 |
|
return x[mask], y[mask] |
|
1887 |
|
else: |
|
1888 |
|
return x, y |
|
1889 |
|
|
|
1890 |
|
def proxy(self, nsim): |
|
1891 |
|
if self.proxy_chk.isChecked(): |
|
1892 |
|
proxy = self.dice_box.proxy |
|
1893 |
|
index = np.array(nsim)-1 |
|
1894 |
|
#č indexy musíme o jedničku změnšit |
|
1895 |
|
#č výsledek nikoliv. Takže v cajku. |
|
1896 |
|
return np.cumsum(~proxy)[index] |
|
1897 |
|
else: |
|
1898 |
|
return nsim |
|
1899 |
|
|
|
1900 |
|
|
|
1901 |
|
def _pens_data_update(self): |
|
1902 |
|
df = self.df |
|
1903 |
|
nsim = df.nsim.to_numpy() |
|
1904 |
|
if self.proxy_chk.isChecked(): |
|
1905 |
|
x = self.proxy(nsim) |
|
1906 |
|
df.insert(loc=0, column='nsim (proxy)', value=x) |
|
1907 |
|
else: |
|
1908 |
|
x = nsim |
|
1909 |
|
# (in case of LogPlot) fallback values also used |
|
1910 |
|
success_values = df.failure+df.mix+df.out |
|
1911 |
|
outmix_values = df.failure+df.mix |
|
1912 |
|
failure_fallback = np.where(outmix_values > 0, outmix_values, success_values) |
|
1913 |
|
self.pen_f.setData(*self.zerosafe(x, df.failure, failure_fallback)) |
|
1914 |
|
self.pen_outmix.setData(*self.zerosafe(x, outmix_values, success_values)) |
|
1915 |
|
self.pen_success.setData(*self.zerosafe(x, success_values)) |
|
1916 |
|
|
|
1917 |
|
|
|
1918 |
|
def redraw(self): |
|
1919 |
|
xmin = np.inf |
|
1920 |
|
xmax = -np.inf |
|
1921 |
|
tri_estimation = dict() |
|
1922 |
|
try: # тут всё что угодно может пойти не так |
|
1923 |
|
# kruci, ještě navic i generovať pokažde znovu... |
|
1924 |
|
|
|
1925 |
|
# new-style: šecko leží dohromady a každý si z toho |
|
1926 |
|
# bere co chce a jak chce |
|
1927 |
|
# ne že by to bylo nějak šetrný |
|
1928 |
|
# estimation je slovníkem |
|
1929 |
|
for estimation in self.dice_box.estimations: |
|
1930 |
|
# nsim musí mäť každej odhad |
|
1931 |
|
# pokud nemá - je třeba jej prostě opravit |
|
1932 |
|
nsim = estimation['nsim'] |
|
1933 |
|
try: |
|
1934 |
|
tri_estimation[nsim] = estimation['TRI_estimation'] |
|
1935 |
|
if nsim > xmax: |
|
1936 |
|
xmax = nsim |
|
1937 |
|
if nsim < xmin: |
|
1938 |
|
xmin = nsim |
|
1939 |
|
|
|
1940 |
|
except KeyError as e: |
|
1941 |
|
pass #print(self.__class__.__name__ + ":", repr(e)) |
|
1942 |
|
|
|
1943 |
|
#č neotravuj uživatele chybovejma hlaškama |
|
1944 |
|
if tri_estimation: |
|
1945 |
|
# it can be effectively done with pandas |
|
1946 |
|
self.df = df = pd.DataFrame(tuple(tri_estimation.values())) |
|
1947 |
|
# -1 = 'out', 0=success, 1=failure, 2=mix |
|
1948 |
|
df.rename(columns={-1:'out', 0:'success', 1:'failure', 2:'mix'}, inplace=True) |
|
1949 |
|
df.insert(loc=0, column='nsim', value=tuple(tri_estimation.keys()), allow_duplicates=False) |
|
1950 |
|
df.sort_values('nsim', inplace=True) |
|
1951 |
|
|
|
1952 |
|
self._pens_data_update() |
|
1953 |
|
|
|
1954 |
|
nsim, y = get_estimation_data(self.dice_box.estimations, 'vertex_estimation') |
|
1955 |
|
df['vertex_estimation'] = y #č spolehám na konzistenci odhadů (ne úplně) |
|
1956 |
|
self.pen_vertex.setData(*self.zerosafe(self.proxy(nsim), y)) |
|
1957 |
|
|
|
1958 |
|
nsim, y = get_estimation_data(self.dice_box.estimations, 'weighted_vertex_estimation') |
|
1959 |
|
df['weighted_vertex_estimation'] = y #č spolehám na konzistenci odhadů (ne úplně) |
|
1960 |
|
self.pen_weighted_vertex.setData(*self.zerosafe(self.proxy(nsim), y)) |
|
1961 |
|
|
|
1962 |
|
|
|
1963 |
|
except BaseException as e: |
|
1964 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
1965 |
|
|
|
1966 |
|
|
|
1967 |
|
# DEPRECATED |
|
1968 |
|
class TriEstimationGraph(SimpleSimplexEstimationGraph): |
|
1969 |
|
def __init__(self, dice_box, tri_estimation_name='TRI_overall_estimations', stream=None, parent=None, *args, **kwargs): |
|
1970 |
|
self.tri_estimation_name = tri_estimation_name |
|
1971 |
|
super().__init__(dice_box, stream, parent, *args, **kwargs) |
|
1972 |
|
|
|
1973 |
|
|
|
1974 |
|
|
|
1975 |
|
def redraw(self): |
|
1976 |
|
try: # тут всё что угодно может пойти не так |
|
1977 |
|
data = self.dice_box.guessbox.estimations[self.tri_estimation_name] |
|
1978 |
|
nsim, tri_data = data |
|
1979 |
|
# it can be effectively done with pandas |
|
1980 |
|
self.df = df = pd.DataFrame(tri_data) |
|
1981 |
|
# -1 = 'out', 0=success, 1=failure, 2=mix |
|
1982 |
|
df.rename(columns={-1:'out', 0:'success', 1:'failure', 2:'mix'}, inplace=True) |
|
1983 |
|
df.insert(loc=0, column='nsim', value=nsim) |
|
1984 |
|
|
|
1985 |
|
# Update the data |
|
1986 |
|
self._pens_data_update() |
|
1987 |
|
|
|
1988 |
|
if 'vertex_estimation' in self.dice_box.guessbox.estimations: |
|
1989 |
|
data = self.dice_box.guessbox.estimations['vertex_estimation'] |
|
1990 |
|
nsim, y = data |
|
1991 |
|
# Update the data |
|
1992 |
|
#č spolehám na konzistenci blackboxu, ne však úplně |
|
1993 |
|
self.pen_vertex.setData(*self.zerosafe(self.proxy(nsim), np.array(y))) |
|
1994 |
|
df['vertex_estimation'] = y |
|
1995 |
|
|
|
1996 |
|
if 'weighted_vertex_estimation' in self.dice_box.guessbox.estimations: |
|
1997 |
|
data = self.dice_box.guessbox.estimations['weighted_vertex_estimation'] |
|
1998 |
|
nsim, y = data |
|
1999 |
|
# Update the data |
|
2000 |
|
#č spolehám na konzistenci blackboxu, ne však úplně |
|
2001 |
|
self.pen_weighted_vertex.setData(*self.zerosafe(self.proxy(nsim), np.array(y))) |
|
2002 |
|
df['weighted_vertex_estimation'] = y |
|
2003 |
|
|
|
2004 |
|
|
|
2005 |
|
# BaseException |
|
2006 |
|
except BaseException as e: |
|
2007 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
2008 |
|
|
|
2009 |
|
|
|
2010 |
|
|
|
2011 |
|
|
|
2012 |
|
|
|
2013 |
|
|
|
2014 |
|
|
|
2015 |
|
class VoronoiEstimationGraph(pg.PlotWidget): |
|
2016 |
|
def __init__(self, black_box, samplebox_item, parent=None, *args, **kwargs): |
|
2017 |
|
super().__init__(parent) |
|
2018 |
|
self.sb_item = samplebox_item |
|
2019 |
|
self.sb_item.box_runned.connect(self.redraw) |
|
2020 |
|
self.sb_item.estimation_added.connect(self.redraw) |
|
2021 |
|
|
|
2022 |
|
self.black_box = black_box |
|
2023 |
|
self.setBackground('w') |
|
2024 |
|
|
|
2025 |
|
|
|
2026 |
|
self.reaction = QtGui.QAction("Redraw", self.plotItem.ctrlMenu) |
|
2027 |
|
self.reaction.triggered.connect(self.redraw) |
|
2028 |
|
self.plotItem.ctrlMenu.insertAction(self.plotItem.ctrlMenu.actions()[0], self.reaction) |
|
2029 |
|
|
|
2030 |
|
|
|
2031 |
|
|
|
2032 |
|
# implicitně Y je v logaritmickem měřítku |
|
2033 |
|
self.setLogMode(False, True) |
|
2034 |
|
|
|
2035 |
|
x = y = () # zde jen vytvoříme kostru, nakrmíme daty v .redraw() |
|
2036 |
|
|
|
2037 |
|
|
|
2038 |
|
# nechapu, proč těm Itemům ríkám "propíska" |
|
2039 |
|
# propíska? Их есть у нас! |
|
2040 |
|
|
|
2041 |
|
self.Voronoi_2_point_upper_bound = self.plot(x, y, pen='y') |
|
2042 |
|
self.Voronoi_2_point_lower_bound = self.plot(x, y, pen='y') |
|
2043 |
|
|
|
2044 |
|
fill_color = (255, 243, 154) # let's try xkcd: dark cream (#fff39a) |
|
2045 |
|
self.fill = pg.FillBetweenItem(self.Voronoi_2_point_upper_bound, self.Voronoi_2_point_lower_bound, fill_color) |
|
2046 |
|
self.addItem(self.fill) |
|
2047 |
|
|
|
2048 |
|
self.Voronoi_2_point_failure_rate = self.plot(x, y, pen=(195,46,212)) |
|
2049 |
|
self.Voronoi_2_point_pure_failure_rate = self.plot(x, y, pen='m') |
|
2050 |
|
self.Voronoi_failure_rate = self.plot(x, y, pen='r') |
|
2051 |
|
|
|
2052 |
|
self.pen_exact = self.plot(x, y, pen='b') # blue |
|
2053 |
|
self.pen_one = self.plot(x, y, pen='k') # black |
|
2054 |
|
|
|
2055 |
|
self.redraw() |
|
2056 |
|
|
|
2057 |
|
|
|
2058 |
|
def redraw(self): |
|
2059 |
|
# kruci, ještě navic i generovať pokažde znovu... |
|
2060 |
|
metrics = {'Voronoi_2_point_upper_bound':{},\ |
|
2061 |
|
'Voronoi_2_point_lower_bound':{},\ |
|
2062 |
|
'Voronoi_2_point_failure_rate':{},\ |
|
2063 |
|
'Voronoi_2_point_pure_failure_rate':{},\ |
|
2064 |
|
'Voronoi_failure_rate':{},} |
|
2065 |
|
xmin = np.inf |
|
2066 |
|
xmax = -np.inf |
|
2067 |
|
try: # тут всё что угодно может пойти не так |
|
2068 |
|
# new-style: šecko leží dohromady a každý z toho |
|
2069 |
|
# bere co chce a jak chce |
|
2070 |
|
# ne že by to bylo nějak šetrný |
|
2071 |
|
# estimation je slovníkem |
|
2072 |
|
for estimation in self.black_box.estimations: |
|
2073 |
|
# nsim musí mäť každej odhad |
|
2074 |
|
# pokud nemá - je třeba jej prostě opravit |
|
2075 |
|
nsim = estimation['nsim'] |
|
2076 |
|
|
|
2077 |
|
|
|
2078 |
|
for metric, metric_dict in metrics.items(): |
|
2079 |
|
try: |
|
2080 |
|
if estimation[metric] > 0: |
|
2081 |
|
metric_dict[nsim] = estimation[metric] |
|
2082 |
|
if nsim > xmax: |
|
2083 |
|
xmax = nsim |
|
2084 |
|
if nsim < xmin: |
|
2085 |
|
xmin = nsim |
|
2086 |
|
except KeyError as e: |
|
2087 |
|
pass #print(self.__class__.__name__ + ":", repr(e)) |
|
2088 |
|
|
|
2089 |
|
for metric, metric_dict in metrics.items(): |
|
2090 |
|
pen = getattr(self, metric) |
|
2091 |
|
# nikdo neslibil, že budou v pořadí |
|
2092 |
|
x = np.sort(tuple(metric_dict.keys())) |
|
2093 |
|
y = np.array(tuple(metric_dict.values()))[np.argsort(tuple(metric_dict.keys()))] |
|
2094 |
|
pen.setData(x, y) |
|
2095 |
|
|
|
2096 |
|
if (xmax - xmin) > 0: |
|
2097 |
|
self.pen_one.setData((xmin,xmax), (1, 1)) |
|
2098 |
|
if hasattr(self.black_box, 'pf_exact'): |
|
2099 |
|
# poslední. I když spadne, tak už nikomu moc nevadí |
|
2100 |
|
self.pen_exact.setData((xmin,xmax), (self.black_box.pf_exact, self.black_box.pf_exact)) |
|
2101 |
|
|
|
2102 |
|
except BaseException as e: |
|
2103 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
2104 |
|
|
|
2105 |
|
|
|
2106 |
|
# pen_f.opts['logMode'] |
|
2107 |
|
# pen_outside.setLogMode(False, False) |
|
2108 |
|
#setLogMode(False, False) |
|
2109 |
|
#f = pg.FillBetweenItem(curves[i], curves[i+1], brushes[i]) |
|
2110 |
|
#win.addItem(f) |
|
2111 |
|
|
|
2112 |
|
|
|
2113 |
|
|
|
2114 |
|
|
|
2115 |
|
|
|
2116 |
|
|
|
2117 |
|
|
|
2118 |
|
""" |
|
2119 |
|
============= |
|
2120 |
|
Эскерон виӝет |
|
2121 |
|
Widgety odhadů |
|
2122 |
|
Estimation widgets |
|
2123 |
|
=================== |
|
2124 |
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
2125 |
|
""" |
|
2126 |
|
|
|
2127 |
|
class FastSimplexEstimationWidget(QtGui.QSplitter): |
|
2128 |
|
# I'd like to get access to the samplebox stuff via the container's reference, |
|
2129 |
|
def __init__(self, samplebox_item, parent=None, *args, **kwargs): |
|
2130 |
|
super().__init__(parent) |
|
2131 |
|
# sb like samplebox, of course |
|
2132 |
|
self.sb_item = samplebox_item |
|
2133 |
|
|
|
2134 |
|
self.sb_item.box_runned.connect(self.on_box_run) |
|
2135 |
|
self.sb_item.slice_changed.connect(self.self_clear) |
|
2136 |
|
self.sb_item.space_changed.connect(self.on_space_changed) |
|
2137 |
|
self.sb_item.redraw_called.connect(self.redraw) |
|
2138 |
|
#☺ na internetu všichni tak dělaj |
|
2139 |
|
self.setup() |
|
2140 |
|
|
|
2141 |
|
def setup(self): |
|
2142 |
|
self.setOrientation(QtCore.Qt.Vertical) |
|
2143 |
|
self.layout = pg.LayoutWidget(self) |
|
2144 |
|
params = list() |
|
2145 |
|
params.append({'name': 'method', 'type': 'list', \ |
|
2146 |
|
'values': ['fast_sampling', 'full_sampling',\ |
|
2147 |
|
'fast_cubature', 'full_cubature'], 'value': 'fast_sampling'}) |
|
2148 |
|
params.append({'name': 'model space', 'type': 'list', \ |
|
2149 |
|
'values': self.sb_item.spaces, 'value': 'Rn'}) |
|
2150 |
|
params.append({'name': 'sampling space', 'type': 'list',\ |
|
2151 |
|
'values': ['None'] + self.sb_item.spaces, 'value': 'None'}) |
|
2152 |
|
params.append({'name': 'weighting space', 'type': 'list',\ |
|
2153 |
|
'values': ['None'] + self.sb_item.spaces, 'value': 'None'}) |
|
2154 |
|
designs = ['None'] |
|
2155 |
|
if 'designs' in self.sb_item.kwargs: |
|
2156 |
|
designs.extend(self.sb_item.kwargs['designs'].keys()) |
|
2157 |
|
params.append({'name': 'design', 'type': 'list', \ |
|
2158 |
|
'values': designs, 'value': 'None'}) |
|
2159 |
|
params.append({'name': 'outside budget', 'type': 'int', \ |
|
2160 |
|
'limits': (1, float('inf')), 'value': 1000, 'default': 1000}) |
|
2161 |
|
params.append({'name': 'nodes per simplex', 'type': 'int', \ |
|
2162 |
|
'limits': (1, float('inf')), 'value': 100, 'default': 100}) |
|
2163 |
|
|
|
2164 |
|
if 'schemes' in self.sb_item.kwargs: |
|
2165 |
|
schemes = list(self.sb_item.kwargs['schemes'].keys()) |
|
2166 |
|
else: |
|
2167 |
|
schemes = ['None'] |
|
2168 |
|
|
|
2169 |
|
params.append({'name': 'scheme', 'type': 'list', \ |
|
2170 |
|
'values': schemes, 'value': schemes[0]}) |
|
2171 |
|
params.append({'name': 'node (pixel) size', 'type': 'float',\ |
|
2172 |
|
'limits': (0, float('inf')), 'value': 3.5, 'default': self.sb_item.px_size}) |
|
2173 |
|
xkcd_green = (167, 255, 181, 255) # xkcd:light seafoam green #a7ffb5 |
|
2174 |
|
xkcd_red = (253, 193, 197, 255) # xkcd: pale rose (#fdc1c5) |
|
2175 |
|
xkcd_cream = (255, 243, 154, 255) # let's try xkcd: dark cream (#fff39a) |
|
2176 |
|
params.append({'name': 'failure', 'type': 'colormap', \ |
|
2177 |
|
'value': pg.colormap.ColorMap((0,1), [xkcd_red, xkcd_red])}) |
|
2178 |
|
params.append({'name': 'success', 'type': 'colormap', \ |
|
2179 |
|
'value': pg.colormap.ColorMap((0,1), [xkcd_green, xkcd_green])}) |
|
2180 |
|
params.append({'name': 'mix', 'type': 'colormap', \ |
|
2181 |
|
'value': pg.colormap.ColorMap((0,1), [xkcd_cream, xkcd_cream])}) |
|
2182 |
|
params.append({'name': 'Run with the box', 'type': 'bool', 'value': False }) # 'tip': "This is a checkbox" |
|
2183 |
|
|
|
2184 |
|
### Create tree of Parameter objects |
|
2185 |
|
self.param = pg.parametertree.Parameter.create(name='params', type='group', children=params) |
|
2186 |
|
# I don't know why that signals do not work for me |
|
2187 |
|
# Only sigTreeStateChanged works, but I don't want to struggle with it |
|
2188 |
|
# May be I'll report the issue |
|
2189 |
|
#self.param.sigValueChanged.connect(self.param_changed) |
|
2190 |
|
#self.param.sigValueChanging.connect(self.param_changing) |
|
2191 |
|
|
|
2192 |
|
### Create ParameterTree widget |
|
2193 |
|
self.ptree = pg.parametertree.ParameterTree() |
|
2194 |
|
self.ptree.setParameters(self.param, showTop=False) |
|
2195 |
|
|
|
2196 |
|
self.layout.addWidget(self.ptree, row=0, col=0, colspan=4) |
|
2197 |
|
|
|
2198 |
|
|
|
2199 |
|
|
|
2200 |
|
self.btn0 = QtGui.QPushButton('(no graphics)') # 'estimate \n (no graphics)' |
|
2201 |
|
self.layout.addWidget(self.btn0, row=1, col=0) |
|
2202 |
|
self.btn0.clicked.connect(self.run_stm) |
|
2203 |
|
|
|
2204 |
|
self.btn = QtGui.QPushButton('estimate') |
|
2205 |
|
self.layout.addWidget(self.btn, row=1, col=1) |
|
2206 |
|
self.btn.clicked.connect(self.go_stm) |
|
2207 |
|
|
|
2208 |
|
self.btn2 = QtGui.QPushButton('redraw') |
|
2209 |
|
self.layout.addWidget(self.btn2, row=1, col=2) |
|
2210 |
|
self.btn2.clicked.connect(self.recolor) |
|
2211 |
|
|
|
2212 |
|
self.btn3 = QtGui.QPushButton('hide') |
|
2213 |
|
self.layout.addWidget(self.btn3, row=1, col=3) |
|
2214 |
|
self.btn3.clicked.connect(self.hide) |
|
2215 |
|
|
|
2216 |
|
self.addWidget(self.layout) |
|
2217 |
|
|
|
2218 |
|
self.table = pg.TableWidget(sortable=False) |
|
2219 |
|
self.addWidget(self.table) |
|
2220 |
|
|
|
2221 |
|
|
|
2222 |
|
|
|
2223 |
|
# pro začatek postačí |
|
2224 |
|
# triangulaci kreslím jen v 2D |
|
2225 |
|
self.triangulation = [] |
|
2226 |
|
self.simplices = [] |
|
2227 |
|
self.max_simplices = {'success':0, 'failure':0, 'mix':0} |
|
2228 |
|
|
|
2229 |
|
|
|
2230 |
|
def hide(self): |
|
2231 |
|
#č nejdřív triangulace |
|
2232 |
|
for tri_bound, plot_item in self.triangulation: |
|
2233 |
|
plot_item.hide() |
|
2234 |
|
# keep the GUI responsive :) |
|
2235 |
|
#self.sb_item.app.processEvents() |
|
2236 |
|
|
|
2237 |
|
#č teď tečičky |
|
2238 |
|
for nodes, plot_item, cell_stats in self.simplices: |
|
2239 |
|
plot_item.hide() |
|
2240 |
|
# keep the GUI responsive :) |
|
2241 |
|
#self.sb_item.app.processEvents() |
|
2242 |
|
|
|
2243 |
|
|
|
2244 |
|
def recolor(self): |
|
2245 |
|
with pg.BusyCursor(): |
|
2246 |
|
# keep the GUI responsive :) |
|
2247 |
|
self.sb_item.app.processEvents() |
|
2248 |
|
#č nejdřív triangulace |
|
2249 |
|
for tri_bound, plot_item in self.triangulation: |
|
2250 |
|
plot_item.show() |
|
2251 |
|
|
|
2252 |
|
|
|
2253 |
|
#č teď tečičky |
|
2254 |
|
for nodes, plot_item, cell_stats in self.simplices: |
|
2255 |
|
event = cell_stats['event'] |
|
2256 |
|
if event in self.max_simplices: |
|
2257 |
|
cell_probability = cell_stats['cell_probability'] |
|
2258 |
|
cm = self.param.getValues()[event][0] #č očekávám tam kolor mapu |
|
2259 |
|
blue_intensity = cell_probability / self.max_simplices[event] |
|
2260 |
|
color = cm.mapToQColor(blue_intensity) |
|
2261 |
|
else: # outside |
|
2262 |
|
color = 0.6 |
|
2263 |
|
#symbolSize = np.sqrt(nodes.w / min(nodes.w)) # not bad |
|
2264 |
|
size = self.param.getValues()['node (pixel) size'][0] |
|
2265 |
|
plot_item.setSymbolBrush(color) |
|
2266 |
|
plot_item.setSymbolSize(size) |
|
2267 |
|
plot_item.show() |
|
2268 |
|
# keep the GUI responsive :) |
|
2269 |
|
#self.sb_item.app.processEvents() |
|
2270 |
|
|
|
2271 |
|
|
|
2272 |
|
|
|
2273 |
|
def on_space_changed(self, *args, **kwargs): |
|
2274 |
|
#with pg.BusyCursor(): |
|
2275 |
|
#self.hide() |
|
2276 |
|
# keep the GUI responsive :) |
|
2277 |
|
#self.sb_item.app.processEvents() |
|
2278 |
|
#č nejdřív triangulace |
|
2279 |
|
for tri_bound, plot_item in self.triangulation: |
|
2280 |
|
pos = getattr(tri_bound, self.sb_item.space) |
|
2281 |
|
plot_item.setData(pos) |
|
2282 |
|
#plot_item.show() |
|
2283 |
|
# keep the GUI responsive :) |
|
2284 |
|
#self.sb_item.app.processEvents() |
|
2285 |
|
|
|
2286 |
|
#č teď tečičky |
|
2287 |
|
for nodes, plot_item, cell_stats in self.simplices: |
|
2288 |
|
pos = getattr(nodes, self.sb_item.space)[:,:2] |
|
2289 |
|
plot_item.setData(pos) |
|
2290 |
|
#plot_item.show() |
|
2291 |
|
# keep the GUI responsive :) |
|
2292 |
|
#self.sb_item.app.processEvents() |
|
2293 |
|
|
|
2294 |
|
|
|
2295 |
|
#č ten hlavní modul se dočkal na překopávání |
|
2296 |
|
def on_box_run(self, *args, **kwargs): |
|
2297 |
|
#č je třeba zkontrolovat autorun a restartovat výpočet |
|
2298 |
|
if self.param.getValues()['Run with the box'][0]: |
|
2299 |
|
self.run_stm() |
|
2300 |
|
#else: |
|
2301 |
|
# self.self_clear() |
|
2302 |
|
|
|
2303 |
|
|
|
2304 |
|
def redraw(self, *args, **kwargs): |
|
2305 |
|
self.triangulation.clear() |
|
2306 |
|
self.simplices.clear() |
|
2307 |
|
self.max_simplices['success'] = 0 |
|
2308 |
|
self.max_simplices['failure'] = 0 |
|
2309 |
|
self.max_simplices['mix'] = 0 |
|
2310 |
|
|
|
2311 |
|
|
|
2312 |
|
def self_clear(self): |
|
2313 |
|
# odebereme prvky-propísky z hlavního plotu |
|
2314 |
|
for tri_bound, plot_item in self.triangulation: |
|
2315 |
|
self.sb_item.central_widget.removeItem(plot_item) |
|
2316 |
|
for nodes, plot_item, cell_stats in self.simplices: |
|
2317 |
|
self.sb_item.central_widget.removeItem(plot_item) |
|
2318 |
|
|
|
2319 |
|
self.redraw() |
|
2320 |
|
|
|
2321 |
|
def go_stm(self): self.start_stm(callback=self.callback) |
|
2322 |
|
def run_stm(self): self.start_stm() |
|
2323 |
|
def start_stm(self, callback=None): |
|
2324 |
|
# indikace |
|
2325 |
|
#self.setDisabled(True) |
|
2326 |
|
with pg.BusyCursor(): |
|
2327 |
|
nsim = self.sb_item.slider.value() |
|
2328 |
|
sample_box = self.sb_item.sample_box[:nsim] |
|
2329 |
|
#☺ Krucinal, kdo ten OrderedDict vymyslel? |
|
2330 |
|
params = self.param.getValues() |
|
2331 |
|
model_space = params['model space'][0] |
|
2332 |
|
sampling_space = params['sampling space'][0] |
|
2333 |
|
if sampling_space == 'None': |
|
2334 |
|
sampling_space = None |
|
2335 |
|
weighting_space = params['weighting space'][0] |
|
2336 |
|
if weighting_space == 'None': |
|
2337 |
|
weighting_space = None |
|
2338 |
|
outside_budget = params['outside budget'][0] |
|
2339 |
|
simplex_budget = params['nodes per simplex'][0] |
|
2340 |
|
|
|
2341 |
|
design = params['design'][0] |
|
2342 |
|
if design == 'None': |
|
2343 |
|
design = None |
|
2344 |
|
else: |
|
2345 |
|
design = self.sb_item.kwargs['designs'][design] |
|
2346 |
|
|
|
2347 |
|
scheme = params['scheme'][0] |
|
2348 |
|
if scheme == 'None': |
|
2349 |
|
scheme = None |
|
2350 |
|
else: |
|
2351 |
|
scheme = self.sb_item.kwargs['schemes'][scheme] |
|
2352 |
|
|
|
2353 |
|
#č je třeba skrýt prvky z minula |
|
2354 |
|
self.self_clear() |
|
2355 |
|
|
|
2356 |
|
try: |
|
2357 |
|
|
|
2358 |
|
if params['method'][0] == 'fast_cubature': |
|
2359 |
|
method = stm.fast_simplex_cubature |
|
2360 |
|
data = method(sample_box, scheme, model_space=model_space,\ |
|
2361 |
|
sampling_space=sampling_space,\ |
|
2362 |
|
weighting_space=weighting_space,\ |
|
2363 |
|
outside_budget=outside_budget, \ |
|
2364 |
|
callback=callback, design=design) |
|
2365 |
|
|
|
2366 |
|
elif params['method'][0] == 'full_cubature': |
|
2367 |
|
method = stm.full_simplex_cubature |
|
2368 |
|
data = method(sample_box, scheme, model_space=model_space,\ |
|
2369 |
|
weighting_space=weighting_space,\ |
|
2370 |
|
callback=callback) |
|
2371 |
|
else: |
|
2372 |
|
if params['method'][0] == 'full_sampling': |
|
2373 |
|
method = stm.full_simplex_estimation |
|
2374 |
|
else: # 'fast_sampling' |
|
2375 |
|
method = stm.fast_simplex_estimation |
|
2376 |
|
data = method(sample_box, model_space=model_space,\ |
|
2377 |
|
sampling_space=sampling_space, \ |
|
2378 |
|
weighting_space=weighting_space,\ |
|
2379 |
|
outside_budget=outside_budget, \ |
|
2380 |
|
simplex_budget=simplex_budget,\ |
|
2381 |
|
callback=callback, design=design) |
|
2382 |
|
|
|
2383 |
|
if hasattr(self.sb_item.sample_box, 'estimations'): |
|
2384 |
|
self.sb_item.sample_box.estimations.append(data) |
|
2385 |
|
self.sb_item.estimation_added.emit() |
|
2386 |
|
self.table.setData(data) |
|
2387 |
|
except BaseException as e: |
|
2388 |
|
msg = "error during estimation " |
|
2389 |
|
error_msg = self.__class__.__name__ + ": " + msg + repr(e) |
|
2390 |
|
print(error_msg) |
|
2391 |
|
# indikace |
|
2392 |
|
#self.setEnabled(True) |
|
2393 |
|
|
|
2394 |
|
|
|
2395 |
|
|
|
2396 |
|
|
|
2397 |
|
|
|
2398 |
|
def callback(self, sx=None, nodes=None, cell_stats=None, simplex=None, *args, **kwargs): |
|
2399 |
|
plot_widget = self.sb_item.central_widget |
|
2400 |
|
#č stm trianguľaciju pokažde provadí znovu, proto skoro nemá cenu drbat se s její znovupoužitím |
|
2401 |
|
if (simplex is not None) and (simplex.nvar==2): |
|
2402 |
|
|
|
2403 |
|
ns = 100 |
|
2404 |
|
# take coordinates in the space, where triangulation has been performed |
|
2405 |
|
simplex_tri = getattr(simplex, sx.tri_space) |
|
2406 |
|
x_tri_1 = np.linspace(simplex_tri[0,0], simplex_tri[1,0], ns, endpoint=False) |
|
2407 |
|
y_tri_1 = np.linspace(simplex_tri[0,1], simplex_tri[1,1], ns, endpoint=False) |
|
2408 |
|
x_tri_2 = np.linspace(simplex_tri[1,0], simplex_tri[2,0], ns, endpoint=False) |
|
2409 |
|
y_tri_2 = np.linspace(simplex_tri[1,1], simplex_tri[2,1], ns, endpoint=False) |
|
2410 |
|
x_tri_3 = np.linspace(simplex_tri[2,0], simplex_tri[0,0], ns, endpoint=True) |
|
2411 |
|
y_tri_3 = np.linspace(simplex_tri[2,1], simplex_tri[0,1], ns, endpoint=True) |
|
2412 |
|
|
|
2413 |
|
tri_bound_tri = np.concatenate(((x_tri_1, y_tri_1), (x_tri_2, y_tri_2),\ |
|
2414 |
|
(x_tri_3, y_tri_3)), axis=1).T |
|
2415 |
|
# vytvořme sample |
|
2416 |
|
tri_bound = self.sb_item.sample_box.f_model.new_sample(tri_bound_tri, space=sx.tri_space) |
|
2417 |
|
|
|
2418 |
|
# draw |
|
2419 |
|
pos = getattr(tri_bound, self.sb_item.space) |
|
2420 |
|
plot_item = plot_widget.plot(pos, pen='k') |
|
2421 |
|
plot_item.setZValue(50) |
|
2422 |
|
|
|
2423 |
|
# uložíme data |
|
2424 |
|
self.triangulation.append((tri_bound, plot_item)) |
|
2425 |
|
|
|
2426 |
|
#plot_item.show() |
|
2427 |
|
|
|
2428 |
|
|
|
2429 |
|
# |
|
2430 |
|
# tečičky |
|
2431 |
|
# |
|
2432 |
|
pos = getattr(nodes, self.sb_item.space)[:,:2] |
|
2433 |
|
event = cell_stats['event'] |
|
2434 |
|
cell_probability = cell_stats['cell_probability'] |
|
2435 |
|
if event in self.max_simplices: |
|
2436 |
|
cm = self.param.getValues()[event][0] #č očekávám tam kolor mapu |
|
2437 |
|
|
|
2438 |
|
#č chcu ještě na konci prekreslit s různejma barvičkama, podle obsahu pravděpodobnosti |
|
2439 |
|
# zkontrolujeme probability |
|
2440 |
|
if self.max_simplices[event] < cell_probability: |
|
2441 |
|
self.max_simplices[event] = cell_probability |
|
2442 |
|
# a hned všecko dotyčné přebarvíme podle obsahu pravděpodobnosti |
|
2443 |
|
for self_simplex in self.simplices: |
|
2444 |
|
if event == self_simplex[2]['event']: |
|
2445 |
|
# zde cell_probability se rovná self.p_cell_max[event] |
|
2446 |
|
# ale bacha! Nesplet se jinde! |
|
2447 |
|
#č nechť zůstane starý nazev |
|
2448 |
|
blue_intensity = self_simplex[2]['cell_probability'] / cell_probability |
|
2449 |
|
color = cm.mapToQColor(blue_intensity) |
|
2450 |
|
self_simplex[1].setSymbolBrush(color) |
|
2451 |
|
|
|
2452 |
|
|
|
2453 |
|
intensity = cell_probability / self.max_simplices[event] |
|
2454 |
|
#č tam prostě MUSÍ být tuple |
|
2455 |
|
color = cm.mapToQColor(intensity) |
|
2456 |
|
|
|
2457 |
|
|
|
2458 |
|
else: # outside |
|
2459 |
|
color = 0.6 |
|
2460 |
|
|
|
2461 |
|
|
|
2462 |
|
# draw tečičky |
|
2463 |
|
# |
|
2464 |
|
|
|
2465 |
|
#symbolSize = np.sqrt(nodes.w / min(nodes.w)) # not bad |
|
2466 |
|
size = self.param.getValues()['node (pixel) size'][0] |
|
2467 |
|
#brush = pg.mkBrush(color) |
|
2468 |
|
plot_item = plot_widget.plot(pos, pen=None, symbol='o', symbolPen=pg.mkPen(None), symbolBrush=color,\ |
|
2469 |
|
symbolSize=size, name='IS localized nodes') |
|
2470 |
|
plot_item.setZValue(40) |
|
2471 |
|
|
|
2472 |
|
# uložíme data |
|
2473 |
|
self.simplices.append((nodes, plot_item, cell_stats)) |
|
2474 |
|
|
|
2475 |
|
|
|
2476 |
|
# keep the GUI responsive :) |
|
2477 |
|
self.sb_item.app.processEvents() |
|
2478 |
|
|
|
2479 |
|
|
|
2480 |
|
|
|
2481 |
|
|
|
2482 |
|
|
|
2483 |
|
|
|
2484 |
|
class VoronoiEstimationWidget(QtGui.QSplitter): |
|
2485 |
|
""" |
|
2486 |
|
addLabel(text=' ', row=None, col=None, rowspan=1, colspan=1, **kargs) |
|
2487 |
|
""" |
|
2488 |
|
# I'd like to get access to the samplebox stuff via the container's reference, |
|
2489 |
|
# INHERETED by gl_plot |
|
2490 |
|
def __init__(self, samplebox_item, parent=None, *args, **kwargs): |
|
2491 |
|
super().__init__(parent) |
|
2492 |
|
# sb like samplebox, of course |
|
2493 |
|
self.sb_item = samplebox_item |
|
2494 |
|
|
|
2495 |
|
self.sb_item.box_runned.connect(self.on_box_run) |
|
2496 |
|
self.sb_item.slice_changed.connect(self.self_clear) |
|
2497 |
|
self.sb_item.space_changed.connect(self.on_space_changed) |
|
2498 |
|
self.sb_item.redraw_called.connect(self.redraw) |
|
2499 |
|
#☺ na internetu všichni tak dělaj |
|
2500 |
|
self.setup() |
|
2501 |
|
|
|
2502 |
|
# INHERETED by gl_plot |
|
2503 |
|
def setup(self): |
|
2504 |
|
self.setOrientation(QtCore.Qt.Vertical) |
|
2505 |
|
self.layout = pg.LayoutWidget(self) |
|
2506 |
|
# model_space='Rn', sampling_space=None, p_norm=1, budget=20000 |
|
2507 |
|
params = [{'name': 'method', 'type': 'list', 'values': ['Voronoi_tesselation','Voronoi_2_point_estimation'], 'value': 'Voronoi_2_point_estimation'}] |
|
2508 |
|
params.append({'name': 'model space', 'type': 'list', 'values': self.sb_item.spaces, 'value': 'Rn'}) |
|
2509 |
|
params.append({'name': 'sampling space', 'type': 'list', 'values': ['None'] + self.sb_item.spaces, 'value': 'None'}) |
|
2510 |
|
params.append({'name': 'p-norm', 'type': 'float', 'limits': (1, float('inf')), 'value': 1, 'default': np.inf}) |
|
2511 |
|
params.append({'name': 'budget', 'type': 'float', 'limits': (1, float('inf')), 'value': 20000, 'default': 20000}) |
|
2512 |
|
self.coloring_modes = ['simple_coloring', 'cell_probability_coloring','node_pf_coloring'] |
|
2513 |
|
params.append({'name': 'coloring', 'type': 'list', 'values': self.coloring_modes, 'value': self.coloring_modes[1]}) |
|
2514 |
|
params.append({'name': 'node (pixel) size', 'type': 'float', 'limits': (0, float('inf')), 'value': 3, 'default': 1}) |
|
2515 |
|
params.append({'name': 'Run with the box', 'type': 'bool', 'value': False }) # 'tip': "This is a checkbox" |
|
2516 |
|
|
|
2517 |
|
### Create tree of Parameter objects |
|
2518 |
|
self.param = pg.parametertree.Parameter.create(name='params', type='group', children=params) |
|
2519 |
|
# I don't know why that signals do not work for me |
|
2520 |
|
# Only sigTreeStateChanged works, but I don't want to struggle with it |
|
2521 |
|
# May be I'll report the issue |
|
2522 |
|
#self.param.sigValueChanged.connect(self.param_changed) |
|
2523 |
|
#self.param.sigValueChanging.connect(self.param_changing) |
|
2524 |
|
|
|
2525 |
|
### Create ParameterTree widget |
|
2526 |
|
self.ptree = pg.parametertree.ParameterTree() |
|
2527 |
|
self.ptree.setParameters(self.param, showTop=False) |
|
2528 |
|
|
|
2529 |
|
self.layout.addWidget(self.ptree, row=0, col=0, colspan=3) |
|
2530 |
|
|
|
2531 |
|
|
|
2532 |
|
self.btn = QtGui.QPushButton('estimate') |
|
2533 |
|
self.layout.addWidget(self.btn, row=1, col=0) |
|
2534 |
|
self.btn.clicked.connect(self.run_stm) |
|
2535 |
|
|
|
2536 |
|
self.btn2 = QtGui.QPushButton('redraw') |
|
2537 |
|
self.layout.addWidget(self.btn2, row=1, col=1) |
|
2538 |
|
self.btn2.clicked.connect(self.recolor) |
|
2539 |
|
|
|
2540 |
|
self.btn3 = QtGui.QPushButton('hide') |
|
2541 |
|
self.layout.addWidget(self.btn3, row=1, col=2) |
|
2542 |
|
self.btn3.clicked.connect(self.hide) |
|
2543 |
|
|
|
2544 |
|
self.addWidget(self.layout) |
|
2545 |
|
|
|
2546 |
|
self.table = pg.TableWidget(sortable=False) |
|
2547 |
|
self.addWidget(self.table) |
|
2548 |
|
|
|
2549 |
|
# pro začatek postačí |
|
2550 |
|
self.cells = [] |
|
2551 |
|
# probability of the biggest cell |
|
2552 |
|
# used for coloring |
|
2553 |
|
self.p_cell_max = {'success':0, 'failure':0} |
|
2554 |
|
|
|
2555 |
|
|
|
2556 |
|
# INHERETED by gl_plot |
|
2557 |
|
def on_box_run(self, *args, **kwargs): |
|
2558 |
|
# je třeba zkontrolovat autorun a restartovat výpočet |
|
2559 |
|
if self.param.getValues()['Run with the box'][0]: |
|
2560 |
|
self.run_stm() |
|
2561 |
|
#else: |
|
2562 |
|
#self.self_clear() |
|
2563 |
|
|
|
2564 |
|
# INHERETED by gl_plot |
|
2565 |
|
def hide(self): |
|
2566 |
|
for nodes, plot_item, cell_stats in self.cells: |
|
2567 |
|
plot_item.hide() |
|
2568 |
|
# keep the GUI responsive :) |
|
2569 |
|
#self.sb_item.app.processEvents() |
|
2570 |
|
|
|
2571 |
|
# INHERETED by gl_plot |
|
2572 |
|
def redraw(self, *args, **kwargs): |
|
2573 |
|
self.cells.clear() |
|
2574 |
|
self.p_cell_max['success'] = 0 |
|
2575 |
|
self.p_cell_max['failure'] = 0 |
|
2576 |
|
|
|
2577 |
|
## I'll rename after main widget refactoring |
|
2578 |
|
# refactoring already done, why I should rename? |
|
2579 |
|
# INHERETED by gl_plot |
|
2580 |
|
def recolor(self): |
|
2581 |
|
# indikace |
|
2582 |
|
#self.setDisabled(True) |
|
2583 |
|
with pg.BusyCursor(): |
|
2584 |
|
# Krucinal, kdo ten OrderedDict vymyslel? |
|
2585 |
|
params = self.param.getValues() |
|
2586 |
|
coloring = params['coloring'][0] |
|
2587 |
|
|
|
2588 |
|
# přebarvíme nějak tečičky |
|
2589 |
|
# callback vybírám ze svého kódu, ten musí bejt v pořádku |
|
2590 |
|
# ne že by to bylo dokonalé bezpečný, |
|
2591 |
|
# ale na lokálním počítači asi to není až tak zavadný |
|
2592 |
|
coloring_function = getattr(self, coloring) |
|
2593 |
|
|
|
2594 |
|
# hura! Jedeme! |
|
2595 |
|
coloring_function() |
|
2596 |
|
|
|
2597 |
|
|
|
2598 |
|
# indikace |
|
2599 |
|
#self.setEnabled(True) |
|
2600 |
|
|
|
2601 |
|
|
|
2602 |
|
def on_space_changed(self, *args, **kwargs): |
|
2603 |
|
# teď tečičky |
|
2604 |
|
for nodes, plot_item, cell_stats in self.cells: |
|
2605 |
|
pos = getattr(nodes, self.sb_item.space)[:,:2] |
|
2606 |
|
plot_item.setData(pos) |
|
2607 |
|
|
|
2608 |
|
|
|
2609 |
|
# INHERETED by gl_plot |
|
2610 |
|
def self_clear(self): |
|
2611 |
|
# odebereme prvky-propísky z hlavního plotu |
|
2612 |
|
for nodes, plot_item, cell_stats in self.cells: |
|
2613 |
|
self.sb_item.central_widget.removeItem(plot_item) |
|
2614 |
|
|
|
2615 |
|
self.redraw() |
|
2616 |
|
|
|
2617 |
|
|
|
2618 |
|
|
|
2619 |
|
# INHERETED by gl_plot |
|
2620 |
|
def run_stm(self): |
|
2621 |
|
# indikace |
|
2622 |
|
#self.setDisabled(True) |
|
2623 |
|
with pg.BusyCursor(): |
|
2624 |
|
nsim = self.sb_item.slider.value() |
|
2625 |
|
sample_box = self.sb_item.sample_box[:nsim] |
|
2626 |
|
# Krucinal, kdo ten OrderedDict vymyslel? |
|
2627 |
|
params = self.param.getValues() |
|
2628 |
|
method = params['method'][0] |
|
2629 |
|
model_space = params['model space'][0] |
|
2630 |
|
sampling_space = params['sampling space'][0] |
|
2631 |
|
if sampling_space == 'None': |
|
2632 |
|
sampling_space = None |
|
2633 |
|
p_norm = params['p-norm'][0] |
|
2634 |
|
budget = params['budget'][0] |
|
2635 |
|
coloring = params['coloring'][0] |
|
2636 |
|
|
|
2637 |
|
# je třeba skrýt prvky z minula |
|
2638 |
|
self.self_clear() |
|
2639 |
|
|
|
2640 |
|
|
|
2641 |
|
# přebarvíme nějak tečičky |
|
2642 |
|
# callback vybírám ze svého kódu, ten musí bejt v pořádku |
|
2643 |
|
# ne že by to bylo dokonalé bezpečný, |
|
2644 |
|
# ale na lokálním počítači asi to není až tak zavadný |
|
2645 |
|
coloring_function = getattr(self, coloring) |
|
2646 |
|
|
|
2647 |
|
|
|
2648 |
|
try: |
|
2649 |
|
stm_function = getattr(stm, method) |
|
2650 |
|
# model_space='Rn', sampling_space=None, p_norm=1, budget=20000 |
|
2651 |
|
data = stm_function(sample_box, model_space=model_space, sampling_space=sampling_space,\ |
|
2652 |
|
p_norm=p_norm, budget=budget, callback=coloring_function) |
|
2653 |
|
|
|
2654 |
|
if hasattr(self.sb_item.sample_box, 'estimations'): |
|
2655 |
|
self.sb_item.sample_box.estimations.append(data) |
|
2656 |
|
self.sb_item.estimation_added.emit() |
|
2657 |
|
self.table.setData(data) |
|
2658 |
|
|
|
2659 |
|
except BaseException as e: |
|
2660 |
|
msg = "error during estimation " |
|
2661 |
|
error_msg = self.__class__.__name__ + ": " + msg + repr(e) |
|
2662 |
|
print(error_msg) |
|
2663 |
|
|
|
2664 |
|
|
|
2665 |
|
|
|
2666 |
|
# indikace |
|
2667 |
|
#self.setEnabled(True) |
|
2668 |
|
|
|
2669 |
|
|
|
2670 |
|
|
|
2671 |
|
|
|
2672 |
|
|
|
2673 |
|
def node_pf_coloring(self, estimation=None, nodes=None, cell_stats=None, out_nodes=None, *args, **kwargs): |
|
2674 |
|
""" |
|
2675 |
|
if nodes and cell_stats provided we will add them to self.cells |
|
2676 |
|
otherwise function redraw items in self.cells |
|
2677 |
|
""" |
|
2678 |
|
plot_widget = self.sb_item.central_widget |
|
2679 |
|
if nodes is None: |
|
2680 |
|
for cell in self.cells: |
|
2681 |
|
nodes, plot_item, cell_stats = cell |
|
2682 |
|
# odebereme prvky z hlavního plotu |
|
2683 |
|
# zde je třeba prvky vygenerovat znovu |
|
2684 |
|
# protože nikdo neví co tam bylo před tím |
|
2685 |
|
# takhle, nechce se mi drbat s tím, co tam bylo před tím |
|
2686 |
|
# komplikace ze strany pyqtgraph |
|
2687 |
|
plot_widget.removeItem(plot_item) |
|
2688 |
|
|
|
2689 |
|
# bacha, potřebuji prvek uložiť in-place |
|
2690 |
|
cell[1] = self.node_pf_scatter_plot(nodes, cell_stats) |
|
2691 |
|
|
|
2692 |
|
# máme nodes, tj. jedeme poprvé |
|
2693 |
|
else: |
|
2694 |
|
plot_item = self.node_pf_scatter_plot(nodes, cell_stats) |
|
2695 |
|
|
|
2696 |
|
# uložíme data |
|
2697 |
|
self.cells.append([nodes, plot_item, cell_stats]) |
|
2698 |
|
|
|
2699 |
|
# keep the GUI responsive :) |
|
2700 |
|
self.sb_item.app.processEvents() |
|
2701 |
|
|
|
2702 |
|
|
|
2703 |
|
|
|
2704 |
|
|
|
2705 |
|
def node_pf_scatter_plot(self, nodes, cell_stats): |
|
2706 |
|
pos = getattr(nodes, self.sb_item.space)[:,:2] |
|
2707 |
|
symbol_size = self.param.getValues()['node (pixel) size'][0] |
|
2708 |
|
plot_widget = self.sb_item.central_widget |
|
2709 |
|
# zas, нет ножек - нет мультиков |
|
2710 |
|
# node_pf_estimations nemusejí bejt |
|
2711 |
|
try: |
|
2712 |
|
# zkusmě pro jednoduchost |
|
2713 |
|
# čírou RGB hračku |
|
2714 |
|
npf = nodes.node_pf_estimations |
|
2715 |
|
colors = tuple((npf[i]*255, (1-npf[i])*255, 0) for i in range(len(pos))) |
|
2716 |
|
# sice dokumentace popisuje víc možností zadávání, |
|
2717 |
|
# ale toto zadávání různejch barviček je pro mě jediné fungujicí. Drbal jsem s tím do znechucení |
|
2718 |
|
# je v podstatě opsané z příkladu |
|
2719 |
|
# rovnou přes PlotDataItem mi nefunguje |
|
2720 |
|
# žádné jiné možností zadávání já jsem v zdrojacích |
|
2721 |
|
# pyqtgraph (konkretně v PlotDataItem a v ScatterPlotItem) neuviděl |
|
2722 |
|
# tuším, že je to neunosně drahý |
|
2723 |
|
list_of_dicts = list({'pos': pos[i], 'size':symbol_size, 'pen': colors[i], 'brush':colors[i], 'symbol':'o'} for i in range(len(pos))) |
|
2724 |
|
plot_item = pg.ScatterPlotItem(list_of_dicts) |
|
2725 |
|
plot_widget.addItem(plot_item) |
|
2726 |
|
return plot_item |
|
2727 |
|
|
|
2728 |
|
except BaseException as e: |
|
2729 |
|
msg = "node_pf_coloring has problems " |
|
2730 |
|
error_msg = self.__class__.__name__ + ": " + msg + repr(e) |
|
2731 |
|
print(error_msg) |
|
2732 |
|
#self.error.emit(error_msg) |
|
2733 |
|
# simple coloring |
|
2734 |
|
event = cell_stats['event'] |
|
2735 |
|
color = self.get_color(event) |
|
2736 |
|
#symbolSize = np.sqrt(nodes.w / min(nodes.w)) # not bad |
|
2737 |
|
return plot_widget.plot(pos, pen=None, symbol='o', symbolPen=color, symbolBrush=color, symbolSize=symbol_size, name='IS localized nodes') |
|
2738 |
|
|
|
2739 |
|
|
|
2740 |
|
|
|
2741 |
|
|
|
2742 |
|
|
|
2743 |
|
def simple_coloring(self, nodes=None, cell_stats=None, *args, **kwargs): |
|
2744 |
|
""" |
|
2745 |
|
if nodes and cell_stats provided we will add them to self.cells |
|
2746 |
|
otherwise function redraw items in self.cells |
|
2747 |
|
""" |
|
2748 |
|
symbol_size = self.param.getValues()['node (pixel) size'][0] |
|
2749 |
|
plot_widget = self.sb_item.central_widget |
|
2750 |
|
if nodes is None: |
|
2751 |
|
for cell in self.cells: |
|
2752 |
|
nodes, plot_item, cell_stats = cell |
|
2753 |
|
# odebereme prvky z hlavního plotu |
|
2754 |
|
# zde je třeba prvky vygenerovat znovu |
|
2755 |
|
# protože nikdo neví co tam bylo před tím |
|
2756 |
|
# takhle, nechce se mi drbat s tím, co tam bylo před tím |
|
2757 |
|
# komplikace ze strany pyqtgraph |
|
2758 |
|
plot_widget.removeItem(plot_item) |
|
2759 |
|
|
|
2760 |
|
# draw |
|
2761 |
|
pos = getattr(nodes, self.sb_item.space)[:,:2] |
|
2762 |
|
#x, y = (*getattr(nodes, self.sb_item.space).T,) |
|
2763 |
|
|
|
2764 |
|
event = cell_stats['event'] |
|
2765 |
|
color = self.get_color(event) |
|
2766 |
|
#symbolSize = np.sqrt(nodes.w / min(nodes.w)) # not bad |
|
2767 |
|
# bacha, potřebuji prvek uložiť in-place |
|
2768 |
|
cell[1] = plot_widget.plot(pos, pen=None, symbol='o',\ |
|
2769 |
|
symbolPen=color, symbolBrush=color, symbolSize=symbol_size, name='IS localized nodes') |
|
2770 |
|
|
|
2771 |
|
# máme nodes, tj. jedeme poprvé |
|
2772 |
|
else: |
|
2773 |
|
# draw tečičky |
|
2774 |
|
# |
|
2775 |
|
pos = getattr(nodes, self.sb_item.space)[:,:2] |
|
2776 |
|
|
|
2777 |
|
event = cell_stats['event'] |
|
2778 |
|
color = self.get_color(event) |
|
2779 |
|
#symbolSize = np.sqrt(nodes.w / min(nodes.w)) # not bad |
|
2780 |
|
plot_item = plot_widget.plot(pos, pen=None, symbol='o',\ |
|
2781 |
|
symbolPen=color, symbolBrush=color, symbolSize=symbol_size, name='IS localized nodes') |
|
2782 |
|
|
|
2783 |
|
# uložíme data |
|
2784 |
|
self.cells.append([nodes, plot_item, cell_stats]) |
|
2785 |
|
|
|
2786 |
|
# keep the GUI responsive :) |
|
2787 |
|
self.sb_item.app.processEvents() |
|
2788 |
|
|
|
2789 |
|
|
|
2790 |
|
|
|
2791 |
|
def cell_probability_coloring(self, nodes=None, cell_stats=None, *args, **kwargs): |
|
2792 |
|
""" |
|
2793 |
|
if nodes and cell_stats provided we will add them to self.cells |
|
2794 |
|
otherwise function redraw items in self.cells |
|
2795 |
|
""" |
|
2796 |
|
symbol_size = self.param.getValues()['node (pixel) size'][0] |
|
2797 |
|
plot_widget = self.sb_item.central_widget |
|
2798 |
|
if nodes is None: |
|
2799 |
|
# odebereme prvky z hlavního plotu |
|
2800 |
|
# zde je třeba prvky vygenerovat znovu |
|
2801 |
|
# protože nikdo neví co tam bylo před tím |
|
2802 |
|
# takhle, nechce se mi drbat s tím, co tam bylo před tím |
|
2803 |
|
# komplikace ze strany pyqtgraph |
|
2804 |
|
for nodes, plot_item, cell_stats in self.cells: |
|
2805 |
|
plot_widget.removeItem(plot_item) |
|
2806 |
|
|
|
2807 |
|
event = cell_stats['event'] |
|
2808 |
|
cell_probability = cell_stats['cell_probability'] |
|
2809 |
|
if self.p_cell_max[event] < cell_probability: |
|
2810 |
|
self.p_cell_max[event] = cell_probability |
|
2811 |
|
|
|
2812 |
|
# přebarvíme tečičky podle obsahu pravděpodobnosti |
|
2813 |
|
for cell in self.cells: |
|
2814 |
|
nodes, plot_item, cell_stats = cell |
|
2815 |
|
# draw |
|
2816 |
|
pos = getattr(nodes, self.sb_item.space)[:,:2] |
|
2817 |
|
#x, y = (*getattr(nodes, self.sb_item.space).T,) |
|
2818 |
|
|
|
2819 |
|
event = cell_stats['event'] |
|
2820 |
|
cell_probability = cell_stats['cell_probability'] |
|
2821 |
|
# bez modrého - maximální intenzita |
|
2822 |
|
blue_intensity = 1 - cell_probability / self.p_cell_max[event] |
|
2823 |
|
color = self.get_color(event, blue_intensity) |
|
2824 |
|
#symbolSize = np.sqrt(nodes.w / min(nodes.w)) # not bad |
|
2825 |
|
# bacha, potřebuji prvek vložit zpätky |
|
2826 |
|
cell[1] = plot_widget.plot(pos, pen=None, symbol='o',\ |
|
2827 |
|
symbolPen=color, symbolBrush=color, symbolSize=symbol_size, name='IS localized nodes') |
|
2828 |
|
|
|
2829 |
|
# máme nodes, tj. jedeme poprvé |
|
2830 |
|
else: |
|
2831 |
|
event = cell_stats['event'] |
|
2832 |
|
cell_probability = cell_stats['cell_probability'] |
|
2833 |
|
# zkontrolujeme probability |
|
2834 |
|
if self.p_cell_max[event] < cell_probability: |
|
2835 |
|
self.p_cell_max[event] = cell_probability |
|
2836 |
|
# a hned všecko dotyčné přebarvíme podle obsahu pravděpodobnosti |
|
2837 |
|
for cell in self.cells: |
|
2838 |
|
if event == cell[2]['event']: |
|
2839 |
|
# bez modrého - maximální intenzita |
|
2840 |
|
# zde cell_probability se rovná self.p_cell_max[event] |
|
2841 |
|
# ale bacha! Nesplet se jinde! |
|
2842 |
|
blue_intensity = 1 - cell[2]['cell_probability'] / cell_probability |
|
2843 |
|
color = self.get_color(event, blue_intensity) |
|
2844 |
|
# bacha, potřebuji prvek vložit zpätky |
|
2845 |
|
cell[1].setSymbolBrush(color) |
|
2846 |
|
cell[1].setSymbolPen(color) |
|
2847 |
|
|
|
2848 |
|
# bez modrého - maximální intenzita |
|
2849 |
|
blue_intensity = 1 - cell_probability / self.p_cell_max[event] |
|
2850 |
|
color = self.get_color(event, blue_intensity) |
|
2851 |
|
|
|
2852 |
|
|
|
2853 |
|
# draw tečičky |
|
2854 |
|
# |
|
2855 |
|
pos = getattr(nodes, self.sb_item.space)[:,:2] |
|
2856 |
|
#x, y = (*getattr(nodes, self.sb_item.space).T,) |
|
2857 |
|
|
|
2858 |
|
#symbolSize = np.sqrt(nodes.w / min(nodes.w)) # not bad |
|
2859 |
|
plot_item = plot_widget.plot(pos, pen=None, symbol='o',\ |
|
2860 |
|
symbolPen=color, symbolBrush=color, symbolSize=symbol_size, name='IS localized nodes') |
|
2861 |
|
|
|
2862 |
|
# uložíme data |
|
2863 |
|
self.cells.append([nodes, plot_item, cell_stats]) |
|
2864 |
|
|
|
2865 |
|
# keep the GUI responsive :) |
|
2866 |
|
self.sb_item.app.processEvents() |
|
2867 |
|
|
|
2868 |
|
|
|
2869 |
|
|
|
2870 |
|
def get_color(self, event, blue_intensity=None): |
|
2871 |
|
""" |
|
2872 |
|
get color for 'simple_coloring' or 'cell_probability_coloring' |
|
2873 |
|
""" |
|
2874 |
|
# generally |
|
2875 |
|
if event == 'success': |
|
2876 |
|
color = [167, 255, 181]# xkcd:light seafoam green #a7ffb5 |
|
2877 |
|
elif event == 'failure': |
|
2878 |
|
color = [253, 193, 197] # xkcd: pale rose (#fdc1c5) |
|
2879 |
|
# já vím, že Voronoi nemá 'mix', эн но юа |
|
2880 |
|
else:# 'mix' |
|
2881 |
|
color = [255, 243, 154] # let's try xkcd: dark cream (#fff39a) |
|
2882 |
|
|
|
2883 |
|
if blue_intensity is not None: |
|
2884 |
|
# let's play with blue a little bit |
|
2885 |
|
# chcu mít korektní výstup |
|
2886 |
|
# aspoň v něčem chcu být jistý |
|
2887 |
|
if blue_intensity > 1: |
|
2888 |
|
color[2] = 255 |
|
2889 |
|
elif blue_intensity < 0: |
|
2890 |
|
color[2] = 0 |
|
2891 |
|
else: |
|
2892 |
|
# pyqtgraph žere barvy i s čarkou |
|
2893 |
|
# ale my je mu davat nebudeme |
|
2894 |
|
color[2] = int(blue_intensity*255) |
|
2895 |
|
|
|
2896 |
|
return tuple(color) |
|
2897 |
|
|
|
2898 |
|
|
|
2899 |
|
|
|
2900 |
|
|
|
2901 |
|
|
|
2902 |
|
|
|
2903 |
|
|
|
2904 |
|
|
|
2905 |
|
class HullEstimationWidget(pg.LayoutWidget): |
|
2906 |
|
# I'd like to get access to the samplebox stuff via the container's reference, |
|
2907 |
|
def __init__(self, samplebox_item, parent=None, *args, **kwargs): |
|
2908 |
|
super().__init__(parent) |
|
2909 |
|
# sb like samplebox, of course |
|
2910 |
|
self.sb_item = samplebox_item |
|
2911 |
|
|
|
2912 |
|
self.giracle = Giracles(w=samplebox_item, autoredraw=False, nrod=200) |
|
2913 |
|
#č Ghull se zkomplikoval. Musím integraci řešit zvlášť |
|
2914 |
|
# Serie for integration nodes |
|
2915 |
|
self.serint = Series(w=samplebox_item, autoredraw=False) |
|
2916 |
|
#ё hyperplanes? Кого ты обманываешь, Alexi? |
|
2917 |
|
#č tak. už je to equation_planes :) |
|
2918 |
|
self.equation_planes = InfiniteLines(w=samplebox_item, autoredraw=False) |
|
2919 |
|
|
|
2920 |
|
# signals handling: |
|
2921 |
|
# box_runned - handled by .on_box_run() method |
|
2922 |
|
# space_changed - handled automatically by smart items |
|
2923 |
|
# slice_changed - setted up clear() on smart items |
|
2924 |
|
# redraw_called - handled automatically by smart items |
|
2925 |
|
# estimation_added - class does not handle the signal |
|
2926 |
|
# nor emits the signal itself |
|
2927 |
|
# (as does not save estimations anywhere for now) |
|
2928 |
|
|
|
2929 |
|
# todo: design estimation record |
|
2930 |
|
|
|
2931 |
|
self.sb_item.box_runned.connect(self.on_box_run) |
|
2932 |
|
#č Alexi, ten signal může té funkce posilát bůhví co navíc. |
|
2933 |
|
#č (ano. clear() nebere žádné argumenty, takže v cajku) |
|
2934 |
|
self.sb_item.slice_changed.connect(self.giracle.clear) |
|
2935 |
|
self.sb_item.slice_changed.connect(self.equation_planes.clear) |
|
2936 |
|
#č ty naše chytré prvky giracle a equation_planes |
|
2937 |
|
#č hlídají space_changed a redraw_called sami. |
|
2938 |
|
|
|
2939 |
|
self.schemes = dict() |
|
2940 |
|
self.ndim = self.sb_item.sample_box.nvar |
|
2941 |
|
#☺ na internetu všichni tak dělaj |
|
2942 |
|
self.setup() |
|
2943 |
|
|
|
2944 |
|
def setup(self): |
|
2945 |
|
#č já teďkom dědím ne QSplitter, ale LayoutWidget |
|
2946 |
|
#оӵ Кужым кариськы, Олёш! |
|
2947 |
|
|
|
2948 |
|
#č zkusíme nový (pro WellMet) UI, uživatelské rozhraní |
|
2949 |
|
#оӵ кнопка вылын |
|
2950 |
|
#self.layout = self.addLayout(row=0, col=0) |
|
2951 |
|
#self.tool_layout = QtGui.QHBoxLayout() |
|
2952 |
|
#self.layout.addLayout(self.tool_layout, 0, 0) |
|
2953 |
|
#self.addWidget(self.layout, row=0, col=0) |
|
2954 |
|
|
|
2955 |
|
#č toolbar je obecně super věc, ale mě zlobí umístění v layoutu |
|
2956 |
|
self.toolbar = QtGui.QToolBar(self) |
|
2957 |
|
#č jmenovitě, roztažení mě nefunguje vůbec |
|
2958 |
|
#size_policy = self.toolbar.sizePolicy() |
|
2959 |
|
#size_policy.setHorizontalPolicy(QtGui.QSizePolicy.Expanding) |
|
2960 |
|
#self.toolbar.setSizePolicy(size_policy) |
|
2961 |
|
|
|
2962 |
|
#č draw_convex_hull ja navržena tak, aby brala jíž hotový hull |
|
2963 |
|
# if self.ndim == 2: |
|
2964 |
|
# action = self.toolbar.addAction("draw convex hull", self.draw_convex_hull) |
|
2965 |
|
# btn = self.toolbar.widgetForAction(action) |
|
2966 |
|
# btn.setAutoRaise(False) |
|
2967 |
|
|
|
2968 |
|
action = self.toolbar.addAction("shell out!", self.get_shell_estimation) |
|
2969 |
|
btn = self.toolbar.widgetForAction(action) |
|
2970 |
|
btn.setAutoRaise(False) |
|
2971 |
|
btn.setToolTip("Creates Ghull object") |
|
2972 |
|
#btn.setSizePolicy(size_policy) |
|
2973 |
|
|
|
2974 |
|
action = self.toolbar.addAction("integrate", self.integrate) |
|
2975 |
|
btn = self.toolbar.widgetForAction(action) |
|
2976 |
|
btn.setAutoRaise(False) |
|
2977 |
|
btn.setToolTip("Only uses Ghull object created before") |
|
2978 |
|
#btn.setSizePolicy(size_policy) |
|
2979 |
|
|
|
2980 |
|
action = self.toolbar.addAction("shot!", self.shot) |
|
2981 |
|
btn = self.toolbar.widgetForAction(action) |
|
2982 |
|
btn.setAutoRaise(False) |
|
2983 |
|
|
|
2984 |
|
action = self.toolbar.addAction("fire!", self.fire) |
|
2985 |
|
btn = self.toolbar.widgetForAction(action) |
|
2986 |
|
btn.setAutoRaise(False) |
|
2987 |
|
#btn.setSizePolicy(size_policy) |
|
2988 |
|
|
|
2989 |
|
action = self.toolbar.addAction("boom!", self.boom) |
|
2990 |
|
btn = self.toolbar.widgetForAction(action) |
|
2991 |
|
btn.setAutoRaise(False) |
|
2992 |
|
|
|
2993 |
|
action = self.toolbar.addAction("hide", self.hide) |
|
2994 |
|
btn = self.toolbar.widgetForAction(action) |
|
2995 |
|
btn.setAutoRaise(False) |
|
2996 |
|
#btn.setSizePolicy(size_policy) |
|
2997 |
|
|
|
2998 |
|
action = self.toolbar.addAction("show", self.show) |
|
2999 |
|
btn = self.toolbar.widgetForAction(action) |
|
3000 |
|
btn.setAutoRaise(False) |
|
3001 |
|
|
|
3002 |
|
action = self.toolbar.addAction("clear", self.clear) |
|
3003 |
|
btn = self.toolbar.widgetForAction(action) |
|
3004 |
|
btn.setAutoRaise(False) |
|
3005 |
|
|
|
3006 |
|
#self.tool_layout.addWidget(self.toolbar) |
|
3007 |
|
self.addWidget(self.toolbar, row=0, col=0) |
|
3008 |
|
|
|
3009 |
|
|
|
3010 |
|
#оӵ остальной (люкет) уллапала |
|
3011 |
|
|
|
3012 |
|
### Create ParameterTree widget |
|
3013 |
|
self.ptree = pg.parametertree.ParameterTree() |
|
3014 |
|
self._set_param() |
|
3015 |
|
self.ptree.setParameters(self.param, showTop=False) |
|
3016 |
|
|
|
3017 |
|
self.splitter = QtGui.QSplitter(self) |
|
3018 |
|
self.splitter.setOrientation(QtCore.Qt.Vertical) |
|
3019 |
|
self.splitter.addWidget(self.ptree) |
|
3020 |
|
|
|
3021 |
|
self.table = pg.TableWidget(sortable=False) |
|
3022 |
|
self.splitter.addWidget(self.table) |
|
3023 |
|
|
|
3024 |
|
#self.addWidget(self.splitter, row=1, col=0, colspan=5) |
|
3025 |
|
self.addWidget(self.splitter, row=1, col=0) |
|
3026 |
|
|
|
3027 |
|
def hide(self): |
|
3028 |
|
self.serint.hide() |
|
3029 |
|
self.giracle.hide() |
|
3030 |
|
self.equation_planes.hide() |
|
3031 |
|
|
|
3032 |
|
def show(self): |
|
3033 |
|
self.serint.show() |
|
3034 |
|
self.giracle.show() |
|
3035 |
|
self.equation_planes.show() |
|
3036 |
|
|
|
3037 |
|
def clear(self): |
|
3038 |
|
self.serint.clear() |
|
3039 |
|
self.giracle.clear() |
|
3040 |
|
self.equation_planes.clear() |
|
3041 |
|
|
|
3042 |
|
#оӵ DirectHull понна гинэ |
|
3043 |
|
#č pouze pro DirectHull |
|
3044 |
|
def get_scheme(self): |
|
3045 |
|
scheme = self.param.getValues()['scheme'][0] |
|
3046 |
|
if scheme == 'random': |
|
3047 |
|
ndir = self.param.getValues()['ndir'][0] |
|
3048 |
|
return sball.get_random_directions(ndir, self.ndim) |
|
3049 |
|
elif scheme in self.schemes: |
|
3050 |
|
return self.schemes[scheme].points |
|
3051 |
|
else: |
|
3052 |
|
Scheme = getattr(quadpy.un, scheme) |
|
3053 |
|
self.schemes[scheme] = Scheme(self.ndim) |
|
3054 |
|
return self.schemes[scheme].points |
|
3055 |
|
|
|
3056 |
|
|
|
3057 |
|
def _set_param(self): |
|
3058 |
|
params = list() |
|
3059 |
|
params.append({'name': 'method', 'type': 'list', 'value': 'DirectHull', \ |
|
3060 |
|
'values': ['SBall', 'BrickHull', 'DirectHull', 'CompleteHull', 'QHull']}) |
|
3061 |
|
params.append({'name': 'space', 'type': 'list', 'tip': "Not used for SBall", \ |
|
3062 |
|
'values': self.sb_item.spaces, 'value': 'G'}) |
|
3063 |
|
|
|
3064 |
|
schemes_list = schemes.un_spheres + ['random'] |
|
3065 |
|
params.append({'name': 'scheme', 'type': 'list', \ |
|
3066 |
|
'values': schemes_list, 'value': schemes_list[0], \ |
|
3067 |
|
'tip': "Used only for DirectHull and CompleteHull. Generation can take for a while"}) |
|
3068 |
|
params.append({'name': 'ndir', 'type': 'int', \ |
|
3069 |
|
'limits': (1, float('inf')), 'value': 1000, 'default': 1000, \ |
|
3070 |
|
'title': "number of random directions", \ |
|
3071 |
|
'tip': "Used only for random scheme in DirectHull (or CompleteHull)"}) |
|
3072 |
|
|
|
3073 |
|
params.append({'name': 'integrator', 'title': "integrator", 'type': 'list', \ |
|
3074 |
|
'values': ['MC', 'IS', '1DS'], 'value': '1DS' }) |
|
3075 |
|
params.append({'name': 'nonG_reduction', 'type': 'float', \ |
|
3076 |
|
'title': "non Gaussian reduction", \ |
|
3077 |
|
'limits': (0, 1), 'value': 0.9, 'default': 0.9,\ |
|
3078 |
|
'tip': "Applied when Ghull integrates non Gaussian convex hulls"}) |
|
3079 |
|
|
|
3080 |
|
params.append({'name': 'use_MC', 'title': "use MC", 'type': 'bool', 'value': False, \ |
|
3081 |
|
'tip': "Used for shot(), fire() and boom() functions"}) |
|
3082 |
|
|
|
3083 |
|
params.append({'name': 'budget', 'type': 'int', \ |
|
3084 |
|
'limits': (1, float('inf')), 'value': 1000, 'default': 1000,\ |
|
3085 |
|
'tip': "Number of simulations for optimal importance sampling"}) |
|
3086 |
|
|
|
3087 |
|
params.append({'name': 'node (pixel) size', 'type': 'float',\ |
|
3088 |
|
'limits': (0, float('inf')), 'value': 3.5, 'default': self.sb_item.px_size}) |
|
3089 |
|
#ё больше калорий богу калорий! |
|
3090 |
|
params.append({'name': 'r', 'type': 'color', 'value': (189, 204, 0, 255) }) |
|
3091 |
|
params.append({'name': 'inside', 'type': 'color', 'value': (133, 172, 102, 255) }) |
|
3092 |
|
params.append({'name': 'convex_hull', 'type': 'color', 'value': (85, 170, 255, 255) }) # (186, 109, 0, 255) |
|
3093 |
|
params.append({'name': 'fire', 'type': 'color', 'value': (245, 117, 0, 255) }) |
|
3094 |
|
params.append({'name': 'orth', 'type': 'color', 'value': (255, 0, 0, 255) }) |
|
3095 |
|
params.append({'name': 'outside', 'type': 'color', 'value': 0.6}) |
|
3096 |
|
params.append({'name': 'R', 'type': 'color', 'value': (85, 85, 255, 255) }) |
|
3097 |
|
params.append({'name': 'Update as the box runned', 'type': 'bool', 'value': False }) # 'tip': "This is a checkbox" |
|
3098 |
|
params.append({'name': 'index', 'title': "replace previous", 'type': 'bool', 'value': True }) |
|
3099 |
|
|
|
3100 |
|
### Create tree of Parameter objects |
|
3101 |
|
# I don't know why that signals do not work for me |
|
3102 |
|
# Only sigTreeStateChanged works, but I don't want to struggle with it |
|
3103 |
|
# May be I'll report the issue |
|
3104 |
|
#self.param.sigValueChanged.connect(self.param_changed) |
|
3105 |
|
#self.param.sigValueChanging.connect(self.param_changing) |
|
3106 |
|
self.param = pg.parametertree.Parameter.create(name='params', type='group', children=params) |
|
3107 |
|
|
|
3108 |
|
def get_ghull(self): |
|
3109 |
|
integrator = self.param.getValues()['integrator'][0] |
|
3110 |
|
if integrator == 'MC': |
|
3111 |
|
Integrator = Shell_MC |
|
3112 |
|
elif integrator == 'IS': |
|
3113 |
|
Integrator = Shell_IS |
|
3114 |
|
elif integrator == '1DS': |
|
3115 |
|
Integrator = Shell_1DS |
|
3116 |
|
nonG_reduction = self.param.getValues()['nonG_reduction'][0] |
|
3117 |
|
hull = self.get_hull() |
|
3118 |
|
self.ghull = Ghull(hull, Integrator=Integrator, non_Gaussian_reduction=nonG_reduction) |
|
3119 |
|
return self.ghull |
|
3120 |
|
|
|
3121 |
|
|
|
3122 |
|
#č jistě potřebuji něco, co zpracuje parameter_tree |
|
3123 |
|
#č a vratí platný hull pro Ghull |
|
3124 |
|
def get_hull(self): |
|
3125 |
|
#č bez semplu se neobejde |
|
3126 |
|
nsim = self.sb_item.slider.value() |
|
3127 |
|
sample = self.sb_item.sample_box.f_model[:nsim] |
|
3128 |
|
|
|
3129 |
|
# ['SBall', 'BrickHull', 'DirectHull', 'QHull'] |
|
3130 |
|
hull_model = self.param.getValues()['method'][0] |
|
3131 |
|
if hull_model == 'SBall': |
|
3132 |
|
return khull.GBall(sample) |
|
3133 |
|
elif hull_model == 'BrickHull': |
|
3134 |
|
space = self.param.getValues()['space'][0] |
|
3135 |
|
return khull.BrickHull(sample, space) |
|
3136 |
|
elif hull_model == 'DirectHull': |
|
3137 |
|
space = self.param.getValues()['space'][0] |
|
3138 |
|
direct_plan = self.get_scheme() |
|
3139 |
|
return khull.DirectHull(sample, direct_plan, space) |
|
3140 |
|
elif hull_model == 'CompleteHull': |
|
3141 |
|
space = self.param.getValues()['space'][0] |
|
3142 |
|
direct_plan = self.get_scheme() |
|
3143 |
|
return khull.CompleteHull(sample, direct_plan, space) |
|
3144 |
|
elif hull_model == 'QHull': |
|
3145 |
|
space = self.param.getValues()['space'][0] |
|
3146 |
|
#č tento widget pokažde generuje obálku znovu |
|
3147 |
|
return khull.QHull(sample, space, incremental=False) |
|
3148 |
|
else: |
|
3149 |
|
raise ValueError("HullEstimationWidget: co to je za obálku?") |
|
3150 |
|
|
|
3151 |
|
#č ten hlavní modul se dočkal na překopávání |
|
3152 |
|
def on_box_run(self, *args, **kwargs): |
|
3153 |
|
self.clear() |
|
3154 |
|
#č je třeba zkontrolovat autorun a restartovat výpočet |
|
3155 |
|
if self.param.getValues()['Update as the box runned'][0]: |
|
3156 |
|
self.get_shell_estimation() |
|
3157 |
|
|
|
3158 |
|
def index(self, index): |
|
3159 |
|
if self.param.getValues()['index'][0]: # replace previous |
|
3160 |
|
return index |
|
3161 |
|
else: |
|
3162 |
|
return None |
|
3163 |
|
|
|
3164 |
|
def draw_planes(self, equations, space, **kwargs): |
|
3165 |
|
if self.ndim == 2: |
|
3166 |
|
#č musíme něco zavolat na self.equation_planes |
|
3167 |
|
#č equation_planes má funkci add_line() |
|
3168 |
|
#č add_line(self, space='G', index=None, **plot_kwargs) |
|
3169 |
|
#č která pak plot_kwargs přeposilá funkci addLine() |
|
3170 |
|
#č na central widgetu. |
|
3171 |
|
#č To vše skončí ve pyqtgrafové InfiniteLine třidě. |
|
3172 |
|
#č ta moje třida InfiniteLines sama se stará o shodování prostorů |
|
3173 |
|
#č indexy posilat nebudeme (s nimi je to trošku komplikovanější) |
|
3174 |
|
|
|
3175 |
|
#pos = list() #č navrhové body nakreslíme všechny dohromady |
|
3176 |
|
for equation in equations: |
|
3177 |
|
#č ve 2D bych očekával v rovnici pouze 3 hodnoty (já potřebuji směry) |
|
3178 |
|
x, y, offset = equation |
|
3179 |
|
design_point = [-x*offset, -y*offset] |
|
3180 |
|
#self.sb_item.central_widget.plot(np.array([pos, pos]), symbol='o') |
|
3181 |
|
# if y < 0: #č tak to aspoň kreslí |
|
3182 |
|
# angle = np.rad2deg(np.arcsin(x)) |
|
3183 |
|
# else: |
|
3184 |
|
# angle = np.rad2deg(np.arccos(y)) |
|
3185 |
|
|
|
3186 |
|
if (x*y) < 0: #č tak to aspoň kreslí |
|
3187 |
|
angle = np.rad2deg(np.arccos(np.abs(y))) |
|
3188 |
|
else: |
|
3189 |
|
angle = np.rad2deg(np.arccos(-np.abs(y))) |
|
3190 |
|
self.equation_planes.add_line(space=space, pos=design_point, angle=angle, **kwargs) |
|
3191 |
|
|
|
3192 |
|
|
|
3193 |
|
|
|
3194 |
|
def draw_convex_hull(self, hull): |
|
3195 |
|
try: |
|
3196 |
|
if self.param.getValues()['index'][0]: # replace previous |
|
3197 |
|
self.equation_planes.clear() |
|
3198 |
|
|
|
3199 |
|
#č zatím uděláme jen pro 2D infinite lajny |
|
3200 |
|
design_points = hull.get_design_points() |
|
3201 |
|
|
|
3202 |
|
size = self.param.getValues()['node (pixel) size'][0] |
|
3203 |
|
color = self.param.getValues()['convex_hull'][0] #č tam bude barva |
|
3204 |
|
|
|
3205 |
|
self.giracle.add_serie(design_points, z=31, index=self.index('design points'),\ |
|
3206 |
|
pen=None, symbol='o', symbolPen=pg.mkPen(None), \ |
|
3207 |
|
symbolBrush=color, symbolSize=size, name='design points') |
|
3208 |
|
self.draw_planes(hull.equations, space=hull.space, z=29, pen=color) |
|
3209 |
|
|
|
3210 |
|
|
|
3211 |
|
# orth |
|
3212 |
|
color = self.param.getValues()['orth'][0] #č tam bude barva |
|
3213 |
|
#self.giracle.add_serie(FORM_points, z=32, index=self.index('2FORM points'),\ |
|
3214 |
|
# pen=None, symbol='o', symbolPen=pg.mkPen(None), \ |
|
3215 |
|
# symbolBrush=color, symbolSize=size, name='2FORM points') |
|
3216 |
|
self.draw_planes(hull.get_orth_equations(), space=hull.space, z=30, pen=color) |
|
3217 |
|
|
|
3218 |
|
|
|
3219 |
|
# 2FORM |
|
3220 |
|
color = self.param.getValues()['fire'][0] #č tam bude barva |
|
3221 |
|
#self.giracle.add_serie(FORM_points, z=32, index=self.index('2FORM points'),\ |
|
3222 |
|
# pen=None, symbol='o', symbolPen=pg.mkPen(None), \ |
|
3223 |
|
# symbolBrush=color, symbolSize=size, name='2FORM points') |
|
3224 |
|
self.draw_planes(hull.get_2FORM_equations(), space=hull.space, z=30, pen=color) |
|
3225 |
|
|
|
3226 |
|
|
|
3227 |
|
except BaseException as e: |
|
3228 |
|
msg = "draw_convex_hull error " |
|
3229 |
|
error_msg = self.__class__.__name__ + ": " + msg + repr(e) |
|
3230 |
|
print(error_msg) |
|
3231 |
|
self.sb_item.errors.append(e) |
|
3232 |
|
|
|
3233 |
|
def draw_ghull(self, r, R): |
|
3234 |
|
# r-circle |
|
3235 |
|
if r < 0: |
|
3236 |
|
r = 0 |
|
3237 |
|
color = self.param.getValues()['r'][0] #č tam bude barva |
|
3238 |
|
#č krucí, nevím co mám dělat s indexama. |
|
3239 |
|
#č co mám dělat s předchozí kresbou? Nechame |
|
3240 |
|
self.giracle.add_circle(r=r, index=self.index('r'),z=32, pen=color, name='r') |
|
3241 |
|
|
|
3242 |
|
# R-circle. #č Při kreslení nahradíme předchozí. |
|
3243 |
|
color = self.param.getValues()['R'][0] #č tam bude barva |
|
3244 |
|
self.giracle.add_circle(R, z=32, index=self.index('R'), pen=color, name='R') |
|
3245 |
|
|
|
3246 |
|
|
|
3247 |
|
|
|
3248 |
|
|
|
3249 |
|
def get_shell_estimation(self): |
|
3250 |
|
ghull = self.get_ghull() |
|
3251 |
|
self.draw_convex_hull(ghull.hull) |
|
3252 |
|
|
|
3253 |
|
try: |
|
3254 |
|
shell_estimation, global_stats = ghull.get_shell_estimation() |
|
3255 |
|
|
|
3256 |
|
# if hasattr(self.sb_item.sample_box, 'estimations'): |
|
3257 |
|
# self.sb_item.sample_box.estimations.append(data) |
|
3258 |
|
# self.sb_item.estimation_added.emit() |
|
3259 |
|
self.table.setData({**global_stats, 'shell_estimation':shell_estimation}) |
|
3260 |
|
|
|
3261 |
|
self.draw_ghull(global_stats['r'], global_stats['R']) |
|
3262 |
|
|
|
3263 |
|
except BaseException as e: |
|
3264 |
|
msg = "error during estimation " |
|
3265 |
|
error_msg = self.__class__.__name__ + ": " + msg + repr(e) |
|
3266 |
|
print(error_msg) |
|
3267 |
|
self.sb_item.errors.append(e) |
|
3268 |
|
|
|
3269 |
|
|
|
3270 |
|
def shot(self): |
|
3271 |
|
ghull = self.get_ghull() |
|
3272 |
|
self.draw_candidates(ghull.hull.shot) |
|
3273 |
|
|
|
3274 |
|
def fire(self): |
|
3275 |
|
ghull = self.get_ghull() |
|
3276 |
|
self.draw_candidates(ghull.hull.fire) |
|
3277 |
|
|
|
3278 |
|
def boom(self): |
|
3279 |
|
ghull = self.get_ghull() |
|
3280 |
|
self.draw_candidates(ghull.boom) |
|
3281 |
|
|
|
3282 |
|
def draw_candidates(self, source_function): |
|
3283 |
|
#č špatně rozumím, co tím bylo mysleno |
|
3284 |
|
#č že jsem chtěl kreslit náhodné směry? |
|
3285 |
|
##č zatím máme issue s náhodným planem |
|
3286 |
|
##č kdyby něco - vyřeším přes ukladání |
|
3287 |
|
##č náhodných plánů v parameter_tree |
|
3288 |
|
|
|
3289 |
|
self.draw_convex_hull(self.ghull.hull) |
|
3290 |
|
|
|
3291 |
|
#☺ Krucinal, kdo ten OrderedDict vymyslel? |
|
3292 |
|
params = self.param.getValues() |
|
3293 |
|
ns = params['budget'][0] |
|
3294 |
|
use_MC = params['use_MC'][0] |
|
3295 |
|
try: |
|
3296 |
|
fire = source_function(ns, use_MC=use_MC) |
|
3297 |
|
# draw tečičky |
|
3298 |
|
color = self.param.getValues()['fire'][0] #č tam bude barva |
|
3299 |
|
size = self.param.getValues()['node (pixel) size'][0] |
|
3300 |
|
#brush = pg.mkBrush(color) |
|
3301 |
|
self.giracle.add_serie(fire, z=30, index=self.index('fire'),\ |
|
3302 |
|
pen=None, symbol='o', symbolPen=pg.mkPen(None), \ |
|
3303 |
|
symbolBrush=color, symbolSize=size, name='fire') |
|
3304 |
|
|
|
3305 |
|
except BaseException as e: |
|
3306 |
|
msg = "error " |
|
3307 |
|
error_msg = self.__class__.__name__ + ": " + msg + repr(e) |
|
3308 |
|
print(error_msg) |
|
3309 |
|
self.sb_item.errors.append(e) |
|
3310 |
|
|
|
3311 |
|
def integration_callback(self, nodes): |
|
3312 |
|
#č draw tečičky |
|
3313 |
|
size = self.param.getValues()['node (pixel) size'][0] |
|
3314 |
|
plot_params = {'pen':None, 'symbol':'o', 'symbolSize':size, \ |
|
3315 |
|
'symbolPen':pg.mkPen(None)} |
|
3316 |
|
#brush = pg.mkBrush(color) |
|
3317 |
|
mask = nodes.is_outside |
|
3318 |
|
|
|
3319 |
|
index = 'inside' |
|
3320 |
|
color = self.param.getValues()[index][0] #č tam bude barva |
|
3321 |
|
self.serint.add_serie(nodes[~mask], z=30,\ |
|
3322 |
|
symbolBrush=color, name=index, **plot_params) |
|
3323 |
|
|
|
3324 |
|
index = 'outside' |
|
3325 |
|
color = self.param.getValues()[index][0] #č tam bude barva |
|
3326 |
|
self.serint.add_serie(nodes[mask], z=30, \ |
|
3327 |
|
symbolBrush=color, name=index, **plot_params) |
|
3328 |
|
|
|
3329 |
|
# keep the GUI responsive :) |
|
3330 |
|
self.sb_item.app.processEvents() |
|
3331 |
|
|
|
3332 |
|
|
|
3333 |
|
|
|
3334 |
|
def integrate(self): |
|
3335 |
|
#č integrace se stala stateful |
|
3336 |
|
#č a musím jú taky testovat |
|
3337 |
|
if 'ghull' not in self.__dict__: |
|
3338 |
|
ghull = self.get_ghull() |
|
3339 |
|
else: |
|
3340 |
|
ghull = self.ghull |
|
3341 |
|
nsim = self.sb_item.slider.value() |
|
3342 |
|
sample = self.sb_item.sample_box.f_model[:nsim] |
|
3343 |
|
#č teď - saháme do vnitřku naších obliběných tříd |
|
3344 |
|
ghull.hull.sample = sample |
|
3345 |
|
ghull.sample = sample |
|
3346 |
|
|
|
3347 |
|
self.draw_convex_hull(ghull.hull) |
|
3348 |
|
|
|
3349 |
|
|
|
3350 |
|
#☺ Krucinal, kdo ten OrderedDict vymyslel? |
|
3351 |
|
params = self.param.getValues() |
|
3352 |
|
budget = params['budget'][0] |
|
3353 |
|
|
|
3354 |
|
if self.param.getValues()['index'][0]: # replace previous |
|
3355 |
|
self.serint.clear() |
|
3356 |
|
|
|
3357 |
|
try: |
|
3358 |
|
data = ghull.integrate(budget, callback_all=self.integration_callback) |
|
3359 |
|
ghull_estimation, convex_hull_estimation, global_stats = data |
|
3360 |
|
|
|
3361 |
|
#if hasattr(self.sb_item.sample_box, 'estimations'): |
|
3362 |
|
#self.sb_item.sample_box.estimations.append(data) |
|
3363 |
|
#self.sb_item.estimation_added.emit() |
|
3364 |
|
self.table.setData({**global_stats, "ghull_estimation":ghull_estimation,\ |
|
3365 |
|
"convex_hull_estimation": convex_hull_estimation}) |
|
3366 |
|
|
|
3367 |
|
self.draw_ghull(global_stats['r'], global_stats['R']) |
|
3368 |
|
|
|
3369 |
|
|
|
3370 |
|
except ValueError as e: #BaseException |
|
3371 |
|
msg = "error during estimation " |
|
3372 |
|
error_msg = self.__class__.__name__ + ": " + msg + repr(e) |
|
3373 |
|
print(error_msg) |
|
3374 |
|
self.sb_item.errors.append(e) |
|
3375 |
|
|
|
3376 |
|
# draw DP |
|
3377 |
|
if ghull.hull.space != 'G': |
|
3378 |
|
size = self.param.getValues()['node (pixel) size'][0] + 3 |
|
3379 |
|
plot_params = {'pen':None, 'symbol':'t2', 'symbolSize':size, \ |
|
3380 |
|
'symbolPen':pg.mkPen(None)} |
|
3381 |
|
|
|
3382 |
|
#color = self.param.getValues()[index][0] #č tam bude barva |
|
3383 |
|
self.serint.add_serie(ghull.gint.DP, z=35, index='DP', name='DP', **plot_params) |
|
3384 |
|
|
|
3385 |
|
|
|
3386 |
|
|
|
3387 |
|
|
|
3388 |
|
|
|
3389 |
|
""" |
|
3390 |
|
=========== |
|
3391 |
|
♥ Чыры-пыры |
|
3392 |
|
č Jiné |
|
3393 |
|
E Miscellaneous |
|
3394 |
|
=============== |
|
3395 |
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
3396 |
|
""" |
|
3397 |
|
|
|
3398 |
|
|
|
3399 |
|
|
|
3400 |
|
class CandidatesWidget(pg.LayoutWidget): |
|
3401 |
|
""" |
|
3402 |
|
""" |
|
3403 |
|
# I'd like to get access to the samplebox stuff via the container's reference, |
|
3404 |
|
# but relying to Qt's parent mechanism makes me worry. |
|
3405 |
|
def __init__(self, samplebox_item, parent=None, *args, **kwargs): |
|
3406 |
|
super().__init__(parent) |
|
3407 |
|
# sb like samplebox, of course |
|
3408 |
|
self.sb_item = samplebox_item |
|
3409 |
|
|
|
3410 |
|
#self.sb_item.box_runned.connect(self.on_box_run) |
|
3411 |
|
self.sb_item.slice_changed.connect(self.rerun) |
|
3412 |
|
self.sb_item.space_changed.connect(self.rerun) |
|
3413 |
|
self.sb_item.redraw_called.connect(self.redraw) |
|
3414 |
|
#☺ na internetu všichni tak dělaj |
|
3415 |
|
self.setup() |
|
3416 |
|
|
|
3417 |
|
def setup(self): |
|
3418 |
|
# 1 |
|
3419 |
|
# |
|
3420 |
|
self.autorun = QtGui.QCheckBox('Show') |
|
3421 |
|
self.autorun.stateChanged.connect(self.rerun) |
|
3422 |
|
self.addWidget(self.autorun) |
|
3423 |
|
|
|
3424 |
|
self.btn = QtGui.QPushButton('redraw') |
|
3425 |
|
self.addWidget(self.btn, row=0, col=1) |
|
3426 |
|
self.btn.clicked.connect(self.rerun) |
|
3427 |
|
|
|
3428 |
|
# 2 |
|
3429 |
|
# |
|
3430 |
|
#č predpokladam pandas verzi CandyBox'u |
|
3431 |
|
#items = list(self.sb_item.sample_box.candidates_index[-1].df.columns) |
|
3432 |
|
try: |
|
3433 |
|
#č načíst sloupce prostě z libovolného vzorku |
|
3434 |
|
df = self.sb_item.sample_box.candidates_index.values().__iter__().__next__() |
|
3435 |
|
items = df.columns |
|
3436 |
|
except: |
|
3437 |
|
#♥ мыным дунне |
|
3438 |
|
items = [] |
|
3439 |
|
|
|
3440 |
|
self.attr = pg.ComboBox(items=items) |
|
3441 |
|
#self.attr.activated.connect(self.redraw) |
|
3442 |
|
self.addWidget(self.attr, row=1, col=0, colspan=2) |
|
3443 |
|
|
|
3444 |
|
# 3 |
|
3445 |
|
# |
|
3446 |
|
self.gradient = pg.GradientWidget(self, orientation='right') |
|
3447 |
|
self.gradient.setColorMap(pg.colormap.ColorMap((0,1),\ |
|
3448 |
|
[(255, 255, 255, 255), (67, 0, 81, 255)])) |
|
3449 |
|
self.addWidget(self.gradient, row=2, col=1) |
|
3450 |
|
|
|
3451 |
|
|
|
3452 |
|
|
|
3453 |
|
#E pens, i.e. handles of PlotItem |
|
3454 |
|
self.pens = [] |
|
3455 |
|
|
|
3456 |
|
|
|
3457 |
|
def run_stm(self): |
|
3458 |
|
#č indikace |
|
3459 |
|
#self.setDisabled(True) |
|
3460 |
|
plot_widget = self.sb_item.central_widget |
|
3461 |
|
with pg.BusyCursor(): |
|
3462 |
|
|
|
3463 |
|
color_map = self.gradient.colorMap() |
|
3464 |
|
|
|
3465 |
|
try:#č může se tu stat cokoliv |
|
3466 |
|
#č načíst sloupce prostě z libovolného vzorku |
|
3467 |
|
cb = self.sb_item.sample_box.candidates_index.values().__iter__().__next__() |
|
3468 |
|
#č je třeba mít seznam aktualní |
|
3469 |
|
self.attr.setItems(list(cb.df.columns)) |
|
3470 |
|
|
|
3471 |
|
#č neplest s self.attr! |
|
3472 |
|
attr = self.attr.currentText() |
|
3473 |
|
|
|
3474 |
|
#č kruci, nejdřív je třeba najít maxvalue, minvalue je implicitně nula |
|
3475 |
|
maxvalue = -np.inf |
|
3476 |
|
minvalue = np.inf |
|
3477 |
|
for id, cb in self.sb_item.sample_box.candidates_index.items(): |
|
3478 |
|
array = getattr(cb, attr) |
|
3479 |
|
if len(array): |
|
3480 |
|
maxcb = np.nanmax(array) |
|
3481 |
|
mincb = np.nanmin(array) |
|
3482 |
|
if maxcb > maxvalue: |
|
3483 |
|
maxvalue = maxcb |
|
3484 |
|
maxitem = cb[np.nanargmax(array)] |
|
3485 |
|
if mincb < minvalue: |
|
3486 |
|
minvalue = mincb |
|
3487 |
|
|
|
3488 |
|
#č zvlášť nakreslím maximální hodnotu |
|
3489 |
|
pos = getattr(maxitem, self.sb_item.space)[:,:2] |
|
3490 |
|
max_item = plot_widget.plot(pos, data=maxvalue, pen=None, symbol='t1',\ |
|
3491 |
|
symbolBrush=color_map.mapToQColor(1)) |
|
3492 |
|
max_item.setZValue(130) |
|
3493 |
|
self.pens.append(max_item) |
|
3494 |
|
|
|
3495 |
|
#č a teď jdeme! |
|
3496 |
|
for id, cb in self.sb_item.sample_box.candidates_index.items(): |
|
3497 |
|
array = getattr(cb, attr) |
|
3498 |
|
if np.isnan(array).any(): |
|
3499 |
|
msg = "%s candidates has nans in %s attribute"%(id, attr) |
|
3500 |
|
error_msg = self.__class__.__name__ + ": " + msg |
|
3501 |
|
print(error_msg) |
|
3502 |
|
mask = np.isfinite(array) |
|
3503 |
|
values = array[mask] |
|
3504 |
|
norm_values = (values - minvalue) / (maxvalue - minvalue) |
|
3505 |
|
|
|
3506 |
|
pos = getattr(cb, self.sb_item.space)[mask][:,:2] |
|
3507 |
|
|
|
3508 |
|
#č sehnal jsem toto ze zdrojaků pyqtgraph |
|
3509 |
|
style = dict(pen=None, symbol='o', symbolSize=self.sb_item.px_size, symbolPen=pg.mkPen(None)) |
|
3510 |
|
style['symbolBrush'] = np.array([pg.functions.mkBrush(*x) for x in color_map.map(norm_values)]) |
|
3511 |
|
pen = plot_widget.plot(pos, data=values, **style) |
|
3512 |
|
pen.setZValue(-1) |
|
3513 |
|
self.pens.append(pen) |
|
3514 |
|
|
|
3515 |
|
except BaseException as e: |
|
3516 |
|
msg = "" |
|
3517 |
|
error_msg = self.__class__.__name__ + ": " + msg + repr(e) |
|
3518 |
|
print(error_msg) |
|
3519 |
|
|
|
3520 |
|
|
|
3521 |
|
|
|
3522 |
|
# indikace |
|
3523 |
|
#self.setEnabled(True) |
|
3524 |
|
|
|
3525 |
|
|
|
3526 |
|
|
|
3527 |
|
#č současně ten hlavní modul se pokusí zavolat redraw při zpouštění boxu |
|
3528 |
|
#č ten hlavní modul se těší na překopávání |
|
3529 |
|
def rerun(self, *args, **kwargs): |
|
3530 |
|
#č uklizení budu chtit jednoznačně |
|
3531 |
|
self.self_clear() |
|
3532 |
|
#č a teď řešíme, zda je třeba restartovat výpočet |
|
3533 |
|
if self.autorun.isChecked(): |
|
3534 |
|
self.run_stm() |
|
3535 |
|
|
|
3536 |
|
def redraw(self, *args, **kwargs): |
|
3537 |
|
self.pens.clear() |
|
3538 |
|
|
|
3539 |
|
|
|
3540 |
|
def self_clear(self): |
|
3541 |
|
#č odebereme prvky-propísky z hlavního plotu |
|
3542 |
|
for plot_item in self.pens: |
|
3543 |
|
self.sb_item.central_widget.removeItem(plot_item) |
|
3544 |
|
|
|
3545 |
|
self.pens.clear() |
|
3546 |
|
|
|
3547 |
|
|
|
3548 |
|
#E not implementeed yet on the main window side |
|
3549 |
|
# def on_space_changed(self, *args, **kwargs): |
|
3550 |
|
# pass |
|
3551 |
|
|
|
3552 |
|
|
|
3553 |
529 |
|
|
3554 |
530 |
class BoxTreeWidget(pg.LayoutWidget): |
class BoxTreeWidget(pg.LayoutWidget): |
3555 |
531 |
""" |
""" |
File qt_gui/qt_plot.py changed (mode: 100644) (index 2a088a1..b211600) |
... |
... |
import pyqtgraph as pg |
5 |
5 |
from pyqtgraph.Qt import QtGui |
from pyqtgraph.Qt import QtGui |
6 |
6 |
from pyqtgraph.Qt import QtCore |
from pyqtgraph.Qt import QtCore |
7 |
7 |
|
|
8 |
|
from pyqtgraph import console |
|
9 |
8 |
|
|
10 |
9 |
import numpy as np |
import numpy as np |
11 |
|
import pandas as pd # required for estimation graph |
|
12 |
10 |
|
|
13 |
11 |
#č vzdávám se. |
#č vzdávám se. |
14 |
12 |
#č quadpy tak se stavá povinnou závislostí |
#č quadpy tak se stavá povinnou závislostí |
|
... |
... |
import quadpy |
18 |
16 |
|
|
19 |
17 |
from .. import estimation as stm |
from .. import estimation as stm |
20 |
18 |
from .. import misc |
from .. import misc |
21 |
|
from .. import stm_df |
|
22 |
19 |
from .. import sball |
from .. import sball |
23 |
20 |
from .. import schemes |
from .. import schemes |
24 |
21 |
from .. import convex_hull as khull |
from .. import convex_hull as khull |
25 |
22 |
#č pro mě je zvykem jako ghull označovat objekt třídy Ghull |
#č pro mě je zvykem jako ghull označovat objekt třídy Ghull |
26 |
23 |
#č nikoliv čerstvě oddelený modul |
#č nikoliv čerstvě oddelený modul |
27 |
|
from .ghull import Ghull, Shell_MC, Shell_IS, Shell_1DS |
|
|
24 |
|
from ..ghull import Ghull, Shell_MC, Shell_IS, Shell_1DS |
|
25 |
|
from . import qt_gui |
28 |
26 |
|
|
29 |
|
|
|
30 |
|
def qt_gui_plot_2d(sample_box, space='R', *args, **kwargs): |
|
31 |
|
""" |
|
32 |
|
This function will start Qt graph window in event loop |
|
33 |
|
""" |
|
34 |
|
|
|
35 |
|
return QtGuiPlot2D(sample_box, space, *args, **kwargs) |
|
36 |
27 |
|
|
37 |
28 |
|
|
38 |
|
### Define a top-level widget to hold everything |
|
39 |
|
class QtGuiPlot2D(QtGui.QMainWindow): |
|
40 |
|
#č box_runned dublikuje slice_changed |
|
41 |
|
# do not redraw twice! |
|
42 |
|
box_runned = QtCore.pyqtSignal() |
|
43 |
|
space_changed = QtCore.pyqtSignal() |
|
44 |
|
slice_changed = QtCore.pyqtSignal() |
|
45 |
|
redraw_called = QtCore.pyqtSignal() |
|
46 |
|
estimation_added = QtCore.pyqtSignal() |
|
47 |
|
|
|
48 |
|
# INHERITED by gl_plot |
|
49 |
|
# snad pri vykreslování argy-kvargy nevádí |
|
50 |
|
def __init__(self, sample_box, space='R', *args, **kwargs): |
|
51 |
|
|
|
52 |
|
#E former self.w = QtGui.QMainWindow() |
|
53 |
|
self.app = pg.mkQApp() |
|
54 |
|
super().__init__() |
|
55 |
|
try: |
|
56 |
|
self.setWindowTitle("%sD: %s" %(sample_box.nvar, sample_box.gm_signature)) |
|
57 |
|
except: |
|
58 |
|
self.setWindowTitle("%sD nodes" % sample_box.nvar) |
|
59 |
|
|
|
60 |
|
# for debug |
|
61 |
|
# container for errors |
|
62 |
|
# to trace errors |
|
63 |
|
self.errors = [] |
|
64 |
|
|
|
65 |
|
self.kwargs = kwargs |
|
66 |
|
self.sample_box = sample_box |
|
67 |
|
#sample_box.sample_box._log = self.logger |
|
68 |
|
self.last_shot = None |
|
69 |
|
try: |
|
70 |
|
self.space = self.sample_box.tri_space |
|
71 |
|
except AttributeError: |
|
72 |
|
self.space = space |
|
73 |
|
|
|
74 |
|
# "zapnuté" prostory |
|
75 |
|
#self.spaces = ['R', 'aR', 'Rn', 'aRn', 'P', 'aP', 'GK', 'aGK', 'G', 'aG', 'U', 'aU'] |
|
76 |
|
self.spaces = ['R', 'aR', 'Rn', 'aRn', 'P', 'GK', 'G', 'aG', 'U', 'aU'] |
|
77 |
|
|
|
78 |
|
# initialize central widget |
|
79 |
|
self.initialize_central_widget() |
|
80 |
|
|
|
81 |
|
# common setup |
|
82 |
|
self.setup() |
|
83 |
|
|
|
84 |
|
self.plot_setup() |
|
85 |
|
|
|
86 |
|
## Display the widget as a new window |
|
87 |
|
self.show() |
|
88 |
|
|
|
89 |
|
# |
|
90 |
|
self.redraw_called.emit() |
|
91 |
|
|
|
92 |
|
## Start the Qt event loop |
|
93 |
|
self.app.exec_() |
|
94 |
|
|
|
95 |
|
|
|
|
29 |
|
class QtGuiPlot2D(qt_gui.QtGuiWindow): |
96 |
30 |
def initialize_central_widget(self): |
def initialize_central_widget(self): |
97 |
31 |
self.central_widget = pg.PlotWidget() |
self.central_widget = pg.PlotWidget() |
98 |
32 |
self.central_widget.setBackground('w') |
self.central_widget.setBackground('w') |
|
... |
... |
class QtGuiPlot2D(QtGui.QMainWindow): |
100 |
34 |
self.ncircles = 5 |
self.ncircles = 5 |
101 |
35 |
self.redraw_called.connect(self.central_widget.clear) |
self.redraw_called.connect(self.central_widget.clear) |
102 |
36 |
|
|
103 |
|
# should be INHERITED by gl_plot |
|
104 |
|
def initialize_matplotlib_menu(self): |
|
105 |
|
try: # entire optional functionality |
|
106 |
|
from .mplot import show_ax, show_ax3d, show_fig |
|
107 |
|
from .mplot import maxes |
|
108 |
|
from .mplot import maxes3d |
|
109 |
|
from .mplot import mfigs |
|
110 |
|
from .mplot import misc as mmisc |
|
111 |
|
self.matplotlib_menu = self.bar.addMenu("Matplotlib") |
|
112 |
|
self.matplotlib_actions = [] |
|
113 |
|
|
|
114 |
|
self.matplotlib_2D_menu = self.matplotlib_menu.addMenu("2D plots") |
|
115 |
|
self._setup_mpl_submenu(self.matplotlib_2D_menu, maxes, show_ax) |
|
116 |
|
|
|
117 |
|
self.matplotlib_3D_menu = self.matplotlib_menu.addMenu("3D plots") |
|
118 |
|
self._setup_mpl_submenu(self.matplotlib_3D_menu, maxes3d, show_ax3d) |
|
119 |
|
|
|
120 |
|
self.matplotlib_figs_menu = self.matplotlib_menu.addMenu("Complex plots") |
|
121 |
|
self._setup_mpl_submenu(self.matplotlib_figs_menu, mfigs, show_fig) |
|
122 |
|
|
|
123 |
|
self.matplotlib_misc_menu = self.matplotlib_menu.addMenu("Others") |
|
124 |
|
for smthng in mmisc.__all__: |
|
125 |
|
mpl_action = QtGui.QAction(smthng, self) |
|
126 |
|
show_mpl = self._mpl_prepare_fn(getattr(mmisc, smthng)) |
|
127 |
|
mpl_action.triggered.connect(show_mpl) |
|
128 |
|
self.matplotlib_misc_menu.addAction(mpl_action) |
|
129 |
|
# prevent GC from wiping out both Qt object and our function |
|
130 |
|
self.matplotlib_actions.append((mpl_action, show_mpl)) |
|
131 |
|
|
|
132 |
|
except ImportError as e: |
|
133 |
|
msg = "Matplotlib related features are unavailiable" |
|
134 |
|
print(self.__class__.__name__ + ":", msg, repr(e)) |
|
135 |
|
|
|
136 |
|
def _setup_mpl_submenu(self, menu, module, handler): |
|
137 |
|
for drawing in module.__all__: |
|
138 |
|
mpl_action = QtGui.QAction(drawing, self) |
|
139 |
|
# do not really understand what I am doing :( |
|
140 |
|
# try to show_mpl remember its actual drawing string |
|
141 |
|
show_mpl = self._mpl_prepare_show_fn(handler, getattr(module, drawing)) |
|
142 |
|
mpl_action.triggered.connect(show_mpl) |
|
143 |
|
menu.addAction(mpl_action) |
|
144 |
|
# prevent GC from wiping out both Qt object and our function |
|
145 |
|
self.matplotlib_actions.append((mpl_action, show_mpl)) |
|
146 |
|
|
|
147 |
|
def _mpl_prepare_show_fn(self, show, to_draw): |
|
148 |
|
return lambda: show(to_draw, self.get_sample_box(), space=self.space) |
|
149 |
|
|
|
150 |
|
def _mpl_prepare_fn(self, fn): |
|
151 |
|
return lambda: fn(sample_box=self.get_sample_box(), space=self.space) |
|
152 |
|
|
|
153 |
|
def get_sample_box(self): |
|
154 |
|
nsim = self.slider.value() |
|
155 |
|
if nsim == self.sample_box.nsim: |
|
156 |
|
return self.sample_box |
|
157 |
|
else: |
|
158 |
|
return self.sample_box[:nsim] |
|
159 |
|
|
|
160 |
|
# INHERITED by gl_plot |
|
161 |
|
# intended as a common setup function |
|
162 |
|
def setup(self): |
|
163 |
|
|
|
164 |
|
self.bar = self.menuBar() |
|
165 |
|
self.view = self.bar.addMenu("View") |
|
166 |
|
|
|
167 |
|
self.graph_menu = self.bar.addMenu("Box") |
|
168 |
|
self.batch_run_action = QtGui.QAction("Batch run", self) |
|
169 |
|
self.batch_run_action.triggered.connect(self.batch_run) |
|
170 |
|
self.graph_menu.addAction(self.batch_run_action) |
|
171 |
|
|
|
172 |
|
# optional feature |
|
173 |
|
self.initialize_matplotlib_menu() |
|
174 |
|
|
|
175 |
|
### Create some widgets to be placed inside |
|
176 |
|
self.combo_space = pg.ComboBox(items=self.spaces, default=self.space) |
|
177 |
|
self.combo_space.activated[str].connect(self.change_space) |
|
178 |
|
|
|
179 |
|
|
|
180 |
|
self.label_nsim = QtGui.QLabel() |
|
181 |
|
self.label_nsim.setText(str(self.sample_box.nsim)) |
|
182 |
|
|
|
183 |
|
self.slider = QtGui.QSlider(QtCore.Qt.Horizontal) |
|
184 |
|
self.slider.valueChanged.connect(self._slider_chainged) |
|
185 |
|
self.slider.sliderReleased.connect(lambda:self.slice_changed.emit()) |
|
186 |
|
self.slider.setMaximum(self.sample_box.nsim) |
|
187 |
|
self.slider.setValue(self.sample_box.nsim) |
|
188 |
|
|
|
189 |
|
#č jen aby se slider probral, když uživatel ručně přídá bodíky |
|
190 |
|
self.redraw_called.connect(lambda:self.slider.setMaximum(self.sample_box.nsim)) |
|
191 |
|
|
|
192 |
|
self.btn = QtGui.QPushButton('run box') |
|
193 |
|
self.btn.clicked.connect(self.run_sb) |
|
194 |
|
|
|
195 |
|
self.btn2 = QtGui.QPushButton('connect/disconnect') |
|
196 |
|
self.btn2.setCheckable(True) |
|
197 |
|
self.btn2.clicked.connect(self.bx_connect) |
|
198 |
|
|
|
199 |
|
self.btn3 = QtGui.QPushButton('redraw') |
|
200 |
|
self.btn3.clicked.connect(lambda:self.redraw_called.emit()) |
|
201 |
|
|
|
202 |
|
|
|
203 |
|
## Create a grid layout to manage the widgets size and position |
|
204 |
|
self.layout = pg.LayoutWidget() |
|
205 |
|
self.setCentralWidget(self.layout) |
|
206 |
|
#self.w.setLayout(self.layout) |
|
207 |
|
|
|
208 |
|
# |
|
209 |
|
self.list_view = QtGui.QListWidget() |
|
210 |
|
|
|
211 |
|
## Add widgets to the layout in their proper positions |
|
212 |
|
#self.layout.addWidget(self.list_view, 0, 0, 2, 1) |
|
213 |
|
self.layout.addWidget(self.combo_space, 0, 0) |
|
214 |
|
self.layout.addWidget(self.slider, 0, 1) |
|
215 |
|
self.layout.addWidget(self.label_nsim, 0, 2) |
|
216 |
|
self.layout.addWidget(self.btn, 0, 3) |
|
217 |
|
self.layout.addWidget(self.btn2, 0, 4) |
|
218 |
|
self.layout.addWidget(self.btn3, 0, 5) |
|
219 |
|
self.layout.addWidget(self.central_widget, 1, 0, 1, 6) |
|
220 |
|
|
|
221 |
|
|
|
222 |
|
|
|
223 |
|
# status bar, mainly to observe BlackBox |
|
224 |
|
self.statusBar = QtGui.QStatusBar() |
|
225 |
|
self.setStatusBar(self.statusBar) |
|
226 |
|
self.btn_continue = QtGui.QPushButton('continue') |
|
227 |
|
self.continue_label = QtGui.QLabel() |
|
228 |
|
# self.continue_layout = QtGui.QHBoxLayout() |
|
229 |
|
# self.continue_layout.addWidget(self.btn_continue) |
|
230 |
|
# self.continue_layout.addWidget(self.continue_label) |
|
231 |
|
self.statusBar.addWidget(self.btn_continue) |
|
232 |
|
self.statusBar.addWidget(self.continue_label) |
|
233 |
|
self.btn_continue.hide() |
|
234 |
|
self.continue_label.hide() |
|
235 |
|
|
|
236 |
|
self.statusBar.showMessage("Vitáme vás u nás!") |
|
237 |
|
|
|
238 |
|
|
|
239 |
|
|
|
240 |
|
|
|
241 |
|
# Dockables, najzajimavejší věc |
|
242 |
|
self.dockables = [] |
|
243 |
|
|
|
244 |
|
|
|
245 |
|
dock = QtGui.QDockWidget("Interactive python console", self) |
|
246 |
|
dock.setWidget(console.ConsoleWidget(namespace={**locals(), **globals()})) |
|
247 |
|
self.dockables.append(dock) |
|
248 |
|
self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, dock) |
|
249 |
|
|
|
250 |
|
|
|
251 |
|
dock = QtGui.QDockWidget("BlackBox output", self) |
|
252 |
|
self.output_label = QtGui.QLabel() |
|
253 |
|
dock.setWidget(self.output_label) |
|
254 |
|
self.dockables.append(dock) |
|
255 |
|
self.tabifyDockWidget(self.dockables[0], dock) |
|
256 |
|
|
|
257 |
|
self.simplex_data = SimplexEstimationData(self.sample_box, self) |
|
258 |
|
#č graphy už nemusí jít po stm widgetech |
|
259 |
|
dock = QtGui.QDockWidget("TRI_overall estimation graph", self) |
|
260 |
|
dock.setWidget(TriEstimationGraph(self.sample_box, 'TRI_overall_estimations', self, dock)) |
|
261 |
|
self.dockables.append(dock) |
|
262 |
|
self.tabifyDockWidget(self.dockables[0], dock) |
|
263 |
|
|
|
264 |
|
dock = QtGui.QDockWidget("Simplex estimation graph", self) |
|
265 |
|
dock.setWidget(SimpleSimplexEstimationGraph(self.sample_box, self, dock)) |
|
266 |
|
self.dockables.append(dock) |
|
267 |
|
self.tabifyDockWidget(self.dockables[0], dock) |
|
268 |
|
|
|
269 |
|
dock = QtGui.QDockWidget("Simplex error graph", self) |
|
270 |
|
dock.setWidget(SimplexErrorGraph(self.simplex_data, dock)) |
|
271 |
|
self.dockables.append(dock) |
|
272 |
|
self.tabifyDockWidget(self.dockables[0], dock) |
|
273 |
|
|
|
274 |
|
|
|
275 |
|
dock = QtGui.QDockWidget("Voronoi estimation graph", self) |
|
276 |
|
dock.setWidget(VoronoiEstimationGraph(self.sample_box, self, dock)) |
|
277 |
|
self.dockables.append(dock) |
|
278 |
|
self.tabifyDockWidget(self.dockables[0], dock) |
|
279 |
|
|
|
280 |
|
|
|
281 |
|
|
|
282 |
|
|
|
283 |
|
dock = dock_l = QtGui.QDockWidget("Box tree", self) |
|
284 |
|
dock.setWidget(BoxTreeWidget(self, dock)) |
|
285 |
|
self.dockables.append(dock) |
|
286 |
|
self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, dock) |
|
287 |
|
|
|
288 |
|
|
|
289 |
|
|
|
290 |
|
dock = QtGui.QDockWidget("View", self) |
|
291 |
|
dock.setWidget(self.list_view) |
|
292 |
|
self.dockables.append(dock) |
|
293 |
|
self.tabifyDockWidget(dock_l, dock) |
|
294 |
|
|
|
295 |
|
|
|
296 |
|
|
|
297 |
|
|
|
298 |
|
for dock in self.dockables: |
|
299 |
|
self.view.addAction(dock.toggleViewAction()) |
|
300 |
|
#dock.setFloating(True) |
|
301 |
|
|
|
302 |
|
#self.w.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.items) |
|
303 |
|
|
|
304 |
|
|
|
305 |
|
|
|
306 |
37 |
|
|
307 |
38 |
|
|
308 |
39 |
def plot_setup(self): |
def plot_setup(self): |
|
... |
... |
class QtGuiPlot2D(QtGui.QMainWindow): |
348 |
79 |
self.tabifyDockWidget(dock_r, dock) |
self.tabifyDockWidget(dock_r, dock) |
349 |
80 |
|
|
350 |
81 |
|
|
351 |
|
# |
|
352 |
|
#č Tlačítka! |
|
353 |
|
# |
|
354 |
|
|
|
355 |
|
# INHERITED by gl_plot |
|
356 |
|
def _slider_chainged(self, value): |
|
357 |
|
#č .setMaximum() nezpůsobuje emitování slice_changed, jsem zkontroloval |
|
358 |
|
self.slider.setMaximum(self.sample_box.nsim) |
|
359 |
|
self.label_nsim.setText(str(value)) |
|
360 |
|
if not self.slider.isSliderDown(): # co to vůbec děla? |
|
361 |
|
self.slice_changed.emit() |
|
362 |
|
|
|
363 |
|
# INHERITED by gl_plot |
|
364 |
|
def change_space(self, space): |
|
365 |
|
self.space = space |
|
366 |
|
self.space_changed.emit() |
|
367 |
|
#self.plot_widget_2d() |
|
368 |
|
#self.slice_plot_data() |
|
369 |
|
|
|
370 |
|
# INHERITED by gl_plot |
|
371 |
|
def run_sb(self): |
|
372 |
|
with pg.BusyCursor(): |
|
373 |
|
self.last_shot = self.sample_box() |
|
374 |
|
|
|
375 |
|
# slider |
|
376 |
|
#č zpusobí slice_changed |
|
377 |
|
self.slider.setMaximum(self.sample_box.nsim) |
|
378 |
|
self.slider.setValue(self.sample_box.nsim) |
|
379 |
|
|
|
380 |
|
self.box_runned.emit() |
|
381 |
|
|
|
382 |
|
|
|
383 |
|
|
|
384 |
|
# INHERITED by gl_plot |
|
385 |
|
def bx_connect(self): |
|
386 |
|
if self.btn2.isChecked(): |
|
387 |
|
try: |
|
388 |
|
self.sample_box.connect(self.logger) |
|
389 |
|
except BaseException as e: |
|
390 |
|
print(self.__class__.__name__ + ":", "connection to BlackBox failed", repr(e)) |
|
391 |
|
else: |
|
392 |
|
try: |
|
393 |
|
self.sample_box.disconnect() |
|
394 |
|
except BaseException as e: |
|
395 |
|
print(self.__class__.__name__ + ":", "error while disconnecting of BlackBox", repr(e)) |
|
396 |
|
|
|
397 |
|
# INHERITED by gl_plot |
|
398 |
|
def logger(self, *args, msg="", indent=0, **kwargs): |
|
399 |
|
self.continue_label.setText("BlackBox: " + msg) |
|
400 |
|
self.output_label.setText(str(args) + str(kwargs)) |
|
401 |
|
|
|
402 |
|
loop = QtCore.QEventLoop() |
|
403 |
|
self.btn_continue.clicked.connect(loop.quit) |
|
404 |
|
self.btn_continue.show() |
|
405 |
|
self.continue_label.show() |
|
406 |
|
# i want to clear status bar temporaly |
|
407 |
|
status = self.statusBar.currentMessage() |
|
408 |
|
self.statusBar.clearMessage() |
|
409 |
|
|
|
410 |
|
loop.exec_() # Execution stops here until finished called |
|
411 |
|
|
|
412 |
|
self.btn_continue.hide() |
|
413 |
|
self.continue_label.hide() |
|
414 |
|
self.statusBar.showMessage(status) |
|
415 |
|
|
|
416 |
|
|
|
417 |
|
def batch_run(self): |
|
418 |
|
#pg.QtGui.QInputDialog.getInt( |
|
419 |
|
runs, ok = QtGui.QInputDialog.getInt(self,"Batch run","runs") |
|
420 |
|
|
|
421 |
|
if ok: |
|
422 |
|
with pg.ProgressDialog("Running..", 0, runs, cancelText='Stop', busyCursor=True) as dlg: |
|
423 |
|
for i in range(runs): |
|
424 |
|
# keep the GUI responsive :) |
|
425 |
|
self.app.processEvents() |
|
426 |
|
|
|
427 |
|
self.last_shot = self.sample_box() |
|
428 |
|
|
|
429 |
|
# slider |
|
430 |
|
#č zpusobí slice_changed |
|
431 |
|
self.slider.setMaximum(self.sample_box.nsim) |
|
432 |
|
self.slider.setValue(self.sample_box.nsim) |
|
433 |
|
|
|
434 |
|
self.box_runned.emit() |
|
435 |
|
|
|
436 |
|
dlg += 1 |
|
437 |
|
if dlg.wasCanceled(): |
|
438 |
|
break |
|
439 |
|
|
|
440 |
|
|
|
441 |
|
|
|
442 |
82 |
|
|
443 |
83 |
|
|
444 |
84 |
|
|
|
... |
... |
class ConvexHull2D(Triangulation): |
1220 |
860 |
|
|
1221 |
861 |
|
|
1222 |
862 |
|
|
1223 |
|
|
|
1224 |
|
""" |
|
1225 |
|
============= |
|
1226 |
|
График виӝет |
|
1227 |
|
Grafy |
|
1228 |
|
Estimation graph widgets |
|
1229 |
|
======================== |
|
1230 |
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
1231 |
|
""" |
|
1232 |
|
|
|
1233 |
|
|
|
1234 |
|
def get_estimation_data(estimations, metric): |
|
1235 |
|
metric_dict = dict() |
|
1236 |
|
# new-style: šecko leží dohromady a každý z toho |
|
1237 |
|
# bere co chce a jak chce |
|
1238 |
|
# ne že by to bylo nějak šetrný |
|
1239 |
|
# estimation je slovníkem |
|
1240 |
|
for estimation in estimations: |
|
1241 |
|
# nsim musí mäť každej odhad |
|
1242 |
|
# pokud nemá - je třeba jej prostě opravit |
|
1243 |
|
nsim = estimation['nsim'] |
|
1244 |
|
try: |
|
1245 |
|
metric_dict[nsim] = estimation[metric] |
|
1246 |
|
except KeyError as e: |
|
1247 |
|
pass #print(self.__class__.__name__ + ":", repr(e)) |
|
1248 |
|
|
|
1249 |
|
# nikdo neslibil, že budou v pořadí |
|
1250 |
|
x = np.sort(tuple(metric_dict.keys())) |
|
1251 |
|
y = np.array(tuple(metric_dict.values()))[np.argsort(tuple(metric_dict.keys()))] |
|
1252 |
|
return x, y |
|
1253 |
|
|
|
1254 |
|
|
|
1255 |
|
class SimplexEstimationData(QtCore.QObject): |
|
1256 |
|
#š budeme mӓť svůj vlastní signaľčík |
|
1257 |
|
simplex_estimation_updated = QtCore.pyqtSignal() |
|
1258 |
|
|
|
1259 |
|
def __init__(self, dice_box, stream=None, *args, **kwargs): |
|
1260 |
|
super().__init__(stream, *args, **kwargs) |
|
1261 |
|
self.dice_box = dice_box |
|
1262 |
|
#č je zřejmě, že tím potokem bylo myšleno hlavní okínko |
|
1263 |
|
#č asi aby nepadalo, když nenajde signaly |
|
1264 |
|
self.stream = stream |
|
1265 |
|
if stream is not None: |
|
1266 |
|
self.stream.box_runned.connect(self.recalculate) |
|
1267 |
|
self.stream.estimation_added.connect(self.recalculate) |
|
1268 |
|
|
|
1269 |
|
self.setup_context_menu() |
|
1270 |
|
self.recalculate() |
|
1271 |
|
|
|
1272 |
|
|
|
1273 |
|
def setup_context_menu(self): |
|
1274 |
|
# simplex_data_menu |
|
1275 |
|
self.TRI_menu = QtGui.QMenu("TRI sources", self.stream) |
|
1276 |
|
|
|
1277 |
|
self.TRI_overall_chk = QtGui.QAction("TRI_overall_estimations", self.TRI_menu) |
|
1278 |
|
self.TRI_overall_chk.setCheckable(True) |
|
1279 |
|
self.TRI_overall_chk.setChecked(True) |
|
1280 |
|
self.TRI_overall_chk.triggered.connect(self.recalculate) |
|
1281 |
|
self.TRI_menu.addAction(self.TRI_overall_chk) |
|
1282 |
|
|
|
1283 |
|
self.simplex_chk = QtGui.QAction("Simplex estimations", self.TRI_menu) |
|
1284 |
|
self.simplex_chk.setCheckable(True) |
|
1285 |
|
self.simplex_chk.setChecked(True) |
|
1286 |
|
self.simplex_chk.triggered.connect(self.recalculate) |
|
1287 |
|
self.TRI_menu.addAction(self.simplex_chk) |
|
1288 |
|
|
|
1289 |
|
# year, it was |
|
1290 |
|
## hope, it is temporary |
|
1291 |
|
#self.sources_action_group = QtGui.QActionGroup(self.TRI_menu) |
|
1292 |
|
#self.sources_action_group.addAction(self.TRI_overall_chk) |
|
1293 |
|
#self.sources_action_group.addAction(self.simplex_chk) |
|
1294 |
|
|
|
1295 |
|
self.TRI_menu.addSeparator() |
|
1296 |
|
|
|
1297 |
|
self.proxy_chk = QtGui.QAction("Proxy", self.TRI_menu) |
|
1298 |
|
self.proxy_chk.setCheckable(True) |
|
1299 |
|
self.proxy_chk.setChecked(hasattr(self.dice_box, 'proxy')) |
|
1300 |
|
self.proxy_chk.triggered.connect(self.recalculate) |
|
1301 |
|
self.TRI_menu.addAction(self.proxy_chk) |
|
1302 |
|
|
|
1303 |
|
self.TRI_menu.addSeparator() |
|
1304 |
|
|
|
1305 |
|
self.reaction = QtGui.QAction("Update", self.TRI_menu) |
|
1306 |
|
self.reaction.triggered.connect(self.recalculate) |
|
1307 |
|
self.TRI_menu.addAction(self.reaction) |
|
1308 |
|
|
|
1309 |
|
self.excelaction = QtGui.QAction("Export to Excel", self.TRI_menu) |
|
1310 |
|
self.excelaction.triggered.connect(self.export_to_excel) |
|
1311 |
|
self.TRI_menu.addAction(self.excelaction) |
|
1312 |
|
|
|
1313 |
|
|
|
1314 |
|
def export_to_excel(self): |
|
1315 |
|
#č já bych nechtěl, aby mně export najednou spadl |
|
1316 |
|
#č z jakéhokoliv důvodu |
|
1317 |
|
try: |
|
1318 |
|
proposal_filename = self.dice_box.guessbox.filename |
|
1319 |
|
if proposal_filename: |
|
1320 |
|
proposal_filename += '.xlsx' |
|
1321 |
|
else: |
|
1322 |
|
proposal_filename = self.dice_box.gm_signature + '.xlsx' |
|
1323 |
|
filename, *__ = pg.FileDialog.getSaveFileName(self.stream, 'Export to Excel',\ |
|
1324 |
|
proposal_filename, initialFilter='*.xlsx') |
|
1325 |
|
self.df.to_excel(filename) |
|
1326 |
|
except BaseException as e: |
|
1327 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
1328 |
|
|
|
1329 |
|
|
|
1330 |
|
def recalculate(self): |
|
1331 |
|
try: |
|
1332 |
|
# sources=['box', 'user'] |
|
1333 |
|
sources = list() |
|
1334 |
|
if self.TRI_overall_chk.isChecked(): |
|
1335 |
|
sources.append('box') |
|
1336 |
|
if self.simplex_chk.isChecked(): |
|
1337 |
|
sources.append('user') |
|
1338 |
|
|
|
1339 |
|
self.df = stm_df.get_tri_data_frame(self.dice_box, sources=sources,\ |
|
1340 |
|
apply_proxy=self.proxy_chk.isChecked()) |
|
1341 |
|
self.simplex_estimation_updated.emit() |
|
1342 |
|
|
|
1343 |
|
except BaseException as e: |
|
1344 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
1345 |
|
|
|
1346 |
|
|
|
1347 |
|
|
|
1348 |
|
class SimplexEstimationGraph(pg.PlotWidget): |
|
1349 |
|
def __init__(self, dice_box, stream=None, parent=None, *args, **kwargs): |
|
1350 |
|
super().__init__(parent, *args, **kwargs) |
|
1351 |
|
#č je zřejmě, že tím potokem bylo myšleno hlavní okínko |
|
1352 |
|
#č asi aby nepadalo, když nenajde signaly |
|
1353 |
|
self.stream = stream |
|
1354 |
|
if stream is not None: |
|
1355 |
|
self.stream.box_runned.connect(self.redraw) |
|
1356 |
|
self.stream.estimation_added.connect(self.redraw) |
|
1357 |
|
|
|
1358 |
|
self.dice_box = dice_box |
|
1359 |
|
|
|
1360 |
|
self.setup_context_menu() |
|
1361 |
|
self.setup() |
|
1362 |
|
self.replot() |
|
1363 |
|
|
|
1364 |
|
def setup_context_menu(self): |
|
1365 |
|
# creates instance of LegendItem |
|
1366 |
|
# and saves it into plotItem.legend |
|
1367 |
|
self.legend = self.addLegend() |
|
1368 |
|
|
|
1369 |
|
self.plotItem.ctrl.xGridCheck.setChecked(True) |
|
1370 |
|
self.plotItem.ctrl.yGridCheck.setChecked(True) |
|
1371 |
|
|
|
1372 |
|
# delete build-in Transforms (with Log_x and Log_y) options, |
|
1373 |
|
# they can cause uncachable exception (on any zero in data) and crash |
|
1374 |
|
self.plotItem.ctrlMenu.removeAction(self.plotItem.ctrlMenu.actions()[0]) |
|
1375 |
|
|
|
1376 |
|
#č já se bojím. radší to uložím |
|
1377 |
|
self.custom_menu = self.plotItem.vb.menu.addMenu("TRI options") |
|
1378 |
|
|
|
1379 |
|
self.plotItem.vb.menu.addMenu(self.stream.simplex_data.TRI_menu) |
|
1380 |
|
|
|
1381 |
|
self.legend_chk = QtGui.QAction("Legend", self.custom_menu) |
|
1382 |
|
self.legend_chk.setCheckable(True) |
|
1383 |
|
self.legend_chk.triggered.connect(lambda: self.legend.setVisible(self.legend_chk.isChecked())) |
|
1384 |
|
self.custom_menu.addAction(self.legend_chk) |
|
1385 |
|
# apply custom menu option |
|
1386 |
|
self.legend.setVisible(self.legend_chk.isChecked()) |
|
1387 |
|
|
|
1388 |
|
self.log_x_chk = QtGui.QAction("Log X", self.custom_menu) |
|
1389 |
|
self.log_x_chk.setCheckable(True) |
|
1390 |
|
self.log_x_chk.triggered.connect(lambda: self.setLogMode(x=self.log_x_chk.isChecked())) |
|
1391 |
|
self.custom_menu.addAction(self.log_x_chk) |
|
1392 |
|
|
|
1393 |
|
self.log_y_chk = QtGui.QAction("Log Y", self.custom_menu) |
|
1394 |
|
self.log_y_chk.setCheckable(True) |
|
1395 |
|
self.log_y_chk.setChecked(True) |
|
1396 |
|
self.log_y_chk.triggered.connect(self.replot) |
|
1397 |
|
self.custom_menu.addAction(self.log_y_chk) |
|
1398 |
|
|
|
1399 |
|
self.laction = QtGui.QAction("Show labels", self.custom_menu) |
|
1400 |
|
self.laction.triggered.connect(self.show_labels) |
|
1401 |
|
self.custom_menu.addAction(self.laction) |
|
1402 |
|
|
|
1403 |
|
|
|
1404 |
|
def show_labels(self): |
|
1405 |
|
self.setLabel('left', "Probability measure") |
|
1406 |
|
self.setLabel('bottom', "Number of simulations") |
|
1407 |
|
|
|
1408 |
|
|
|
1409 |
|
|
|
1410 |
|
# self.legend.addItem(self.pen_success, "success domain estimation") |
|
1411 |
|
# self.legend.addItem(self.pen_outside, "out of sampling domain estimation") |
|
1412 |
|
# self.legend.addItem(self.pen_mix, "mixed simplices measure") |
|
1413 |
|
# self.legend.addItem(self.pen_f, "failure domain estimation") |
|
1414 |
|
|
|
1415 |
|
def setup(self, *args, **kwargs): |
|
1416 |
|
self.clear() |
|
1417 |
|
self.setBackground('w') |
|
1418 |
|
x = y = () # zde jen vytvoříme kostru, nakrmime daty v .redraw() |
|
1419 |
|
|
|
1420 |
|
#xkcd_green = (167, 255, 181) # xkcd:light seafoam green #a7ffb5 |
|
1421 |
|
green = (0, 255, 38, 96) |
|
1422 |
|
#xkcd_red = (253, 193, 197) # xkcd: pale rose (#fdc1c5) |
|
1423 |
|
red = (253, 0, 17, 96) |
|
1424 |
|
#xkcd_cream = (255, 243, 154) # let's try xkcd: dark cream (#fff39a) |
|
1425 |
|
cream = (255, 221, 0, 96) |
|
1426 |
|
grey = (196, 196, 196, 96) |
|
1427 |
|
|
|
1428 |
|
self.pen_f = self.plot(x, y, brush=red)#, name="failure domain estimation") |
|
1429 |
|
self.pen_f.setZValue(-100) |
|
1430 |
|
|
|
1431 |
|
self.pen_success = self.plot(x, y, brush=green) #, name="success domain estimation") |
|
1432 |
|
self.pen_success.setZValue(-100) |
|
1433 |
|
|
|
1434 |
|
self.pen_outmix = self.plot(x, y) |
|
1435 |
|
|
|
1436 |
|
self.fill_mix = pg.FillBetweenItem(self.pen_f, self.pen_outmix) |
|
1437 |
|
#self.fill_mix.setData(name="mixed simplices measure") |
|
1438 |
|
self.fill_mix.setBrush(cream) |
|
1439 |
|
self.fill_mix.setZValue(-100) |
|
1440 |
|
self.addItem(self.fill_mix) |
|
1441 |
|
|
|
1442 |
|
#self.pen_outside = self.plot(x, y) |
|
1443 |
|
self.fill_outside = pg.FillBetweenItem(self.pen_outmix, self.pen_success) |
|
1444 |
|
#self.fill_outside.setData(name="out of sampling domain estimation") |
|
1445 |
|
self.fill_outside.setBrush(grey) |
|
1446 |
|
self.fill_outside.setZValue(-100) |
|
1447 |
|
self.addItem(self.fill_outside) |
|
1448 |
|
|
|
1449 |
|
self.one_ruler = self.addLine(y=1, pen='k') |
|
1450 |
|
self.zero_ruler = self.addLine(y=0, pen='k') |
|
1451 |
|
|
|
1452 |
|
|
|
1453 |
|
try: |
|
1454 |
|
exact_name = self.dice_box.pf_exact_method |
|
1455 |
|
pen = pg.mkPen(color='b', width=1.5) # blue |
|
1456 |
|
self.pen_exact = self.addLine(y=self.dice_box.pf_exact, pen=pen, name=exact_name) |
|
1457 |
|
#č aby se nám něco zobrazovalo v legendu |
|
1458 |
|
self.pen_exact_PR = self.plot(x, y, pen=pen, name=exact_name) |
|
1459 |
|
except: |
|
1460 |
|
pass |
|
1461 |
|
|
|
1462 |
|
pen = pg.mkPen(color='m', width=2) |
|
1463 |
|
self.pen_vertex = self.plot(x, y, pen=pen, name="simple pf estimation") |
|
1464 |
|
pen = pg.mkPen(color='r', width=2) #(118, 187, 255) |
|
1465 |
|
self.pen_weighted_vertex = self.plot(x, y, pen=pen, name="weighted pf estimation") |
|
1466 |
|
|
|
1467 |
|
|
|
1468 |
|
|
|
1469 |
|
|
|
1470 |
|
|
|
1471 |
|
def replot(self, *args, **kwargs): |
|
1472 |
|
if self.log_y_chk.isChecked(): |
|
1473 |
|
self.one_ruler.hide() |
|
1474 |
|
try: |
|
1475 |
|
#č try nás nezáchraní protí odloženému spádnutí pyqtgraph |
|
1476 |
|
if self.dice_box.pf_exact > 0: |
|
1477 |
|
self.pen_exact.setPos(np.log10(self.dice_box.pf_exact)) |
|
1478 |
|
self.pen_exact.show() |
|
1479 |
|
else: |
|
1480 |
|
self.pen_exact.hide() |
|
1481 |
|
except: |
|
1482 |
|
pass |
|
1483 |
|
self.setLogMode(y=True) |
|
1484 |
|
#self.pen_f.setPen(pg.mkPen(color=(255, 0, 0), width=3)) #, style=QtCore.Qt.DashLine) |
|
1485 |
|
self.pen_f.setPen(None) |
|
1486 |
|
self.pen_f.setFillLevel(None) |
|
1487 |
|
self.pen_success.setFillLevel(0) |
|
1488 |
|
|
|
1489 |
|
else: |
|
1490 |
|
self.one_ruler.show() |
|
1491 |
|
try: |
|
1492 |
|
self.pen_exact.setPos(self.dice_box.pf_exact) |
|
1493 |
|
self.pen_exact.show() |
|
1494 |
|
except: |
|
1495 |
|
pass |
|
1496 |
|
self.setLogMode(y=False) |
|
1497 |
|
self.pen_f.setPen(None) |
|
1498 |
|
self.pen_f.setFillLevel(0) |
|
1499 |
|
self.pen_success.setFillLevel(1) |
|
1500 |
|
|
|
1501 |
|
self.redraw() |
|
1502 |
|
|
|
1503 |
|
|
|
1504 |
|
#č když se někde objeví nula se zapnutým LogModem - |
|
1505 |
|
#č qtpygraph hned spadne a není možne ten pad zachytit |
|
1506 |
|
def zerosafe(self, x, y, fallback_y=None): |
|
1507 |
|
if self.log_y_chk.isChecked(): |
|
1508 |
|
x = np.array(x) |
|
1509 |
|
y = np.array(y) |
|
1510 |
|
if fallback_y is None: |
|
1511 |
|
fallback_y = y |
|
1512 |
|
y = np.where(y > 0, y, fallback_y) |
|
1513 |
|
mask = y > 0 |
|
1514 |
|
return x[mask], y[mask] |
|
1515 |
|
else: |
|
1516 |
|
return x, y |
|
1517 |
|
|
|
1518 |
|
def proxy(self, nsim): |
|
1519 |
|
if self.proxy_chk.isChecked(): |
|
1520 |
|
proxy = self.dice_box.proxy |
|
1521 |
|
index = np.array(nsim)-1 |
|
1522 |
|
#č indexy musíme o jedničku změnšit |
|
1523 |
|
#č výsledek nikoliv. Takže v cajku. |
|
1524 |
|
return np.cumsum(~proxy)[index] |
|
1525 |
|
else: |
|
1526 |
|
return nsim |
|
1527 |
|
|
|
1528 |
|
|
|
1529 |
|
def _pens_data_update(self): |
|
1530 |
|
df = self.df |
|
1531 |
|
nsim = df.nsim.to_numpy() |
|
1532 |
|
if self.proxy_chk.isChecked(): |
|
1533 |
|
x = self.proxy(nsim) |
|
1534 |
|
df.insert(loc=0, column='nsim (proxy)', value=x) |
|
1535 |
|
else: |
|
1536 |
|
x = nsim |
|
1537 |
|
# (in case of LogPlot) fallback values also used |
|
1538 |
|
success_values = df.failure+df.mix+df.out |
|
1539 |
|
outmix_values = df.failure+df.mix |
|
1540 |
|
failure_fallback = np.where(outmix_values > 0, outmix_values, success_values) |
|
1541 |
|
self.pen_f.setData(*self.zerosafe(x, df.failure, failure_fallback)) |
|
1542 |
|
self.pen_outmix.setData(*self.zerosafe(x, outmix_values, success_values)) |
|
1543 |
|
self.pen_success.setData(*self.zerosafe(x, success_values)) |
|
1544 |
|
|
|
1545 |
|
|
|
1546 |
|
def redraw(self): |
|
1547 |
|
xmin = np.inf |
|
1548 |
|
xmax = -np.inf |
|
1549 |
|
tri_estimation = dict() |
|
1550 |
|
try: # тут всё что угодно может пойти не так |
|
1551 |
|
# kruci, ještě navic i generovať pokažde znovu... |
|
1552 |
|
|
|
1553 |
|
# new-style: šecko leží dohromady a každý si z toho |
|
1554 |
|
# bere co chce a jak chce |
|
1555 |
|
# ne že by to bylo nějak šetrný |
|
1556 |
|
# estimation je slovníkem |
|
1557 |
|
for estimation in self.dice_box.estimations: |
|
1558 |
|
# nsim musí mäť každej odhad |
|
1559 |
|
# pokud nemá - je třeba jej prostě opravit |
|
1560 |
|
nsim = estimation['nsim'] |
|
1561 |
|
try: |
|
1562 |
|
tri_estimation[nsim] = estimation['TRI_estimation'] |
|
1563 |
|
if nsim > xmax: |
|
1564 |
|
xmax = nsim |
|
1565 |
|
if nsim < xmin: |
|
1566 |
|
xmin = nsim |
|
1567 |
|
|
|
1568 |
|
except KeyError as e: |
|
1569 |
|
pass #print(self.__class__.__name__ + ":", repr(e)) |
|
1570 |
|
|
|
1571 |
|
#č neotravuj uživatele chybovejma hlaškama |
|
1572 |
|
if tri_estimation: |
|
1573 |
|
# it can be effectively done with pandas |
|
1574 |
|
self.df = df = pd.DataFrame(tuple(tri_estimation.values())) |
|
1575 |
|
# -1 = 'out', 0=success, 1=failure, 2=mix |
|
1576 |
|
df.rename(columns={-1:'out', 0:'success', 1:'failure', 2:'mix'}, inplace=True) |
|
1577 |
|
df.insert(loc=0, column='nsim', value=tuple(tri_estimation.keys()), allow_duplicates=False) |
|
1578 |
|
df.sort_values('nsim', inplace=True) |
|
1579 |
|
|
|
1580 |
|
self._pens_data_update() |
|
1581 |
|
|
|
1582 |
|
nsim, y = get_estimation_data(self.dice_box.estimations, 'vertex_estimation') |
|
1583 |
|
df['vertex_estimation'] = y #č spolehám na konzistenci odhadů (ne úplně) |
|
1584 |
|
self.pen_vertex.setData(*self.zerosafe(self.proxy(nsim), y)) |
|
1585 |
|
|
|
1586 |
|
nsim, y = get_estimation_data(self.dice_box.estimations, 'weighted_vertex_estimation') |
|
1587 |
|
df['weighted_vertex_estimation'] = y #č spolehám na konzistenci odhadů (ne úplně) |
|
1588 |
|
self.pen_weighted_vertex.setData(*self.zerosafe(self.proxy(nsim), y)) |
|
1589 |
|
|
|
1590 |
|
|
|
1591 |
|
except BaseException as e: |
|
1592 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
1593 |
|
|
|
1594 |
|
|
|
1595 |
|
|
|
1596 |
|
class SimplexErrorGraph(pg.PlotWidget): |
|
1597 |
|
def __init__(self, simplex_data, parent=None, *args, **kwargs): |
|
1598 |
|
super().__init__(parent, *args, **kwargs) |
|
1599 |
|
self.simplex_data = simplex_data |
|
1600 |
|
self.simplex_data.simplex_estimation_updated.connect(self.redraw) |
|
1601 |
|
|
|
1602 |
|
self.setup_context_menu() |
|
1603 |
|
self.setup() |
|
1604 |
|
|
|
1605 |
|
def setup_context_menu(self): |
|
1606 |
|
# creates instance of LegendItem |
|
1607 |
|
# and saves it into plotItem.legend |
|
1608 |
|
self.legend = self.addLegend() |
|
1609 |
|
|
|
1610 |
|
self.plotItem.ctrl.xGridCheck.setChecked(True) |
|
1611 |
|
self.plotItem.ctrl.yGridCheck.setChecked(True) |
|
1612 |
|
|
|
1613 |
|
# menu of SimplexEstimationData |
|
1614 |
|
self.plotItem.vb.menu.addMenu(self.simplex_data.TRI_menu) |
|
1615 |
|
|
|
1616 |
|
#č já se bojím. radší to uložím |
|
1617 |
|
self.custom_menu = self.plotItem.vb.menu.addMenu("Error graph") |
|
1618 |
|
|
|
1619 |
|
self.legend_chk = QtGui.QAction("Legend", self.custom_menu) |
|
1620 |
|
self.legend_chk.setCheckable(True) |
|
1621 |
|
self.legend_chk.triggered.connect(lambda: self.legend.setVisible(self.legend_chk.isChecked())) |
|
1622 |
|
self.custom_menu.addAction(self.legend_chk) |
|
1623 |
|
# apply custom menu option |
|
1624 |
|
self.legend.setVisible(self.legend_chk.isChecked()) |
|
1625 |
|
|
|
1626 |
|
self.laction = QtGui.QAction("Show labels", self.custom_menu) |
|
1627 |
|
self.laction.triggered.connect(self.show_labels) |
|
1628 |
|
self.custom_menu.addAction(self.laction) |
|
1629 |
|
|
|
1630 |
|
|
|
1631 |
|
def show_labels(self): |
|
1632 |
|
self.setLabel('left', "Failure probability estimation error") |
|
1633 |
|
self.setLabel('bottom', "Number of simulations") |
|
1634 |
|
|
|
1635 |
|
|
|
1636 |
|
def setup(self, *args, **kwargs): |
|
1637 |
|
self.clear() |
|
1638 |
|
self.setBackground('w') |
|
1639 |
|
x = y = () # zde jen vytvoříme kostru, nakrmime daty v .redraw() |
|
1640 |
|
|
|
1641 |
|
# We will use logMode by default |
|
1642 |
|
self.setLogMode(y=True) |
|
1643 |
|
|
|
1644 |
|
#xkcd_red = (253, 193, 197) # xkcd: pale rose (#fdc1c5) |
|
1645 |
|
#red = (253, 0, 17, 96) |
|
1646 |
|
|
|
1647 |
|
#self.pen_f = self.plot(x, y, brush=red)#, name="failure domain estimation") |
|
1648 |
|
#self.pen_f.setZValue(-100) |
|
1649 |
|
|
|
1650 |
|
|
|
1651 |
|
pen = pg.mkPen(color='m', width=2) |
|
1652 |
|
self.pen_vertex = self.plot(x, y, pen=pen, name="simple pf estimation") |
|
1653 |
|
pen = pg.mkPen(color='r', width=2) #(118, 187, 255) |
|
1654 |
|
self.pen_weighted_vertex = self.plot(x, y, pen=pen, name="weighted pf estimation") |
|
1655 |
|
|
|
1656 |
|
|
|
1657 |
|
|
|
1658 |
|
#č když se někde objeví nula se zapnutým LogModem - |
|
1659 |
|
#č qtpygraph hned spadne a není možne ten pad zachytit |
|
1660 |
|
def zerosafe(self, x, y, fallback_y=None): |
|
1661 |
|
x = np.array(x) |
|
1662 |
|
y = np.array(y) |
|
1663 |
|
if fallback_y is None: |
|
1664 |
|
fallback_y = y |
|
1665 |
|
y = np.where(y > 0, y, fallback_y) |
|
1666 |
|
mask = y > 0 |
|
1667 |
|
return x[mask], y[mask] |
|
1668 |
|
|
|
1669 |
|
|
|
1670 |
|
def redraw(self): |
|
1671 |
|
#č neotravujme uživatele chybovejma hlaškama |
|
1672 |
|
if hasattr(self.simplex_data.dice_box, 'pf_exact'): |
|
1673 |
|
try: #ё тут всё что угодно может пойти не так |
|
1674 |
|
pf_exact = self.simplex_data.dice_box.pf_exact |
|
1675 |
|
|
|
1676 |
|
df = self.simplex_data.df |
|
1677 |
|
#č zapíšeme do data rámu, snad nikomu nebude vadit |
|
1678 |
|
df['vertex_estimation_error'] = df['vertex_estimation'] - pf_exact |
|
1679 |
|
df['weighted_vertex_estimation_error'] = df['weighted_vertex_estimation'] - pf_exact |
|
1680 |
|
|
|
1681 |
|
v = df['vertex_estimation_error'].abs() |
|
1682 |
|
wv = df['weighted_vertex_estimation_error'].abs() |
|
1683 |
|
|
|
1684 |
|
x, y = self.zerosafe(v.index, v.to_numpy()) |
|
1685 |
|
self.pen_vertex.setData(x, y) |
|
1686 |
|
|
|
1687 |
|
x, y = self.zerosafe(wv.index, wv.to_numpy()) |
|
1688 |
|
self.pen_weighted_vertex.setData(x, y) |
|
1689 |
|
|
|
1690 |
|
|
|
1691 |
|
except BaseException as e: |
|
1692 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
1693 |
|
|
|
1694 |
|
|
|
1695 |
|
|
|
1696 |
|
|
|
1697 |
|
|
|
1698 |
|
|
|
1699 |
|
|
|
1700 |
|
# DEPRECATED |
|
1701 |
|
class SimpleSimplexEstimationGraph(pg.PlotWidget): |
|
1702 |
|
def __init__(self, dice_box, stream=None, parent=None, *args, **kwargs): |
|
1703 |
|
super().__init__(parent, *args, **kwargs) |
|
1704 |
|
#č je zřejmě, že tím potokem bylo myšleno hlavní okínko |
|
1705 |
|
#č asi aby nepadalo, když nenajde signaly |
|
1706 |
|
self.stream = stream |
|
1707 |
|
if stream is not None: |
|
1708 |
|
self.stream.box_runned.connect(self.redraw) |
|
1709 |
|
self.stream.estimation_added.connect(self.redraw) |
|
1710 |
|
|
|
1711 |
|
self.dice_box = dice_box |
|
1712 |
|
|
|
1713 |
|
self.setup_context_menu() |
|
1714 |
|
self.setup() |
|
1715 |
|
self.replot() |
|
1716 |
|
|
|
1717 |
|
def setup_context_menu(self): |
|
1718 |
|
# creates instance of LegendItem |
|
1719 |
|
# and saves it into plotItem.legend |
|
1720 |
|
self.legend = self.addLegend() |
|
1721 |
|
|
|
1722 |
|
self.plotItem.ctrl.xGridCheck.setChecked(True) |
|
1723 |
|
self.plotItem.ctrl.yGridCheck.setChecked(True) |
|
1724 |
|
|
|
1725 |
|
# delete build-in Transforms (with Log_x and Log_y) options, |
|
1726 |
|
# they can cause uncachable exception (on any zero in data) and crash |
|
1727 |
|
self.plotItem.ctrlMenu.removeAction(self.plotItem.ctrlMenu.actions()[0]) |
|
1728 |
|
|
|
1729 |
|
#č já se bojím. radší to uložím |
|
1730 |
|
self.custom_menu = self.plotItem.vb.menu.addMenu("TRI options") |
|
1731 |
|
|
|
1732 |
|
self.legend_chk = QtGui.QAction("Legend", self.custom_menu) |
|
1733 |
|
self.legend_chk.setCheckable(True) |
|
1734 |
|
self.legend_chk.triggered.connect(lambda: self.legend.setVisible(self.legend_chk.isChecked())) |
|
1735 |
|
self.custom_menu.addAction(self.legend_chk) |
|
1736 |
|
# apply custom menu option |
|
1737 |
|
self.legend.setVisible(self.legend_chk.isChecked()) |
|
1738 |
|
|
|
1739 |
|
self.proxy_chk = QtGui.QAction("Proxy", self.custom_menu) |
|
1740 |
|
self.proxy_chk.setCheckable(True) |
|
1741 |
|
self.proxy_chk.triggered.connect(self.redraw) |
|
1742 |
|
self.custom_menu.addAction(self.proxy_chk) |
|
1743 |
|
|
|
1744 |
|
self.log_x_chk = QtGui.QAction("Log X", self.custom_menu) |
|
1745 |
|
self.log_x_chk.setCheckable(True) |
|
1746 |
|
self.log_x_chk.triggered.connect(lambda: self.setLogMode(x=self.log_x_chk.isChecked())) |
|
1747 |
|
self.custom_menu.addAction(self.log_x_chk) |
|
1748 |
|
|
|
1749 |
|
self.log_y_chk = QtGui.QAction("Log Y", self.custom_menu) |
|
1750 |
|
self.log_y_chk.setCheckable(True) |
|
1751 |
|
self.log_y_chk.setChecked(True) |
|
1752 |
|
self.log_y_chk.triggered.connect(self.replot) |
|
1753 |
|
self.custom_menu.addAction(self.log_y_chk) |
|
1754 |
|
|
|
1755 |
|
self.reaction = QtGui.QAction("Redraw", self.custom_menu) |
|
1756 |
|
self.reaction.triggered.connect(self.redraw) |
|
1757 |
|
self.custom_menu.addAction(self.reaction) |
|
1758 |
|
|
|
1759 |
|
self.laction = QtGui.QAction("Show labels", self.custom_menu) |
|
1760 |
|
self.laction.triggered.connect(self.show_labels) |
|
1761 |
|
self.custom_menu.addAction(self.laction) |
|
1762 |
|
|
|
1763 |
|
self.excelaction = QtGui.QAction("Export to Excel", self.custom_menu) |
|
1764 |
|
self.excelaction.triggered.connect(self.export_to_excel) |
|
1765 |
|
self.custom_menu.addAction(self.excelaction) |
|
1766 |
|
|
|
1767 |
|
|
|
1768 |
|
def export_to_excel(self): |
|
1769 |
|
#č já bych nechtěl, aby mně export najednou spadl |
|
1770 |
|
#č z jakéhokoliv důvodu |
|
1771 |
|
try: |
|
1772 |
|
proposal_filename = self.dice_box.guessbox.filename |
|
1773 |
|
if proposal_filename: |
|
1774 |
|
proposal_filename += '.xlsx' |
|
1775 |
|
else: |
|
1776 |
|
proposal_filename = self.dice_box.gm_signature + '.xlsx' |
|
1777 |
|
filename, *__ = pg.FileDialog.getSaveFileName(self, 'Export to Excel',\ |
|
1778 |
|
proposal_filename, initialFilter='*.xlsx') |
|
1779 |
|
self.df.to_excel(filename) |
|
1780 |
|
except BaseException as e: |
|
1781 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
1782 |
|
|
|
1783 |
|
def show_labels(self): |
|
1784 |
|
self.setLabel('left', "Probability measure") |
|
1785 |
|
self.setLabel('bottom', "Number of simulations") |
|
1786 |
|
|
|
1787 |
|
|
|
1788 |
|
|
|
1789 |
|
# self.legend.addItem(self.pen_success, "success domain estimation") |
|
1790 |
|
# self.legend.addItem(self.pen_outside, "out of sampling domain estimation") |
|
1791 |
|
# self.legend.addItem(self.pen_mix, "mixed simplices measure") |
|
1792 |
|
# self.legend.addItem(self.pen_f, "failure domain estimation") |
|
1793 |
|
|
|
1794 |
|
def setup(self, *args, **kwargs): |
|
1795 |
|
self.clear() |
|
1796 |
|
self.setBackground('w') |
|
1797 |
|
x = y = () # zde jen vytvoříme kostru, nakrmime daty v .redraw() |
|
1798 |
|
|
|
1799 |
|
#xkcd_green = (167, 255, 181) # xkcd:light seafoam green #a7ffb5 |
|
1800 |
|
green = (0, 255, 38, 96) |
|
1801 |
|
#xkcd_red = (253, 193, 197) # xkcd: pale rose (#fdc1c5) |
|
1802 |
|
red = (253, 0, 17, 96) |
|
1803 |
|
#xkcd_cream = (255, 243, 154) # let's try xkcd: dark cream (#fff39a) |
|
1804 |
|
cream = (255, 221, 0, 96) |
|
1805 |
|
grey = (196, 196, 196, 96) |
|
1806 |
|
|
|
1807 |
|
self.pen_f = self.plot(x, y, brush=red)#, name="failure domain estimation") |
|
1808 |
|
self.pen_f.setZValue(-100) |
|
1809 |
|
|
|
1810 |
|
self.pen_success = self.plot(x, y, brush=green) #, name="success domain estimation") |
|
1811 |
|
self.pen_success.setZValue(-100) |
|
1812 |
|
|
|
1813 |
|
self.pen_outmix = self.plot(x, y) |
|
1814 |
|
|
|
1815 |
|
self.fill_mix = pg.FillBetweenItem(self.pen_f, self.pen_outmix) |
|
1816 |
|
#self.fill_mix.setData(name="mixed simplices measure") |
|
1817 |
|
self.fill_mix.setBrush(cream) |
|
1818 |
|
self.fill_mix.setZValue(-100) |
|
1819 |
|
self.addItem(self.fill_mix) |
|
1820 |
|
|
|
1821 |
|
#self.pen_outside = self.plot(x, y) |
|
1822 |
|
self.fill_outside = pg.FillBetweenItem(self.pen_outmix, self.pen_success) |
|
1823 |
|
#self.fill_outside.setData(name="out of sampling domain estimation") |
|
1824 |
|
self.fill_outside.setBrush(grey) |
|
1825 |
|
self.fill_outside.setZValue(-100) |
|
1826 |
|
self.addItem(self.fill_outside) |
|
1827 |
|
|
|
1828 |
|
self.one_ruler = self.addLine(y=1, pen='k') |
|
1829 |
|
self.zero_ruler = self.addLine(y=0, pen='k') |
|
1830 |
|
|
|
1831 |
|
|
|
1832 |
|
try: |
|
1833 |
|
exact_name = self.dice_box.pf_exact_method |
|
1834 |
|
pen = pg.mkPen(color='b', width=1.5) # blue |
|
1835 |
|
self.pen_exact = self.addLine(y=self.dice_box.pf_exact, pen=pen, name=exact_name) |
|
1836 |
|
#č aby se nám něco zobrazovalo v legendu |
|
1837 |
|
self.pen_exact_PR = self.plot(x, y, pen=pen, name=exact_name) |
|
1838 |
|
except: |
|
1839 |
|
pass |
|
1840 |
|
|
|
1841 |
|
pen = pg.mkPen(color='m', width=2) |
|
1842 |
|
self.pen_vertex = self.plot(x, y, pen=pen, name="simple pf estimation") |
|
1843 |
|
pen = pg.mkPen(color='r', width=2) #(118, 187, 255) |
|
1844 |
|
self.pen_weighted_vertex = self.plot(x, y, pen=pen, name="weighted pf estimation") |
|
1845 |
|
|
|
1846 |
|
|
|
1847 |
|
|
|
1848 |
|
|
|
1849 |
|
|
|
1850 |
|
def replot(self, *args, **kwargs): |
|
1851 |
|
if self.log_y_chk.isChecked(): |
|
1852 |
|
self.one_ruler.hide() |
|
1853 |
|
try: |
|
1854 |
|
#č try nás nezáchraní protí odloženému spádnutí pyqtgraph |
|
1855 |
|
if self.dice_box.pf_exact > 0: |
|
1856 |
|
self.pen_exact.setPos(np.log10(self.dice_box.pf_exact)) |
|
1857 |
|
self.pen_exact.show() |
|
1858 |
|
else: |
|
1859 |
|
self.pen_exact.hide() |
|
1860 |
|
except: |
|
1861 |
|
pass |
|
1862 |
|
self.setLogMode(y=True) |
|
1863 |
|
#self.pen_f.setPen(pg.mkPen(color=(255, 0, 0), width=3)) #, style=QtCore.Qt.DashLine) |
|
1864 |
|
self.pen_f.setPen(None) |
|
1865 |
|
self.pen_f.setFillLevel(None) |
|
1866 |
|
self.pen_success.setFillLevel(0) |
|
1867 |
|
|
|
1868 |
|
else: |
|
1869 |
|
self.one_ruler.show() |
|
1870 |
|
try: |
|
1871 |
|
self.pen_exact.setPos(self.dice_box.pf_exact) |
|
1872 |
|
self.pen_exact.show() |
|
1873 |
|
except: |
|
1874 |
|
pass |
|
1875 |
|
self.setLogMode(y=False) |
|
1876 |
|
self.pen_f.setPen(None) |
|
1877 |
|
self.pen_f.setFillLevel(0) |
|
1878 |
|
self.pen_success.setFillLevel(1) |
|
1879 |
|
|
|
1880 |
|
self.redraw() |
|
1881 |
|
|
|
1882 |
|
|
|
1883 |
|
#č když se někde objeví nula se zapnutým LogModem - |
|
1884 |
|
#č qtpygraph hned spadne a není možne ten pad zachytit |
|
1885 |
|
def zerosafe(self, x, y, fallback_y=None): |
|
1886 |
|
if self.log_y_chk.isChecked(): |
|
1887 |
|
x = np.array(x) |
|
1888 |
|
y = np.array(y) |
|
1889 |
|
if fallback_y is None: |
|
1890 |
|
fallback_y = y |
|
1891 |
|
y = np.where(y > 0, y, fallback_y) |
|
1892 |
|
mask = y > 0 |
|
1893 |
|
return x[mask], y[mask] |
|
1894 |
|
else: |
|
1895 |
|
return x, y |
|
1896 |
|
|
|
1897 |
|
def proxy(self, nsim): |
|
1898 |
|
if self.proxy_chk.isChecked(): |
|
1899 |
|
proxy = self.dice_box.proxy |
|
1900 |
|
index = np.array(nsim)-1 |
|
1901 |
|
#č indexy musíme o jedničku změnšit |
|
1902 |
|
#č výsledek nikoliv. Takže v cajku. |
|
1903 |
|
return np.cumsum(~proxy)[index] |
|
1904 |
|
else: |
|
1905 |
|
return nsim |
|
1906 |
|
|
|
1907 |
|
|
|
1908 |
|
def _pens_data_update(self): |
|
1909 |
|
df = self.df |
|
1910 |
|
nsim = df.nsim.to_numpy() |
|
1911 |
|
if self.proxy_chk.isChecked(): |
|
1912 |
|
x = self.proxy(nsim) |
|
1913 |
|
df.insert(loc=0, column='nsim (proxy)', value=x) |
|
1914 |
|
else: |
|
1915 |
|
x = nsim |
|
1916 |
|
# (in case of LogPlot) fallback values also used |
|
1917 |
|
success_values = df.failure+df.mix+df.out |
|
1918 |
|
outmix_values = df.failure+df.mix |
|
1919 |
|
failure_fallback = np.where(outmix_values > 0, outmix_values, success_values) |
|
1920 |
|
self.pen_f.setData(*self.zerosafe(x, df.failure, failure_fallback)) |
|
1921 |
|
self.pen_outmix.setData(*self.zerosafe(x, outmix_values, success_values)) |
|
1922 |
|
self.pen_success.setData(*self.zerosafe(x, success_values)) |
|
1923 |
|
|
|
1924 |
|
|
|
1925 |
|
def redraw(self): |
|
1926 |
|
xmin = np.inf |
|
1927 |
|
xmax = -np.inf |
|
1928 |
|
tri_estimation = dict() |
|
1929 |
|
try: # тут всё что угодно может пойти не так |
|
1930 |
|
# kruci, ještě navic i generovať pokažde znovu... |
|
1931 |
|
|
|
1932 |
|
# new-style: šecko leží dohromady a každý si z toho |
|
1933 |
|
# bere co chce a jak chce |
|
1934 |
|
# ne že by to bylo nějak šetrný |
|
1935 |
|
# estimation je slovníkem |
|
1936 |
|
for estimation in self.dice_box.estimations: |
|
1937 |
|
# nsim musí mäť každej odhad |
|
1938 |
|
# pokud nemá - je třeba jej prostě opravit |
|
1939 |
|
nsim = estimation['nsim'] |
|
1940 |
|
try: |
|
1941 |
|
tri_estimation[nsim] = estimation['TRI_estimation'] |
|
1942 |
|
if nsim > xmax: |
|
1943 |
|
xmax = nsim |
|
1944 |
|
if nsim < xmin: |
|
1945 |
|
xmin = nsim |
|
1946 |
|
|
|
1947 |
|
except KeyError as e: |
|
1948 |
|
pass #print(self.__class__.__name__ + ":", repr(e)) |
|
1949 |
|
|
|
1950 |
|
#č neotravuj uživatele chybovejma hlaškama |
|
1951 |
|
if tri_estimation: |
|
1952 |
|
# it can be effectively done with pandas |
|
1953 |
|
self.df = df = pd.DataFrame(tuple(tri_estimation.values())) |
|
1954 |
|
# -1 = 'out', 0=success, 1=failure, 2=mix |
|
1955 |
|
df.rename(columns={-1:'out', 0:'success', 1:'failure', 2:'mix'}, inplace=True) |
|
1956 |
|
df.insert(loc=0, column='nsim', value=tuple(tri_estimation.keys()), allow_duplicates=False) |
|
1957 |
|
df.sort_values('nsim', inplace=True) |
|
1958 |
|
|
|
1959 |
|
self._pens_data_update() |
|
1960 |
|
|
|
1961 |
|
nsim, y = get_estimation_data(self.dice_box.estimations, 'vertex_estimation') |
|
1962 |
|
df['vertex_estimation'] = y #č spolehám na konzistenci odhadů (ne úplně) |
|
1963 |
|
self.pen_vertex.setData(*self.zerosafe(self.proxy(nsim), y)) |
|
1964 |
|
|
|
1965 |
|
nsim, y = get_estimation_data(self.dice_box.estimations, 'weighted_vertex_estimation') |
|
1966 |
|
df['weighted_vertex_estimation'] = y #č spolehám na konzistenci odhadů (ne úplně) |
|
1967 |
|
self.pen_weighted_vertex.setData(*self.zerosafe(self.proxy(nsim), y)) |
|
1968 |
|
|
|
1969 |
|
|
|
1970 |
|
except BaseException as e: |
|
1971 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
1972 |
|
|
|
1973 |
|
|
|
1974 |
|
# DEPRECATED |
|
1975 |
|
class TriEstimationGraph(SimpleSimplexEstimationGraph): |
|
1976 |
|
def __init__(self, dice_box, tri_estimation_name='TRI_overall_estimations', stream=None, parent=None, *args, **kwargs): |
|
1977 |
|
self.tri_estimation_name = tri_estimation_name |
|
1978 |
|
super().__init__(dice_box, stream, parent, *args, **kwargs) |
|
1979 |
|
|
|
1980 |
|
|
|
1981 |
|
|
|
1982 |
|
def redraw(self): |
|
1983 |
|
try: # тут всё что угодно может пойти не так |
|
1984 |
|
data = self.dice_box.guessbox.estimations[self.tri_estimation_name] |
|
1985 |
|
nsim, tri_data = data |
|
1986 |
|
# it can be effectively done with pandas |
|
1987 |
|
self.df = df = pd.DataFrame(tri_data) |
|
1988 |
|
# -1 = 'out', 0=success, 1=failure, 2=mix |
|
1989 |
|
df.rename(columns={-1:'out', 0:'success', 1:'failure', 2:'mix'}, inplace=True) |
|
1990 |
|
df.insert(loc=0, column='nsim', value=nsim) |
|
1991 |
|
|
|
1992 |
|
# Update the data |
|
1993 |
|
self._pens_data_update() |
|
1994 |
|
|
|
1995 |
|
if 'vertex_estimation' in self.dice_box.guessbox.estimations: |
|
1996 |
|
data = self.dice_box.guessbox.estimations['vertex_estimation'] |
|
1997 |
|
nsim, y = data |
|
1998 |
|
# Update the data |
|
1999 |
|
#č spolehám na konzistenci blackboxu, ne však úplně |
|
2000 |
|
self.pen_vertex.setData(*self.zerosafe(self.proxy(nsim), np.array(y))) |
|
2001 |
|
df['vertex_estimation'] = y |
|
2002 |
|
|
|
2003 |
|
if 'weighted_vertex_estimation' in self.dice_box.guessbox.estimations: |
|
2004 |
|
data = self.dice_box.guessbox.estimations['weighted_vertex_estimation'] |
|
2005 |
|
nsim, y = data |
|
2006 |
|
# Update the data |
|
2007 |
|
#č spolehám na konzistenci blackboxu, ne však úplně |
|
2008 |
|
self.pen_weighted_vertex.setData(*self.zerosafe(self.proxy(nsim), np.array(y))) |
|
2009 |
|
df['weighted_vertex_estimation'] = y |
|
2010 |
|
|
|
2011 |
|
|
|
2012 |
|
# BaseException |
|
2013 |
|
except BaseException as e: |
|
2014 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
2015 |
|
|
|
2016 |
|
|
|
2017 |
|
|
|
2018 |
|
|
|
2019 |
|
|
|
2020 |
|
|
|
2021 |
|
|
|
2022 |
|
class VoronoiEstimationGraph(pg.PlotWidget): |
|
2023 |
|
def __init__(self, black_box, samplebox_item, parent=None, *args, **kwargs): |
|
2024 |
|
super().__init__(parent) |
|
2025 |
|
self.sb_item = samplebox_item |
|
2026 |
|
self.sb_item.box_runned.connect(self.redraw) |
|
2027 |
|
self.sb_item.estimation_added.connect(self.redraw) |
|
2028 |
|
|
|
2029 |
|
self.black_box = black_box |
|
2030 |
|
self.setBackground('w') |
|
2031 |
|
|
|
2032 |
|
|
|
2033 |
|
self.reaction = QtGui.QAction("Redraw", self.plotItem.ctrlMenu) |
|
2034 |
|
self.reaction.triggered.connect(self.redraw) |
|
2035 |
|
self.plotItem.ctrlMenu.insertAction(self.plotItem.ctrlMenu.actions()[0], self.reaction) |
|
2036 |
|
|
|
2037 |
|
|
|
2038 |
|
|
|
2039 |
|
# implicitně Y je v logaritmickem měřítku |
|
2040 |
|
self.setLogMode(False, True) |
|
2041 |
|
|
|
2042 |
|
x = y = () # zde jen vytvoříme kostru, nakrmíme daty v .redraw() |
|
2043 |
|
|
|
2044 |
|
|
|
2045 |
|
# nechapu, proč těm Itemům ríkám "propíska" |
|
2046 |
|
# propíska? Их есть у нас! |
|
2047 |
|
|
|
2048 |
|
self.Voronoi_2_point_upper_bound = self.plot(x, y, pen='y') |
|
2049 |
|
self.Voronoi_2_point_lower_bound = self.plot(x, y, pen='y') |
|
2050 |
|
|
|
2051 |
|
fill_color = (255, 243, 154) # let's try xkcd: dark cream (#fff39a) |
|
2052 |
|
self.fill = pg.FillBetweenItem(self.Voronoi_2_point_upper_bound, self.Voronoi_2_point_lower_bound, fill_color) |
|
2053 |
|
self.addItem(self.fill) |
|
2054 |
|
|
|
2055 |
|
self.Voronoi_2_point_failure_rate = self.plot(x, y, pen=(195,46,212)) |
|
2056 |
|
self.Voronoi_2_point_pure_failure_rate = self.plot(x, y, pen='m') |
|
2057 |
|
self.Voronoi_failure_rate = self.plot(x, y, pen='r') |
|
2058 |
|
|
|
2059 |
|
self.pen_exact = self.plot(x, y, pen='b') # blue |
|
2060 |
|
self.pen_one = self.plot(x, y, pen='k') # black |
|
2061 |
|
|
|
2062 |
|
self.redraw() |
|
2063 |
|
|
|
2064 |
|
|
|
2065 |
|
def redraw(self): |
|
2066 |
|
# kruci, ještě navic i generovať pokažde znovu... |
|
2067 |
|
metrics = {'Voronoi_2_point_upper_bound':{},\ |
|
2068 |
|
'Voronoi_2_point_lower_bound':{},\ |
|
2069 |
|
'Voronoi_2_point_failure_rate':{},\ |
|
2070 |
|
'Voronoi_2_point_pure_failure_rate':{},\ |
|
2071 |
|
'Voronoi_failure_rate':{},} |
|
2072 |
|
xmin = np.inf |
|
2073 |
|
xmax = -np.inf |
|
2074 |
|
try: # тут всё что угодно может пойти не так |
|
2075 |
|
# new-style: šecko leží dohromady a každý z toho |
|
2076 |
|
# bere co chce a jak chce |
|
2077 |
|
# ne že by to bylo nějak šetrný |
|
2078 |
|
# estimation je slovníkem |
|
2079 |
|
for estimation in self.black_box.estimations: |
|
2080 |
|
# nsim musí mäť každej odhad |
|
2081 |
|
# pokud nemá - je třeba jej prostě opravit |
|
2082 |
|
nsim = estimation['nsim'] |
|
2083 |
|
|
|
2084 |
|
|
|
2085 |
|
for metric, metric_dict in metrics.items(): |
|
2086 |
|
try: |
|
2087 |
|
if estimation[metric] > 0: |
|
2088 |
|
metric_dict[nsim] = estimation[metric] |
|
2089 |
|
if nsim > xmax: |
|
2090 |
|
xmax = nsim |
|
2091 |
|
if nsim < xmin: |
|
2092 |
|
xmin = nsim |
|
2093 |
|
except KeyError as e: |
|
2094 |
|
pass #print(self.__class__.__name__ + ":", repr(e)) |
|
2095 |
|
|
|
2096 |
|
for metric, metric_dict in metrics.items(): |
|
2097 |
|
pen = getattr(self, metric) |
|
2098 |
|
# nikdo neslibil, že budou v pořadí |
|
2099 |
|
x = np.sort(tuple(metric_dict.keys())) |
|
2100 |
|
y = np.array(tuple(metric_dict.values()))[np.argsort(tuple(metric_dict.keys()))] |
|
2101 |
|
pen.setData(x, y) |
|
2102 |
|
|
|
2103 |
|
if (xmax - xmin) > 0: |
|
2104 |
|
self.pen_one.setData((xmin,xmax), (1, 1)) |
|
2105 |
|
if hasattr(self.black_box, 'pf_exact'): |
|
2106 |
|
# poslední. I když spadne, tak už nikomu moc nevadí |
|
2107 |
|
self.pen_exact.setData((xmin,xmax), (self.black_box.pf_exact, self.black_box.pf_exact)) |
|
2108 |
|
|
|
2109 |
|
except BaseException as e: |
|
2110 |
|
print(self.__class__.__name__ + ":", repr(e)) |
|
2111 |
|
|
|
2112 |
|
|
|
2113 |
|
# pen_f.opts['logMode'] |
|
2114 |
|
# pen_outside.setLogMode(False, False) |
|
2115 |
|
#setLogMode(False, False) |
|
2116 |
|
#f = pg.FillBetweenItem(curves[i], curves[i+1], brushes[i]) |
|
2117 |
|
#win.addItem(f) |
|
2118 |
|
|
|
2119 |
|
|
|
2120 |
|
|
|
2121 |
|
|
|
2122 |
|
|
|
2123 |
|
|
|
2124 |
|
|
|
2125 |
863 |
""" |
""" |
2126 |
864 |
============= |
============= |
2127 |
865 |
Эскерон виӝет |
Эскерон виӝет |
|
... |
... |
class CandidatesWidget(pg.LayoutWidget): |
3557 |
2295 |
# pass |
# pass |
3558 |
2296 |
|
|
3559 |
2297 |
|
|
3560 |
|
|
|
3561 |
|
class BoxTreeWidget(pg.LayoutWidget): |
|
3562 |
|
""" |
|
3563 |
|
""" |
|
3564 |
|
# I'd like to get access to the samplebox stuff via the container's reference, |
|
3565 |
|
# but relying to Qt's parent mechanism makes me worry. |
|
3566 |
|
def __init__(self, samplebox_item, parent=None, *args, **kwargs): |
|
3567 |
|
super().__init__(parent) |
|
3568 |
|
# sb like samplebox, of course |
|
3569 |
|
self.sb_item = samplebox_item |
|
3570 |
|
|
|
3571 |
|
|
|
3572 |
|
self.btn = QtGui.QPushButton('update') |
|
3573 |
|
self.addWidget(self.btn, row=0, col=0) |
|
3574 |
|
self.btn.clicked.connect(self.update) |
|
3575 |
|
|
|
3576 |
|
#self.tree = pg.DataTreeWidget(self, data=self.get_data(samplebox_item)) |
|
3577 |
|
self.tree = pg.DataTreeWidget(self, data=dict()) |
|
3578 |
|
self.addWidget(self.tree, row=1, col=0) |
|
3579 |
|
|
|
3580 |
|
def update(self, *args, **kwargs): |
|
3581 |
|
try: |
|
3582 |
|
self.tree.setData(self.get_data(self.sb_item), hideRoot=True) |
|
3583 |
|
except BaseException as e: |
|
3584 |
|
msg = "" |
|
3585 |
|
error_msg = self.__class__.__name__ + ": " + msg + repr(e) |
|
3586 |
|
print(error_msg) |
|
3587 |
|
|
|
3588 |
|
@staticmethod |
|
3589 |
|
def get_data(self): #č nenechej si splest tím "self", je to prostě reference na QtGuiPlot2D |
|
3590 |
|
data_tree = dict() |
|
3591 |
|
data_tree['self.sample_box'] = self.sample_box.__dict__ |
|
3592 |
|
try: # shapeshare |
|
3593 |
|
data_tree['self.sample_box.shapeshare'] = self.sample_box.shapeshare.__dict__ |
|
3594 |
|
except AttributeError: |
|
3595 |
|
pass |
|
3596 |
|
try: |
|
3597 |
|
data_tree['self.sample_box.dicebox'] = self.sample_box.dicebox.__dict__ |
|
3598 |
|
except AttributeError: |
|
3599 |
|
pass |
|
3600 |
|
try: |
|
3601 |
|
data_tree['self.sample_box.reader'] = self.sample_box.reader.__dict__ |
|
3602 |
|
except AttributeError: |
|
3603 |
|
pass |
|
3604 |
|
try: |
|
3605 |
|
data_tree['self.sample_box.samplebox'] = self.sample_box.samplebox.__dict__ |
|
3606 |
|
except AttributeError: |
|
3607 |
|
pass |
|
3608 |
|
try: |
|
3609 |
|
data_tree['self.sample_box.candybox'] = self.sample_box.candybox.__dict__ |
|
3610 |
|
except AttributeError: |
|
3611 |
|
pass |
|
3612 |
|
try: |
|
3613 |
|
data_tree['self.sample_box.f_model'] = self.sample_box.f_model.__dict__ |
|
3614 |
|
except AttributeError: |
|
3615 |
|
pass |
|
3616 |
|
|
|
3617 |
|
return data_tree |
|
3618 |
|
|
|
3619 |
|
|
|
3620 |
2298 |
|
|