-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathPlot.py
More file actions
164 lines (139 loc) · 5.23 KB
/
Plot.py
File metadata and controls
164 lines (139 loc) · 5.23 KB
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
"""
Plotting utility functions for neural data visualization.
This minimal version contains only the functions actually used in Fig2-6 scripts:
- AvgSem() - Plot average with standard error of the mean
- let() - Add panel letter labels to subplots
- set_xlim() - Set x-axis limits with proper tick labels
"""
import numpy as np
import Details
def AvgSem(arr, ax=None, c=None, ls=None, label=None, lw=None, do_sem=True,
zorder=1, xrange=None, showsem=True, showleg=True, alpha=0.4):
"""
Calculate and plot average with standard error of the mean.
Parameters
----------
arr : ndarray
Input array (neurons x timepoints)
ax : matplotlib.axes.Axes, optional
Axes to plot on. If None, only returns avg and sem without plotting
c : str, optional
Color for the line
ls : str, optional
Line style
label : str, optional
Label for legend
lw : float, optional
Line width
do_sem : bool, default=True
Whether to divide by sqrt(n) for standard error
zorder : int, default=1
Z-order for plotting layers
xrange : array-like, optional
X-axis values. If None, uses range(arr.shape[-1])
showsem : bool, default=True
Whether to show shaded SEM region
showleg : bool, default=True
Whether to show legend
alpha : float, default=0.4
Alpha transparency for SEM shading
Returns
-------
avg : ndarray
Mean across neurons
sem : ndarray
Standard error of the mean
"""
if xrange is None:
xrange = range(arr.shape[-1])
arr = np.array(arr)
avg = np.nanmean(arr, axis=0)
sem = np.nanstd(arr, axis=0)
# Convert to standard error of the mean
if do_sem:
for i in range(len(sem)):
if np.sum(~np.isnan(arr[:, i])) > 0:
sem[i] /= np.sqrt(np.sum(~np.isnan(arr[:, i])))
# Plot if axes provided
if ax is not None:
ax.plot(xrange, avg, color=c, lw=lw, ls=ls, label=label, zorder=zorder)
col = ax.get_lines()[-1].get_color()
if showsem:
ax.fill_between(xrange, avg - sem, avg + sem, color=col,
alpha=alpha, zorder=zorder - 1)
if label is not None and showleg:
ax.legend()
return avg, sem
def let(ax, let, x=-0.2, y=1, fontsize=10):
"""
Add panel letter labels (A, B, C, etc.) to subplot axes.
Parameters
----------
ax : matplotlib.axes.Axes
Axes to add label to
let : int or str
Panel letter. If int, converts to letter (0='A', 1='B', etc.)
If str, uses directly
x : float, default=-0.2
X position in axes coordinates
y : float, default=1
Y position in axes coordinates
fontsize : int, default=10
Font size for the label
"""
if not isinstance(let, str):
let = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'][let]
ax.text(x, y, let,
verticalalignment='top',
horizontalalignment='right',
transform=ax.transAxes,
weight='bold',
fontsize=fontsize)
def set_xlim(data, ax, minv=None, maxv=None, showTicks=True, y=False,
res=500, offset=0):
"""
Set x-axis limits and tick labels based on data properties.
This function handles the conversion between data indices and actual
time values (in milliseconds), accounting for pre-window smoothing.
Parameters
----------
data : object
Data object with attributes:
- res: resolution (bin size in ms)
- smooth_prewindow: pre-window duration (ms)
- smooth_postwindow: post-window duration (ms)
- numTimepoints: number of timepoints
ax : matplotlib.axes.Axes
Axes to modify
minv : int, optional
Minimum time value (ms). If None, uses default from data
maxv : int, optional
Maximum time value (ms). If None, uses default from data
showTicks : bool, default=True
Whether to show tick labels
y : bool, default=False
If True, applies limits to y-axis instead of x-axis (inverted)
res : int, default=500
Resolution for tick spacing (ms)
offset : int, default=0
Time offset (ms). If 0, uses data.smooth_prewindow
"""
if offset == 0:
offset = data.smooth_prewindow
# Set tick positions (in data indices)
ax.set_xticks(range(offset // Details.smooth_step, data.numTimepoints + 1, res // Details.smooth_step))
# Set tick labels (in milliseconds)
if showTicks:
ax.set_xticklabels(np.arange(-data.smooth_prewindow + offset,
data.smooth_postwindow + 1, res))
else:
ax.set_xticklabels([''] * len(np.arange(-data.smooth_prewindow + offset,
data.smooth_postwindow, res)))
# Set axis limits if specified
if minv is not None and maxv is not None:
ax.set_xlim((minv + data.smooth_prewindow) // Details.smooth_step,
(maxv + data.smooth_prewindow) // Details.smooth_step)
# Apply to y-axis if requested (inverted)
if y:
ax.set_ylim((maxv + data.smooth_prewindow) // Details.smooth_step,
(minv + data.smooth_prewindow) // Details.smooth_step)