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,860 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Name: igrf.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
+ """
26
+ This code is based on the Geomag software, with information given below. It was
27
+ translated into Python from the Geomag code.
28
+
29
+ | This program, originally written in FORTRAN, was developed using subroutines
30
+ | written by : A. Zunde
31
+ | USGS, MS 964, Box 25046 Federal Center, Denver, Co. 80225
32
+ | and
33
+ | S.R.C. Malin & D.R. Barraclough
34
+ | Institute of Geological Sciences, United Kingdom.
35
+
36
+ | Translated
37
+ | into C by : Craig H. Shaffer
38
+ | 29 July, 1988
39
+
40
+ | Rewritten by : David Owens
41
+ | For Susan McLean
42
+
43
+ | Maintained by: Stefan Maus
44
+ | Contact : stefan.maus@noaa.gov
45
+ | National Geophysical Data Center
46
+ | World Data Center-A for Solid Earth Geophysics
47
+ | NOAA, E/GC1, 325 Broadway,
48
+ | Boulder, CO 80303
49
+ """
50
+
51
+ from PyQt4 import QtGui, QtCore
52
+ import numpy as np
53
+ from math import sin
54
+ from math import cos
55
+ from math import sqrt
56
+ from math import atan2
57
+ from osgeo import osr
58
+ import copy
59
+ import pygmi.raster.dataprep as dp
60
+ import pygmi.menu_default as menu_default
61
+
62
+
63
+ class IGRF(QtGui.QDialog):
64
+ """
65
+ IGRF field calculation
66
+
67
+ This produces two datasets. The first is an IGRF dataset for the area of
68
+ interest, defined by some input magnetic dataset. The second is the IGRF
69
+ corrected form of that input magnetic dataset.
70
+
71
+ To do this, the input dataset must be reprojected from its local projection
72
+ to degrees, where the IGRF correction will take place. This is done within
73
+ this class.
74
+
75
+ Attributes
76
+ ----------
77
+ parent : parent
78
+ reference to the parent routine
79
+ indata : dictionary
80
+ dictionary of input datasets
81
+ outdata : dictionary
82
+ dictionary of output datasets
83
+
84
+ Parameters
85
+ ----------
86
+ altmin : Double
87
+ Minimum height of selected model.
88
+ altmax : Double array
89
+ array of MAXMOD Maximum height of model.
90
+ maxalt : Double
91
+ Maximum height of selected model.
92
+ d : float
93
+ Declination of the field from the geographic north (deg).
94
+ sdate : float
95
+ start date inputted
96
+ ddot : float
97
+ annual rate of change of decl. (arc-min/yr)
98
+ alt : float
99
+ altitude above WGS84 Ellipsoid
100
+ epoch : list
101
+ list of MAXMOD epoch of model.
102
+ latitude : float
103
+ Latitude.
104
+ longitude : float
105
+ Longitude.
106
+ gh : numpy array
107
+ Schmidt quasi-normal internal spherical harmonic coeff.
108
+ Schmidt quasi-normal internal spherical harmonic coeff.
109
+ Coefficients of resulting model.
110
+ Coefficients of rate of change model.
111
+ i : float
112
+ Inclination (deg).
113
+ idot : float
114
+ Rate of change of i (arc-min/yr).
115
+ igdgc : int
116
+ Flag for geodetic or geocentric coordinate choice.
117
+ irec_pos : int array
118
+ array of MAXMOD Record counter for header
119
+ fileline : int
120
+ Current line in file (for errors)
121
+ max1 : list, int
122
+ array of MAXMOD Main field coefficient.
123
+ max2 : list, int
124
+ array of MAXMOD Secular variation coefficient.
125
+ max3 : list, int
126
+ array of MAXMOD Acceleration coefficient.
127
+ minyr : float
128
+ Min year of all models
129
+ maxyr : float
130
+ Max year of all models
131
+ yrmax : list, float
132
+ array of MAXMOD Max year of model.
133
+ yrmin : list, float
134
+ array of MAXMOD Min year of model.
135
+ """
136
+ def __init__(self, parent=None):
137
+ QtGui.QDialog.__init__(self, parent=None)
138
+
139
+ self.parent = parent
140
+ self.indata = {}
141
+ self.outdata = {}
142
+ self.reportback = self.parent.showprocesslog
143
+ self.pbar = self.parent.pbar
144
+
145
+ MAXDEG = 13
146
+ MAXCOEFF = (MAXDEG*(MAXDEG+2)+1)
147
+
148
+ self.gh = np.zeros([4, MAXCOEFF])
149
+ self.d = 0
150
+ self.f = 0
151
+ self.h = 0
152
+ self.i = 0
153
+ self.dtemp = 0
154
+ self.ftemp = 0
155
+ self.htemp = 0
156
+ self.itemp = 0
157
+ self.x = 0
158
+ self.y = 0
159
+ self.z = 0
160
+ self.xtemp = 0
161
+ self.ytemp = 0
162
+ self.ztemp = 0
163
+ self.xdot = 0
164
+ self.ydot = 0
165
+ self.zdot = 0
166
+ self.fdot = 0
167
+ self.hdot = 0
168
+ self.idot = 0
169
+ self.ddot = 0
170
+
171
+ self.dsb_alt = QtGui.QDoubleSpinBox()
172
+ self.dateedit = QtGui.QDateEdit()
173
+ self.combobox_dtm = QtGui.QComboBox()
174
+ self.combobox_mag = QtGui.QComboBox()
175
+ self.proj = dp.GroupProj('Input Projection')
176
+
177
+ self.setupui()
178
+
179
+ self.ctrans = None
180
+
181
+ def setupui(self):
182
+ """ Setup UI """
183
+
184
+ gridlayout = QtGui.QGridLayout(self)
185
+ buttonbox = QtGui.QDialogButtonBox()
186
+ helpdocs = menu_default.HelpButton('pygmi.raster.igrf')
187
+
188
+ label_0 = QtGui.QLabel()
189
+ label_1 = QtGui.QLabel()
190
+ label_2 = QtGui.QLabel()
191
+ label_3 = QtGui.QLabel()
192
+
193
+ buttonbox.setOrientation(QtCore.Qt.Horizontal)
194
+ buttonbox.setStandardButtons(buttonbox.Cancel | buttonbox.Ok)
195
+
196
+ self.dsb_alt.setMaximum(99999.9)
197
+
198
+ self.setWindowTitle("IGRF")
199
+ label_0.setText("Sensor clearance above ground")
200
+ label_1.setText("Date")
201
+ label_2.setText("Digital Elevation Model")
202
+ label_3.setText("Magnetic Data")
203
+
204
+ gridlayout.addWidget(self.proj, 0, 0, 1, 2)
205
+ gridlayout.addWidget(label_0, 2, 0, 1, 1)
206
+ gridlayout.addWidget(self.dsb_alt, 2, 1, 1, 1)
207
+ gridlayout.addWidget(label_1, 3, 0, 1, 1)
208
+ gridlayout.addWidget(self.dateedit, 3, 1, 1, 1)
209
+ gridlayout.addWidget(label_2, 4, 0, 1, 1)
210
+ gridlayout.addWidget(self.combobox_dtm, 4, 1, 1, 1)
211
+ gridlayout.addWidget(label_3, 5, 0, 1, 1)
212
+ gridlayout.addWidget(self.combobox_mag, 5, 1, 1, 1)
213
+ gridlayout.addWidget(buttonbox, 6, 1, 1, 1)
214
+ gridlayout.addWidget(helpdocs, 6, 0, 1, 1)
215
+
216
+ buttonbox.accepted.connect(self.accept)
217
+ buttonbox.rejected.connect(self.reject)
218
+
219
+ def acceptall(self):
220
+ """ Accept button"""
221
+
222
+ orig_wkt = self.proj.wkt
223
+
224
+ orig = osr.SpatialReference()
225
+ orig.ImportFromWkt(orig_wkt)
226
+
227
+ targ = osr.SpatialReference()
228
+ targ.SetWellKnownGeogCS('WGS84')
229
+
230
+ self.ctrans = osr.CoordinateTransformation(orig, targ)
231
+
232
+ # self.accept()
233
+
234
+ def settings(self):
235
+ """
236
+ Settings Dialog. This is the main entrypoint into this routine. It also
237
+ contains the main IGRF code.
238
+ """
239
+ # Variable declaration
240
+ # Control variables
241
+ self.proj.set_current(self.indata['Raster'][0].wkt)
242
+
243
+ data = dp.merge(self.indata['Raster'])
244
+ self.combobox_dtm.clear()
245
+ self.combobox_mag.clear()
246
+ for i in data:
247
+ self.combobox_dtm.addItem(i.dataid)
248
+ self.combobox_mag.addItem(i.dataid)
249
+
250
+ tmp = self.exec_()
251
+
252
+ if tmp == 1:
253
+ self.acceptall()
254
+ tmp = True
255
+ else:
256
+ return False
257
+
258
+ # again = 1
259
+ mdf = open(__file__.rpartition('\\')[0]+'\\IGRF11.cof')
260
+ modbuff = mdf.readlines()
261
+ fileline = -1 # First line will be 1
262
+ model = []
263
+ epoch = []
264
+ max1 = []
265
+ max2 = []
266
+ max3 = []
267
+ yrmin = []
268
+ yrmax = []
269
+ altmin = []
270
+ altmax = []
271
+ irec_pos = []
272
+ # First model will be 0
273
+ for i in modbuff:
274
+ fileline += 1 # On new line
275
+ if i[:3] == ' ':
276
+ i2 = i.split()
277
+ model.append(i2[0])
278
+ epoch.append(float(i2[1]))
279
+ max1.append(int(i2[2]))
280
+ max2.append(int(i2[3]))
281
+ max3.append(int(i2[4]))
282
+ yrmin.append(float(i2[5]))
283
+ yrmax.append(float(i2[6]))
284
+ altmin.append(float(i2[7]))
285
+ altmax.append(float(i2[8]))
286
+ irec_pos.append(fileline)
287
+
288
+ i = self.combobox_mag.currentIndex()
289
+ maggrid = data[i]
290
+
291
+ i = self.combobox_dtm.currentIndex()
292
+ data = data[i]
293
+ altgrid = data.data.flatten() * 0.001 # in km
294
+
295
+ maxyr = max(yrmax)
296
+ sdate = self.dateedit.date()
297
+ sdate = sdate.year()+sdate.dayOfYear()/sdate.daysInYear()
298
+ alt = self.dsb_alt.value()
299
+ xrange = data.tlx+data.xdim/2.+np.arange(data.cols)*data.xdim
300
+ yrange = data.tly-data.ydim/2.-np.arange(data.rows)*data.ydim
301
+ xdat, ydat = np.meshgrid(xrange, yrange)
302
+ xdat = xdat.flatten()
303
+ ydat = ydat.flatten()
304
+
305
+ igrf_F = altgrid * 0
306
+ # Pick model
307
+ yrmax = np.array(yrmax)
308
+ modelI = sum(yrmax < sdate)
309
+ igdgc = 1
310
+
311
+ if (sdate > maxyr) and (sdate < maxyr+1):
312
+ print("\nWarning: The date %4.2f is out of range,\n", sdate)
313
+ print("but still within one year of model expiration date.\n")
314
+ print("An updated model file is available before 1.1.%4.0f\n",
315
+ maxyr)
316
+
317
+ if max2[modelI] == 0:
318
+ self.getshc(modbuff, 1, irec_pos[modelI], max1[modelI], 0)
319
+ self.getshc(modbuff, 1, irec_pos[modelI+1], max1[modelI+1], 1)
320
+ nmax = self.interpsh(sdate, yrmin[modelI], max1[modelI],
321
+ yrmin[modelI+1], max1[modelI+1], 2)
322
+ nmax = self.interpsh(sdate+1, yrmin[modelI], max1[modelI],
323
+ yrmin[modelI+1], max1[modelI+1], 3)
324
+ else:
325
+ self.getshc(modbuff, 1, irec_pos[modelI], max1[modelI], 0)
326
+ self.getshc(modbuff, 0, irec_pos[modelI], max2[modelI], 1)
327
+ nmax = self.extrapsh(sdate, epoch[modelI], max1[modelI],
328
+ max2[modelI], 2)
329
+ nmax = self.extrapsh(sdate+1, epoch[modelI], max1[modelI],
330
+ max2[modelI], 3)
331
+
332
+ progress = 0
333
+ maxlen = xdat.size
334
+
335
+ for i in self.pbar.iter(range(maxlen)):
336
+ if igrf_F.mask[i] == True:
337
+ continue
338
+
339
+ tmp = int(i*100/maxlen)
340
+ if tmp > progress:
341
+ progress = tmp
342
+ # self.reportback('Calculation: ' + str(progress) + '%', True)
343
+
344
+ longitude, latitude, _ = self.ctrans.TransformPoint(xdat[i],
345
+ ydat[i])
346
+ alt = altgrid[i]
347
+
348
+ # Do the first calculations
349
+ self.shval3(igdgc, latitude, longitude, alt, nmax, 3)
350
+ self.dihf(3)
351
+ # self.shval3(igdgc, latitude, longitude, alt, nmax, 4)
352
+ # self.dihf(4)
353
+ #
354
+ # RAD2DEG = (180.0/np.pi)
355
+ #
356
+ # self.ddot = ((self.dtemp - self.d)*RAD2DEG)
357
+ # if self.ddot > 180.0:
358
+ # self.ddot -= 360.0
359
+ # if self.ddot <= -180.0:
360
+ # self.ddot += 360.0
361
+ # self.ddot *= 60.0
362
+ #
363
+ # self.idot = ((self.itemp - self.i)*RAD2DEG)*60
364
+ # self.d = self.d*(RAD2DEG)
365
+ # self.i = self.i*(RAD2DEG)
366
+ # self.hdot = self.htemp - self.h
367
+ # self.xdot = self.xtemp - self.x
368
+ # self.ydot = self.ytemp - self.y
369
+ # self.zdot = self.ztemp - self.z
370
+ # self.fdot = self.ftemp - self.f
371
+ #
372
+ # # deal with geographic and magnetic poles
373
+ #
374
+ # if self.h < 100.0: # at magnetic poles
375
+ # self.d = np.nan
376
+ # self.ddot = np.nan
377
+ # # while rest is ok
378
+ #
379
+ # if 90.0-abs(latitude) <= 0.001: # at geographic poles
380
+ # self.x = np.nan
381
+ # self.y = np.nan
382
+ # self.d = np.nan
383
+ # self.xdot = np.nan
384
+ # self.ydot = np.nan
385
+ # self.ddot = np.nan
386
+
387
+ # print('Test Data')
388
+ # print('==========')
389
+ #
390
+ # print('# Date 2014.5', sdate)
391
+ # print('# Coord-System D')
392
+ # print('# Altitude K100', alt)
393
+ # print('# Latitude 70.3', latitude)
394
+ # print('# Longitude 30.8', longitude)
395
+ # print('# D_deg 13d', int(self.d))
396
+ # print('# D_min 51m ', int((self.d-int(self.d))*60))
397
+ # print('# I_deg 78d', int(self.i))
398
+ # print('# I_min 55m', int((self.i-int(self.i))*60))
399
+ # print('# H_nT 9987.9 {0:.1f}'.format(self.h))
400
+ # print('# X_nT 9697.4 {0:.1f}'.format(self.x))
401
+ # print('# Y_nT 2391.4 {0:.1f}'.format(self.y))
402
+ # print('# Z_nT 51022.3 {0:.1f}'.format(self.z))
403
+ # print('# F_nT 51990.7 {0:.1f}'.format(self.f))
404
+ # print('# dD_min 10.9 {0:.1f}'.format(self.ddot))
405
+ # print('# dI_min 1.0 {0:.1f}'.format(self.idot))
406
+ # print('# dH_nT -10.4 {0:.1f}'.format(self.hdot))
407
+ # print('# dX_nT -17.7 {0:.1f}'.format(self.xdot))
408
+ # print('# dY_nT 28.1 {0:.1f}'.format(self.ydot))
409
+ # print('# dZ_nT 29.0 {0:.1f}'.format(self.zdot))
410
+ # print('# dF_nT 26.5 {0:.1f}'.format(self.fdot))
411
+ igrf_F[i] = self.f
412
+
413
+ self.outdata['Raster'] = copy.deepcopy(self.indata['Raster'])
414
+ igrf_F = np.ma.array(igrf_F)
415
+ igrf_F.shape = data.data.shape
416
+ igrf_F.mask = data.data.mask
417
+ self.outdata['Raster'].append(copy.deepcopy(data))
418
+ self.outdata['Raster'][-1].data = igrf_F
419
+ self.outdata['Raster'][-1].dataid = 'IGRF'
420
+ self.outdata['Raster'].append(copy.deepcopy(maggrid))
421
+ self.outdata['Raster'][-1].data -= igrf_F
422
+ self.outdata['Raster'][-1].dataid = 'Magnetic Data: IGRF Corrected'
423
+
424
+ self.reportback('Calculation: Completed', True)
425
+
426
+ return True
427
+
428
+ def getshc(self, file, iflag, strec, nmax_of_gh, gh):
429
+ """
430
+ Reads spherical harmonic coefficients from the specified model into an
431
+ array.
432
+
433
+ | FORTRAN: Bill Flanagan, NOAA CORPS, DESDIS, NGDC, 325 Broadway,
434
+ | Boulder CO. 80301
435
+ | C: C. H. Shaffer, Lockheed Missiles and Space Company, Sunnyvale CA
436
+
437
+ Parameters
438
+ ----------
439
+ file : file
440
+ reference to a file object
441
+ iflag :
442
+ Flag for SV equal to 1 or not equal to 1 for designated read
443
+ statements
444
+ strec : int
445
+ Starting record number to read from model
446
+ nmax_of_gh : int
447
+ Maximum degree and order of model
448
+
449
+ Returns
450
+ -------
451
+ gh : list
452
+ Schmidt quasi-normal internal spherical harmonic coefficients
453
+ """
454
+ ii = -1
455
+ cnt = 0
456
+
457
+ for nn in range(1, nmax_of_gh+1):
458
+ for _ in range(nn+1):
459
+ cnt += 1
460
+ tmp = file[strec+cnt]
461
+ tmp = tmp.split()
462
+ # n = int(tmp[0])
463
+ m = int(tmp[1])
464
+
465
+ if iflag == 1:
466
+ g = float(tmp[2])
467
+ hh = float(tmp[3])
468
+ else:
469
+ g = float(tmp[4])
470
+ hh = float(tmp[5])
471
+
472
+ ii = ii + 1
473
+ self.gh[gh][ii] = g
474
+
475
+ if m != 0:
476
+ ii = ii + 1
477
+ self.gh[gh][ii] = hh
478
+
479
+ return
480
+
481
+ def extrapsh(self, date, dte1, nmax1, nmax2, gh):
482
+ """
483
+ Extrapolates linearly a spherical harmonic model with a
484
+ rate-of-change model.
485
+
486
+ | FORTRAN : A. Zunde, USGS, MS 964, box 25046 Federal Center, Denver,
487
+ | CO. 80225
488
+ | C : C. H. Shaffer, Lockheed Missiles and Space Company, Sunnyvale CA
489
+
490
+ Parameters
491
+ ----------
492
+ date : float
493
+ date of resulting model (in decimal year)
494
+ dte1 : float
495
+ date of base model
496
+ nmax1 : int
497
+ maximum degree and order of base model
498
+ gh : numpy array
499
+ Schmidt quasi-normal internal spherical harmonic coefficients of
500
+ base model and rate-of-change model
501
+ nmax2 : int
502
+ maximum degree and order of rate-of-change model
503
+
504
+ Returns
505
+ -------
506
+ gh : numpy array
507
+ Schmidt quasi-normal internal spherical harmonic coefficients
508
+ nmax : int
509
+ maximum degree and order of resulting model
510
+ """
511
+ factor = date - dte1
512
+ if nmax1 == nmax2:
513
+ k = nmax1 * (nmax1 + 2)
514
+ nmax = nmax1
515
+ else:
516
+ if nmax1 > nmax2:
517
+ k = nmax2 * (nmax2 + 2)
518
+ l = nmax1 * (nmax1 + 2)
519
+ for ii in range(k, l):
520
+ self.gh[gh][ii] = self.gh[0][ii]
521
+
522
+ nmax = nmax1
523
+ else:
524
+ k = nmax1 * (nmax1 + 2)
525
+ l = nmax2 * (nmax2 + 2)
526
+ for ii in range(k, l):
527
+ self.gh[gh][ii] = factor * self.gh[1][ii]
528
+
529
+ nmax = nmax2
530
+
531
+ for ii in range(k):
532
+ self.gh[gh][ii] = self.gh[0][ii] + factor * self.gh[1][ii]
533
+
534
+ return nmax
535
+
536
+ def interpsh(self, date, dte1, nmax1, dte2, nmax2, gh):
537
+ """
538
+ Interpolates linearly, in time, between two spherical harmonic
539
+ models.
540
+
541
+ | FORTRAN : A. Zunde, USGS, MS 964, box 25046 Federal Center, Denver,
542
+ | CO. 80225
543
+ | C : C. H. Shaffer, Lockheed Missiles and Space Company, Sunnyvale CA
544
+
545
+ Parameters
546
+ ----------
547
+ date : float
548
+ date of resulting model (in decimal year)
549
+ dte1 : float
550
+ date of earlier model
551
+ nmax1 : int
552
+ maximum degree and order of earlier model
553
+ gh : numpy array
554
+ Schmidt quasi-normal internal spherical harmonic coefficients of
555
+ earlier model and internal model
556
+ dte2 : float
557
+ date of later model
558
+ nmax2 : int
559
+ maximum degree and order of later model
560
+
561
+ Returns
562
+ -------
563
+ gh : numpy array
564
+ coefficients of resulting model
565
+ nmax : int
566
+ maximum degree and order of resulting model
567
+ """
568
+ factor = (date - dte1) / (dte2 - dte1)
569
+ if nmax1 == nmax2:
570
+ k = nmax1 * (nmax1 + 2)
571
+ nmax = nmax1
572
+ else:
573
+ if nmax1 > nmax2:
574
+ k = nmax2 * (nmax2 + 2)
575
+ l = nmax1 * (nmax1 + 2)
576
+ for ii in range(k, l):
577
+ self.gh[gh][ii] = self.gh[0][ii] + factor*(-self.gh[0][ii])
578
+ nmax = nmax1
579
+ else:
580
+ k = nmax1 * (nmax1 + 2)
581
+ l = nmax2 * (nmax2 + 2)
582
+ for ii in range(k, l):
583
+ self.gh[gh][ii] = factor * self.gh[1][ii]
584
+
585
+ nmax = nmax2
586
+
587
+ for ii in range(k):
588
+ self.gh[gh][ii] = self.gh[0][ii] + factor*(self.gh[1][ii] -
589
+ self.gh[0][ii])
590
+
591
+ return nmax
592
+
593
+ def shval3(self, igdgc, flat, flon, elev, nmax, gh):
594
+ """
595
+ Calculates field components from spherical harmonic (sh) models.
596
+
597
+ Based on subroutine 'igrf' by D. R. Barraclough and S. R. C. Malin,
598
+ report no. 71/1, institute of geological sciences, U.K.
599
+
600
+ | FORTRAN : Norman W. Peddie, USGS, MS 964, box 25046 Federal Center,
601
+ | Denver, CO. 80225
602
+ | C : C. H. Shaffer, Lockheed Missiles and Space Company, Sunnyvale CA
603
+
604
+ Parameters
605
+ ----------
606
+ igdgc : int
607
+ indicates coordinate system used set equal to 1 if geodetic, 2 if
608
+ geocentric
609
+ latitude : float
610
+ north latitude, in degrees
611
+ longitude : float
612
+ east longitude, in degrees
613
+ elev : float
614
+ WGS84 altitude above ellipsoid (igdgc=1), or radial distance from
615
+ earth's center (igdgc=2)
616
+ a2,b2 : float
617
+ squares of semi-major and semi-minor axes of the reference spheroid
618
+ used for transforming between geodetic and geocentric coordinates
619
+ or components
620
+ nmax : int
621
+ maximum degree and order of coefficients
622
+
623
+ Returns
624
+ -------
625
+ x : float
626
+ northward component
627
+ y : float
628
+ eastward component
629
+ z : float
630
+ vertically-downward component
631
+ """
632
+
633
+ sl = np.zeros(14)
634
+ cl = np.zeros(14)
635
+ p = np.zeros(119)
636
+ q = np.zeros(119)
637
+ earths_radius = 6371.2
638
+ dtr = np.pi/180.0
639
+ a2 = 40680631.59 # WGS84
640
+ b2 = 40408299.98 # WGS84
641
+ r = elev
642
+ argument = flat * dtr
643
+ slat = sin(argument)
644
+ if (90.0 - flat) < 0.001:
645
+ aa = 89.999 # 300 ft. from North pole
646
+ elif (90.0 + flat) < 0.001:
647
+ aa = -89.999 # 300 ft. from South pole
648
+ else:
649
+ aa = flat
650
+
651
+ argument = aa * dtr
652
+ clat = cos(argument)
653
+ argument = flon * dtr
654
+ sl[1] = sin(argument)
655
+ cl[1] = cos(argument)
656
+
657
+ if gh == 3:
658
+ self.x = 0
659
+ self.y = 0
660
+ self.z = 0
661
+ elif gh == 4:
662
+ self.xtemp = 0
663
+ self.ytemp = 0
664
+ self.ztemp = 0
665
+
666
+ sd = 0.0
667
+ cd = 1.0
668
+ l = 0
669
+ n = 0
670
+ m = 1
671
+ npq = int((nmax * (nmax + 3)) / 2)
672
+ if igdgc == 1:
673
+ aa = a2 * clat * clat
674
+ bb = b2 * slat * slat
675
+ cc = aa + bb
676
+ argument = cc
677
+ dd = sqrt(argument)
678
+ argument = elev * (elev + 2.0 * dd) + (a2 * aa + b2 * bb) / cc
679
+ r = sqrt(argument)
680
+ cd = (elev + dd) / r
681
+ sd = (a2 - b2) / dd * slat * clat / r
682
+ aa = slat
683
+ slat = slat * cd - clat * sd
684
+ clat = clat * cd + aa * sd
685
+
686
+ ratio = earths_radius / r
687
+ argument = 3.0
688
+ aa = sqrt(argument)
689
+ p[1] = 2.0 * slat
690
+ p[2] = 2.0 * clat
691
+ p[3] = 4.5 * slat * slat - 1.5
692
+ p[4] = 3.0 * aa * clat * slat
693
+ q[1] = -clat
694
+ q[2] = slat
695
+ q[3] = -3.0 * clat * slat
696
+ q[4] = aa * (slat * slat - clat * clat)
697
+ for k in range(1, npq+1):
698
+ if n < m:
699
+ m = 0
700
+ n = n + 1
701
+ argument = ratio
702
+ power = n + 2
703
+ rr = pow(argument, power)
704
+ fn = n
705
+
706
+ fm = m
707
+ if k >= 5:
708
+ if m == n:
709
+ argument = (1.0 - 0.5/fm)
710
+ aa = sqrt(argument)
711
+ j = k - n - 1
712
+ p[k] = (1.0 + 1.0/fm) * aa * clat * p[j]
713
+ q[k] = aa * (clat * q[j] + slat/fm * p[j])
714
+ sl[m] = sl[m-1] * cl[1] + cl[m-1] * sl[1]
715
+ cl[m] = cl[m-1] * cl[1] - sl[m-1] * sl[1]
716
+ else:
717
+ argument = fn*fn - fm*fm
718
+ aa = sqrt(argument)
719
+ argument = ((fn - 1.0)*(fn-1.0)) - (fm * fm)
720
+ bb = sqrt(argument)/aa
721
+ cc = (2.0 * fn - 1.0)/aa
722
+ ii = k - n
723
+ j = k - 2 * n + 1
724
+ p[k] = (fn + 1.0) * (cc * slat/fn * p[ii] - bb/(fn - 1.0)
725
+ * p[j])
726
+ q[k] = cc * (slat * q[ii] - clat/fn * p[ii]) - bb * q[j]
727
+
728
+ if gh == 3:
729
+ aa = rr * self.gh[2][l]
730
+ elif gh == 4:
731
+ aa = rr * self.gh[3][l]
732
+
733
+ if m == 0:
734
+ if gh == 3:
735
+ self.x = self.x + aa * q[k]
736
+ self.z = self.z - aa * p[k]
737
+ elif gh == 4:
738
+ self.xtemp = self.xtemp + aa * q[k]
739
+ self.ztemp = self.ztemp - aa * p[k]
740
+ else:
741
+ print("\nError in subroutine shval3")
742
+
743
+ l = l + 1
744
+ else:
745
+ if gh == 3:
746
+ bb = rr * self.gh[2][l+1]
747
+ cc = aa * cl[m] + bb * sl[m]
748
+ self.x = self.x + cc * q[k]
749
+ self.z = self.z - cc * p[k]
750
+ if clat > 0:
751
+ self.y = (self.y + (aa*sl[m] - bb*cl[m])*fm *
752
+ p[k]/((fn + 1.0)*clat))
753
+ else:
754
+ self.y = self.y + (aa*sl[m] - bb*cl[m])*q[k]*slat
755
+ l = l + 2
756
+ elif gh == 4:
757
+ bb = rr * self.gh[3][l+1]
758
+ cc = aa * cl[m] + bb * sl[m]
759
+ self.xtemp = self.xtemp + cc * q[k]
760
+ self.ztemp = self.ztemp - cc * p[k]
761
+ if clat > 0:
762
+ self.ytemp = (self.ytemp + (aa*sl[m] - bb*cl[m])*fm *
763
+ p[k]/((fn + 1.0) * clat))
764
+ else:
765
+ self.ytemp = (self.ytemp + (aa*sl[m] - bb*cl[m]) *
766
+ q[k]*slat)
767
+ l = l + 2
768
+
769
+ m = m + 1
770
+
771
+ if gh == 3:
772
+ aa = self.x
773
+ self.x = self.x * cd + self.z * sd
774
+ self.z = self.z * cd - aa * sd
775
+ elif gh == 4:
776
+ aa = self.xtemp
777
+ self.xtemp = self.xtemp * cd + self.ztemp * sd
778
+ self.ztemp = self.ztemp * cd - aa * sd
779
+
780
+ def dihf(self, gh):
781
+ """
782
+ Computes the geomagnetic d, i, h, and f from x, y, and z.
783
+
784
+ | FORTRAN : A. Zunde, USGS, MS 964, box 25046 Federal Center, Denver,
785
+ | CO. 80225
786
+ | C : C. H. Shaffer, Lockheed Missiles and Space Company, Sunnyvale CA
787
+
788
+ Parameters
789
+ ----------
790
+ x : float
791
+ northward component
792
+ y : float
793
+ eastward component
794
+ z : float
795
+ vertically-downward component
796
+
797
+ Returns
798
+ -------
799
+ d : float
800
+ declination
801
+ i : float
802
+ inclination
803
+ h : float
804
+ horizontal intensity
805
+ f : float
806
+ total intensity
807
+ """
808
+ sn = 0.0001
809
+
810
+ if gh == 3:
811
+ x = self.x
812
+ y = self.y
813
+ z = self.z
814
+ h = self.h
815
+ f = self.f
816
+ i = self.i
817
+ d = self.d
818
+ else:
819
+ x = self.xtemp
820
+ y = self.ytemp
821
+ z = self.ztemp
822
+ h = self.htemp
823
+ f = self.ftemp
824
+ i = self.itemp
825
+ d = self.dtemp
826
+
827
+ for _ in range(2):
828
+ h2 = x*x + y*y
829
+ argument = h2
830
+ h = sqrt(argument) # calculate horizontal intensity
831
+ argument = h2 + z*z
832
+ f = sqrt(argument) # calculate total intensity
833
+ if f < sn:
834
+ d = np.nan # If d and i cannot be determined,
835
+ i = np.nan # set equal to NaN
836
+ else:
837
+ argument = z
838
+ argument2 = h
839
+ i = atan2(argument, argument2)
840
+ if h < sn:
841
+ d = np.nan
842
+ else:
843
+ hpx = h + x
844
+ if hpx < sn:
845
+ d = np.pi
846
+ else:
847
+ argument = y
848
+ argument2 = hpx
849
+ d = 2.0 * atan2(argument, argument2)
850
+
851
+ if gh == 3:
852
+ self.h = h
853
+ self.f = f
854
+ self.i = i
855
+ self.d = d
856
+ else:
857
+ self.htemp = h
858
+ self.ftemp = f
859
+ self.itemp = i
860
+ self.dtemp = d