def test_onregulararray(self):
     "Test cmov_average on a basic ndarray."
     data = self.data
     for width in [3, 5, 7]:
         k = (width - 1) / 2
         ravg = mf.cmov_average(data, width)
         self.failUnless(isinstance(ravg, MaskedArray))
         assert_equal(ravg, data)
         assert_equal(ravg._mask, [1] * k + [0] * (len(data) - 2 * k) + [1] * k)
 def test_onregulararray(self):
     "Test cmov_average on a basic ndarray."
     data = self.data
     for width in [3, 5, 7]:
         k = (width - 1) / 2
         ravg = mf.cmov_average(data, width)
         self.failUnless(isinstance(ravg, MaskedArray))
         assert_equal(ravg, data)
         assert_equal(ravg._mask,
                      [1] * k + [0] * (len(data) - 2 * k) + [1] * k)
 def test_onmaskedarray(self):
     "Test cmov_average on a MaskedArray."
     data = self.maskeddata
     for width in [3, 5, 7]:
         k = (width - 1) / 2
         ravg = mf.cmov_average(data, width)
         self.failUnless(isinstance(ravg, MaskedArray))
         assert_equal(ravg, data)
         m = np.zeros(len(data), bool)
         m[:k] = m[-k:] = m[10 - k:10 + k + 1] = True
         assert_equal(ravg._mask, m)
 def test_onmaskedarray(self):
     "Test cmov_average on a MaskedArray."
     data = self.maskeddata
     for width in [3, 5, 7]:
         k = (width - 1) / 2
         ravg = mf.cmov_average(data, width)
         self.failUnless(isinstance(ravg, MaskedArray))
         assert_equal(ravg, data)
         m = np.zeros(len(data), bool)
         m[:k] = m[-k:] = m[10 - k : 10 + k + 1] = True
         assert_equal(ravg._mask, m)
 def test_ontimeseries(self):
     "Test cmov_average on a 1D TimeSeries."
     data = ts.time_series(self.maskeddata, start_date=ts.now('D'))
     for width in [3, 5, 7]:
         k = (width - 1) / 2
         ravg = mf.cmov_average(data, width)
         self.failUnless(isinstance(ravg, MaskedArray))
         assert_equal(ravg, data)
         m = np.zeros(len(data), bool)
         m[:k] = m[-k:] = m[10 - k:10 + k + 1] = True
         assert_equal(ravg._mask, m)
         assert_equal(ravg._dates, data._dates)
 def test_ontimeseries(self):
     "Test cmov_average on a 1D TimeSeries."
     data = ts.time_series(self.maskeddata, start_date=ts.now("D"))
     for width in [3, 5, 7]:
         k = (width - 1) / 2
         ravg = mf.cmov_average(data, width)
         self.failUnless(isinstance(ravg, MaskedArray))
         assert_equal(ravg, data)
         m = np.zeros(len(data), bool)
         m[:k] = m[-k:] = m[10 - k : 10 + k + 1] = True
         assert_equal(ravg._mask, m)
         assert_equal(ravg._dates, data._dates)
 def tests_onmultitimeseries(self):
     "Test cmov_average on a nD TimeSeries."
     maskeddata = MaskedArray(np.random.random(75).reshape(25, 3))
     maskeddata[10] = masked
     data = ts.time_series(maskeddata, start_date=ts.now("D"))
     for width in [3, 5, 7]:
         k = (width - 1) / 2
         ravg = mf.cmov_average(data, width)
         self.failUnless(isinstance(ravg, MaskedArray))
         #!!!: __getitem__ used to return a TimeSeries, now returns an array
         #            assert_almost_equal(ravg[18]._series.squeeze(),
         #                                data[18-k:18+k+1]._series.mean(0))
         assert_almost_equal(ravg[18].squeeze(), data[18 - k : 18 + k + 1]._series.mean(0))
         m = np.zeros(data.shape, bool)
         m[:k] = m[-k:] = m[10 - k : 10 + k + 1] = True
         assert_equal(ravg._mask, m)
         assert_equal(ravg._dates, data._dates)
 def tests_onmultitimeseries(self):
     "Test cmov_average on a nD TimeSeries."
     maskeddata = MaskedArray(np.random.random(75).reshape(25, 3))
     maskeddata[10] = masked
     data = ts.time_series(maskeddata, start_date=ts.now('D'))
     for width in [3, 5, 7]:
         k = (width - 1) / 2
         ravg = mf.cmov_average(data, width)
         self.failUnless(isinstance(ravg, MaskedArray))
         #!!!: __getitem__ used to return a TimeSeries, now returns an array
         #            assert_almost_equal(ravg[18]._series.squeeze(),
         #                                data[18-k:18+k+1]._series.mean(0))
         assert_almost_equal(ravg[18].squeeze(),
                             data[18 - k:18 + k + 1]._series.mean(0))
         m = np.zeros(data.shape, bool)
         m[:k] = m[-k:] = m[10 - k:10 + k + 1] = True
         assert_equal(ravg._mask, m)
         assert_equal(ravg._dates, data._dates)
Exemple #9
0
def main(options, args):
	"""The main procedure of physionoise"""
	initialize_logger()
	if (options.verbosity == 1): logger.setLevel(logging.INFO)
	if (options.verbosity == 2): logger.setLevel(logging.DEBUG)
	if (options.verbosity > 2):  logger.setLevel(0)
	
	respiratory_signal     =  mean_centered( load_signal(options.sigfile) )
	respiratory_triggers   =  load_signal(options.ctrigfile).astype('int')
	cardiac_signal         =  mean_centered( load_signal(options.csigfile) )
	cardiac_triggers       =  load_signal(options.ctrigfile).astype('int')
	
	respiratory_xaxis      = range(len(respiratory_signal))
	cardiac_xaxis          = range(len(cardiac_signal))
	
	input_sample_rate      = options.OrigSamp
	output_sample_rate     = options.NewSamp
	sample_ratio           = float(input_sample_rate) / output_sample_rate
	nyquist                = input_sample_rate / 2.0
	passband_frequency     = options.fpass / nyquist
	stopband_frequency     = options.fstop / nyquist
	
	tr_time                = options.TR
	num_tr                 = options.NumTR
	input_signal_length    = int(num_tr * tr_time * input_sample_rate)
	output_signal_length   = int(num_tr * tr_time * output_sample_rate)
	
	# these options are for tuning the peakdet algorithm
	respiratory_dm         = options.RMagThresh
	respiratory_dt         = options.RTimeThresh  # in seconds!
	cardiac_dm             = options.CMagThresh
	cardiac_dt             = options.CTimeThresh  # in seconds!
	
	plots_requested        = options.PlotAll
	use_fast_spline        = options.Speed
	prefix                 = options.Prefix
	truncate               = options.truncate
	
	# converting absolute event times from the trigger file to a boolean array
	CPttl = (numpy.zeros(len(cardiac_signal)) != 0) # array of Falses same size as signal
	CPttl[cardiac_triggers] = True
	
	
	### NOTE on encoding events ###
	# in all cases where we want to denote a series of events in a signal, we will
	# use an array of booleans.  For example, if we want to know where signal
	# peaks are we create an array of the same size as the signal with True entries
	# where each of the peaks occured and False everywhere else.
	# These boolean arrays can be used conveniently to index into the signals
	# e.g. signal[peaks] => produces the magnitude of the signal at the peaks.
	#
	
	
	####  Butterworth Filter Data  ###
	filter_b, filter_a, butter_response_magnitude, butter_sample_frequences = build_butterworth_filter(
		passband_frequency, stopband_frequency
	)
	
	filtered_respiratory = filtfilt(filter_b, filter_a, respiratory_signal)
	filtered_cardiac     = filtfilt(filter_b, filter_a, cardiac_signal)
	
	# the spectral analyses are just for plotting, they are currently not saved
	# to file at the end
	pxx, freqs, maxfreq, PeakPower, TPeriod = spectral_analysis(
		filtered_respiratory, input_sample_rate, "Respiratory"
	)
	
	Cpxx, Cfreqs, Cmaxfreq, CPeakPower, CTPeriod = spectral_analysis(
		filtered_cardiac, input_sample_rate, "Cardiac"
	)
	
	
	
	####  Spline interpolation  ####
	respiratory_residual = respiratory_signal - filtered_respiratory
	cardiac_residual     = cardiac_signal - filtered_cardiac

	if use_fast_spline:
		logger.info( "Speedy Spline Filtering" )
		respiratory_spline  = scipy.ndimage.spline_filter1d(filtered_respiratory, order=3)
		cardiac_spline      = scipy.ndimage.spline_filter1d(filtered_cardiac, order=3)
	else:
		logger.info( "Slower (better?) Spline Filtering" )
		logger.info( "Censoring regions of high variance" )
		
		censored_resp, resp_included, resp_included_indexes = censor_signal(
			respiratory_signal, filtered_respiratory,
			options.FoldSTD, options.TrimWindow, options.FwdRm
		)
		censored_cardiac, card_included, card_included_indexes = censor_signal(
			cardiac_signal, filtered_cardiac,
			options.FoldSTD, options.TrimWindow, options.FwdRm
		)
		
		logger.debug("resp len(%d) censored resp len(%d)" % (len(respiratory_signal), len(censored_resp)))
		logger.debug("card len(%d) censored card len(%d)" % (len(cardiac_signal), len(censored_cardiac)))
		
		logger.info( "Spline interpolation" )
		# Generate cubic spline....Too slow when not on Mac OS X but looks nice
		resp_spline_estimate  = scipy.interpolate.splrep(resp_included_indexes, resp_included, k=3)
		respiratory_spline    = scipy.interpolate.splev(respiratory_xaxis, resp_spline_estimate)
		card_spline_estimate  = scipy.interpolate.splrep(card_included_indexes, card_included, k=3)
		cardiac_spline        = scipy.interpolate.splev(cardiac_xaxis, card_spline_estimate)
	
	
	
	#----------------------------------------------------------  Finding peaks
	respiratory_extrema = extrema(respiratory_spline, respiratory_dm, respiratory_dt)
	respiratory_maxima  = maxima(respiratory_spline, respiratory_dm, respiratory_dt)
	respiratory_minima  = minima(respiratory_spline, respiratory_dm, respiratory_dt)
	
	cardiac_extrema     = extrema(cardiac_spline, cardiac_dm, cardiac_dt)
	cardiac_maxima      = maxima(cardiac_spline, cardiac_dm, cardiac_dt)
	cardiac_minima      = minima(cardiac_spline, cardiac_dm, cardiac_dt)
	
	
	
	#------------------------------------------------------- Find Volume over Time
	logger.info( "Calculating Envelopes" )
	logger.info( "Respiratory" )
	
	resp_top_envelope    = envelope(respiratory_spline, respiratory_maxima)
	resp_bottom_envelope = envelope(respiratory_spline, respiratory_minima)
	resp_abs_volume      = resp_top_envelope - resp_bottom_envelope
	resp_rate            = event_rate(respiratory_maxima, input_sample_rate) 
	rvt                  = resp_abs_volume * resp_rate
	
	logger.info( "Cardiac" )
	
	card_top_envelope    = envelope(cardiac_spline, cardiac_maxima)
	card_bottom_envelope = envelope(cardiac_spline, cardiac_minima)
	card_abs_volume      = card_top_envelope - card_bottom_envelope
	card_rate            = event_rate(cardiac_maxima, input_sample_rate)
	cvt                  = card_abs_volume * card_rate
	
	
	
	#------ Find third derivatives of Cardiac signal to create new trigger file
	logger.info( "Finding Cardiac Derivatives" )
	
	cardiac_d1 = slopes(cardiac_xaxis, cardiac_spline) #* input_sample_rate
	cardiac_d2 = slopes(cardiac_xaxis, cardiac_d1) #* input_sample_rate
	cardiac_d3 = slopes(cardiac_xaxis, cardiac_d2) #* input_sample_rate
	smoothed_caradiac_d3 = cmov_average(cardiac_d3, input_sample_rate / 2)
	
	# caution: using 1.0 for the amplitude threshold for peak finding, this might
	# not always work well.
	card_d3_maxima  = maxima(smoothed_caradiac_d3, 1.0, cardiac_dt)
	card_d3_minima  = minima(smoothed_caradiac_d3, 1.0, cardiac_dt)
	
	logger.info( "Thresholding CPd3" )
	CPd3 = card_d3_minima
	card_d3_bottom_envelope = envelope(smoothed_caradiac_d3, card_d3_minima)
	card_d3_top_envelope    = envelope(smoothed_caradiac_d3, card_d3_maxima)
	# There have been several approaches to filtering acceptable d3 minima 
	# to include in CPd3:
	# 1. the min must be in a region where d1 is negative
	# 2. the min must be less than the top envelope at that point
	# 3. the min must be less than 0.5 * the mean of the top envelope
	#
	# The current approach, calculate the bottom envelope and compute a moving
	# average of it at 1.5 * the sampling rate, accept any minima that
	# are <= the moving average.  The motivation for this is that in most cases
	# there are two classes of minima that are relatively seperable locally but 
	# not globally.  The moving average provides a consistent margin between the 
	# classes at the local level.
	
	CPd3 &= (card_d3_bottom_envelope <= cmov_average(card_d3_bottom_envelope, input_sample_rate*1.5))
	
	# Older minima filtering approaches
	#
	# CPd3 &= (cardiac_d1 >= -0.5)
	# CPd3 &= (card_d3_bottom_envelope <= mean(card_d3_bottom_envelope))
	# CPd3 &= (abs(card_d3_bottom_envelope) >= abs(card_d3_top_envelope))
	# CPd3 &= (abs(card_d3_bottom_envelope) >= 0.5*mean(abs(card_d3_top_envelope)))
	# CPd3 = -1.0 * spikewave(smoothed_caradiac_d3, CPd3)
	
	# R waves are d3 peaks that immediately precede CPd3 blips
	CPd3Rwave = (numpy.zeros(len(CPd3)) != 0)  # boolean array of all falses.
	for i in indices_of(CPd3):
		previous_d3_maxima = card_d3_maxima[0:i]
		if (len(indices_of(previous_d3_maxima)) > 0):
			index_of_prior_d3_maximum = indices_of(previous_d3_maxima)[-1]
			CPd3Rwave[index_of_prior_d3_maximum] = True
	
	
	
	#----------- Calculate respiratory (RRT) and cardiac rate per time (CRT)
	logger.info( "Calculating Rates over Time" )
	
	RRT    = event_rate(respiratory_maxima, input_sample_rate)
	CRTttl = event_rate(CPttl, input_sample_rate)
	CRTd3  = event_rate(CPd3, input_sample_rate)
	CRTd3R = event_rate(CPd3Rwave, input_sample_rate)
	
	
	
	
	#---------------------------------------------------------------- DownSampling
	logger.info( "Downsampling" )
	
	downsampled_respiratory = downsample(respiratory_spline, sample_ratio)
	downsampled_cardiac     = downsample(cardiac_spline,     sample_ratio)
	
	
	
	#-------------------------------------------------------------------- Plotting
	if plots_requested:
		# Butterworth filter analysis summary
		plt.figure(1)
		plt.title("Butterworth filter spectral analysis")
		plt.subplot(311)
		plt.semilogy(butter_sample_frequences * nyquist, butter_response_magnitude)
		plt.ylabel('Magnitude')
		plt.title('Bode Plot')
		plt.ylim((10e-4, 10e0))
		plt.xlim((0.0, options.fstop))
		plt.figure(1)
		plt.subplot(312) 
		plt.plot(freqs, pxx)
		plt.ylabel('Respiratory Power')
		plt.xlim((0.0, options.fstop))
		plt.figure(1)
		plt.subplot(313) 
		plt.plot(Cfreqs, Cpxx)
		plt.xlabel('frequency(Hz)')
		plt.ylabel('Cardiac Power')
		plt.xlim((0.0, options.fstop))
		
		# overview of the filter and spline interpolated signals
		plt.figure(2)
		plt.subplot(211)
		plt.plot(respiratory_xaxis, filtered_respiratory, 'b-',
		         respiratory_xaxis, respiratory_spline,   'go',
		         respiratory_xaxis, respiratory_signal,   'k',
		         respiratory_xaxis, respiratory_residual, 'r'
		)
		plt.legend(('Filtered', 'Spline', 'Raw', 'Residual'), shadow=False, loc=1)
		ltext = plt.gca().get_legend().get_texts()
		plt.setp(ltext[0], fontsize = 8, color = 'b')
		plt.setp(ltext[1], fontsize = 8, color = 'g')
		plt.setp(ltext[2], fontsize = 8, color = 'k')
		plt.setp(ltext[3], fontsize = 8, color = 'r')
		plt.title('Respiratory')
		plt.subplot(212)
		plt.plot(cardiac_xaxis, filtered_cardiac, 'b-',
		         cardiac_xaxis, cardiac_spline,   'go',
		         cardiac_xaxis, cardiac_signal,   'k',
		         cardiac_xaxis, cardiac_residual, 'r'
		)
		plt.legend(('Filtered','Spline','Raw','Residual'), shadow=False, loc=1)
		ltext = plt.gca().get_legend().get_texts()
		plt.setp(ltext[0], fontsize = 8, color = 'b')
		plt.setp(ltext[1], fontsize = 8, color = 'g')
		plt.setp(ltext[2], fontsize = 8, color = 'k')
		plt.setp(ltext[3], fontsize = 8, color = 'r')
		plt.title('Cardiac')
		
		# top and bottom peak finding and envelopes
		chart_envelopes(respiratory_spline,
			respiratory_maxima, resp_top_envelope,
			respiratory_minima, resp_bottom_envelope,
			rvt, 'Respiratory Data',
			('Respiratory Spline','Top Envelope','Bottom Envelope','Maxima','Minima','RVT'),
			figure=3, row=1
		)
		chart_envelopes(cardiac_spline,
			cardiac_maxima, card_top_envelope,
			cardiac_minima, card_bottom_envelope,
			cvt, 'Cardiac Data',
			('Cardiac Spline','Top Envelope','Bottom Envelope','Maxima','Minima','CVT'),
			figure=3, row=2
		)
		
		# summary of the volume over time waves and  cardiac wave event finding results
		signals_to_plot = (CRTd3R, CRTttl, RRT, CRTd3, rvt, cvt)
		labels = ('CRTd3R', 'CRTttl', 'RRT', 'CRTd3', 'RVT', 'CVT')
		chart_summary_of_signals(signals_to_plot, labels, figure=5)
		
		# cardiac wave events viewed on the spline 
		# make cardiac_d3 in roughly the same range as the spline
		adjustment_ratio = numpy.nanmax(cardiac_spline) / numpy.nanmax(smoothed_caradiac_d3)
		adjusted_d3      = smoothed_caradiac_d3 * 1.5 * adjustment_ratio
		plt.figure(6)
		plt.title('Event Locations on the Cardiac Waveform')
		plt.hold()
		plt.plot(cardiac_signal, '#aaaaaa')
		plt.plot(cardiac_spline, 'k')
		plt.plot(adjusted_d3, '#ff5555')
		plt.plot(indices_of(CPttl), cardiac_spline[CPttl], 'yo')
		plt.plot(indices_of(CPd3), cardiac_spline[CPd3], 'bo')
		plt.plot(indices_of(CPd3Rwave), cardiac_spline[CPd3Rwave], 'go')
		plt.legend(('Raw Cardiac','Cardiac Spline','Cardiac d3','CPttl','CPd3','CPd3Rwave'), shadow=False, loc=1)
		ltext = plt.gca().get_legend().get_texts()
		plt.setp(ltext[0], fontsize = 8, color = '#aaaaaa')
		plt.setp(ltext[1], fontsize = 8, color = 'k')
		plt.setp(ltext[2], fontsize = 8, color = '#ff5555')
		plt.setp(ltext[3], fontsize = 8, color = 'y')
		plt.setp(ltext[4], fontsize = 8, color = 'b')
		plt.setp(ltext[5], fontsize = 8, color = 'g')
		
		
	
	
	#--------------------------------------------------- Trim length for retroicor
	logger.info( "Trim length" )
	
	# expected length at input sample rate
	ei = tr_time * num_tr * input_sample_rate
	
	# expected length at downsample rate
	ed =   tr_time * num_tr * output_sample_rate
	
	if (truncate == 'end'):
		logger.info( "Truncating at end of signal" )
		respiratory_spline      = respiratory_spline[0:ei]
		cardiac_spline          = cardiac_spline[0:ei]
		CPd3                    = CPd3[0:ei]
		CPd3Rwave               = CPd3Rwave[0:ei]
		CPttl                   = CPttl[0:ei]
		RRT                     = RRT[0:ei]
		CRTd3                   = CRTd3[0:ei]
		CRTttl                  = CRTttl[0:ei]
		CRTd3R                  = CRTd3R[0:ei]
		resp_top_envelope       = resp_top_envelope[0:ei]
		card_top_envelope       = card_top_envelope[0:ei]
		downsampled_cardiac     = downsampled_cardiac[0:ed]
		downsampled_respiratory = downsampled_respiratory[0:ed]
	elif (truncate == 'front'):
		logger.info( "Truncating at front of signal" )
		ei_front = len(respiratory_spline) - ei
		ed_front = len(downsampled_respiratory) - ed
		
		respiratory_spline      = respiratory_spline[ei_front:]
		cardiac_spline          = cardiac_spline[ei_front:]
		CPd3                    = CPd3[ei_front:]
		CPd3Rwave               = CPd3Rwave[ei_front:]
		CPttl                   = CPttl[ei_front:]
		RRT                     = RRT[ei_front:]
		CRTd3                   = CRTd3[ei_front:]
		CRTttl                  = CRTttl[ei_front:]
		CRTd3R                  = CRTd3R[ei_front:]
		resp_top_envelope       = resp_top_envelope[ei_front:]
		card_top_envelope       = card_top_envelope[ei_front:]
		downsampled_cardiac     = downsampled_cardiac[ed_front:]
		downsampled_respiratory = downsampled_respiratory[ei_front:]
	else:
		logger.info( "Not truncating signal to expected TR size." )
	
	
	#---------------------------------------------------------------- Reporting
	peaktypes = {
		"CPttl": CPttl, "CPd3": CPd3, "CPd3Rwave": CPd3Rwave
	}
	
	rpt = report_value # just aliasing the report_value function
	tblhdr_fmt = "%-14s%-14s%-14s"
	tblrow_fmt = "%-14d%-14.4f%-14.4f"
	lbl_fmt = "%-14s%-14s"
	divider_width = 90
	divider = "=" * divider_width
	
	print
	rpt( lbl_fmt % ("Peak type","Aspect"), tblhdr_fmt % ('N', 'mean', 'std') )
	print divider
	
	for peak_label, peakseries in peaktypes.iteritems():
		mags    = cardiac_spline[peakseries]
		times   = indices_of(peakseries)
		dt      = diff(times)
		gt3std  = mags[mags > mean(mags) + 3*std(mags)]
		gt4std  = mags[mags > mean(mags) + 4*std(mags)]
		gtmean  = mags[mags > mean(mags) + 1.0]
		gtbelow = mags[mags > mean(mags) - 0.4]
		
		reports = {
			"all timepoints": peakseries, "peak magnitudes": mags, "peak times": times,
			"interpeak times": dt,        "peaks > 3std": gt3std,  "peaks > 4std": gt4std,
			"peaks > mean + 1": gtmean,   "peaks > mean - 0.4": gtbelow }
		for report_label, report_series in reports.iteritems():
			n, m, s = stat_summary(report_series)
			rpt(lbl_fmt % (peak_label, report_label), tblrow_fmt % (n,m,s))
			
	
	# Dumping results to files
	if (options.saveFiles):
		logger.info( "Saving files" )
		
		signals  = { 'resp_spline': respiratory_spline,    'card_spline': cardiac_spline,
		             'RVT'      : rvt,
		             'RRT'      : RRT,                     'CRTd3' : CRTd3,
		             'CRTd3R'   : CRTd3R,                  'CRTttl': CRTttl }
		for fbase, signal in signals.iteritems():
			dump(zeromin(signal), fbase, prefix, input_sample_rate)
			for tr_label, tr_multiple in { 'TR_': 1.0, 'HalfTR_': 0.5 }.iteritems():
				resampled_signal = resample_to_tr(signal, input_sample_rate, num_tr, tr_time, tr_multiple)
				dump(zeromin(resampled_signal), tr_label + fbase, prefix, input_sample_rate)
				
		peaksigs = { 'CPd3': CPd3, 'CPd3R': CPd3Rwave, 'CPttl': CPttl }
		for fbase, peak in peaksigs.iteritems():
			dump(peak, fbase, prefix, input_sample_rate)
		
		# probably not needed, left over from original physionoise.py
		dump(zeromin(downsampled_respiratory), 'resp_spline_downsampled', prefix, output_sample_rate)
	
	
	if plots_requested:
		plt.show()
	
	
	sys.exit(0)
Exemple #10
0
def main(options, args):
    """The main procedure of physionoise"""
    initialize_logger()
    if (options.verbosity == 1): logger.setLevel(logging.INFO)
    if (options.verbosity == 2): logger.setLevel(logging.DEBUG)
    if (options.verbosity > 2): logger.setLevel(0)

    respiratory_signal = mean_centered(load_signal(options.sigfile))
    respiratory_triggers = load_signal(options.ctrigfile).astype('int')
    cardiac_signal = mean_centered(load_signal(options.csigfile))
    cardiac_triggers = load_signal(options.ctrigfile).astype('int')

    respiratory_xaxis = range(len(respiratory_signal))
    cardiac_xaxis = range(len(cardiac_signal))

    input_sample_rate = options.OrigSamp
    output_sample_rate = options.NewSamp
    sample_ratio = float(input_sample_rate) / output_sample_rate
    nyquist = input_sample_rate / 2.0
    passband_frequency = options.fpass / nyquist
    stopband_frequency = options.fstop / nyquist

    tr_time = options.TR
    num_tr = options.NumTR
    input_signal_length = int(num_tr * tr_time * input_sample_rate)
    output_signal_length = int(num_tr * tr_time * output_sample_rate)

    # these options are for tuning the peakdet algorithm
    respiratory_dm = options.RMagThresh
    respiratory_dt = options.RTimeThresh  # in seconds!
    cardiac_dm = options.CMagThresh
    cardiac_dt = options.CTimeThresh  # in seconds!

    plots_requested = options.PlotAll
    use_fast_spline = options.Speed
    prefix = options.Prefix
    truncate = options.truncate

    # converting absolute event times from the trigger file to a boolean array
    CPttl = (numpy.zeros(len(cardiac_signal)) != 0
             )  # array of Falses same size as signal
    CPttl[cardiac_triggers] = True

    ### NOTE on encoding events ###
    # in all cases where we want to denote a series of events in a signal, we will
    # use an array of booleans.  For example, if we want to know where signal
    # peaks are we create an array of the same size as the signal with True entries
    # where each of the peaks occured and False everywhere else.
    # These boolean arrays can be used conveniently to index into the signals
    # e.g. signal[peaks] => produces the magnitude of the signal at the peaks.
    #

    ####  Butterworth Filter Data  ###
    filter_b, filter_a, butter_response_magnitude, butter_sample_frequences = build_butterworth_filter(
        passband_frequency, stopband_frequency)

    filtered_respiratory = filtfilt(filter_b, filter_a, respiratory_signal)
    filtered_cardiac = filtfilt(filter_b, filter_a, cardiac_signal)

    # the spectral analyses are just for plotting, they are currently not saved
    # to file at the end
    pxx, freqs, maxfreq, PeakPower, TPeriod = spectral_analysis(
        filtered_respiratory, input_sample_rate, "Respiratory")

    Cpxx, Cfreqs, Cmaxfreq, CPeakPower, CTPeriod = spectral_analysis(
        filtered_cardiac, input_sample_rate, "Cardiac")

    ####  Spline interpolation  ####
    respiratory_residual = respiratory_signal - filtered_respiratory
    cardiac_residual = cardiac_signal - filtered_cardiac

    if use_fast_spline:
        logger.info("Speedy Spline Filtering")
        respiratory_spline = scipy.ndimage.spline_filter1d(
            filtered_respiratory, order=3)
        cardiac_spline = scipy.ndimage.spline_filter1d(filtered_cardiac,
                                                       order=3)
    else:
        logger.info("Slower (better?) Spline Filtering")
        logger.info("Censoring regions of high variance")

        censored_resp, resp_included, resp_included_indexes = censor_signal(
            respiratory_signal, filtered_respiratory, options.FoldSTD,
            options.TrimWindow, options.FwdRm)
        censored_cardiac, card_included, card_included_indexes = censor_signal(
            cardiac_signal, filtered_cardiac, options.FoldSTD,
            options.TrimWindow, options.FwdRm)

        logger.debug("resp len(%d) censored resp len(%d)" %
                     (len(respiratory_signal), len(censored_resp)))
        logger.debug("card len(%d) censored card len(%d)" %
                     (len(cardiac_signal), len(censored_cardiac)))

        logger.info("Spline interpolation")
        # Generate cubic spline....Too slow when not on Mac OS X but looks nice
        resp_spline_estimate = scipy.interpolate.splrep(resp_included_indexes,
                                                        resp_included,
                                                        k=3)
        respiratory_spline = scipy.interpolate.splev(respiratory_xaxis,
                                                     resp_spline_estimate)
        card_spline_estimate = scipy.interpolate.splrep(card_included_indexes,
                                                        card_included,
                                                        k=3)
        cardiac_spline = scipy.interpolate.splev(cardiac_xaxis,
                                                 card_spline_estimate)

    #----------------------------------------------------------  Finding peaks
    respiratory_extrema = extrema(respiratory_spline, respiratory_dm,
                                  respiratory_dt)
    respiratory_maxima = maxima(respiratory_spline, respiratory_dm,
                                respiratory_dt)
    respiratory_minima = minima(respiratory_spline, respiratory_dm,
                                respiratory_dt)

    cardiac_extrema = extrema(cardiac_spline, cardiac_dm, cardiac_dt)
    cardiac_maxima = maxima(cardiac_spline, cardiac_dm, cardiac_dt)
    cardiac_minima = minima(cardiac_spline, cardiac_dm, cardiac_dt)

    #------------------------------------------------------- Find Volume over Time
    logger.info("Calculating Envelopes")
    logger.info("Respiratory")

    resp_top_envelope = envelope(respiratory_spline, respiratory_maxima)
    resp_bottom_envelope = envelope(respiratory_spline, respiratory_minima)
    resp_abs_volume = resp_top_envelope - resp_bottom_envelope
    resp_rate = event_rate(respiratory_maxima, input_sample_rate)
    rvt = resp_abs_volume * resp_rate

    logger.info("Cardiac")

    card_top_envelope = envelope(cardiac_spline, cardiac_maxima)
    card_bottom_envelope = envelope(cardiac_spline, cardiac_minima)
    card_abs_volume = card_top_envelope - card_bottom_envelope
    card_rate = event_rate(cardiac_maxima, input_sample_rate)
    cvt = card_abs_volume * card_rate

    #------ Find third derivatives of Cardiac signal to create new trigger file
    logger.info("Finding Cardiac Derivatives")

    cardiac_d1 = slopes(cardiac_xaxis, cardiac_spline)  #* input_sample_rate
    cardiac_d2 = slopes(cardiac_xaxis, cardiac_d1)  #* input_sample_rate
    cardiac_d3 = slopes(cardiac_xaxis, cardiac_d2)  #* input_sample_rate
    smoothed_caradiac_d3 = cmov_average(cardiac_d3, input_sample_rate / 2)

    # caution: using 1.0 for the amplitude threshold for peak finding, this might
    # not always work well.
    card_d3_maxima = maxima(smoothed_caradiac_d3, 1.0, cardiac_dt)
    card_d3_minima = minima(smoothed_caradiac_d3, 1.0, cardiac_dt)

    logger.info("Thresholding CPd3")
    CPd3 = card_d3_minima
    card_d3_bottom_envelope = envelope(smoothed_caradiac_d3, card_d3_minima)
    card_d3_top_envelope = envelope(smoothed_caradiac_d3, card_d3_maxima)
    # There have been several approaches to filtering acceptable d3 minima
    # to include in CPd3:
    # 1. the min must be in a region where d1 is negative
    # 2. the min must be less than the top envelope at that point
    # 3. the min must be less than 0.5 * the mean of the top envelope
    #
    # The current approach, calculate the bottom envelope and compute a moving
    # average of it at 1.5 * the sampling rate, accept any minima that
    # are <= the moving average.  The motivation for this is that in most cases
    # there are two classes of minima that are relatively seperable locally but
    # not globally.  The moving average provides a consistent margin between the
    # classes at the local level.

    CPd3 &= (card_d3_bottom_envelope <= cmov_average(card_d3_bottom_envelope,
                                                     input_sample_rate * 1.5))

    # Older minima filtering approaches
    #
    # CPd3 &= (cardiac_d1 >= -0.5)
    # CPd3 &= (card_d3_bottom_envelope <= mean(card_d3_bottom_envelope))
    # CPd3 &= (abs(card_d3_bottom_envelope) >= abs(card_d3_top_envelope))
    # CPd3 &= (abs(card_d3_bottom_envelope) >= 0.5*mean(abs(card_d3_top_envelope)))
    # CPd3 = -1.0 * spikewave(smoothed_caradiac_d3, CPd3)

    # R waves are d3 peaks that immediately precede CPd3 blips
    CPd3Rwave = (numpy.zeros(len(CPd3)) != 0)  # boolean array of all falses.
    for i in indices_of(CPd3):
        previous_d3_maxima = card_d3_maxima[0:i]
        if (len(indices_of(previous_d3_maxima)) > 0):
            index_of_prior_d3_maximum = indices_of(previous_d3_maxima)[-1]
            CPd3Rwave[index_of_prior_d3_maximum] = True

    #----------- Calculate respiratory (RRT) and cardiac rate per time (CRT)
    logger.info("Calculating Rates over Time")

    RRT = event_rate(respiratory_maxima, input_sample_rate)
    CRTttl = event_rate(CPttl, input_sample_rate)
    CRTd3 = event_rate(CPd3, input_sample_rate)
    CRTd3R = event_rate(CPd3Rwave, input_sample_rate)

    #---------------------------------------------------------------- DownSampling
    logger.info("Downsampling")

    downsampled_respiratory = downsample(respiratory_spline, sample_ratio)
    downsampled_cardiac = downsample(cardiac_spline, sample_ratio)

    #-------------------------------------------------------------------- Plotting
    if plots_requested:
        # Butterworth filter analysis summary
        plt.figure(1)
        plt.title("Butterworth filter spectral analysis")
        plt.subplot(311)
        plt.semilogy(butter_sample_frequences * nyquist,
                     butter_response_magnitude)
        plt.ylabel('Magnitude')
        plt.title('Bode Plot')
        plt.ylim((10e-4, 10e0))
        plt.xlim((0.0, options.fstop))
        plt.figure(1)
        plt.subplot(312)
        plt.plot(freqs, pxx)
        plt.ylabel('Respiratory Power')
        plt.xlim((0.0, options.fstop))
        plt.figure(1)
        plt.subplot(313)
        plt.plot(Cfreqs, Cpxx)
        plt.xlabel('frequency(Hz)')
        plt.ylabel('Cardiac Power')
        plt.xlim((0.0, options.fstop))

        # overview of the filter and spline interpolated signals
        plt.figure(2)
        plt.subplot(211)
        plt.plot(respiratory_xaxis, filtered_respiratory, 'b-',
                 respiratory_xaxis, respiratory_spline, 'go',
                 respiratory_xaxis, respiratory_signal, 'k', respiratory_xaxis,
                 respiratory_residual, 'r')
        plt.legend(('Filtered', 'Spline', 'Raw', 'Residual'),
                   shadow=False,
                   loc=1)
        ltext = plt.gca().get_legend().get_texts()
        plt.setp(ltext[0], fontsize=8, color='b')
        plt.setp(ltext[1], fontsize=8, color='g')
        plt.setp(ltext[2], fontsize=8, color='k')
        plt.setp(ltext[3], fontsize=8, color='r')
        plt.title('Respiratory')
        plt.subplot(212)
        plt.plot(cardiac_xaxis, filtered_cardiac, 'b-', cardiac_xaxis,
                 cardiac_spline, 'go', cardiac_xaxis, cardiac_signal, 'k',
                 cardiac_xaxis, cardiac_residual, 'r')
        plt.legend(('Filtered', 'Spline', 'Raw', 'Residual'),
                   shadow=False,
                   loc=1)
        ltext = plt.gca().get_legend().get_texts()
        plt.setp(ltext[0], fontsize=8, color='b')
        plt.setp(ltext[1], fontsize=8, color='g')
        plt.setp(ltext[2], fontsize=8, color='k')
        plt.setp(ltext[3], fontsize=8, color='r')
        plt.title('Cardiac')

        # top and bottom peak finding and envelopes
        chart_envelopes(respiratory_spline,
                        respiratory_maxima,
                        resp_top_envelope,
                        respiratory_minima,
                        resp_bottom_envelope,
                        rvt,
                        'Respiratory Data',
                        ('Respiratory Spline', 'Top Envelope',
                         'Bottom Envelope', 'Maxima', 'Minima', 'RVT'),
                        figure=3,
                        row=1)
        chart_envelopes(cardiac_spline,
                        cardiac_maxima,
                        card_top_envelope,
                        cardiac_minima,
                        card_bottom_envelope,
                        cvt,
                        'Cardiac Data',
                        ('Cardiac Spline', 'Top Envelope', 'Bottom Envelope',
                         'Maxima', 'Minima', 'CVT'),
                        figure=3,
                        row=2)

        # summary of the volume over time waves and  cardiac wave event finding results
        signals_to_plot = (CRTd3R, CRTttl, RRT, CRTd3, rvt, cvt)
        labels = ('CRTd3R', 'CRTttl', 'RRT', 'CRTd3', 'RVT', 'CVT')
        chart_summary_of_signals(signals_to_plot, labels, figure=5)

        # cardiac wave events viewed on the spline
        # make cardiac_d3 in roughly the same range as the spline
        adjustment_ratio = numpy.nanmax(cardiac_spline) / numpy.nanmax(
            smoothed_caradiac_d3)
        adjusted_d3 = smoothed_caradiac_d3 * 1.5 * adjustment_ratio
        plt.figure(6)
        plt.title('Event Locations on the Cardiac Waveform')
        plt.hold()
        plt.plot(cardiac_signal, '#aaaaaa')
        plt.plot(cardiac_spline, 'k')
        plt.plot(adjusted_d3, '#ff5555')
        plt.plot(indices_of(CPttl), cardiac_spline[CPttl], 'yo')
        plt.plot(indices_of(CPd3), cardiac_spline[CPd3], 'bo')
        plt.plot(indices_of(CPd3Rwave), cardiac_spline[CPd3Rwave], 'go')
        plt.legend(('Raw Cardiac', 'Cardiac Spline', 'Cardiac d3', 'CPttl',
                    'CPd3', 'CPd3Rwave'),
                   shadow=False,
                   loc=1)
        ltext = plt.gca().get_legend().get_texts()
        plt.setp(ltext[0], fontsize=8, color='#aaaaaa')
        plt.setp(ltext[1], fontsize=8, color='k')
        plt.setp(ltext[2], fontsize=8, color='#ff5555')
        plt.setp(ltext[3], fontsize=8, color='y')
        plt.setp(ltext[4], fontsize=8, color='b')
        plt.setp(ltext[5], fontsize=8, color='g')

    #--------------------------------------------------- Trim length for retroicor
    logger.info("Trim length")

    # expected length at input sample rate
    ei = tr_time * num_tr * input_sample_rate

    # expected length at downsample rate
    ed = tr_time * num_tr * output_sample_rate

    if (truncate == 'end'):
        logger.info("Truncating at end of signal")
        respiratory_spline = respiratory_spline[0:ei]
        cardiac_spline = cardiac_spline[0:ei]
        CPd3 = CPd3[0:ei]
        CPd3Rwave = CPd3Rwave[0:ei]
        CPttl = CPttl[0:ei]
        RRT = RRT[0:ei]
        CRTd3 = CRTd3[0:ei]
        CRTttl = CRTttl[0:ei]
        CRTd3R = CRTd3R[0:ei]
        resp_top_envelope = resp_top_envelope[0:ei]
        card_top_envelope = card_top_envelope[0:ei]
        downsampled_cardiac = downsampled_cardiac[0:ed]
        downsampled_respiratory = downsampled_respiratory[0:ed]
    elif (truncate == 'front'):
        logger.info("Truncating at front of signal")
        ei_front = len(respiratory_spline) - ei
        ed_front = len(downsampled_respiratory) - ed

        respiratory_spline = respiratory_spline[ei_front:]
        cardiac_spline = cardiac_spline[ei_front:]
        CPd3 = CPd3[ei_front:]
        CPd3Rwave = CPd3Rwave[ei_front:]
        CPttl = CPttl[ei_front:]
        RRT = RRT[ei_front:]
        CRTd3 = CRTd3[ei_front:]
        CRTttl = CRTttl[ei_front:]
        CRTd3R = CRTd3R[ei_front:]
        resp_top_envelope = resp_top_envelope[ei_front:]
        card_top_envelope = card_top_envelope[ei_front:]
        downsampled_cardiac = downsampled_cardiac[ed_front:]
        downsampled_respiratory = downsampled_respiratory[ei_front:]
    else:
        logger.info("Not truncating signal to expected TR size.")

    #---------------------------------------------------------------- Reporting
    peaktypes = {"CPttl": CPttl, "CPd3": CPd3, "CPd3Rwave": CPd3Rwave}

    rpt = report_value  # just aliasing the report_value function
    tblhdr_fmt = "%-14s%-14s%-14s"
    tblrow_fmt = "%-14d%-14.4f%-14.4f"
    lbl_fmt = "%-14s%-14s"
    divider_width = 90
    divider = "=" * divider_width

    print
    rpt(lbl_fmt % ("Peak type", "Aspect"), tblhdr_fmt % ('N', 'mean', 'std'))
    print divider

    for peak_label, peakseries in peaktypes.iteritems():
        mags = cardiac_spline[peakseries]
        times = indices_of(peakseries)
        dt = diff(times)
        gt3std = mags[mags > mean(mags) + 3 * std(mags)]
        gt4std = mags[mags > mean(mags) + 4 * std(mags)]
        gtmean = mags[mags > mean(mags) + 1.0]
        gtbelow = mags[mags > mean(mags) - 0.4]

        reports = {
            "all timepoints": peakseries,
            "peak magnitudes": mags,
            "peak times": times,
            "interpeak times": dt,
            "peaks > 3std": gt3std,
            "peaks > 4std": gt4std,
            "peaks > mean + 1": gtmean,
            "peaks > mean - 0.4": gtbelow
        }
        for report_label, report_series in reports.iteritems():
            n, m, s = stat_summary(report_series)
            rpt(lbl_fmt % (peak_label, report_label), tblrow_fmt % (n, m, s))

    # Dumping results to files
    if (options.saveFiles):
        logger.info("Saving files")

        signals = {
            'resp_spline': respiratory_spline,
            'card_spline': cardiac_spline,
            'RVT': rvt,
            'RRT': RRT,
            'CRTd3': CRTd3,
            'CRTd3R': CRTd3R,
            'CRTttl': CRTttl
        }
        for fbase, signal in signals.iteritems():
            dump(zeromin(signal), fbase, prefix, input_sample_rate)
            for tr_label, tr_multiple in {
                    'TR_': 1.0,
                    'HalfTR_': 0.5
            }.iteritems():
                resampled_signal = resample_to_tr(signal, input_sample_rate,
                                                  num_tr, tr_time, tr_multiple)
                dump(zeromin(resampled_signal), tr_label + fbase, prefix,
                     input_sample_rate)

        peaksigs = {'CPd3': CPd3, 'CPd3R': CPd3Rwave, 'CPttl': CPttl}
        for fbase, peak in peaksigs.iteritems():
            dump(peak, fbase, prefix, input_sample_rate)

        # probably not needed, left over from original physionoise.py
        dump(zeromin(downsampled_respiratory), 'resp_spline_downsampled',
             prefix, output_sample_rate)

    if plots_requested:
        plt.show()

    sys.exit(0)