You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pyrocko/src/shadow_pile.py

131 lines
3.5 KiB
Python

# http://pyrocko.org - GPLv3
#
# The Pyrocko Developers, 21st Century
# ---|P------/S----------~Lg----------
from __future__ import absolute_import, division
import math
import logging
from . import pile, util, io
logger = logging.getLogger('pyrocko.shadow_pile')
class NoBasePileSet(Exception):
pass
class ShadowBlock(object):
def __init__(self):
self.mtime = None
self.files = []
class ShadowPile(pile.Pile):
def __init__(self, basepile=None, tinc=360., tpad=0., storepath=None):
pile.Pile.__init__(self)
self._tinc = tinc
self._tpad = tpad
self._storepath = storepath
self._blocks = {}
if basepile is None:
basepile = pile.Pile()
self.set_basepile(basepile)
def clear(self):
for iblock in self._blocks.keys():
self._clearblock()
self._blocks = {}
def set_basepile(self, basepile):
self.clear()
self._base = basepile
def get_basepile(self):
return self._base
def set_chopsize(self, tinc, tpad=0.):
self.clear()
self._tinc = tinc
self._tpad = tpad
def set_store(self, storepath=None):
self.clear()
self._storepath = storepath
def chopper(
self, tmin=None, tmax=None, tinc=None, tpad=0., *args, **kwargs):
if tmin is None:
tmin = self.base.tmin+tpad
if tmax is None:
tmax = self.base.tmax-tpad
self._update_range(tmin, tmax)
return pile.Pile.chopper(self, tmin, tmax, tinc, tpad, *args, **kwargs)
def process(self, iblock, tmin, tmax, traces):
return traces
def _update_range(self, tmin, tmax):
imin = int(math.floor(tmin / self._tinc))
imax = int(math.floor(tmax / self._tinc)+1)
todo = []
for i in range(imin, imax):
wmin = i * self._tinc
wmax = (i+1) * self._tinc
mtime = util.gmctime(self._base.get_newest_mtime(wmin, wmax))
if i not in self._blocks or self._blocks[i].mtime != mtime:
if i not in self._blocks:
self._blocks[i] = ShadowBlock()
todo.append(i)
self._blocks[i].mtime = mtime
else:
if todo:
self._process_blocks(todo[0], todo[-1]+1)
todo = []
if todo:
self._process_blocks(todo[0], todo[-1]+1)
def _process_blocks(self, imin, imax):
pmin = imin * self._tinc
pmax = imax * self._tinc
iblock = imin
for traces in self._base.chopper(pmin, pmax, self._tinc, self._tpad):
tmin = iblock*self._tinc
tmax = (iblock+1)*self._tinc
traces = self.process(iblock, tmin, tmax, traces)
if self._tpad != 0.0:
for trace in traces:
trace.chop(tmin, tmax, inplace=True)
self._clearblock(iblock)
self._insert(iblock, traces)
iblock += 1
def _insert(self, iblock, traces):
if traces:
if self._storepath is not None:
fns = io.save(
traces, self._storepath,
format='mseed',
additional={'iblock': iblock})
self.load_files(fns, fileformat='mseed', show_progress=False)
else:
file = pile.MemTracesFile(None, traces)
self.add_file(file)
def _clearblock(self, iblock):
for file in self._blocks[iblock].files:
self.remove_file(file)