Skip to content

Commit 1a3d07c

Browse files
committed
Two place cell related additions
- Function for detecting place cells - Function for quantifying place cell reliability
1 parent bd006d7 commit 1a3d07c

File tree

3 files changed

+76
-4
lines changed

3 files changed

+76
-4
lines changed

.vscode/settings.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"python.pythonPath": "C:\\Users\\wm228\\Anaconda3\\envs\\ca_imaging\\python.exe"
3+
}

CircleTrack/MiniscopeFunctions.py

+72-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
find_members,
2727
)
2828

29-
3029
hv.extension("bokeh")
3130
from bokeh.plotting import show
3231
from itertools import product
@@ -41,9 +40,11 @@ def __init__(
4140
spatial_bin_size_radians=0.05,
4241
S_std_thresh=1,
4342
velocity_threshold=7,
43+
place_cell_alpha=0.001,
44+
place_cell_transient_threshold=40,
4445
overwrite_synced_data=False,
4546
overwrite_placefields=False,
46-
overwrite_placefield_trials=False,
47+
overwrite_placefield_trials=True,
4748
overwrite_assemblies=False,
4849
local=True,
4950
):
@@ -196,6 +197,11 @@ def __init__(
196197
with open(fpath, "wb") as file:
197198
pkl.dump(self.assemblies, file)
198199

200+
self.spatial.data['place_cells'] = self.get_place_cells(alpha=place_cell_alpha,
201+
transient_threshold=place_cell_transient_threshold)
202+
self.spatial.meta['place_cell_pval'] = place_cell_alpha
203+
self.spatial.meta['place_cell_transient_threshold'] = place_cell_transient_threshold
204+
199205
def get_pkl_path(self, fname):
200206
if self.meta["local"]:
201207
local_path = get_equivalent_local_path(self.meta["folder"])
@@ -367,7 +373,8 @@ def spatial_activity_by_trial(self):
367373

368374
# Get occupancy this trial.
369375
occupancy = spatial_bin(
370-
positions_this_trial, filler, bins=bin_edges, one_dim=True
376+
positions_this_trial, filler, bins=bin_edges, one_dim=True,
377+
weights=running_this_trial.astype(int)
371378
)[0]
372379

373380
# Weight position by activity of each neuron.
@@ -386,6 +393,68 @@ def spatial_activity_by_trial(self):
386393

387394
return fields, occ_map_by_trial
388395

396+
def get_place_cells(self, alpha=0.001, transient_threshold=40):
397+
n_transients = np.sum(np.sum(self.spatial.data['rasters'], axis=1), axis=1)
398+
place_cells = np.where(np.logical_and(self.spatial.data['spatial_info_pvals'] < alpha,
399+
n_transients> transient_threshold))[0]
400+
401+
return place_cells
402+
403+
def placefield_reliability(self, neuron, field_threshold=0.15, even_split=True, split=4,
404+
show_plot=True):
405+
"""
406+
Compute the trial-by-trial in-field consistency of a neuron (whether it fired in field).
407+
408+
:parameters
409+
---
410+
neuron: int
411+
Neuron number.
412+
413+
field_threshold: float
414+
Percentage of field peak to be considered part of the field.
415+
416+
even_split: bool
417+
Flag to split trials evenly into n parts (defined by the argument split). If False,
418+
instead split is the number of trials in each split.
419+
420+
split: int
421+
If even_split, the number of parts to divide the trial into.
422+
If not even_split, the number of trials in each split.
423+
424+
"""
425+
raster = self.spatial.data['rasters'][neuron]
426+
placefield = self.spatial.data['placefields_normalized'][neuron]
427+
428+
field_bins = np.where(placefield > max(placefield) * field_threshold)[0]
429+
fired_in_field = np.any(raster[:, field_bins], axis=1)
430+
431+
if not even_split:
432+
split = np.arange(split, len(fired_in_field), split)
433+
434+
split_fired_in_field = np.array_split(fired_in_field, split)
435+
436+
# Handles cases where you don't actually want to split the reliability across trials.
437+
if split == 1 and even_split:
438+
reliability = np.sum(split_fired_in_field[0])/len(split_fired_in_field[0])
439+
else:
440+
reliability = [np.sum(fired_in_field) / len(fired_in_field) for fired_in_field in split_fired_in_field]
441+
442+
if show_plot and even_split:
443+
fig, axs = plt.subplots(1,2)
444+
axs[0].imshow(raster > 0, aspect='auto')
445+
axs[0].set_xlabel('Position')
446+
axs[0].set_ylabel('Trials')
447+
448+
axs[1].plot(reliability, range(len(reliability)))
449+
axs[1].set_xlim([0, 1])
450+
axs[1].invert_yaxis()
451+
axs[1].set_ylabel(f'Trial block #, {len(split_fired_in_field[0])} trials per block')
452+
axs[1].set_xlabel('Proportion of trials with '
453+
'\n in-field calcium transient')
454+
fig.tight_layout()
455+
456+
return reliability
457+
389458
def viz_spatial_trial_activity(self, neurons=range(10), preserve_neuron_idx=True):
390459
"""
391460
Visualize single cell activity binned in spatial and separated

CircleTrack/scripts.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1775,7 +1775,7 @@ def spiralplot_matched_ensembles(
17751775
]
17761776

17771777
# Make a figure with 2 subplots, one for each session.
1778-
fig, axs = plt.subplots(2, 1, subplot_kw=dict(polar=True))
1778+
fig, axs = plt.subplots(2, 1, subplot_kw=dict(polar=True), figsize=(6.4, 10))
17791779
for ax, activation, t_, lin_pos, assembly_number, session_type in zip(
17801780
axs,
17811781
activations,

0 commit comments

Comments
 (0)