pygmi 2.2.7__zip

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. pygmi-2.2.7/LICENSE.txt +623 -0
  2. pygmi-2.2.7/MANIFEST.in +7 -0
  3. pygmi-2.2.7/PKG-INFO +47 -0
  4. pygmi-2.2.7/README.md +55 -0
  5. pygmi-2.2.7/README.rst +20 -0
  6. pygmi-2.2.7/log.txt +242 -0
  7. pygmi-2.2.7/pygmi/__init__.py +22 -0
  8. pygmi-2.2.7/pygmi/clust/__init__.py +4 -0
  9. pygmi-2.2.7/pygmi/clust/crisp_clust.py +708 -0
  10. pygmi-2.2.7/pygmi/clust/datatypes.py +65 -0
  11. pygmi-2.2.7/pygmi/clust/fuzzy_clust.py +906 -0
  12. pygmi-2.2.7/pygmi/clust/graphs.py +421 -0
  13. pygmi-2.2.7/pygmi/clust/graphtool.py +667 -0
  14. pygmi-2.2.7/pygmi/clust/menu.py +139 -0
  15. pygmi-2.2.7/pygmi/clust/var_ratio.py +92 -0
  16. pygmi-2.2.7/pygmi/clust/xie_beni.py +93 -0
  17. pygmi-2.2.7/pygmi/helpdocs/linepointer.png +0 -0
  18. pygmi-2.2.7/pygmi/helpdocs/pygmi.main.html +31 -0
  19. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.ddisp.html +15 -0
  20. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.iodefs.exportkmz.html +13 -0
  21. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.iodefs.importpicture.html +16 -0
  22. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.layer.html +17 -0
  23. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.mext.html +44 -0
  24. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.misc.rangedcopy.html +16 -0
  25. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.param.html +37 -0
  26. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.prof.html +32 -0
  27. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.pview.html +26 -0
  28. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.cooper.gradients.html +14 -0
  29. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.cooper.tilt.html +14 -0
  30. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.cooper.visibility.html +14 -0
  31. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.datagrid.html +13 -0
  32. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.datamerge.html +11 -0
  33. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.datareproj.html +11 -0
  34. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.rtp.html +14 -0
  35. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.ginterp.html +31 -0
  36. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.igrf.html +20 -0
  37. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.normalisation.html +14 -0
  38. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.smooth.html +22 -0
  39. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.tiltdepth.html +20 -0
  40. pygmi-2.2.7/pygmi/images/Help.png +0 -0
  41. pygmi-2.2.7/pygmi/images/bringtofront.png +0 -0
  42. pygmi-2.2.7/pygmi/images/cgs2.emf +0 -0
  43. pygmi-2.2.7/pygmi/images/delete.png +0 -0
  44. pygmi-2.2.7/pygmi/images/linepointer.png +0 -0
  45. pygmi-2.2.7/pygmi/images/logo256.ico +0 -0
  46. pygmi-2.2.7/pygmi/images/logo256.png +0 -0
  47. pygmi-2.2.7/pygmi/images/pointer.png +0 -0
  48. pygmi-2.2.7/pygmi/images/pygmi.png +0 -0
  49. pygmi-2.2.7/pygmi/images/sendtoback.png +0 -0
  50. pygmi-2.2.7/pygmi/main.py +1037 -0
  51. pygmi-2.2.7/pygmi/menu_default.py +327 -0
  52. pygmi-2.2.7/pygmi/misc.py +147 -0
  53. pygmi-2.2.7/pygmi/pfmod/__init__.py +6 -0
  54. pygmi-2.2.7/pygmi/pfmod/cubes.py +1488 -0
  55. pygmi-2.2.7/pygmi/pfmod/datatypes.py +292 -0
  56. pygmi-2.2.7/pygmi/pfmod/grvmag3d.py +1265 -0
  57. pygmi-2.2.7/pygmi/pfmod/iodefs.py +1001 -0
  58. pygmi-2.2.7/pygmi/pfmod/menu.py +107 -0
  59. pygmi-2.2.7/pygmi/pfmod/misc.py +301 -0
  60. pygmi-2.2.7/pygmi/pfmod/pfmod.py +248 -0
  61. pygmi-2.2.7/pygmi/pfmod/tab_ddisp.py +425 -0
  62. pygmi-2.2.7/pygmi/pfmod/tab_layer.py +490 -0
  63. pygmi-2.2.7/pygmi/pfmod/tab_mext.py +544 -0
  64. pygmi-2.2.7/pygmi/pfmod/tab_param.py +548 -0
  65. pygmi-2.2.7/pygmi/pfmod/tab_prof.py +946 -0
  66. pygmi-2.2.7/pygmi/pfmod/tab_pview.py +740 -0
  67. pygmi-2.2.7/pygmi/raster/IGRF11.COF +1635 -0
  68. pygmi-2.2.7/pygmi/raster/__init__.py +14 -0
  69. pygmi-2.2.7/pygmi/raster/cooper.py +718 -0
  70. pygmi-2.2.7/pygmi/raster/dataprep.py +1640 -0
  71. pygmi-2.2.7/pygmi/raster/datatypes.py +123 -0
  72. pygmi-2.2.7/pygmi/raster/equation_editor.py +256 -0
  73. pygmi-2.2.7/pygmi/raster/ginterp.py +1901 -0
  74. pygmi-2.2.7/pygmi/raster/graphs.py +531 -0
  75. pygmi-2.2.7/pygmi/raster/igrf.py +860 -0
  76. pygmi-2.2.7/pygmi/raster/iodefs.py +813 -0
  77. pygmi-2.2.7/pygmi/raster/menu.py +307 -0
  78. pygmi-2.2.7/pygmi/raster/normalisation.py +187 -0
  79. pygmi-2.2.7/pygmi/raster/show_table.py +245 -0
  80. pygmi-2.2.7/pygmi/raster/smooth.py +406 -0
  81. pygmi-2.2.7/pygmi/raster/tiltdepth.py +590 -0
  82. pygmi-2.2.7/pygmi/seis/__init__.py +0 -0
  83. pygmi-2.2.7/pygmi/seis/beachball.py +751 -0
  84. pygmi-2.2.7/pygmi/seis/datatypes.py +605 -0
  85. pygmi-2.2.7/pygmi/seis/del_rec.py +410 -0
  86. pygmi-2.2.7/pygmi/seis/iodefs.py +1261 -0
  87. pygmi-2.2.7/pygmi/seis/menu.py +136 -0
  88. pygmi-2.2.7/pygmi/seis/scan_imp.py +795 -0
  89. pygmi-2.2.7/pygmi/test/__init__.py +6 -0
  90. pygmi-2.2.7/pygmi/test/pfmod.py +212 -0
  91. pygmi-2.2.7/pygmi/test/tests.py +39 -0
  92. pygmi-2.2.7/pygmi/vector/__init__.py +7 -0
  93. pygmi-2.2.7/pygmi/vector/datatypes.py +74 -0
  94. pygmi-2.2.7/pygmi/vector/graphs.py +443 -0
  95. pygmi-2.2.7/pygmi/vector/iodefs.py +345 -0
  96. pygmi-2.2.7/pygmi/vector/menu.py +127 -0
  97. pygmi-2.2.7/pygmi.egg-info/PKG-INFO +47 -0
  98. pygmi-2.2.7/pygmi.egg-info/SOURCES.txt +105 -0
  99. pygmi-2.2.7/pygmi.egg-info/dependency_links.txt +1 -0
  100. pygmi-2.2.7/pygmi.egg-info/entry_points.txt +3 -0
  101. pygmi-2.2.7/pygmi.egg-info/not-zip-safe +1 -0
  102. pygmi-2.2.7/pygmi.egg-info/requires.txt +7 -0
  103. pygmi-2.2.7/pygmi.egg-info/top_level.txt +1 -0
  104. pygmi-2.2.7/quickstart.py +35 -0
  105. pygmi-2.2.7/setup.cfg +8 -0
  106. pygmi-2.2.7/setup.py +80 -0
@@ -0,0 +1,1037 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Name: main.py (part of PyGMI)
3
+ #
4
+ # Author: Patrick Cole
5
+ # E-Mail: pcole@geoscience.org.za
6
+ #
7
+ # Copyright: (c) 2013 Council for Geoscience
8
+ # Licence: GPL-3.0
9
+ #
10
+ # This file is part of PyGMI
11
+ #
12
+ # PyGMI is free software: you can redistribute it and/or modify
13
+ # it under the terms of the GNU General Public License as published by
14
+ # the Free Software Foundation, either version 3 of the License, or
15
+ # (at your option) any later version.
16
+ #
17
+ # PyGMI is distributed in the hope that it will be useful,
18
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
+ # GNU General Public License for more details.
21
+ #
22
+ # You should have received a copy of the GNU General Public License
23
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
24
+ # -----------------------------------------------------------------------------
25
+ """ This is the main module for PyGMI.
26
+
27
+ This module comprises a series of classes which are responsible for the primary
28
+ interface to the software. Credit must go to PyQt's examples, upon which some
29
+ of this was originally based.
30
+
31
+ Although the main interface is controlled here, the content of the menus and
32
+ routines is not. The menus and corresponding classes are found within the
33
+ pygmi packages.
34
+
35
+ """
36
+
37
+ from PyQt4 import QtGui, QtCore
38
+ import pygmi
39
+ import pygmi.menu_default as menu_default
40
+ import sys
41
+ import importlib
42
+ import numpy as np
43
+ import math
44
+ import pkgutil
45
+ import os
46
+ import pygmi.misc as misc
47
+
48
+
49
+ class Arrow(QtGui.QGraphicsLineItem):
50
+ """
51
+ Class responsible for drawing arrows on the main interface.
52
+
53
+ Attributes
54
+ ----------
55
+ arrow_head : QPolygonF
56
+ Arrow head polygon.
57
+ my_start_item : DiagramItem
58
+ Starting DiagramItem object. This will send information to my_end_item
59
+ my_end_item : DiagramItem
60
+ End DiagramItem object. This will get information from my_start_item
61
+ my_color : QtCore color (default is QtCore.Qt.black)
62
+ Color
63
+ """
64
+ def __init__(self, start_item, end_item, parent=None, scene=None):
65
+ super(Arrow, self).__init__(parent, scene)
66
+
67
+ self.arrow_head = QtGui.QPolygonF()
68
+
69
+ self.my_start_item = start_item
70
+ self.my_end_item = end_item
71
+ self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
72
+ self.my_color = QtCore.Qt.black
73
+ self.setPen(QtGui.QPen(self.my_color, 2, QtCore.Qt.SolidLine,
74
+ QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
75
+
76
+ def boundingRect(self):
77
+ """
78
+ Overloaded bounding rectangle. This is necessary to ensure that the
79
+ line and arrowhead are cleaned properly when moving.
80
+
81
+ Returns
82
+ -------
83
+ tmp : QtCore.QRectF
84
+ """
85
+ extra = (self.pen().width() + 20) / 2.0
86
+ p1 = self.line().p1()
87
+ p2 = self.line().p2()
88
+ tmp = QtCore.QRectF(p1, QtCore.QSizeF(p2.x()-p1.x(), p2.y()-p1.y()))
89
+
90
+ return tmp.normalized().adjusted(-extra, -extra, extra, extra)
91
+
92
+ def paint(self, painter, option, widget=None):
93
+ """
94
+ Overloaded paint method.
95
+
96
+ Parameters
97
+ ----------
98
+ painter : QPainter
99
+ option : QStyleOptionGraphicsItem
100
+ widget : QWidget, optional
101
+ """
102
+ pi = math.pi
103
+ if self.my_start_item.collidesWithItem(self.my_end_item):
104
+ return
105
+
106
+ my_start_item = self.my_start_item
107
+ my_end_item = self.my_end_item
108
+ my_color = self.my_color
109
+ my_pen = self.pen()
110
+ my_pen.setColor(self.my_color)
111
+ arrow_size = 10.0
112
+ painter.setPen(my_pen)
113
+ painter.setBrush(self.my_color)
114
+
115
+ x0, y0 = np.mean(self.my_start_item.np_poly, 0)
116
+ my_start_off = QtCore.QPointF(x0, y0)
117
+ x1, y1 = np.mean(self.my_end_item.np_poly, 0)
118
+ my_end_off = QtCore.QPointF(x1, y1)
119
+
120
+ center_line = QtCore.QLineF(my_start_item.pos()+my_start_off,
121
+ my_end_item.pos()+my_end_off)
122
+ end_polygon = my_end_item.polygon()
123
+ p1 = end_polygon.first() + my_end_item.pos()
124
+
125
+ intersect_point = QtCore.QPointF()
126
+ for i in end_polygon:
127
+ p2 = i + my_end_item.pos()
128
+ poly_line = QtCore.QLineF(p1, p2)
129
+ intersect_type = poly_line.intersect(center_line, intersect_point)
130
+ if intersect_type == QtCore.QLineF.BoundedIntersection:
131
+ break
132
+ p1 = p2
133
+
134
+ self.setLine(QtCore.QLineF(intersect_point,
135
+ my_start_item.pos()+my_start_off))
136
+ line = self.line()
137
+
138
+ angle = math.acos(line.dx() / line.length())
139
+ if line.dy() >= 0:
140
+ angle = (math.pi*2.0) - angle
141
+
142
+ arrow_p1 = (line.p1() + QtCore.QPointF(math.sin(angle+pi/3) *
143
+ arrow_size,
144
+ math.cos(angle+pi/3) *
145
+ arrow_size))
146
+ arrow_p2 = (line.p1() + QtCore.QPointF(math.sin(angle+pi-pi/3) *
147
+ arrow_size,
148
+ math.cos(angle+pi-pi/3) *
149
+ arrow_size))
150
+
151
+ self.arrow_head.clear()
152
+ for point in [line.p1(), arrow_p1, arrow_p2]:
153
+ self.arrow_head.append(point)
154
+
155
+ painter.drawLine(line)
156
+ painter.drawPolygon(self.arrow_head)
157
+ if self.isSelected():
158
+ painter.setPen(QtGui.QPen(my_color, 1, QtCore.Qt.DashLine))
159
+ my_line = QtCore.QLineF(line)
160
+ my_line.translate(0, 4.0)
161
+ painter.drawLine(my_line)
162
+ my_line.translate(0, -8.0)
163
+ painter.drawLine(my_line)
164
+
165
+
166
+ class DiagramItem(QtGui.QGraphicsPolygonItem):
167
+ """
168
+ Diagram Item
169
+
170
+ Attributes
171
+ ----------
172
+ arrows : list
173
+ list of Arrow objects
174
+ diagram_type : str
175
+ string denoting the diagram type. Can be 'StartEnd', 'Conditional' or
176
+ 'Step'
177
+ context_menu = context_menu
178
+ my_class : object
179
+ Class that the diagram item is linked to.
180
+ is_import : bool
181
+ Flags whether my_class is used to import data
182
+ text_item : None
183
+ my_class_name : str
184
+ Class name being referenced
185
+ """
186
+ def __init__(self, diagram_type, context_menu, my_class, parent=None,
187
+ scene=None):
188
+ super(DiagramItem, self).__init__(parent, scene)
189
+
190
+ self.arrows = []
191
+
192
+ self.diagram_type = diagram_type
193
+ self.context_menu = context_menu
194
+ self.my_class = my_class
195
+ self.is_import = False
196
+ self.text_item = None
197
+ self.my_class_name = ''
198
+
199
+ if hasattr(self.my_class, 'arrows'):
200
+ self.my_class.arrows = self.arrows
201
+
202
+ path = QtGui.QPainterPath()
203
+ if self.diagram_type == "StartEnd":
204
+ path.moveTo(200, 50)
205
+ path.arcTo(150, 0, 50, 50, 0, 90)
206
+ path.arcTo(50, 0, 50, 50, 90, 90)
207
+ path.arcTo(50, 50, 50, 50, 180, 90)
208
+ path.arcTo(150, 50, 50, 50, 270, 90)
209
+ path.lineTo(200, 25)
210
+ self.my_polygon = path.toFillPolygon()
211
+ elif self.diagram_type == "Conditional":
212
+ self.np_poly = np.array([[-100., 0.],
213
+ [0., 100.],
214
+ [100., 0.],
215
+ [0., -100.],
216
+ [-100., 0.]])
217
+
218
+ my_points = []
219
+ for i in self.np_poly:
220
+ my_points.append(QtCore.QPointF(i[0], i[1]))
221
+ self.my_polygon = QtGui.QPolygonF(my_points)
222
+
223
+ elif self.diagram_type == "Step":
224
+ self.np_poly = np.array([[-100., -100.],
225
+ [100., -100.],
226
+ [100., 100.],
227
+ [-100., 100.],
228
+ [-100., -100.]])
229
+
230
+ my_points = []
231
+ for i in self.np_poly:
232
+ my_points.append(QtCore.QPointF(i[0], i[1]))
233
+ self.my_polygon = QtGui.QPolygonF(my_points)
234
+
235
+ else:
236
+ self.np_poly = np.array([[-120., -80.],
237
+ [-70., 80.],
238
+ [120., 80.],
239
+ [70., -80.],
240
+ [-120., -80.]])
241
+
242
+ my_points = []
243
+ for i in self.np_poly:
244
+ my_points.append(QtCore.QPointF(i[0], i[1]))
245
+ self.my_polygon = QtGui.QPolygonF(my_points)
246
+
247
+ self.setPolygon(self.my_polygon)
248
+ self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
249
+ self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
250
+
251
+ def add_arrow(self, arrow):
252
+ """Add Arrow
253
+
254
+ Parameters
255
+ ----------
256
+ arrow : Arrow
257
+ Arrow object to add.
258
+ """
259
+ self.arrows.append(arrow)
260
+
261
+ def update_indata(self):
262
+ """Routine to add datasets"""
263
+ data = {}
264
+ for i in self.arrows:
265
+ odata = i.my_start_item.my_class.outdata
266
+ for j in odata.keys():
267
+ if j in data:
268
+ data[j] = data[j] + odata[j]
269
+ else:
270
+ data[j] = odata[j]
271
+
272
+ # if 'Model3D' not in data.keys() and 'Seis' not in data.keys():
273
+ # for j in data.keys():
274
+ # tmp = []
275
+ # for i in data[j]:
276
+ # tmp.append(i.dataid)
277
+ # tmp = ComboBoxBasic(txt='Select Datasets', dlist=tmp)
278
+ # atmp = [i.text() for i in tmp.combo.selectedItems()]
279
+ # # aa.show()
280
+ # if len(atmp) > 0:
281
+ # dtmp = []
282
+ # for i in data[j]:
283
+ # if i.dataid in atmp:
284
+ # dtmp.append(i)
285
+ # data[j] = dtmp
286
+
287
+ self.my_class.indata = data
288
+ if hasattr(self.my_class, 'data_init'):
289
+ self.my_class.data_init()
290
+
291
+ def contextMenuEvent(self, event):
292
+ """
293
+ Overloaded context menu event
294
+
295
+ Parameters
296
+ ----------
297
+ event : N/A
298
+ """
299
+ self.scene().clearSelection()
300
+ self.setSelected(True)
301
+
302
+ tmplist = ['Basic']+list(self.my_class.outdata.keys())
303
+ tmp = []
304
+ # exclude = ['ProfPic', 'Seis']
305
+ exclude = ['ProfPic']
306
+ for i in tmplist:
307
+ if i not in exclude:
308
+ tmp += self.context_menu[i].actions()
309
+ if i == 'ProfPic' and 'Raster' not in tmplist:
310
+ tmp += self.context_menu['Raster'].actions()
311
+ local_menu = QtGui.QMenu()
312
+ local_menu.addActions(tmp)
313
+ local_menu.exec_(event.screenPos())
314
+
315
+ def mouseDoubleClickEvent(self, event):
316
+ """
317
+ Mouse double click event
318
+
319
+ This event is used to activate an item. It does this by calling the
320
+ settings() method of the item. The event also changes the color of the
321
+ item to reflect whether it is busy working.
322
+ """
323
+ self.setBrush(QtGui.QColor(255, 0, 0, 127))
324
+
325
+ temp = self.settings()
326
+ if temp is True:
327
+ self.setBrush(QtGui.QColor(0, 255, 0, 127))
328
+ else:
329
+ self.setBrush(self.scene().my_item_color)
330
+
331
+ def remove_arrow(self, arrow):
332
+ """
333
+ Remove a single Arrow
334
+
335
+ Parameters
336
+ ----------
337
+ arrow : Arrow
338
+ Arrow object to remove.
339
+ """
340
+ try:
341
+ self.arrows.remove(arrow)
342
+ except ValueError:
343
+ pass
344
+
345
+ def remove_arrows(self):
346
+ """Remove Arrows. Uses the remove_arrow method."""
347
+ for arrow in self.arrows[:]:
348
+ arrow.my_start_item.remove_arrow(arrow)
349
+ arrow.my_end_item.remove_arrow(arrow)
350
+ self.scene().removeItem(arrow)
351
+
352
+ def settings(self):
353
+ """
354
+ Routine Settings.
355
+
356
+ Returns
357
+ -------
358
+ iflag : bool
359
+ Returns a boolean reflecting success of the my_class.settings()
360
+ method.
361
+ """
362
+ if self.is_import is True:
363
+ pass
364
+ elif self.my_class.indata == {} and self.is_import is False:
365
+ QtGui.QMessageBox.warning(QtGui.QMessageBox(), 'Warning',
366
+ ' You need to connect data first!',
367
+ QtGui.QMessageBox.Ok,
368
+ QtGui.QMessageBox.Ok)
369
+ return
370
+
371
+ self.my_class.parent.process_is_active()
372
+ self.my_class.parent.showprocesslog(self.my_class_name+' busy...')
373
+ iflag = self.my_class.settings()
374
+ self.my_class.parent.process_is_active(False)
375
+ self.my_class.parent.showprocesslog(self.my_class_name+' finished!')
376
+ return iflag
377
+
378
+
379
+ class DiagramScene(QtGui.QGraphicsScene):
380
+ """ Diagram Scene """
381
+ def __init__(self, item_menu, parent):
382
+ super(DiagramScene, self).__init__(parent)
383
+
384
+ self.my_item_menu = item_menu
385
+ self.my_mode = "MoveItem"
386
+ self.my_item_type = "Step"
387
+ self.line = None
388
+ self.text_item = None
389
+ self.my_item_color = QtCore.Qt.cyan
390
+ self.my_text_color = QtCore.Qt.black
391
+ self.my_line_color = QtCore.Qt.black
392
+ self.my_font = QtGui.QFont()
393
+ self.parent = parent
394
+
395
+ def mousePressEvent(self, mouse_event):
396
+ """
397
+ Overloaded Mouse Press Event
398
+ Parameters
399
+ ----------
400
+ mouse_event: QGraphicsSceneMouseEvent
401
+ mouse event.
402
+ """
403
+ if mouse_event.button() != QtCore.Qt.LeftButton:
404
+ return
405
+ if self.my_mode == "InsertLine":
406
+ self.line = QtGui.QGraphicsLineItem(
407
+ QtCore.QLineF(mouse_event.scenePos(), mouse_event.scenePos()))
408
+ self.line.setPen(QtGui.QPen(self.my_line_color, 2))
409
+ self.addItem(self.line)
410
+
411
+ super(DiagramScene, self).mousePressEvent(mouse_event)
412
+
413
+ # now display the information about the selected data
414
+ tmp = self.selectedItems()
415
+ if len(tmp) == 0:
416
+ return
417
+ try:
418
+ odata = tmp[0].my_class.outdata
419
+ except AttributeError:
420
+ return
421
+ parent = self.parent
422
+ text = ''
423
+ for i in odata.keys():
424
+ text += '\n' + i + ' dataset:\n'
425
+ if i == 'Raster' or i == 'Cluster':
426
+ for j in odata[i]:
427
+ text += ' '+j.dataid + '\n'
428
+ if i == 'Model3D':
429
+ for j in odata[i][0].lith_list.keys():
430
+ text += ' '+j + '\n'
431
+ parent.showdatainfo(text)
432
+
433
+ def mouseMoveEvent(self, mouse_event):
434
+ """
435
+ Overloaded Mouse Move Event
436
+
437
+ Parameters
438
+ ----------
439
+ mouse_event: QGraphicsSceneMouseEvent
440
+ mouse event.
441
+ """
442
+ if self.my_mode == "InsertLine" and self.line:
443
+ new_line = QtCore.QLineF(self.line.line().p1(),
444
+ mouse_event.scenePos())
445
+ self.line.setLine(new_line)
446
+ elif self.my_mode == "MoveItem":
447
+ super(DiagramScene, self).mouseMoveEvent(mouse_event)
448
+
449
+ def mouseReleaseEvent(self, mouse_event):
450
+ """
451
+ Overloaded Mouse Release Event
452
+
453
+ Parameters
454
+ ----------
455
+ mouse_event: QGraphicsSceneMouseEvent
456
+ mouse event.
457
+ """
458
+ if self.line and self.my_mode == "InsertLine":
459
+ start_items = self.items(self.line.line().p1())
460
+ if len(start_items) and start_items[0] == self.line:
461
+ start_items.pop(0)
462
+ end_items = self.items(self.line.line().p2())
463
+ if len(end_items) and end_items[0] == self.line:
464
+ end_items.pop(0)
465
+
466
+ self.removeItem(self.line)
467
+ self.line = None
468
+
469
+ if (len(start_items) and len(end_items) and
470
+ isinstance(start_items[-1], DiagramItem) and
471
+ isinstance(end_items[-1], DiagramItem) and
472
+ start_items[-1] != end_items[-1]):
473
+ start_item = start_items[-1]
474
+ end_item = end_items[-1]
475
+ arrow = Arrow(start_item, end_item)
476
+ start_item.add_arrow(arrow)
477
+ end_item.add_arrow(arrow)
478
+ arrow.setZValue(-1000.0)
479
+ self.addItem(arrow)
480
+ end_item.update_indata()
481
+
482
+ self.line = None
483
+ self.my_mode = "MoveItem"
484
+ self.parent.action_pointer.setChecked(True)
485
+ super(DiagramScene, self).mouseReleaseEvent(mouse_event)
486
+
487
+
488
+ class MainWidget(QtGui.QMainWindow):
489
+ """
490
+ Widget class to call the main interface
491
+
492
+ Attributes
493
+ ----------
494
+ pdlg : list
495
+ context_menu : dictionary
496
+ """
497
+ def __init__(self, parent=None):
498
+ QtGui.QMainWindow.__init__(self, parent)
499
+
500
+ ipth = os.path.dirname(menu_default.__file__)+r'/images/'
501
+
502
+ self.__version__ = pygmi.__version__
503
+ self.pdlg = []
504
+ self.context_menu = {}
505
+ self.add_to_context('Basic')
506
+
507
+ self.menubar = QtGui.QMenuBar()
508
+
509
+ self.statusbar = QtGui.QStatusBar()
510
+ self.toolbar = QtGui.QToolBar()
511
+
512
+ self.centralwidget = QtGui.QWidget()
513
+ self.grid_layout = QtGui.QGridLayout(self.centralwidget)
514
+ self.graphics_view = QtGui.QGraphicsView()
515
+ self.textbrowser_datainfo = QtGui.QTextBrowser()
516
+ self.textbrowser_processlog = QtGui.QTextBrowser()
517
+ self.pbar = misc.ProgressBar()
518
+
519
+ self.action_help = QtGui.QAction(self)
520
+ self.action_delete = QtGui.QAction(self)
521
+ self.action_bring_to_front = QtGui.QAction(self)
522
+ self.action_send_to_back = QtGui.QAction(self)
523
+ self.action_pointer = QtGui.QAction(self)
524
+ self.action_linepointer = QtGui.QAction(self)
525
+ self.actiongroup_pointer = QtGui.QActionGroup(self)
526
+ self.actiongroup_pointer.addAction(self.action_pointer)
527
+ self.actiongroup_pointer.addAction(self.action_linepointer)
528
+ self.action_pointer.setCheckable(True)
529
+ self.action_linepointer.setCheckable(True)
530
+ self.action_pointer.setChecked(True)
531
+
532
+ self.action_delete.setIcon(QtGui.QIcon(ipth+'delete.png'))
533
+ self.action_bring_to_front.setIcon(
534
+ QtGui.QIcon(ipth+'bringtofront.png'))
535
+ self.action_send_to_back.setIcon(QtGui.QIcon(ipth+'sendtoback.png'))
536
+ self.action_pointer.setIcon(QtGui.QIcon(ipth+'pointer.png'))
537
+ self.action_linepointer.setIcon(QtGui.QIcon(ipth+'linepointer.png'))
538
+ self.action_help.setIcon(QtGui.QIcon(ipth+'help.png'))
539
+
540
+ self.setWindowIcon(QtGui.QIcon(ipth+'logo256.ico'))
541
+
542
+ self.setupui()
543
+
544
+ menus = []
545
+ for _, modname, _ in pkgutil.walk_packages(
546
+ path=pygmi.__path__, prefix=pygmi.__name__+'.',
547
+ onerror=lambda x: None):
548
+ menus.append(modname)
549
+
550
+ raster_menu = menus.pop(menus.index('pygmi.raster.menu'))
551
+ vector_menu = menus.pop(menus.index('pygmi.vector.menu'))
552
+ menus = [raster_menu, vector_menu]+menus
553
+ start = Startup(len(menus))
554
+ menuimports = []
555
+ for i in menus:
556
+ if i == 'pygmi.__pycache__.menu':
557
+ continue
558
+ if i[-5:] == '.menu':
559
+ start.update()
560
+ menuimports.append(importlib.import_module(i))
561
+ start.close()
562
+
563
+ self.menus = []
564
+ self.menus.append(menu_default.FileMenu(self))
565
+ for i in menuimports:
566
+ self.menus.append(i.MenuWidget(self))
567
+ self.menus.append(menu_default.HelpMenu(self))
568
+
569
+ self.scene = DiagramScene(self.context_menu['Basic'], self)
570
+
571
+ self.view = self.graphics_view
572
+ self.view.setScene(self.scene)
573
+
574
+ # Menus
575
+ self.action_pointer.triggered.connect(self.pointer)
576
+ self.action_linepointer.triggered.connect(self.linepointer)
577
+ self.action_delete.triggered.connect(self.delete_item)
578
+ self.action_bring_to_front.triggered.connect(self.bring_to_front)
579
+ self.action_send_to_back.triggered.connect(self.send_to_back)
580
+ self.action_help.triggered.connect(self.help_docs)
581
+
582
+ # Start of Functions
583
+ def setupui(self):
584
+ """ Setup UI """
585
+ self.resize(800, 600)
586
+ sizepolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred,
587
+ QtGui.QSizePolicy.Expanding)
588
+ sizepolicy.setHorizontalStretch(0)
589
+ sizepolicy.setVerticalStretch(0)
590
+ sizepolicy.setHeightForWidth(
591
+ self.graphics_view.sizePolicy().hasHeightForWidth())
592
+
593
+ self.graphics_view.setSizePolicy(sizepolicy)
594
+ self.graphics_view.setTransformationAnchor(
595
+ QtGui.QGraphicsView.AnchorUnderMouse)
596
+
597
+ self.textbrowser_datainfo.setSizePolicy(sizepolicy)
598
+ self.textbrowser_processlog.setSizePolicy(sizepolicy)
599
+ self.textbrowser_processlog.setStyleSheet(
600
+ "* { background-color: rgb(255, 255, 255); }")
601
+
602
+ self.grid_layout.addWidget(self.graphics_view, 0, 0, 4, 2)
603
+ self.grid_layout.addWidget(self.textbrowser_datainfo, 1, 2, 1, 1)
604
+ self.grid_layout.addWidget(self.textbrowser_processlog, 3, 2, 1, 1)
605
+ self.grid_layout.addWidget(self.pbar, 5, 0, 1, 3)
606
+
607
+ label = QtGui.QLabel()
608
+ label_2 = QtGui.QLabel()
609
+ self.grid_layout.addWidget(label, 0, 2, 1, 1)
610
+ self.grid_layout.addWidget(label_2, 2, 2, 1, 1)
611
+
612
+ self.setCentralWidget(self.centralwidget)
613
+ self.setMenuBar(self.menubar)
614
+ self.setStatusBar(self.statusbar)
615
+ self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolbar)
616
+
617
+ self.toolbar.addAction(self.action_delete)
618
+ self.toolbar.addAction(self.action_bring_to_front)
619
+ self.toolbar.addAction(self.action_send_to_back)
620
+ self.toolbar.addSeparator()
621
+ self.toolbar.addAction(self.action_pointer)
622
+ self.toolbar.addAction(self.action_linepointer)
623
+ self.toolbar.addSeparator()
624
+ self.toolbar.addAction(self.action_help)
625
+
626
+ self.setWindowTitle(
627
+ "PyGMI - Python Geophysical Modelling and Interpretation")
628
+ label.setText("Dataset Information:")
629
+ label_2.setText("Process Log:")
630
+ self.action_delete.setText("Delete")
631
+ self.action_bring_to_front.setText("Bring to Front")
632
+ self.action_send_to_back.setText("Send to Back")
633
+ self.action_pointer.setText("Pointer")
634
+ self.action_linepointer.setText("LinePointer")
635
+
636
+ item_menu = self.context_menu['Basic']
637
+ item_menu.addAction(self.action_delete)
638
+ item_menu.addAction(self.action_bring_to_front)
639
+ item_menu.addAction(self.action_send_to_back)
640
+
641
+ def add_to_context(self, txt):
642
+ """
643
+ Adds to a context menu.
644
+
645
+ Each dataset type which PyGMI uses can have its own context menu. This
646
+ method allows for the definition of each group of context menu items
647
+ under a user defined text label.
648
+
649
+ Parameters
650
+ ----------
651
+ txt : str
652
+ Label for a group of context menu items
653
+ """
654
+
655
+ if self.context_menu.get(txt) is not None:
656
+ return
657
+ self.context_menu[txt] = QtGui.QMenu()
658
+
659
+ def bring_to_front(self):
660
+ """Bring the selected item to front."""
661
+
662
+ if not self.scene.selectedItems():
663
+ return
664
+
665
+ selected_item = self.scene.selectedItems()[0]
666
+ overlap_items = selected_item.collidingItems()
667
+
668
+ zvalue = 0
669
+ for item in overlap_items:
670
+ if item.zValue() >= zvalue and isinstance(item, DiagramItem):
671
+ zvalue = item.zValue() + 0.1
672
+ selected_item.setZValue(zvalue)
673
+
674
+ def clearprocesslog(self):
675
+ """Clears the process log."""
676
+ self.textbrowser_processlog.setPlainText('')
677
+
678
+ def delete_item(self):
679
+ """Delete the selected item from main interface."""
680
+ for item in self.scene.selectedItems():
681
+ if isinstance(item, DiagramItem):
682
+ item.remove_arrows()
683
+ self.scene.removeItem(item)
684
+
685
+ for item in self.scene.items():
686
+ if isinstance(item, DiagramItem):
687
+ item.update_indata()
688
+ if item.my_class.indata == {} and item.is_import is False:
689
+ item.setBrush(self.scene.my_item_color)
690
+
691
+ def get_indata(self):
692
+ """
693
+ Gets input data from the selected item on the main interface.
694
+
695
+ Returns
696
+ -------
697
+ idata : list
698
+ Input list of PyGMI dataset
699
+ """
700
+
701
+ idata = []
702
+ for item in self.scene.selectedItems():
703
+ if isinstance(item, DiagramItem):
704
+ idata.append(item.my_class.indata)
705
+ return idata
706
+
707
+ def get_outdata(self):
708
+ """
709
+ Gets output data from the selected item on the main interface.
710
+
711
+ Returns
712
+ -------
713
+ odata : list
714
+ Output list of PyGMI dataset
715
+ """
716
+ odata = []
717
+ for item in self.scene.selectedItems():
718
+ if isinstance(item, DiagramItem):
719
+ odata.append(item.my_class.outdata)
720
+ return odata
721
+
722
+ def help_docs(self):
723
+ """
724
+ Help Routine
725
+ """
726
+ menu_default.HelpDocs(self, 'pygmi.main')
727
+
728
+ def item_insert(self, item_type, item_name, class_name):
729
+ """
730
+ Item insert.
731
+
732
+ Insert an item on the main interface. The item is an object passed by
733
+ one of the menu.py routines and is one of the algorithims chosen on
734
+ the main PyGMI menu.
735
+
736
+ Parameters
737
+ ----------
738
+ item_type : str
739
+ str describing the shape of the graphic used to describe the item.
740
+ item_name : str
741
+ str describing the name of the item to be displayed.
742
+ class_name : object
743
+ class to be called when double clicking on the item.
744
+
745
+ Returns
746
+ -------
747
+ item : DiagramItem
748
+ Return a DiagramItem object
749
+ """
750
+ item = DiagramItem(item_type, self.scene.my_item_menu, class_name)
751
+ item_color = self.scene.my_item_color
752
+
753
+ item.my_class_name = item_name.replace('\n', ' ')
754
+
755
+ if item_name == "Potential\nField\nModelling":
756
+ item.my_class.indata['tmp'] = True
757
+
758
+ if 'Import' in item_name:
759
+ item.is_import = True
760
+ iflag = item.settings()
761
+ if iflag is False:
762
+ return
763
+ ifile = item.my_class.ifile.split('/')[-1]
764
+ if len(ifile) > len(item_name):
765
+ ifile = ifile[:len(item_name)]+'\n'+ifile[len(item_name):]
766
+ if len(ifile) > 2*len(item_name):
767
+ ifile = ifile[:2*len(item_name)]+'...\n'
768
+ item_name += ':\n'+ifile
769
+ item_color = QtGui.QColor(0, 255, 0, 127)
770
+
771
+ # Do text first, since this determines size of polygon
772
+ # text_item = DiagramTextItem()
773
+ text_item = QtGui.QGraphicsTextItem()
774
+ text_item.setPlainText(item_name)
775
+ text_item.setFont(self.scene.my_font)
776
+ text_item.setZValue(1000.0)
777
+ text_item.setDefaultTextColor(self.scene.my_text_color)
778
+
779
+ # Rectangle for text label
780
+ rect_item = QtGui.QGraphicsRectItem(text_item.boundingRect())
781
+ rect_item.setZValue(500.0)
782
+ rect_item.setBrush(self.scene.my_item_color)
783
+
784
+ # Actual polygon item
785
+ text_width = text_item.boundingRect().width()
786
+ item.np_poly *= 1.5*text_width/item.np_poly[:, 0].ptp()
787
+ item.np_poly[:, 0] += (text_item.boundingRect().left() -
788
+ item.np_poly[:, 0].min() - text_width/4)
789
+ item.np_poly[:, 1] += text_item.boundingRect().height()/2
790
+
791
+ my_points = []
792
+ for i in item.np_poly:
793
+ my_points.append(QtCore.QPointF(i[0], i[1]))
794
+ item.my_polygon = QtGui.QPolygonF(my_points)
795
+
796
+ item.setPolygon(item.my_polygon)
797
+ item.setBrush(item_color)
798
+
799
+ # Menu Stuff
800
+ item.context_menu = self.context_menu
801
+
802
+ # Add item to scene and merge
803
+ self.scene.addItem(item)
804
+
805
+ xxyy = self.view.mapToScene(self.view.width()/2.,
806
+ self.view.height()/2.)
807
+ item.setPos(xxyy)
808
+
809
+ text_item.setParentItem(item)
810
+ rect_item.setParentItem(item)
811
+
812
+ # Enable moving
813
+ self.scene.my_mode = "MoveItem"
814
+ return item
815
+
816
+ def launch_context_item(self, newitem):
817
+ """
818
+ Launches a context menu item, using output data
819
+
820
+ Parameters
821
+ ----------
822
+ newitem : custom class
823
+ newitem is the class to be called by the context menu item
824
+ """
825
+ outdata = self.get_outdata()
826
+
827
+ # if outdata[0] == {}:
828
+ # self.run()
829
+ # outdata = self.get_outdata()
830
+
831
+ for odata in outdata:
832
+ if odata is not None and odata != {}:
833
+ dlg = newitem(self)
834
+ dlg.indata = odata
835
+ dlg.run()
836
+ self.update_pdlg(dlg)
837
+
838
+ def launch_context_item_indata(self, newitem):
839
+ """
840
+ Launches a context menu item, using input data.
841
+
842
+ Parameters
843
+ ----------
844
+ newitem : custom class
845
+ newitem is the class to be called by the context menu item
846
+ """
847
+ indata = self.get_indata()
848
+
849
+ for idata in indata:
850
+ if idata is not None and idata != {}:
851
+ dlg = newitem(self)
852
+ dlg.indata = idata
853
+ dlg.run()
854
+ self.update_pdlg(dlg)
855
+
856
+ def linepointer(self):
857
+ """Select line pointer."""
858
+ self.scene.my_mode = "InsertLine"
859
+
860
+ def pointer(self):
861
+ """Select pointer."""
862
+ self.scene.my_mode = "MoveItem"
863
+
864
+ def process_is_active(self, isactive=True):
865
+ """
866
+ Changes process log color when a process is active.
867
+
868
+ Parameters
869
+ ----------
870
+ isactive : bool, optional
871
+ boolean variable indicating if a process is active.
872
+ """
873
+
874
+ if isactive:
875
+ self.textbrowser_processlog.setStyleSheet(
876
+ "* { background-color: rgba(255, 0, 0, 127); }")
877
+ self.pbar.setValue(0)
878
+ else:
879
+ self.textbrowser_processlog.setStyleSheet(
880
+ "* { background-color: rgb(255, 255, 255); }")
881
+
882
+ # def run(self):
883
+ # """Runs program to end. Currently this is unused."""
884
+ # item_list = []
885
+ #
886
+ # # First get the data import items
887
+ # for item in self.scene.items():
888
+ # if isinstance(item, DiagramItem):
889
+ # if item.is_import is True:
890
+ # item_list.append(item)
891
+ #
892
+ # # Then get the rest of the items in sequence, while running them
893
+ # while len(item_list) > 0:
894
+ # item = item_list.pop(0)
895
+ # if item.is_import is False:
896
+ # item.settings()
897
+ # for i in item.arrows:
898
+ # newitem = i.my_end_item
899
+ # if newitem != item and newitem not in item_list:
900
+ # item_list.append(newitem)
901
+
902
+ def send_to_back(self):
903
+ """Send the selected item to the back."""
904
+ if not self.scene.selectedItems():
905
+ return
906
+
907
+ selected_item = self.scene.selectedItems()[0]
908
+ overlap_items = selected_item.collidingItems()
909
+
910
+ zvalue = 0
911
+ for item in overlap_items:
912
+ if item.zValue() <= zvalue and isinstance(item, DiagramItem):
913
+ zvalue = item.zValue() - 0.1
914
+ selected_item.setZValue(zvalue)
915
+
916
+ def showdatainfo(self, txt):
917
+ """ Show text in the dataset information panel
918
+
919
+ Parameters
920
+ ----------
921
+ txt : str
922
+ Message to be displayed in the datainfo panel
923
+ """
924
+ self.textbrowser_datainfo.setPlainText(txt)
925
+ tmp = self.textbrowser_datainfo.verticalScrollBar()
926
+ tmp.setValue(tmp.maximumHeight())
927
+ self.repaint()
928
+
929
+ def showprocesslog(self, txt, replacelast=False):
930
+ """
931
+ Show text on the process log.
932
+
933
+ Parameters
934
+ ----------
935
+ txt : str
936
+ Message to be displayed in the process log
937
+ replacelast : bool, optional
938
+ flag to indicate whether the last row on the log should be
939
+ overwritten.
940
+ """
941
+ self.showtext(self.textbrowser_processlog, txt, replacelast)
942
+ QtGui.QApplication.processEvents()
943
+
944
+ def showtext(self, txtobj, txt, replacelast=False):
945
+ """
946
+ Show text on the text panel
947
+
948
+ Parameters
949
+ ----------
950
+ txt : str
951
+ Message to be displayed in the text panel
952
+ replacelast : bool, optional
953
+ flag to indicate whether the last row on the log should be
954
+ overwritten.
955
+ """
956
+ txtmsg = str(txtobj.toPlainText())
957
+ if replacelast is True:
958
+ txtmsg = txtmsg[:txtmsg.rfind('\n')]
959
+ txtmsg = txtmsg[:txtmsg.rfind('\n')]
960
+ txtmsg += '\n'
961
+ txtmsg += txt + '\n'
962
+ txtobj.setPlainText(txtmsg)
963
+ tmp = txtobj.verticalScrollBar()
964
+ tmp.setValue(tmp.maximumHeight())
965
+ self.repaint()
966
+
967
+ def update_pdlg(self, dlg):
968
+ """ Cleans deleted objects in self.pdlg and appends a new object.
969
+
970
+ self.pdlg allows for modeless dialogs to remain in existance until they
971
+ are closed
972
+
973
+ Parameters
974
+ ----------
975
+ dlg : object
976
+ Object to be appended to self.pdlg
977
+ """
978
+ for i in range(len(self.pdlg)-1, -1, -1):
979
+ try:
980
+ if not self.pdlg[i].isVisible():
981
+ self.pdlg.pop(i)
982
+ except RuntimeError:
983
+ self.pdlg.pop(i)
984
+ except AttributeError:
985
+ self.pdlg.pop(i)
986
+
987
+ self.pdlg.append(dlg)
988
+
989
+
990
+ class Startup(QtGui.QDialog):
991
+ """ Class to provide a startup display while PyGMI loads into memory """
992
+ def __init__(self, pbarmax, parent=None):
993
+ QtGui.QDialog.__init__(self, parent)
994
+ self.setWindowFlags(QtCore.Qt.ToolTip)
995
+
996
+ self.gridlayout_main = QtGui.QVBoxLayout(self)
997
+ self.label_info = QtGui.QLabel(self)
998
+ self.label_pic = QtGui.QLabel(self)
999
+ self.label_pic.setPixmap(QtGui.QPixmap(pygmi.__path__[0] +
1000
+ r'/images/logo256.ico'))
1001
+ self.label_info.setScaledContents(True)
1002
+ self.pbar = QtGui.QProgressBar(self)
1003
+
1004
+ labeltext = "<font color='red'>Py</font><font color='blue'>GMI</font>"
1005
+
1006
+ fnt = QtGui.QFont("Arial", 72, QtGui.QFont.Bold)
1007
+ self.label_info.setFont(fnt)
1008
+ self.label_info.setText(labeltext)
1009
+ self.gridlayout_main.addWidget(self.label_info)
1010
+ self.gridlayout_main.addWidget(self.label_pic)
1011
+
1012
+ self.pbar.setMaximum(pbarmax - 1)
1013
+ self.gridlayout_main.addWidget(self.pbar)
1014
+
1015
+ self.open()
1016
+
1017
+ def update(self):
1018
+ """ Updates the text on the dialog """
1019
+ self.pbar.setValue(self.pbar.value() + 1)
1020
+ QtGui.QApplication.processEvents()
1021
+
1022
+
1023
+ def main():
1024
+ """ Main entry point for the PyGMI software. """
1025
+ app = QtGui.QApplication(sys.argv)
1026
+ wid = MainWidget()
1027
+ wid.show()
1028
+
1029
+ wid.setWindowState(wid.windowState() & ~QtCore.Qt.WindowMinimized |
1030
+ QtCore.Qt.WindowActive)
1031
+
1032
+ # this will activate the window
1033
+ wid.activateWindow()
1034
+ sys.exit(app.exec_())
1035
+
1036
+ if __name__ == "__main__":
1037
+ main()