Esempio n. 1
0
	def applyFilter(self, event):
		#should we write filtered data for individual seismograms
		self.opts.filterParameters['apply'] = True

		# replot filtered stuff
		self.axstk.clear()
		self.ppm.axpp.clear()
		self.axs['Fron'].clear()
		self.axs['Prev'].clear()
		self.axs['Next'].clear()
		self.axs['Last'].clear()
		self.axs['Zoba'].clear()
		self.axs['Shdo'].clear()
		self.axs['Shfp'].clear()
		self.axs['Shod'].clear()
		self.axs['Quit'].clear()

		self.ppm = PickPhaseMenu(self.gsac, self.opts, self.axs)

		# make the legend box invisible
		if self.opts.pick_on:
			self.ppm.axpp.get_legend().set_visible(False)
		self.plotStack()

		# redraw figures
		self.ppm.axpp.figure.canvas.draw()
		self.axstk.figure.canvas.draw()

		# disconnect
		self.bnorder.disconnect(self.cidorder)
		self.bnunapply.disconnect(self.cidunapply)
		self.bnband.disconnect(self.cidband)
		self.filterAxs['amVfreq'].figure.canvas.mpl_disconnect(self.cidSelectFreq)

		close()
Esempio n. 2
0
	def initPlot(self):
		""" Plot waveforms """
		gsac = self.gsac
		opts = self.opts
		sortSeis(gsac, opts)
		self.ppm = PickPhaseMenu(gsac, opts, self.axs)
		# make the legend box invisible
		if self.opts.pick_on:
			self.ppm.axpp.get_legend().set_visible(False)
Esempio n. 3
0
class PickPhaseMenuMore:
	""" Pick phase for multiple seismograms and array stack
		Button: Sync
	"""
	def __init__(self, gsac, opts, axs):
		self.gsac = gsac
		self.opts = opts
		self.axs = axs
		self.axstk = self.axs['Fstk']
		if not 'stkdh' in gsac.__dict__:
			if opts.filemode == 'sac' and os.path.isfile(opts.fstack):
				gsac.stkdh = SacDataHdrs(opts.fstack, opts.delta)
			else:
				hdrini, hdrmed, hdrfin = opts.qcpara.ichdrs
				self.cchdrs = [hdrini, hdrmed]
				self.twcorr = opts.ccpara.twcorr
				# check data coverage
				opts.ipick = hdrini
				opts.twcorr = opts.ccpara.twcorr
				checkCoverage(gsac, opts) 
				gsac.selist = gsac.saclist
				self.ccStack()
		self.initPlot()
		self.plotStack()
		self.addEarthquakeInfo()
		self.setLabels()
		self.connect()

	def initPlot(self):
		""" Plot waveforms """
		gsac = self.gsac
		opts = self.opts
		sortSeis(gsac, opts)
		self.ppm = PickPhaseMenu(gsac, opts, self.axs)
		# make the legend box invisible
		if self.opts.pick_on:
			self.ppm.axpp.get_legend().set_visible(False)

	def addEarthquakeInfo(self):
		""" Set Earthquake Info
		  * Magnitude
		  * Location (Lat and Long)
		  * Depth
		"""
		gsac = self.gsac

		# get required parameters
		locationLat = round(gsac.event[6],2)
		locationLon = round(gsac.event[7],2)
		depth = round(gsac.event[8],2)
		magnitude = round(gsac.event[9],2)
		all_gcarc = []
		[all_gcarc.append(hdr.gcarc) for hdr in gsac.selist ]
		avg_gcarc = round(np.mean(all_gcarc),2)

		infoaxis = self.axs['Info']

		# remove axes markings
		infoaxis.axes.get_xaxis().set_ticks([])
		infoaxis.axes.get_yaxis().set_visible(False)

		# write the info into the axis plot
		infoaxis.text(0.1,0.85,'Magnitude: '+str(magnitude))
		infoaxis.text(0.1,0.65,'Lat: '+str(locationLat))
		infoaxis.text(0.1,0.45,'Lon: '+str(locationLon))
		infoaxis.text(0.1,0.25,'Depth: '+str(depth))
		infoaxis.text(0.1,0.05,'Gcarc: '+str(avg_gcarc))

	def setLabels(self):
		""" Set plot attributes """
		self.ppm.axpp.set_title('Seismograms')
		if self.opts.filemode == 'pkl':
			axstk = self.axstk
			trans = transforms.blended_transform_factory(axstk.transAxes, axstk.transAxes)
			axstk.text(1,1.01,self.opts.pklfile,transform=trans, va='bottom', ha='right',color='k')
		axpp = self.ppm.axpp
		trans = transforms.blended_transform_factory(axpp.transAxes, axpp.transData)
		font = FontProperties()
		font.set_family('monospace')
		axpp.text(1.025, 0, ' '*8+'qual= CCC/SNR/COH', transform=trans, va='center', 
			color='k', fontproperties=font)

	def plotStack(self):
		""" Plot array stack and span """
		colorwave = self.opts.pppara.colorwave
		stkybase = 0

		ppstk = PickPhase(self.gsac.stkdh, self.opts, self.axstk, stkybase, colorwave, 1) 

		ppstk.plotPicks()
		ppstk.disconnectPick()
		self.ppstk = ppstk
		self.axstk.set_title('Array Stack')
		self.ppstk.stalabel.set_visible(False)
		if self.opts.ynorm == 1.0:
			self.axstk.set_ylim(stkybase-0.5, stkybase+0.5)
		self.axstk.set_yticks([stkybase])
		self.axstk.set_yticklabels([])
		self.axstk.axvline(x=0, color='k', ls=':')
		# plot legend
		pppara = self.opts.pppara
		pickLegend(self.axstk, pppara.npick, pppara.pickcolors, pppara.pickstyles, False)
		self.plotSpan()

	def plotSpan(self):
		""" Span for array stack """
		axstk = self.axstk
		self.xzoom = [axstk.get_xlim(),]
		def on_select(xmin, xmax):
			""" Mouse event: select span. """
			if self.span.visible:
				print 'span selected: %6.1f %6.1f ' % (xmin, xmax)
				xxlim = (xmin, xmax)
				axstk.set_xlim(xxlim)
				self.xzoom.append(xxlim)
				if self.opts.upylim_on:
					print ('upylim')
					ppstk.updateY(xxlim)
				axstk.figure.canvas.draw()
		pppara = self.opts.pppara
		a, col = pppara.alphatwsele, pppara.colortwsele
		mspan = pppara.minspan * self.opts.delta
		self.span = TimeSelector(axstk, on_select, 'horizontal', minspan=mspan, useblit=False,
			rectprops=dict(alpha=a, facecolor=col))

		#self.replot()
		#self.ppm.axpp.figure.canvas.draw()

	# -------------------------------- SORTING ---------------------------------- #

	# Sort seismograms by 
	#    --------------
	# * | file indices |
	#    --------------
	#                   ----- ----- ----- -----
	# * quality factor | all | ccc | snr | coh |
	#                   ----- ----- ----- -----
	#                 ---- ----- ------
	# * given header | az | baz | dist | ...
	#                 ---- ----- ------
	
	def sorting(self, event):
		""" Sort the seismograms in particular order """
		self.getSortAxes()
		self.summarize_sort()
		self.sort_connect()
		show()

	def getSortAxes(self):
		figsort = figure('SortSeismograms',figsize=(15, 12))

		x0 = 0.05
		xx = 0.10
		yy = 0.04
		xm = 0.02
		dy = 0.15
		dx = 0.12
		y0 = 0.90

		"""Allocating size of buttons"""
		# file indices (filenames)
		rectfile = [x0, y0-dy*1, xx, yy]
		# quality
		rectqall = [x0+dx*0, y0-2*dy, xx, yy]
		rectqccc = [x0+dx*1, y0-2*dy, xx, yy]
		rectqsnr = [x0+dx*2, y0-2*dy, xx, yy]
		rectqcoh = [x0+dx*3, y0-2*dy, xx, yy]
		# headers
		recthnpts = [x0+dx*0, y0-3*dy, xx, yy]
		recthb = [x0+dx*1, y0-3*dy, xx, yy]
		recthe = [x0+dx*2, y0-3*dy, xx, yy]
		recthdelta = [x0+dx*3, y0-3*dy, xx, yy]
		recthstla = [x0+dx*0, y0-3.5*dy, xx, yy]
		recthstlo = [x0+dx*1, y0-3.5*dy, xx, yy]
		recthdist = [x0+dx*2, y0-3.5*dy, xx, yy]
		recthaz = [x0+dx*3, y0-3.5*dy, xx, yy]
		recthbaz = [x0+dx*0, y0-4*dy, xx, yy]
		recthgcarc = [x0+dx*1, y0-4*dy, xx, yy]
		# quit
		rectquit = [0.2, y0-5*dy, 0.2, yy]

		"""writing buttons to axis"""
		sortAxs = {}
		figsort.text(0.1,y0-dy*0.5,'Sort by file Index Name: ')
		sortAxs['file'] = figsort.add_axes(rectfile)
		figsort.text(0.1,y0-dy*1.5,'Sort by Quality: ')
		sortAxs['qall'] = figsort.add_axes(rectqall)
		sortAxs['qccc'] = figsort.add_axes(rectqccc)
		sortAxs['qsnr'] = figsort.add_axes(rectqsnr)
		sortAxs['qcoh'] = figsort.add_axes(rectqcoh)
		figsort.text(0.1,y0-dy*2.5,'Sort by Header: ')
		sortAxs['hnpts'] = figsort.add_axes(recthnpts)
		sortAxs['hb'] = figsort.add_axes(recthb)
		sortAxs['he'] = figsort.add_axes(recthe)
		sortAxs['hdelta'] = figsort.add_axes(recthdelta)
		sortAxs['hstla'] = figsort.add_axes(recthstla)
		sortAxs['hstlo'] = figsort.add_axes(recthstlo)
		sortAxs['hdist'] = figsort.add_axes(recthdist)
		sortAxs['haz'] = figsort.add_axes(recthaz)
		sortAxs['hbaz'] = figsort.add_axes(recthbaz)
		sortAxs['hgcarc'] = figsort.add_axes(recthgcarc)
		sortAxs['quit'] = figsort.add_axes(rectquit)

		""" size of text summary box """
		rectsumm = [0.55, 0.05, 0.40, 0.90]
		sortAxs['summary'] = figsort.add_axes(rectsumm)
		# remove axes markings on summary field
		sortAxs['summary'].get_xaxis().set_ticks([])
		sortAxs['summary'].get_yaxis().set_visible([])

		self.sortAxs = sortAxs
		self.figsort = figsort

	def summarize_sort(self):
		sortAxs = self.sortAxs

		# define constants
		x0 = 0.03
		x1 = 0.20
		y0 = 0.95
		dy = 0.03

		# explain what the summaries are
		sortAxs['summary'].text(x0,y0-dy*0,'FILENAMES')
		sortAxs['summary'].text(x0,y0-dy*1,'File: ')
		sortAxs['summary'].text(x1,y0-dy*1,'Sort in alphabetical order by filename')

		sortAxs['summary'].text(x0,y0-dy*3,'QUALITY:')
		sortAxs['summary'].text(x0,y0-dy*4,'All: ')
		sortAxs['summary'].text(x1,y0-dy*4,'Weighted Ratio of all quality measures')
		sortAxs['summary'].text(x0,y0-dy*5,'CCC: ')
		sortAxs['summary'].text(x1,y0-dy*5,'Cross-coefficient Coefficient')
		sortAxs['summary'].text(x0,y0-dy*6,'SNR: ')
		sortAxs['summary'].text(x1,y0-dy*6,'Signal-to-noise Ratio')
		sortAxs['summary'].text(x0,y0-dy*7,'COH: ')
		sortAxs['summary'].text(x1,y0-dy*7,'time domain coherence')

		sortAxs['summary'].text(x0,y0-dy*9,'OTHER HEADERS:')
		sortAxs['summary'].text(x0,y0-dy*10,'NPTS: ')
		sortAxs['summary'].text(x1,y0-dy*10,'Number of points per data component')
		sortAxs['summary'].text(x0,y0-dy*11,'B: ')
		sortAxs['summary'].text(x1,y0-dy*11,'Beginning value of the independent variable')
		sortAxs['summary'].text(x0,y0-dy*12,'E: ')
		sortAxs['summary'].text(x1,y0-dy*12,'Ending value of the independent variable')
		sortAxs['summary'].text(x0,y0-dy*13,'Delta: ')
		sortAxs['summary'].text(x1,y0-dy*13,'Increment between evenly spaced samples')
		sortAxs['summary'].text(x0,y0-dy*14,'STLA: ')
		sortAxs['summary'].text(x1,y0-dy*14,'Station latitude (deg, north positive)')
		sortAxs['summary'].text(x0,y0-dy*15,'STLO: ')
		sortAxs['summary'].text(x1,y0-dy*15,'Station longitude (deg, east positive)')
		sortAxs['summary'].text(x0,y0-dy*16,'DIST: ')
		sortAxs['summary'].text(x1,y0-dy*16,'Station to event distance (km)')
		sortAxs['summary'].text(x0,y0-dy*17,'AZ: ')
		sortAxs['summary'].text(x1,y0-dy*17,'Event to station azimuth (deg)')
		sortAxs['summary'].text(x0,y0-dy*18,'BAZ: ')
		sortAxs['summary'].text(x1,y0-dy*18,'Station to event azimuth (deg)')
		sortAxs['summary'].text(x0,y0-dy*19,'GCARC: ')
		sortAxs['summary'].text(x1,y0-dy*19,'Station to event great circle arc length (deg)')

	""" Connect button events. """
	def sort_connect(self):
		"""write the position for the buttons into self"""
		self.axfile = self.sortAxs['file']
		self.axqall = self.sortAxs['qall']
		self.axqccc = self.sortAxs['qccc']
		self.axqsnr = self.sortAxs['qsnr']
		self.axqcoh = self.sortAxs['qcoh']
		self.axqcoh = self.sortAxs['qcoh']
		self.axhnpts = self.sortAxs['hnpts']
		self.axhb = self.sortAxs['hb']
		self.axhe = self.sortAxs['he']
		self.axhdelta = self.sortAxs['hdelta']
		self.axhstla = self.sortAxs['hstla']
		self.axhstlo = self.sortAxs['hstlo']
		self.axhdist = self.sortAxs['hdist']
		self.axhaz = self.sortAxs['haz']
		self.axhbaz = self.sortAxs['hbaz']
		self.axhgcarc = self.sortAxs['hgcarc']
		self.axquit = self.sortAxs['quit']

		"""add a button to the correct place as defined by the axes
		   Also label the buttons here, as seen in the GUI
		"""
		self.bnfile = Button(self.axfile, 'File')
		self.bnqall = Button(self.axqall, 'All')
		self.bnqccc = Button(self.axqccc, 'CCC')
		self.bnqsnr = Button(self.axqsnr, 'SNR')
		self.bnqcoh = Button(self.axqcoh, 'COH')
		self.bnhnpts = Button(self.axhnpts, 'NPTS')
		self.bnhb = Button(self.axhb, 'B')
		self.bnhe = Button(self.axhe, 'E')
		self.bnhdelta = Button(self.axhdelta, 'Delta')
		self.bnhstla = Button(self.axhstla, 'STLA')
		self.bnhstlo = Button(self.axhstlo, 'STLO')
		self.bnhdist = Button(self.axhdist, 'Dist')
		self.bnhaz = Button(self.axhaz, 'AZ')
		self.bnhbaz = Button(self.axhbaz, 'BAZ')
		self.bnhgcarc = Button(self.axhgcarc, 'GCARC')
		self.bnquit = Button(self.axquit, 'Waiting for User input')

		""" each button changes the way the seismograms are sorted """
		self.cidfile = self.bnfile.on_clicked(self.sort_file)
		self.cidqall = self.bnqall.on_clicked(self.sort_qall)
		self.cidqccc = self.bnqccc.on_clicked(self.sort_qccc)
		self.cidqsnr = self.bnqsnr.on_clicked(self.sort_qsnr)
		self.cidqcoh = self.bnqcoh.on_clicked(self.sort_qcoh)
		self.cidhnpts = self.bnhnpts.on_clicked(self.sort_hnpts)
		self.cidhb = self.bnhb.on_clicked(self.sort_hb)
		self.cidhe = self.bnhe.on_clicked(self.sort_he)
		self.cidhdelta = self.bnhdelta.on_clicked(self.sort_hdelta)
		self.cidhstla = self.bnhstla.on_clicked(self.sort_hstla)
		self.cidhstlo = self.bnhstlo.on_clicked(self.sort_hstlo)
		self.cidhdist = self.bnhdist.on_clicked(self.sort_hdist)
		self.cidhaz = self.bnhaz.on_clicked(self.sort_haz)
		self.cidhbaz = self.bnhbaz.on_clicked(self.sort_hbaz)
		self.cidhgcarc = self.bnhgcarc.on_clicked(self.sort_hgcarc)

		# dismiss window when done
		self.bnquit.on_clicked(self.dismiss_sort)

	def sort_disconnect(self):
		self.bnfile.disconnect(self.cidfile)
		self.bnqall.disconnect(self.cidqall)
		self.bnqccc.disconnect(self.cidqccc)
		self.bnqsnr.disconnect(self.cidqsnr)
		self.bnqcoh.disconnect(self.cidqcoh)
		self.bnhnpts.disconnect(self.cidhnpts)
		self.bnhb.disconnect(self.cidhb)
		self.bnhe.disconnect(self.cidhe)
		self.bnhdelta.disconnect(self.cidhdelta)
		self.bnhstla.disconnect(self.cidhstla)
		self.bnhstlo.disconnect(self.cidhstlo)
		self.bnhdist.disconnect(self.cidhdist)
		self.bnhaz.disconnect(self.cidhaz)
		self.bnhbaz.disconnect(self.cidhbaz)
		self.bnhgcarc.disconnect(self.cidhgcarc)

	def sort_file(self, event):
		self.bnquit.label.set_text('Processing...')
		event.canvas.draw()

		self.opts.sortby = 'i';
		self.replot_seismograms()
		self.ppm.axpp.figure.canvas.draw()

		self.bnquit.label.set_text('Done! Click to Exit.')
		event.canvas.draw()
		return

	def sort_qall(self, event):
		self.bnquit.label.set_text('Processing...')
		event.canvas.draw()

		self.opts.sortby = 'all';
		self.replot_seismograms()
		self.ppm.axpp.figure.canvas.draw()

		self.bnquit.label.set_text('Done! Click to Exit.')
		event.canvas.draw()
		return

	def sort_qccc(self, event):
		self.bnquit.label.set_text('Processing...')
		event.canvas.draw()

		self.opts.sortby = '1';
		self.replot_seismograms()
		self.ppm.axpp.figure.canvas.draw()

		self.bnquit.label.set_text('Done! Click to Exit.')
		event.canvas.draw()
		return

	def sort_qsnr(self, event):
		self.bnquit.label.set_text('Processing...')
		event.canvas.draw()

		self.opts.sortby = '2';
		self.replot_seismograms()
		self.ppm.axpp.figure.canvas.draw()

		self.bnquit.label.set_text('Done! Click to Exit.')
		event.canvas.draw()
		return

	def sort_qcoh(self, event):
		self.bnquit.label.set_text('Processing...')
		event.canvas.draw()

		self.opts.sortby = '3';
		self.replot_seismograms()
		self.ppm.axpp.figure.canvas.draw()

		self.bnquit.label.set_text('Done! Click to Exit.')
		event.canvas.draw()
		return

	def sort_hnpts(self, event):
		self.bnquit.label.set_text('Processing...')
		event.canvas.draw()

		self.opts.sortby = 'npts';
		self.replot_seismograms()
		self.ppm.axpp.figure.canvas.draw()

		self.bnquit.label.set_text('Done! Click to Exit.')
		event.canvas.draw()
		return

	def sort_hb(self, event):
		self.bnquit.label.set_text('Processing...')
		event.canvas.draw()

		self.opts.sortby = 'b';
		self.replot_seismograms()
		self.ppm.axpp.figure.canvas.draw()

		self.bnquit.label.set_text('Done! Click to Exit.')
		event.canvas.draw()
		return

	def sort_he(self, event):
		self.bnquit.label.set_text('Processing...')
		event.canvas.draw()

		self.opts.sortby = 'e';
		self.replot_seismograms()
		self.ppm.axpp.figure.canvas.draw()

		self.bnquit.label.set_text('Done! Click to Exit.')
		event.canvas.draw()
		return

	def sort_hdelta(self, event):
		self.bnquit.label.set_text('Processing...')
		event.canvas.draw()

		self.opts.sortby = 'delta';
		self.replot_seismograms()
		self.ppm.axpp.figure.canvas.draw()

		self.bnquit.label.set_text('Done! Click to Exit.')
		event.canvas.draw()
		return

	def sort_hkstnm(self, event):
		self.bnquit.label.set_text('Processing...')
		event.canvas.draw()

		self.opts.sortby = 'kstnm';
		self.replot_seismograms()
		self.ppm.axpp.figure.canvas.draw()

		self.bnquit.label.set_text('Done! Click to Exit.')
		event.canvas.draw()
		return

	def sort_hstla(self, event):
		self.bnquit.label.set_text('Processing...')
		event.canvas.draw()

		self.opts.sortby = 'stla';
		self.replot_seismograms()
		self.ppm.axpp.figure.canvas.draw()

		self.bnquit.label.set_text('Done! Click to Exit.')
		event.canvas.draw()
		return

	def sort_hstlo(self, event):
		self.bnquit.label.set_text('Processing...')
		event.canvas.draw()

		self.opts.sortby = 'stlo';
		self.replot_seismograms()
		self.ppm.axpp.figure.canvas.draw()

		self.bnquit.label.set_text('Done! Click to Exit.')
		event.canvas.draw()
		return

	def sort_hdist(self, event):
		self.bnquit.label.set_text('Processing...')
		event.canvas.draw()

		self.opts.sortby = 'dist';
		self.replot_seismograms()
		self.ppm.axpp.figure.canvas.draw()

		self.bnquit.label.set_text('Done! Click to Exit.')
		event.canvas.draw()
		return

	def sort_haz(self, event):
		self.bnquit.label.set_text('Processing...')
		event.canvas.draw()

		self.opts.sortby = 'az';
		self.replot_seismograms()
		self.ppm.axpp.figure.canvas.draw()

		self.bnquit.label.set_text('Done! Click to Exit.')
		event.canvas.draw()
		return

	def sort_hbaz(self, event):
		self.bnquit.label.set_text('Processing...')
		event.canvas.draw()

		self.opts.sortby = 'baz';
		self.replot_seismograms()
		self.ppm.axpp.figure.canvas.draw()

		self.bnquit.label.set_text('Done! Click to Exit.')
		event.canvas.draw()
		return

	def sort_hgcarc(self, event):
		self.bnquit.label.set_text('Processing...')
		event.canvas.draw()

		self.opts.sortby = 'gcarc';
		self.replot_seismograms()
		self.ppm.axpp.figure.canvas.draw()

		self.bnquit.label.set_text('Done! Click to Exit.')
		event.canvas.draw()
		return

	def dismiss_sort(self, event):
		"""Dismiss the sorting selection popup Window"""
		self.sort_disconnect()
		close()

	# -------------------------------- SORTING ---------------------------------- #

	# --------------------------------- Filtering ------------------------------- #
	# Implement Butterworth filter
	#

	def filtering(self,event):
		filterAxes = self.getFilterAxes()
		self.spreadButter()
		self.filter_connect()
		show()

	def filter_connect(self):
		# user to change default parameters
		self.cidSelectFreq = self.filterAxs['amVfreq'].get_figure().canvas.mpl_connect('button_press_event', self.getBandpassFreq)

		# get order
		self.bnorder = RadioButtons(self.filterAxs['ordr'], (1,2,3,4), active=1)
		self.cidorder = self.bnorder.on_clicked(self.getButterOrder)

		# get type of filter to use
		self.bnband = RadioButtons(self.filterAxs['band'], ('bandpass','lowpass','highpass'))
		self.cidband = self.bnband.on_clicked(self.getBandtype)

		# get reverse pass option
		self.bnreversepass = RadioButtons(self.filterAxs['reversepass'], ('yes', 'no'), active=1)
		self.cidreversepass = self.bnreversepass.on_clicked(self.getReversePassOption)

		#add apply button. causes the filtered data to be applied 
		self.bnapply = Button(self.filterAxs['apply'], 'Apply')
		self.cidapply = self.bnapply.on_clicked(self.applyFilter)

		#add unapply button. causes the filtered data to be applied 
		self.bnunapply = Button(self.filterAxs['unapply'], 'Unapply')
		self.cidunapply = self.bnunapply.on_clicked(self.unapplyFilter)

	def getReversePassOption(self, event):
		if event == 'yes':
			self.opts.filterParameters['reversepass'] = True
		else:
			self.opts.filterParameters['reversepass'] = False
		self.spreadButter()

	def getBandtype(self, event):
		self.opts.filterParameters['band'] = event
		if event=='bandpass':
			self.filterAxs['amVfreq'].figure.canvas.mpl_disconnect(self.cidSelectFreq)
			# set defaults
			self.opts.filterParameters['lowFreq'] = 0.05
			self.opts.filterParameters['highFreq'] = 0.25
			self.opts.filterParameters['advance'] = False
			self.spreadButter()
			#execute
			self.cidSelectFreq = self.filterAxs['amVfreq'].get_figure().canvas.mpl_connect('button_press_event', self.getBandpassFreq)
		elif event=='lowpass':
			self.filterAxs['amVfreq'].figure.canvas.mpl_disconnect(self.cidSelectFreq)
			# set defaults
			self.opts.filterParameters['lowFreq'] = 0.05
			self.opts.filterParameters['highFreq'] = nan
			self.opts.filterParameters['advance'] = False
			self.spreadButter()
			#execute
			self.cidSelectFreq = self.filterAxs['amVfreq'].get_figure().canvas.mpl_connect('button_press_event', self.getLowFreq)
		elif event=='highpass':
			self.filterAxs['amVfreq'].figure.canvas.mpl_disconnect(self.cidSelectFreq)
			# set defaults
			self.opts.filterParameters['lowFreq'] = nan
			self.opts.filterParameters['highFreq'] = 0.25
			self.opts.filterParameters['advance'] = False
			self.spreadButter()
			#execute
			self.cidSelectFreq = self.filterAxs['amVfreq'].get_figure().canvas.mpl_connect('button_press_event', self.getHighFreq)

	def getLowFreq(self, event):
		if event.inaxes == self.filterAxs['amVfreq']:
			self.opts.filterParameters['lowFreq'] = event.xdata
			self.spreadButter()

	def getHighFreq(self, event):
		if event.inaxes == self.filterAxs['amVfreq']:
			self.opts.filterParameters['highFreq'] = event.xdata
			self.spreadButter()

	def getButterOrder(self, event):
		self.opts.filterParameters['order'] = int(event)
		self.spreadButter()

	def getBandpassFreq(self,event):
		if event.inaxes == self.filterAxs['amVfreq']:
			if self.opts.filterParameters['advance']: # low and high frequencies recorded
				self.opts.filterParameters['highFreq'] = event.xdata
				if self.opts.filterParameters['lowFreq']<self.opts.filterParameters['highFreq']:
					self.opts.filterParameters['advance'] = False
					self.spreadButter()
				else:
					print 'Value chose must be higher than lower frequency of %f' % self.opts.filterParameters['lowFreq']
			else:
				self.opts.filterParameters['lowFreq'] = event.xdata
				self.opts.filterParameters['advance'] = True

	def modifyFilterTextLabels(self):
		self.filterAxs['Info'].clear()
		self.filterAxs['Info'].text(0.1,0.7,'Low Freq: '+str(self.opts.filterParameters['lowFreq']))
		self.filterAxs['Info'].text(0.1,0.4,'High Freq: '+str(self.opts.filterParameters['highFreq']))
		self.filterAxs['Info'].text(0.1,0.1,'Order: '+str(self.opts.filterParameters['order']))

	"""Apply the butterworth filter to the data """
	def spreadButter(self):
		# clear axes
		self.filterAxs['amVtime'].clear()
		self.filterAxs['amVfreq'].clear()

		#set axes limit
		self.filterAxs['amVtime'].set_xlim(-30,30)
		self.filterAxs['amVfreq'].set_xlim(0,1.50)

		self.modifyFilterTextLabels()

		originalTime = self.ppstk.time - self.ppstk.sacdh.reftime
		originalSignalTime = self.ppstk.sacdh.data

		originalFreq, originalSignalFreq = ftr.time_to_freq(originalTime, originalSignalTime, self.opts.delta)
		filteredSignalTime, filteredSignalFreq, adjusted_w, adjusted_h = ftr.filtering_time_freq(originalTime, originalSignalTime, self.opts.delta, self.opts.filterParameters['band'], self.opts.filterParameters['highFreq'], self.opts.filterParameters['lowFreq'], self.opts.filterParameters['order'], self.opts.filterParameters['reversepass'])

		# PLOT TIME
		self.filterAxs['amVtime'].plot(originalTime, originalSignalTime, label='Original')
		self.filterAxs['amVtime'].plot(originalTime, filteredSignalTime, label='Filtered')
		self.filterAxs['amVtime'].legend(loc="upper right")
		self.filterAxs['amVtime'].set_title('Signal vs Time')
		self.filterAxs['amVtime'].set_xlabel('Time (s)', fontsize = 12)
		self.filterAxs['amVtime'].set_ylabel('Signal', fontsize = 12)

		# PLOT FREQUENCY
		self.filterAxs['amVfreq'].plot(originalFreq, np.abs(originalSignalFreq), label='Original')
		self.filterAxs['amVfreq'].plot(originalFreq, np.abs(filteredSignalFreq), label='Filtered')
		self.filterAxs['amVfreq'].plot(adjusted_w, adjusted_h, label='Butterworth Filter')
		self.filterAxs['amVfreq'].legend(loc="upper right")
		self.filterAxs['amVfreq'].set_title('Amplitude vs frequency')
		self.filterAxs['amVfreq'].set_xlabel('Frequency (Hz)', fontsize = 12)
		self.filterAxs['amVfreq'].set_ylabel('Amplitude Signal', fontsize = 12)

		# redraw the plots on the popup window
		self.figfilter.canvas.draw()

	def applyFilter(self, event):
		#should we write filtered data for individual seismograms
		self.opts.filterParameters['apply'] = True

		# replot filtered stuff
		self.axstk.clear()
		self.ppm.axpp.clear()
		self.axs['Fron'].clear()
		self.axs['Prev'].clear()
		self.axs['Next'].clear()
		self.axs['Last'].clear()
		self.axs['Zoba'].clear()
		self.axs['Shdo'].clear()
		self.axs['Shfp'].clear()
		self.axs['Shod'].clear()
		self.axs['Quit'].clear()

		self.ppm = PickPhaseMenu(self.gsac, self.opts, self.axs)

		# make the legend box invisible
		if self.opts.pick_on:
			self.ppm.axpp.get_legend().set_visible(False)
		self.plotStack()

		# redraw figures
		self.ppm.axpp.figure.canvas.draw()
		self.axstk.figure.canvas.draw()

		# disconnect
		self.bnorder.disconnect(self.cidorder)
		self.bnunapply.disconnect(self.cidunapply)
		self.bnband.disconnect(self.cidband)
		self.filterAxs['amVfreq'].figure.canvas.mpl_disconnect(self.cidSelectFreq)

		close()

	def unapplyFilter(self, event):
		# do not write filtered data for individual seismograms
		self.opts.filterParameters['apply'] = False

		#reset back to original defaults
		self.opts.filterParameters['band'] = 'bandpass'
		self.opts.filterParameters['lowFreq'] = 0.05
		self.opts.filterParameters['highFreq'] = 0.25
		self.opts.filterParameters['order'] = 2

		# replot filtered stuff
		self.axstk.clear()
		self.ppm.axpp.clear()
		self.axs['Fron'].clear()
		self.axs['Prev'].clear()
		self.axs['Next'].clear()
		self.axs['Last'].clear()
		self.axs['Zoba'].clear()
		self.axs['Shdo'].clear()
		self.axs['Shfp'].clear()
		self.axs['Shod'].clear()
		self.axs['Quit'].clear()
		self.initPlot()
		self.plotStack()

		# redraw figures
		self.ppm.axpp.figure.canvas.draw()
		self.axstk.figure.canvas.draw()

		# disconnect
		self.bnorder.disconnect(self.cidorder)
		self.bnapply.disconnect(self.cidapply)
		self.bnband.disconnect(self.cidband)
		self.filterAxs['amVfreq'].figure.canvas.mpl_disconnect(self.cidSelectFreq)

		close()

	def getFilterAxes(self):
		figfilter = figure(figsize=(15, 12))
		self.figfilter = figfilter

		rect_amVtime = [0.10, 0.50, 0.80, 0.35]
		rect_amVfreq = [0.10, 0.07, 0.80, 0.35]
		rectinfo = [0.8, 0.86, 0.15, 0.10]
		rectordr = [0.3, 0.86, 0.10, 0.10]
		rectunapply = [0.42, 0.90, 0.07, 0.04]
		rectapply = [0.5, 0.90, 0.05, 0.04]
		rectband = [0.6, 0.86, 0.10, 0.10]
		rectreversepass = [0.72, 0.86, 0.07, 0.10]

		filterAxs = {}
		self.figfilter.text(0.03,0.95,'Butterworth Filter', {'weight':'bold', 'size':21})
		filterAxs['amVtime'] = figfilter.add_axes(rect_amVtime) 
		filterAxs['amVfreq'] = figfilter.add_axes(rect_amVfreq) 
		filterAxs['ordr'] = figfilter.add_axes(rectordr)
		filterAxs['unapply'] = figfilter.add_axes(rectunapply)
		filterAxs['apply'] = figfilter.add_axes(rectapply)
		filterAxs['band'] = figfilter.add_axes(rectband)
		filterAxs['reversepass'] = figfilter.add_axes(rectreversepass)

		self.figfilter.text(0.3, 0.97, 'Order:')
		self.figfilter.text(0.6, 0.97, 'Filter Type:')
		self.figfilter.text(0.72, 0.97, 'Run Reverse:')

		# frequencies used to compute butterworth filter displayed here
		filterAxs['Info'] = figfilter.add_axes(rectinfo)
		filterAxs['Info'].axes.get_xaxis().set_visible(False)
		filterAxs['Info'].axes.get_yaxis().set_visible(False)

		self.filterAxs = filterAxs

	# --------------------------------- Filtering ------------------------------- #

	def plot_stations(self, event):
		event_name = 'event'
		if hasattr(self.opts, 'pklfile'):
			event_name = self.opts.pklfile
		PlotStations(event_name, self.gsac)

	def on_zoom(self, event):
		""" Zoom back to previous xlim when event is in event.inaxes.
		"""
		evkey = event.key
		axstk = self.axstk
		if not axstk.contains(event)[0] or evkey is None: return
		xzoom = self.xzoom
		if evkey.lower() == 'z' and len(xzoom) > 1:
			del xzoom[-1]
			axstk.set_xlim(xzoom[-1])
			print 'Zoom back to: %6.1f %6.1f ' % tuple(xzoom[-1])
			if self.opts.upylim_on:
				for pp in self.pps:
					del pp.ynorm[-1]
					setp(pp.lines[0], ydata=pp.ybase+pp.sacdh.data*pp.ynorm[-1])
			axstk.figure.canvas.draw()

	def replot_seismograms(self):
		""" Replot seismograms and array stack after running iccs.
		"""
		sortSeis(self.gsac, self.opts)
		self.ppm.initIndex()
		self.ppm.replot(0)
		self.setLabels()

	def replot(self):
		""" Replot seismograms and array stack after running iccs.
		"""
		self.ppstk.disconnect()
		self.ppstk.axpp.cla()
		self.plotStack()
		sortSeis(self.gsac, self.opts)
		self.ppm.initIndex()
		self.ppm.replot(0)
		self.setLabels()

	def connect(self):
		""" Connect button events. """
		# write the position for the buttons into self
		self.axccim = self.axs['CCIM']
		self.axccff = self.axs['CCFF']
		self.axsync = self.axs['Sync']
		self.axmccc = self.axs['MCCC']
		self.axsac2 = self.axs['SAC2']
		self.axsort = self.axs['Sort']
		self.axfilter = self.axs['Filter']
		self.axplotsta = self.axs['plotsta']

		# name the buttons
		self.bnccim = Button(self.axccim, 'Align')
		self.bnccff = Button(self.axccff, 'Refine')
		self.bnsync = Button(self.axsync, 'Sync')
		self.bnmccc = Button(self.axmccc, 'Finalize')
		self.bnsac2 = Button(self.axsac2, 'SAC P2')
		self.bnsort = Button(self.axsort, 'Sort')
		self.bnfilter = Button(self.axfilter, 'Filter')
		self.bnplotsta = Button(self.axplotsta, 'Map of\n stations')

		self.cidccim = self.bnccim.on_clicked(self.ccim)
		self.cidccff = self.bnccff.on_clicked(self.ccff)
		self.cidsync = self.bnsync.on_clicked(self.sync)
		self.cidmccc = self.bnmccc.on_clicked(self.mccc)
		self.cidsac2 = self.bnsac2.on_clicked(self.plot2)

		self.cidsort = self.bnsort.on_clicked(self.sorting)
		self.cidfilter = self.bnfilter.on_clicked(self.filtering)
		self.cidplotsta = self.bnplotsta.on_clicked(self.plot_stations)

		self.cidpress = self.axstk.figure.canvas.mpl_connect('key_press_event', self.on_zoom)

	def disconnect(self):
		""" Disconnect button events. """
		self.bnccim.disconnect(self.cidccim)
		self.bnccff.disconnect(self.cidccff)
		self.bnsync.disconnect(self.cidsync)
		self.bnmccc.disconnect(self.cidmccc)
		self.bnsac2.disconnect(self.cidsac2)
		self.bnsort.disconnect(self.cidsort)
		self.bnfilter.disconnect(self.cidfilter)

		self.axccim.cla()
		self.axccff.cla()
		self.axsync.cla()
		self.axmccc.cla()
		self.axsac2.cla()
		self.axsort.cla()
		self.axfilter.cla()

	def syncPick(self):
		""" Sync final time pick hdrfin from array stack to all traces. 
		"""
		self.getPicks()
		tshift = self.tfin - self.tmed
		hdrini, hdrmed, hdrfin = self.opts.qcpara.ichdrs
		for sacdh in self.gsac.saclist:
			tfin = sacdh.gethdr(hdrmed) + tshift
			sacdh.sethdr(hdrfin, tfin)

	def syncWind(self):
		""" Sync time window relative to hdrfin from array stack to all traces. 
			Times saved to twhdrs are alway absolute.
		"""
		wh0, wh1 = self.opts.qcpara.twhdrs
		hdrini, hdrmed, hdrfin = self.opts.qcpara.ichdrs
		self.getWindow(hdrfin)
		twfin = self.twcorr
		for sacdh in self.gsac.saclist:
			tfin = sacdh.gethdr(hdrfin)
			th0 = tfin + twfin[0]
			th1 = tfin + twfin[1]
			sacdh.sethdr(wh0, th0)
			sacdh.sethdr(wh1, th1)
			
	def sync(self, event):
		""" Sync final time pick and time window from array stack to each trace and update current page.
		"""
		hdrini, hdrmed, hdrfin = self.opts.qcpara.ichdrs
		wh0, wh1 = self.opts.qcpara.twhdrs
		if self.ppstk.sacdh.gethdr(hdrfin) == -12345.:
			print '*** hfinal %s is not defined. Pick at array stack first! ***' % hdrfin
			return
		self.syncPick()
		self.syncWind()
		twfin = self.twcorr
		for pp in self.ppm.pps:
			sacdh = pp.sacdh
			tfin = sacdh.gethdr(hdrfin)
			ipk = int(hdrfin[1])
			tpk = tfin - sacdh.reftime
			pp.timepicks[ipk].set_xdata(tpk)
			th0 = tfin + twfin[0]
			th1 = tfin + twfin[1]
			pp.twindow = [th0, th1]
			pp.resetWindow()
		print '--> Sync final time picks and time window... You can now run CCFF to refine final picks.'
	
	def getWindow(self, hdr):
		""" Get time window twcorr (relative to hdr) from array stack, which is from last run. 
		"""
		ppstk = self.ppstk
		tw0, tw1 = ppstk.twindow
		t0 = ppstk.sacdh.gethdr(hdr)
		if t0 == -12345.:
			print ('Header {0:s} not defined'.format(hdr))
			return
		twcorr = [tw0-t0, tw1-t0]
		self.twcorr = twcorr

	def getPicks(self):
		""" Get time picks of stack
		"""
		hdrini, hdrmed, hdrfin = self.opts.qcpara.ichdrs
		self.tini = self.gsac.stkdh.gethdr(hdrini)
		self.tmed = self.gsac.stkdh.gethdr(hdrmed)
		self.tfin = self.gsac.stkdh.gethdr(hdrfin)

	def ccim(self, event):
		# running ICCS-A will erase everything you did. Make sure the user did not hit it by mistake
		shouldRun = tkMessageBox.askokcancel("Will Erase Work!","This will erase any picks past t1. \nAre you sure?")

		if shouldRun:
			""" Run iccs with time window from final stack. Time picks: hdrini, hdrmed.
			"""
			hdrini, hdrmed, hdrfin = self.opts.qcpara.ichdrs
			self.cchdrs = hdrini, hdrmed
			self.getWindow(self.cchdrs[0])
			self.ccStack()
			self.getPicks()
			self.replot()

	def ccff(self, event):
		""" Run iccs with time window from final stack. Time picks: hdrfin, hdrfin.
		"""
		hdrini, hdrmed, hdrfin = self.opts.qcpara.ichdrs

		if self.gsac.stkdh.gethdr(hdrfin) == -12345.:
			print '*** hfinal %s is not defined. Sync first! ***' % hdrfin
			return

		"""running ICCS-B will erase everything you did. Make sure the user did not hit it by mistake"""
		shouldRun = tkMessageBox.askokcancel("Will Erase Work!","This will erase any picks past t2 and will recalculate all t2 values. \nAre you sure?")
		
		if shouldRun:
			self.cchdrs = hdrfin, hdrfin
			self.getWindow(self.cchdrs[0])
			self.getPicks()
			self.ccStack()
			stkdh = self.gsac.stkdh
			stkdh.sethdr(hdrini, self.tini)
			stkdh.sethdr(hdrmed, self.tmed)
			self.replot()

	def ccStack(self):
		""" 
		Call iccs.ccWeightStack. 
		Change reference time pick to the input pick before ICCS and to the output pick afterwards.
		"""
		opts = self.opts
		ccpara = opts.ccpara
		opts.ccpara.twcorr = self.twcorr
		ccpara.cchdrs = self.cchdrs
		hdr0, hdr1 = int(ccpara.cchdrs[0][1]), int(ccpara.cchdrs[1][1])
		stkdh, stkdata, quas = ccWeightStack(self.gsac.selist, self.opts)
		stkdh.selected = True
		stkdh.sethdr(opts.qcpara.hdrsel, 'True    ')
		self.gsac.stkdh = stkdh
		if opts.reltime != hdr1:
			out = '\n--> change opts.reltime from %i to %i'
			print out % (opts.reltime, hdr1)
		opts.reltime = hdr1

	def mccc(self, event):
		""" Run mccc.py  """
		gsac = self.gsac
		mcpara = self.opts.mcpara
		rcfile = mcpara.rcfile
		ipick = mcpara.ipick
		wpick = mcpara.wpick
		self.getWindow(ipick)
		timewindow = self.twcorr
		tw = timewindow[1]-timewindow[0]
		taperwindow = taperWindow(timewindow, mcpara.taperwidth)
		mcpara.timewindow = timewindow
		mcpara.taperwindow = taperwindow
		evline, mcname = eventListName(gsac.event, mcpara.phase)
		mcpara.evline = evline
		mcpara.mcname = mcname
		mcpara.kevnm = gsac.kevnm
		solution, solist_LonLat, delay_times = mccc(gsac, mcpara)
		self.gsac.solist_LonLat = solist_LonLat
		self.gsac.delay_times = delay_times

		wpk = int(wpick[1])
		if self.opts.reltime != wpk:
			out = '\n--> change opts.reltime from %i to %i'
			print out % (self.opts.reltime, wpk)
		self.opts.reltime = wpk
		self.replot()

	def plot2(self, event):
		""" Plot P2 stack of seismograms for defined time picks (ichdrs + wpick).
		"""
		opts = copy.copy(self.opts)
		twin_on = opts.twin_on
		pick_on = opts.pick_on
		reltime = opts.reltime
		ynorm = opts.ynorm
		fill = opts.fill
		selist = self.gsac.selist

		tpicks = opts.qcpara.ichdrs + [opts.mcpara.wpick,]
		npick = len(tpicks)
		tlabs = 'ABCDE'

		fig2 = figure(figsize=(9,12))
		fig2.clf()
		subplots_adjust(bottom=.05, top=0.96, left=.1, right=.97, wspace=.5, hspace=.24)
		opts.twin_on = False
		opts.pick_on = False
		ax0 = fig2.add_subplot(npick,1,1)
		axsacs = [ ax0 ] + [ fig2.add_subplot(npick,1,i+1, sharex=ax0) for i in range(1, npick) ]
		for i in range(npick):
			opts.reltime = int(tpicks[i][1])
			ax = axsacs[i]
			sacp2(selist, opts, ax)
			tt = '(' + tlabs[i] + ')'
			trans = transforms.blended_transform_factory(ax.transAxes, ax.transAxes)
			ax.text(-.05, 1, tt, transform=trans, va='center', ha='right', size=16)	

		opts.ynorm = ynorm
		opts.twin_on = twin_on
		opts.pick_on = pick_on
		opts.reltime = reltime
		opts.fill = fill
		opts.zero_on = False

		show()
Esempio n. 4
0
class PickPhaseMenuMore:
	""" Pick phase for multiple seismograms and array stack
		Button: Sync
	"""
	def __init__(self, gsac, opts, axs):
		self.gsac = gsac
		self.opts = opts
		self.axs = axs
		self.axstk = self.axs['Fstk']
		if not 'stkdh' in gsac.__dict__:
			if opts.filemode == 'sac' and os.path.isfile(opts.fstack):
				gsac.stkdh = SacDataHdrs(opts.fstack, opts.delta)
			else:
				hdrini, hdrmed, hdrfin = opts.qcpara.ichdrs
				self.cchdrs = [hdrini, hdrmed]
				self.twcorr = opts.ccpara.twcorr
				# check data coverage
				opts.ipick = hdrini
				opts.twcorr = opts.ccpara.twcorr
				checkCoverage(gsac, opts) 
				gsac.selist = gsac.saclist
				self.ccStack()
		self.initPlot()
		self.plotStack()
		self.setLabels()
		self.connect()

	def initPlot(self):
		""" Plot waveforms """
		gsac = self.gsac
		opts = self.opts
		sortSeis(gsac, opts)
		self.ppm = PickPhaseMenu(gsac, opts, self.axs)
		# make the legend box invisible
		if self.opts.pick_on:
			self.ppm.axpp.get_legend().set_visible(False)

	def setLabels(self):
		""" Set plot attributes """
		self.ppm.axpp.set_title('Seismograms')
		if self.opts.filemode == 'pkl':
			axstk = self.axstk
			trans = transforms.blended_transform_factory(axstk.transAxes, axstk.transAxes)
			axstk.text(1,1.01,self.opts.pklfile,transform=trans, va='bottom', ha='right',color='k')
		axpp = self.ppm.axpp
		trans = transforms.blended_transform_factory(axpp.transAxes, axpp.transData)
		font = FontProperties()
		font.set_family('monospace')
		axpp.text(1.025, 0, ' '*8+'qual= CCC/SNR/COH', transform=trans, va='center', 
			color='k', fontproperties=font)

	def plotStack(self):
		""" Plot array stack and span """
		colorwave = self.opts.pppara.colorwave
		stkybase = 0
		ppstk = PickPhase(self.gsac.stkdh, self.opts,self.axstk, stkybase, colorwave, 1) 
		ppstk.plotPicks()
		ppstk.disconnectPick()
		self.ppstk = ppstk
		self.axstk.set_title('Array Stack')
		self.ppstk.stalabel.set_visible(False)
		if self.opts.ynorm == 1.0:
			self.axstk.set_ylim(stkybase-0.5, stkybase+0.5)
		self.axstk.set_yticks([stkybase])
		self.axstk.set_yticklabels([])
		self.axstk.axvline(x=0, color='k', ls=':')
		# plot legend
		pppara = self.opts.pppara
		pickLegend(self.axstk, pppara.npick, pppara.pickcolors, pppara.pickstyles, False)
		self.plotSpan()

	def plotSpan(self):
		""" Span for array stack """
		axstk = self.axstk
		self.xzoom = [axstk.get_xlim(),]
		def on_select(xmin, xmax):
			""" Mouse event: select span. """
			if self.span.visible:
				print 'span selected: %6.1f %6.1f ' % (xmin, xmax)
				xxlim = (xmin, xmax)
				axstk.set_xlim(xxlim)
				self.xzoom.append(xxlim)
				if self.opts.upylim_on:
					print ('upylim')
					ppstk.updateY(xxlim)
				axstk.figure.canvas.draw()
		pppara = self.opts.pppara
		a, col = pppara.alphatwsele, pppara.colortwsele
		mspan = pppara.minspan * self.opts.delta
		self.span = TimeSelector(axstk, on_select, 'horizontal', minspan=mspan, useblit=False,
			rectprops=dict(alpha=a, facecolor=col))

	def on_zoom(self, event):
		""" Zoom back to previous xlim when event is in event.inaxes.
		"""
		evkey = event.key
		axstk = self.axstk
		if not axstk.contains(event)[0] or evkey is None: return
		xzoom = self.xzoom
		if evkey.lower() == 'z' and len(xzoom) > 1:
			del xzoom[-1]
			axstk.set_xlim(xzoom[-1])
			print 'Zoom back to: %6.1f %6.1f ' % tuple(xzoom[-1])
			if self.opts.upylim_on:
				for pp in self.pps:
					del pp.ynorm[-1]
					setp(pp.lines[0], ydata=pp.ybase+pp.sacdh.data*pp.ynorm[-1])
			axstk.figure.canvas.draw()

	def replot(self):
		""" Replot seismograms and array stack after running iccs.
		"""
		self.ppstk.disconnect()
		self.ppstk.axpp.cla()
		self.plotStack()
		opts = self.opts
		sortSeis(self.gsac, self.opts)
		self.ppm.initIndex()
		self.ppm.replot(0)
		self.setLabels()

	def connect(self):
		""" Connect button events. """
		self.axccim = self.axs['CCIM']
		self.axccff = self.axs['CCFF']
		self.axsync = self.axs['Sync']
		self.axmccc = self.axs['MCCC']

		self.axsac2 = self.axs['SAC2']

		self.bnccim = Button(self.axccim, 'ICCS-A')
		self.bnccff = Button(self.axccff, 'ICCS-B')
		self.bnsync = Button(self.axsync, 'Sync')
		self.bnmccc = Button(self.axmccc, 'MCCC')

		self.bnsac2 = Button(self.axsac2, 'SAC P2')
		self.cidccim = self.bnccim.on_clicked(self.ccim)
		self.cidccff = self.bnccff.on_clicked(self.ccff)
		self.cidsync = self.bnsync.on_clicked(self.sync)
		self.cidmccc = self.bnmccc.on_clicked(self.mccc)

		self.cidsac2 = self.bnsac2.on_clicked(self.plot2)
		self.cidpress = self.axstk.figure.canvas.mpl_connect('key_press_event', self.on_zoom)

	def disconnect(self):
		""" Disconnect button events. """
		self.bnccim.disconnect(self.cidccim)
		self.bnccff.disconnect(self.cidccff)
		self.bnsync.disconnect(self.cidsync)
		self.bnmccc.disconnect(self.cidmccc)
		self.bnsac1.disconnect(self.cidsac1)
		self.bnsac2.disconnect(self.cidsac2)
		self.axccim.cla()
		self.axccff.cla()
		self.axsync.cla()
		self.axmccc.cla()
		self.axsac1.cla()
		self.axsac2.cla()

	def syncPick(self):
		""" Sync final time pick hdrfin from array stack to all traces. 
		"""
		self.getPicks()
		tshift = self.tfin - self.tmed
		hdrini, hdrmed, hdrfin = self.opts.qcpara.ichdrs
		for sacdh in self.gsac.saclist:
			tfin = sacdh.gethdr(hdrmed) + tshift
			sacdh.sethdr(hdrfin, tfin)

	def syncWind(self):
		""" Sync time window relative to hdrfin from array stack to all traces. 
			Times saved to twhdrs are alway absolute.
		"""
		wh0, wh1 = self.opts.qcpara.twhdrs
		hdrini, hdrmed, hdrfin = self.opts.qcpara.ichdrs
		self.getWindow(hdrfin)
		twfin = self.twcorr
		for sacdh in self.gsac.saclist:
			tfin = sacdh.gethdr(hdrfin)
			th0 = tfin + twfin[0]
			th1 = tfin + twfin[1]
			sacdh.sethdr(wh0, th0)
			sacdh.sethdr(wh1, th1)
			
	def sync(self, event):
		""" Sync final time pick and time window from array stack to each trace and update current page.
		"""
		hdrini, hdrmed, hdrfin = self.opts.qcpara.ichdrs
		wh0, wh1 = self.opts.qcpara.twhdrs
		if self.ppstk.sacdh.gethdr(hdrfin) == -12345.:
			print '*** hfinal %s is not defined. Pick at array stack first! ***' % hdrfin
			return
		self.syncPick()
		self.syncWind()
		twfin = self.twcorr
		for pp in self.ppm.pps:
			sacdh = pp.sacdh
			tfin = sacdh.gethdr(hdrfin)
			ipk = int(hdrfin[1])
			tpk = tfin - sacdh.reftime
			pp.timepicks[ipk].set_xdata(tpk)
			th0 = tfin + twfin[0]
			th1 = tfin + twfin[1]
			pp.twindow = [th0, th1]
			pp.resetWindow()
		print '--> Sync final time picks and time window... You can now run CCFF to refine final picks.'
	
	def getWindow(self, hdr):
		""" Get time window twcorr (relative to hdr) from array stack, which is from last run. 
		"""
		ppstk = self.ppstk
		tw0, tw1 = ppstk.twindow
		t0 = ppstk.sacdh.gethdr(hdr)
		if t0 == -12345.:
			print ('Header {0:s} not defined'.format(hdr))
			return
		twcorr = [tw0-t0, tw1-t0]
		self.twcorr = twcorr

	def getPicks(self):
		""" Get time picks of stack
		"""
		hdrini, hdrmed, hdrfin = self.opts.qcpara.ichdrs
		self.tini = self.gsac.stkdh.gethdr(hdrini)
		self.tmed = self.gsac.stkdh.gethdr(hdrmed)
		self.tfin = self.gsac.stkdh.gethdr(hdrfin)

	def ccim(self, event):
		# running ICCS-A will erase everything you did. Make sure the user did not hit it by mistake
	   	tkMessageBox.showwarning("Will Erase Work!","This will erase everything you manually selected. \nAre you sure?")

		""" Run iccs with time window from final stack. Time picks: hdrini, hdrmed.
		"""
		hdrini, hdrmed, hdrfin = self.opts.qcpara.ichdrs
		self.cchdrs = hdrini, hdrmed
		self.getWindow(self.cchdrs[0])
		self.ccStack()
		self.getPicks()
		self.replot()

	def ccff(self, event):
		""" Run iccs with time window from final stack. Time picks: hdrfin, hdrfin.
		"""
		hdrini, hdrmed, hdrfin = self.opts.qcpara.ichdrs
		if self.gsac.stkdh.gethdr(hdrfin) == -12345.:
			print '*** hfinal %s is not defined. Sync first! ***' % hdrfin
			return

		# running ICCS-B will erase everything you did. Make sure the user did not hit it by mistake
		tkMessageBox.showwarning("Will Erase Work!","This will erase everything you manually selected. \nAre you sure?")

		self.cchdrs = hdrfin, hdrfin
		self.getWindow(self.cchdrs[0])
		self.getPicks()
		self.ccStack()
		stkdh = self.gsac.stkdh
		stkdh.sethdr(hdrini, self.tini)
		stkdh.sethdr(hdrmed, self.tmed)
		self.replot()

	def ccStack(self):
		""" 
		Call iccs.ccWeightStack. 
		Change reference time pick to the input pick before ICCS and to the output pick afterwards.
		"""
		opts = self.opts
		ccpara = opts.ccpara
		opts.ccpara.twcorr = self.twcorr
		ccpara.cchdrs = self.cchdrs
		hdr0, hdr1 = int(ccpara.cchdrs[0][1]), int(ccpara.cchdrs[1][1])
		stkdh, stkdata, quas = ccWeightStack(self.gsac.selist, self.opts)
		stkdh.selected = True
		stkdh.sethdr(opts.qcpara.hdrsel, 'True    ')
		self.gsac.stkdh = stkdh
		if opts.reltime != hdr1:
			out = '\n--> change opts.reltime from %i to %i'
			print out % (opts.reltime, hdr1)
		opts.reltime = hdr1

	def mccc(self, event):
		""" Run mccc.py  """
		gsac = self.gsac
		mcpara = self.opts.mcpara
		rcfile = mcpara.rcfile
		ipick = mcpara.ipick
		wpick = mcpara.wpick
		self.getWindow(ipick)
		timewindow = self.twcorr
		tw = timewindow[1]-timewindow[0]
		taperwindow = taperWindow(timewindow, mcpara.taperwidth)
		mcpara.timewindow = timewindow
		mcpara.taperwindow = taperwindow
		evline, mcname = eventListName(gsac.event, mcpara.phase)
		mcpara.evline = evline
		mcpara.mcname = mcname
		mcpara.kevnm = gsac.kevnm
		#rcwrite(ipick, timewindow, taperwindow, rcfile)
		solution = mccc(gsac, mcpara)
		wpk = int(wpick[1])
		if self.opts.reltime != wpk:
			out = '\n--> change opts.reltime from %i to %i'
			print out % (self.opts.reltime, wpk)
		self.opts.reltime = wpk
		self.replot()

	def plot2(self, event):
		""" Plot P2 stack of seismograms for defined time picks (ichdrs + wpick).
		"""
		opts = copy.copy(self.opts)
		twin_on = opts.twin_on
		pick_on = opts.pick_on
		reltime = opts.reltime
		ynorm = opts.ynorm
		fill = opts.fill
		selist = self.gsac.selist

		tpicks = opts.qcpara.ichdrs + [opts.mcpara.wpick,]
		print ('SAC Plot2')
		npick = len(tpicks)
		tlabs = 'ABCDE'

		fig2 = figure(figsize=(9,12))
		fig2.clf()
		subplots_adjust(bottom=.05, top=0.96, left=.1, right=.97, wspace=.5, hspace=.24)
		opts.twin_on = False
		opts.pick_on = False
		ax0 = fig2.add_subplot(npick,1,1)
		axsacs = [ ax0 ] + [ fig2.add_subplot(npick,1,i+1, sharex=ax0) for i in range(1, npick) ]
		for i in range(npick):
			opts.reltime = int(tpicks[i][1])
			ax = axsacs[i]
			sacp2(selist, opts, ax)
			tt = '(' + tlabs[i] + ')'
			trans = transforms.blended_transform_factory(ax.transAxes, ax.transAxes)
			ax.text(-.05, 1, tt, transform=trans, va='center', ha='right', size=16)	

		opts.ynorm = ynorm
		opts.twin_on = twin_on
		opts.pick_on = pick_on
		opts.reltime = reltime
		opts.fill = fill
		opts.zero_on = False

		show()