11from pathlib import Path
22
33import numpy as np
4+ import scipy .signal
5+
46from PyQt5 import QtWidgets , QtCore , QtGui , uic
57import pyqtgraph as pg
6- import scipy .signal
78from brainbox .processing import bincount2D
89import qt
910from iblutil .numerical import ismember
1011from easyqc .gui import viewseis
1112from ibllib .io import spikeglx
1213from ibllib .dsp import voltage
1314
15+ T_BIN = .007 # time bin size in secs
16+ D_BIN = 10 # depth bin size in um
17+
18+ SNS_PALETTE = [(0.12156862745098039 , 0.4666666666666667 , 0.7058823529411765 ),
19+ (1.0 , 0.4980392156862745 , 0.054901960784313725 ),
20+ (0.17254901960784313 , 0.6274509803921569 , 0.17254901960784313 ),
21+ (0.8392156862745098 , 0.15294117647058825 , 0.1568627450980392 ),
22+ (0.5803921568627451 , 0.403921568627451 , 0.7411764705882353 ),
23+ (0.5490196078431373 , 0.33725490196078434 , 0.29411764705882354 ),
24+ (0.8901960784313725 , 0.4666666666666667 , 0.7607843137254902 ),
25+ (0.4980392156862745 , 0.4980392156862745 , 0.4980392156862745 ),
26+ (0.7372549019607844 , 0.7411764705882353 , 0.13333333333333333 ),
27+ (0.09019607843137255 , 0.7450980392156863 , 0.8117647058823529 )]
28+
29+ YMAX = 4000
1430
1531class RasterView (QtWidgets .QMainWindow ):
1632 def __init__ (self , bin_file , spikes , clusters , channels = None , trials = None , * args , ** kwargs ):
1733 self .sr = spikeglx .Reader (bin_file )
1834 self .spikes = spikes
1935 self .clusters = clusters
2036 self .channels = channels
37+ self .trials = trials
2138 self .eqcs = []
2239 super (RasterView , self ).__init__ (* args , ** kwargs )
2340 # wave by Diana Militano from the Noun Projectp
@@ -31,31 +48,54 @@ def __init__(self, bin_file, spikes, clusters, channels=None, trials=None, *args
3148 s = self .viewBox_raster .scene ()
3249 # vb.scene().sigMouseMoved.connect(self.mouseMoveEvent)
3350 s .sigMouseClicked .connect (self .mouseClick )
34-
35- # set image
36- t_bin = .007
37- d_bin = 10
38- self .raster , self .rtimes , self .depths = bincount2D (spikes .times , spikes .depths , t_bin , d_bin )
51+ ################################################### set image
52+ iok = ~ np .isnan (spikes .depths )
53+ self .raster , self .rtimes , self .depths = bincount2D (
54+ spikes .times [iok ], spikes .depths [iok ], T_BIN , D_BIN )
3955 self .imageItem_raster .setImage (np .flip (self .raster .T ))
40- transform = [t_bin , 0. , 0. , 0. , d_bin , 0. , - .5 , - .5 , 1. ]
56+ transform = [T_BIN , 0. , 0. , 0. , D_BIN , 0. , - .5 , - .5 , 1. ]
4157 self .transform = np .array (transform ).reshape ((3 , 3 )).T
4258 self .imageItem_raster .setTransform (QtGui .QTransform (* transform ))
4359 self .plotItem_raster .setLimits (xMin = 0 , xMax = self .rtimes [- 1 ], yMin = 0 , yMax = self .depths [- 1 ])
44-
4560 # set colormap
4661 cm = pg .colormap .get ('Greys' , source = 'matplotlib' ) # prepare a linear color map
4762 bar = pg .ColorBarItem (values = (0 , .5 ), colorMap = cm ) # prepare interactive color bar
4863 # Have ColorBarItem control colors of img and appear in 'plot':
4964 bar .setImageItem (self .imageItem_raster )
50- self .show ()
51-
65+ ################################################## plot location
66+ # self.view.layers[label] = {'layer': new_scatter, 'type': 'scatter'}
67+ self .line_eqc = pg .PlotCurveItem ()
68+ self .plotItem_raster .addItem (self .line_eqc )
69+ # self.plotItem_raster.removeItem(new_curve)
70+ ################################################## plot trials
71+ if self .trials is not None :
72+ trial_times = dict (
73+ goCue_times = trials ['goCue_times' ],
74+ error_times = trials ['feedback_times' ][trials ['feedbackType' ] == - 1 ],
75+ reward_times = trials ['feedback_times' ][trials ['feedbackType' ] == 1 ])
76+ self .trial_lines = {}
77+ for i , k in enumerate (trial_times ):
78+ self .trial_lines [k ] = pg .PlotCurveItem ()
79+ self .plotItem_raster .addItem (self .trial_lines [k ])
80+ x = np .tile (trial_times [k ][:, np .newaxis ], (1 , 2 )).flatten ()
81+ y = np .tile (np .array ([0 , 1 , 1 , 0 ]), int (trial_times [k ].shape [0 ] / 2 + 1 ))[
82+ :trial_times [k ].shape [0 ] * 2 ] * YMAX
83+ self .trial_lines [k ].setData (x = x .flatten (), y = y .flatten (), pen = pg .mkPen (np .array (SNS_PALETTE [i ]) * 256 ))
5284
85+ self .show ()
5386
5487 def mouseClick (self , event ):
88+ """Draws a line on the raster and display in EasyQC"""
5589 if not event .double ():
5690 return
5791 qxy = self .imageItem_raster .mapFromScene (event .scenePos ())
58- self .show_ephys (t0 = self .rtimes [int (qxy .x ())])
92+ x = qxy .x ()
93+ self .show_ephys (t0 = self .rtimes [int (x - .5 )])
94+ ymax = np .max (self .depths ) + 50
95+ self .line_eqc .setData (x = x + np .array ([- .5 , - .5 , .5 , .5 ]),
96+ y = np .array ([0 , ymax , ymax , 0 ]),
97+ pen = pg .mkPen ((0 , 255 , 0 )))
98+
5999
60100 def keyPressEvent (self , e ):
61101 """
@@ -73,10 +113,10 @@ def keyPressEvent(self, e):
73113 m == QtCore .Qt .ControlModifier and k == QtCore .Qt .Key_Z ):
74114 self .imageItem_raster .setLevels ([0 , self .imageItem_raster .levels [1 ] * 1.4 ])
75115
76- def show_ephys (self , t0 , len = 1 ):
116+ def show_ephys (self , t0 , tlen = 1 ):
77117
78118 first = int (t0 * self .sr .fs )
79- last = first + int (self .sr .fs * len )
119+ last = first + int (self .sr .fs * tlen )
80120
81121 raw = self .sr [first :last , : - self .sr .nsync ].T
82122
@@ -85,19 +125,21 @@ def show_ephys(self, t0, len=1):
85125 butt = scipy .signal .sosfiltfilt (sos , raw )
86126 destripe = voltage .destripe (raw , fs = self .sr .fs )
87127
128+ self .eqc_raw = viewephys (butt , self .sr .fs , channels = None , br = None , title = 'butt' , t0 = t0 , t_scalar = 1 )
129+ self .eqc_des = viewephys (destripe , self .sr .fs , channels = None , br = None , title = 'destripe' , t0 = t0 , t_scalar = 1 )
130+
131+ eqc_xrange = [t0 + tlen / 2 - 0.01 , t0 + tlen / 2 + 0.01 ]
132+ self .eqc_des .viewBox_seismic .setXRange (* eqc_xrange )
133+ self .eqc_raw .viewBox_seismic .setXRange (* eqc_xrange )
134+
135+ # eqc2 = viewephys(butt - destripe, self.sr.fs, channels=None, br=None, title='diff')
88136 # overlay spikes
89137 tprobe = self .spikes .samples / self .sr .fs
90- slice_spikes = slice (np .searchsorted (tprobe , t0 ), np .searchsorted (tprobe , t0 + len ))
138+ slice_spikes = slice (np .searchsorted (tprobe , t0 ), np .searchsorted (tprobe , t0 + tlen ))
91139 t = tprobe [slice_spikes ]
92140 c = self .clusters .channels [self .spikes .clusters [slice_spikes ]]
93-
94- self .eqc_raw = viewephys (butt , self .sr .fs , channels = None , br = None , title = 'butt' , t0 = t0 , t_scalar = 1 )
95- self .eqc_des = viewephys (destripe , self .sr .fs , channels = None , br = None , title = 'destripe' , t0 = t0 , t_scalar = 1 )
96- # eqc2 = viewephys(butt - destripe, self.sr.fs, channels=None, br=None, title='diff')
97-
98141 self .eqc_raw .ctrl .add_scatter (t , c )
99142 self .eqc_des .ctrl .add_scatter (t , c )
100- # eqc2.ctrl.add_scatter(t, c)
101143
102144
103145
0 commit comments