-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpyan.py
122 lines (99 loc) · 4.36 KB
/
pyan.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#%%
import pynapple as nap
import pandas as pd
import numpy as np
from pynwb import NWBHDF5IO
import matplotlib.pyplot as plt
import scienceplots
# %%
# Load NWB file using Pynapple
file_path = 'vgat4.nwb' # Replace with the actual path to your NWB file
nwb_data = nap.load_file(file_path)
# %%
dff = nwb_data['DfOverF']
# Investigate the structure of dff
print("DFF object attributes:", dir(dff))
print("DFF object type:", type(dff))
print("DFF shape:", dff.shape)
print("DFF index type:", type(dff.index))
print("DFF index (first 5):", dff.index[:5])
print("DFF columns type:", type(dff.columns))
print("DFF columns (first 5):", dff.columns[:5])
# Print the first few rows of the DFF data
print("DFF first 5 rows, first 5 columns:")
print(dff.values[:5, :5])
# %%
# Convert dff to a dictionary of TimeSeries objects
dff_dict = {}
for i, column in enumerate(dff.columns):
print(f"Processing column {i}: {column}")
print(f"Column data type: {type(dff[column])}")
print(f"Column data shape: {dff[column].shape}")
dff_dict[i] = dff[column] # dff[column] should already be a Tsd object
# Create TsGroup from the dictionary
dff_group = nap.TsGroup(dff_dict)
# %%
# Access the stimulus intervals table
stimuli_table = nwb_data["StimulusIntervals"]
# Create a dictionary to group intervals by orientation
dict_ep = {}
for _, row in stimuli_table.iterrows():
orientation = row['orientation']
start_time = row['start_time']
stop_time = row['stop_time']
key = f"stim{orientation}"
if key not in dict_ep:
dict_ep[key] = []
dict_ep[key].append((start_time, stop_time))
# Convert lists of tuples to IntervalSets
for key, intervals in dict_ep.items():
starts, stops = zip(*intervals)
dict_ep[key] = nap.IntervalSet(start=starts, end=stops)
# Print the resulting dictionary
print(dict_ep)
# %%
# Compute tuning curves
tuning_curves = nap.compute_discrete_tuning_curves(dff_group, dict_ep)
# Set the science plot style
plt.style.use(['science', 'ieee'])
# Convert orientation labels to radians for polar plot and sort them
orientations = [float(key.replace('stim', '')) for key in tuning_curves.index]
sorted_indices = np.argsort(orientations)
orientations = [orientations[i] for i in sorted_indices]
orientations_rad = np.deg2rad(orientations)
# Plot polar tuning curves for a subset of neurons
num_neurons_to_plot = min(15, len(tuning_curves.columns)) # Plot up to 15 neurons
neurons_to_plot = tuning_curves.columns[:num_neurons_to_plot]
plt.figure(figsize=(15, 12))
for i, neuron in enumerate(neurons_to_plot):
plt.subplot(3, 5, i + 1, projection="polar")
sorted_tuning = tuning_curves[neuron].iloc[sorted_indices]
plt.polar(np.concatenate([orientations_rad, [orientations_rad[0]]]), # Close the circle
np.concatenate([sorted_tuning, [sorted_tuning.iloc[0]]]), # Close the circle
'b-') # Blue line
plt.fill(np.concatenate([orientations_rad, [orientations_rad[0]]]), # Close the circle
np.concatenate([sorted_tuning, [sorted_tuning.iloc[0]]]), # Close the circle
alpha=0.2) # Light blue fill
plt.title(f"Neuron {neuron}", fontsize=10)
plt.xticks(np.deg2rad([0, 90, 180, 270]), ['0°', '90°', '180°', '270°'])
plt.yticks([]) # Remove radial ticks for cleaner look
plt.tight_layout()
plt.show()
# Plot mean tuning curve across all neurons (polar)
mean_tuning_curve = tuning_curves.mean(axis=1).iloc[sorted_indices]
std_tuning_curve = tuning_curves.std(axis=1).iloc[sorted_indices]
plt.figure(figsize=(8, 8))
ax = plt.subplot(111, projection="polar")
ax.plot(np.concatenate([orientations_rad, [orientations_rad[0]]]), # Close the circle
np.concatenate([mean_tuning_curve, [mean_tuning_curve.iloc[0]]]), # Close the circle
'b-', linewidth=2)
ax.fill_between(np.concatenate([orientations_rad, [orientations_rad[0]]]), # Close the circle
np.concatenate([mean_tuning_curve - std_tuning_curve, [mean_tuning_curve.iloc[0] - std_tuning_curve.iloc[0]]]), # Close the circle
np.concatenate([mean_tuning_curve + std_tuning_curve, [mean_tuning_curve.iloc[0] + std_tuning_curve.iloc[0]]]), # Close the circle
alpha=0.2)
plt.title('Mean Tuning Curve Across All Neurons', fontsize=12)
plt.xticks(np.deg2rad([0, 90, 180, 270]), ['0°', '90°', '180°', '270°'])
plt.yticks([]) # Remove radial ticks for cleaner look
plt.tight_layout()
plt.show()
# %%