Esempio n. 1
0
class AlignTime:
    def __init__(self, filter=True, filt_ord=4, filt_cut=5, datetime=False):
        """
        Method for aligning time-stamps of different time series data

        Parameters
        ----------
        filter : {bool, array_like}, optional
            Filter the input data. Either bool for both data series, or an array_like of bools if only one series of
            data should be filtered.
        filt_ord : {int, array_like}, optional
            Filter order for the filtering process. Either a single int for both data series, or an array_like of 2
            ints, with orders for the first and second time series. Default is 4. Ignored if filter is False.
        filt_cut : {float, array_like}, optional
            Low-pass filter cutoffs for the filtering process. Either a signal float for both data series, or an
            array_like of 2 floats, with orders for the first and second time series. Default is 5Hz. Ignored if filter
            is False.
        datetime : bool, optional
            Whether or not datetime units are provided for the the time. Default is False, in which case seconds
            are expected
        """
        # assign values as appropriate
        if isinstance(filter, (tuple, list, ndarray)):
            self._filt1, self._filt2 = filter
        else:
            self._filt1, self._filt2 = filter, filter

        if isinstance(filt_ord, (tuple, list, ndarray)):
            self._ord1, self._ord2 = filt_ord
        else:
            self._ord1, self._ord2 = filt_ord, filt_ord

        if isinstance(filt_cut, (tuple, list, ndarray)):
            self._cut1, self._cut2 = filt_cut
        else:
            self._cut1, self._cut2 = filt_cut, filt_cut

        self.datetime = datetime

        # line for plotting the aligned signals
        self.line = None

    def fit(self,
            time1,
            data1,
            time2,
            data2,
            dt1=None,
            dt2=None,
            xlim1=None,
            xlim2=None,
            xnear1=None,
            xnear2=None):
        """
        Align the two time series

        Parameters
        ----------
        time1 : numpy.ndarray
            (N1, ) array of time-stamps for the first series of data. Will be resampled to match the sampling rate of
            the second data series if necessary during the alignment process.
        data1 : numpy.ndarray
            (N1, M1) array of the first series of data
        time2 : numpy.ndarray
            (N2, ) array of time-stamps for the second series of data. Does not have to be the same sampling rate as
            the first series of data. The first series of data will be resampled to match that of the second series
        data2 : numpy.ndarray
            (N2, M2) array of the second series of data
        dt1 : {None, float}, optional
            Sampling time for the first series time stamps, if necessary. Default is None, which will be ignored and
            the mean difference in time-stamps for the first 100 samples of the provided time stamps will be used.
        dt2 : {None, float}, optional
            Sampling time for the second series time stamps, if necessary. Default is None, which will be ignored and
            the mean difference in time-stamps for the first 100 samples of the provided time stamps will be used.
        xlim1 : array_like, optional
            X-limits for plotting series 1 data. Useful if you know approximately where the events to time sync are
            located in the series 1 data.
        xlim2 : array_like, optional
            X-limits for plotting series 2 data. Useful if you now approximately where the events to time sync are
            located in the series 2 data.
        xnear1 : float, optional
            X-value where to search near in the first signal. Will be marked on the graph with a vertical line.
        xnear2 : float, optional
            X-value where to search near in the second signal. Will be marked on the graph with a vertical line.

        Returns
        -------
        dt_1_2 : float
            The time difference between series 2 and series 1, calculated by subtracting the aligned time 2 - time 1

        Attributes
        ----------
        t1_0 : float
            Aligned time int time1 detected by the convolution of the two signals in th regions chosen.
        t2_0 : float
            Aligned time in time2 detected by the convolution of the two signals in the regions chosen.
        """
        # assign the times
        self._t1 = time1
        self._t2 = time2

        # assign the raw data
        self._rx1 = data1
        self._rx2 = data2

        # compute the sampling times
        if dt1 is None:
            if self.datetime:
                self._dt1 = mean(diff(self._t1[:100])) / timedelta64(1, 's')
            else:
                self._dt1 = mean(diff(self._t1[:100]))
        else:
            self._dt1 = dt1
        if dt2 is None:
            if self.datetime:
                self._dt2 = mean(diff(self._t2[:100])) / timedelta64(1, 's')
            else:
                self._dt2 = mean(diff(self._t2[:100]))
        else:
            self._dt2 = dt2

        # filter the data
        if self._filt1:
            fc1 = butter(self._ord1, 2 * self._cut1 * self._dt1, btype='low')
            self._x1 = filtfilt(fc1[0], fc1[1], self._rx1)
        else:
            self._x1 = self._rx1

        if self._filt2:
            fc2 = butter(self._ord2, 2 * self._cut2 * self._dt2, btype='low')
            self._x2 = filtfilt(fc2[0], fc2[1], self._rx2)
        else:
            self._x2 = self._rx2

        # plot the data
        self._f, (self._ax1, self._ax2) = plt.subplots(2, figsize=(20, 10))

        if self._filt1:
            self._ax1.plot(self._t1,
                           self._rx1,
                           color='C0',
                           linewidth=1.5,
                           label='Raw',
                           alpha=0.7)
        if self._filt2:
            self._ax2.plot(self._t2,
                           self._rx2,
                           color='C0',
                           linewidth=1.5,
                           label='Raw',
                           alpha=0.7)
        self._ax1.plot(self._t1,
                       self._x1,
                       color='C1',
                       linewidth=2,
                       label='Filtered')
        self._ax2.plot(self._t2,
                       self._x2,
                       color='C1',
                       linewidth=2,
                       label='Filtered')

        if xlim1 is not None:
            self._ax1.set_xlim(xlim1)
        if xlim2 is not None:
            self._ax2.set_xlim(xlim2)

        if xnear1 is not None:
            self._ax1.axvline(xnear1, color='k', linewidth=3, alpha=0.5)
        if xnear2 is not None:
            self._ax2.axvline(xnear2, color='k', linewidth=3, alpha=0.5)

        self._ax1.legend(loc='best')
        self._ax2.legend(loc='best')

        # create the cursor and span selectors for the first axis
        self._ax1.set_title('Navigate and select the region to check: '
                            )  # let user know what they are doing
        self._cursor1 = Cursor(self._ax1,
                               color='C0',
                               useblit=True,
                               linewidth=1)
        self._span1 = SpanSelector(self._ax1,
                                   self._on_select1,
                                   'horizontal',
                                   useblit=True,
                                   rectprops=dict(alpha=0.5, facecolor='red'),
                                   button=1,
                                   span_stays=True)

        self._ax2.set_title('Navigate and select region to match: ')
        self._cursor2 = Cursor(self._ax2,
                               color='C0',
                               useblit=True,
                               linewidth=1)
        self._span2 = SpanSelector(self._ax2,
                                   self._on_select2,
                                   'horizontal',
                                   useblit=True,
                                   rectprops=dict(alpha=0.5, facecolor='red'),
                                   button=1,
                                   span_stays=True)

        self._cursor2.set_active(False)
        self._span2.set_visible(False)

        self._f.tight_layout()

        plt.show(block=True)

        return self.t_diff

    def _on_select1(self, xmin, xmax):
        self._ax1.set_title(None)
        if self.datetime:
            t1 = date2num(self._t1)
        else:
            t1 = self._t1

        start, stop = searchsorted(t1, (xmin, xmax))

        f = interp1d(t1[start - 10:stop + 10],
                     self._x1[start - 10:stop + 10],
                     kind='cubic')
        if self.datetime:
            self._ta = drange(self._t1[start], self._t1[stop],
                              to_timedelta(self._dt2, unit='s'))
        else:
            self._t1 = arange(self._t1[start], self._t1[stop], self._dt2)

        self._a = f(self._ta)

        self._cursor2.set_active(True)
        self._span2.set_visible(True)

    def _on_select2(self, xmin, xmax):
        self._ax2.set_title(None)
        if self.datetime:
            t2 = date2num(self._t2)
        else:
            t2 = self._t2
        start, stop = searchsorted(t2, (xmin, xmax))

        self._b = zeros(self._a.shape)
        self._tb = t2[stop - self._a.size:stop]

        self._b[-(stop - start):] = self._x2[start:stop]

        A = fftpack.fft(self._a)
        B = fftpack.fft(self._b)

        Ar = -A.conjugate()

        self._ind_shift = argmax(nabs(fftpack.ifft(
            Ar * B)))  # convolve the arrays and find the peak

        self.t1_0 = self._ta[0]  # find the time value in the first signal
        self.t2_0 = self._tb[
            self._ind_shift]  # find the time value in the second signal

        t_pl = self._ta + (self.t2_0 - self.t1_0)
        x_pl = self._a

        if self.line is not None:
            self.line.set_data([], [])
        self.line, = self._ax2.plot(t_pl, x_pl, color='C2', label='Aligned')

        if self.datetime:
            self.t1_0 = to_datetime(num2date(self.t1_0)).tz_localize(None)
            self.t2_0 = to_datetime(num2date(self.t2_0)).tz_localize(None)

        # time difference between the signals
        self.t_diff = self.t2_0 - self.t1_0
Esempio n. 2
0
run.save_result("peakODX", pOptX[0])
run.save_result("widthX", widthX)
run.save_result("tempX", tempX)
run.save_result("centerX", centerX)
run.save_result("peakODZ", pOptZ[0])
run.save_result("widthZ", widthZ)
run.save_result("tempZ", tempZ)
run.save_result("centerZ", centerZ)
run.save_result("avgWidth", avgWidth)
run.save_result("avgPeakOD", avgPeakOD)
run.save_result("avgTemp", avgTemp)

# Set Center event

cursor = Cursor(ax, useblit=True, color='white', linewidth=1)
cursor.set_active(False)


def set_center(event):
    if event.key in ['C', 'c'] and not cursor.active:
        cursor.set_active(True)
    elif event.key in ['C', 'c'] and cursor.active:
        cursor.set_active(False)
        center = (int(event.xdata), int(event.ydata))
        print(center)
        with h5py.File('current_roi.h5', 'w') as f:
            if 'center' not in f:
                f.attrs.create('center', center)
            else:
                f.attrs['center'] = center