Beispiel #1
0
    def make(self, key):

        print(f'Populating Sync for {key}')

        # Get olfactory h5 path and filename
        olfactory_path = (OdorSession & key).fetch1('odor_path')
        local_path = lab.Paths().get_local_path(olfactory_path)
        filename_base = (OdorRecording & key).fetch1('filename')
        analog_filename = os.path.join(local_path, filename_base + '_%d.h5')

        # Load olfactory data
        analog_data = h5.read_analog_olfaction_file(analog_filename)

        scan_times = h5.ts2sec(analog_data['ts'], is_packeted=True)
        binarized_signal = analog_data['scanImage'] > 2.7  # TTL voltage low/high threshold
        rising_edges = np.where(np.diff(binarized_signal.astype(int)) > 0)[0]
        frame_times = scan_times[rising_edges]

        # Correct NaN gaps in timestamps (mistimed or dropped packets during recording)
        if np.any(np.isnan(frame_times)):
            # Raise exception if first or last frame pulse was recorded in mistimed packet
            if np.isnan(frame_times[0]) or np.isnan(frame_times[-1]):
                msg = ('First or last frame happened during misstamped packets. Pulses '
                       'could have been missed: start/end of scanning is unknown.')
                raise PipelineException(msg)

            # Fill each gap of nan values with correct number of timepoints
            frame_period = np.nanmedian(np.diff(frame_times))  # approx
            nan_limits = np.where(np.diff(np.isnan(frame_times)))[0]
            nan_limits[1::2] += 1  # limits are indices of the last valid point before the nan gap and first after it
            correct_fts = []
            for i, (start, stop) in enumerate(zip(nan_limits[::2], nan_limits[1::2])):
                correct_fts.extend(frame_times[0 if i == 0 else nan_limits[2 * i - 1]: start + 1])
                num_missing_points = int(round((frame_times[stop] - frame_times[start]) /
                                               frame_period - 1))
                correct_fts.extend(np.linspace(frame_times[start], frame_times[stop],
                                               num_missing_points + 2)[1:-1])
            correct_fts.extend(frame_times[nan_limits[-1]:])
            frame_times = np.array(correct_fts)

        # Check that frame times occur at the same period
        frame_intervals = np.diff(frame_times)
        frame_period = np.median(frame_intervals)
        if np.any(abs(frame_intervals - frame_period) > 0.15 * frame_period):
            raise PipelineException('Frame time period is irregular')

        self.insert1({**key, 'signal_start_time': frame_times[0],
                      'signal_duration': frame_times[-1] - frame_times[0],
                      'frame_times': frame_times})

        print(f'ScanImage sync added for animal {key["animal_id"]}, '
              f'olfactory session {key["odor_session"]}, '
              f'recording {key["recording_idx"]}\n')
Beispiel #2
0
    def make(self, key):

        print(f'Populating Respiration for {key}')

        # Get olfactory h5 path and filename
        olfactory_path = (OdorSession & key).fetch1('odor_path')
        local_path = lab.Paths().get_local_path(olfactory_path)
        filename_base = (OdorRecording & key).fetch1('filename')
        analog_filename = os.path.join(local_path, filename_base + '_%d.h5')

        # Load olfactory data
        analog_data = h5.read_analog_olfaction_file(analog_filename)
        breath_times = h5.ts2sec(analog_data['ts'], is_packeted=True)
        breath_trace = analog_data['breath']

        # Correct NaN gaps in timestamps (mistimed or dropped packets during recording)
        if np.any(np.isnan(breath_times)):
            # Raise exception if first or last frame pulse was recorded in mistimed packet
            if np.isnan(breath_times[0]) or np.isnan(breath_times[-1]):
                msg = (
                    'First or last breath happened during misstamped packets. Pulses '
                    'could have been missed: start/end of collection is unknown.'
                )
                raise PipelineException(msg)

            # Linear interpolate between nans
            nans_idx = np.where(np.isnan(breath_times))[0]
            non_nans_idx = np.where(~np.isnan(breath_times))[0]
            breath_times[nans_idx] = np.interp(nans_idx, non_nans_idx,
                                               breath_times[non_nans_idx])
            print(
                f'Largest NaN gap found: {np.max(np.abs(np.diff(breath_times[non_nans_idx])))} seconds'
            )

        # Check that frame times occur at the same period
        breath_intervals = np.diff(breath_times)
        breath_period = np.median(breath_intervals)
        if np.any(
                abs(breath_intervals - breath_period) > 0.15 * breath_period):
            raise PipelineException('Breath time period is irregular')

        # Error check tracing and timing match
        if breath_trace.shape[0] != breath_times.shape[0]:
            raise PipelineException('Breath timing and trace mismatch!')

        breath_key = {**key, 'trace': breath_trace, 'times': breath_times}

        self.insert1(breath_key)
        print(f'Respiration data for {key} successfully inserted.\n')