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,946 @@
|
|
|
1
|
+
# -----------------------------------------------------------------------------
|
|
2
|
+
# Name: tab_prof.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
|
+
""" Profile Display Tab Routines """
|
|
26
|
+
|
|
27
|
+
from PyQt4 import QtGui, QtCore
|
|
28
|
+
import numpy as np
|
|
29
|
+
import scipy.interpolate as si
|
|
30
|
+
from . import misc
|
|
31
|
+
from ..raster import iodefs as ir
|
|
32
|
+
import os
|
|
33
|
+
|
|
34
|
+
import matplotlib.pyplot as plt
|
|
35
|
+
from matplotlib.backends.backend_qt4agg import FigureCanvas
|
|
36
|
+
from matplotlib.backends.backend_qt4agg import \
|
|
37
|
+
NavigationToolbar2QT as NavigationToolbar
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class ProfileDisplay(object):
|
|
41
|
+
""" Widget class to call the main interface """
|
|
42
|
+
def __init__(self, parent):
|
|
43
|
+
self.parent = parent
|
|
44
|
+
self.lmod1 = parent.lmod1
|
|
45
|
+
self.lmod2 = parent.lmod2
|
|
46
|
+
self.showtext = parent.showtext
|
|
47
|
+
self.pbar = self.parent.pbar_sub
|
|
48
|
+
self.viewmagnetics = True
|
|
49
|
+
|
|
50
|
+
self.userint = QtGui.QWidget()
|
|
51
|
+
|
|
52
|
+
self.mmc = MyMplCanvas(self, self.lmod1)
|
|
53
|
+
self.mpl_toolbar = NavigationToolbar(self.mmc, self.userint)
|
|
54
|
+
|
|
55
|
+
self.sb_profnum = QtGui.QSpinBox()
|
|
56
|
+
self.hs_profnum = MySlider()
|
|
57
|
+
self.combo_profpic = QtGui.QComboBox()
|
|
58
|
+
self.hs_ppic_opacity = MySlider()
|
|
59
|
+
self.rb_axis_datamax = QtGui.QRadioButton()
|
|
60
|
+
self.rb_axis_profmax = QtGui.QRadioButton()
|
|
61
|
+
self.rb_axis_calcmax = QtGui.QRadioButton()
|
|
62
|
+
self.rb_axis_custmax = QtGui.QRadioButton()
|
|
63
|
+
self.dsb_axis_custmin = QtGui.QDoubleSpinBox()
|
|
64
|
+
self.dsb_axis_custmax = QtGui.QDoubleSpinBox()
|
|
65
|
+
self.sb_profile_linethick = QtGui.QSpinBox()
|
|
66
|
+
self.lw_prof_defs = QtGui.QListWidget()
|
|
67
|
+
self.pb_prof_rcopy = QtGui.QPushButton()
|
|
68
|
+
self.pb_lbound = QtGui.QPushButton()
|
|
69
|
+
self.pb_export_csv = QtGui.QPushButton()
|
|
70
|
+
|
|
71
|
+
self.setupui()
|
|
72
|
+
|
|
73
|
+
def setupui(self):
|
|
74
|
+
""" Setup UI """
|
|
75
|
+
gridlayout = QtGui.QGridLayout(self.userint)
|
|
76
|
+
groupbox = QtGui.QGroupBox()
|
|
77
|
+
verticallayout = QtGui.QVBoxLayout(groupbox)
|
|
78
|
+
|
|
79
|
+
sizepolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred,
|
|
80
|
+
QtGui.QSizePolicy.Fixed)
|
|
81
|
+
|
|
82
|
+
self.hs_profnum.setSizePolicy(sizepolicy)
|
|
83
|
+
self.hs_ppic_opacity.setSizePolicy(sizepolicy)
|
|
84
|
+
|
|
85
|
+
self.lw_prof_defs.setFixedWidth(220)
|
|
86
|
+
self.sb_profnum.setWrapping(True)
|
|
87
|
+
self.sb_profnum.setMaximum(999999999)
|
|
88
|
+
self.hs_profnum.setOrientation(QtCore.Qt.Horizontal)
|
|
89
|
+
self.hs_ppic_opacity.setMaximum(255)
|
|
90
|
+
self.hs_ppic_opacity.setProperty("value", 255)
|
|
91
|
+
self.hs_ppic_opacity.setOrientation(QtCore.Qt.Horizontal)
|
|
92
|
+
self.hs_ppic_opacity.setTickPosition(QtGui.QSlider.TicksAbove)
|
|
93
|
+
self.dsb_axis_custmin.setValue(0.)
|
|
94
|
+
self.dsb_axis_custmax.setValue(50.)
|
|
95
|
+
self.dsb_axis_custmin.setMinimum(-1000000.)
|
|
96
|
+
self.dsb_axis_custmin.setMaximum(1000000.)
|
|
97
|
+
self.dsb_axis_custmax.setMinimum(-1000000.)
|
|
98
|
+
self.dsb_axis_custmax.setMaximum(1000000.)
|
|
99
|
+
self.sb_profile_linethick.setMinimum(1)
|
|
100
|
+
self.sb_profile_linethick.setMaximum(1000)
|
|
101
|
+
self.rb_axis_datamax.setChecked(True)
|
|
102
|
+
|
|
103
|
+
groupbox.setTitle("Profile Y-Axis Scale")
|
|
104
|
+
self.sb_profnum.setPrefix("Profile: ")
|
|
105
|
+
self.rb_axis_datamax.setText("Scale to dataset maximum")
|
|
106
|
+
self.rb_axis_profmax.setText("Scale to profile maximum")
|
|
107
|
+
self.rb_axis_calcmax.setText("Scale to calculated maximum")
|
|
108
|
+
self.rb_axis_custmax.setText("Scale to custom maximum")
|
|
109
|
+
self.sb_profile_linethick.setPrefix("Line Thickness: ")
|
|
110
|
+
self.pb_prof_rcopy.setText("Ranged Copy")
|
|
111
|
+
self.pb_lbound.setText("Add Lithological Boundary")
|
|
112
|
+
self.pb_export_csv.setText("Export Profile")
|
|
113
|
+
|
|
114
|
+
gridlayout.addWidget(self.mpl_toolbar, 0, 0, 1, 1)
|
|
115
|
+
gridlayout.addWidget(self.mmc, 1, 0, 9, 1)
|
|
116
|
+
gridlayout.addWidget(self.sb_profnum, 0, 1, 1, 1)
|
|
117
|
+
gridlayout.addWidget(self.hs_profnum, 1, 1, 1, 1)
|
|
118
|
+
gridlayout.addWidget(self.combo_profpic, 2, 1, 1, 1)
|
|
119
|
+
gridlayout.addWidget(self.hs_ppic_opacity, 3, 1, 1, 1)
|
|
120
|
+
gridlayout.addWidget(self.lw_prof_defs, 4, 1, 1, 1)
|
|
121
|
+
gridlayout.addWidget(self.sb_profile_linethick, 5, 1, 1, 1)
|
|
122
|
+
gridlayout.addWidget(groupbox, 6, 1, 1, 1)
|
|
123
|
+
gridlayout.addWidget(self.pb_prof_rcopy, 7, 1, 1, 1)
|
|
124
|
+
gridlayout.addWidget(self.pb_lbound, 8, 1, 1, 1)
|
|
125
|
+
gridlayout.addWidget(self.pb_export_csv, 9, 1, 1, 1)
|
|
126
|
+
|
|
127
|
+
verticallayout.addWidget(self.rb_axis_datamax)
|
|
128
|
+
verticallayout.addWidget(self.rb_axis_profmax)
|
|
129
|
+
verticallayout.addWidget(self.rb_axis_calcmax)
|
|
130
|
+
verticallayout.addWidget(self.rb_axis_custmax)
|
|
131
|
+
verticallayout.addWidget(self.dsb_axis_custmin)
|
|
132
|
+
verticallayout.addWidget(self.dsb_axis_custmax)
|
|
133
|
+
|
|
134
|
+
# Buttons etc
|
|
135
|
+
self.sb_profile_linethick.valueChanged.connect(self.width)
|
|
136
|
+
self.lw_prof_defs.currentItemChanged.connect(self.change_defs)
|
|
137
|
+
self.pb_prof_rcopy.clicked.connect(self.rcopy)
|
|
138
|
+
self.pb_lbound.clicked.connect(self.lbound)
|
|
139
|
+
self.hs_profnum.valueChanged.connect(self.hprofnum)
|
|
140
|
+
self.hs_profnum.sliderReleased.connect(self.hprofnum)
|
|
141
|
+
self.sb_profnum.valueChanged.connect(self.sprofnum)
|
|
142
|
+
self.rb_axis_calcmax.clicked.connect(self.rb_plot_scale)
|
|
143
|
+
self.rb_axis_profmax.clicked.connect(self.rb_plot_scale)
|
|
144
|
+
self.rb_axis_datamax.clicked.connect(self.rb_plot_scale)
|
|
145
|
+
self.rb_axis_custmax.clicked.connect(self.rb_plot_scale)
|
|
146
|
+
self.dsb_axis_custmin.valueChanged.connect(self.rb_plot_scale)
|
|
147
|
+
self.dsb_axis_custmax.valueChanged.connect(self.rb_plot_scale)
|
|
148
|
+
self.pb_export_csv.clicked.connect(self.export_csv)
|
|
149
|
+
self.hs_ppic_opacity.valueChanged.connect(self.profpic_hs)
|
|
150
|
+
self.combo_profpic.currentIndexChanged.connect(self.profpic_hs)
|
|
151
|
+
|
|
152
|
+
def change_defs(self):
|
|
153
|
+
""" List box in profile tab for definitions """
|
|
154
|
+
|
|
155
|
+
i = self.lw_prof_defs.currentRow()
|
|
156
|
+
if i == -1:
|
|
157
|
+
misc.update_lith_lw(self.lmod1, self.lw_prof_defs)
|
|
158
|
+
i = 0
|
|
159
|
+
itxt = str(self.lw_prof_defs.item(i).text())
|
|
160
|
+
|
|
161
|
+
if itxt not in self.lmod1.lith_list.keys():
|
|
162
|
+
return
|
|
163
|
+
|
|
164
|
+
lith = self.lmod1.lith_list[itxt]
|
|
165
|
+
self.mmc.curmodel = lith.lith_index
|
|
166
|
+
|
|
167
|
+
def change_model(self, slide=False):
|
|
168
|
+
""" Change Model """
|
|
169
|
+
|
|
170
|
+
bottom = self.lmod1.zrange[0]
|
|
171
|
+
top = self.lmod1.zrange[1]
|
|
172
|
+
|
|
173
|
+
# First we plot the model stuff
|
|
174
|
+
newprof = self.lmod1.curprof
|
|
175
|
+
if self.lmod1.is_ew:
|
|
176
|
+
# gtmp = self.lmod1.lith_index[:, newprof,:].T.copy()
|
|
177
|
+
gtmp = self.lmod1.lith_index[:, newprof, ::-1].T.copy()
|
|
178
|
+
left = self.lmod1.xrange[0]
|
|
179
|
+
right = self.lmod1.xrange[1]
|
|
180
|
+
else:
|
|
181
|
+
# gtmp = self.lmod1.lith_index[newprof,:,:].T.copy()
|
|
182
|
+
gtmp = self.lmod1.lith_index[newprof, :, ::-1].T.copy()
|
|
183
|
+
left = self.lmod1.yrange[0]
|
|
184
|
+
right = self.lmod1.yrange[1]
|
|
185
|
+
|
|
186
|
+
extent = (left, right, bottom, top)
|
|
187
|
+
|
|
188
|
+
ctxt = str(self.combo_profpic.currentText())
|
|
189
|
+
if len(self.lmod1.profpics) > 0 and ctxt != u'':
|
|
190
|
+
gtmpl = self.lmod1.profpics[ctxt]
|
|
191
|
+
opac = self.hs_ppic_opacity.value()/self.hs_ppic_opacity.maximum()
|
|
192
|
+
else:
|
|
193
|
+
gtmpl = None
|
|
194
|
+
opac = 1.0
|
|
195
|
+
|
|
196
|
+
if slide is True:
|
|
197
|
+
self.mmc.slide_grid(gtmp, gtmpl, opac)
|
|
198
|
+
else:
|
|
199
|
+
self.mmc.init_grid(gtmp, extent, gtmpl, opac)
|
|
200
|
+
|
|
201
|
+
alt = self.lmod1.zrange[1]-self.lmod1.curlayer*self.lmod1.d_z
|
|
202
|
+
|
|
203
|
+
if self.lmod1.is_ew:
|
|
204
|
+
self.mmc.update_line(self.lmod1.xrange, [alt, alt])
|
|
205
|
+
else:
|
|
206
|
+
self.mmc.update_line(self.lmod1.yrange, [alt, alt])
|
|
207
|
+
|
|
208
|
+
def export_csv(self):
|
|
209
|
+
""" Export Profile to csv """
|
|
210
|
+
self.parent.pbars.resetall()
|
|
211
|
+
filename = QtGui.QFileDialog.getSaveFileName(
|
|
212
|
+
self.parent, 'Save File', '.', 'Comma separated values (*.csv)')
|
|
213
|
+
if filename == '':
|
|
214
|
+
return
|
|
215
|
+
os.chdir(filename.rpartition('/')[0])
|
|
216
|
+
|
|
217
|
+
maggrid = self.lmod1.griddata['Calculated Magnetics'].data
|
|
218
|
+
grvgrid = self.lmod1.griddata['Calculated Gravity'].data
|
|
219
|
+
curprof = self.lmod1.curprof
|
|
220
|
+
|
|
221
|
+
if self.lmod1.is_ew:
|
|
222
|
+
cmag = maggrid[-curprof-1]
|
|
223
|
+
cgrv = grvgrid[-curprof-1]
|
|
224
|
+
xrng = (np.arange(cmag.shape[0])*self.lmod1.dxy +
|
|
225
|
+
self.lmod1.xrange[0]+self.lmod1.dxy/2.)
|
|
226
|
+
yrng = np.zeros_like(xrng)+self.lmod1.dxy/2.
|
|
227
|
+
|
|
228
|
+
else:
|
|
229
|
+
cmag = maggrid[::-1, curprof]
|
|
230
|
+
cgrv = grvgrid[::-1, curprof]
|
|
231
|
+
yrng = (np.arange(cmag.shape[0])*self.lmod1.dxy +
|
|
232
|
+
self.lmod1.yrange[0]+self.lmod1.dxy/2.)
|
|
233
|
+
xrng = np.zeros_like(yrng)+self.lmod1.dxy/2.
|
|
234
|
+
|
|
235
|
+
newdata = np.transpose([xrng, yrng, cgrv, cmag])
|
|
236
|
+
|
|
237
|
+
fno = open(filename, 'wb')
|
|
238
|
+
fno.write(b'"x","y","Gravity","Magnetics"\n')
|
|
239
|
+
np.savetxt(fno, newdata, delimiter=',')
|
|
240
|
+
fno.close()
|
|
241
|
+
self.parent.pbars.incr()
|
|
242
|
+
self.showtext('Profile save complete')
|
|
243
|
+
|
|
244
|
+
def lbound_dialog(self):
|
|
245
|
+
""" Main routine to perform actual ranged copy """
|
|
246
|
+
lmod1 = self.lmod1
|
|
247
|
+
lbnd = LithBound()
|
|
248
|
+
lw_lithupper = lbnd.lw_lithupper
|
|
249
|
+
lw_lithlower = lbnd.lw_lithlower
|
|
250
|
+
|
|
251
|
+
lw_lithupper.addItem(r'Do Not Change')
|
|
252
|
+
lw_lithlower.addItem(r'Do Not Change')
|
|
253
|
+
for i in lmod1.lith_list.keys():
|
|
254
|
+
lw_lithupper.addItem(i)
|
|
255
|
+
lw_lithlower.addItem(i)
|
|
256
|
+
|
|
257
|
+
lw_lithupper.setCurrentItem(lw_lithupper.item(0))
|
|
258
|
+
lw_lithlower.setCurrentItem(lw_lithlower.item(1))
|
|
259
|
+
|
|
260
|
+
tmp = lbnd.exec_()
|
|
261
|
+
if tmp == 0:
|
|
262
|
+
return
|
|
263
|
+
|
|
264
|
+
tupper = lw_lithupper.selectedItems()
|
|
265
|
+
tlower = lw_lithlower.selectedItems()
|
|
266
|
+
|
|
267
|
+
if tupper[0].text() == r'Do Not Change':
|
|
268
|
+
lithupper = -999
|
|
269
|
+
else:
|
|
270
|
+
lithupper = lmod1.lith_list[tupper[0].text()].lith_index
|
|
271
|
+
|
|
272
|
+
if tlower[0].text() == r'Do Not Change':
|
|
273
|
+
lithlower = -999
|
|
274
|
+
else:
|
|
275
|
+
lithlower = lmod1.lith_list[tlower[0].text()].lith_index
|
|
276
|
+
|
|
277
|
+
return lithlower, lithupper
|
|
278
|
+
|
|
279
|
+
def lbound(self):
|
|
280
|
+
""" Insert a lithological boundary """
|
|
281
|
+
curgrid = self.load_data()
|
|
282
|
+
if curgrid is None:
|
|
283
|
+
return
|
|
284
|
+
|
|
285
|
+
self.update_model()
|
|
286
|
+
lowerb, upperb = self.lbound_dialog()
|
|
287
|
+
|
|
288
|
+
if lowerb == -999 and upperb == -999:
|
|
289
|
+
return
|
|
290
|
+
|
|
291
|
+
cols = curgrid.cols
|
|
292
|
+
rows = curgrid.rows
|
|
293
|
+
tlx = curgrid.tlx
|
|
294
|
+
tly = curgrid.tly
|
|
295
|
+
d_x = curgrid.xdim
|
|
296
|
+
d_y = curgrid.ydim
|
|
297
|
+
regz = self.lmod1.zrange[1]
|
|
298
|
+
d_z = self.lmod1.d_z
|
|
299
|
+
|
|
300
|
+
gxrng = np.array([tlx+i*d_x for i in range(cols)])
|
|
301
|
+
gyrng = np.array([(tly-(rows-1)*d_y)+i*d_y for i in range(rows)])
|
|
302
|
+
|
|
303
|
+
# This section gets rid of null values quickly
|
|
304
|
+
xt, yt = np.meshgrid(gxrng, gyrng)
|
|
305
|
+
zt = curgrid.data.data
|
|
306
|
+
msk = np.logical_not(np.logical_or(curgrid.data.mask, np.isnan(zt)))
|
|
307
|
+
zt = zt[msk]
|
|
308
|
+
xy = np.transpose([xt[msk], yt[msk]])
|
|
309
|
+
xy2 = np.transpose([xt, yt])
|
|
310
|
+
newgrid = np.transpose(si.griddata(xy, zt, xy2, 'nearest'))
|
|
311
|
+
|
|
312
|
+
# Back to splines
|
|
313
|
+
fgrid = si.RectBivariateSpline(gyrng, gxrng, newgrid)
|
|
314
|
+
|
|
315
|
+
for i in range(self.lmod1.numx):
|
|
316
|
+
for j in range(self.lmod1.numy):
|
|
317
|
+
imod = i*self.lmod1.dxy+self.lmod1.xrange[0]
|
|
318
|
+
jmod = j*self.lmod1.dxy+self.lmod1.yrange[0]
|
|
319
|
+
|
|
320
|
+
igrd = int((imod-tlx)/d_x)
|
|
321
|
+
jgrd = int((tly-jmod)/d_y)
|
|
322
|
+
|
|
323
|
+
if igrd >= 0 and jgrd >= 0 and igrd < cols and jgrd < rows:
|
|
324
|
+
# k_2 = int((regz-fgrid.ev(jmod, imod))/d_z)
|
|
325
|
+
k_2 = int((regz-fgrid(jmod, imod))/d_z)
|
|
326
|
+
if k_2 < 0:
|
|
327
|
+
k_2 = 0
|
|
328
|
+
lfilt = self.lmod1.lith_index[i, j, k_2:] != -1
|
|
329
|
+
ufilt = self.lmod1.lith_index[i, j, :k_2] != -1
|
|
330
|
+
if lowerb != -999:
|
|
331
|
+
self.lmod1.lith_index[i, j, k_2:][lfilt] = lowerb
|
|
332
|
+
if upperb != -999:
|
|
333
|
+
self.lmod1.lith_index[i, j, :k_2][ufilt] = upperb
|
|
334
|
+
|
|
335
|
+
self.change_model()
|
|
336
|
+
self.update_plot()
|
|
337
|
+
|
|
338
|
+
def load_data(self):
|
|
339
|
+
""" Used to load Layer data"""
|
|
340
|
+
self.pbar.setMaximum(100)
|
|
341
|
+
self.pbar.setValue(0)
|
|
342
|
+
|
|
343
|
+
dtmp = ir.ImportData()
|
|
344
|
+
tmp = dtmp.settings()
|
|
345
|
+
if tmp is False:
|
|
346
|
+
return None
|
|
347
|
+
data = dtmp.outdata['Raster']
|
|
348
|
+
|
|
349
|
+
data[0].data = data[0].data
|
|
350
|
+
data[0].data = data[0].data[::-1] # need this reversed
|
|
351
|
+
|
|
352
|
+
self.pbar.setValue(100)
|
|
353
|
+
return data[0]
|
|
354
|
+
|
|
355
|
+
def profpic_hs(self):
|
|
356
|
+
""" Horizontal slider to change the profile """
|
|
357
|
+
self.update_model()
|
|
358
|
+
self.change_model(slide=True)
|
|
359
|
+
self.update_plot(slide=True)
|
|
360
|
+
|
|
361
|
+
def sprofnum(self):
|
|
362
|
+
""" Routine to change a profile from spinbox"""
|
|
363
|
+
self.hs_profnum.valueChanged.disconnect()
|
|
364
|
+
self.hs_profnum.setValue(self.sb_profnum.value())
|
|
365
|
+
self.hs_profnum.valueChanged.connect(self.hprofnum)
|
|
366
|
+
|
|
367
|
+
self.update_model()
|
|
368
|
+
self.lmod1.curprof = self.sb_profnum.value()
|
|
369
|
+
self.change_model(slide=True)
|
|
370
|
+
self.update_plot(slide=False)
|
|
371
|
+
|
|
372
|
+
def hprofnum(self):
|
|
373
|
+
""" Routine to change a profile from spinbox"""
|
|
374
|
+
self.sb_profnum.valueChanged.disconnect()
|
|
375
|
+
self.sb_profnum.setValue(self.hs_profnum.sliderPosition())
|
|
376
|
+
self.sb_profnum.valueChanged.connect(self.sprofnum)
|
|
377
|
+
|
|
378
|
+
self.update_model()
|
|
379
|
+
self.lmod1.curprof = self.sb_profnum.value()
|
|
380
|
+
self.change_model(slide=True)
|
|
381
|
+
self.update_plot(slide=self.hs_profnum.isSliderDown())
|
|
382
|
+
|
|
383
|
+
def rcopy(self):
|
|
384
|
+
""" Do a ranged copy on a profile """
|
|
385
|
+
self.update_model()
|
|
386
|
+
misc.rcopy_dialog(self.lmod1, islayer=False,
|
|
387
|
+
is_ew=self.lmod1.is_ew)
|
|
388
|
+
|
|
389
|
+
def update_model(self):
|
|
390
|
+
""" Update model itself """
|
|
391
|
+
if self.lmod1.is_ew:
|
|
392
|
+
tmp = self.lmod1.lith_index[:, self.lmod1.curprof, ::-1]
|
|
393
|
+
else:
|
|
394
|
+
tmp = self.lmod1.lith_index[self.lmod1.curprof, :, ::-1]
|
|
395
|
+
|
|
396
|
+
if tmp.shape != self.mmc.mdata.T.shape:
|
|
397
|
+
return
|
|
398
|
+
|
|
399
|
+
if self.lmod1.is_ew:
|
|
400
|
+
self.lmod1.lith_index[:, self.lmod1.curprof, ::-1] = (
|
|
401
|
+
self.mmc.mdata.T.copy())
|
|
402
|
+
else:
|
|
403
|
+
self.lmod1.lith_index[self.lmod1.curprof, :, ::-1] = (
|
|
404
|
+
self.mmc.mdata.T.copy())
|
|
405
|
+
|
|
406
|
+
def rb_plot_scale(self):
|
|
407
|
+
""" plot scale """
|
|
408
|
+
self.change_model()
|
|
409
|
+
self.update_plot()
|
|
410
|
+
self.mpl_toolbar.update()
|
|
411
|
+
|
|
412
|
+
def update_plot(self, slide=False):
|
|
413
|
+
""" Update the profile on the model view """
|
|
414
|
+
|
|
415
|
+
# Display the calculated profile
|
|
416
|
+
data = None
|
|
417
|
+
if self.viewmagnetics:
|
|
418
|
+
if 'Calculated Magnetics' in self.lmod1.griddata.keys():
|
|
419
|
+
data = self.lmod1.griddata['Calculated Magnetics'].data
|
|
420
|
+
# data2 = self.lmod2.griddata['Calculated Magnetics'].data
|
|
421
|
+
self.mmc.ptitle = 'Magnetic Intensity: '
|
|
422
|
+
self.mmc.punit = 'nT'
|
|
423
|
+
regtmp = 0.0
|
|
424
|
+
else:
|
|
425
|
+
if 'Calculated Gravity' in self.lmod1.griddata.keys():
|
|
426
|
+
data = self.lmod1.griddata['Calculated Gravity'].data
|
|
427
|
+
# data2 = self.lmod2.griddata['Calculated Gravity'].data
|
|
428
|
+
self.mmc.ptitle = 'Gravity: '
|
|
429
|
+
self.mmc.punit = 'mGal'
|
|
430
|
+
regtmp = self.lmod1.gregional
|
|
431
|
+
|
|
432
|
+
# if data2.shape != data.shape:
|
|
433
|
+
# data2 = np.zeros_like(data)
|
|
434
|
+
# alt = self.lmod1.zrange[1]-self.lmod1.curlayer*self.lmod1.d_z
|
|
435
|
+
|
|
436
|
+
if self.lmod1.is_ew and data is not None:
|
|
437
|
+
self.mmc.ptitle += 'West to East'
|
|
438
|
+
self.mmc.xlabel = "Eastings (m)"
|
|
439
|
+
|
|
440
|
+
tmpprof = data[self.lmod1.numy-1-self.lmod1.curprof, :]+regtmp
|
|
441
|
+
# tmpprof2 = data2[self.lmod1.curprof, :]
|
|
442
|
+
tmprng = (np.arange(tmpprof.shape[0])*self.lmod1.dxy +
|
|
443
|
+
self.lmod1.xrange[0]+self.lmod1.dxy/2.)
|
|
444
|
+
self.sb_profnum.setMaximum(self.lmod1.numy-1)
|
|
445
|
+
# self.mmc.update_line(self.lmod1.xrange, [alt, alt])
|
|
446
|
+
extent = self.lmod1.xrange
|
|
447
|
+
|
|
448
|
+
elif not(self.lmod1.is_ew) and data is not None:
|
|
449
|
+
self.mmc.ptitle += 'South to North'
|
|
450
|
+
self.mmc.xlabel = "Northings (m)"
|
|
451
|
+
|
|
452
|
+
tmpprof = data[::-1, self.lmod1.curprof]+regtmp
|
|
453
|
+
# tmpprof2 = data2[:, self.lmod1.curprof]
|
|
454
|
+
tmprng = (np.arange(tmpprof.shape[0])*self.lmod1.dxy +
|
|
455
|
+
self.lmod1.yrange[0]+self.lmod1.dxy/2.)
|
|
456
|
+
self.sb_profnum.setMaximum(self.lmod1.numx-1)
|
|
457
|
+
# self.mmc.update_line(self.lmod1.yrange, [alt, alt])
|
|
458
|
+
extent = self.lmod1.yrange
|
|
459
|
+
|
|
460
|
+
if self.rb_axis_custmax.isChecked():
|
|
461
|
+
extent = list(extent)+[self.dsb_axis_custmin.value(),
|
|
462
|
+
self.dsb_axis_custmax.value()]
|
|
463
|
+
elif self.rb_axis_calcmax.isChecked():
|
|
464
|
+
extent = list(extent)+[data.min()+regtmp, data.max()+regtmp]
|
|
465
|
+
else:
|
|
466
|
+
extent = list(extent)+[tmpprof.min(), tmpprof.max()]
|
|
467
|
+
|
|
468
|
+
# Load in observed data - if there is any
|
|
469
|
+
data2 = None
|
|
470
|
+
tmprng2 = None
|
|
471
|
+
tmpprof2 = None
|
|
472
|
+
if ('Magnetic Dataset' in self.lmod1.griddata.keys() and
|
|
473
|
+
self.viewmagnetics):
|
|
474
|
+
data2 = self.lmod1.griddata['Magnetic Dataset']
|
|
475
|
+
# regtmp = 0.0
|
|
476
|
+
elif ('Gravity Dataset' in self.lmod1.griddata.keys() and
|
|
477
|
+
not self.viewmagnetics):
|
|
478
|
+
data2 = self.lmod1.griddata['Gravity Dataset']
|
|
479
|
+
# regtmp = self.lmod1.gregional
|
|
480
|
+
|
|
481
|
+
if data2 is not None:
|
|
482
|
+
if self.lmod1.is_ew:
|
|
483
|
+
ycrdl = self.lmod1.yrange[0]+self.lmod1.curprof*self.lmod1.dxy
|
|
484
|
+
# ycrdl = self.lmod1.yrange[1]-self.lmod1.curprof*self.lmod1.dxy
|
|
485
|
+
ycrd = int((data2.tly - ycrdl)/data2.ydim)
|
|
486
|
+
# ycrd = data2.rows-int((data2.tly - ycrdl)/data2.ydim)
|
|
487
|
+
|
|
488
|
+
if ycrd < 0 or ycrd >= data2.rows:
|
|
489
|
+
if slide is False:
|
|
490
|
+
self.mmc.init_plot(tmprng, tmpprof, extent, tmprng2,
|
|
491
|
+
tmpprof2)
|
|
492
|
+
else:
|
|
493
|
+
self.mmc.slide_plot(tmprng, tmpprof, extent, tmprng2,
|
|
494
|
+
tmpprof2)
|
|
495
|
+
return
|
|
496
|
+
else:
|
|
497
|
+
tmpprof2 = data2.data[ycrd, :]
|
|
498
|
+
tmprng2 = (data2.tlx + np.arange(data2.cols)*data2.xdim +
|
|
499
|
+
data2.xdim/2)
|
|
500
|
+
else:
|
|
501
|
+
xcrdl = self.lmod1.xrange[0]+self.lmod1.curprof*self.lmod1.dxy
|
|
502
|
+
xcrd = int((xcrdl-data2.tlx)/data2.xdim)
|
|
503
|
+
|
|
504
|
+
if xcrd < 0 or xcrd >= data2.cols:
|
|
505
|
+
if slide is False:
|
|
506
|
+
self.mmc.init_plot(tmprng, tmpprof, extent, tmprng2,
|
|
507
|
+
tmpprof2)
|
|
508
|
+
else:
|
|
509
|
+
self.mmc.slide_plot(tmprng, tmpprof, extent, tmprng2,
|
|
510
|
+
tmpprof2)
|
|
511
|
+
return
|
|
512
|
+
else:
|
|
513
|
+
tmpprof2 = data2.data[::-1, xcrd]
|
|
514
|
+
tmprng2 = (data2.tly-data2.rows*data2.ydim +
|
|
515
|
+
np.arange(data2.rows)*data2.ydim + data2.ydim/2)
|
|
516
|
+
|
|
517
|
+
tmpprof2 = tmpprof2[tmprng2 >= tmprng[0]] # must be before tmprng2
|
|
518
|
+
tmprng2 = tmprng2[tmprng2 >= tmprng[0]]
|
|
519
|
+
tmpprof2 = tmpprof2[tmprng2 <= tmprng[-1]] # must bebefore tmprng2
|
|
520
|
+
tmprng2 = tmprng2[tmprng2 <= tmprng[-1]]
|
|
521
|
+
|
|
522
|
+
nomask = np.logical_not(tmpprof2.mask)
|
|
523
|
+
tmprng2 = tmprng2[nomask]
|
|
524
|
+
tmpprof2 = tmpprof2[nomask]
|
|
525
|
+
|
|
526
|
+
if self.rb_axis_datamax.isChecked():
|
|
527
|
+
extent[2:] = [data2.data.min(), data2.data.max()]
|
|
528
|
+
elif self.rb_axis_profmax.isChecked():
|
|
529
|
+
extent[2:] = [tmpprof2.min(), tmpprof2.max()]
|
|
530
|
+
|
|
531
|
+
if slide is True:
|
|
532
|
+
self.mmc.slide_plot(tmprng, tmpprof, extent, tmprng2, tmpprof2)
|
|
533
|
+
else:
|
|
534
|
+
self.mmc.init_plot(tmprng, tmpprof, extent, tmprng2, tmpprof2)
|
|
535
|
+
|
|
536
|
+
def width(self, width):
|
|
537
|
+
""" Sets the width of the edits on the profile view """
|
|
538
|
+
|
|
539
|
+
self.mmc.width = width
|
|
540
|
+
|
|
541
|
+
def tab_activate(self):
|
|
542
|
+
""" Runs when the tab is activated """
|
|
543
|
+
self.lmod1 = self.parent.lmod1
|
|
544
|
+
self.mmc.lmod = self.lmod1
|
|
545
|
+
|
|
546
|
+
txtmsg = ('Note: The display of gravity or magnetic data is '
|
|
547
|
+
'triggered off their respective calculations. Press '
|
|
548
|
+
'"Calculate Gravity" to see the gravity plot and '
|
|
549
|
+
'"Calculate Magnetics" to see the magnetic plot')
|
|
550
|
+
|
|
551
|
+
if txtmsg not in self.parent.txtmsg.split('\n'):
|
|
552
|
+
self.showtext(txtmsg)
|
|
553
|
+
|
|
554
|
+
misc.update_lith_lw(self.lmod1, self.lw_prof_defs)
|
|
555
|
+
|
|
556
|
+
self.hs_profnum.valueChanged.disconnect()
|
|
557
|
+
self.combo_profpic.currentIndexChanged.disconnect()
|
|
558
|
+
self.sb_profnum.valueChanged.disconnect()
|
|
559
|
+
|
|
560
|
+
self.hs_profnum.setMinimum(0)
|
|
561
|
+
if self.lmod1.is_ew:
|
|
562
|
+
self.hs_profnum.setMaximum(self.lmod1.numy-1)
|
|
563
|
+
else:
|
|
564
|
+
self.hs_profnum.setMaximum(self.lmod1.numx-1)
|
|
565
|
+
|
|
566
|
+
if len(self.lmod1.profpics) > 0:
|
|
567
|
+
self.combo_profpic.clear()
|
|
568
|
+
self.combo_profpic.addItems(list(self.lmod1.profpics.keys()))
|
|
569
|
+
self.combo_profpic.setCurrentIndex(0)
|
|
570
|
+
|
|
571
|
+
self.change_model() # needs to happen before profnum set value
|
|
572
|
+
self.sb_profnum.setValue(self.lmod1.curprof)
|
|
573
|
+
self.hs_profnum.setValue(self.sb_profnum.value())
|
|
574
|
+
self.update_plot()
|
|
575
|
+
# self.change_model() # needs to happen before profnum set value
|
|
576
|
+
self.sb_profnum.valueChanged.connect(self.sprofnum)
|
|
577
|
+
self.hs_profnum.valueChanged.connect(self.hprofnum)
|
|
578
|
+
self.combo_profpic.currentIndexChanged.connect(self.profpic_hs)
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
class LithBound(QtGui.QDialog):
|
|
582
|
+
""" Class to call up a dialog for lithological boundary"""
|
|
583
|
+
def __init__(self, parent=None):
|
|
584
|
+
QtGui.QDialog.__init__(self, parent)
|
|
585
|
+
|
|
586
|
+
self.gridlayout = QtGui.QGridLayout(self)
|
|
587
|
+
self.buttonbox = QtGui.QDialogButtonBox(self)
|
|
588
|
+
self.lw_lithupper = QtGui.QListWidget(self)
|
|
589
|
+
self.lw_lithlower = QtGui.QListWidget(self)
|
|
590
|
+
self.label_3 = QtGui.QLabel(self)
|
|
591
|
+
self.label_4 = QtGui.QLabel(self)
|
|
592
|
+
self.setupui()
|
|
593
|
+
|
|
594
|
+
def setupui(self):
|
|
595
|
+
""" Setup UI """
|
|
596
|
+
self.gridlayout.addWidget(self.label_3, 0, 0, 1, 1)
|
|
597
|
+
self.lw_lithupper.setSelectionMode(
|
|
598
|
+
QtGui.QAbstractItemView.SingleSelection)
|
|
599
|
+
self.gridlayout.addWidget(self.lw_lithupper, 0, 1, 1, 1)
|
|
600
|
+
self.gridlayout.addWidget(self.label_4, 1, 0, 1, 1)
|
|
601
|
+
self.lw_lithlower.setSelectionMode(
|
|
602
|
+
QtGui.QAbstractItemView.SingleSelection)
|
|
603
|
+
self.gridlayout.addWidget(self.lw_lithlower, 1, 1, 1, 1)
|
|
604
|
+
self.buttonbox.setOrientation(QtCore.Qt.Horizontal)
|
|
605
|
+
self.buttonbox.setStandardButtons(
|
|
606
|
+
QtGui.QDialogButtonBox.Cancel | QtGui.QDialogButtonBox.Ok)
|
|
607
|
+
self.gridlayout.addWidget(self.buttonbox, 2, 0, 1, 2)
|
|
608
|
+
|
|
609
|
+
self.setWindowTitle("Add Lithological Boundary")
|
|
610
|
+
self.label_3.setText("Lithologies Above Layer")
|
|
611
|
+
self.label_4.setText("Lithologies Below Layer")
|
|
612
|
+
|
|
613
|
+
self.buttonbox.accepted.connect(self.accept)
|
|
614
|
+
self.buttonbox.rejected.connect(self.reject)
|
|
615
|
+
|
|
616
|
+
# QtCore.QMetaObject.connectSlotsByName(Dialog)
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
class MyMplCanvas(FigureCanvas):
|
|
620
|
+
"""This is a QWidget"""
|
|
621
|
+
def __init__(self, parent, lmod):
|
|
622
|
+
# fig = Figure()
|
|
623
|
+
fig = plt.figure()
|
|
624
|
+
FigureCanvas.__init__(self, fig)
|
|
625
|
+
|
|
626
|
+
self.parent = parent
|
|
627
|
+
self.lmod = lmod
|
|
628
|
+
self.cbar = plt.cm.jet
|
|
629
|
+
self.curmodel = 0
|
|
630
|
+
self.width = 1
|
|
631
|
+
self.xold = None
|
|
632
|
+
self.yold = None
|
|
633
|
+
self.press = False
|
|
634
|
+
self.newline = False
|
|
635
|
+
self.mdata = np.zeros([10, 100])
|
|
636
|
+
self.ptitle = ''
|
|
637
|
+
self.punit = ''
|
|
638
|
+
self.xlabel = 'Eastings (m)'
|
|
639
|
+
self.plotisinit = False
|
|
640
|
+
|
|
641
|
+
# Events
|
|
642
|
+
self.figure.canvas.mpl_connect('motion_notify_event', self.move)
|
|
643
|
+
self.figure.canvas.mpl_connect('button_press_event', self.button_press)
|
|
644
|
+
self.figure.canvas.mpl_connect('button_release_event',
|
|
645
|
+
self.button_release)
|
|
646
|
+
# Initial Images
|
|
647
|
+
self.paxes = fig.add_subplot(211)
|
|
648
|
+
self.paxes.yaxis.set_label_text("mGal")
|
|
649
|
+
self.paxes.ticklabel_format(useOffset=False)
|
|
650
|
+
|
|
651
|
+
self.cal = self.paxes.plot([], [])
|
|
652
|
+
self.obs = plt.plot([], [], '.')
|
|
653
|
+
|
|
654
|
+
self.axes = fig.add_subplot(212)
|
|
655
|
+
self.axes.xaxis.set_label_text(self.xlabel)
|
|
656
|
+
self.axes.yaxis.set_label_text("Altitude (m)")
|
|
657
|
+
|
|
658
|
+
tmp = self.cbar(self.mdata)
|
|
659
|
+
tmp[:, :, 3] = 0
|
|
660
|
+
|
|
661
|
+
self.ims2 = plt.imshow(tmp.copy(), interpolation='nearest',
|
|
662
|
+
aspect='auto')
|
|
663
|
+
self.ims = plt.imshow(tmp.copy(), interpolation='nearest',
|
|
664
|
+
aspect='auto')
|
|
665
|
+
self.figure.canvas.draw()
|
|
666
|
+
|
|
667
|
+
self.bbox = self.figure.canvas.copy_from_bbox(self.axes.bbox)
|
|
668
|
+
self.pbbox = self.figure.canvas.copy_from_bbox(self.paxes.bbox)
|
|
669
|
+
self.prf = self.axes.plot([0, 0])
|
|
670
|
+
self.figure.canvas.draw()
|
|
671
|
+
self.lbbox = self.figure.canvas.copy_from_bbox(self.axes.bbox)
|
|
672
|
+
|
|
673
|
+
def button_press(self, event):
|
|
674
|
+
""" Button press """
|
|
675
|
+
nmode = self.axes.get_navigate_mode()
|
|
676
|
+
if event.button == 1 and nmode is None:
|
|
677
|
+
self.press = True
|
|
678
|
+
self.newline = True
|
|
679
|
+
self.move(event)
|
|
680
|
+
|
|
681
|
+
def button_release(self, event):
|
|
682
|
+
""" Button press """
|
|
683
|
+
nmode = self.axes.get_navigate_mode()
|
|
684
|
+
if event.button == 1:
|
|
685
|
+
self.press = False
|
|
686
|
+
if nmode == 'ZOOM':
|
|
687
|
+
extent = self.axes.get_xbound()
|
|
688
|
+
self.paxes.set_xbound(extent[0], extent[1])
|
|
689
|
+
self.figure.canvas.draw()
|
|
690
|
+
else:
|
|
691
|
+
self.parent.update_model()
|
|
692
|
+
|
|
693
|
+
def move(self, event):
|
|
694
|
+
""" Mouse is moving """
|
|
695
|
+
|
|
696
|
+
if self.figure.canvas.toolbar._active is None:
|
|
697
|
+
vlim = self.axes.viewLim
|
|
698
|
+
if self.lmod.is_ew:
|
|
699
|
+
xptp = self.lmod.xrange[1]-self.lmod.xrange[0]
|
|
700
|
+
else:
|
|
701
|
+
xptp = self.lmod.yrange[1]-self.lmod.yrange[0]
|
|
702
|
+
yptp = self.lmod.zrange[1]-self.lmod.zrange[0]
|
|
703
|
+
tmp0 = self.axes.transData.transform((vlim.x0, vlim.y0))
|
|
704
|
+
tmp1 = self.axes.transData.transform((vlim.x1, vlim.y1))
|
|
705
|
+
width, height = tmp1-tmp0
|
|
706
|
+
width /= self.mdata.shape[1]
|
|
707
|
+
height /= self.mdata.shape[0]
|
|
708
|
+
width *= xptp/vlim.width
|
|
709
|
+
height *= yptp/vlim.height
|
|
710
|
+
cwidth = (2*self.width-1)
|
|
711
|
+
cb = QtGui.QBitmap(cwidth*width, cwidth*height)
|
|
712
|
+
cb.fill(QtCore.Qt.color1)
|
|
713
|
+
self.setCursor(QtGui.QCursor(cb))
|
|
714
|
+
|
|
715
|
+
dxy = self.lmod.dxy
|
|
716
|
+
xmin = self.lmod.xrange[0]
|
|
717
|
+
ymin = self.lmod.yrange[0]
|
|
718
|
+
zmin = self.lmod.zrange[0]
|
|
719
|
+
|
|
720
|
+
if event.inaxes == self.axes and self.press is True:
|
|
721
|
+
if self.lmod.is_ew:
|
|
722
|
+
col = int((event.xdata - xmin)/dxy)+1
|
|
723
|
+
else:
|
|
724
|
+
col = int((event.xdata - ymin)/dxy)+1
|
|
725
|
+
row = int((event.ydata - zmin)/self.lmod.d_z)+1
|
|
726
|
+
|
|
727
|
+
xdata = col
|
|
728
|
+
ydata = row
|
|
729
|
+
|
|
730
|
+
if self.newline is True:
|
|
731
|
+
self.newline = False
|
|
732
|
+
self.set_mdata(xdata, ydata)
|
|
733
|
+
elif xdata != self.xold:
|
|
734
|
+
mmm = float(ydata-self.yold)/(xdata-self.xold)
|
|
735
|
+
ccc = ydata - mmm * xdata
|
|
736
|
+
x_1 = min([self.xold, xdata])
|
|
737
|
+
x_2 = max([self.xold, xdata])
|
|
738
|
+
for i in range(x_1+1, x_2+1):
|
|
739
|
+
jold = int(mmm*(i-1)+ccc)
|
|
740
|
+
jnew = int(mmm*i+ccc)
|
|
741
|
+
if jold > jnew:
|
|
742
|
+
jold, jnew = jnew, jold
|
|
743
|
+
for j in range(jold, jnew+1):
|
|
744
|
+
self.set_mdata(i, j)
|
|
745
|
+
|
|
746
|
+
elif ydata != self.yold:
|
|
747
|
+
y_1 = min([self.yold, ydata])
|
|
748
|
+
y_2 = max([self.yold, ydata])
|
|
749
|
+
for j in range(y_1, y_2+1):
|
|
750
|
+
self.set_mdata(xdata, j)
|
|
751
|
+
|
|
752
|
+
self.xold = xdata
|
|
753
|
+
self.yold = ydata
|
|
754
|
+
|
|
755
|
+
self.slide_grid(self.mdata)
|
|
756
|
+
|
|
757
|
+
def set_mdata(self, xdata, ydata):
|
|
758
|
+
""" Routine to 'draw' the line on mdata """
|
|
759
|
+
gheight = self.mdata.shape[0]
|
|
760
|
+
gwidth = self.mdata.shape[1]
|
|
761
|
+
|
|
762
|
+
width = self.width-1 # 'pen' width
|
|
763
|
+
xstart = xdata-width-1
|
|
764
|
+
xend = xdata+width
|
|
765
|
+
ystart = ydata-width-1
|
|
766
|
+
yend = ydata+width
|
|
767
|
+
if xstart < 0:
|
|
768
|
+
xstart = 0
|
|
769
|
+
if xend > gwidth:
|
|
770
|
+
xend = gwidth
|
|
771
|
+
if ystart < 0:
|
|
772
|
+
ystart = 0
|
|
773
|
+
if yend > gheight:
|
|
774
|
+
yend = gheight
|
|
775
|
+
|
|
776
|
+
if xstart < xend and ystart < yend:
|
|
777
|
+
mtmp = self.mdata[ystart:yend, xstart:xend]
|
|
778
|
+
mtmp[np.logical_and(mtmp != -1, mtmp < 900)] = self.curmodel
|
|
779
|
+
|
|
780
|
+
def luttodat(self, dat):
|
|
781
|
+
""" lut to dat grid """
|
|
782
|
+
mlut = self.lmod.mlut
|
|
783
|
+
tmp = np.zeros([dat.shape[0], dat.shape[1], 4])
|
|
784
|
+
|
|
785
|
+
for i in np.unique(dat):
|
|
786
|
+
if i == -1:
|
|
787
|
+
ctmp = [0, 0, 0, 0]
|
|
788
|
+
else:
|
|
789
|
+
ctmp = np.array(mlut[i]+[255])/255.
|
|
790
|
+
|
|
791
|
+
tmp[dat[::-1] == i] = ctmp
|
|
792
|
+
|
|
793
|
+
return tmp
|
|
794
|
+
|
|
795
|
+
def init_grid(self, dat, extent, dat2, opac):
|
|
796
|
+
""" Updates the single color map """
|
|
797
|
+
# Note that because we clear the current axes, we must put the objects
|
|
798
|
+
# back into it are the graph will go blank on a draw(). This is the
|
|
799
|
+
# reason for the ims and prf commands below.
|
|
800
|
+
|
|
801
|
+
self.paxes.set_xbound(extent[0], extent[1])
|
|
802
|
+
|
|
803
|
+
self.ims.set_visible(False)
|
|
804
|
+
self.axes.set_xlim(extent[0], extent[1])
|
|
805
|
+
self.axes.set_ylim(extent[2], extent[3])
|
|
806
|
+
|
|
807
|
+
if dat2 is not None:
|
|
808
|
+
self.ims2.set_data(dat2.data)
|
|
809
|
+
self.ims2.set_extent(self.dat_extent(dat2))
|
|
810
|
+
self.ims2.set_clim(dat2.data.min(), dat2.data.max())
|
|
811
|
+
|
|
812
|
+
self.figure.canvas.draw()
|
|
813
|
+
QtGui.QApplication.processEvents()
|
|
814
|
+
self.bbox = self.figure.canvas.copy_from_bbox(self.axes.bbox)
|
|
815
|
+
|
|
816
|
+
self.ims.set_visible(True)
|
|
817
|
+
self.ims.set_extent(extent)
|
|
818
|
+
tmp = self.luttodat(dat)
|
|
819
|
+
self.ims.set_data(tmp)
|
|
820
|
+
self.ims.set_alpha(opac)
|
|
821
|
+
|
|
822
|
+
self.lbbox = self.figure.canvas.copy_from_bbox(self.axes.bbox)
|
|
823
|
+
self.figure.canvas.draw()
|
|
824
|
+
QtGui.QApplication.processEvents()
|
|
825
|
+
|
|
826
|
+
self.mdata = dat
|
|
827
|
+
|
|
828
|
+
def slide_grid(self, dat, dat2=None, opac=1.0):
|
|
829
|
+
""" Slider """
|
|
830
|
+
self.mdata = dat
|
|
831
|
+
tmp = self.luttodat(dat)
|
|
832
|
+
self.ims.set_data(tmp)
|
|
833
|
+
self.ims.set_alpha(opac)
|
|
834
|
+
|
|
835
|
+
self.figure.canvas.restore_region(self.bbox)
|
|
836
|
+
self.axes.draw_artist(self.ims)
|
|
837
|
+
self.figure.canvas.update()
|
|
838
|
+
|
|
839
|
+
self.lbbox = self.figure.canvas.copy_from_bbox(self.axes.bbox)
|
|
840
|
+
self.axes.draw_artist(self.prf[0])
|
|
841
|
+
self.figure.canvas.update()
|
|
842
|
+
|
|
843
|
+
def update_line(self, xrng, yrng):
|
|
844
|
+
""" Updates the line position """
|
|
845
|
+
self.prf[0].set_data([xrng, yrng])
|
|
846
|
+
self.figure.canvas.restore_region(self.lbbox)
|
|
847
|
+
self.axes.draw_artist(self.prf[0])
|
|
848
|
+
self.figure.canvas.update()
|
|
849
|
+
|
|
850
|
+
def dat_extent(self, dat):
|
|
851
|
+
""" Gets the extend of the dat variable """
|
|
852
|
+
left = dat.tlx
|
|
853
|
+
top = dat.tly
|
|
854
|
+
right = left + dat.cols*dat.xdim
|
|
855
|
+
bottom = top - dat.rows*dat.ydim
|
|
856
|
+
return (left, right, bottom, top)
|
|
857
|
+
|
|
858
|
+
# This section is just for the profile line plot
|
|
859
|
+
|
|
860
|
+
def extentchk(self, extent):
|
|
861
|
+
""" Checks extent """
|
|
862
|
+
dmin = extent[2]
|
|
863
|
+
dmax = extent[3]
|
|
864
|
+
if dmin == dmax:
|
|
865
|
+
dmax = dmin+1
|
|
866
|
+
return dmin, dmax
|
|
867
|
+
|
|
868
|
+
def init_plot(self, xdat, dat, extent, xdat2, dat2):
|
|
869
|
+
""" Updates the single color map """
|
|
870
|
+
self.paxes.autoscale(False)
|
|
871
|
+
dmin, dmax = self.extentchk(extent)
|
|
872
|
+
self.paxes.cla()
|
|
873
|
+
self.paxes.ticklabel_format(useOffset=False)
|
|
874
|
+
self.paxes.set_title(self.ptitle)
|
|
875
|
+
self.axes.xaxis.set_label_text(self.xlabel)
|
|
876
|
+
self.paxes.yaxis.set_label_text(self.punit)
|
|
877
|
+
self.paxes.set_ylim(dmin, dmax)
|
|
878
|
+
self.paxes.set_xlim(extent[0], extent[1])
|
|
879
|
+
self.figure.canvas.draw()
|
|
880
|
+
QtGui.QApplication.processEvents()
|
|
881
|
+
self.pbbox = self.figure.canvas.copy_from_bbox(self.paxes.bbox)
|
|
882
|
+
|
|
883
|
+
self.paxes.set_autoscalex_on(False)
|
|
884
|
+
self.cal = self.paxes.plot(xdat, dat)
|
|
885
|
+
if xdat2 is not None:
|
|
886
|
+
self.obs = self.paxes.plot(xdat2, dat2, '.')
|
|
887
|
+
else:
|
|
888
|
+
self.obs = self.paxes.plot([], [], '.')
|
|
889
|
+
self.figure.canvas.draw()
|
|
890
|
+
QtGui.QApplication.processEvents()
|
|
891
|
+
self.plotisinit = True
|
|
892
|
+
|
|
893
|
+
def slide_plot(self, xdat, dat, extent, xdat2, dat2):
|
|
894
|
+
""" Slider """
|
|
895
|
+
self.figure.canvas.restore_region(self.pbbox)
|
|
896
|
+
self.cal[0].set_data([xdat, dat])
|
|
897
|
+
if xdat2 is not None:
|
|
898
|
+
self.obs[0].set_data([xdat2, dat2])
|
|
899
|
+
else:
|
|
900
|
+
self.obs[0].set_data([[], []])
|
|
901
|
+
|
|
902
|
+
self.paxes.draw_artist(self.cal[0])
|
|
903
|
+
if xdat2 is not None:
|
|
904
|
+
self.paxes.draw_artist(self.obs[0])
|
|
905
|
+
self.figure.canvas.update()
|
|
906
|
+
|
|
907
|
+
QtGui.QApplication.processEvents()
|
|
908
|
+
|
|
909
|
+
|
|
910
|
+
class MySlider(QtGui.QSlider):
|
|
911
|
+
"""
|
|
912
|
+
My Slider
|
|
913
|
+
|
|
914
|
+
Custom class which allows clicking on slider bar with slider moving to
|
|
915
|
+
click in a single step.
|
|
916
|
+
"""
|
|
917
|
+
def __init__(self, parent=None):
|
|
918
|
+
QtGui.QPushButton.__init__(self, parent)
|
|
919
|
+
|
|
920
|
+
def mousePressEvent(self, event):
|
|
921
|
+
""" Mouse Press Event """
|
|
922
|
+
opt = QtGui.QStyleOptionSlider()
|
|
923
|
+
self.initStyleOption(opt)
|
|
924
|
+
sr = self.style()
|
|
925
|
+
sr = sr.subControlRect(QtGui.QStyle.CC_Slider, opt,
|
|
926
|
+
QtGui.QStyle.SC_SliderHandle, self)
|
|
927
|
+
if (event.button() == QtCore.Qt.LeftButton and
|
|
928
|
+
sr.contains(event.pos()) is False):
|
|
929
|
+
if self.orientation() == QtCore.Qt.Vertical:
|
|
930
|
+
self.setValue(self.minimum() + ((self.maximum()-self.minimum())
|
|
931
|
+
* (self.height()-event.y())) / self.height())
|
|
932
|
+
else:
|
|
933
|
+
halfHandleWidth = (0.5 * sr.width()) + 0.5
|
|
934
|
+
adaptedPosX = event.x()
|
|
935
|
+
if (adaptedPosX < halfHandleWidth):
|
|
936
|
+
adaptedPosX = halfHandleWidth
|
|
937
|
+
if (adaptedPosX > self.width() - halfHandleWidth):
|
|
938
|
+
adaptedPosX = self.width() - halfHandleWidth
|
|
939
|
+
newWidth = (self.width() - halfHandleWidth) - halfHandleWidth
|
|
940
|
+
normalizedPosition = (adaptedPosX-halfHandleWidth)/newWidth
|
|
941
|
+
|
|
942
|
+
newVal = self.minimum() + ((self.maximum()-self.minimum()) *
|
|
943
|
+
normalizedPosition)
|
|
944
|
+
self.setValue(newVal)
|
|
945
|
+
event.accept()
|
|
946
|
+
super(MySlider, self).mousePressEvent(event)
|