diff --git a/.travis.yml b/.travis.yml
index 9040eb410..bf3abf771 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -75,6 +75,7 @@ install:
pytest
pytest-pep8
opencv
+ pyflakes=0.9.0
- source activate test-environment
# install packages not available via conda
# - pip install -r requirements.txt
diff --git a/CHANGES.md b/CHANGES.md
index 537f07be6..33eea1e66 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,27 @@
+## 0.1.1
+* Cope with events not always having time_errors in them in eventtoSfile;
+* Convert Quakeml depths from m to km;
+* Multiple little fixes to make Sfile conversion play well with GeoNet QuakeML files;
+* Add function to convert from obspy.core.inventory.station.Station to string format
+for Seisan STATION0.HYP file;
+* Merged feature branch - hypoDD into develop, this provides mappings for the
+hypoDD location program, including generation of dt.cc files;
+* Added tests for functions in catalog_to_dd;
+* Implemented unittest tests;
+* Changed name of EQcorrscan_plotting to plotting;
+* Added depreciation warnings;
+* Changed internal structure of pre-processing to aid long-term upkeep;
+* Added warnings in docs for template_gen relating to template generation from
+set length files;
+* Updated template_creation tutorial to use day-long data;
+* Renamed Sfile_util to sfile_util, and functions there-in: will warn about name changes;
+* Updated template plotting to include pick labels;
+* Updated template_creation tutorial to download S-picks as well as P-picks;
+* Update sfile_util to cope with many possible unfilled objects;
+* Added sac_util to convert from sac headers to useful event information - note,
+does not convert all things, just origin and pick times;
+* Added from_sac function to template_gen.
+
## 0.1.0
* Implimented tests for synthetic generation and match-filter functions
* Developed new tutorials that download from GeoNet and are much clearer
diff --git a/MANIFEST.in b/MANIFEST.in
index 74b64a4cf..d568d76be 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -18,5 +18,6 @@ prune eqcorrscan/doc/_build/latex
prune eqcorrscan/plot
prune eqcorrscan/detections
prune eqcorrscan/grid
+prune eqcorrscan/tests/test_data
# prune eqcorrscan/stack_templates
# prune eqcorrscan/templates
diff --git a/README.md b/README.md
index 4455fbe25..09a5bdeae 100644
--- a/README.md
+++ b/README.md
@@ -69,7 +69,7 @@ Also within this package are:
We are currently hovering around 9,000 lines of code (including doc-strings) - it is probably worth
having a look at the docs to check what functions we have. We plan to write a series of tutorials to be
-included on the EQcorrscan API to highlight key functions, currently our tutorial only shows
+included on the EQcorrscan API to highlight key functions, currently our tutorials only show
how to do the core matched-filter detection.
# Licence
@@ -108,3 +108,4 @@ will keep us all branching in the same way.
* Thurber, C. H., Zeng, X., Thomas, A. M., & Audet, P. (2014). [Phase‐Weighted Stacking Applied to Low‐Frequency Earthquakes](http://www.bssaonline.org/content/early/2014/08/12/0120140077.abstract), __BSSA__, doi:10.1785/0120140077.
* Frank, W. B., & Shapiro, N. M. (2014). [Automatic detection of low-frequency earthquakes (LFEs) based on a beamformed network response](http://gji.oxfordjournals.org/content/197/2/1215.short), __Geophysical Journal International__, 197(2), 1215-1223, doi:10.1093/gji/ggu058.
* Rubinstein, J. L., & Ellsworth, W. L. (2010). [Precise estimation of repeating earthquake moment: Example from Parkfield, California](http://www.bssaonline.org/content/100/5A/1952.short), __BSSA__, doi:10.1785/0120100007
+fa66e06971b2dd1e4bf766
diff --git a/eqcorrscan/__init__.py b/eqcorrscan/__init__.py
index 3d6f75ae9..a7996585c 100755
--- a/eqcorrscan/__init__.py
+++ b/eqcorrscan/__init__.py
@@ -30,10 +30,82 @@
You should have received a copy of the GNU General Public License
along with EQcorrscan. If not, see .
"""
-
+import sys
+import importlib
+import warnings
__all__ = ['core', 'utils', 'par']
-__version__ = '0.1.0'
+
+__version__ = '0.1.1'
+
+# Cope with changes to name-space to remove most of the camel-case
+_import_map = {
+ "eqcorrscan.utils.catalogue2DD": "eqcorrscan.utils.catalog_to_dd",
+ "eqcorrscan.utils.EQcorrscan_plotting": "eqcorrscan.utils.plotting"
+}
+
+
+class EQcorrscanDeprecationWarning(UserWarning):
+ """
+ Force pop-up of warnings.
+ """
+ pass
+
+
+class EQcorrscanRestructureAndLoad(object):
+ """
+ Path finder and module loader for transitioning
+ """
+ def find_module(self, fullname, path=None):
+ # Compatibility with namespace paths.
+ if hasattr(path, "_path"):
+ path = path._path
+
+ if not path or not path[0].startswith(__path__[0]):
+ return None
+
+ for key in _import_map.keys():
+ if fullname.startswith(key):
+ break
+ else:
+ return None
+ return self
+
+ def load_module(self, name):
+ # Use cached modules.
+ if name in sys.modules:
+ return sys.modules[name]
+ # Otherwise check if the name is part of the import map.
+ elif name in _import_map:
+ new_name = _import_map[name]
+ else:
+ new_name = name
+ for old, new in _import_map.items():
+ if not new_name.startswith(old):
+ continue
+ new_name = new_name.replace(old, new)
+ break
+ else:
+ return None
+
+ # Don't load again if already loaded.
+ if new_name in sys.modules:
+ module = sys.modules[new_name]
+ else:
+ module = importlib.import_module(new_name)
+
+ # Warn here as at this point the module has already been imported.
+ warnings.warn("Module '%s' is deprecated and will stop working "
+ "with the next EQcorrscan version. Please import module "
+ "'%s' instead." % (name, new_name),
+ EQcorrscanDeprecationWarning)
+ sys.modules[new_name] = module
+ sys.modules[name] = module
+ return module
+
+
+sys.meta_path.append(EQcorrscanRestructureAndLoad())
+
if __name__ == '__main__':
import doctest
doctest.testmod(exclude_empty=True)
diff --git a/eqcorrscan/core/bright_lights.py b/eqcorrscan/core/bright_lights.py
index 2d2098566..384c2f130 100644
--- a/eqcorrscan/core/bright_lights.py
+++ b/eqcorrscan/core/bright_lights.py
@@ -573,7 +573,7 @@ def brightness(stations, nodes, lags, stream, threshold, thresh_type,
from obspy.core.event import EventDescription, CreationInfo, Comment
import obspy.Stream
import matplotlib.pyplot as plt
- from eqcorrscan.utils import EQcorrscan_plotting as plotting
+ from eqcorrscan.utils import plotting
# Check that we actually have the correct stations
realstations = []
for station in stations:
@@ -659,7 +659,7 @@ def brightness(stations, nodes, lags, stream, threshold, thresh_type,
del energy, indeces
else:
print('Reading the temp files and computing network response')
- node_splits = len(nodes) // num_cores
+ node_splits = int(len(nodes) // num_cores)
indeces = [range(node_splits)]
for i in range(1, num_cores - 1):
indeces.append(range(node_splits * i, node_splits * (i + 1)))
diff --git a/eqcorrscan/core/match_filter.py b/eqcorrscan/core/match_filter.py
index c217e8a90..e85842329 100644
--- a/eqcorrscan/core/match_filter.py
+++ b/eqcorrscan/core/match_filter.py
@@ -401,12 +401,12 @@ def match_filter(template_names, template_list, st, threshold,
import matplotlib.pyplot as plt
plt.ioff()
import copy
- from eqcorrscan.utils import EQcorrscan_plotting
+ from eqcorrscan.utils import plotting
from eqcorrscan.utils import findpeaks
from obspy import Trace
import time
- # Copy the stream here because we will fuck about with it
+ # Copy the stream here because we will muck about with it
stream = st.copy()
templates = copy.deepcopy(template_list)
# Debug option to confirm that the channel names match those in the
@@ -517,19 +517,19 @@ def match_filter(template_names, template_list, st, threshold,
cccsum_hist = cccsum_plot.copy()
cccsum_hist = cccsum_hist.decimate(int(stream[0].stats.
sampling_rate / 10)).data
- cccsum_plot = EQcorrscan_plotting.chunk_data(cccsum_plot, 10,
- 'Maxabs').data
+ cccsum_plot = plotting.chunk_data(cccsum_plot, 10,
+ 'Maxabs').data
# Enforce same length
stream_plot.data = stream_plot.data[0:len(cccsum_plot)]
cccsum_plot = cccsum_plot[0:len(stream_plot.data)]
cccsum_hist = cccsum_hist[0:len(stream_plot.data)]
- EQcorrscan_plotting.triple_plot(cccsum_plot, cccsum_hist,
- stream_plot, rawthresh, True,
- plotdir + '/cccsum_plot_' +
- template_names[i] + '_' +
- stream[0].stats.starttime.
- datetime.strftime('%Y-%m-%d') +
- '.' + plot_format)
+ plotting.triple_plot(cccsum_plot, cccsum_hist,
+ stream_plot, rawthresh, True,
+ plotdir + '/cccsum_plot_' +
+ template_names[i] + '_' +
+ stream[0].stats.starttime.
+ datetime.strftime('%Y-%m-%d') +
+ '.' + plot_format)
if debug >= 4:
print(' '.join(['Saved the cccsum to:', template_names[i],
stream[0].stats.starttime.datetime.
diff --git a/eqcorrscan/core/template_gen.py b/eqcorrscan/core/template_gen.py
index 4e0d9f8c2..2b5ee3c13 100644
--- a/eqcorrscan/core/template_gen.py
+++ b/eqcorrscan/core/template_gen.py
@@ -3,6 +3,13 @@
for the application of cross-correlation of seismic data for the detection of \
repeating events.
+.. note:: All of these functions work for a single template, however all of \
+ them call _template_gen, which takes care of pick association and \
+ cutting. If you have many templates in one day of data it would be \
+ simple to write a wrapper that cuts multiple templates from one day \
+ of processed data rather than re-processing the same day of data \
+ for each template.
+
Code written by Calum John Chamberlain & Chet Hopp of \
Victoria University of Wellington, 2015.
@@ -30,8 +37,72 @@
from __future__ import unicode_literals
+def from_sac(sac_files, lowcut, highcut, samp_rate, filt_order, length, swin,
+ prepick=0.05, debug=0, plot=False):
+ """Function to read picks and waveforms from SAC data, and generate a \
+ template from these.
+
+ :type sac_files: list or stream
+ :param sac_files: List or stream of sac waveforms, or list of paths to \
+ sac waveforms.
+ :type lowcut: float
+ :param lowcut: Low cut (Hz), if set to None will look in template \
+ defaults file
+ :type highcut: float
+ :param highcut: High cut (Hz), if set to None will look in template \
+ defaults file
+ :type samp_rate: float
+ :param samp_rate: New sampling rate in Hz, if set to None will look in \
+ template defaults file
+ :type filt_order: int
+ :param filt_order: Filter level, if set to None will look in \
+ template defaults file
+ :type swin: str
+ :param swin: Either 'all', 'P' or 'S', to select which phases to output.
+ :type length: float
+ :param length: Extract length in seconds, if None will look in template \
+ defaults file.
+ :type prepick: float
+ :param prepick: Length to extract prior to the pick in seconds.
+ :type debug: int
+ :param debug: Debug level, higher number=more output.
+ :type plot: bool
+ :param plot: Turns template plotting on or off.
+
+ :returns: obspy.Stream Newly cut template
+
+ .. note:: This functionality is not supported for obspy versions below \
+ 1.0.0 as references times are not read in by SACIO, which are needed \
+ for defining pick times.
+ """
+ from obspy import read, Stream
+ from eqcorrscan.utils.sac_util import sactoevent
+ from eqcorrscan.utils import pre_processing
+ # Check whether sac_files is a stream or a list
+ if isinstance(sac_files, list):
+ if isinstance(sac_files[0], str) or isinstance(sac_files[0], unicode):
+ sac_files = [read(sac_file)[0] for sac_file in sac_files]
+ if isinstance(sac_files[0], Stream):
+ # This is a list of streams...
+ st = sac_files[0]
+ for sac_file in sac_files[1:]:
+ st += sac_file
+ st = Stream(sac_files)
+ elif isinstance(sac_files, Stream):
+ st = sac_files
+ # Make an event object...
+ event = sactoevent(st)
+ # Process the data
+ st.merge(fill_value='interpolate')
+ st = pre_processing.shortproc(st, lowcut, highcut, filt_order,
+ samp_rate, debug)
+ template = _template_gen(picks=event.picks, st=st, length=length,
+ swin=swin, prepick=prepick, plot=plot)
+ return template
+
+
def from_sfile(sfile, lowcut, highcut, samp_rate, filt_order, length, swin,
- debug=0, plot=False):
+ prepick=0.05, debug=0, plot=False):
r"""Function to read in picks from sfile then generate the template from \
the picks within this and the wavefile found in the pick file.
@@ -56,12 +127,19 @@ def from_sfile(sfile, lowcut, highcut, samp_rate, filt_order, length, swin,
:type length: float
:param length: Extract length in seconds, if None will look in template \
defaults file.
+ :type prepick: float
+ :param prepick: Length to extract prior to the pick in seconds.
:type debug: int
:param debug: Debug level, higher number=more output.
:type plot: bool
:param plot: Turns template plotting on or off.
:returns: obspy.Stream Newly cut template
+
+ .. warning:: This will use whatever data is pointed to in the s-file, if \
+ this is not the coninuous data, we recommend using other functions. \
+ Differences in processing between short files and day-long files \
+ (inherent to resampling) will produce lower cross-correlations.
"""
# Perform some checks first
import os
@@ -69,10 +147,10 @@ def from_sfile(sfile, lowcut, highcut, samp_rate, filt_order, length, swin,
raise IOError('sfile does not exist')
from eqcorrscan.utils import pre_processing
- from eqcorrscan.utils import Sfile_util
+ from eqcorrscan.utils import sfile_util
from obspy import read as obsread
# Read in the header of the sfile
- wavefiles = Sfile_util.readwavename(sfile)
+ wavefiles = sfile_util.readwavename(sfile)
pathparts = sfile.split('/')[0:-1]
new_path_parts = []
for part in pathparts:
@@ -100,7 +178,7 @@ def from_sfile(sfile, lowcut, highcut, samp_rate, filt_order, length, swin,
raise ValueError("Trace: " + tr.stats.station +
" sampling rate: " + str(tr.stats.sampling_rate))
# Read in pick info
- catalog = Sfile_util.readpicks(sfile)
+ catalog = sfile_util.readpicks(sfile)
# Read the list of Picks for this event
picks = catalog[0].picks
print("I have found the following picks")
@@ -113,7 +191,8 @@ def from_sfile(sfile, lowcut, highcut, samp_rate, filt_order, length, swin,
st.merge(fill_value='interpolate')
st = pre_processing.shortproc(st, lowcut, highcut, filt_order,
samp_rate, debug)
- st1 = _template_gen(picks, st, length, swin, plot=plot)
+ st1 = _template_gen(picks=picks, st=st, length=length, swin=swin,
+ prepick=prepick, plot=plot)
return st1
@@ -170,16 +249,16 @@ def from_contbase(sfile, contbase_list, lowcut, highcut, samp_rate, filt_order,
# import some things
from eqcorrscan.utils import pre_processing
- from eqcorrscan.utils import Sfile_util
+ from eqcorrscan.utils import sfile_util
import glob
from obspy import read as obsread
# Read in the header of the sfile
- event = Sfile_util.readheader(sfile)
+ event = sfile_util.readheader(sfile)
day = event.origins[0].time
# Read in pick info
- catalog = Sfile_util.readpicks(sfile)
+ catalog = sfile_util.readpicks(sfile)
picks = catalog[0].picks
print("I have found the following picks")
pick_chans = []
@@ -249,7 +328,10 @@ def from_quakeml(quakeml, st, lowcut, highcut, samp_rate, filt_order,
:param quakeml: QuakeML file containing pick information, can contain \
multiple events.
:type st: class: obspy.Stream
- :param st: Stream containing waveform data for template (hopefully)
+ :param st: Stream containing waveform data for template (hopefully). \
+ Note that this should be the same length of stream as you will use \
+ for the continuous detection, e.g. if you detect in day-long files, \
+ give this a day-long file!
:type lowcut: float
:param lowcut: Low cut (Hz), if set to None will look in template \
defaults file
@@ -275,6 +357,11 @@ def from_quakeml(quakeml, st, lowcut, highcut, samp_rate, filt_order,
:param plot: Display template plots or not
:returns: list of obspy.Stream Newly cut templates
+
+ .. warning:: We suggest giving this function a full day of data, to \
+ ensure templates are generated with **exactly** the same processing \
+ as the continuous data. Not doing this will result in slightly \
+ reduced cross-correlation values.
"""
# Perform some checks first
import os
@@ -295,8 +382,9 @@ def from_quakeml(quakeml, st, lowcut, highcut, samp_rate, filt_order,
st.merge(fill_value='interpolate')
for tr in st:
tr = pre_processing.dayproc(tr, lowcut, highcut, filt_order,
- samp_rate, debug,
- UTCDateTime(tr.stats.starttime.date))
+ samp_rate, debug=debug,
+ starttime=UTCDateTime(tr.stats.
+ starttime.date))
# Read QuakeML file into Catalog class
catalog = read_events(quakeml)
templates = []
@@ -368,6 +456,7 @@ def from_seishub(catalog, url, lowcut, highcut, samp_rate, filt_order,
else:
from obspy.seishub import Client
from eqcorrscan.utils import pre_processing
+ from obspy import UTCDateTime
client = Client(url)
temp_list = []
for event in catalog:
@@ -380,9 +469,12 @@ def from_seishub(catalog, url, lowcut, highcut, samp_rate, filt_order,
sta = pick.waveform_id.station_code
chan = pick.waveform_id.channel_code
loc = pick.waveform_id.location_code
- starttime = pick.time - (prepick + 600)
- # Enforce some pad, 10min either side, to reduce filter effects
- endtime = pick.time + length + 600 - prepick
+ starttime = UTCDateTime(pick.time.date)
+ endtime = starttime + 86400
+ # Here we download a full day of data. We do this so that minor
+ # differences in processing during processing due to the effect
+ # of resampling do not impinge on our cross-correaltions.
+
if debug > 0:
print('start-time: ' + str(starttime))
print('end-time: ' + str(endtime))
@@ -401,8 +493,9 @@ def from_seishub(catalog, url, lowcut, highcut, samp_rate, filt_order,
st.plot()
print('Preprocessing data for event: '+str(event.resource_id))
st.merge(fill_value='interpolate')
- st1 = pre_processing.shortproc(st, lowcut, highcut, filt_order,
- samp_rate, debug)
+ st1 = pre_processing.dayproc(st, lowcut, highcut, filt_order,
+ samp_rate, starttime=starttime,
+ debug=debug)
template = _template_gen(event.picks, st1, length, swin, prepick,
plot=plot)
del st, st1
@@ -456,6 +549,7 @@ def from_client(catalog, client_id, lowcut, highcut, samp_rate, filt_order,
from obspy.fdsn import Client
from obspy.fdsn.header import FDSNException
from eqcorrscan.utils import pre_processing
+ from obspy import UTCDateTime
import warnings
client = Client(client_id)
@@ -469,13 +563,16 @@ def from_client(catalog, client_id, lowcut, highcut, samp_rate, filt_order,
sta = pick.waveform_id.station_code
chan = pick.waveform_id.channel_code
loc = pick.waveform_id.location_code
- starttime = pick.time - (prepick + 600)
- # Enforce some pad, 10min either side, to reduce filter effects
- endtime = pick.time + length + 600 - prepick
+ starttime = UTCDateTime(pick.time.date)
+ endtime = starttime + 86400
+ # Here we download a full day of data. We do this so that minor
+ # differences in processing during processing due to the effect
+ # of resampling do not impinge on our cross-correaltions.
if debug > 0:
print('start-time: ' + str(starttime))
print('end-time: ' + str(endtime))
print('pick-time: ' + str(pick.time))
+ print('pick phase: ' + pick.phase_hint)
print('.'.join([net, sta, loc, chan]))
if 'st' not in locals():
try:
@@ -493,8 +590,9 @@ def from_client(catalog, client_id, lowcut, highcut, samp_rate, filt_order,
st.plot()
print('Pre-processing data for event: '+str(event.resource_id))
st.merge(fill_value='interpolate')
- st1 = pre_processing.shortproc(st, lowcut, highcut, filt_order,
- samp_rate, debug)
+ st1 = pre_processing.dayproc(st, lowcut, highcut, filt_order,
+ samp_rate, starttime=starttime,
+ debug=debug, parallel=True)
if debug > 0:
st1.plot()
template = _template_gen(event.picks, st1, length, swin, prepick,
@@ -537,7 +635,7 @@ def _template_gen(picks, st, length, swin='all', prepick=0.05, plot=False):
all channels with picks will be used.
"""
import copy
- from eqcorrscan.utils.EQcorrscan_plotting import pretty_template_plot as\
+ from eqcorrscan.utils.plotting import pretty_template_plot as\
tplot
from obspy import Stream
import warnings
@@ -648,7 +746,9 @@ def _template_gen(picks, st, length, swin='all', prepick=0.05, plot=False):
10,
st1.sort(['starttime'])[-1].stats.endtime +
10)
- tplot(st1, background=background)
+ tplot(st1, background=background,
+ title='Template for '+str(st1[0].stats.starttime),
+ picks=picks)
del stplot
del st
# st1.plot(size=(800,600))
diff --git a/eqcorrscan/core/thresholding.py b/eqcorrscan/core/thresholding.py
index 6ae2e0590..deacfcf6f 100755
--- a/eqcorrscan/core/thresholding.py
+++ b/eqcorrscan/core/thresholding.py
@@ -88,7 +88,7 @@ def coherence_test(stream, stations, nodes, lags, wlen):
# path = os.path.dirname(os.path.abspath(__file__))
# sys.path.insert(0, path[0:len(path)-5])
# from core import bright_lights
-# from utils import EQcorrscan_plotting as plotting
+# from utils import plotting
# # Use the brightness function to search for possible
# # templates
# # First read in the travel times
diff --git a/eqcorrscan/doc/_build/doctrees/environment.pickle b/eqcorrscan/doc/_build/doctrees/environment.pickle
index 6c8ae4f9d..d52903160 100644
Binary files a/eqcorrscan/doc/_build/doctrees/environment.pickle and b/eqcorrscan/doc/_build/doctrees/environment.pickle differ
diff --git a/eqcorrscan/doc/_build/doctrees/index.doctree b/eqcorrscan/doc/_build/doctrees/index.doctree
index 37e1085f7..25db04067 100644
Binary files a/eqcorrscan/doc/_build/doctrees/index.doctree and b/eqcorrscan/doc/_build/doctrees/index.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/intro.doctree b/eqcorrscan/doc/_build/doctrees/intro.doctree
index 9b99ffdd7..2d39a73f0 100644
Binary files a/eqcorrscan/doc/_build/doctrees/intro.doctree and b/eqcorrscan/doc/_build/doctrees/intro.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/submodules/core.bright_lights.doctree b/eqcorrscan/doc/_build/doctrees/submodules/core.bright_lights.doctree
index 7c782fa0d..9cd9f5609 100644
Binary files a/eqcorrscan/doc/_build/doctrees/submodules/core.bright_lights.doctree and b/eqcorrscan/doc/_build/doctrees/submodules/core.bright_lights.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/submodules/core.match_filter.doctree b/eqcorrscan/doc/_build/doctrees/submodules/core.match_filter.doctree
index 67e1a5595..8072e540c 100644
Binary files a/eqcorrscan/doc/_build/doctrees/submodules/core.match_filter.doctree and b/eqcorrscan/doc/_build/doctrees/submodules/core.match_filter.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/submodules/core.template_gen.doctree b/eqcorrscan/doc/_build/doctrees/submodules/core.template_gen.doctree
index 5b49aa846..8b4e5f1d7 100644
Binary files a/eqcorrscan/doc/_build/doctrees/submodules/core.template_gen.doctree and b/eqcorrscan/doc/_build/doctrees/submodules/core.template_gen.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/submodules/utils.EQcorrscan_plotting.doctree b/eqcorrscan/doc/_build/doctrees/submodules/utils.EQcorrscan_plotting.doctree
index 80f842f00..e468ca5eb 100644
Binary files a/eqcorrscan/doc/_build/doctrees/submodules/utils.EQcorrscan_plotting.doctree and b/eqcorrscan/doc/_build/doctrees/submodules/utils.EQcorrscan_plotting.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/submodules/utils.Sfile_util.doctree b/eqcorrscan/doc/_build/doctrees/submodules/utils.Sfile_util.doctree
index b5abec22a..3c0dd813d 100644
Binary files a/eqcorrscan/doc/_build/doctrees/submodules/utils.Sfile_util.doctree and b/eqcorrscan/doc/_build/doctrees/submodules/utils.Sfile_util.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/submodules/utils.catalog_to_dd.doctree b/eqcorrscan/doc/_build/doctrees/submodules/utils.catalog_to_dd.doctree
new file mode 100644
index 000000000..9b9433606
Binary files /dev/null and b/eqcorrscan/doc/_build/doctrees/submodules/utils.catalog_to_dd.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/submodules/utils.clustering.doctree b/eqcorrscan/doc/_build/doctrees/submodules/utils.clustering.doctree
index bc3864425..e8b3931cf 100644
Binary files a/eqcorrscan/doc/_build/doctrees/submodules/utils.clustering.doctree and b/eqcorrscan/doc/_build/doctrees/submodules/utils.clustering.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/submodules/utils.findpeaks.doctree b/eqcorrscan/doc/_build/doctrees/submodules/utils.findpeaks.doctree
index 351a3080a..04932e0ff 100644
Binary files a/eqcorrscan/doc/_build/doctrees/submodules/utils.findpeaks.doctree and b/eqcorrscan/doc/_build/doctrees/submodules/utils.findpeaks.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/submodules/utils.mag_calc.doctree b/eqcorrscan/doc/_build/doctrees/submodules/utils.mag_calc.doctree
index e771dbb83..adb5f1e32 100644
Binary files a/eqcorrscan/doc/_build/doctrees/submodules/utils.mag_calc.doctree and b/eqcorrscan/doc/_build/doctrees/submodules/utils.mag_calc.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/submodules/utils.plotting.doctree b/eqcorrscan/doc/_build/doctrees/submodules/utils.plotting.doctree
new file mode 100644
index 000000000..c5f650bd9
Binary files /dev/null and b/eqcorrscan/doc/_build/doctrees/submodules/utils.plotting.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/submodules/utils.pre_processing.doctree b/eqcorrscan/doc/_build/doctrees/submodules/utils.pre_processing.doctree
index ea0087291..15e0d7446 100644
Binary files a/eqcorrscan/doc/_build/doctrees/submodules/utils.pre_processing.doctree and b/eqcorrscan/doc/_build/doctrees/submodules/utils.pre_processing.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/submodules/utils.sac_util.doctree b/eqcorrscan/doc/_build/doctrees/submodules/utils.sac_util.doctree
new file mode 100644
index 000000000..605a79f5b
Binary files /dev/null and b/eqcorrscan/doc/_build/doctrees/submodules/utils.sac_util.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/submodules/utils.seismo_logs.doctree b/eqcorrscan/doc/_build/doctrees/submodules/utils.seismo_logs.doctree
index 0d0a7bef2..9a6a589f9 100644
Binary files a/eqcorrscan/doc/_build/doctrees/submodules/utils.seismo_logs.doctree and b/eqcorrscan/doc/_build/doctrees/submodules/utils.seismo_logs.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/submodules/utils.sfile_util.doctree b/eqcorrscan/doc/_build/doctrees/submodules/utils.sfile_util.doctree
new file mode 100644
index 000000000..bae85d37d
Binary files /dev/null and b/eqcorrscan/doc/_build/doctrees/submodules/utils.sfile_util.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/submodules/utils.stacking.doctree b/eqcorrscan/doc/_build/doctrees/submodules/utils.stacking.doctree
index 02b21b0dd..3df0156e4 100644
Binary files a/eqcorrscan/doc/_build/doctrees/submodules/utils.stacking.doctree and b/eqcorrscan/doc/_build/doctrees/submodules/utils.stacking.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/submodules/utils.synth_seis.doctree b/eqcorrscan/doc/_build/doctrees/submodules/utils.synth_seis.doctree
index d480d8398..c1c860b2e 100644
Binary files a/eqcorrscan/doc/_build/doctrees/submodules/utils.synth_seis.doctree and b/eqcorrscan/doc/_build/doctrees/submodules/utils.synth_seis.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/tutorials/matched-filter.doctree b/eqcorrscan/doc/_build/doctrees/tutorials/matched-filter.doctree
index f85d8f7b8..a6c15e0c5 100644
Binary files a/eqcorrscan/doc/_build/doctrees/tutorials/matched-filter.doctree and b/eqcorrscan/doc/_build/doctrees/tutorials/matched-filter.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/tutorials/template-creation.doctree b/eqcorrscan/doc/_build/doctrees/tutorials/template-creation.doctree
index b627d5934..a393a2a46 100644
Binary files a/eqcorrscan/doc/_build/doctrees/tutorials/template-creation.doctree and b/eqcorrscan/doc/_build/doctrees/tutorials/template-creation.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/updates.doctree b/eqcorrscan/doc/_build/doctrees/updates.doctree
new file mode 100644
index 000000000..d4daf6dda
Binary files /dev/null and b/eqcorrscan/doc/_build/doctrees/updates.doctree differ
diff --git a/eqcorrscan/doc/_build/doctrees/utils.doctree b/eqcorrscan/doc/_build/doctrees/utils.doctree
index 898ca372f..3cf5c60c4 100644
Binary files a/eqcorrscan/doc/_build/doctrees/utils.doctree and b/eqcorrscan/doc/_build/doctrees/utils.doctree differ
diff --git a/eqcorrscan/doc/_build/html/.buildinfo b/eqcorrscan/doc/_build/html/.buildinfo
index 396a78b21..40c193d83 100644
--- a/eqcorrscan/doc/_build/html/.buildinfo
+++ b/eqcorrscan/doc/_build/html/.buildinfo
@@ -1,4 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
-config: 66c486cd85f32812f89c64141c06ce4c
+config: e9ef4141a04a343e14d396aa0126b14f
tags: 645f666f9bcd5a90fca523b33c5a78b7
diff --git a/eqcorrscan/doc/_build/html/_modules/EQcorrscan_plotting.html b/eqcorrscan/doc/_build/html/_modules/EQcorrscan_plotting.html
index d005d9076..bedc00f4e 100644
--- a/eqcorrscan/doc/_build/html/_modules/EQcorrscan_plotting.html
+++ b/eqcorrscan/doc/_build/html/_modules/EQcorrscan_plotting.html
@@ -7,7 +7,7 @@
-
+"""
+This module contains functions to convert seisan catalogue to files to hypoDD
+input files.
+
+These functions will generate both a catalogue (dt.ct) file, event
+file (event.dat), station information file (station.dat), and a correlation
+oiutput file correlated every event in the catalogue with every other event to
+optimize the picks (dt.cc).
+
+The correlation routine relies on obspy's xcorr_pick_correction function from
+the obspy.signal.cross_correlation module. This function optimizes picks to
+better than sample accuracy by interpolating the correlation function and
+finding the maximum of this rather than the true maximum correlation value.
+The output from this function is stored in the dt.cc file.
+
+Information for the station.dat file is read from SEISAN's STATION0.HYP file
+
+Earthquake picks and locations are taken from the catalogued s-files - these
+must be pre-located before entering this routine as origin times and hypocentre
+locations are needed for event.dat files.
+
+Copyright 2015 Calum Chamberlain
+
+This file is part of EQcorrscan.
+
+ EQcorrscan is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ EQcorrscan is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with EQcorrscan. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+fromeqcorrscan.utilsimportsfile_util
+importos
+
+
+
[docs]def_cc_round(num,dp):
+ """
+ Convenience function to take a float and round it to dp padding with zeros
+ to return a string
+
+ :type num: float
+ :param num: Number to round
+ :type dp: int
+ :param dp: Number of decimal places to round to.
+
+ :returns: str
+ """
+ num=round(num,dp)
+ num='{0:.{1}f}'.format(num,dp)
+ returnnum
+
+
[docs]defreadSTATION0(path,stations):
+ """
+ Function to read the STATION0.HYP file on the path given. Outputs written
+ in station.dat file.
+
+ :type path: str
+ :param path: Path to the STATION0.HYP file
+ :type station: list
+ :param station: Stations to look for
+
+ :returns: List of tuples of station, lat, long, elevation
+ """
+ stalist=[]
+ f=open(path+'/STATION0.HYP','r')
+ forlineinf:
+ ifline[1:6].strip()instations:
+ station=line[1:6].strip()
+ lat=line[6:14]# Format is either ddmm.mmS/N or ddmm(.)mmmS/N
+ iflat[-1]=='S':
+ NS=-1
+ else:
+ NS=1
+ iflat[4]=='.':
+ lat=(int(lat[0:2])+float(lat[2:-1])/60)*NS
+ else:
+ lat=(int(lat[0:2])+float(lat[2:4]+'.'+lat[4:-1])/
+ 60)*NS
+ lon=line[14:23]
+ iflon[-1]=='S':
+ EW=-1
+ else:
+ EW=1
+ iflon[5]=='.':
+ lon=(int(lon[0:3])+float(lon[3:-1])/60)*EW
+ else:
+ lon=(int(lon[0:3])+float(lon[3:5]+'.'+lon[5:-1])/
+ 60)*EW
+ elev=float(line[23:-1].strip())
+ # Note, negative altitude can be indicated in 1st column
+ ifline[0]=='-':
+ elev*=-1
+ stalist.append((station,lat,lon,elev))
+ f.close()
+ f=open('station.dat','w')
+ forstainstalist:
+ line=''.join([sta[0].ljust(5),_cc_round(sta[1],4).ljust(10),
+ _cc_round(sta[2],4).ljust(10),
+ _cc_round(sta[3]/1000,4).rjust(7),'\n'])
+ f.write(line)
+ f.close()
+ returnstalist
+
+
+
[docs]defsfiles_to_event(sfile_list):
+ """
+ Function to write out an event.dat file of the events
+
+ :type sfile_list: list
+ :param sfile_list: List of s-files to sort and put into the database
+
+ :returns: List of tuples of event ID (int) and Sfile name
+ """
+ fromobspy.core.eventimportCatalog
+ event_list=[]
+ sort_list=[(sfile_util.readheader(sfile).origins[0].time,sfile)
+ forsfileinsfile_list]
+ sort_list.sort(key=lambdatup:tup[0])
+ sfile_list=[sfile[1]forsfileinsort_list]
+ catalog=Catalog()
+ fori,sfileinenumerate(sfile_list):
+ event_list.append((i,sfile))
+ catalog.append(sfile_util.readheader(sfile))
+ # Hand off to sister function
+ write_event(catalog)
+ returnevent_list
+
+