|
@@ -45,18 +45,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
import glob
|
|
|
import os
|
|
|
import re
|
|
|
+import warnings
|
|
|
|
|
|
import numpy as np
|
|
|
import odml.tools
|
|
|
import quantities as pq
|
|
|
|
|
|
import neo
|
|
|
-
|
|
|
-# Using old version of IO as long as available - should be deleted at some point
|
|
|
-try:
|
|
|
- from neo.io import OldBlackrockIO as BlackrockIO
|
|
|
-except ImportError:
|
|
|
- from neo.io.blackrockio import BlackrockIO
|
|
|
+from neo.io.blackrockio import BlackrockIO
|
|
|
|
|
|
|
|
|
class ReachGraspIO(BlackrockIO):
|
|
@@ -93,11 +89,17 @@ class ReachGraspIO(BlackrockIO):
|
|
|
File name of the .nev file (without extension). If None, the
|
|
|
current spike-sorted version filename is used (see parameter
|
|
|
filename above). Default: None.
|
|
|
- sif_override (string):
|
|
|
+ nsx_to_load (int, list, 'max', 'all' (=None)) default None:
|
|
|
+ IDs of nsX file from which to load data, e.g., if set to
|
|
|
+ 5 only data from the ns5 file are loaded.
|
|
|
+ If 'all', then all nsX will be loaded.
|
|
|
+ Contrary to previsous version of the IO (<0.7), nsx_to_load
|
|
|
+ must be set at the init before parse_header().
|
|
|
+ sif_override (string): DEPRECATED
|
|
|
File name of the .sif file (without extension). If None,
|
|
|
filename is used.
|
|
|
Default: None.
|
|
|
- ccf_override (string):
|
|
|
+ ccf_override (string): DEPRECATED
|
|
|
File name of the .ccf file (without extension). If None,
|
|
|
filename is used.
|
|
|
Default: None.
|
|
@@ -289,10 +291,9 @@ class ReachGraspIO(BlackrockIO):
|
|
|
'65510': 'RW-ON (+CONF-HF)',
|
|
|
'65513': 'RW-ON (+CONF-LF)',
|
|
|
'65514': 'RW-ON (+CONF-SG)'}
|
|
|
- event_labels_codes = dict(
|
|
|
- [(k, []) for k in np.unique(list(event_labels_str.values()))]) #inefficient in Python2
|
|
|
+ event_labels_codes = dict([(k, []) for k in np.unique(list(event_labels_str.values()))])
|
|
|
for k in list(event_labels_codes):
|
|
|
- for l, v in event_labels_str.items(): #inefficient in Python2
|
|
|
+ for l, v in event_labels_str.items():
|
|
|
if v == k:
|
|
|
event_labels_codes[k].append(l)
|
|
|
|
|
@@ -331,8 +332,7 @@ class ReachGraspIO(BlackrockIO):
|
|
|
'SR': 5,
|
|
|
'RW-ON': 6,
|
|
|
'STOP': 7}
|
|
|
- trial_const_sequence_str = dict(
|
|
|
- (v, k) for k, v in trial_const_sequence_codes.items()) #inefficient in Python2
|
|
|
+ trial_const_sequence_str = dict((v, k) for k, v in trial_const_sequence_codes.items())
|
|
|
|
|
|
# Create dictionaries for trial performances
|
|
|
# (resulting decimal number from binary number created from trial_sequence)
|
|
@@ -345,10 +345,10 @@ class ReachGraspIO(BlackrockIO):
|
|
|
'error<GO-ON': 175,
|
|
|
'grip_error': 191,
|
|
|
'correct_trial': 255}
|
|
|
- performance_str = dict((v, k) for k, v in performance_codes.items()) #inefficient in Python2
|
|
|
+ performance_str = dict((v, k) for k, v in performance_codes.items())
|
|
|
|
|
|
def __init__(
|
|
|
- self, filename, odml_directory=None,
|
|
|
+ self, filename, odml_directory=None, nsx_to_load=None,
|
|
|
nsx_override=None, nev_override=None,
|
|
|
sif_override=None, ccf_override=None, odml_filename=None,
|
|
|
verbose=False):
|
|
@@ -356,6 +356,13 @@ class ReachGraspIO(BlackrockIO):
|
|
|
Constructor
|
|
|
"""
|
|
|
|
|
|
+ if sif_override is not None:
|
|
|
+ warnings.warn('`sif_override is deprecated.')
|
|
|
+
|
|
|
+ if ccf_override is not None:
|
|
|
+ warnings.warn('`ccf_override is deprecated.')
|
|
|
+
|
|
|
+
|
|
|
# Remember choice whether to print diagnostic messages or not
|
|
|
self._verbose = verbose
|
|
|
|
|
@@ -373,8 +380,7 @@ class ReachGraspIO(BlackrockIO):
|
|
|
else:
|
|
|
# find most recent spike sorting version
|
|
|
nev_versions = [re.sub(
|
|
|
- os.path.extsep + 'nev$', '', p) for p in glob.glob(
|
|
|
- filename + '*.nev')]
|
|
|
+ os.path.extsep + 'nev$', '', p) for p in glob.glob(filename + '*.nev')]
|
|
|
nev_versions = [p.replace(filename, '') for p in nev_versions]
|
|
|
if len(nev_versions):
|
|
|
sorting_postfix = sorted(nev_versions)[-1]
|
|
@@ -384,22 +390,24 @@ class ReachGraspIO(BlackrockIO):
|
|
|
|
|
|
# Initialize file
|
|
|
BlackrockIO.__init__(
|
|
|
- self, filename, nsx_override=nsx_override,
|
|
|
- nev_override=sorting_version, sif_override=sif_override,
|
|
|
- ccf_override=ccf_override, verbose=verbose)
|
|
|
+ self, filename, nsx_to_load=nsx_to_load, nsx_override=nsx_override,
|
|
|
+ nev_override=sorting_version, verbose=verbose)
|
|
|
|
|
|
# if no odML directory is specified, use same directory as main files
|
|
|
if not odml_directory:
|
|
|
- odml_directory = os.path.dirname(self.filename)[:-1]
|
|
|
+ odml_directory = os.path.dirname(self.filename)
|
|
|
+ # remove potential trailing separators
|
|
|
+ if odml_directory[-1] == os.path.sep:
|
|
|
+ odml_directory = odml_directory[:-1]
|
|
|
|
|
|
# remove extensions from odml override
|
|
|
filen = os.path.split(self.filename)[-1]
|
|
|
if odml_filename:
|
|
|
- self._filenames['odml'] = ''.join(
|
|
|
- [odml_directory, os.path.sep, odml_filename])
|
|
|
+ # strip potential extension
|
|
|
+ odmlname = os.path.splitext(odml_filename)[0]
|
|
|
+ self._filenames['odml'] = ''.join([odml_directory, os.path.sep, odmlname])
|
|
|
else:
|
|
|
- self._filenames['odml'] = ''.join(
|
|
|
- [odml_directory, os.path.sep, filen])
|
|
|
+ self._filenames['odml'] = ''.join([odml_directory, os.path.sep, filen])
|
|
|
|
|
|
file2check = ''.join([self._filenames['odml'], os.path.extsep, 'odml'])
|
|
|
if os.path.exists(file2check):
|
|
@@ -427,6 +435,23 @@ class ReachGraspIO(BlackrockIO):
|
|
|
else:
|
|
|
self._load_spikesorting_info = False
|
|
|
|
|
|
+ # extract available neuronal ids
|
|
|
+ self.avail_electrode_ids = None
|
|
|
+ if self.odmldoc:
|
|
|
+ self.avail_electrode_ids = []
|
|
|
+ secs = self.odmldoc['UtahArray']['Array'].sections
|
|
|
+ for i in range(1, 101):
|
|
|
+ elidx = [s.properties['ID'].values for s in secs if
|
|
|
+ s.name.startswith('Electrode') and
|
|
|
+ s.properties['ConnectorAlignedID'].values[0] == i]
|
|
|
+ if len(elidx) == 0:
|
|
|
+ self.avail_electrode_ids.append(-1)
|
|
|
+ elif len(elidx) == 1:
|
|
|
+ self.avail_electrode_ids.append(elidx[0])
|
|
|
+ else:
|
|
|
+ raise ValueError("Electrode IDs in odML file are corrupt. "
|
|
|
+ "ID %i occurs %i times" % (i, len(elidx)))
|
|
|
+
|
|
|
def __is_set(self, flag, pos):
|
|
|
"""
|
|
|
Checks if bit is set at the given position for flag. If flag is an
|
|
@@ -489,7 +514,7 @@ class ReachGraspIO(BlackrockIO):
|
|
|
task_condition = 0
|
|
|
|
|
|
if len(occurring_trtys) > 0:
|
|
|
- for cnd, trtys in self.condition_str.items(): #inefficient in Python2
|
|
|
+ for cnd, trtys in self.condition_str.items():
|
|
|
if set(trtys) == set(occurring_trtys):
|
|
|
# replace with detected task condition
|
|
|
task_condition = cnd
|
|
@@ -511,23 +536,16 @@ class ReachGraspIO(BlackrockIO):
|
|
|
tr_secs = sec.itersections(filter_func=ff)
|
|
|
for trial_sec in tr_secs:
|
|
|
for signalname in ['GripForceSignals', 'DisplacementSignal']:
|
|
|
- for analog_events in trial_sec[
|
|
|
- 'AnalogEvents'][signalname].properties:
|
|
|
+ for analog_events in trial_sec['AnalogEvents'][signalname].properties:
|
|
|
|
|
|
- time = analog_events.values * \
|
|
|
- pq.CompoundUnit(analog_events.unit)
|
|
|
+ time = analog_events.values * pq.CompoundUnit(analog_events.unit)
|
|
|
if time >= t_start and time < t_stop:
|
|
|
event_name.append(analog_events.name)
|
|
|
event_time.append(time)
|
|
|
- trial_id.extend(
|
|
|
- trial_sec.properties['TrialID'].values)
|
|
|
- trial_timestamp_id.extend(
|
|
|
- trial_sec.properties[
|
|
|
- 'TrialTimestampID'].values)
|
|
|
- performance_code.extend(
|
|
|
- trial_sec.properties['PerformanceCode'].values)
|
|
|
- trial_type.extend(
|
|
|
- trial_sec.properties['TrialType'].values)
|
|
|
+ trial_id.extend(trial_sec.properties['TrialID'].values)
|
|
|
+ trial_timestamp_id.extend(trial_sec.properties['TrialTimestampID'].values)
|
|
|
+ performance_code.extend(trial_sec.properties['PerformanceCode'].values)
|
|
|
+ trial_type.extend(trial_sec.properties['TrialType'].values)
|
|
|
|
|
|
# Create event object with analog events
|
|
|
analog_events = neo.Event(
|
|
@@ -564,13 +582,6 @@ class ReachGraspIO(BlackrockIO):
|
|
|
events.name = "DigitalTrialEvents"
|
|
|
events.description = "Trial " + events.description.lower()
|
|
|
|
|
|
- # Uncomment for event and trial sequence debugging
|
|
|
-# for ev in events.labels:
|
|
|
-# if ev in list(self.event_labels_str):
|
|
|
-# print ev, self.event_labels_str[ev]
|
|
|
-# else:
|
|
|
-# print ev
|
|
|
-
|
|
|
# Extract beginning of first complete trial
|
|
|
tson_label = self.event_labels_codes['TS-ON'][0]
|
|
|
if tson_label in events.labels:
|
|
@@ -601,11 +612,8 @@ class ReachGraspIO(BlackrockIO):
|
|
|
if self.event_labels_str[l] == 'TS-ON':
|
|
|
if i > 0:
|
|
|
prev_ev = events.labels[i - 1]
|
|
|
- if self.event_labels_str[prev_ev] in \
|
|
|
- ['STOP', 'TS-OFF/STOP']:
|
|
|
- timestamp_id = int(events.times[i].rescale(
|
|
|
- self._BlackrockIO__nev_params(
|
|
|
- 'event_unit')).item())
|
|
|
+ if self.event_labels_str[prev_ev] in ['STOP', 'TS-OFF/STOP']:
|
|
|
+ timestamp_id = int(events.times[i].item())
|
|
|
trial_timestamp_ID.append(timestamp_id)
|
|
|
trial_event_labels.append('TS-ON')
|
|
|
trialsequence[timestamp_id] = self.__set_bit(
|
|
@@ -615,9 +623,7 @@ class ReachGraspIO(BlackrockIO):
|
|
|
trial_timestamp_ID.append(timestamp_id)
|
|
|
trial_event_labels.append('TS-ON-ERROR')
|
|
|
else:
|
|
|
- timestamp_id = int(events.times[i].rescale(
|
|
|
- self._BlackrockIO__nev_params(
|
|
|
- 'event_unit')).item())
|
|
|
+ timestamp_id = int(events.times[i].item())
|
|
|
trial_timestamp_ID.append(timestamp_id)
|
|
|
trial_event_labels.append('TS-ON')
|
|
|
trialsequence[timestamp_id] = self.__set_bit(
|
|
@@ -761,8 +767,7 @@ class ReachGraspIO(BlackrockIO):
|
|
|
for tid in trial_timestamp_ID:
|
|
|
if tid not in list(trialtypes):
|
|
|
trialtypes[tid] = 'NONE'
|
|
|
- belongs_to_trialtype = [
|
|
|
- trialtypes[tid] for tid in trial_timestamp_ID]
|
|
|
+ belongs_to_trialtype = [trialtypes[tid] for tid in trial_timestamp_ID]
|
|
|
events.array_annotate(belongs_to_trialtype=belongs_to_trialtype)
|
|
|
|
|
|
# add modified trial_performance_codes to annotations
|
|
@@ -828,33 +833,52 @@ class ReachGraspIO(BlackrockIO):
|
|
|
for st in un.spiketrains:
|
|
|
st.annotate(**an_dict)
|
|
|
|
|
|
- def __annotate_spiketrains_with_odml(self, sts):
|
|
|
- """
|
|
|
- Annotates spiketrains with metadata from odml file.
|
|
|
- """
|
|
|
-
|
|
|
def __annotate_analogsignals_with_odml(self, asig):
|
|
|
"""
|
|
|
Annotates analogsignals with metadata from odml file.
|
|
|
"""
|
|
|
- if self.odmldoc and asig.annotations['channel_id'] in range(1, 129):
|
|
|
- # Annotate filter settings from odML
|
|
|
- sec = self.odmldoc[
|
|
|
- 'Cerebus']['NeuralSignalProcessor']['NeuralSignals'][
|
|
|
- 'Filter_ns%i' % asig.annotations['nsx']]
|
|
|
- asig.annotate(
|
|
|
- filter_hi_pass_freq=pq.Quantity(
|
|
|
- sec.properties['HighPassFreq'].values[0],
|
|
|
- sec.properties['HighPassFreq'].unit),
|
|
|
- filter_lo_pass_freq=pq.Quantity(
|
|
|
- sec.properties['LowPassFreq'].values[0],
|
|
|
- sec.properties['LowPassFreq'].unit),
|
|
|
- filter_hi_pass_order=sec.properties[
|
|
|
- 'HighPassOrder'].values[0],
|
|
|
- filter_lo_pass_order=sec.properties[
|
|
|
- 'LowPassOrder'].values[0],
|
|
|
- filter_type=sec.properties[
|
|
|
- 'Type'].values[0])
|
|
|
+
|
|
|
+ if self.odmldoc:
|
|
|
+ chids = asig.array_annotations['channel_ids']
|
|
|
+ neural_chids = [chid in self.avail_electrode_ids for chid in chids]
|
|
|
+
|
|
|
+ if not any(neural_chids):
|
|
|
+ asig.annotate(neural_signal=False)
|
|
|
+ elif all(neural_chids):
|
|
|
+ asig.annotate(neural_signal=True)
|
|
|
+
|
|
|
+ # Annotate filter settings from odML
|
|
|
+ nchan = asig.shape[-1]
|
|
|
+ sec = self.odmldoc['Cerebus']['NeuralSignalProcessor']['NeuralSignals'][
|
|
|
+ 'Filter_ns%i' % asig.array_annotations['nsx'][0]]
|
|
|
+ props = sec.properties
|
|
|
+ hi_pass_freq = np.full((nchan), pq.Quantity(props['HighPassFreq'].values[0],
|
|
|
+ props['HighPassFreq'].unit))
|
|
|
+ lo_pass_freq = np.full((nchan), pq.Quantity(props['LowPassFreq'].values[0],
|
|
|
+ props['LowPassFreq'].unit))
|
|
|
+ hi_pass_order = np.zeros_like(hi_pass_freq)
|
|
|
+ lo_pass_order = np.zeros_like(lo_pass_freq)
|
|
|
+ filter_type= np.empty((nchan), np.str)
|
|
|
+ for chidx in range(nchan):
|
|
|
+ filter_name = 'Filter_ns%i' % asig.array_annotations['nsx'][chidx]
|
|
|
+ sec = self.odmldoc['Cerebus']['NeuralSignalProcessor']['NeuralSignals'][filter_name]
|
|
|
+ hi_pass_freq[chidx] = pq.Quantity(
|
|
|
+ sec.properties['HighPassFreq'].values[0],
|
|
|
+ sec.properties['HighPassFreq'].unit)
|
|
|
+ lo_pass_freq[chidx] = pq.Quantity(
|
|
|
+ sec.properties['LowPassFreq'].values[0],
|
|
|
+ sec.properties['LowPassFreq'].unit)
|
|
|
+ hi_pass_order[chidx] = sec.properties['HighPassOrder'].values[0]
|
|
|
+ lo_pass_order[chidx] = sec.properties['LowPassOrder'].values[0]
|
|
|
+ filter_type[chidx] = sec.properties['Type'].values[0]
|
|
|
+
|
|
|
+ asig.array_annotations.update(dict(
|
|
|
+ hi_pass_freq=hi_pass_freq,
|
|
|
+ lo_pass_freq=lo_pass_freq,
|
|
|
+ hi_pass_order=hi_pass_order,
|
|
|
+ lo_pass_order=lo_pass_order,
|
|
|
+ filter_type=filter_type
|
|
|
+ ))
|
|
|
|
|
|
def __annotate_channelindex_with_odml(self, chidx):
|
|
|
"""
|
|
@@ -899,8 +923,7 @@ class ReachGraspIO(BlackrockIO):
|
|
|
st.annotate(**rej_dict)
|
|
|
|
|
|
# Annotate connector aligned ID to channel
|
|
|
- if chidx.channel_ids[0] in \
|
|
|
- chidx.block.annotations['avail_electrode_ids']:
|
|
|
+ if chidx.channel_ids[0] in chidx.block.annotations['avail_electrode_ids']:
|
|
|
ca_dict = {
|
|
|
'connector_aligned_id': chidx.block.annotations[
|
|
|
'avail_electrode_ids'].index(chidx.channel_ids[0])+1}
|
|
@@ -928,8 +951,7 @@ class ReachGraspIO(BlackrockIO):
|
|
|
project_subtype=sec.properties['Subtype'].values)
|
|
|
|
|
|
sec = self.odmldoc['Project']['TaskDesigns']
|
|
|
- bl.annotate(
|
|
|
- taskdesigns=[v for v in sec.properties['UsedDesign'].values])
|
|
|
+ bl.annotate( taskdesigns=[v for v in sec.properties['UsedDesign'].values])
|
|
|
|
|
|
sec = self.odmldoc['Subject']
|
|
|
bl.annotate(
|
|
@@ -960,29 +982,21 @@ class ReachGraspIO(BlackrockIO):
|
|
|
arraygrid_col_num=sec.properties['GridColumns'].values)
|
|
|
|
|
|
secs = self.odmldoc['UtahArray']['Array'].sections
|
|
|
- bl.annotate(
|
|
|
- avail_electrode_ids=[])
|
|
|
- for i in range(1, 101):
|
|
|
- elidx = [s.properties['ID'].values for s in secs if
|
|
|
- s.name.startswith('Electrode') and
|
|
|
- s.properties['ConnectorAlignedID'].values[0] == i]
|
|
|
- if len(elidx) == 0:
|
|
|
- bl.annotations['avail_electrode_ids'].append(-1)
|
|
|
- elif len(elidx) == 1:
|
|
|
- bl.annotations['avail_electrode_ids'].append(elidx[0])
|
|
|
- else:
|
|
|
- raise ValueError("Electrode IDs in odML file are corrupt. "
|
|
|
- "ID %i occurs %i times" % (i, len(elidx)))
|
|
|
+ bl.annotate(avail_electrode_ids=self.avail_electrode_ids)
|
|
|
|
|
|
# TODO: add list of behavioral channels
|
|
|
# bl.annotate(avail_behavsig_indexes=[])
|
|
|
|
|
|
def __correct_filter_shifts(self, asig):
|
|
|
- if self.odmldoc and asig.annotations['channel_id'] in range(1, 129):
|
|
|
+ if self.odmldoc and asig.annotations['neural_signal']:
|
|
|
+ # assert all signals are originating from same nsx file
|
|
|
+ if len(np.unique(asig.array_annotations['nsx'])) > 1:
|
|
|
+ raise ValueError('Multiple nsx file origins (%s) in single AnalogSignal'
|
|
|
+ ''.format(asig.array_annotations['nsx']))
|
|
|
+
|
|
|
# Get and correct for shifts
|
|
|
- sec = self.odmldoc[
|
|
|
- 'Cerebus']['NeuralSignalProcessor']['NeuralSignals'][
|
|
|
- 'Filter_ns%i' % asig.annotations['nsx']]
|
|
|
+ filter_name = 'Filter_ns%i' % asig.array_annotations['nsx'][0] # use nsx of 1st signal
|
|
|
+ sec = self.odmldoc['Cerebus']['NeuralSignalProcessor']['NeuralSignals'][filter_name]
|
|
|
shift = pq.Quantity(
|
|
|
sec.properties['EstimatedShift'].values[0],
|
|
|
sec.properties['EstimatedShift'].unit)
|
|
@@ -1050,10 +1064,10 @@ class ReachGraspIO(BlackrockIO):
|
|
|
return merged_event
|
|
|
|
|
|
def read_block(
|
|
|
- self, index=None, name=None, description=None, nsx_to_load='none',
|
|
|
+ self, index=None, block_index=0, name=None, description=None, nsx_to_load='none',
|
|
|
n_starts=None, n_stops=None, channels=range(1, 97), units='none',
|
|
|
load_waveforms=False, load_events=False, scaling='raw',
|
|
|
- correct_filter_shifts=True, lazy=False, cascade=True):
|
|
|
+ correct_filter_shifts=True, lazy=False, cascade=True, **kwargs):
|
|
|
"""
|
|
|
Reads file contents as a Neo Block.
|
|
|
|
|
@@ -1064,33 +1078,35 @@ class ReachGraspIO(BlackrockIO):
|
|
|
The Block contains one ChannelIndex per channel.
|
|
|
|
|
|
Args:
|
|
|
- index (None, int):
|
|
|
+ index (None, int): DEPRECATED
|
|
|
If not None, index of block is set to user input.
|
|
|
+ block_index (int):
|
|
|
+ Index of block to load.
|
|
|
name (None, str):
|
|
|
If None, name is set to default, otherwise it is set to user
|
|
|
input.
|
|
|
description (None, str):
|
|
|
If None, description is set to default, otherwise it is set to
|
|
|
user input.
|
|
|
- nsx_to_load (int, list, str):
|
|
|
+ nsx_to_load (int, list, str): DEPRECATED
|
|
|
ID(s) of nsx file(s) from which to load data, e.g., if set to
|
|
|
5 only data from the ns5 file are loaded. If 'none' or empty
|
|
|
list, no nsx files and therefore no analog signals are loaded.
|
|
|
If 'all', data from all available nsx are loaded.
|
|
|
- n_starts (None, Quantity, list):
|
|
|
+ n_starts (None, Quantity, list): DEPRECATED
|
|
|
Start times for data in each segment. Number of entries must be
|
|
|
equal to length of n_stops. If None, intrinsic recording start
|
|
|
times of files set are used.
|
|
|
- n_stops (None, Quantity, list):
|
|
|
+ n_stops (None, Quantity, list): DEPRECATED
|
|
|
Stop times for data in each segment. Number of entries must be
|
|
|
equal to length of n_starts. If None, intrinsic recording stop
|
|
|
times of files set are used.
|
|
|
- channels (int, list, str):
|
|
|
+ channels (int, list, str): DEPRECATED
|
|
|
Channel id(s) from which to load data. If 'none' or empty list,
|
|
|
no channels and therefore no analog signal or spiketrains are
|
|
|
loaded. If 'all', all available channels are loaded. By
|
|
|
default, all neural channels (1-96) are loaded.
|
|
|
- units (int, list, str, dict):
|
|
|
+ units (int, list, str, dict): DEPRECATED
|
|
|
ID(s) of unit(s) to load. If 'none' or empty list, no units and
|
|
|
therefore no spiketrains are loaded. If 'all', all available
|
|
|
units are loaded. If dict, the above can be specified
|
|
@@ -1098,9 +1114,9 @@ class ReachGraspIO(BlackrockIO):
|
|
|
loads unit 5 from channel 1 and all units from channel 2.
|
|
|
load_waveforms (boolean):
|
|
|
If True, waveforms are attached to all loaded spiketrains.
|
|
|
- load_events (boolean):
|
|
|
+ load_events (boolean): DEPRECATED
|
|
|
If True, all recorded events are loaded.
|
|
|
- scaling (str):
|
|
|
+ scaling (str): DEPRECATED
|
|
|
Determines whether time series of individual
|
|
|
electrodes/channels are returned as AnalogSignals containing
|
|
|
raw integer samples ('raw'), or scaled to arrays of floats
|
|
@@ -1115,8 +1131,10 @@ class ReachGraspIO(BlackrockIO):
|
|
|
/Cerebus/NeuralSignalProcessor/NeuralSignals/Filter_nsX/
|
|
|
lazy (bool):
|
|
|
If True, only the shape of the data is loaded.
|
|
|
- cascade (bool or "lazy"):
|
|
|
+ cascade (bool or "lazy"): DEPRECATED
|
|
|
If True, only the block without children is returned.
|
|
|
+ kwargs:
|
|
|
+ Additional keyword arguments are forwarded to the BlackrockIO.
|
|
|
|
|
|
Returns:
|
|
|
Block (neo.segment.Block):
|
|
@@ -1434,23 +1452,48 @@ class ReachGraspIO(BlackrockIO):
|
|
|
if not name:
|
|
|
name = 'Reachgrasp Recording Data Block'
|
|
|
if not description:
|
|
|
- description = \
|
|
|
- "Block of reach-to-grasp project data from Blackrock file set."
|
|
|
+ description = "Block of reach-to-grasp project data from Blackrock file set."
|
|
|
+
|
|
|
+ if index is not None:
|
|
|
+ warnings.warn('`index` is deprecated and will be replaced by `block_index`.')
|
|
|
+
|
|
|
+ if nsx_to_load != 'none':
|
|
|
+ warnings.warn('`nsx_to_load` is deprecated for `read_block`. '
|
|
|
+ 'Specify `nsx_to_load when initializing the IO or use lazy loading.')
|
|
|
+ if n_starts is not None:
|
|
|
+ warnings.warn('`n_starts` is deprecated. Use lazy loading instead.')
|
|
|
+
|
|
|
+ if n_stops is not None:
|
|
|
+ warnings.warn('`n_stops` is deprecated. Use lazy loading instead.')
|
|
|
+
|
|
|
+ if channels != range(1, 97):
|
|
|
+ warnings.warn('`channels` is deprecated. Use lazy loading instead.')
|
|
|
+
|
|
|
+ if units != 'none':
|
|
|
+ warnings.warn('`units` is deprecated. Use lazy loading instead.')
|
|
|
+
|
|
|
+ if load_events is not False:
|
|
|
+ warnings.warn('`load_events` is deprecated. Use lazy loading instead.')
|
|
|
+
|
|
|
+ if scaling != 'raw':
|
|
|
+ warnings.warn('`scaling` is deprecated.')
|
|
|
+
|
|
|
+ if cascade is not True:
|
|
|
+ warnings.warn('`cascade` is deprecated. Use lazy loading instead.')
|
|
|
|
|
|
# Load neo block
|
|
|
bl = BlackrockIO.read_block(
|
|
|
- self, index=index, name=name, description=description,
|
|
|
- nsx_to_load=nsx_to_load, n_starts=n_starts, n_stops=n_stops,
|
|
|
- channels=channels, units=units, load_waveforms=load_waveforms,
|
|
|
- load_events=load_events, scaling=scaling, lazy=lazy,
|
|
|
- cascade=cascade)
|
|
|
+ self, block_index=block_index, load_waveforms=load_waveforms, lazy=lazy, **kwargs)
|
|
|
+
|
|
|
+ if name is not None:
|
|
|
+ bl.name = name
|
|
|
+ if description is not None:
|
|
|
+ bl.description = description
|
|
|
|
|
|
bl.annotate(conditions=[])
|
|
|
for seg in bl.segments:
|
|
|
- if load_events and not lazy:
|
|
|
- if 'condition' in list(seg.annotations):
|
|
|
- bl.annotations['conditions'].append(
|
|
|
- seg.annotations['condition'])
|
|
|
+ if 'condition' in list(seg.annotations):
|
|
|
+ bl.annotations['conditions'].append(seg.annotations['condition'])
|
|
|
|
|
|
if self.odmldoc:
|
|
|
self.__annotate_block_with_odml(bl)
|
|
@@ -1465,10 +1508,10 @@ class ReachGraspIO(BlackrockIO):
|
|
|
return bl
|
|
|
|
|
|
def read_segment(
|
|
|
- self, n_start, n_stop, name=None, description=None, index=None,
|
|
|
+ self, block_index=0, seg_index=0, name=None, description=None, index=None,
|
|
|
nsx_to_load='none', channels=range(1, 97), units='none',
|
|
|
load_waveforms=False, load_events=False, scaling='raw',
|
|
|
- correct_filter_shifts=True, lazy=False, cascade=True):
|
|
|
+ correct_filter_shifts=True, lazy=False, cascade=True, **kwargs):
|
|
|
"""
|
|
|
Reads file contents as a Neo Block.
|
|
|
|
|
@@ -1479,31 +1522,32 @@ class ReachGraspIO(BlackrockIO):
|
|
|
The Block contains one ChannelIndex per channel.
|
|
|
|
|
|
Args:
|
|
|
- n_start (Quantity):
|
|
|
+ n_start (Quantity): DEPRECATED
|
|
|
Start time of maximum time range of signals contained in this
|
|
|
- segment.
|
|
|
- n_stop (Quantity):
|
|
|
+ segment. Deprecated, use lazy loading instead.
|
|
|
+ n_stop (Quantity): DEPRECATED
|
|
|
Stop time of maximum time range of signals contained in this
|
|
|
- segment.
|
|
|
+ segment. Deprecated, use lazy loading instead.
|
|
|
name (None, string):
|
|
|
If None, name is set to default, otherwise it is set to user
|
|
|
input.
|
|
|
description (None, string):
|
|
|
If None, description is set to default, otherwise it is set to
|
|
|
user input.
|
|
|
- index (None, int):
|
|
|
+ index (None, int): DEPRECATED
|
|
|
If not None, index of segment is set to user index.
|
|
|
+ Deprecated, use `seg_index` instead.
|
|
|
nsx_to_load (int, list, str):
|
|
|
ID(s) of nsx file(s) from which to load data, e.g., if set to
|
|
|
5 only data from the ns5 file are loaded. If 'none' or empty
|
|
|
list, no nsx files and therefore no analog signals are loaded.
|
|
|
If 'all', data from all available nsx are loaded.
|
|
|
- channels (int, list, str):
|
|
|
+ channels (int, list, str): DEPRECATED
|
|
|
Channel id(s) from which to load data. If 'none' or empty list,
|
|
|
no channels and therefore no analog signal or spiketrains are
|
|
|
loaded. If 'all', all available channels are loaded. By
|
|
|
default, all neural channels (1-96) are loaded.
|
|
|
- units (int, list, str, dict):
|
|
|
+ units (int, list, str, dict): DEPRECATED
|
|
|
ID(s) of unit(s) to load. If 'none' or empty list, no units and
|
|
|
therefore no spiketrains are loaded. If 'all', all available
|
|
|
units are loaded. If dict, the above can be specified
|
|
@@ -1511,9 +1555,9 @@ class ReachGraspIO(BlackrockIO):
|
|
|
loads unit 5 from channel 1 and all units from channel 2.
|
|
|
load_waveforms (boolean):
|
|
|
If True, waveforms are attached to all loaded spiketrains.
|
|
|
- load_events (boolean):
|
|
|
+ load_events (boolean): DEPRECATED
|
|
|
If True, all recorded events are loaded.
|
|
|
- scaling (str):
|
|
|
+ scaling (str): DEPRECATED
|
|
|
Determines whether time series of individual
|
|
|
electrodes/channels are returned as AnalogSignals containing
|
|
|
raw integer samples ('raw'), or scaled to arrays of floats
|
|
@@ -1528,52 +1572,82 @@ class ReachGraspIO(BlackrockIO):
|
|
|
/Cerebus/NeuralSignalProcessor/NeuralSignals/Filter_nsX/
|
|
|
lazy (boolean):
|
|
|
If True, only the shape of the data is loaded.
|
|
|
- cascade (boolean):
|
|
|
+ cascade (boolean): DEPRECATED
|
|
|
If True, only the segment without children is returned.
|
|
|
+ kwargs:
|
|
|
+ Additional keyword arguments are forwarded to the BlackrockIO.
|
|
|
|
|
|
Returns:
|
|
|
Segment (neo.segment.Segment):
|
|
|
Segment linking to all loaded Neo objects. See documentation of
|
|
|
read_block() for a full list of annotations per Neo object.
|
|
|
"""
|
|
|
+
|
|
|
+ if index is not None:
|
|
|
+ warnings.warn('`index` is deprecated and will be replaced by `segment_index`.')
|
|
|
+
|
|
|
+ if nsx_to_load != 'none':
|
|
|
+ warnings.warn('`nsx_to_load` is deprecated for `read_block`. '
|
|
|
+ 'Specify `nsx_to_load when initializing the IO or use lazy loading.')
|
|
|
+
|
|
|
+ if channels != range(1, 97):
|
|
|
+ warnings.warn('`channels` is deprecated. Use lazy loading instead.')
|
|
|
+
|
|
|
+ if units != 'none':
|
|
|
+ warnings.warn('`units` is deprecated. Use lazy loading instead.')
|
|
|
+
|
|
|
+ if load_events is not False:
|
|
|
+ warnings.warn('`load_events` is deprecated. Use lazy loading instead.')
|
|
|
+
|
|
|
+ if scaling != 'raw':
|
|
|
+ warnings.warn('`scaling` is deprecated.')
|
|
|
+
|
|
|
+ if cascade is not True:
|
|
|
+ warnings.warn('`cascade` is deprecated. Use lazy loading instead.')
|
|
|
+
|
|
|
# Load neo block
|
|
|
seg = BlackrockIO.read_segment(
|
|
|
- self, n_start, n_stop, name=name, description=description,
|
|
|
- index=index, nsx_to_load=nsx_to_load, channels=channels,
|
|
|
- units=units, load_waveforms=load_waveforms,
|
|
|
- load_events=load_events, scaling=scaling, lazy=lazy,
|
|
|
- cascade=cascade)
|
|
|
+ self, block_index=block_index, seg_index=seg_index, load_waveforms=load_waveforms,
|
|
|
+ lazy=lazy, **kwargs)
|
|
|
+
|
|
|
+ if name is not None:
|
|
|
+ seg.name = name
|
|
|
+ if description is not None:
|
|
|
+ seg.description = description
|
|
|
+
|
|
|
+ # load data of all events and epochs
|
|
|
+ for ev_idx, event in enumerate(seg.events):
|
|
|
+ seg.events[ev_idx] = event.load()
|
|
|
+ seg.events[ev_idx].segment = seg
|
|
|
+ for ep_idx, epoch in enumerate(seg.epochs):
|
|
|
+ seg.epochs[ep_idx] = epoch.load()
|
|
|
+ seg.epochs[ep_idx].segment = seg
|
|
|
|
|
|
for asig in seg.analogsignals:
|
|
|
- asig.name = str(asig.name)
|
|
|
self.__annotate_analogsignals_with_odml(asig)
|
|
|
if correct_filter_shifts:
|
|
|
self.__correct_filter_shifts(asig)
|
|
|
|
|
|
- if load_events and not lazy:
|
|
|
- for ev in seg.events:
|
|
|
- # Modify digital trial events to include semantic event
|
|
|
- # informations
|
|
|
- if ev.name == 'digital_input_port':
|
|
|
- self.__annotate_dig_trial_events(ev)
|
|
|
- self.__add_rejection_to_event(ev)
|
|
|
-
|
|
|
- cnd = self.__extract_task_condition(
|
|
|
- ev.array_annotations['belongs_to_trialtype'])
|
|
|
- seg.annotate(condition=cnd)
|
|
|
-
|
|
|
- # If digital trial events exist, extract analog events from odML
|
|
|
- # and create one common event array
|
|
|
- if len(seg.events) > 0 and self.odmldoc:
|
|
|
- analog_event = self.__extract_analog_events_from_odml(
|
|
|
- seg.t_start, seg.t_stop)
|
|
|
- self.__add_rejection_to_event(analog_event)
|
|
|
- seg.events.append(analog_event)
|
|
|
-
|
|
|
- merged_event = self.__merge_digital_analog_events(
|
|
|
- seg.events)
|
|
|
- self.__add_rejection_to_event(merged_event)
|
|
|
- seg.events.append(merged_event)
|
|
|
+ for ev in seg.events:
|
|
|
+ # Modify digital trial events to include semantic event
|
|
|
+ # informations
|
|
|
+ if ev.name == 'digital_input_port':
|
|
|
+ self.__annotate_dig_trial_events(ev)
|
|
|
+ self.__add_rejection_to_event(ev)
|
|
|
+
|
|
|
+ cnd = self.__extract_task_condition(ev.array_annotations['belongs_to_trialtype'])
|
|
|
+ seg.annotate(condition=cnd)
|
|
|
+
|
|
|
+ # If digital trial events exist, extract analog events from odML
|
|
|
+ # and create one common event array
|
|
|
+ if len(seg.events) > 0 and self.odmldoc:
|
|
|
+ analog_event = self.__extract_analog_events_from_odml(seg.t_start, seg.t_stop)
|
|
|
+ self.__add_rejection_to_event(analog_event)
|
|
|
+ seg.events.append(analog_event)
|
|
|
+
|
|
|
+ merged_event = self.__merge_digital_analog_events(seg.events)
|
|
|
+ self.__add_rejection_to_event(merged_event)
|
|
|
+ seg.events.append(merged_event)
|
|
|
|
|
|
return seg
|
|
|
|