Пример #1
0
    def make(self, key):
        wheel_move_key = key.copy()

        eID = str((acquisition.Session & key).fetch1('session_uuid'))
        wheel_moves_intervals, wheel_moves_types = \
            ONE().load(eID, dataset_types=['_ibl_wheelMoves.intervals',
                                           '_ibl_wheelMoves.type'])

        wheel_moves_types = wheel_moves_types.columns

        assert len(np.unique(np.array([len(wheel_moves_intervals),
                                       len(wheel_moves_types)]))) == 1, \
            'Loaded wheel move files do not have the same length'

        key['wheel_move_number'] = len(wheel_moves_types)
        self.insert1(key)

        for idx_move in range(len(wheel_moves_types)):
            wheel_move_key['wheel_move_id'] = idx_move + 1
            wheel_move_key['wheel_move_start_time'] = \
                wheel_moves_intervals[idx_move, 0]
            wheel_move_key['wheel_move_end_time'] = \
                wheel_moves_intervals[idx_move, 1]

            wheel_move_type = wheel_moves_types[idx_move]
            if 'CCW' in wheel_move_type:
                wheel_move_key['wheel_move_type'] = 'CCW'
            elif 'flinch' in wheel_move_type:
                wheel_move_key['wheel_move_type'] = 'flinch'
            else:
                wheel_move_key['wheel_move_type'] = 'CW'

            self.WheelMove().insert1(wheel_move_key)

        logger.info('Populated a WheelMoveSet and all WheelMove tuples for \
            subject {subject_uuid} in session started at \
            {session_start_time}'.format(**key))
Пример #2
0
def load_spike_sorting(eid, one=None, dataset_types=None):
    """
    From an eid, hits the Alyx database and downloads a standard set of dataset types to perform
    analysis.
    :param eid:
    :param dataset_types: additional spikes/clusters objects to add to the standard list
    :return:
    """
    if not one:
        one = ONE()
    # This is a first draft, no safeguard, no error handling and a draft dataset list.
    session_path = one.path_from_eid(eid)
    dtypes = [
        'clusters.channels',
        'clusters.depths',
        'clusters.metrics',
        'spikes.clusters',
        'spikes.times',
        'probes.description',
    ]
    if dataset_types:
        dtypes = list(set(dataset_types + dtypes))

    _ = one.load(eid, dataset_types=dtypes, download_only=True)
    probes = alf.io.load_object(session_path.joinpath('alf'), 'probes')
    spikes = {}
    clusters = {}
    for i, _ in enumerate(probes['description']):
        probe_path = session_path.joinpath('alf',
                                           probes['description'][i]['label'])
        cluster = alf.io.load_object(probe_path, object='clusters')
        spike = alf.io.load_object(probe_path, object='spikes')
        label = probes['description'][i]['label']
        clusters[label] = cluster
        spikes[label] = spike

    return spikes, clusters
Пример #3
0
def get_example_images(eid):

    eids = get_repeated_sites()
    #    eid = eids[23]
    #    video_type = 'body'

    #eids = ['15f742e1-1043-45c9-9504-f1e8a53c1744']
    eids = ['4a45c8ba-db6f-4f11-9403-56e06a33dfa4']
    frts = {'body': 30, 'left': 60, 'right': 150}

    one = ONE()

    #for eid in eids:
    for video_type in frts:

        frame_idx = [20 * 60 * frts[video_type]]
        try:

            r = one.list(eid, 'dataset_types')
            recs = [
                x for x in r if f'{video_type}Camera.raw.mp4' in x['name']
            ][0]['file_records']
            video_path = [
                x['data_url'] for x in recs if x['data_url'] is not None
            ][0]

            frames = get_video_frames_preload(video_path,
                                              frame_idx,
                                              mask=np.s_[:, :, 0])
            np.save(
                '/home/mic/reproducible_dlc/example_images/'
                f'{eid}_{video_type}.npy', frames)
            print(eid, video_type, 'done')
        except:
            print(eid, video_type, 'error')
            continue
Пример #4
0
def get_ME(eid, video_type):

    #video_type = 'left'
    one = ONE()
    dataset_types = ['camera.ROIMotionEnergy', 'camera.times']
    a = one.list(eid, 'dataset-types')
    # for newer iblib version do [x['dataset_type'] for x in a]
    #    if not all([(u in [x['dataset_type'] for x in a]) for u in dataset_types]):
    #        print('not all data available')
    #        return

    one.load(eid, dataset_types=dataset_types)
    local_path = one.path_from_eid(eid)
    alf_path = local_path / 'alf'

    cam0 = alf.io.load_object(alf_path,
                              '%sCamera' % video_type,
                              namespace='ibl')

    ME = np.load(alf_path / f'{video_type}Camera.ROIMotionEnergy.npy')

    Times = cam0['times']

    return Times, ME
Пример #5
0
def get_dlc_XYs(eid, video_type):

    #video_type = 'left'
    one = ONE()
    dataset_types = ['camera.dlc', 'camera.times']
    a = one.list(eid, 'dataset-types')
    # for newer iblib version do [x['dataset_type'] for x in a]
    #    if not all([(u in [x['dataset_type'] for x in a]) for u in dataset_types]):
    #        print('not all data available')
    #        return

    one.load(eid, dataset_types=dataset_types)  #clobber=True # force download
    local_path = one.path_from_eid(eid)
    alf_path = local_path / 'alf'

    cam0 = alf.io.load_object(alf_path,
                              '%sCamera' % video_type,
                              namespace='ibl')

    Times = cam0['times']

    cam = cam0['dlc']
    points = np.unique(['_'.join(x.split('_')[:-1]) for x in cam.keys()])

    # Set values to nan if likelyhood is too low # for pqt: .to_numpy()
    XYs = {}
    for point in points:
        x = np.ma.masked_where(cam[point + '_likelihood'] < 0.9,
                               cam[point + '_x'])
        x = x.filled(np.nan)
        y = np.ma.masked_where(cam[point + '_likelihood'] < 0.9,
                               cam[point + '_y'])
        y = y.filled(np.nan)
        XYs[point] = np.array([x, y])

    return Times, XYs
Пример #6
0
    def make(self, key):

        eID = str((acquisition.Session & key).fetch1('session_uuid'))
        wheel_position, wheel_velocity, wheel_timestamps = \
            ONE().load(eID, dataset_types=['_ibl_wheel.position',
                                           '_ibl_wheel.velocity',
                                           '_ibl_wheel.timestamps'])

        wheel_sample_ids = wheel_timestamps[:, 0]
        wheel_timestamps = wheel_timestamps[:, 1]
        wheel_sampling_rate = 1 / np.median(np.diff(wheel_timestamps))

        key['wheel_position'] = wheel_position
        key['wheel_velocity'] = wheel_velocity
        key['wheel_sample_ids'] = wheel_sample_ids
        key['wheel_timestamps'] = wheel_timestamps
        key['wheel_start_time'] = wheel_timestamps[0]
        key['wheel_end_time'] = wheel_timestamps[-1]
        key['wheel_duration'] = wheel_timestamps[-1] - wheel_timestamps[0]
        key['wheel_sampling_rate'] = wheel_sampling_rate

        self.insert1(key)
        logger.info('Populated a Wheel tuple for subject {subject_uuid} \
            in session on {session_start_time}'.format(**key))
Пример #7
0
    def test_training_session(self, mock_ext, mock_meta):
        """
        Tests the full QC process for a training session.  Mock a load of things so we don't need
        the ful video file.
        :param mock_ext: mock cv.VideoCapture in camera extractor module
        :param mock_meta: mock get_video_meta
        :return:
        """
        n_samples = 100
        length = 107913
        eid, session_path = self.training
        self.frames = np.load(self.data_path / 'camera' / f'{eid}_frame_samples.npy')
        mock_meta.return_value = \
            Bunch({'length': length, **CameraQC.video_meta['training']['left']})
        mock_ext().get.return_value = length
        mock_ext().read.side_effect = self.side_effect()

        qc = CameraQC(session_path, 'left',
                      stream=False, n_samples=n_samples, one=ONE(offline=True))
        qc.load_data(download_data=False, extract_times=True)
        outcome, extended = qc.run(update=False)
        self.assertEqual('FAIL', outcome)
        expected = {
            '_videoLeft_brightness': 'FAIL',
            '_videoLeft_camera_times': ('PASS', 0),
            '_videoLeft_dropped_frames': ('PASS', 1, 0),
            '_videoLeft_file_headers': 'PASS',
            '_videoLeft_focus': 'FAIL',
            '_videoLeft_framerate': ('FAIL', 32.895),
            '_videoLeft_pin_state': ('WARNING', 1151, 0),
            '_videoLeft_position': 'FAIL',
            '_videoLeft_resolution': 'PASS',
            '_videoLeft_timestamps': 'PASS',
            '_videoLeft_wheel_alignment': ('FAIL', -95)
        }
        self.assertEqual(expected, extended)
Пример #8
0
    def make(self, key):

        eID = (acquisition.Session & key).fetch1('session_uuid')

        lick_times, lick_piezo_raw, lick_piezo_timestamps = \
            ONE().load(eID, dataset_types=['_ibl_licks.times', '_ibl_lickPiezo.raw', '_ibl_lickPiezo.timestamps'])

        lick_sample_ids = lick_piezo_timestamps[:, 0]
        lick_piezo_timestamps = lick_piezo_timestamps[:, 1]

        key['lick_times'] = lick_times
        key['lick_piezo_raw'] = lick_piezo_raw
        key['lick_sample_ids'] = lick_sample_ids
        key['lick_piezo_timestamps'] = lick_piezo_timestamps
        key['lick_start_time'] = lick_piezo_timestamps[0]
        key['lick_end_time'] = lick_piezo_timestamps[-1]
        key['lick_sampling_rate'] = 1 / np.median(
            np.diff(lick_piezo_timestamps))

        self.insert1(key)

        logger.info(
            'Populated a Lick tuple for subject {subject_nickname} in session started at {session_start_time}'
            .format(**key))
Пример #9
0
    def make(self, key):
        spon_time_key = key.copy()

        eID = str((acquisition.Session & key).fetch1('session_uuid'))

        spontaneous_intervals = \
            ONE().load(eID, dataset_types=['_ibl_spontaneous.intervals'])

        key['spontaneous_time_total_num'] = len(spontaneous_intervals)
        self.insert1(key)

        for idx_spon in range(len(spontaneous_intervals)):
            spon_time_key['spontaneous_time_id'] = idx_spon + 1
            spon_time_key['spontaneous_start_time'] = \
                spontaneous_intervals[idx_spon, 0]
            spon_time_key['spontaneous_end_time'] = \
                spontaneous_intervals[idx_spon, 1]
            spon_time_key['spontaneous_time_duration'] = \
                float(np.diff(spontaneous_intervals[idx_spon, :]))
            self.SpontaneousTime().insert1(spon_time_key)

        logger.info('Populated a SpontaneousTimeSet tuple and all \
            Spontaneoustime tuples for subject {subject_uuid} in \
                session started at {session_start_time}'.format(**key))
Пример #10
0
 def setUpClass(cls) -> None:
     """Load a few 10 second videos for testing the various video QC checks"""
     data_path = base.IntegrationTest.default_data_root()
     video_path = data_path.joinpath('camera')
     videos = sorted(video_path.rglob('*.mp4'))
     # Instantiate using session with a video path to fool constructor.
     # To remove once we use ONE cache file
     one = ONE(base_url='https://test.alyx.internationalbrainlab.org',
               username='******',
               password='******')
     dummy_id = 'd3372b15-f696-4279-9be5-98f15783b5bb'
     qc = CameraQC(dummy_id, 'left',
                   n_samples=10, stream=False, download_data=False, one=one)
     qc.one = None
     qc._type = 'ephys'  # All videos come from ephys sessions
     qcs = OrderedDict()
     for video in videos:
         qc.video_path = video
         qc.label = vidio.label_from_path(video)
         qc.n_samples = 10
         qc.load_video_data()
         qcs[video] = qc.data.copy()
     cls.qc = qc
     cls.data = qcs
With EXAMPLE_OVERWRITE = True, the script downloads an example dataset and runs
the registration (used for automatic testing of the example).
'''
# Author: Olivier, Gaelle

from ibllib.pipes import histology
from oneibl.one import ONE
from pathlib import Path

# ======== EDIT FOR USERS ====

# Edit so as to reflect the directory containing your electrode tracks
path_tracks = "/Users/gaelle/Downloads/Flatiron/examples/00_to_add"


EXAMPLE_OVERWRITE = True  # Put to False when wanting to run the script on your data

ALYX_URL = "https://dev.alyx.internationalbrainlab.org"  # FOR TESTING
# ALYX_URL = "https://alyx.internationalbrainlab.org"  # UNCOMMENT WHEN READY

# ======== DO NOT EDIT BELOW ====
one = ONE(base_url=ALYX_URL)

if EXAMPLE_OVERWRITE:
    # TODO Olivier : Function to download examples folder
    cachepath = Path(one._par.CACHE_DIR)
    path_tracks = cachepath.joinpath('examples', 'histology', 'tracks_to_add')

histology.register_track_files(path_tracks=path_tracks, one=one, overwrite=True)
histology.detect_missing_histology_tracks(path_tracks=path_tracks, one=one)
Пример #12
0
# loading and plotting functions
from define_paths import fig_path
from behavior_plots import *
# from load_mouse_data import * # this has all plotting functions

## INITIALIZE A FEW THINGS
sns.set_style("darkgrid", {
    'xtick.bottom': True,
    'ytick.left': True,
    'lines.markeredgewidth': 0
})
sns.set_context(context="paper")
sns.set_palette("colorblind")  # palette for water types

## CONNECT TO ONE
one = ONE()  # initialize

# get folder to save plots
path = fig_path()
path = os.path.join(path, 'per_lab/')
if not os.path.exists(path):
    os.mkdir(path)

users = [
    'danlab', 'angelakilab', 'wittenlab', 'churchlandlab', 'mainenlab',
    'mrsicflogellab'
]

# ============================================= #
# START BIG OVERVIEW PLOT
# ============================================= #
Пример #13
0
from . import acquisition, reference, behavior
import numpy as np
try:
    from oneibl.one import ONE
except:
    pass

mode = environ.get('MODE')

if mode == 'update':
    schema = dj.schema('ibl_ephys')
else:
    schema = dj.schema(dj.config.get('database.prefix', '') + 'ibl_ephys')

try:
    one = ONE()
except:
    pass


@schema
class Ephys(dj.Imported):
    definition = """
    -> acquisition.Session
    ---
    ephys_raw_dir=null:         varchar(256) # Path of Raw ephys file: array of size nSamples * nChannels. Channels from all probes are included. NOTE: this is huge, and hardly even used. To allow people to load it, we need to add slice capabilities to ONE
    ephys_timestamps=null:      longblob     # Timestamps for raw ephys timeseries (seconds)
    ephys_start_time=null:      float        # (seconds)
    ephys_stop_time=null:       float        # (seconds)
    ephys_duration=null:        float        # (seconds)
    ephys_sampling_rate=null:   float        # samples per second
Пример #14
0
def load_trials_df(eid,
                   one=None,
                   maxlen=None,
                   t_before=0.,
                   t_after=0.,
                   ret_wheel=False,
                   ret_abswheel=False,
                   wheel_binsize=0.02):
    """
    Generate a pandas dataframe of per-trial timing information about a given session.
    Each row in the frame will correspond to a single trial, with timing values indicating timing
    session-wide (i.e. time in seconds since session start). Can optionally return a resampled
    wheel velocity trace of either the signed or absolute wheel velocity.

    The resulting dataframe will have a new set of columns, trial_start and trial_end, which define
    via t_before and t_after the span of time assigned to a given trial.
    (useful for bb.modeling.glm)

    Parameters
    ----------
    eid : str
        Session UUID string to pass to ONE
    one : oneibl.one.OneAlyx, optional
        one object to use for loading. Will generate internal one if not used, by default None
    maxlen : float, optional
        Maximum trial length for inclusion in df. Trials where feedback - response is longer
        than this value will not be included in the dataframe, by default None
    t_before : float, optional
        Time before stimulus onset to include for a given trial, as defined by the trial_start
        column of the dataframe. If zero, trial_start will be identical to stimOn, by default 0.
    t_after : float, optional
        Time after feedback to include in the trail, as defined by the trial_end
        column of the dataframe. If zero, trial_end will be identical to feedback, by default 0.
    ret_wheel : bool, optional
        Whether to return the time-resampled wheel velocity trace, by default False
    ret_abswheel : bool, optional
        Whether to return the time-resampled absolute wheel velocity trace, by default False
    wheel_binsize : float, optional
        Time bins to resample wheel velocity to, by default 0.02

    Returns
    -------
    pandas.DataFrame
        Dataframe with trial-wise information. Indices are the actual trial order in the original
        data, preserved even if some trials do not meet the maxlen criterion. As a result will not
        have a monotonic index. Has special columns trial_start and trial_end which define start
        and end times via t_before and t_after
    """
    if not one:
        one = ONE()

    if ret_wheel and ret_abswheel:
        raise ValueError('ret_wheel and ret_abswheel cannot both be true.')

    # Define which datatypes we want to pull out
    trialstypes = [
        'trials.choice',
        'trials.probabilityLeft',
        'trials.feedbackType',
        'trials.feedback_times',
        'trials.contrastLeft',
        'trials.contrastRight',
        'trials.goCue_times',
        'trials.stimOn_times',
    ]

    # A quick function to remap probabilities in those sessions where it was not computed correctly
    def remap_trialp(probs):
        # Block probabilities in trial data aren't accurate and need to be remapped
        validvals = np.array([0.2, 0.5, 0.8])
        diffs = np.abs(np.array([x - validvals for x in probs]))
        maps = diffs.argmin(axis=1)
        return validvals[maps]

    starttimes = one.load(eid, dataset_types=['trials.stimOn_times'])[0]
    endtimes = one.load(eid, dataset_types=['trials.feedback_times'])[0]
    tmp = one.load(eid, dataset_types=trialstypes)

    if maxlen is not None:
        with np.errstate(invalid='ignore'):
            keeptrials = (endtimes - starttimes) <= maxlen
    else:
        keeptrials = range(len(starttimes))
    trialdata = {
        x.split('.')[1]: tmp[i][keeptrials]
        for i, x in enumerate(trialstypes)
    }
    trialdata['probabilityLeft'] = remap_trialp(trialdata['probabilityLeft'])
    trialsdf = pd.DataFrame(trialdata)
    if maxlen is not None:
        trialsdf.set_index(np.nonzero(keeptrials)[0], inplace=True)
    trialsdf['trial_start'] = trialsdf['stimOn_times'] - t_before
    trialsdf['trial_end'] = trialsdf['feedback_times'] + t_after
    if not ret_wheel and not ret_abswheel:
        return trialsdf

    wheel = one.load_object(eid, 'wheel')
    whlpos, whlt = wheel.position, wheel.timestamps
    starttimes = trialsdf['trial_start']
    endtimes = trialsdf['trial_end']
    wh_endlast = 0
    trials = []
    for (start, end) in np.vstack((starttimes, endtimes)).T:
        wh_startind = np.searchsorted(whlt[wh_endlast:], start) + wh_endlast
        wh_endind = np.searchsorted(whlt[wh_endlast:], end,
                                    side='right') + wh_endlast + 4
        wh_endlast = wh_endind
        tr_whlpos = whlpos[wh_startind - 1:wh_endind + 1]
        tr_whlt = whlt[wh_startind - 1:wh_endind + 1] - start
        tr_whlt[0] = 0.  # Manual previous-value interpolation
        whlseries = TimeSeries(tr_whlt, tr_whlpos, columns=['whlpos'])
        whlsync = sync(wheel_binsize, timeseries=whlseries, interp='previous')
        trialstartind = np.searchsorted(whlsync.times, 0)
        trialendind = np.ceil((end - start) / wheel_binsize).astype(int)
        trpos = whlsync.values[trialstartind:trialendind + trialstartind]
        whlvel = trpos[1:] - trpos[:-1]
        whlvel = np.insert(whlvel, 0, 0)
        if np.abs((trialendind - len(whlvel))) > 0:
            raise IndexError(
                'Mismatch between expected length of wheel data and actual.')
        if ret_wheel:
            trials.append(whlvel)
        elif ret_abswheel:
            trials.append(np.abs(whlvel))
    trialsdf['wheel_velocity'] = trials
    return trialsdf
Пример #15
0
def load_spike_sorting(eid,
                       one=None,
                       probe=None,
                       dataset_types=None,
                       force=False):
    """
    From an eid, hits the Alyx database and downloads a standard default set of dataset types
    From a local session Path (pathlib.Path), loads a standard default set of dataset types
     to perform analysis:
        'clusters.channels',
        'clusters.depths',
        'clusters.metrics',
        'spikes.clusters',
        'spikes.times',
        'probes.description'
    :param eid: experiment UUID or pathlib.Path of the local session
    :param one:
    :param probe: name of probe to load in, if not given all probes for session will be loaded
    :param dataset_types: additional spikes/clusters objects to add to the standard default list
    :param force: by default function looks for data on local computer and loads this in. If you
    want to connect to database and make sure files are still the same set force=True
    :return: spikes, clusters (dict of bunch, 1 bunch per probe)
    """
    if isinstance(eid, Path):
        # Do everything locally without ONE
        session_path = eid
        if isinstance(probe, str):
            labels = [probe]
        else:
            probes = alf.io.load_object(session_path.joinpath('alf'), 'probes')
            labels = [pr['label'] for pr in probes['description']]
        spikes = Bunch({})
        clusters = Bunch({})
        for label in labels:
            _spikes, _clusters = _load_spike_sorting_local(session_path, label)
            spikes[label] = _spikes
            clusters[label] = _clusters

        return spikes, clusters

    else:
        session_path = one.path_from_eid(eid)
        if not session_path:
            logger.warning('Session not found')
            return (None, None), 'no session path'

        one = one or ONE()
        dtypes_default = [
            'clusters.channels', 'clusters.depths', 'clusters.metrics',
            'spikes.clusters', 'spikes.times', 'probes.description'
        ]
        if dataset_types is None:
            dtypes = dtypes_default
        else:
            # Append extra optional DS
            dtypes = list(set(dataset_types + dtypes_default))

        if isinstance(probe, str):
            labels = [probe]
        else:
            insertions = one.alyx.rest('insertions', 'list', session=eid)
            labels = [ins['name'] for ins in insertions]

        spikes = Bunch({})
        clusters = Bunch({})
        for label in labels:
            _spikes, _clusters = _load_spike_sorting_local(session_path, label)
            spike_dtypes = [sp for sp in dtypes if 'spikes.' in sp]
            spike_local = ['spikes.' + sp for sp in list(_spikes.keys())]
            spike_exists = all([sp in spike_local for sp in spike_dtypes])
            cluster_dtypes = [cl for cl in dtypes if 'clusters.' in cl]
            cluster_local = ['clusters.' + cl for cl in list(_clusters.keys())]
            cluster_exists = all(
                [cl in cluster_local for cl in cluster_dtypes])

            if not spike_exists or not cluster_exists or force:
                logger.info(
                    f'Did not find local files for spikes and clusters for {session_path} '
                    f'and {label}. Downloading....')
                one.load(eid, dataset_types=dtypes, download_only=True)
                _spikes, _clusters = _load_spike_sorting_local(
                    session_path, label)
                if not _spikes:
                    logger.warning(
                        f'Could not load spikes datasets for session {session_path} and {label}. '
                        f'Spikes for {probe} will return an empty dict')
                else:
                    spikes[label] = _spikes
                if not _clusters:
                    logger.warning(
                        f'Could not load clusters datasets for session {session_path} and {label}.'
                        f' Clusters for {label} will return an empty dict')
                else:
                    clusters[label] = _clusters
            else:
                logger.info(
                    f'Local files for spikes and clusters for {session_path} '
                    f'and {label} found. To re-download set force=True')

                spikes[label] = _spikes
                clusters[label] = _clusters

        return spikes, clusters
Пример #16
0
 def setUpClass(cls) -> None:
     cls.one = ONE(
         base_url="https://test.alyx.internationalbrainlab.org",
         username="******",
         password="******"
     )
Пример #17
0
def check_wheel_angle(eid):

    Plot = True

    one = ONE()
    #eid = 'e1023140-50c1-462a-b80e-5e05626d7f0e' # at least 9 bad cases

    #eid = one.search(subject='ZM_2104', date='2019-09-19', number=1)
    Dataset_types = [
        'wheel.position', 'wheel.timestamps', 'trials.feedback_times',
        'trials.feedbackType'
    ]

    D = one.load(eid,
                 dataset_types=Dataset_types,
                 clobber=False,
                 download_only=True)
    session_path = Path(D[0]).parent

    wheel = alf.io.load_object(session_path, 'wheel')
    trials = alf.io.load_object(session_path, 'trials')
    reward_success = trials['feedback_times'][trials['feedbackType'] == 1]
    reward_failure = trials['feedback_times'][trials['feedbackType'] == -1]

    if Plot:
        plt.plot(wheel['times'], wheel['position'], linestyle='', marker='o')

        #iblplt.vertical_lines(trials['stimOn_times'], ymin=-100, ymax=100,
        #                      color='r', linewidth=0.5, label='stimOn_times')

        #iblplt.vertical_lines(reward_failure, ymin=-100, ymax=100,
        #                      color='b', linewidth=0.5, label='reward_failure')

        iblplt.vertical_lines(reward_success,
                              ymin=-100,
                              ymax=100,
                              color='k',
                              linewidth=0.5,
                              label='reward_success')

        plt.legend()
        plt.xlabel('time [sec]')
        plt.ylabel('wheel linear displacement [cm]')
        plt.show()

    # get fraction of reward deliveries with silent wheel time_delay before the reward
    time_delay = 0.5

    bad_cases1 = []
    for rew in reward_success:

        left = wheel['times'][find_nearest(wheel['times'], rew - time_delay)]
        right = wheel['times'][find_nearest(wheel['times'], rew)]

        if left == right:
            if left < rew - time_delay:
                bad_cases1.append(rew)

    if len(bad_cases1) == 0:
        print('Good news, no impossible case found.')
    else:
        print('Bad news, at least one impossible case found.')
        return len(bad_cases1)
Пример #18
0
    def make(self, key):
        trial_key = key.copy()
        eID = str((acquisition.Session & key).fetch1('session_uuid'))

        trials_feedback_times, trials_feedback_types, trials_intervals, \
            trials_response_choice, trials_response_times, \
            trials_contrast_left, trials_contrast_right, trials_p_left = \
            ONE().load(eID, dataset_types=['_ibl_trials.feedback_times',
                                           '_ibl_trials.feedbackType',
                                           '_ibl_trials.intervals',
                                           '_ibl_trials.choice',
                                           '_ibl_trials.response_times',
                                           '_ibl_trials.contrastLeft',
                                           '_ibl_trials.contrastRight',
                                           '_ibl_trials.probabilityLeft'])

        stim_on_times_status, rep_num_status, included_status = \
            (CompleteTrialSession & key).fetch1(
                'stim_on_times_status', 'rep_num_status', 'included_status')

        lab_name = (subject.SubjectLab & key).fetch1('lab_name')
        if stim_on_times_status != 'Missing':
            if lab_name == 'wittenlab':
                trials_visual_stim_times = np.squeeze(ONE().load(
                    eID,
                    dataset_types='_ibl_trials.stimOn_times',
                    clobber=True))
            else:
                trials_visual_stim_times = ONE().load(
                    eID, dataset_types='_ibl_trials.stimOn_times')

            if len(trials_visual_stim_times) == 1:
                trials_visual_stim_times = np.squeeze(trials_visual_stim_times)

        if rep_num_status != 'Missing':
            trials_rep_num = np.squeeze(ONE().load(
                eID, dataset_types='_ibl_trials.repNum'))

        if included_status != 'Missing':
            trials_included = np.squeeze(ONE().load(
                eID, dataset_types='_ibl_trials.included'))

        assert len(
            np.unique(
                np.array([
                    len(trials_feedback_times),
                    len(trials_feedback_types),
                    len(trials_intervals),
                    # len(trials_rep_num),
                    len(trials_response_choice),
                    len(trials_response_times),
                    len(trials_contrast_left),
                    len(trials_contrast_right),
                    # len(trials_visual_stim_times),
                    # len(trials_included),
                    len(trials_p_left)
                ]))) == 1
        'Loaded trial files do not have the same length'

        key['n_trials'] = len(trials_response_choice)

        key_session = dict()
        key_session['model'] = 'actions.session'
        key_session['uuid'] = (acquisition.Session
                               & key).fetch1('session_uuid')

        n_correct_trials = grf(key_session, 'n_correct_trials')
        if n_correct_trials != 'None':
            key['n_correct_trials'] = n_correct_trials
        else:
            key['n_correct_trials'] = \
                sum((np.squeeze(trials_response_choice) == 1) &
                    (np.squeeze(trials_contrast_left) > 0)) \
                + sum((np.squeeze(trials_response_choice) == -1) &
                      (np.squeeze(trials_contrast_right) > 0))

        key['trials_start_time'] = trials_intervals[0, 0]
        key['trials_end_time'] = trials_intervals[-1, 1]

        self.insert1(key)

        for idx_trial in range(len(trials_response_choice)):

            if np.isnan(trials_contrast_left[idx_trial]):
                trial_stim_contrast_left = 0
            else:
                trial_stim_contrast_left = trials_contrast_left[idx_trial]

            if np.isnan(trials_contrast_right[idx_trial]):
                trial_stim_contrast_right = 0
            else:
                trial_stim_contrast_right = trials_contrast_right[idx_trial]

            if trials_response_choice[idx_trial] == -1:
                trial_response_choice = "CCW"
            elif trials_response_choice[idx_trial] == 0:
                trial_response_choice = "No Go"
            elif trials_response_choice[idx_trial] == 1:
                trial_response_choice = "CW"
            else:
                raise ValueError('Invalid reponse choice.')

            trial_key['trial_id'] = idx_trial + 1
            trial_key['trial_start_time'] = trials_intervals[idx_trial, 0]
            trial_key['trial_end_time'] = trials_intervals[idx_trial, 1]
            trial_key['trial_response_time'] = float(
                trials_response_times[idx_trial])
            trial_key['trial_response_choice'] = trial_response_choice

            if stim_on_times_status != 'Missing':
                trial_key['trial_stim_on_time'] = trials_visual_stim_times[
                    idx_trial]

            trial_key['trial_stim_contrast_left'] = float(
                trial_stim_contrast_left)
            trial_key['trial_stim_contrast_right'] = float(
                trial_stim_contrast_right)
            trial_key['trial_feedback_time'] = float(
                trials_feedback_times[idx_trial])
            trial_key['trial_feedback_type'] = int(
                trials_feedback_types[idx_trial])

            if rep_num_status != 'Missing':
                trial_key['trial_rep_num'] = int(trials_rep_num[idx_trial])

            trial_key['trial_stim_prob_left'] = float(trials_p_left[idx_trial])

            if included_status != 'Missing':
                trial_key['trial_included'] = bool(trials_included[idx_trial])

            self.Trial().insert1(trial_key)

        logger.info('Populated a TrialSet tuple, \
            all Trial tuples and Excluded Trial tuples for \
            subject {subject_uuid} in session started at \
            {session_start_time}'.format(**key))
Пример #19
0
def register(root_data_folder, dry=False):
    # registration part
    one = ONE(base_url='https://alyx.internationalbrainlab.org')
    rc = RegistrationClient(one=one)
    rc.register_sync(root_data_folder, dry=dry)
Пример #20
0
def create_alyx_probe_insertions(
    session_path: str,
    force: bool = False,
    one: object = None,
    model: str = None,
    labels: list = None,
):
    if one is None:
        one = ONE()
    if is_uuid_string(session_path):
        eid = session_path
    else:
        eid = one.eid_from_path(session_path)
    if eid is None:
        print(
            "Session not found on Alyx: please create session before creating insertions"
        )
    if model is None:
        probe_model = spikeglx.get_neuropixel_version_from_folder(session_path)
        pmodel = "3B2" if probe_model == "3B" else probe_model
    else:
        pmodel = model
    raw_ephys_data_path = Path(session_path) / "raw_ephys_data"
    if labels is None:
        probe_labels = [
            x.name for x in Path(raw_ephys_data_path).glob("*")
            if x.is_dir() and ("00" in x.name or "01" in x.name)
        ]
    else:
        probe_labels = labels

    # create the qc fields in the json field
    qc_dict = {}
    qc_dict.update({"qc": "NOT_SET"})
    qc_dict.update({"extended_qc": {}})

    # create the dictionary
    for plabel in probe_labels:
        insdict = {
            "session": eid,
            "name": plabel,
            "model": pmodel,
            "json": qc_dict
        }
        # search for the corresponding insertion in Alyx
        alyx_insertion = one.alyx.rest("insertions",
                                       "list",
                                       session=insdict["session"],
                                       name=insdict["name"])
        # if it doesn't exist, create it
        if len(alyx_insertion) == 0:
            alyx_insertion = one.alyx.rest("insertions",
                                           "create",
                                           data=insdict)
        else:
            iid = alyx_insertion[0]["id"]
            if force:
                alyx_insertion = one.alyx.rest("insertions",
                                               "update",
                                               id=iid,
                                               data=insdict)
            else:
                alyx_insertion = alyx_insertion[0]
Пример #21
0
import unittest
import numpy as np
import requests
from pathlib import Path

from alf.io import remove_uuid_file
from oneibl.one import ONE

one = ONE(base_url='https://test.alyx.internationalbrainlab.org',
          username='******',
          password='******')


class TestSearch(unittest.TestCase):
    def setUp(self):
        # Init connection to the database
        self.One = one

    def test_search_simple(self):
        one = self.One
        # Test users
        usr = ['olivier', 'nbonacchi']
        sl, sd = one.search(users=usr, details=True)
        self.assertTrue(isinstance(sl, list) and isinstance(sd, list))
        self.assertTrue(
            all([set(usr).issubset(set(u)) for u in [s['users'] for s in sd]]))
        # when the user is a string instead of a list
        sl1, sd1 = one.search(users=['olivier'], details=True)
        sl2, sd2 = one.search(users='olivier', details=True)
        self.assertTrue(sl1 == sl2 and sd1 == sd2)
        ses = one.search(users='olivier', number=6)
Пример #22
0
    (behavior.TrialSet.Trial & 'trial_go_cue_time is NULL') & \
    'go_cue_times_status = "Complete"'
n_go_cue = len(trial_sets_go_cue)

trial_sets_go_cue_trigger = behavior.CompleteTrialSession & \
    (behavior.TrialSet.Trial & 'trial_go_cue_trigger_time is NULL') & \
    'go_cue_trigger_times_status = "Complete"'
n_go_cue_trigger = len(trial_sets_go_cue_trigger)


if len(trial_sets_go_cue):
    for ikey, key in enumerate(trial_sets_go_cue.fetch('KEY')):
        # download data
        try:
            eID = str((acquisition.Session & key).fetch1('session_uuid'))
            go_cue_times = np.squeeze(ONE().load(
                eID, dataset_types='_ibl_trials.goCue_times'))

            # update go cue time value
            trials = behavior.TrialSet.Trial & key & \
                'trial_go_cue_time is NULL'
            for trial in trials.fetch('KEY'):
                dj.Table._update(
                    behavior.TrialSet.Trial & trial, 'trial_go_cue_time',
                    go_cue_times[trial['trial_id']-1])

            if ikey % 100 == 0:
                print('Go Cue entry number: {}/{}'.format(ikey, n_go_cue))
        except:
            print(key)

Пример #23
0
rot_mat[0, 1] = sca_rot_mat[0, 1] / sy
rot_mat[1, 1] = sca_rot_mat[1, 1] / sy
rot_mat[2, 1] = sca_rot_mat[2, 1] / sy

rot_mat[0, 2] = sca_rot_mat[0, 2] / sz
rot_mat[1, 2] = sca_rot_mat[1, 2] / sz
rot_mat[2, 2] = sca_rot_mat[2, 2] / sz

# extract individual rotations in x y z:
rx = math.atan2(rot_mat[2, 1], rot_mat[2, 2])
ry = math.atan2((-rot_mat[2, 0]),
                math.sqrt(((rot_mat[2, 1]**2) + (rot_mat[2, 2]**2))))
rz = math.atan2(rot_mat[1, 0], rot_mat[0, 0])

# Upload to IBL alyx:
one = ONE(base_url='https://dev.alyx.internationalbrainlab.org')

TASK_PROTOCOL = 'SWC_Histology_Serial2P_v0.0.1'

json_note = {
    'sample_reception_date': ibllib.time.date2isostr(sample_reception_date),
    'elastix_affine_transform': affine_matrix,
    'tilt': rx,
    'yaw': ry,
    'roll': rz,
    'dv_scale': sy,
    'ap_scale': sz,
    'ml_scale': sx
}

# use dump() to properly encode np array:
Пример #24
0
 def setUp(self):
     # Init connection to the database
     one = ONE(base_url='https://test.alyx.internationalbrainlab.org',
               username='******',
               password='******')
     self.One = one
Пример #25
0
def load_channel_locations(eid, one=None, probe=None, aligned=False):
    """
    From an eid, get brain locations from Alyx database
    analysis.
    :param eid: session eid or dictionary returned by one.alyx.rest('sessions', 'read', id=eid)
    :param dataset_types: additional spikes/clusters objects to add to the standard list
    :return: channels
    """
    if isinstance(eid, dict):
        ses = eid
        eid = ses['url'][-36:]

    one = one or ONE()

    # When a specific probe has been requested
    if isinstance(probe, str):
        insertions = one.alyx.rest('insertions',
                                   'list',
                                   session=eid,
                                   name=probe)[0]
        labels = [probe]
        if not insertions['json']:
            tracing = [False]
            resolved = [False]
            counts = [0]
        else:
            tracing = [(insertions.get('json', {
                'temp': 0
            }).get('extended_qc', {
                'temp': 0
            }).get('tracing_exists', False))]
            resolved = [(insertions.get('json', {
                'temp': 0
            }).get('extended_qc', {
                'temp': 0
            }).get('alignment_resolved', False))]
            counts = [(insertions.get('json', {
                'temp': 0
            }).get('extended_qc', {
                'temp': 0
            }).get('alignment_count', 0))]
        probe_id = [insertions['id']]
    # No specific probe specified, load any that is available
    # Need to catch for the case where we have two of the same probe insertions
    else:
        insertions = one.alyx.rest('insertions', 'list', session=eid)
        labels = [ins['name'] for ins in insertions]
        try:
            tracing = [
                ins.get('json', {
                    'temp': 0
                }).get('extended_qc', {
                    'temp': 0
                }).get('tracing_exists', False) for ins in insertions
            ]
            resolved = [
                ins.get('json', {
                    'temp': 0
                }).get('extended_qc', {
                    'temp': 0
                }).get('alignment_resolved', False) for ins in insertions
            ]
            counts = [
                ins.get('json', {
                    'temp': 0
                }).get('extended_qc', {
                    'temp': 0
                }).get('alignment_count', 0) for ins in insertions
            ]
        except Exception:
            tracing = [False for ins in insertions]
            resolved = [False for ins in insertions]
            counts = [0 for ins in insertions]

        probe_id = [ins['id'] for ins in insertions]

    channels = Bunch({})
    r = BrainRegions()
    for label, trace, resol, count, id in zip(labels, tracing, resolved,
                                              counts, probe_id):
        if trace:
            if resol:
                logger.info(
                    f'Channel locations for {label} have been resolved. '
                    f'Channel and cluster locations obtained from ephys aligned histology '
                    f'track.')
                # download the data
                chans = one.load_object(eid,
                                        'channels',
                                        collection=f'alf/{label}')

                # If we have successfully downloaded the data
                if 'brainLocationIds_ccf_2017' in chans.keys():

                    channels[label] = Bunch({
                        'atlas_id':
                        chans['brainLocationIds_ccf_2017'],
                        'acronym':
                        r.get(chans['brainLocationIds_ccf_2017'])['acronym'],
                        'x':
                        chans['mlapdv'][:, 0] / 1e6,
                        'y':
                        chans['mlapdv'][:, 1] / 1e6,
                        'z':
                        chans['mlapdv'][:, 2] / 1e6,
                        'axial_um':
                        chans['localCoordinates'][:, 1],
                        'lateral_um':
                        chans['localCoordinates'][:, 0]
                    })
                # Otherwise we just get the channels from alyx. Shouldn't happen often, only if
                # data is still inbetween ftp and flatiron after being resolved
                else:
                    traj_id = one.alyx.rest(
                        'trajectories',
                        'list',
                        session=eid,
                        probe=label,
                        provenance='Ephys aligned histology track')[0]['id']
                    chans = one.alyx.rest('channels',
                                          'list',
                                          trajectory_estimate=traj_id)

                    channels[label] = Bunch({
                        'atlas_id':
                        np.array([ch['brain_region'] for ch in chans]),
                        'x':
                        np.array([ch['x'] for ch in chans]) / 1e6,
                        'y':
                        np.array([ch['y'] for ch in chans]) / 1e6,
                        'z':
                        np.array([ch['z'] for ch in chans]) / 1e6,
                        'axial_um':
                        np.array([ch['axial'] for ch in chans]),
                        'lateral_um':
                        np.array([ch['lateral'] for ch in chans])
                    })
                    channels[label]['acronym'] = r.get(
                        channels[label]['atlas_id'])['acronym']

            elif count > 0 and aligned:
                logger.info(
                    f'Channel locations for {label} have not been '
                    f'resolved. However, alignment flag set to True so channel and cluster'
                    f' locations will be obtained from latest available ephys aligned '
                    f'histology track.')
                # get the latest user aligned channels
                traj_id = one.alyx.rest(
                    'trajectories',
                    'list',
                    session=eid,
                    probe=label,
                    provenance='Ephys aligned histology track')[0]['id']
                chans = one.alyx.rest('channels',
                                      'list',
                                      trajectory_estimate=traj_id)

                channels[label] = Bunch({
                    'atlas_id':
                    np.array([ch['brain_region'] for ch in chans]),
                    'x':
                    np.array([ch['x'] for ch in chans]) / 1e6,
                    'y':
                    np.array([ch['y'] for ch in chans]) / 1e6,
                    'z':
                    np.array([ch['z'] for ch in chans]) / 1e6,
                    'axial_um':
                    np.array([ch['axial'] for ch in chans]),
                    'lateral_um':
                    np.array([ch['lateral'] for ch in chans])
                })
                channels[label]['acronym'] = r.get(
                    channels[label]['atlas_id'])['acronym']
            else:
                logger.info(
                    f'Channel locations for {label} have not been resolved. '
                    f'Channel and cluster locations obtained from histology track.'
                )
                # get the channels from histology tracing
                traj_id = one.alyx.rest('trajectories',
                                        'list',
                                        session=eid,
                                        probe=label,
                                        provenance='Histology track')[0]['id']
                chans = one.alyx.rest('channels',
                                      'list',
                                      trajectory_estimate=traj_id)

                channels[label] = Bunch({
                    'atlas_id':
                    np.array([ch['brain_region'] for ch in chans]),
                    'x':
                    np.array([ch['x'] for ch in chans]) / 1e6,
                    'y':
                    np.array([ch['y'] for ch in chans]) / 1e6,
                    'z':
                    np.array([ch['z'] for ch in chans]) / 1e6,
                    'axial_um':
                    np.array([ch['axial'] for ch in chans]),
                    'lateral_um':
                    np.array([ch['lateral'] for ch in chans])
                })
                channels[label]['acronym'] = r.get(
                    channels[label]['atlas_id'])['acronym']
        else:
            logger.warning(f'Histology tracing for {label} does not exist. '
                           f'No channels for {label}')

    return channels
Пример #26
0
def Viewer(eid, video_type, trial_range, save_video=True, eye_zoom=False):
    '''
    eid: session id, e.g. '3663d82b-f197-4e8b-b299-7b803a155b84'
    video_type: one of 'left', 'right', 'body'
    trial_range: first and last trial number of range to be shown, e.g. [5,7]
    save_video: video is displayed and saved in local folder

    Example usage to view and save labeled video with wheel angle:
    Viewer('3663d82b-f197-4e8b-b299-7b803a155b84', 'left', [5,7])
    3D example: 'cb2ad999-a6cb-42ff-bf71-1774c57e5308', [5,7]
    '''

    save_vids_here = '/home/mic/'
    if save_vids_here[-1] != '/':
        return 'Last character of save_vids_here must be slash'

    one = ONE()
    dataset_types = [
        'camera.times', 'wheel.position', 'wheel.timestamps',
        'trials.intervals', 'camera.dlc'
    ]

    a = one.list(eid, 'dataset-types')

    assert all([i in a for i in dataset_types
                ]), 'For this eid, not all data available'

    D = one.load(eid, dataset_types=dataset_types, dclass_output=True)
    alf_path = Path(D.local_path[0]).parent.parent / 'alf'

    # Download a single video
    video_data = alf_path.parent / 'raw_video_data'
    download_raw_video(eid, cameras=[video_type])
    video_path = list(video_data.rglob('_iblrig_%sCamera.raw.*' %
                                       video_type))[0]
    print(video_path)

    # that gives cam time stamps and DLC output (change to alf_path eventually)

    cam = alf.io.load_object(alf_path,
                             '%sCamera' % video_type,
                             namespace='ibl')

    # just to read in times for newer data (which has DLC results in pqt format
    # cam = alf.io.load_object(alf_path, '_ibl_%sCamera' % video_type)

    # set where to read and save video and get video info
    cap = cv2.VideoCapture(video_path.as_uri())
    length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    fps = cap.get(cv2.CAP_PROP_FPS)
    size = (int(cap.get(3)), int(cap.get(4)))

    assert length < len(cam['times']), '#frames > #stamps'
    print(eid, ', ', video_type, ', fsp:', fps, ', #frames:', length,
          ', #stamps:', len(cam['times']), ', #frames - #stamps = ',
          length - len(cam['times']))

    # pick trial range for which to display stuff
    trials = alf.io.load_object(alf_path, 'trials', namespace='ibl')
    num_trials = len(trials['intervals'])
    if trial_range[-1] > num_trials - 1:
        print('There are only %s trials' % num_trials)

    frame_start = find_nearest(cam['times'],
                               [trials['intervals'][trial_range[0]][0]])
    frame_stop = find_nearest(cam['times'],
                              [trials['intervals'][trial_range[-1]][1]])
    '''
    wheel related stuff
    '''

    wheel = alf.io.load_object(alf_path, 'wheel', namespace='ibl')
    import brainbox.behavior.wheel as wh
    try:
        pos, t = wh.interpolate_position(wheel['timestamps'],
                                         wheel['position'],
                                         freq=1000)
    except BaseException:
        pos, t = wh.interpolate_position(wheel['times'],
                                         wheel['position'],
                                         freq=1000)

    w_start = find_nearest(t, trials['intervals'][trial_range[0]][0])
    w_stop = find_nearest(t, trials['intervals'][trial_range[-1]][1])

    # confine to interval
    pos_int = pos[w_start:w_stop]
    t_int = t[w_start:w_stop]

    # alignment of cam stamps and interpolated wheel stamps
    wheel_pos = []
    kk = 0
    for wt in cam['times'][frame_start:frame_stop]:
        wheel_pos.append(pos_int[find_nearest(t_int, wt)])
        kk += 1
        if kk % 3000 == 0:
            print('iteration', kk)
    '''
    DLC related stuff
    '''
    Times = cam['times'][frame_start:frame_stop]
    del cam['times']

    # some exception for inconsisitent data formats
    try:
        dlc_name = '_ibl_%sCamera.dlc.pqt' % video_type
        dlc_path = alf_path / dlc_name
        cam = pd.read_parquet(dlc_path, engine="fastparquet")
        print('it is pqt')
    except BaseException:
        raw_vid_path = alf_path.parent / 'raw_video_data'
        cam = alf.io.load_object(raw_vid_path,
                                 '%sCamera' % video_type,
                                 namespace='ibl')

    points = np.unique(['_'.join(x.split('_')[:-1]) for x in cam.keys()])
    if len(points) == 1:
        cam = cam['dlc']
        points = np.unique(['_'.join(x.split('_')[:-1]) for x in cam.keys()])

    if video_type != 'body':
        d = list(points)
        d.remove('tube_top')
        d.remove('tube_bottom')
        points = np.array(d)

    # Set values to nan if likelyhood is too low # for pqt: .to_numpy()
    XYs = {}
    for point in points:
        x = np.ma.masked_where(cam[point + '_likelihood'] < 0.9,
                               cam[point + '_x'])
        x = x.filled(np.nan)
        y = np.ma.masked_where(cam[point + '_likelihood'] < 0.9,
                               cam[point + '_y'])
        y = y.filled(np.nan)
        XYs[point] = np.array(
            [x[frame_start:frame_stop], y[frame_start:frame_stop]])

    # Just for 3D testing
    # return XYs

    # Zoom at eye
    if eye_zoom:
        pivot = np.nanmean(XYs['pupil_top_r'], axis=1)
        x0 = int(pivot[0]) - 33
        x1 = int(pivot[0]) + 33
        y0 = int(pivot[1]) - 28
        y1 = int(pivot[1]) + 38
        size = (66, 66)
        dot_s = 1  # [px] for painting DLC dots

    else:
        x0 = 0
        x1 = size[0]
        y0 = 0
        y1 = size[1]
        if video_type == 'left':
            dot_s = 10  # [px] for painting DLC dots
        else:
            dot_s = 5

    if save_video:
        loc = save_vids_here + '%s_trials_%s_%s_%s.mp4' % (
            eid, trial_range[0], trial_range[-1], video_type)
        out = cv2.VideoWriter(loc, cv2.VideoWriter_fourcc(*'mp4v'), fps,
                              size)  # put , 0 if grey scale

    # writing stuff on frames
    font = cv2.FONT_HERSHEY_SIMPLEX

    if video_type == 'left':
        bottomLeftCornerOfText = (20, 1000)
        fontScale = 4
    else:
        bottomLeftCornerOfText = (10, 500)
        fontScale = 2

    lineType = 2

    # assign a color to each DLC point (now: all points red)
    cmap = matplotlib.cm.get_cmap('Spectral')
    CR = np.arange(len(points)) / len(points)

    block = np.ones((2 * dot_s, 2 * dot_s, 3))

    # set start frame
    cap.set(1, frame_start)

    k = 0
    while (cap.isOpened()):
        ret, frame = cap.read()
        gray = frame

        # print wheel angle
        fontColor = (255, 255, 255)
        Angle = round(wheel_pos[k], 2)
        Time = round(Times[k], 3)
        cv2.putText(gray, 'Wheel angle: ' + str(Angle), bottomLeftCornerOfText,
                    font, fontScale / 2, fontColor, lineType)

        a, b = bottomLeftCornerOfText
        bottomLeftCornerOfText0 = (int(a * 10 + b / 2), b)
        cv2.putText(gray, '  time: ' + str(Time), bottomLeftCornerOfText0,
                    font, fontScale / 2, fontColor, lineType)

        # print DLC dots
        ll = 0
        for point in points:

            # Put point color legend
            fontColor = (np.array([cmap(CR[ll])]) * 255)[0][:3]
            a, b = bottomLeftCornerOfText
            if video_type == 'right':
                bottomLeftCornerOfText2 = (a, a * 2 * (1 + ll))
            else:
                bottomLeftCornerOfText2 = (b, a * 2 * (1 + ll))
            fontScale2 = fontScale / 4
            cv2.putText(gray, point, bottomLeftCornerOfText2, font, fontScale2,
                        fontColor, lineType)

            X0 = XYs[point][0][k]
            Y0 = XYs[point][1][k]
            # transform for opencv?
            X = Y0
            Y = X0

            if not np.isnan(X) and not np.isnan(Y):
                col = (np.array([cmap(CR[ll])]) * 255)[0][:3]
                # col = np.array([0, 0, 255]) # all points red
                X = X.astype(int)
                Y = Y.astype(int)
                gray[X - dot_s:X + dot_s, Y - dot_s:Y + dot_s] = block * col
            ll += 1

        gray = gray[y0:y1, x0:x1]
        if save_video:
            out.write(gray)
        cv2.imshow('frame', gray)
        cv2.waitKey(1)
        k += 1
        if k == (frame_stop - frame_start) - 1:
            break

    if save_video:
        out.release()
    cap.release()
    cv2.destroyAllWindows()
Пример #27
0
# Mock dataset
import unittest

import numpy as np

from ibllib.qc import BpodQCExtractor
from oneibl.one import ONE

one = ONE(
    base_url="https://test.alyx.internationalbrainlab.org",
    username="******",
    password="******",
)

dstypes = [
    "_iblrig_taskData.raw",
    "_iblrig_taskSettings.raw",
    "_iblrig_encoderPositions.raw",
    "_iblrig_encoderEvents.raw",
    "_iblrig_stimPositionScreen.raw",
    "_iblrig_syncSquareUpdate.raw",
    "_iblrig_encoderTrialInfo.raw",
    "_iblrig_ambientSensorData.raw",
]


class TestBpodQCExtractors(unittest.TestCase):
    """TODO: should be an integration test in iblscripts"""
    def setUp(self):
        self.one = one
        self.eid = "b1c968ad-4874-468d-b2e4-5ffa9b9964e9"
Пример #28
0
 def __init__(self,
              saveloc=None,
              nwb_metadata_file=None,
              metadata_obj: Alyx2NWBMetadata = None,
              one_object: ONE = None,
              save_raw=False,
              save_camera_raw=False,
              complevel=4,
              shuffle=False,
              buffer_size=1):
     """
     Retrieve all Alyx session, subject metadata, raw data for eid using the one apis load method
     Map that to nwb supported datatypes and create an nwb file.
     Parameters
     ----------
     saveloc: str, Path
         save location of nwbfile
     nwb_metadata_file: [dict, str]
         output of Alyx2NWBMetadata as a dict/json location str
     metadata_obj: Alyx2NWBMetadata
     one_object: ONE()
     save_raw: bool
         will load and save large raw files: ecephys.raw.ap/lf.cbin to nwb
     save_camera_raw: bool
         will load and save mice camera movie .mp4: _iblrig_Camera.raw
     complevel: int
         level of compression to apply to raw datasets
         (0-9)>(low,high). https://docs.h5py.org/en/latest/high/dataset.html
     shuffle: bool
         Enable shuffle I/O filter. http://docs.h5py.org/en/latest/high/dataset.html#dataset-shuffle
     """
     self.buffer_size = buffer_size
     self.complevel = complevel
     self.shuffle = shuffle
     if nwb_metadata_file is not None:
         if isinstance(nwb_metadata_file, dict):
             self.nwb_metadata = nwb_metadata_file
         elif isinstance(nwb_metadata_file, str):
             with open(nwb_metadata_file, 'r') as f:
                 self.nwb_metadata = json.load(f)
     elif metadata_obj is not None:
         self.nwb_metadata = metadata_obj.complete_metadata
     else:
         raise Exception(
             'required one of argument: nwb_metadata_file OR metadata_obj')
     if one_object is not None:
         self.one_object = one_object
     elif metadata_obj is not None:
         self.one_object = metadata_obj.one_obj
     else:
         Warning('creating a ONE object and continuing')
         self.one_object = ONE()
     if saveloc is None:
         Warning('saving nwb file in current working directory')
         self.saveloc = str(Path.cwd())
     else:
         self.saveloc = str(saveloc)
     self.eid = self.nwb_metadata["eid"]
     if not isinstance(self.nwb_metadata['NWBFile']['session_start_time'],
                       datetime):
         self.nwb_metadata['NWBFile']['session_start_time'] = \
             datetime.strptime(self.nwb_metadata['NWBFile']['session_start_time'], '%Y-%m-%dT%X').replace(
                 tzinfo=pytz.utc)
         self.nwb_metadata['IBLSubject']['date_of_birth'] = \
             datetime.strptime(self.nwb_metadata['IBLSubject']['date_of_birth'], '%Y-%m-%dT%X').replace(
                 tzinfo=pytz.utc)
     # create nwbfile:
     self.initialize_nwbfile()
     self.no_probes = len(self.nwb_metadata['Probes'])
     if self.no_probes == 0:
         warnings.warn(
             'could not find probe information, will create trials, behavior, acquisition'
         )
     self.electrode_table_exist = False
     self._one_data = _OneData(self.one_object,
                               self.eid,
                               self.no_probes,
                               self.nwb_metadata,
                               save_raw=save_raw,
                               save_camera_raw=save_camera_raw)
Пример #29
0
 def __init__(self, one=None):
     # one object
     if one is None:
         self.one = ONE()
     else:
         self.one = one
Пример #30
0
"""
Get video frames and metadata
===================================
Video frames and meta data can be loaded using the ibllib.io.video module, which contains
functions for loading individual or groups of frames efficiently.  The video may be streamed
remotely or loaded from a local file.  In these examples a remote URL is used.
"""
import numpy as np

import ibllib.io.video as vidio
from oneibl.one import ONE

one = ONE(silent=True)
eid = 'edd22318-216c-44ff-bc24-49ce8be78374'  # 2020-08-19_1_CSH_ZAD_019

# Example 1: get the remote video URL from eid
urls = vidio.url_from_eid(eid, one=one)
# Without the `label` kwarg, returns a dictionary of camera URLs
url = urls['left']  # URL for the left camera

# Example 2: get the video label from a video file path or URL
label = vidio.label_from_path(url)
print(f'Using URL for the {label} camera')

# Example 3: loading a single frame
frame_n = 1000  # Frame number to fetch.  Indexing starts from 0.
frame = vidio.get_video_frame(url, frame_n)
assert frame is not None, 'failed to load frame'

# Example 4: loading multiple frames
"""