Пример #1
0
def get_aligned_channels(ins, chn_coords, one, ba=None, save_dir=None):

    ba = ba or AllenAtlas(25)
    depths = chn_coords[:, 1]
    xyz = np.array(ins['json']['xyz_picks']) / 1e6
    traj = one.alyx.rest('trajectories', 'list', probe_insertion=ins['id'],
                         provenance='Ephys aligned histology track')[0]
    align_key = ins['json']['extended_qc']['alignment_stored']
    feature = traj['json'][align_key][0]
    track = traj['json'][align_key][1]
    ephysalign = EphysAlignment(xyz, depths, track_prev=track,
                                feature_prev=feature,
                                brain_atlas=ba, speedy=True)
    channels_mlapdv = np.int32(ephysalign.get_channel_locations(feature, track) * 1e6)
    channels_atlas_ids = ephysalign.get_brain_locations(channels_mlapdv / 1e6)['id']

    out_files = []
    if save_dir is not None:
        f_name = Path(save_dir).joinpath('channels.mlapdv.npy')
        np.save(f_name, channels_mlapdv)
        out_files.append(f_name)

        f_name = Path(save_dir).joinpath('channels.brainLocationIds_ccf_2017.npy')
        np.save(f_name, channels_atlas_ids)
        out_files.append(f_name)

    return out_files
Пример #2
0
    def compute_similarity_matrix(self):
        """
        Computes the similarity matrix between each alignment stored in the ephys aligned
        trajectory. Similarity matrix based on number of clusters that share brain region and
        parent brain region
        """

        r = regions_from_allen_csv()

        clusters = dict()
        for iK, key in enumerate(self.align_keys_sorted):
            # Location of reference lines used for alignment
            feature = np.array(self.alignments[key][0])
            track = np.array(self.alignments[key][1])

            # Instantiate EphysAlignment object
            ephysalign = EphysAlignment(self.xyz_picks,
                                        self.depths,
                                        track_prev=track,
                                        feature_prev=feature,
                                        brain_atlas=self.brain_atlas)

            # Find xyz location of all channels
            xyz_channels = ephysalign.get_channel_locations(feature, track)
            brain_regions = ephysalign.get_brain_locations(xyz_channels)

            # Find the location of clusters along the alignment
            cluster_info = dict()
            cluster_info['brain_id'] = brain_regions['id'][self.cluster_chns]
            cluster_info['parent_id'] = r.get(
                ids=cluster_info['brain_id']).parent.astype(int)
            clusters.update({key: cluster_info})

        sim_matrix = np.zeros(
            (len(self.align_keys_sorted), len(self.align_keys_sorted)))

        for ik, key in enumerate(self.align_keys_sorted):
            for ikk, key2 in enumerate(self.align_keys_sorted):
                same_id = np.where(
                    clusters[key]['brain_id'] == clusters[key2]['brain_id'])[0]
                not_same_id = \
                    np.where(clusters[key]['brain_id'] != clusters[key2]['brain_id'])[0]
                same_parent = np.where(
                    clusters[key]['parent_id'][not_same_id] == clusters[key2]
                    ['parent_id'][not_same_id])[0]
                sim_matrix[ik, ikk] = len(same_id) + (len(same_parent) * 0.5)
        # Normalise
        sim_matrix_norm = sim_matrix / np.max(sim_matrix)

        return sim_matrix_norm
Пример #3
0
class TestsEphysReconstruction(unittest.TestCase):

    def setUp(self):
        self.ephysalign = EphysAlignment(xyz_picks, track_prev=track_prev,
                                         feature_prev=feature_prev, brain_atlas=brain_atlas)
        self.feature = self.ephysalign.feature_init
        self.track = self.ephysalign.track_init

    def test_channel_locations(self):
        xyz_channels = self.ephysalign.get_channel_locations(self.feature, self.track,
                                                             depths=depths)
        self.assertTrue(np.all(np.isclose(xyz_channels[0, :], xyz_channels_ref[0])))
        self.assertTrue(np.all(np.isclose(xyz_channels[-1, :], xyz_channels_ref[-1])))
        brain_regions = self.ephysalign.get_brain_locations(xyz_channels)
        self.assertTrue(np.all(np.equal(np.unique(brain_regions.acronym), brain_regions_ref)))
Пример #4
0
    def upload_channels(self, alignment_key, upload_alyx, upload_flatiron):
        """
        Upload channels to alyx and flatiron based on the alignment specified by the alignment key
        """

        feature = np.array(self.alignments[alignment_key][0])
        track = np.array(self.alignments[alignment_key][1])
        ephysalign = EphysAlignment(self.xyz_picks,
                                    self.depths,
                                    track_prev=track,
                                    feature_prev=feature,
                                    brain_atlas=self.brain_atlas)

        # Find the channels
        channels_mlapdv = np.int32(
            ephysalign.get_channel_locations(feature, track) * 1e6)
        channels_brainID = ephysalign.get_brain_locations(channels_mlapdv /
                                                          1e6)['id']

        # Find the clusters
        r = regions_from_allen_csv()
        clusters_mlapdv = channels_mlapdv[self.cluster_chns]
        clusters_brainID = channels_brainID[self.cluster_chns]
        clusters_brainAcro = r.get(ids=clusters_brainID).acronym

        # upload datasets to flatiron
        files_to_register = []
        if upload_flatiron:
            ftp_patcher = FTPPatcher(one=self.one)
            insertion = self.one.alyx.rest('insertions', 'read', id=self.eid)
            alf_path = self.one.path_from_eid(insertion['session']).joinpath(
                'alf', insertion['name'])
            alf_path.mkdir(exist_ok=True, parents=True)

            # Make the channels.mlapdv dataset
            f_name = alf_path.joinpath('channels.mlapdv.npy')
            np.save(f_name, channels_mlapdv)
            files_to_register.append(f_name)

            # Make the channels.brainLocationIds dataset
            f_name = alf_path.joinpath(
                'channels.brainLocationIds_ccf_2017.npy')
            np.save(f_name, channels_brainID)
            files_to_register.append(f_name)

            # Make the clusters.mlapdv dataset
            f_name = alf_path.joinpath('clusters.mlapdv.npy')
            np.save(f_name, clusters_mlapdv)
            files_to_register.append(f_name)

            # Make the clusters.brainLocationIds dataset
            f_name = alf_path.joinpath(
                'clusters.brainLocationIds_ccf_2017.npy')
            np.save(f_name, clusters_brainID)
            files_to_register.append(f_name)

            # Make the clusters.brainLocationAcronym dataset
            f_name = alf_path.joinpath(
                'clusters.brainLocationAcronyms_ccf_2017.npy')
            np.save(f_name, clusters_brainAcro)
            files_to_register.append(f_name)

            self.log.info("Writing datasets to FlatIron")
            ftp_patcher.create_dataset(path=files_to_register,
                                       created_by=self.one._par.ALYX_LOGIN)

        # Need to change channels stored on alyx as well as the stored key is not the same as the
        # latest key
        if upload_alyx:
            if alignment_key != self.align_keys_sorted[0]:
                histology.register_aligned_track(self.eid,
                                                 channels_mlapdv / 1e6,
                                                 chn_coords=SITES_COORDINATES,
                                                 one=self.one,
                                                 overwrite=True,
                                                 channels=self.channels)

                ephys_traj = self.one.alyx.rest(
                    'trajectories',
                    'list',
                    probe_insertion=self.eid,
                    provenance='Ephys aligned histology track')
                patch_dict = {'json': self.alignments}
                self.one.alyx.rest('trajectories',
                                   'partial_update',
                                   id=ephys_traj[0]['id'],
                                   data=patch_dict)

        return files_to_register
Пример #5
0
    def upload_channels(self, alignment_key, upload_alyx, upload_flatiron):
        """
        Upload channels to alyx and flatiron based on the alignment specified by the alignment key
        """

        feature = np.array(self.alignments[alignment_key][0])
        track = np.array(self.alignments[alignment_key][1])

        try:
            meta_dset = self.one.list_datasets(self.insertion['session'], '*ap.meta',
                                               collection=f'raw_ephys_data/{self.insertion["name"]}')

            meta_file = self.one.load_dataset(self.insertion['session'], meta_dset[0].split('/')[-1],
                                              collection=f'raw_ephys_data/{self.insertion["name"]}',
                                              download_only=True)
            geometry = spikeglx.read_geometry(meta_file)
            chns = np.c_[geometry['x'], geometry['y']]
        except Exception as err:
            self.log.warning(f"Could not compute channel locations from meta file, errored with message: {err}. "
                             f"Will use default Neuropixel 1 channels")
            geometry = trace_header(version=1)
            chns = np.c_[geometry['x'], geometry['y']]

        ephysalign = EphysAlignment(self.xyz_picks, chns[:, 1],
                                    track_prev=track,
                                    feature_prev=feature,
                                    brain_atlas=self.brain_atlas)
        channels_mlapdv = np.int32(ephysalign.get_channel_locations(feature, track) * 1e6)
        channels_atlas_id = ephysalign.get_brain_locations(channels_mlapdv / 1e6)['id']

        # Need to change channels stored on alyx as well as the stored key is not the same as the latest key
        if upload_alyx:
            if alignment_key != self.align_keys_sorted[0]:
                histology.register_aligned_track(self.eid, channels_mlapdv / 1e6,
                                                 chn_coords=chns, one=self.one,
                                                 overwrite=True, channels=self.channels_flag,
                                                 brain_atlas=self.brain_atlas)

                ephys_traj = self.one.alyx.get(f'/trajectories?&probe_insertion={self.eid}'
                                               '&provenance=Ephys aligned histology track',
                                               clobber=True)
                patch_dict = {'json': self.alignments}
                self.one.alyx.rest('trajectories', 'partial_update', id=ephys_traj[0]['id'],
                                   data=patch_dict)

        files_to_register = []
        if upload_flatiron:
            ftp_patcher = FTPPatcher(one=self.one)

            alf_path = self.one.eid2path(self.insertion['session']).joinpath('alf', self.insertion["name"])
            alf_path.mkdir(exist_ok=True, parents=True)

            f_name = alf_path.joinpath('electrodeSites.mlapdv.npy')
            np.save(f_name, channels_mlapdv)
            files_to_register.append(f_name)

            f_name = alf_path.joinpath('electrodeSites.brainLocationIds_ccf_2017.npy')
            np.save(f_name, channels_atlas_id)
            files_to_register.append(f_name)

            f_name = alf_path.joinpath('electrodeSites.localCoordinates.npy')
            np.save(f_name, chns)
            files_to_register.append(f_name)

            probe_collections = self.one.list_collections(self.insertion['session'], filename='channels*',
                                                          collection=f'alf/{self.insertion["name"]}*')

            for collection in probe_collections:
                chns = self.one.load_dataset(self.insertion['session'], 'channels.localCoordinates', collection=collection)
                ephysalign = EphysAlignment(self.xyz_picks, chns[:, 1],
                                            track_prev=track,
                                            feature_prev=feature,
                                            brain_atlas=self.brain_atlas)
                channels_mlapdv = np.int32(ephysalign.get_channel_locations(feature, track) * 1e6)
                channels_atlas_id = ephysalign.get_brain_locations(channels_mlapdv / 1e6)['id']

                alf_path = self.one.eid2path(self.insertion['session']).joinpath(collection)
                alf_path.mkdir(exist_ok=True, parents=True)

                f_name = alf_path.joinpath('channels.mlapdv.npy')
                np.save(f_name, channels_mlapdv)
                files_to_register.append(f_name)

                f_name = alf_path.joinpath('channels.brainLocationIds_ccf_2017.npy')
                np.save(f_name, channels_atlas_id)
                files_to_register.append(f_name)

            self.log.info("Writing datasets to FlatIron")
            ftp_patcher.create_dataset(path=files_to_register,
                                       created_by=self.one.alyx.user)

        return files_to_register
Пример #6
0
def plot_alignment(insertion, traj, ind=None):
    depths = SITES_COORDINATES[:, 1]
    xyz_picks = np.array(insertion['json']['xyz_picks']) / 1e6

    alignments = traj['json'].copy()
    k = list(alignments.keys())[-1]  # if only I had a Walrus available !
    alignments = {k: alignments[k]}
    # Create a figure and arrange using gridspec
    widths = [1, 2.5]
    heights = [1] * len(alignments)
    gs_kw = dict(width_ratios=widths, height_ratios=heights)
    fig, axis = plt.subplots(len(alignments),
                             2,
                             constrained_layout=True,
                             gridspec_kw=gs_kw,
                             figsize=(8, 9))

    # Iterate over all alignments for trajectory
    # 1. Plot brain regions that channel pass through
    # 2. Plot coronal slice along trajectory with location of channels shown as red points
    # 3. Save results for each alignment into a dict - channels
    channels = {}
    for iK, key in enumerate(alignments):

        # Location of reference lines used for alignmnet
        feature = np.array(alignments[key][0])
        track = np.array(alignments[key][1])
        chn_coords = SITES_COORDINATES
        # Instantiate EphysAlignment object
        ephysalign = EphysAlignment(xyz_picks,
                                    depths,
                                    track_prev=track,
                                    feature_prev=feature)

        # Find xyz location of all channels
        xyz_channels = ephysalign.get_channel_locations(feature, track)
        # Find brain region that each channel is located in
        brain_regions = ephysalign.get_brain_locations(xyz_channels)
        # Add extra keys to store all useful information as one bunch object
        brain_regions['xyz'] = xyz_channels
        brain_regions['lateral'] = chn_coords[:, 0]
        brain_regions['axial'] = chn_coords[:, 1]

        # Store brain regions result in channels dict with same key as in alignment
        channel_info = {key: brain_regions}
        channels.update(channel_info)

        # For plotting -> extract the boundaries of the brain regions, as well as CCF label and colour
        region, region_label, region_colour, _ = ephysalign.get_histology_regions(
            xyz_channels, depths)

        # Make plot that shows the brain regions that channels pass through
        ax_regions = fig.axes[iK * 2]
        for reg, col in zip(region, region_colour):
            height = np.abs(reg[1] - reg[0])
            bottom = reg[0]
            color = col / 255
            ax_regions.bar(x=0.5,
                           height=height,
                           width=1,
                           color=color,
                           bottom=reg[0],
                           edgecolor='w')
        ax_regions.set_yticks(region_label[:, 0].astype(int))
        ax_regions.yaxis.set_tick_params(labelsize=8)
        ax_regions.get_xaxis().set_visible(False)
        ax_regions.set_yticklabels(region_label[:, 1])
        ax_regions.spines['right'].set_visible(False)
        ax_regions.spines['top'].set_visible(False)
        ax_regions.spines['bottom'].set_visible(False)
        ax_regions.hlines([0, 3840],
                          *ax_regions.get_xlim(),
                          linestyles='dashed',
                          linewidth=3,
                          colors='k')
        # ax_regions.plot(np.ones(channel_depths_track.shape), channel_depths_track, '*r')

        # Make plot that shows coronal slice that trajectory passes through with location of channels
        # shown in red
        ax_slice = fig.axes[iK * 2 + 1]
        brain_atlas.plot_tilted_slice(xyz_channels, axis=1, ax=ax_slice)
        ax_slice.plot(xyz_channels[:, 0] * 1e6, xyz_channels[:, 2] * 1e6, 'r*')
        ax_slice.title.set_text(insertion['id'] + '\n' + str(key))

    # Make sure the plot displays
    plt.show()
Пример #7
0
for iK, key in enumerate(alignments):

    # Location of reference lines used for alignmnet
    feature = np.array(alignments[key][0])
    track = np.array(alignments[key][1])

    # Instantiate EphysAlignment object
    ephysalign = EphysAlignment(xyz_picks,
                                depths,
                                track_prev=track,
                                feature_prev=feature)

    # Find xyz location of all channels
    xyz_channels = ephysalign.get_channel_locations(feature, track)
    # Find brain region that each channel is located in
    brain_regions = ephysalign.get_brain_locations(xyz_channels)
    # Add extra keys to store all useful information as one bunch object
    brain_regions['xyz'] = xyz_channels
    brain_regions['lateral'] = chn_coords[:, 0]
    brain_regions['axial'] = chn_coords[:, 1]

    # Store brain regions result in channels dict with same key as in alignment
    channel_info = {key: brain_regions}
    channels.update(channel_info)

    # For plotting -> extract the boundaries of the brain regions, as well as CCF label and colour
    region, region_label, region_colour, _ = ephysalign.get_histology_regions(
        xyz_channels, depths)

    channel_depths_track = (ephysalign.feature2track(depths, feature, track) -
                            ephysalign.track_extent[0])