From e45eb9ab767160692df12ae8d576e291c7b40556 Mon Sep 17 00:00:00 2001 From: marysethomas Date: Thu, 2 Dec 2021 15:27:38 -0500 Subject: [PATCH 1/3] Save F_chan2 and Fneu_chan2 during save to mat --- suite2p/gui/io.py | 45 ++++++++++++++++++++++++++++++++------------- suite2p/io/save.py | 43 +++++++++++++++++++++++++++++-------------- suite2p/run_s2p.py | 6 +++++- 3 files changed, 66 insertions(+), 28 deletions(-) diff --git a/suite2p/gui/io.py b/suite2p/gui/io.py index c5dd79fc..51352108 100644 --- a/suite2p/gui/io.py +++ b/suite2p/gui/io.py @@ -283,6 +283,8 @@ def load_files(name): redcell = np.load(basename + "/redcell.npy") probredcell = redcell[:,1].copy() redcell = redcell[:,0].astype('bool') + F_chan2 = np.load(basename + "/F_chan2.npy") + Fneu_chan2 = np.load(basename + "/Fneu_chan2.npy") hasred = True except (ValueError, OSError, RuntimeError, TypeError, NameError): print("no channel 2 labels found (redcell.npy)") @@ -291,12 +293,14 @@ def load_files(name): NN = Fcell.shape[0] redcell = np.zeros((NN,), 'bool') probredcell = np.zeros((NN,), np.float32) + F_chan2 = [] + Fneu_chan2 = [] else: print("incorrect file, not a stat.npy") return None if goodfolder: - return stat, ops, Fcell, Fneu, Spks, iscell, probcell, redcell, probredcell, hasred + return stat, ops, Fcell, Fneu, Spks, iscell, probcell, redcell, probredcell, hasred, F_chan2, Fneu_chan2 else: print("stat.npy found, but other files not in folder") return None @@ -314,7 +318,7 @@ def load_proc(parent): load_again(parent, Text) def load_to_GUI(parent, basename, procs): - stat, ops, Fcell, Fneu, Spks, iscell, probcell, redcell, probredcell, hasred = procs + stat, ops, Fcell, Fneu, Spks, iscell, probcell, redcell, probredcell, hasred, F_chan2, Fneu_chan2 = procs parent.basename = basename parent.stat = stat parent.ops = ops @@ -326,6 +330,8 @@ def load_to_GUI(parent, basename, procs): parent.redcell = redcell.astype('bool') parent.probredcell = probredcell parent.hasred = hasred + parent.F_chan2 = F_chan2 + parent.Fneu_chan2 = Fneu_chan2 parent.notmerged = np.ones_like(parent.iscell).astype('bool') for n in range(len(parent.stat)): if parent.hasred: @@ -413,17 +419,30 @@ def save_mat(parent): matpath = os.path.join(parent.basename,'Fall.mat') if 'date_proc' in parent.ops: parent.ops['date_proc'] = [] - scipy.io.savemat(matpath, {'stat': parent.stat, - 'ops': parent.ops, - 'F': parent.Fcell, - 'Fneu': parent.Fneu, - 'spks': parent.Spks, - 'iscell': np.concatenate((parent.iscell[:,np.newaxis], - parent.probcell[:,np.newaxis]), axis=1), - 'redcell': np.concatenate((np.expand_dims(parent.redcell,axis=1), - np.expand_dims(parent.probredcell,axis=1)), axis=1) - }) - + if parent.hasred: + scipy.io.savemat(matpath, {'stat': parent.stat, + 'ops': parent.ops, + 'F': parent.Fcell, + 'Fneu': parent.Fneu, + 'F_chan2': parent.F_chan2, + 'Fneu_chan2': parent.Fneu_chan2, + 'spks': parent.Spks, + 'iscell': np.concatenate((parent.iscell[:,np.newaxis], + parent.probcell[:,np.newaxis]), axis=1), + 'redcell': np.concatenate((np.expand_dims(parent.redcell,axis=1), + np.expand_dims(parent.probredcell,axis=1)), axis=1) + }) + else: + scipy.io.savemat(matpath, {'stat': parent.stat, + 'ops': parent.ops, + 'F': parent.Fcell, + 'Fneu': parent.Fneu, + 'spks': parent.Spks, + 'iscell': np.concatenate((parent.iscell[:,np.newaxis], + parent.probcell[:,np.newaxis]), axis=1), + 'redcell': np.concatenate((np.expand_dims(parent.redcell,axis=1), + np.expand_dims(parent.probredcell,axis=1)), axis=1) + }) def save_merge(parent): print('saving to NPY') np.save(os.path.join(parent.basename, 'ops.npy'), parent.ops) diff --git a/suite2p/io/save.py b/suite2p/io/save.py index 34930fa6..a958d5e9 100644 --- a/suite2p/io/save.py +++ b/suite2p/io/save.py @@ -5,7 +5,7 @@ import scipy import pathlib -def save_mat(ops, stat, F, Fneu, spks, iscell, redcell): +def save_mat(ops, stat, F, Fneu, spks, iscell, redcell, F_chan2=None, Fneu_chan2=None): ops_matlab = ops.copy() if ops_matlab.get('date_proc'): try: @@ -20,19 +20,34 @@ def save_mat(ops, stat, F, Fneu, spks, iscell, redcell): ops_matlab[k] = [os.fspath(p.absolute()) for p in ops_matlab[k]] print(k, ops_matlab[k]) - - scipy.io.savemat( - file_name=os.path.join(ops['save_path'], 'Fall.mat'), - mdict={ - 'stat': stat, - 'ops': ops_matlab, - 'F': F, - 'Fneu': Fneu, - 'spks': spks, - 'iscell': iscell, - 'redcell': redcell - } - ) + if F_chan2 is not None: + scipy.io.savemat( + file_name=os.path.join(ops['save_path'], 'Fall.mat'), + mdict={ + 'stat': stat, + 'ops': ops_matlab, + 'F': F, + 'Fneu': Fneu, + 'F_chan2': F_chan2, + 'Fneu_chan2': Fneu_chan2, + 'spks': spks, + 'iscell': iscell, + 'redcell': redcell + } + ) + else: + scipy.io.savemat( + file_name=os.path.join(ops['save_path'], 'Fall.mat'), + mdict={ + 'stat': stat, + 'ops': ops_matlab, + 'F': F, + 'Fneu': Fneu, + 'spks': spks, + 'iscell': iscell, + 'redcell': redcell + } + ) def compute_dydx(ops1): ops = ops1[0].copy() diff --git a/suite2p/run_s2p.py b/suite2p/run_s2p.py index 758fb981..9c03dc28 100644 --- a/suite2p/run_s2p.py +++ b/suite2p/run_s2p.py @@ -301,7 +301,11 @@ def run_plane(ops, ops_path=None, stat=None): stat = np.load(os.path.join(ops['save_path'], 'stat.npy'), allow_pickle=True) iscell = np.load(os.path.join(ops['save_path'], 'iscell.npy')) redcell = np.load(os.path.join(ops['save_path'], 'redcell.npy')) if ops['nchannels']==2 else [] - io.save_mat(ops, stat, F, Fneu, spks, iscell, redcell) + # if second channel, save F_chan2 and Fneu_chan2 + if 'meanImg_chan2' in ops: + io.save_mat(ops, stat, F, Fneu, spks, iscell, redcell, F_chan2, Fneu_chan2) + else: + io.save_mat(ops, stat, F, Fneu, spks, iscell, redcell) else: print("WARNING: skipping cell detection (ops['roidetect']=False)") From f8dcd938e610265114208d721bce7d60dbc4de17 Mon Sep 17 00:00:00 2001 From: marysethomas Date: Fri, 10 Dec 2021 16:33:29 -0500 Subject: [PATCH 2/3] Add red cell shortcut --- suite2p/gui/gui2p.py | 11 +++++++++++ suite2p/gui/masks.py | 16 ++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/suite2p/gui/gui2p.py b/suite2p/gui/gui2p.py index 675a6818..926d03c1 100644 --- a/suite2p/gui/gui2p.py +++ b/suite2p/gui/gui2p.py @@ -398,6 +398,17 @@ def keyPressEvent(self, event): elif event.key() == QtCore.Qt.Key_Up: masks.flip_plot(self) self.ROI_remove() + + elif event.key() == QtCore.Qt.Key_C: + if self.hasred: + self.redcell[self.ichosen] = ~self.redcell[self.ichosen] + self.imerge = [self.ichosen] + masks.change_red(self) + print('switched red') + + # self.update_plot() + ## NOTE: do we want to have C be a toggle key? + def update_plot(self): diff --git a/suite2p/gui/masks.py b/suite2p/gui/masks.py index c168deb8..0d85fac0 100644 --- a/suite2p/gui/masks.py +++ b/suite2p/gui/masks.py @@ -177,6 +177,22 @@ def flip_plot(parent): raise FileNotFoundError("Unable to find `iscell.npy` file") io.save_iscell(parent) + + +def change_red(parent): + # for n in parent.imerge: + # isred = int(parent.redcell[n]) + chan2_masks(parent) + parent.update_plot() + # Check if `redcell.npy` file exists + if not Path(parent.basename).joinpath("redcell.npy").exists(): + # Try the `plane0` folder in case of NWB file loaded + if Path(parent.basename).joinpath("plane0", "redcell.npy").exists(): + parent.basename = str(Path(parent.basename).joinpath("plane0")) + else: + raise FileNotFoundError("Unable to find `redcell.npy` file") + io.save_redcell(parent) + def chan2_prob(parent): chan2prob = float(parent.chan2edit.text()) From 8fa504d867ddf67873625387d70ee16d41084082 Mon Sep 17 00:00:00 2001 From: marysethomas Date: Fri, 10 Dec 2021 17:49:33 -0500 Subject: [PATCH 3/3] Add chan2, corr and chan2 as view options in Manual Labeling --- suite2p/gui/drawroi.py | 51 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/suite2p/gui/drawroi.py b/suite2p/gui/drawroi.py index 7bc88f30..7465af1c 100644 --- a/suite2p/gui/drawroi.py +++ b/suite2p/gui/drawroi.py @@ -124,7 +124,10 @@ def __init__(self, parent): self.styleUnpressed = ("QPushButton {Text-align: left; " "background-color: rgb(50,50,50); " "color:white;}") - + self.styleInactive = ("QPushButton {Text-align: left; " + "background-color: rgb(50,50,50); " + "color:gray;}") + # self.p0 = pg.ViewBox(lockAspect=False,name='plot1',border=[100,100,100],invertY=True) self.win = pg.GraphicsLayoutWidget() # --- cells image @@ -194,7 +197,9 @@ def __init__(self, parent): self.views = ["W: mean img", "E: mean img (enhanced)", "R: correlation map", - "T: max projection"] + "T: max projection", + "Y: mean img chan2, corr", + "U: mean img chan2"] b = 0 self.viewbtns = QButtonGroup(self) for names in self.views: @@ -202,6 +207,18 @@ def __init__(self, parent): self.viewbtns.addButton(btn, b) self.l0.addWidget(btn, b, 4, 1, 1) btn.setEnabled(True) + + # check for second channel + if b == 4: + if "meanImg_chan2_corrected" not in parent.ops: + btn.setEnabled(False) + btn.setStyleSheet(parent.styleInactive) + + if b == 5: + if "meanImg_chan2" not in parent.ops: + btn.setEnabled(False) + btn.setStyleSheet(parent.styleInactive) + b += 1 b = 0 self.viewbtns.button(b).setChecked(True) @@ -286,8 +303,8 @@ def close_GUI(self): self.close() def normalize_img_add_masks(self): - masked_image = np.zeros(((self.Ly, self.Lx, 3, 4))) # 3 for RGB and 4 for buttons - for i in np.arange(4): # 4 because 4 buttons + masked_image = np.zeros(((self.Ly, self.Lx, 3, 6))) # 3 for RGB and 6 for buttons + for i in np.arange(6): # 6 because 6 buttons if i == 0: mimg = np.zeros((self.Ly, self.Lx), np.float32) mimg[self.parent.ops['yrange'][0]:self.parent.ops['yrange'][1], @@ -304,12 +321,26 @@ def normalize_img_add_masks(self): mimg[self.parent.ops['yrange'][0]:self.parent.ops['yrange'][1], self.parent.ops['xrange'][0]:self.parent.ops['xrange'][1]] = self.parent.ops['Vcorr'] - else: + elif i == 3: mimg = np.zeros((self.Ly, self.Lx), np.float32) if 'max_proj' in self.parent.ops: mimg[self.parent.ops['yrange'][0]:self.parent.ops['yrange'][1], self.parent.ops['xrange'][0]:self.parent.ops['xrange'][1]] = self.parent.ops['max_proj'] - + + elif i == 4: + mimg = np.zeros((self.Ly, self.Lx), np.float32) + if 'meanImg_chan2_corrected' in self.parent.ops: + mimg[self.parent.ops['yrange'][0]:self.parent.ops['yrange'][1], + self.parent.ops['xrange'][0]:self.parent.ops['xrange'][1]] = self.parent.ops['meanImg_chan2_corrected'][self.parent.ops['yrange'][0]:self.parent.ops['yrange'][1], + self.parent.ops['xrange'][0]:self.parent.ops['xrange'][1]] + + elif i == 5: + mimg = np.zeros((self.Ly, self.Lx), np.float32) + if 'meanImg_chan2' in self.parent.ops: + mimg[self.parent.ops['yrange'][0]:self.parent.ops['yrange'][1], + self.parent.ops['xrange'][0]:self.parent.ops['xrange'][1]] = self.parent.ops['meanImg_chan2'][self.parent.ops['yrange'][0]:self.parent.ops['yrange'][1], + self.parent.ops['xrange'][0]:self.parent.ops['xrange'][1]] + mimg1 = np.percentile(mimg, 1) mimg99 = np.percentile(mimg, 99) mimg = (mimg - mimg1) / (mimg99 - mimg1) @@ -360,6 +391,14 @@ def keyPressEvent(self, event): elif event.key() == QtCore.Qt.Key_T: self.viewbtns.button(3).setChecked(True) self.viewbtns.button(3).press(self, 3) + elif event.key() == QtCore.Qt.Key_Y: + if "meanImg_chan2_corrected" in self.ops: + self.viewbtns.button(4).setChecked(True) + self.viewbtns.button(4).press(self, 4) + elif event.key() == QtCore.Qt.Key_U: + if "meanImg_chan2" in self.ops: + self.viewbtns.button(5).setChecked(True) + self.viewbtns.button(5).press(self, 5) def add_ROI(self, pos=None): self.iROI = len(self.ROIs)