Exemple #1
0
    def test_rises_falls(self):
        # test 1D case with a long pulse and a dirac
        a = np.zeros(500,)
        a[80:120] = 1
        a[200] = 1
        # rising fronts
        self.assertTrue(all(rises(a) == np.array([80, 200])))
        # falling fronts
        self.assertTrue(all(falls(a) == np.array([120, 201])))
        # both
        ind, val = fronts(a)
        self.assertTrue(all(ind == np.array([80, 120, 200, 201])))
        self.assertTrue(all(val == np.array([1, -1, 1, -1])))

        # test a 2D case with 2 long pulses and a dirac
        a = np.zeros((2, 500))
        a[0, 80:120] = 1
        a[0, 200] = 1
        a[1, 280:320] = 1
        a[1, 400] = 1
        # rising fronts
        self.assertTrue(np.all(rises(a) == np.array([[0, 0, 1, 1], [80, 200, 280, 400]])))
        # falling fronts
        self.assertTrue(np.all(falls(a) == np.array([[0, 0, 1, 1], [120, 201, 320, 401]])))
        # both
        ind, val = fronts(a)
        self.assertTrue(all(ind[0] == np.array([0, 0, 0, 0, 1, 1, 1, 1])))
        self.assertTrue(all(ind[1] == np.array([80, 120, 200, 201, 280, 320, 400, 401])))
        self.assertTrue(all(val == np.array([1, -1, 1, -1, 1, -1, 1, -1])))
Exemple #2
0
def _sync_to_alf(raw_ephys_apfile, output_path=None, save=False, parts=''):
    """
    Extracts sync.times, sync.channels and sync.polarities from binary ephys dataset

    :param raw_ephys_apfile: bin file containing ephys data or spike
    :param output_path: output directory
    :param save: bool write to disk only if True
    :param parts: string or list of strings that will be appended to the filename before extension
    :return:
    """
    # handles input argument: support ibllib.io.spikeglx.Reader, str and pathlib.Path
    if isinstance(raw_ephys_apfile, spikeglx.Reader):
        sr = raw_ephys_apfile
    else:
        raw_ephys_apfile = Path(raw_ephys_apfile)
        sr = spikeglx.Reader(raw_ephys_apfile)
    # if no output, need a temp folder to swap for big files
    if not output_path:
        output_path = raw_ephys_apfile.parent
    file_ftcp = Path(output_path).joinpath(
        f'fronts_times_channel_polarity{str(uuid.uuid4())}.bin')

    # loop over chunks of the raw ephys file
    wg = dsp.WindowGenerator(sr.ns,
                             int(SYNC_BATCH_SIZE_SECS * sr.fs),
                             overlap=1)
    fid_ftcp = open(file_ftcp, 'wb')
    for sl in wg.slice:
        ss = sr.read_sync(sl)
        ind, fronts = dsp.fronts(ss, axis=0)
        # a = sr.read_sync_analog(sl)
        sav = np.c_[(ind[0, :] + sl.start) / sr.fs, ind[1, :],
                    fronts.astype(np.double)]
        sav.tofile(fid_ftcp)
        # print progress
        wg.print_progress()
    # close temp file, read from it and delete
    fid_ftcp.close()
    tim_chan_pol = np.fromfile(str(file_ftcp))
    tim_chan_pol = tim_chan_pol.reshape((int(tim_chan_pol.size / 3), 3))
    file_ftcp.unlink()
    sync = {
        'times': tim_chan_pol[:, 0],
        'channels': tim_chan_pol[:, 1],
        'polarities': tim_chan_pol[:, 2]
    }
    if save:
        out_files = alf.io.save_object_npy(output_path,
                                           sync,
                                           '_spikeglx_sync',
                                           parts=parts)
        return Bunch(sync), out_files
    else:
        return Bunch(sync)
Exemple #3
0
def _sync_to_alf(raw_ephys_apfile, output_path=None, save=False):
    """
    Extracts sync.times, sync.channels and sync.polarities from binary ephys dataset

    :param raw_ephys_apfile: bin file containing ephys data or spike
    :param out_dir: output directory
    :return:
    """
    if not output_path:
        file_ftcp = tempfile.TemporaryFile()
    else:
        file_ftcp = Path(output_path) / 'fronts_times_channel_polarity.bin'
    if isinstance(raw_ephys_apfile, ibllib.io.spikeglx.Reader):
        sr = raw_ephys_apfile
    else:
        sr = ibllib.io.spikeglx.Reader(raw_ephys_apfile)
    # loop over chunks of the raw ephys file
    wg = dsp.WindowGenerator(sr.ns, SYNC_BATCH_SIZE_SAMPLES, overlap=1)
    fid_ftcp = open(file_ftcp, 'wb')
    for sl in wg.slice:
        ss = sr.read_sync(sl)
        ind, fronts = dsp.fronts(ss, axis=0)
        sav = np.c_[(ind[0, :] + sl.start) / sr.fs, ind[1, :],
                    fronts.astype(np.double)]
        sav.tofile(fid_ftcp)
        # print progress
        wg.print_progress()
    # close temp file, read from it and delete
    fid_ftcp.close()
    tim_chan_pol = np.fromfile(str(file_ftcp))
    tim_chan_pol = tim_chan_pol.reshape((int(tim_chan_pol.size / 3), 3))
    file_ftcp.unlink()
    sync = {
        'times': tim_chan_pol[:, 0],
        'channels': tim_chan_pol[:, 1],
        'polarities': tim_chan_pol[:, 2]
    }
    if save:
        alf.io.save_object_npy(output_path, sync, '_spikeglx_sync')
    return sync
Exemple #4
0
def _rotary_encoder_positions_from_gray_code(channela, channelb):
    """
    Extracts the rotary encoder absolute position (cm) as function of time from digital recording
    of the 2 channels.

    Rotary Encoder implements X1 encoding: http://www.ni.com/tutorial/7109/en/
    rising A  & B high = +1
    rising A  & B low = -1
    falling A & B high = -1
    falling A & B low = +1

    :param channelA: Vector of rotary encoder digital recording channel A
    :type channelA: numpy array
    :param channelB: Vector of rotary encoder digital recording channel B
    :type channelB: numpy array
    :return: indices vector and position vector
    """
    # detect rising and falling fronts
    t, fronts = dsp.fronts(channela)
    # apply X1 logic to get positions in ticks
    p = (channelb[t] * 2 - 1) * fronts
    # convert position in cm
    p = np.cumsum(p) / WHEEL_TICKS * np.pi * WHEEL_RADIUS_CM
    return t, p