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,795 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Name: scan_imp.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 program converts scanned bulletins to seisan format """
26
+
27
+ import numpy as np
28
+ from PyQt4 import QtGui
29
+ import os
30
+ import re
31
+ from . import datatypes as sdt
32
+
33
+
34
+ def str2float(inp):
35
+ """
36
+ Converts a set number of columns to float, or returns None
37
+
38
+ Parameters
39
+ ----------
40
+ inp : str
41
+ string with a list of floats in it
42
+
43
+ Returns
44
+ -------
45
+ output : float
46
+ all columns returned as floats
47
+ """
48
+ if inp.strip() == '':
49
+ return None
50
+ return float(inp)
51
+
52
+
53
+ def str2int(inp):
54
+ """
55
+ Converts a set number of columns to integer, or returns None
56
+
57
+ Parameters
58
+ ----------
59
+ inp : str
60
+ string with a list of floats in it
61
+
62
+ Returns
63
+ -------
64
+ output : float
65
+ all columns returned as integers
66
+ """
67
+ if inp.strip() == '':
68
+ return None
69
+ return int(inp)
70
+
71
+
72
+ class SIMP(object):
73
+ """ Main form which does the GUI and the program """
74
+ def __init__(self, parent=None):
75
+ # PyGMI variables
76
+ self.ifile = ""
77
+ self.name = "Import Data: "
78
+ self.ext = ""
79
+ self.pbar = None
80
+ self.parent = parent
81
+ self.indata = {}
82
+ self.outdata = {}
83
+
84
+ # Initialize Variables
85
+ self.datanum = -1
86
+ self.timesection = ''
87
+ self.datastat = []
88
+ self.dataphase = []
89
+ self.datahours = []
90
+ self.datamins = []
91
+ self.datasecs = []
92
+ self.dataperiod = []
93
+ self.dataamplitude = []
94
+ self.datadist = []
95
+ self.datad = []
96
+ self.dataw = []
97
+ self.data_azim = []
98
+ self.dataresid = []
99
+ self.mon = ''
100
+ self.mondec = -999
101
+ self.day = -999
102
+ self.year = -999
103
+ self.region = ''
104
+ self.lat = -999
105
+ self.laterr = -999
106
+ self.lon = -999
107
+ self.lonerr = -999
108
+ self.depth = -999
109
+ self.numstations = -999
110
+ self.datanum = -999
111
+ self.magnitude = -999
112
+ self.distanceindicator = 'R'
113
+ self.hour = '00'
114
+ self.minute = '00'
115
+ self.sec = '00.00'
116
+ self.secerr = '00.00'
117
+ self.datarms = 0
118
+ self.ofile = None
119
+ self.parent = parent
120
+ self.showtext = self.parent.showprocesslog
121
+ self.event = {}
122
+
123
+ def settings(self):
124
+ """ Settings """
125
+ self.parent.clearprocesslog()
126
+ self.showtext('Import Bulletin to Seisan Format')
127
+
128
+ ext = "Scanned Bulletin Text File (*.txt)"
129
+
130
+ filename = QtGui.QFileDialog.getOpenFileName(self.parent, 'Open File',
131
+ '.', ext)
132
+ if filename == '':
133
+ return False
134
+ os.chdir(filename.rpartition('/')[0])
135
+
136
+ self.ifile = str(filename)
137
+ self.ext = filename[-3:]
138
+
139
+ ifile = self.ifile
140
+
141
+ self.showtext('Input File: '+ifile)
142
+
143
+ # Read entire file
144
+ idata = read_ifile(ifile)
145
+ mrecs, monconv = self.get_record_info(idata)
146
+
147
+ # Start main loop
148
+ dat = []
149
+ for i in mrecs:
150
+ self.reset_vars(i[0], monconv[i[0]])
151
+
152
+ try:
153
+ self.extract_date(idata[i[1]]) # self.day, self.year from here
154
+ self.look_for_origin(idata[i[1]])
155
+ except ValueError:
156
+ self.inerror(idata[i[1]])
157
+ currecs = idata[i[1]:i[2]]
158
+
159
+ for j in currecs:
160
+ try:
161
+ self.look_for_region(j)
162
+ self.look_for_latitude(j)
163
+ self.look_for_depth(j)
164
+ self.look_for_magnitude(j)
165
+ except ValueError:
166
+ self.inerror(j)
167
+
168
+ self.numstations = 0
169
+ if i[3] == 'RECORDA':
170
+ self.get_data_record_a(currecs)
171
+ if i[3] == 'RECORDB':
172
+ self.get_data_record_b(currecs)
173
+ if i[3] == 'RECORDC':
174
+ self.get_data_record_c(currecs)
175
+ self.calc_rms()
176
+
177
+ # Make sure we have at least one time
178
+ if self.hour == 0 and self.minute == 0 and self.sec == 0.0:
179
+ self.hour = self.datahours[0]
180
+ self.minute = self.datamins[0]
181
+ self.sec = self.datasecs[0]
182
+
183
+ # Put data into seisan structures
184
+ self.event = {}
185
+ self.get_record_type_1()
186
+ self.get_record_type_e()
187
+ self.get_record_type_i()
188
+ self.get_record_type_4()
189
+
190
+ dat.append(self.event)
191
+
192
+ # Open output files
193
+ ofile = ifile[:-3]+'err'
194
+ self.ofile = open(ofile, 'w')
195
+
196
+ self.showtext('Error File: '+ofile)
197
+
198
+ self.ofile.write(self.parent.textbrowser_processlog.toPlainText())
199
+ self.ofile.close()
200
+
201
+ self.outdata['Seis'] = dat
202
+ self.showtext('\nCompleted!')
203
+
204
+ return True
205
+
206
+ def reset_vars(self, mon, mondec):
207
+ """ Used to reset the header variables to their defaults """
208
+ self.mon = mon
209
+ self.mondec = mondec
210
+ self.region = ''
211
+ self.lat = -999
212
+ self.laterr = -999
213
+ self.lon = -999
214
+ self.lonerr = -999
215
+ self.depth = -999
216
+ self.numstations = -999
217
+ self.datanum = -999
218
+ self.magnitude = -999
219
+ self.distanceindicator = 'R'
220
+ self.hour = 0
221
+ self.minute = 0
222
+ self.sec = 0.0
223
+ self.secerr = 0.0
224
+ self.datarms = 0
225
+
226
+ def reset_data_vars(self):
227
+ """ Resets the various data variables """
228
+ self.datanum = -1
229
+ self.timesection = ''
230
+ self.datastat = []
231
+ self.dataphase = []
232
+ self.datahours = []
233
+ self.datamins = []
234
+ self.datasecs = []
235
+ self.dataperiod = []
236
+ self.dataamplitude = []
237
+ self.datadist = []
238
+ self.datad = []
239
+ self.dataw = []
240
+ self.data_azim = []
241
+ self.dataresid = []
242
+
243
+ def init_data_var_row(self):
244
+ """ Initializes a data variable row """
245
+ self.datastat.append(' ')
246
+ self.dataphase.append(' ')
247
+ self.datahours.append(0)
248
+ self.datamins.append(0)
249
+ self.datasecs.append(0.0)
250
+ self.dataperiod.append(0.0)
251
+ self.dataamplitude.append(0.0)
252
+ self.datadist.append(0.0)
253
+ self.datad.append(' ')
254
+ self.dataw.append(1)
255
+ self.data_azim.append(0.0)
256
+ self.dataresid.append(0.0)
257
+
258
+ # Perhaps we should have a place to load in stations outside of the program?
259
+
260
+ def extract_date(self, tmp):
261
+ """ Extracts the date from the string """
262
+ tmp2 = tmp.partition(self.mon)
263
+ self.day = int(tmp2[0])
264
+ tmp2 = tmp2[2].split()
265
+ self.year = int(tmp2[0])
266
+
267
+ def look_for_magnitude(self, tmp):
268
+ """ Looks for the magnitude in the string """
269
+ if tmp.find('MAGNITUDE') > -1 and tmp.find('PHASE') == -1:
270
+ self.magnitude = float(tmp.partition('+-')[0][-4:])
271
+
272
+ def look_for_latitude(self, tmp):
273
+ """ Looks for latitude and longitude """
274
+ if tmp.find('LATITUDE') > -1:
275
+ tmp = tmp.replace(' ', '')
276
+ # remove extra illegal characters
277
+ tmp2 = ''
278
+ for i in tmp:
279
+ if i.isalnum() or i == '.' or i == '-' or i == '+' or i == '=':
280
+ tmp2 += i
281
+ else:
282
+ tmp2 += ''
283
+ tmp = tmp2
284
+ # extracted and forced negative
285
+ self.lat = -1*abs(float(tmp[tmp.find('.')-2:tmp.find('.')+3]))
286
+ tmp = tmp[tmp.find('.')+3:]
287
+ self.laterr = float(tmp[tmp.find('.')-3:tmp.find('.')+3])
288
+ tmp = tmp[tmp.find('.')+3:]
289
+ # extracted and forced negative
290
+ self.lon = float(tmp[tmp.find('.')-2:tmp.find('.')+3])
291
+ tmp = tmp[tmp.find('.')+3:]
292
+ self.lonerr = float(tmp[tmp.find('.')-3:tmp.find('.')+3])
293
+
294
+ def look_for_depth(self, tmp):
295
+ """ Looks for depth """
296
+ if tmp.find('DEPTH') > -1:
297
+ tmp = tmp.partition('=')[2]
298
+ tmp = tmp.partition('km')[0]
299
+ self.depth = float(tmp)
300
+
301
+ def look_for_region(self, tmp):
302
+ """ Looks for region """
303
+ if tmp.find('REGION') > -1:
304
+ self.region = tmp.partition(' ')[2]
305
+
306
+ def look_for_origin(self, tmp):
307
+ """ Looks for origin """
308
+ if tmp.find('ORIGIN') > -1:
309
+ self.hour = int(ncor(tmp.partition('h')[0][-2:]))
310
+ self.minute = int(ncor(tmp.partition('m')[0][-2:]))
311
+ self.sec = float(ncor(tmp.partition('+-')[0][-5:]))
312
+ self.secerr = float(ncor(tmp.partition('s')[0][-5:]))
313
+
314
+ def get_data_record_a(self, tmp):
315
+ """ gets record type A """
316
+ did_alt_phase = False
317
+ self.reset_data_vars()
318
+ # Get rid of spaces
319
+ tmp = clean_string(tmp)
320
+
321
+ self.distanceindicator = 'D'
322
+ for i in tmp[0:]:
323
+ station = is_stat(i)
324
+ if i.find('LZ') == -1:
325
+ tmp2 = i.split()
326
+ self.init_data_var_row()
327
+ try:
328
+ tmp2 = self.get_station(tmp2, station)
329
+ tmp2 = self.get_data_phase(tmp2, station, '')
330
+ tmp2 = self.get_data_d(tmp2)
331
+ tmp2 = self.get_time_section(tmp2)
332
+ tmp2 = self.get_data_period(tmp2)
333
+ tmp2 = self.get_data_amplitude(tmp2)
334
+ except ValueError:
335
+ self.inerror(i)
336
+ if station == '':
337
+ did_alt_phase = True
338
+ self.datanum = len(self.datastat)
339
+ self.numstations = int(self.datanum)
340
+ if did_alt_phase is True:
341
+ self.numstations = int(self.numstations / 2)
342
+ self.dataresid = [0.0]*self.datanum
343
+ self.data_azim = [0.0]*self.datanum
344
+ self.datadist = [0.0]*self.datanum
345
+
346
+ def get_data_record_b(self, tmp):
347
+ """ Gets record type B"""
348
+ self.reset_data_vars()
349
+ # Get rid of spaces
350
+ tmp = clean_string(tmp)
351
+
352
+ self.distanceindicator = 'R'
353
+ for i in tmp[0:]:
354
+ station = is_stat(i)
355
+ tmp2 = i.split()
356
+ self.init_data_var_row()
357
+ try:
358
+ tmp2 = self.get_station(tmp2, station)
359
+ tmp2 = self.get_data_dist(tmp2, station)
360
+ tmp2 = self.get_data_phase(tmp2, station, 'ES')
361
+ tmp2 = self.get_data_d(tmp2)
362
+ tmp2 = self.get_time_section(tmp2)
363
+ tmp2 = self.get_data_period(tmp2)
364
+ tmp2 = self.get_data_amplitude(tmp2)
365
+ except ValueError:
366
+ self.inerror(i)
367
+ self.datanum = len(self.datastat)
368
+ self.numstations = int(self.datanum/2)
369
+ self.dataresid = [0.0]*self.datanum
370
+ self.data_azim = [0.0]*self.datanum
371
+
372
+ def get_data_record_c(self, tmp):
373
+ """ Gets record type C """
374
+ self.reset_data_vars()
375
+ # Get rid of spaces
376
+ tmp = clean_string(tmp)
377
+
378
+ self.distanceindicator = 'R'
379
+ for i in tmp[0:]:
380
+ station = is_stat(i)
381
+ tmp2 = i.split()
382
+ self.init_data_var_row()
383
+ try:
384
+ tmp2 = self.get_station(tmp2, station)
385
+ tmp2 = self.get_data_dist(tmp2, station)
386
+ tmp2 = self.get_data_azim(tmp2, station)
387
+ tmp2 = self.get_data_phase(tmp2, station, '')
388
+ tmp2 = self.get_data_d(tmp2)
389
+ tmp2 = self.get_time_section(tmp2)
390
+ tmp2 = self.get_data_resid(tmp2, station)
391
+ tmp2 = self.get_data_period(tmp2)
392
+ tmp2 = self.get_data_amplitude(tmp2)
393
+ except ValueError:
394
+ self.inerror(i)
395
+ self.datanum = len(self.datastat)
396
+ self.numstations = int(self.datanum/2)
397
+
398
+ def get_station(self, tmp, station):
399
+ """ Gets the station """
400
+ if len(tmp) == 0:
401
+ return tmp
402
+
403
+ if station != '':
404
+ self.datastat[-1] = station
405
+ tmp.pop(0)
406
+ elif len(self.datastat) > 1:
407
+ self.datastat[-1] = self.datastat[-2]
408
+ else:
409
+ self.datastat[-1] = '???'
410
+ return tmp
411
+
412
+ def get_data_dist(self, tmp, station):
413
+ """ Gets the distance """
414
+ if len(tmp) == 0:
415
+ return tmp
416
+
417
+ if station == '' and len(self.datastat) > 1:
418
+ self.datadist[-1] = self.datadist[-2]
419
+ elif station == '' and len(self.datastat) < 2:
420
+ self.datadist[-1] = -999
421
+ if (station != '' and isfloat(tmp[0]) is True and
422
+ tmp[0].isdigit() is False):
423
+ self.datadist[-1] = float(tmp[0])
424
+ tmp.pop(0)
425
+ return tmp
426
+
427
+ def get_data_azim(self, tmp, station):
428
+ """ Gets the azimuth """
429
+ if len(tmp) == 0:
430
+ return tmp
431
+
432
+ if station == '' and len(self.data_azim) > 1:
433
+ self.data_azim[-1] = self.data_azim[-2]
434
+ elif station == '' and len(self.data_azim) < 2:
435
+ self.data_azim[-1] = -999
436
+ if (station != '' and isfloat(tmp[0]) is True and
437
+ tmp[0].isdigit() is False):
438
+ self.data_azim[-1] = float(tmp[0])
439
+ tmp.pop(0)
440
+ return tmp
441
+
442
+ def get_data_phase(self, tmp, station, default):
443
+ """ Gets the phase """
444
+ if len(tmp) == 0:
445
+ return tmp
446
+
447
+ self.dataphase[-1] = default
448
+ if station != '':
449
+ self.dataphase[-1] = ''
450
+ if tmp[0].find('E') != -1:
451
+ self.dataphase[-1] += 'E'
452
+ if tmp[0].find('I') != -1:
453
+ self.dataphase[-1] += 'I'
454
+ if tmp[0].find('P') != -1:
455
+ self.dataphase[-1] += 'P'
456
+ if tmp[0].find('S') != -1:
457
+ self.dataphase[-1] += 'S'
458
+ tmp.pop(0)
459
+ elif tmp[0].find('P') != -1 or tmp[0].find('S') != -1:
460
+ tmp.pop(0)
461
+ return tmp
462
+
463
+ def get_data_d(self, tmp):
464
+ """ Gets the D value """
465
+ if len(tmp) == 0:
466
+ return tmp
467
+
468
+ if tmp[0].isalpha():
469
+ self.datad[-1] = tmp[0]
470
+ tmp.pop(0)
471
+ elif tmp[0] == '*':
472
+ self.dataw[-1] = 4
473
+ tmp.pop(0)
474
+ return tmp
475
+
476
+ def get_time_section(self, tmp):
477
+ """ Gets the time """
478
+ if len(tmp) == 0:
479
+ return tmp
480
+ tmp2 = tmp.pop(0)
481
+ if tmp2.find('.') == -1:
482
+ if len(tmp) == 0:
483
+ return tmp
484
+ tmp2 += tmp.pop(0)
485
+ if tmp2.find('.') == -1:
486
+ if len(tmp) == 0:
487
+ return tmp
488
+ tmp2 += tmp.pop(0)
489
+ tmp2 = tmp2.zfill(8) # pad with zeros if needed
490
+ while tmp2.count('.') > 1:
491
+ tmp2 = tmp2.replace('.', '', 1)
492
+
493
+ self.datahours[-1] = int(tmp2[0:2])
494
+ self.datamins[-1] = int(tmp2[2:4])
495
+ self.datasecs[-1] = float(tmp2[4:])
496
+ if self.datasecs[-1] > 60.0:
497
+ self.showtext('Possible problem with time field')
498
+ # raise NameError('Possible problem with time field')
499
+ return tmp
500
+
501
+ def get_data_resid(self, tmp, station):
502
+ """ Gets the data residual """
503
+ if len(tmp) == 0:
504
+ return tmp
505
+ if (station != '' and isfloat(tmp[0]) is True and
506
+ tmp[0].isdigit() is False):
507
+ self.dataresid[-1] = float(tmp[0])
508
+ tmp.pop(0)
509
+ return tmp
510
+
511
+ def get_data_period(self, tmp):
512
+ """ Gets the period """
513
+ if len(tmp) > 0:
514
+ self.dataperiod[-1] = float(tmp[0])
515
+ tmp.pop(0)
516
+ return tmp
517
+
518
+ def get_data_amplitude(self, tmp):
519
+ """ Gets the amplitude """
520
+ if len(tmp) > 0:
521
+ self.dataamplitude[-1] = float(tmp[0][:4])*1000
522
+ tmp.pop(0)
523
+ return tmp
524
+
525
+ def calc_rms(self):
526
+ """ Calculates the RMS """
527
+ rmscnt = 0
528
+ if self.datanum > -1:
529
+ for i in range(self.datanum):
530
+ if self.dataw[i] != 4 and abs(self.dataresid[i]) > 0:
531
+ self.datarms += self.dataresid[i]**2
532
+ rmscnt = rmscnt + 1
533
+ if rmscnt > 0:
534
+ self.datarms = self.datarms / rmscnt
535
+ self.datarms = np.sqrt(self.datarms)
536
+ else:
537
+ self.datarms = 0
538
+
539
+ def get_record_type_1(self):
540
+ """ Writes record type 1"""
541
+ tmp = sdt.seisan_1()
542
+ tmp.year = self.year
543
+ tmp.month = self.mondec
544
+ tmp.day = self.day
545
+ # tmp.fixed_origin_time = i[10]
546
+ tmp.hour = self.hour
547
+ tmp.minutes = self.minute
548
+ tmp.seconds = self.sec
549
+ # tmp.location_model_indicator = i[20]
550
+ tmp.distance_indicator = self.distanceindicator
551
+ # tmp.event_id = i[22]
552
+ tmp.latitude = self.lat # -999 means none
553
+ tmp.longitude = self.lon # -999 means none
554
+ tmp.depth = self.depth # -999 means none
555
+ if self.depth != -999:
556
+ tmp.depth_indicator = 'F'
557
+ # tmp.locating_indicator = i[44]
558
+ tmp.hypocenter_reporting_agency = 'PRE'
559
+ tmp.number_of_stations_used = self.numstations
560
+ tmp.rms_of_time_residuals = self.datarms
561
+ tmp.magnitude_1 = self.magnitude
562
+ tmp.type_of_magnitude_1 = 'L'
563
+ tmp.magnitude_reporting_agency_1 = 'PRE'
564
+ # tmp.magnitude_2 = str2float(i[63:67])
565
+ # tmp.type_of_magnitude_2 = i[67]
566
+ # tmp.magnitude_reporting_agency_2 = i[68:71]
567
+ # tmp.magnitude_3 = str2float(i[71:75])
568
+ # tmp.type_of_magnitude_3 = i[75]
569
+ # tmp.magnitude_reporting_agency_3 = i[76:79]
570
+ self.event['1'] = tmp
571
+
572
+ def get_record_type_e(self):
573
+ """ Get record type E"""
574
+ if self.laterr != -999:
575
+ tmp = sdt.seisan_1()
576
+ tmp.gap = 0
577
+ tmp.origin_time_error = self.secerr
578
+ tmp.latitude_error = self.laterr
579
+ tmp.longitude_error = self.lonerr
580
+ tmp.depth_error = 0
581
+ tmp.cov_xy = 0
582
+ tmp.cov_xz = 0
583
+ tmp.cov_yz = 0
584
+
585
+ self.event['E'] = tmp
586
+
587
+ def get_record_type_i(self):
588
+ """ Get record type I"""
589
+ tmp = sdt.seisan_I()
590
+
591
+ tmp.last_action_done = 'SPL'
592
+ tmp.date_time_of_last_action = '09-02-11 11:35'
593
+ tmp.operator = 'ian '
594
+ tmp.status = ' '
595
+ tmp.id = (str(self.year).zfill(4)+str(self.mondec).zfill(2) +
596
+ str(self.day).zfill(2)+str(self.hour).zfill(2) +
597
+ str(self.minute).zfill(2)+str(int(round(self.sec))))
598
+ tmp.new_id_created = ' '
599
+ tmp.id_locked = 'L'
600
+
601
+ if self.region is not '':
602
+ tmp.region = self.region
603
+
604
+ self.event['I'] = tmp
605
+
606
+ def get_record_type_4(self):
607
+ """ Get record type 4"""
608
+ tmp2 = []
609
+ for i in range(self.datanum):
610
+ tmp = sdt.seisan_4()
611
+
612
+ tmp.station_name = self.datastat[i]
613
+ tmp.instrument_type = 'S'
614
+ tmp.component = 'Z'
615
+ if self.dataphase[i] is not '':
616
+ tmp.quality = self.dataphase[i][0]
617
+ tmp.phase_id = self.dataphase[i][1:]
618
+ if self.dataw[i] != 1:
619
+ tmp.weighting_indicator = self.dataw[i]
620
+ tmp.first_motion = self.datad[i]
621
+ if (self.datahours[i] != 0 or self.datamins[i] != 0 or
622
+ self.datasecs[i] != 0):
623
+ tmp.hour = self.datahours[i]
624
+ tmp.minutes = self.datamins[i]
625
+ tmp.seconds = self.datasecs[i]
626
+ tmp.coda = None
627
+
628
+ if self.dataamplitude[i] != 0:
629
+ tmp.amplitude = self.dataamplitude[i]
630
+
631
+ if self.dataperiod[i] != 0:
632
+ tmp.period = self.dataperiod[i]
633
+
634
+ tmp.direction_of_approach = None
635
+ tmp.phase_velocity = None
636
+ tmp.angle_of_incidence = None
637
+ tmp.azimuth_residual = None
638
+ tmp.travel_time_residual = None
639
+
640
+ if self.dataresid[i] != 0:
641
+ tmp.time_residual = self.dataresid[i]
642
+
643
+ if self.datadist[i] != 0:
644
+ tmp.epicentral_distance = self.datadist[i]
645
+
646
+ if self.data_azim[i] != 0:
647
+ tmp.azimuth_at_source = int(self.data_azim[i])
648
+
649
+ tmp2.append(tmp)
650
+
651
+ self.event['4'] = tmp2
652
+
653
+ def inerror(self, eline):
654
+ """ Writes an error to the error file """
655
+ if eline[0:3].isalpha():
656
+ station = is_stat(eline)
657
+ if station == '':
658
+ self.showtext('\nStation does not exist:')
659
+ self.showtext('\nCharacter recognition error:')
660
+ self.showtext('Line: "'+eline)
661
+
662
+ def get_record_info(self, idata):
663
+ """ Get the information on when records start and finish etc """
664
+ # Get Dates and the beginnings of sections
665
+ monconv = {'JAN': 1, 'FEB': 2, 'MAR': 3, 'APR': 4, 'MAY': 5, 'JUN': 6,
666
+ 'JUL': 7, 'AUG': 8, 'SEP': 9, 'OCT': 10, 'NOV': 11,
667
+ 'DEC': 12}
668
+ mrecs = []
669
+ for i in range(len(idata)):
670
+ for j in monconv.keys():
671
+ if idata[i].find(j) > -1:
672
+ mrecs.append([j, i])
673
+
674
+ # Add the end of each record.
675
+ for i in range(len(mrecs)-1):
676
+ mrecs[i].append(mrecs[i+1][1])
677
+ mrecs[-1].append(len(idata))
678
+
679
+ # Add the data record type
680
+ for i in range(len(mrecs)):
681
+ dtype = ''
682
+ for j in idata[mrecs[i][1]:mrecs[i][2]]:
683
+ if j.find('STA') > -1 and j.find('INST') > -1:
684
+ dtype = 'RECORDA'
685
+ if j.find('STA') > -1 and j.find('MAGNITUDE') > -1:
686
+ dtype = 'RECORDB'
687
+ if j.find('STA') > -1 and j.find('RESID') > -1:
688
+ dtype = 'RECORDC'
689
+ mrecs[i].append(dtype)
690
+ return mrecs, monconv
691
+
692
+
693
+ def read_ifile(ifile):
694
+ """ Routine to read and clean some of the input file """
695
+ # Read entire file
696
+ inputf = open(ifile)
697
+ idata = inputf.read()
698
+
699
+ # Fix bad characters
700
+ idata = idata.replace('\xb1', '+-')
701
+ idata = idata.replace('\xba', ' ')
702
+ idata = idata.replace('(P)', 'P')
703
+ idata = idata.replace('(S)', 'S')
704
+ idata = idata.replace(',', '.')
705
+ idata = re.sub(r'[^\x21-x7E\n]', ' ', idata)
706
+ # idata = nohex(idata)
707
+ inputf.close()
708
+
709
+ # Split into lines
710
+ idata = idata.splitlines()
711
+
712
+ # Strip spaces from front of lines
713
+ idata = [i.lstrip() for i in idata]
714
+ return idata
715
+
716
+
717
+ def isfloat(tmp):
718
+ """Check if a number is a float. Can take decimal point"""
719
+ try:
720
+ float(tmp)
721
+ return True
722
+ except ValueError:
723
+ return False
724
+
725
+
726
+ def clean_string(tmp):
727
+ """ Cleans string of illegal characters """
728
+ tmp = np.copy(tmp)
729
+ tmp = tmp[tmp != '']
730
+ tmp = tmp.tolist()
731
+ # remove header
732
+ while tmp[0].find('STA') == -1 or (tmp[0].find('INST') == -1 and
733
+ tmp[0].find('RESID') == -1 and
734
+ tmp[0].find('MAGNITUDE') == -1):
735
+ tmp.pop(0)
736
+ tmp.pop(0)
737
+
738
+ # remove extra illegal characters
739
+ tmp2 = []
740
+ for j in tmp:
741
+ tmp2.append('')
742
+ for i in j:
743
+ if i.isalnum() or i == '.' or i == '-':
744
+ tmp2[-1] += i
745
+ else:
746
+ tmp2[-1] += ' '
747
+
748
+ # remove page numbers
749
+ for j in range(len(tmp2)):
750
+ tmp3 = tmp2[j].replace(' ', '')
751
+ if tmp3[0] == '-' and tmp3[-1] == '-'and len(tmp3) <= 5:
752
+ tmp2[j] = ''
753
+
754
+ # remove some records
755
+ tmp2 = np.copy(tmp2)
756
+ tmp2 = tmp2[tmp2 != '']
757
+ tmp2 = tmp2[tmp2 != ' ']
758
+ tmp2 = tmp2[tmp2 != '- ']
759
+ tmp2 = tmp2[tmp2 != ' -']
760
+ tmp2 = tmp2[tmp2 != '-']
761
+ tmp2 = tmp2.tolist()
762
+
763
+ return tmp2
764
+
765
+
766
+ def is_stat(tmp):
767
+ """Check if the string is a station """
768
+ station = ''
769
+ stationlist = ['SNA', 'BEW', 'SNA', 'BEW', 'BPI', 'BFT', 'BLE', 'BLF',
770
+ 'BOSA', 'BFS', 'CVN', 'CER', 'ERS', 'FRS', 'GRM', 'HVD',
771
+ 'KSR', 'KSD', 'MSN', 'NWL', 'PRY', 'PHA', 'POF', 'POG',
772
+ 'PKA', 'SLR', 'SEK', 'SOE', 'SBO', 'SUR', 'SWZ', 'UPI',
773
+ 'WIN', 'KTS', 'KT1', 'KT2', 'KT3', 'KIM', 'TUH', 'CAV',
774
+ 'BUL', 'BOS', 'SME', 'CAV', 'NCA', 'SPB', 'JOZ', 'EVA',
775
+ 'KIM', 'VIR', 'BPI', 'UMT', 'ZOM', 'LLO', 'MZU', 'VPT',
776
+ 'CGY', 'PRE', 'MDN', 'MDL', 'PSD', 'QUA']
777
+
778
+ for i in stationlist:
779
+ if tmp.find(i) > -1:
780
+ station = i
781
+
782
+ # This section checked if any stations have mis-identifies P's or F's
783
+ if station == '':
784
+ tmp2 = tmp.replace('P', 'F')
785
+ for i in stationlist:
786
+ if tmp2.find(i) > -1:
787
+ station = i
788
+
789
+ return station
790
+
791
+
792
+ def ncor(tmp):
793
+ """ Correct number problems """
794
+ tmp = tmp.replace('I', '1')
795
+ return tmp