Beispiel #1
0
def test_add_ragged_data_to_dynamic_table(units_table, spike_times):

    write_nwb.add_ragged_data_to_dynamic_table(table=units_table,
                                               data=spike_times,
                                               column_name='spike_times')

    assert np.allclose([1, 2, 3, 4, 5, 6], units_table['spike_times'][0])
    assert np.allclose([], units_table['spike_times'][1])
    assert np.allclose([13, 4, 12], units_table['spike_times'][2])
Beispiel #2
0
                      waveform_duration=duration,
                      cluster_depths=cluster_depths[i],
                      sampling_rate=30000.0)

# Add spike amps and depths
amps = {}
depths = {}

for c in cluster_info.keys():
    amps[c] = spike_amps[cluster_info[c]]
    depths[c] = spike_depths[cluster_info[c]]

add_ragged_data_to_dynamic_table(
    table=nwb_file.units,
    data=amps,
    column_name='spike_amps',
    column_description=
    'The peak-to-trough amplitude, obtained from the template and '
    'template-scaling amplitude returned by Kilosort (not from the raw data).')
add_ragged_data_to_dynamic_table(
    table=nwb_file.units,
    data=depths,
    column_name='spike_depths',
    column_description=
    'The position of the center of mass of the spike on the probe, '
    'determined from the principal component features returned by Kilosort. '
    'The deepest channel on the probe is depth=0, and the most superficial is depth=3820.'
)
################################################################################
# WRITE TO FILE
Beispiel #3
0
def neural_data(nwb_file):
    """
    Add in probes as devices and electrode groups.
    """
    probe_descriptions = pd.read_csv('probes.description.tsv', sep='\t')
    probe_descriptions = list(probe_descriptions['description'])
    electrode_groups = list()
    for i in range(len(probe_descriptions)):
        probe_device = Device(name=str(i))
        probe_electrode_group = ElectrodeGroup(
            name='Probe' + str(i + 1),
            description='Neuropixels Phase3A opt3',
            device=probe_device,
            location='')
        nwb_file.add_device(probe_device)
        electrode_groups.append(probe_electrode_group)
        nwb_file.add_electrode_group(probe_electrode_group)

    # CHANNELS
    """
    Add channel information into the Electrode Table.
    """
    # Read data
    insertion_df = pd.read_csv('probes.insertion.tsv', sep='\t')
    insertion_df['group_name'] = insertion_df.index.values

    channel_site = read_npy_file('channels.site.npy')
    channel_brain = pd.read_csv('channels.brainLocation.tsv', sep='\t')

    channel_probes = read_npy_file('channels.probe.npy')
    channel_probes = np.ravel(channel_probes.astype(int))
    channel_table = pd.DataFrame(columns=['group_name'])
    channel_table['group_name'] = channel_probes
    channel_table = channel_table.merge(insertion_df, 'left', 'group_name')

    entry_point_rl = np.array(channel_table['entry_point_rl'])
    entry_point_ap = np.array(channel_table['entry_point_ap'])
    axial_angle = np.array(channel_table['axial_angle'])
    vertical_angle = np.array(channel_table['vertical_angle'])
    horizontal_angle = np.array(channel_table['horizontal_angle'])
    distance_advanced = np.array(channel_table['distance_advanced'])

    locations = np.array(channel_brain['allen_ontology'])
    groups = np.asarray([electrode_groups[c] for c in channel_probes])
    channel_site_pos = read_npy_file('channels.sitePositions.npy')

    for i in range(len(groups)):
        nwb_file.add_electrode(x=float('NaN'),
                               y=float('NaN'),
                               z=float('NaN'),
                               imp=float('NaN'),
                               location=str(locations[i]),
                               group=groups[i],
                               filtering='none')

    # Add Electrode columns
    nwb_file.add_electrode_column(
        name='site_id',
        description='The site number, in within-probe numbering, of the channel '
        '(in practice for this dataset this always starts at zero and '
        'counts up to 383 on each probe so is equivalent to the channel '
        'number - but if switches had been used, the site number could '
        'have been different than the channel number).',
        data=np.ravel(channel_site))
    nwb_file.add_electrode_column(
        name='site_position',
        description=
        'The x- and y-position of the site relative to the face of the probe '
        '(where the first column is across the face of the probe laterally '
        'and the second is the position along the length of the probe; '
        'the sites nearest the tip have second column=0).',
        data=channel_site_pos)
    nwb_file.add_electrode_column(
        name='ccf_ap',
        description=
        'The AP position in Allen Institute\'s Common Coordinate Framework.',
        data=np.array(channel_brain['ccf_ap']))
    nwb_file.add_electrode_column(
        name='ccf_dv',
        description=
        'The DV position in Allen Institute\'s Common Coordinate Framework.',
        data=np.array(channel_brain['ccf_dv']))
    nwb_file.add_electrode_column(
        name='ccf_lr',
        description=
        'The LR position in Allen Institute\'s Common Coordinate Framework.',
        data=np.array(channel_brain['ccf_lr']))

    # Insertion
    nwb_file.add_electrode_column(
        name='entry_point_rl',
        description=
        'mediolateral position of probe entry point relative to midline (microns). '
        'Positive means right',
        data=entry_point_rl)
    nwb_file.add_electrode_column(
        name='entry_point_ap',
        description=
        'anteroposterior position of probe entry point relative to bregma (microns). '
        'Positive means anterior',
        data=entry_point_ap)
    nwb_file.add_electrode_column(
        name='vertical_angle',
        description='vertical angle of probe (degrees). Zero means horizontal. '
        'Positive means pointing down',
        data=vertical_angle)
    nwb_file.add_electrode_column(
        name='horizontal_angle',
        description=
        'horizontal angle of probe (degrees), after vertical rotation. '
        'Zero means anterior. Positive means counterclockwise (i.e. left).',
        data=horizontal_angle)
    nwb_file.add_electrode_column(
        name='axial_angle',
        description=
        'axial angle of probe (degrees). Zero means that without vertical and horizontal rotations, '
        'the probe contacts would be pointing up. Positive means "counterclockwise.',
        data=axial_angle)
    nwb_file.add_electrode_column(
        name='distance_advanced',
        description=
        'How far the probe was moved forward from its entry point. (microns).',
        data=distance_advanced)
    # CLUSTERS & SPIKES
    """
    Add cluster information into the Unit Table.
    """
    # Read data
    cluster_probe = read_npy_file('clusters.probes.npy')
    cluster_probe = np.ravel(cluster_probe.astype(int))
    cluster_channel = read_npy_file('clusters.peakChannel.npy')
    cluster_depths = read_npy_file('clusters.depths.npy')
    phy_annotations = np.ravel(read_npy_file('clusters._phy_annotation.npy'))
    waveform_chans = read_npy_file('clusters.templateWaveformChans.npy')
    waveform_chans = waveform_chans.astype(int)
    waveform = read_npy_file('clusters.templateWaveforms.npy')
    waveform_duration = read_npy_file('clusters.waveformDuration.npy')
    spike_to_clusters = read_npy_file('spikes.clusters.npy')
    spike_times = read_npy_file('spikes.times.npy')
    spike_amps = read_npy_file('spikes.amps.npy')
    spike_depths = read_npy_file('spikes.depths.npy')

    # Sorting spikes into clusters
    cluster_info = dict()
    for i in range(len(spike_to_clusters)):
        s = int(spike_to_clusters[i])
        if s not in cluster_info:
            cluster_info[s] = [i]
        else:
            cluster_info[s].append(i)

    # Add Unit Columns
    nwb_file.add_unit_column(
        name='peak_channel',
        description=
        'The channel number of the location of the peak of the cluster\'s waveform.'
    )
    nwb_file.add_unit_column(
        name='waveform_duration',
        description=
        'The trough-to-peak duration of the waveform on the peak channel.')
    nwb_file.add_unit_column(
        name='phy_annotations',
        description=
        '0 = noise (these are already excluded and don\'t appear in this dataset '
        'at all); 1 = MUA (i.e. presumed to contain spikes from multiple neurons; '
        'these are not analyzed in any analyses in the paper); 2 = Good (manually '
        'labeled); 3 = Unsorted. In this dataset \'Good\' was applied in a few but '
        'not all datasets to included neurons, so in general the neurons with '
        '_phy_annotation>=2 are the ones that should be included.',
    )
    nwb_file.add_unit_column(
        name='cluster_depths',
        description=
        'The position of the center of mass of the template of the cluster, '
        'relative to the probe. The deepest channel on the probe is depth=0, '
        'and the most superficial is depth=3820. Units: µm',
    )
    nwb_file.add_unit_column(
        name='sampling_rate',
        description='Sampling rate, in Hz.',
    )

    # Add Units by cluster
    for i in cluster_info:
        c = cluster_info[i]
        times = np.array(spike_times[c])
        annotations = phy_annotations[i]
        annotations = annotations.astype(int)
        channel = cluster_channel[i]
        channel = channel.astype(int)
        duration = waveform_duration[i]
        duration = duration.astype(int)

        nwb_file.add_unit(spike_times=np.ravel(times),
                          electrodes=waveform_chans[i, :],
                          electrode_group=electrode_groups[cluster_probe[i]],
                          waveform_mean=waveform[i, :, :],
                          id=i,
                          phy_annotations=annotations,
                          peak_channel=channel,
                          waveform_duration=duration,
                          cluster_depths=cluster_depths[i],
                          sampling_rate=30000.0)

    # Add spike amps and depths
    amps = {}
    depths = {}

    for c in cluster_info.keys():
        amps[c] = spike_amps[cluster_info[c]]
        depths[c] = spike_depths[cluster_info[c]]

    add_ragged_data_to_dynamic_table(
        table=nwb_file.units,
        data=amps,
        column_name='spike_amps',
        column_description=
        'The peak-to-trough amplitude, obtained from the template and '
        'template-scaling amplitude returned by Kilosort (not from the raw data).'
    )
    add_ragged_data_to_dynamic_table(
        table=nwb_file.units,
        data=depths,
        column_name='spike_depths',
        column_description=
        'The position of the center of mass of the spike on the probe, '
        'determined from the principal component features returned by Kilosort. '
        'The deepest channel on the probe is depth=0, and the most superficial is depth=3820.'
    )