Skip to content

Commit

Permalink
Merge branch 'release/2.31.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
mayofaulkner committed Feb 26, 2024
2 parents ad5e3b9 + ebf37b4 commit 6912198
Show file tree
Hide file tree
Showing 36 changed files with 361 additions and 136 deletions.
2 changes: 1 addition & 1 deletion brainbox/behavior/dlc.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import scipy.interpolate as interpolate
from scipy.stats import zscore

from neurodsp.smooth import smooth_interpolate_savgol
from ibldsp.smooth import smooth_interpolate_savgol
from iblutil.numerical import bincount2D
import brainbox.behavior.wheel as bbox_wheel

Expand Down
2 changes: 1 addition & 1 deletion brainbox/metrics/electrode_drift.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import numpy as np

from neurodsp import smooth, utils, fourier
from ibldsp import smooth, utils, fourier
from iblutil.numerical import bincount2D


Expand Down
2 changes: 1 addition & 1 deletion brainbox/metrics/single_units.py
Original file line number Diff line number Diff line change
Expand Up @@ -981,7 +981,7 @@ def quick_unit_metrics(spike_clusters, spike_times, spike_amps, spike_depths,
r.amp_std_dB[ir] = np.array(camp['log_amps'].std())
srp = metrics.slidingRP_all(spikeTimes=spike_times, spikeClusters=spike_clusters,
**{'sampleRate': 30000, 'binSizeCorr': 1 / 30000})
r.slidingRP_viol[srp['cidx']] = srp['value']
r.slidingRP_viol[ir] = srp['value']

# loop over each cluster to compute the rest of the metrics
for ic in np.arange(nclust):
Expand Down
4 changes: 2 additions & 2 deletions examples/archive/ibllib/synchronisation_ephys.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import neurodsp.utils
import ibldsp.utils
import spikeglx
import ibllib.io.extractors.ephys_fpga

Expand All @@ -15,7 +15,7 @@

# if the data is needed as well, loop over the file
# raw data contains raw ephys traces, while raw_sync contains the 16 sync traces
wg = neurodsp.utils.WindowGenerator(sr.ns, BATCH_SIZE_SAMPLES, overlap=1)
wg = ibldsp.utils.WindowGenerator(sr.ns, BATCH_SIZE_SAMPLES, overlap=1)
for first, last in wg.firstlast:
rawdata, rawsync = sr.read_samples(first, last)
wg.print_progress()
4 changes: 2 additions & 2 deletions examples/loading_data/loading_raw_ephys_data.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@
"metadata": {},
"outputs": [],
"source": [
"from neurodsp.voltage import destripe\n",
"from ibldsp.voltage import destripe\n",
"# Reminder : If not done before, remove first the sync channel from raw data\n",
"# Apply destriping algorithm to data\n",
"destriped = destripe(raw_ap, fs=sr_ap.fs)"
Expand Down Expand Up @@ -445,7 +445,7 @@
"source": [
"## Useful modules\n",
"* [ibllib.io.spikeglx](https://int-brain-lab.github.io/ibl-neuropixel/_autosummary/spikeglx.html)\n",
"* [ibllib.voltage.dsp](https://int-brain-lab.github.io/ibl-neuropixel/_autosummary/neurodsp.voltage.html)\n",
"* [ibllib.voltage.dsp](https://int-brain-lab.github.io/ibl-neuropixel/_autosummary/ibldsp.voltage.html)\n",
"* [brainbox.io.spikeglx.stream](https://int-brain-lab.github.io/iblenv/_autosummary/brainbox.io.spikeglx.html#brainbox.io.spikeglx.stream)\n",
"* [viewephys](https://github.com/oliche/viewephys) to visualise raw data snippets (Note: this package is not within `ibllib` but standalone)"
]
Expand Down
2 changes: 1 addition & 1 deletion examples/one/histology/coverage_map.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import matplotlib.pyplot as plt
import numpy as np
from one.api import ONE
from neurodsp.utils import fcn_cosine
from ibldsp.utils import fcn_cosine

import iblatlas.atlas as atlas
from ibllib.pipes.histology import coverage
Expand Down
2 changes: 1 addition & 1 deletion ibllib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import logging
import warnings

__version__ = '2.30.0'
__version__ = '2.31.0'
warnings.filterwarnings('always', category=DeprecationWarning, module='ibllib')

# if this becomes a full-blown library we should let the logging configuration to the discretion of the dev
Expand Down
2 changes: 1 addition & 1 deletion ibllib/ephys/ephysqc.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from iblutil.util import Bunch
import spikeglx
import neuropixel
from neurodsp import fourier, utils, voltage
from ibldsp import fourier, utils, voltage
from tqdm import tqdm

from brainbox.io.spikeglx import Streamer
Expand Down
2 changes: 1 addition & 1 deletion ibllib/ephys/spikes.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def ks2_to_alf(ks_path, bin_path, out_path, bin_file=None, ampfactor=1, label=No
"""
m = ephysqc.phy_model_from_ks2_path(ks2_path=ks_path, bin_path=bin_path, bin_file=bin_file)
ac = phylib.io.alf.EphysAlfCreator(m)
ac.convert(out_path, label=label, force=force, ampfactor=ampfactor)
ac.convert(out_path, label=label, force=force, ampfactor=float(ampfactor))


def ks2_to_tar(ks_path, out_path, force=False):
Expand Down
4 changes: 2 additions & 2 deletions ibllib/ephys/sync_probes.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ def sync_probe_front_times(t, tref, sr, display=False, type='smooth', tol=2.0):
to the sampling rate of digital channels. The residual is fit using frequency domain
smoothing
"""
import neurodsp.fourier
import ibldsp.fourier
CAMERA_UPSAMPLING_RATE_HZ = 300
PAD_LENGTH_SECS = 60
STAT_LENGTH_SECS = 30 # median length to compute padding value
Expand All @@ -214,7 +214,7 @@ def sync_probe_front_times(t, tref, sr, display=False, type='smooth', tol=2.0):
res_filt = np.pad(res_upsamp, lpad, mode='median',
stat_length=CAMERA_UPSAMPLING_RATE_HZ * STAT_LENGTH_SECS)
fbounds = [0.001, 0.002]
res_filt = neurodsp.fourier.lp(res_filt, 1 / CAMERA_UPSAMPLING_RATE_HZ, fbounds)[lpad[0]:-lpad[1]]
res_filt = ibldsp.fourier.lp(res_filt, 1 / CAMERA_UPSAMPLING_RATE_HZ, fbounds)[lpad[0]:-lpad[1]]
tout = np.arange(0, np.max(tref) + SYNC_SAMPLING_RATE_SECS, 20)
sync_points = np.c_[tout, np.polyval(pol, tout) + np.interp(tout, t_upsamp, res_filt)]
if display:
Expand Down
2 changes: 1 addition & 1 deletion ibllib/io/extractors/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import matplotlib.pyplot as plt
from iblutil.util import range_str

import neurodsp.utils as dsp
import ibldsp.utils as dsp
from ibllib.plots import squares, vertical_lines
from ibllib.io.video import assert_valid_label, VideoStreamer
from iblutil.numerical import within_ranges
Expand Down
10 changes: 5 additions & 5 deletions ibllib/io/extractors/ephys_fpga.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
from packaging import version

import spikeglx
import neurodsp.utils
import ibldsp.utils
import one.alf.io as alfio
from iblutil.util import Bunch
from iblutil.spacer import Spacer
Expand Down Expand Up @@ -160,11 +160,11 @@ def _sync_to_alf(raw_ephys_apfile, output_path=None, save=False, parts=''):
file_ftcp = Path(output_path).joinpath(f'fronts_times_channel_polarity{uuid.uuid4()}.bin')

# loop over chunks of the raw ephys file
wg = neurodsp.utils.WindowGenerator(sr.ns, int(SYNC_BATCH_SIZE_SECS * sr.fs), overlap=1)
wg = ibldsp.utils.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 = neurodsp.utils.fronts(ss, axis=0)
ind, fronts = ibldsp.utils.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)
Expand Down Expand Up @@ -775,7 +775,7 @@ def _extract(self, sync=None, chmap=None, sync_collection='raw_ephys_data',
bpod_start = self.bpod_trials['intervals'][:, 0]
if len(t_trial_start) > len(bpod_start) / 2: # if least half the trial start TTLs detected
_logger.warning('Attempting to get protocol period from aligning trial start TTLs')
fcn, *_ = neurodsp.utils.sync_timestamps(bpod_start, t_trial_start)
fcn, *_ = ibldsp.utils.sync_timestamps(bpod_start, t_trial_start)
buffer = 2.5 # the number of seconds to include before/after task
start, end = fcn(self.bpod_trials['intervals'].flat[[0, -1]])
tmin = min(sync['times'][0], start - buffer)
Expand Down Expand Up @@ -1202,7 +1202,7 @@ def sync_bpod_clock(bpod_trials, fpga_trials, sync_field):
bpod_fpga_timestamps[i] = trials[sync_field]

# Sync the two timestamps
fcn, drift, ibpod, ifpga = neurodsp.utils.sync_timestamps(*bpod_fpga_timestamps, return_indices=True)
fcn, drift, ibpod, ifpga = ibldsp.utils.sync_timestamps(*bpod_fpga_timestamps, return_indices=True)

# If it's drifting too much throw warning or error
_logger.info('N trials: %i bpod, %i FPGA, %i merged, sync %.5f ppm',
Expand Down
2 changes: 1 addition & 1 deletion ibllib/io/extractors/fibrephotometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from ibllib.io.extractors.base import BaseExtractor
from ibllib.io.raw_daq_loaders import load_channels_tdms, load_raw_daq_tdms
from ibllib.io.extractors.training_trials import GoCueTriggerTimes
from neurodsp.utils import rises, sync_timestamps
from ibldsp.utils import rises, sync_timestamps

_logger = logging.getLogger(__name__)

Expand Down
26 changes: 18 additions & 8 deletions ibllib/io/extractors/habituation_trials.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import logging
import numpy as np

from packaging import version

import ibllib.io.raw_data_loaders as raw
from ibllib.io.extractors.base import BaseBpodTrialsExtractor, run_extractor_classes
from ibllib.io.extractors.biased_trials import ContrastLR
Expand All @@ -26,10 +28,13 @@ def _extract(self) -> dict:
"""
Extract the Bpod trial events.
The Bpod state machine for this task has extremely misleading names! The 'iti' state is
actually the delay between valve open and trial end (the stimulus is still present during
this period), and the 'trial_start' state is actually the ITI during which there is a 1s
Bpod TTL and gray screen period.
For iblrig versions < 8.13 the Bpod state machine for this task had extremely misleading names!
The 'iti' state was actually the delay between valve close and trial end (the stimulus is
still present during this period), and the 'trial_start' state is actually the ITI during
which there is a 1s Bpod TTL and gray screen period.
In version 8.13 and later, the 'iti' state was renamed to 'post_reward' and 'trial_start'
was renamed to 'iti'.
Returns
-------
Expand Down Expand Up @@ -57,12 +62,17 @@ def _extract(self) -> dict:
bpod_trials=self.bpod_trials, settings=self.settings, task_collection=self.task_collection)

"""
The 'trial_start' state is in fact the 1s grey screen period, therefore the first timestamp
is really the end of the previous trial and also the stimOff trigger time. The second
timestamp is the true trial start time.
The 'trial_start'/'iti' state is in fact the 1s grey screen period, therefore the first
timestamp is really the end of the previous trial and also the stimOff trigger time. The
second timestamp is the true trial start time. This state was renamed in version 8.13.
"""
state_names = self.bpod_trials[0]['behavior_data']['States timestamps'].keys()
rig_version = version.parse(self.settings['IBLRIG_VERSION'])
legacy_state_machine = 'post_reward' not in state_names and 'trial_start' in state_names

key = 'iti' if (rig_version >= version.parse('8.13') and not legacy_state_machine) else 'trial_start'
(_, *ends), starts = zip(*[
t['behavior_data']['States timestamps']['trial_start'][-1] for t in self.bpod_trials]
t['behavior_data']['States timestamps'][key][-1] for t in self.bpod_trials]
)

# StimOffTrigger times
Expand Down
2 changes: 1 addition & 1 deletion ibllib/io/extractors/mesoscope.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class TimelineTrials(FpgaTrials):
timeline = None
"""one.alf.io.AlfBunch: The timeline data object."""

sync_field = 'itiIn_times' # trial start events
sync_field = 'itiIn_times'
"""str: The trial event to synchronize (must be present in extracted trials)."""

def __init__(self, *args, sync_collection='raw_sync_data', **kwargs):
Expand Down
4 changes: 2 additions & 2 deletions ibllib/io/extractors/training_audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
from scipy.io import wavfile


from neurodsp.utils import WindowGenerator
from neurodsp import fourier
from ibldsp.utils import WindowGenerator
from ibldsp import fourier
import ibllib.io.raw_data_loaders as ioraw
from ibllib.io.extractors.training_trials import GoCueTimes

Expand Down
2 changes: 1 addition & 1 deletion ibllib/io/extractors/training_wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import numpy as np
from scipy import interpolate

from neurodsp.utils import sync_timestamps
from ibldsp.utils import sync_timestamps
from ibllib.io.extractors.base import BaseBpodTrialsExtractor, run_extractor_classes
import ibllib.io.raw_data_loaders as raw
from ibllib.misc import structarr
Expand Down
2 changes: 1 addition & 1 deletion ibllib/io/extractors/video_motion.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from pathlib import Path
from joblib import Parallel, delayed, cpu_count

from neurodsp.utils import WindowGenerator
from ibldsp.utils import WindowGenerator
from one.api import ONE
import ibllib.io.video as vidio
from iblutil.util import Bunch
Expand Down
13 changes: 11 additions & 2 deletions ibllib/io/extractors/widefield.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,17 @@
from ibllib.io.extractors.ephys_fpga import get_sync_fronts, get_sync_and_chn_map
from ibllib.io.video import get_video_meta

import wfield.cli as wfield_cli
from labcams.io import parse_cam_log
_logger = logging.getLogger('ibllib')

try:
import wfield.cli as wfield_cli
except ImportError:
_logger.warning('wfield not installed')

try:
from labcams.io import parse_cam_log
except ImportError:
_logger.warning('labcams not installed')

_logger = logging.getLogger('ibllib')

Expand Down
8 changes: 4 additions & 4 deletions ibllib/io/raw_daq_loaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import nptdms
import numpy as np
import neurodsp.utils
import ibldsp.utils
import one.alf.io as alfio
import one.alf.exceptions as alferr
from one.alf.spec import to_alf
Expand Down Expand Up @@ -134,7 +134,7 @@ def load_sync_tdms(path, sync_map, fs=None, threshold=2.5, floor_percentile=10):
logger.info(f'estimated analogue channel DC Offset approx. {np.mean(offset):.2f}')
analogue -= offset
ttl = analogue > threshold
ind, sign = neurodsp.utils.fronts(ttl.astype(int))
ind, sign = ibldsp.utils.fronts(ttl.astype(int))
try: # attempt to get the times from the meta data
times = np.vstack([ch.time_track() for ch in raw_channels])
times = times[tuple(ind)]
Expand Down Expand Up @@ -276,8 +276,8 @@ def extract_sync_timeline(timeline, chmap=None, floor_percentile=10, threshold=N
step = threshold.get(label) if isinstance(threshold, dict) else threshold
if step is None:
step = np.max(raw - offset) / 2
iup = neurodsp.utils.rises(raw - offset, step=step, analog=True)
idown = neurodsp.utils.falls(raw - offset, step=step, analog=True)
iup = ibldsp.utils.rises(raw - offset, step=step, analog=True)
idown = ibldsp.utils.falls(raw - offset, step=step, analog=True)
pol = np.r_[np.ones_like(iup), -np.ones_like(idown)].astype('i1')
ind = np.r_[iup, idown]

Expand Down
17 changes: 17 additions & 0 deletions ibllib/pipes/dynamic_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@
The principal function here is `make_pipeline` which reads an `_ibl_experiment.description.yaml`
file and determines the set of tasks required to preprocess the session.
In the experiment description file there is a 'tasks' key that defines each task protocol and the
location of the raw data (i.e. task collection). The protocol subkey may contain an 'extractors'
field that should contain a list of dynamic pipeline task class names for extracting the task data.
These must be subclasses of the :class:`ibllib.pipes.base_tasks.DynamicTask` class. If the
extractors key is absent or empty, the tasks are chosen based on the sync label and protocol name.
NB: The standard behvaiour extraction task classes (e.g.
:class:`ibllib.pipes.behaviour_tasks.ChoiceWorldTrialsBpod` and :class:`ibllib.pipes.behaviour_tasks.ChoiceWorldTrialsNidq`)
handle the clock synchronization, behaviour plots and QC. This is typically independent of the Bpod
trials extraction (i.e. extraction of trials data from the Bpod raw data, in Bpod time). The Bpod
trials extractor class is determined by the :func:`ibllib.io.extractors.base.protocol2extractor`
map. IBL protocols may be added to the ibllib.io.extractors.task_extractor_map.json file, while
non-IBL ones should be in projects.base.task_extractor_map.json file located in the personal
projects repo. The Bpod trials extractor class must be a subclass of the
:class:`ibllib.io.extractors.base.BaseBpodTrialsExtractor` class, and located in either the
personal projects repo or in :py:mod:`ibllib.io.extractors.bpod_trials` module.
"""
import logging
import re
Expand Down
2 changes: 1 addition & 1 deletion ibllib/pipes/ephys_preprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import packaging.version

import one.alf.io as alfio
from neurodsp.utils import rms
from ibldsp.utils import rms
import spikeglx

from ibllib.misc import check_nvidia_driver
Expand Down
2 changes: 1 addition & 1 deletion ibllib/pipes/ephys_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import pandas as pd
import spikeglx
import neuropixel
from neurodsp.utils import rms
from ibldsp.utils import rms
import one.alf.io as alfio

from ibllib.misc import check_nvidia_driver
Expand Down
2 changes: 1 addition & 1 deletion ibllib/pipes/histology.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from ibllib.ephys.spikes import probes_description as extract_probes
from ibllib.qc import base

from neurodsp.utils import fcn_cosine
from ibldsp.utils import fcn_cosine


_logger = logging.getLogger(__name__)
Expand Down
Loading

0 comments on commit 6912198

Please sign in to comment.