Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Red channel workflow enhancements #785

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 45 additions & 6 deletions suite2p/gui/drawroi.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -194,14 +197,28 @@ 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:
btn = ViewButton(b, "&" + names, self)
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)
Expand Down Expand Up @@ -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],
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
11 changes: 11 additions & 0 deletions suite2p/gui/gui2p.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
45 changes: 32 additions & 13 deletions suite2p/gui/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)")
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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:
Expand Down Expand Up @@ -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)
Expand Down
16 changes: 16 additions & 0 deletions suite2p/gui/masks.py
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
43 changes: 29 additions & 14 deletions suite2p/io/save.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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()
Expand Down
6 changes: 5 additions & 1 deletion suite2p/run_s2p.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)")
Expand Down