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.
- pygmi-2.2.7/LICENSE.txt +623 -0
- pygmi-2.2.7/MANIFEST.in +7 -0
- pygmi-2.2.7/PKG-INFO +47 -0
- pygmi-2.2.7/README.md +55 -0
- pygmi-2.2.7/README.rst +20 -0
- pygmi-2.2.7/log.txt +242 -0
- pygmi-2.2.7/pygmi/__init__.py +22 -0
- pygmi-2.2.7/pygmi/clust/__init__.py +4 -0
- pygmi-2.2.7/pygmi/clust/crisp_clust.py +708 -0
- pygmi-2.2.7/pygmi/clust/datatypes.py +65 -0
- pygmi-2.2.7/pygmi/clust/fuzzy_clust.py +906 -0
- pygmi-2.2.7/pygmi/clust/graphs.py +421 -0
- pygmi-2.2.7/pygmi/clust/graphtool.py +667 -0
- pygmi-2.2.7/pygmi/clust/menu.py +139 -0
- pygmi-2.2.7/pygmi/clust/var_ratio.py +92 -0
- pygmi-2.2.7/pygmi/clust/xie_beni.py +93 -0
- pygmi-2.2.7/pygmi/helpdocs/linepointer.png +0 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.main.html +31 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.ddisp.html +15 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.iodefs.exportkmz.html +13 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.iodefs.importpicture.html +16 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.layer.html +17 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.mext.html +44 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.misc.rangedcopy.html +16 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.param.html +37 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.prof.html +32 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.pview.html +26 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.cooper.gradients.html +14 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.cooper.tilt.html +14 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.cooper.visibility.html +14 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.datagrid.html +13 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.datamerge.html +11 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.datareproj.html +11 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.rtp.html +14 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.ginterp.html +31 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.igrf.html +20 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.normalisation.html +14 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.smooth.html +22 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.tiltdepth.html +20 -0
- pygmi-2.2.7/pygmi/images/Help.png +0 -0
- pygmi-2.2.7/pygmi/images/bringtofront.png +0 -0
- pygmi-2.2.7/pygmi/images/cgs2.emf +0 -0
- pygmi-2.2.7/pygmi/images/delete.png +0 -0
- pygmi-2.2.7/pygmi/images/linepointer.png +0 -0
- pygmi-2.2.7/pygmi/images/logo256.ico +0 -0
- pygmi-2.2.7/pygmi/images/logo256.png +0 -0
- pygmi-2.2.7/pygmi/images/pointer.png +0 -0
- pygmi-2.2.7/pygmi/images/pygmi.png +0 -0
- pygmi-2.2.7/pygmi/images/sendtoback.png +0 -0
- pygmi-2.2.7/pygmi/main.py +1037 -0
- pygmi-2.2.7/pygmi/menu_default.py +327 -0
- pygmi-2.2.7/pygmi/misc.py +147 -0
- pygmi-2.2.7/pygmi/pfmod/__init__.py +6 -0
- pygmi-2.2.7/pygmi/pfmod/cubes.py +1488 -0
- pygmi-2.2.7/pygmi/pfmod/datatypes.py +292 -0
- pygmi-2.2.7/pygmi/pfmod/grvmag3d.py +1265 -0
- pygmi-2.2.7/pygmi/pfmod/iodefs.py +1001 -0
- pygmi-2.2.7/pygmi/pfmod/menu.py +107 -0
- pygmi-2.2.7/pygmi/pfmod/misc.py +301 -0
- pygmi-2.2.7/pygmi/pfmod/pfmod.py +248 -0
- pygmi-2.2.7/pygmi/pfmod/tab_ddisp.py +425 -0
- pygmi-2.2.7/pygmi/pfmod/tab_layer.py +490 -0
- pygmi-2.2.7/pygmi/pfmod/tab_mext.py +544 -0
- pygmi-2.2.7/pygmi/pfmod/tab_param.py +548 -0
- pygmi-2.2.7/pygmi/pfmod/tab_prof.py +946 -0
- pygmi-2.2.7/pygmi/pfmod/tab_pview.py +740 -0
- pygmi-2.2.7/pygmi/raster/IGRF11.COF +1635 -0
- pygmi-2.2.7/pygmi/raster/__init__.py +14 -0
- pygmi-2.2.7/pygmi/raster/cooper.py +718 -0
- pygmi-2.2.7/pygmi/raster/dataprep.py +1640 -0
- pygmi-2.2.7/pygmi/raster/datatypes.py +123 -0
- pygmi-2.2.7/pygmi/raster/equation_editor.py +256 -0
- pygmi-2.2.7/pygmi/raster/ginterp.py +1901 -0
- pygmi-2.2.7/pygmi/raster/graphs.py +531 -0
- pygmi-2.2.7/pygmi/raster/igrf.py +860 -0
- pygmi-2.2.7/pygmi/raster/iodefs.py +813 -0
- pygmi-2.2.7/pygmi/raster/menu.py +307 -0
- pygmi-2.2.7/pygmi/raster/normalisation.py +187 -0
- pygmi-2.2.7/pygmi/raster/show_table.py +245 -0
- pygmi-2.2.7/pygmi/raster/smooth.py +406 -0
- pygmi-2.2.7/pygmi/raster/tiltdepth.py +590 -0
- pygmi-2.2.7/pygmi/seis/__init__.py +0 -0
- pygmi-2.2.7/pygmi/seis/beachball.py +751 -0
- pygmi-2.2.7/pygmi/seis/datatypes.py +605 -0
- pygmi-2.2.7/pygmi/seis/del_rec.py +410 -0
- pygmi-2.2.7/pygmi/seis/iodefs.py +1261 -0
- pygmi-2.2.7/pygmi/seis/menu.py +136 -0
- pygmi-2.2.7/pygmi/seis/scan_imp.py +795 -0
- pygmi-2.2.7/pygmi/test/__init__.py +6 -0
- pygmi-2.2.7/pygmi/test/pfmod.py +212 -0
- pygmi-2.2.7/pygmi/test/tests.py +39 -0
- pygmi-2.2.7/pygmi/vector/__init__.py +7 -0
- pygmi-2.2.7/pygmi/vector/datatypes.py +74 -0
- pygmi-2.2.7/pygmi/vector/graphs.py +443 -0
- pygmi-2.2.7/pygmi/vector/iodefs.py +345 -0
- pygmi-2.2.7/pygmi/vector/menu.py +127 -0
- pygmi-2.2.7/pygmi.egg-info/PKG-INFO +47 -0
- pygmi-2.2.7/pygmi.egg-info/SOURCES.txt +105 -0
- pygmi-2.2.7/pygmi.egg-info/dependency_links.txt +1 -0
- pygmi-2.2.7/pygmi.egg-info/entry_points.txt +3 -0
- pygmi-2.2.7/pygmi.egg-info/not-zip-safe +1 -0
- pygmi-2.2.7/pygmi.egg-info/requires.txt +7 -0
- pygmi-2.2.7/pygmi.egg-info/top_level.txt +1 -0
- pygmi-2.2.7/quickstart.py +35 -0
- pygmi-2.2.7/setup.cfg +8 -0
- 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()
|