Skip to content

Commit d922871

Browse files
Merge branch 'main' of https://github.com/mouseland/suite2p
2 parents ac9aa68 + 8fbe1b8 commit d922871

22 files changed

+941
-122
lines changed

README.md

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# suite2p <img src="suite2p/logo/logo_unshaded.png" width="250" title="sweet two pea" alt="sweet two pea" align="right" vspace = "50">
22

3-
[![Documentation Status](https://readthedocs.org/projects/cellpose/badge/?version=latest)](https://cellpose.readthedocs.io/en/latest/?badge=latest)
4-
![tests](https://github.com/mouseland/cellpose/actions/workflows/test_and_deploy.yml/badge.svg)
3+
[![Documentation Status](https://readthedocs.org/projects/suite2p/badge/?version=latest)](https://suite2p.readthedocs.io/en/latest/?badge=latest)
4+
![tests](https://github.com/mouseland/suite2p/actions/workflows/test_and_deploy.yml/badge.svg)
55
[![codecov](https://codecov.io/gh/MouseLand/suite2p/branch/main/graph/badge.svg?token=OJEC3mty85)](https://codecov.io/gh/MouseLand/suite2p)
66
[![PyPI version](https://badge.fury.io/py/suite2p.svg)](https://badge.fury.io/py/suite2p)
7-
[![Downloads](https://pepy.tech/badge/suite2p)](https://pepy.tech/project/suite2p)
8-
[![Downloads](https://pepy.tech/badge/suite2p/month)](https://pepy.tech/project/suite2p)
7+
[![Downloads](https://static.pepy.tech/badge/suite2p)](https://pepy.tech/project/suite2p)
8+
[![Downloads](https://static.pepy.tech/badge/suite2p/month)](https://pepy.tech/project/suite2p)
99
[![Python version](https://img.shields.io/pypi/pyversions/suite2p)](https://pypistats.org/packages/suite2p)
1010
[![Licence: GPL v3](https://img.shields.io/github/license/MouseLand/suite2p)](https://github.com/MouseLand/suite2p/blob/main/LICENSE)
1111
[![Contributors](https://img.shields.io/github/contributors-anon/MouseLand/suite2p)](https://github.com/MouseLand/suite2p/graphs/contributors)
@@ -27,16 +27,19 @@ suite2p includes the following modules:
2727

2828
This code was written by Carsen Stringer and Marius Pachitariu.
2929
For support, please open an [issue](https://github.com/MouseLand/suite2p/issues).
30+
3031
The reference paper is [here](https://www.biorxiv.org/content/early/2017/07/20/061507). The deconvolution algorithm is based on [this paper](https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1005423), with settings based on [this paper](http://www.jneurosci.org/content/early/2018/08/06/JNEUROSCI.3339-17.2018).
3132

32-
You can now run suite2p in google colab, no need to locally install (although we recommend doing so eventually): [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/MouseLand/suite2p/blob/main/jupyter/run_suite2p_colab_2021.ipynb). Note you do not have access to the GUI via google colab, but you can download the processed files and view them locally in the GUI.
33+
You can now run suite2p in google colab, no need to locally install (although we recommend doing so eventually): [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/MouseLand/suite2p/blob/main/jupyter/run_suite2p_colab_2023.ipynb). Note you do not have access to the GUI via google colab, but you can download the processed files and view them locally in the GUI.
3334

3435
See this **twitter [thread](https://twitter.com/marius10p/status/1032804776633880583)** for GUI demonstrations.
3536

3637
The matlab version is available [here](https://github.com/cortex-lab/Suite2P). Note that the algorithm is older and will not work as well on non-circular ROIs.
3738

3839
Lectures on how suite2p works are available [here](https://youtu.be/HpL5XNtC5wU?list=PLutb8FMs2QdNqL4h4NrNhSHgLGk4sXarb).
3940

41+
**Note on pull requests**: we accept very few pull requests due to the maintenance efforts required to support new code, and we do not accept pull requests from automated code checkers. If you wrote code that interfaces/changes suite2p behavior, a common approach would be to keep that in a fork and pull periodically from the main branch to make sure you have the latest updates.
42+
4043
### CITATION
4144

4245
If you use this package in your research, please cite the [paper](https://www.biorxiv.org/content/early/2017/07/20/061507):
@@ -89,7 +92,7 @@ If you want to download and edit the code, and use that version,
8992
### Installation for developers
9093

9194
1. Clone the repository and `cd suite2p` in an anaconda prompt / command prompt with `conda` for **python 3** in the path
92-
2. Run `conda env create --name suite2p`
95+
2. Run `conda create --name suite2p python=3.9`
9396
3. To activate this new environment, run `conda activate suite2p` (you will have to activate every time you want to run suite2p)
9497
4. Install the local version of suite2p into this environment in develop mode with the command `pip install -e .[all]`
9598
5. Run tests: `python setup.py test` or `pytest -vs`, this will automatically download the test data into your `suite2p` folder. The test data is split into two parts: test inputs and expected test outputs which will be downloaded in `data/test_inputs` and `data/test_outputs` respectively. The .zip files for these two parts can be downloaded from these links: [test_inputs](https://www.suite2p.org/static/test_data/test_inputs.zip) and [test_outputs](https://www.suite2p.org/static/test_data/test_outputs.zip).

docs/gui.rst

+16-4
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ Correlations with 1D var
6565
You can load an external stimulus or behavioral trace (1D) using "File -
6666
Load behavior or stim trace (1D only)". The GUI expects a \*.npy file
6767
that is the same length as the data in time (F.shape[1] from "F.npy").
68-
You can then look at the correlation of each cell with this trace. And
69-
it will be plotted along with the cell traces if you select multiple
70-
cells or in the "Visualize" menu.
68+
The length should match the number of frames in "F.npy". You can then look at the correlation of each
69+
cell with this trace. And it will be plotted along with the cell traces
70+
if you select multiple cells or in the "Visualize" menu.
7171

7272
.. _rastermap--custom:
7373

@@ -198,6 +198,18 @@ and it will ask you to specify a file location for the new classifier.
198198
Then you can load the classifier that you built into the GUI, or you can
199199
save it as your default classifier.
200200

201+
Applying a custom classifier
202+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
203+
204+
Go to the "Classifier" menu and click "Load / from file". A window will
205+
pop up and allow you to select a classfier from a file that you have
206+
already built. Upon loading, the GUI will recolor ROIs according to their
207+
iscell probability according to the new classifier, but they will retain
208+
their previous category and the ``iscell.npy`` file will not be updated.
209+
If you want to apply this new classifier to the ROIs category and update
210+
the ``iscell.npy`` file, then click the classifier probability box, enter
211+
your threshold, and press enter.
212+
201213
Visualizing activity
202214
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
203215

@@ -316,4 +328,4 @@ non-rigid registered. The metrics suggest that non-rigid registration
316328
should also be performed on this recording.
317329

318330
.. image:: _static/reg_metrics.png
319-
:width: 600
331+
:width: 600

docs/inputs.rst

+15-4
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,22 @@ imageJ and suite2p can recognize (see matlab tiff writing
9393
Bruker
9494
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
9595

96+
**Single Page Tifs**:
9697
Using Bruker Prairie View system, .RAW files are batch converted to single .ome.tifs.
9798
Now, you can load the resulting multiple tif files (i.e. one per frame per channel) to suite2p to be converted to binary.
9899
This looks for files containing 'Ch1', and will assume all additional files are 'Ch2'.
99100
Select "input_format" as "bruker" in the drop down menu in the GUI or set ``ops['input_format'] = "bruker"``.
100101

102+
**Multi Page Tifs**:
103+
To speed up the processing of input from bruker scopes, we recommend you save your .RAW files as multipage tifs. This can be done using the Bruker Prairie View system.
104+
105+
In the PrairieView software, set your preferences to convert your raw files to multipage TIFFs.
106+
107+
* Preferences > Save Multipage TIFFs
108+
* Preferences > Automatically Convert Raw Files > After Acquisition
109+
110+
This will cause the GUI to be unresponsive for some time after each acquisition. This should work for both single-channel and 2-channel recordings.
111+
101112
Mesoscope tiffs
102113
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
103114

@@ -118,10 +129,10 @@ you're using this and having trouble because it's not straightforward.
118129
Thorlabs raw files
119130
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
120131

121-
Christoph Schmidt-Hieber (@neurodroid) has written `haussmeister`_ which
122-
can load and convert ThorLabs \*.raw files to suite2p binary files!
123-
suite2p will automatically use this if you have pip installed it
124-
(``pip install haussmeister``).
132+
Suite2p has been upgraded with internal support for Thorlabs raw files (Yael Prilutski).
133+
Specify "raw" for "input_format".
134+
Designed to work with one or several planes and/or channels.
135+
125136

126137
.. _hdf5-files-and-sbx:
127138

setup.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
"paramiko",
2626
"nd2",
2727
"sbxreader",
28-
"h5py"
28+
"h5py",
29+
"opencv-python-headless",
30+
"xmltodict"
2931
]
3032

3133
nwb_deps = [
@@ -62,7 +64,7 @@
6264
except:
6365
pass
6466

65-
all_deps = gui_deps + nwb_deps + test_deps + io_deps
67+
all_deps = gui_deps + nwb_deps + test_deps + io_deps
6668

6769
try:
6870
import torch
@@ -102,6 +104,7 @@
102104
],
103105
"gui": gui_deps,
104106
"nwb": nwb_deps,
107+
"dcimg": dcimg_deps,
105108
"io": io_deps,
106109
"tests": test_deps,
107110
"all": all_deps,

suite2p/detection/anatomical.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def roi_detect(mproj, diameter=None, cellprob_threshold=0.0, flow_threshold=1.5,
105105
model = CellposeModel(model_type=pretrained_model)
106106
else:
107107
model = CellposeModel(pretrained_model=pretrained_model)
108-
masks = model.eval(mproj, net_avg=True, channels=[0, 0], diameter=diameter,
108+
masks = model.eval(mproj, channels=[0, 0], diameter=diameter,
109109
cellprob_threshold=cellprob_threshold,
110110
flow_threshold=flow_threshold)[0]
111111
shape = masks.shape

suite2p/detection/detect.py

+6
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ def detection_wrapper(f_reg, mov=None, yrange=None, xrange=None, ops=default_ops
125125
n_frames, Ly, Lx = f_reg.shape
126126
yrange = ops.get("yrange", [0, Ly]) if yrange is None else yrange
127127
xrange = ops.get("xrange", [0, Lx]) if xrange is None else xrange
128+
ops["yrange"] = yrange
129+
ops["xrange"] = xrange
128130

129131
if mov is None:
130132
bin_size = int(
@@ -138,6 +140,10 @@ def detection_wrapper(f_reg, mov=None, yrange=None, xrange=None, ops=default_ops
138140
elif mov.shape[2] != xrange[-1] - xrange[0]:
139141
raise ValueError("mov.shape[2] is not same size as xrange")
140142

143+
if "meanImg" not in ops:
144+
ops["meanImg"] = mov.mean(axis=0)
145+
ops["max_proj"] = mov.max(axis=0)
146+
141147
if ops.get("inverted_activity", False):
142148
mov -= mov.min()
143149
mov *= -1

suite2p/gui/gui2p.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ def make_buttons(self):
208208
return b0
209209

210210
def roi_text(self, state):
211-
if state == QtCore.Qt.Checked:
211+
if QtCore.Qt.CheckState(state) == QtCore.Qt.Checked:
212212
for n in range(len(self.roi_text_labels)):
213213
if self.iscell[n] == 1:
214214
self.p1.addItem(self.roi_text_labels[n])
@@ -232,7 +232,7 @@ def roi_text(self, state):
232232

233233
def zoom_cell(self, state):
234234
if self.loaded:
235-
if state == QtCore.Qt.Checked:
235+
if QtCore.Qt.CheckState(state) == QtCore.Qt.Checked:
236236
self.zoomtocell = True
237237
else:
238238
self.zoomtocell = False
@@ -554,7 +554,7 @@ def number_chosen(self):
554554
self.show()
555555

556556
def ROIs_on(self, state):
557-
if state == QtCore.Qt.Checked:
557+
if QtCore.Qt.CheckState(state) == QtCore.Qt.Checked:
558558
self.ops_plot["ROIs_on"] = True
559559
self.p1.addItem(self.color1)
560560
self.p2.addItem(self.color2)

suite2p/gui/io.py

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import os, time
55
import numpy as np
66
import scipy.io
7+
from scipy.ndimage import gaussian_filter1d
78
from qtpy import QtGui
89
from qtpy.QtWidgets import QFileDialog, QMessageBox
910

suite2p/gui/merge.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ def set_merge_list(self, parent, goodind):
316316
self.n = 0
317317
if len(self.merge_list) > 0:
318318
self.suggestMerge.setEnabled(True)
319-
self.unmerged = np.ones(len(self.merge_list), np.bool)
319+
self.unmerged = np.ones(len(self.merge_list), bool)
320320
self.suggest_merge(parent)
321321

322322
def suggest_merge(self, parent):

suite2p/gui/reggui.py

+16-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from scipy.ndimage import gaussian_filter1d
1414
from natsort import natsorted
1515
from tifffile import imread
16+
import json
1617

1718
from . import masks, views, graphics, traces, classgui, utils
1819
from .. import registration
@@ -354,8 +355,7 @@ def plot_trace(self):
354355
self.p2.setLimits(xMin=0, xMax=self.nframes)
355356

356357
def open(self):
357-
filename = QFileDialog.getOpenFileName(self, "Open single-plane ops.npy file",
358-
filter="ops*.npy")
358+
filename = QFileDialog.getOpenFileName(self, "Open single-plane ops.npy file or single-plane ops.json file")
359359
# load ops in same folder
360360
if filename:
361361
print(filename[0])
@@ -430,7 +430,19 @@ def openCombined(self, save_folder):
430430

431431
def openFile(self, filename, fromgui):
432432
try:
433-
ops = np.load(filename, allow_pickle=True).item()
433+
ext = os.path.splitext(filename)[1]
434+
if ext == ".npy":
435+
ops = np.load(filename, allow_pickle=True).item()
436+
dirname = os.path.dirname(filename)
437+
elif ext == ".json":
438+
with open(filename, "r") as f:
439+
ops = json.load(f)
440+
ops["Ly"] = ops["Lys"] if isinstance(ops["Lys"], int) else ops["Lys"][0]
441+
ops["Lx"] = ops["Lxs"] if isinstance(ops["Lxs"], int) else ops["Lxs"][0]
442+
dirname = os.path.join(os.path.dirname(filename), "suite2p/plane0/")
443+
ops["reg_file"] = os.path.join(dirname, "data.bin")
444+
nbytesread = np.int64(2 * ops["Ly"] * ops["Lx"])
445+
ops["nframes"] = os.path.getsize(ops["reg_file"]) // nbytesread
434446
self.LY = ops["Ly"]
435447
self.LX = ops["Lx"]
436448
self.Ly = [ops["Ly"]]
@@ -442,7 +454,7 @@ def openFile(self, filename, fromgui):
442454
self.reg_loc = [ops["reg_file"]]
443455
else:
444456
self.reg_loc = [
445-
os.path.abspath(os.path.join(os.path.dirname(filename), "data.bin"))
457+
os.path.abspath(os.path.join(dirname, "data.bin"))
446458
]
447459
self.reg_file = [open(self.reg_loc[-1], "rb")]
448460
self.wraw = False

suite2p/gui/rungui.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ def create_buttons(self):
276276
self.inputformat = QComboBox()
277277
[
278278
self.inputformat.addItem(f)
279-
for f in ["tif", "bruker", "sbx", "h5", "mesoscan", "haus", "nd2"]
279+
for f in ["tif", "binary", "bruker", "sbx", "h5", "movie", "nd2", "mesoscan", "raw", "dcimg"]
280280
]
281281
self.inputformat.currentTextChanged.connect(self.parse_inputformat)
282282
self.layout.addWidget(self.inputformat, 2, 0, 1, 1)
@@ -438,7 +438,7 @@ def run_S2P(self):
438438
# pre-download model
439439
pretrained_model_string = self.ops.get("pretrained_model", "cyto")
440440
pretrained_model_string = pretrained_model_string if pretrained_model_string is not None else "cyto"
441-
pretrained_model_path = model_path(pretrained_model_string, 0, True)
441+
pretrained_model_path = model_path(pretrained_model_string, 0)
442442
self.finish = True
443443
self.error = False
444444
ops_file = os.path.join(self.ops_path, "ops.npy")

suite2p/io/__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22
Copyright © 2023 Howard Hughes Medical Institute, Authored by Carsen Stringer and Marius Pachitariu.
33
"""
44
from .h5 import h5py_to_binary
5+
from .raw import raw_to_binary
56
from .nwb import save_nwb, read_nwb, nwb_to_binary
67
from .save import combined, compute_dydx, save_mat
78
from .sbx import sbx_to_binary
9+
from .movie import movie_to_binary
810
from .tiff import mesoscan_to_binary, ome_to_binary, tiff_to_binary, generate_tiff_filename, save_tiff
911
from .nd2 import nd2_to_binary
12+
from .dcam import dcimg_to_binary
1013
from .binary import BinaryFile, BinaryFileCombined
1114
from .server import send_jobs

0 commit comments

Comments
 (0)