def test_align(self): """Check that alignment does as expected.""" test_stream = Stream(read()[0]) # Shift it length = 15 st1 = test_stream.copy().trim(test_stream[0].stats.starttime + 3, test_stream[0].stats.starttime + 3 + length) st2 = test_stream.trim(test_stream[0].stats.starttime, test_stream[0].stats.starttime + length) aligned = subspace.align_design(design_set=[st1.copy(), st2.copy()], shift_len=5, reject=0.3, multiplex=False, plot=False) self.assertEqual(aligned[0][0].stats.starttime, aligned[1][0].stats.starttime)
def stack_party(party, sac_dir, method='linear', filt_params=None, align=True, shift_len=0.1, prepick=2., postpick=5., reject=0.7, normalize=False, plot=False, outdir=None): """ Return a stream for the linear stack of the templates in a multiplet. The approach here is to first stack all of the detections in a family over the rejection ccc threshold and THEN stack the Family stacks into the final stack for the multiplet. This avoids attempting to correlate detections from different Families with each other, which is nonsensical. :param party: Party for the multiplet we're interested in :param sac_dir: Directory of SAC files made for Stefan :param method: Stacking method: 'linear' or 'PWS' :param filt_params: (optional) Dictionary of filter parameters to use before aligning waveforms. Keys must be 'highcut', 'lowcut', 'filt_order', and 'samp_rate' :param align: Whether or not to align the waveforms :param shift_len: Allowed shift in aligning in seconds :param reject: Correlation coefficient cutoff in aligning :param normalize: Whether to normalize before stacking :param plot: Alignment plot flag :return: """ sac_dirs = glob('{}/2*'.format(sac_dir)) fam_stacks = {} for fam in party: fam_id = fam.template.event.resource_id print('For Family {}'.format(fam_id)) eids = [str(ev.resource_id).split('/')[-1] for ev in fam.catalog] raws = [] for s_dir in sac_dirs: if s_dir.split('/')[-1] in eids: raws.append( read('{}/*'.format(s_dir)).merge(fill_value='interpolate')) # Stupid check for empty det directories. Not yet resolved lens = [len(raw) for raw in raws] if len(lens) == 0: continue if max(lens) == 0: continue print('Removing all traces without 3001 samples') for st in raws: for tr in st.copy(): if len(tr.data) != 3001: st.remove(tr) if filt_params: for raw in raws: shortproc(raw, lowcut=filt_params['lowcut'], highcut=filt_params['highcut'], filt_order=filt_params['filt_order'], samp_rate=filt_params['samp_rate']) print('Now trimming around pick times') z_streams = [] for raw in raws: z_stream = Stream() for tr in raw.copy(): if 'a' in tr.stats.sac: strt = tr.stats.starttime z_stream += tr.trim( starttime=strt + tr.stats.sac['a'] - prepick, endtime=strt + tr.stats.sac['a'] + postpick) if len(z_stream) > 0: z_streams.append(z_stream) # At the moment, the picks are based on P-arrival correlation already! if align: z_streams = align_design(z_streams, shift_len=shift_len, reject=reject, multiplex=False, no_missed=False, plot=plot) if method == 'linear': fam_stacks[fam_id] = linstack(z_streams, normalize=normalize) elif method == 'PWS': fam_stacks[fam_id] = PWS_stack(z_streams, normalize=normalize) if plot: # Plot up the stacks of the Families first for id, fam_stack in fam_stacks.items(): fam_stack.plot(equal_scale=False) if outdir: if not os.path.isdir(outdir): os.mkdir(outdir) for id, fam_stack in fam_stacks.items(): filename = '{}/Family_{}_stack.mseed'.format( outdir, str(id).split('/')[-1]) fam_stack.write(filename, format='MSEED') return fam_stacks
def temp_det_dict_shifts(cat, temp_cat, det_dir, ccs_thresh, shift_len, plot=False): """ Function to create a dictionary of {temp_id: {...relevant info...}} including shift information :param cat: catalog of detections :param temp_cat: catalog of templates :param det_dir: directory of detection waveforms :param ccs_thresh: cc threshold for alignment :param shift_len: allowed shift for alignment (sec) :param plot: plot bool :return: template dictionary """ # Make convenience dict of {temp_id: index} for use in creating template_dict ind_dict = {} for i, ev in enumerate(cat): ind_dict[ev.resource_id] = i temp_files = glob(det_dir) template_dict = {} for filename in temp_files: temp_rid = ResourceIdentifier('smi:org.gfz-potsdam.de/geofon/' + filename.split('/')[-1].split('_')[0]) det_rid = ResourceIdentifier('smi:local/' + filename.split('/')[-1].rstrip('.mseed')) if det_rid in ind_dict: if temp_rid not in template_dict and str(det_rid).split( '/')[-1].split('_')[-1] == 'self': template_dict[temp_rid] = { det_rid: { 'stream': read(filename), 'shifts': {}, 'ind': ind_dict[det_rid], 'align_stream': read(filename) }, 'temp_mag': [ ev.preferred_magnitude().mag for ev in temp_cat if ev.resource_id == temp_rid ][0], 'temp_ind': ind_dict[det_rid] } elif temp_rid not in template_dict: template_dict[temp_rid] = { det_rid: { 'stream': read(filename), 'shifts': {}, 'ind': ind_dict[det_rid], 'align_stream': read(filename) }, 'temp_mag': None } elif str(det_rid).split('/')[-1].split('_')[-1] == 'self': template_dict[temp_rid][det_rid] = { 'stream': read(filename), 'shifts': {}, 'ind': ind_dict[det_rid], 'align_stream': read(filename) } template_dict[temp_rid]['temp_mag'] = [ ev.preferred_magnitude().mag for ev in temp_cat if ev.resource_id == temp_rid ][0] template_dict[temp_rid]['temp_ind'] = ind_dict[det_rid] else: template_dict[temp_rid][det_rid] = { 'stream': read(filename), 'shifts': {}, 'ind': ind_dict[det_rid], 'align_stream': read(filename) } # Trim the waveforms to shorter lengths # Templates from /2015_det2cats/* are 3 sec pre-pick and 7 sec post-pick for tid, det_dict in template_dict.iteritems(): for evid, ev_dict in det_dict.iteritems(): if evid != 'temp_mag' and evid != 'temp_ind': for tr in ev_dict['stream']: tr.trim(starttime=tr.stats.starttime + 2.7, endtime=tr.stats.endtime - 5) for tr in ev_dict['align_stream']: tr.trim(starttime=tr.stats.starttime + 2.9, endtime=tr.stats.endtime - 6) # Variable of random keys for plotting samp_ids = [ id for i, id in enumerate(template_dict.keys()) if i in np.random.choice( range(len(template_dict)), len(template_dict) // 20, replace=False) ] # Now shift and save shift value for tid, det_dict in template_dict.iteritems(): design_set = [] design_inds = [] print('Shifting waveforms for template %s' % str(tid)) if plot: if tid in samp_ids: plotvar = True else: plotvar = False else: plotvar = False for eid, ev_dict in det_dict.iteritems(): if eid != 'temp_mag' and eid != 'temp_ind': design_set.append(ev_dict['align_stream']) design_inds.append(ev_dict['ind']) aligned_streams = subspace.align_design(design_set, reject=ccs_thresh, multiplex=False, shift_len=shift_len, plot=plotvar) det_dict['aligned'] = aligned_streams det_dict['aligned_inds'] = design_inds return template_dict