Skip to content

Commit 66f322d

Browse files
updating code for avi / mp4 support
1 parent a7f0118 commit 66f322d

3 files changed

Lines changed: 124 additions & 48 deletions

File tree

notebooks/example_notebook.ipynb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,22 @@
88
"source": [
99
"import suite2p\n",
1010
"from suite2p import default_settings\n",
11+
"from suite2p.run_s2p import logger_setup\n",
12+
"\n",
1113
"db = {\"data_path\": [\"/media/carsen/ssd2/suite2p_paper/GT1/\"], \n",
1214
" \"file_list\": [\"input_1500.tif\"], # (optional) Specify files you'd like to specifically use in the data_path\n",
1315
" \"input_format\": \"tif\",\n",
1416
" \"nplanes\": 1, # each tiff has these many planes in sequence\n",
1517
" \"nchannels\": 1, # each tiff has these many channels per plane\n",
16-
" \"keep_movie_raw\": True,\n",
18+
" \"keep_movie_raw\": True, # optional, to keep the raw movie after registration\n",
1719
"}\n",
1820
"\n",
21+
"db[\"save_path0\"] = db[\"data_path\"][0]\n",
22+
"\n",
23+
"# initialize logger\n",
24+
"logger_setup(db[\"save_path0\"])\n",
25+
"\n",
26+
"# initialize settings\n",
1927
"settings = default_settings()\n",
2028
"settings[\"registration\"][\"align_by_chan2\"] = False\n",
2129
"settings[\"run\"][\"do_registration\"] = 1\n",
@@ -24,7 +32,7 @@
2432
"settings[\"detection\"][\"threshold_scaling\"] = 1.0\n",
2533
"settings[\"detection\"][\"algorithm\"] = \"sparsery\"\n",
2634
"settings[\"torch_device\"] = \"mps\" # use mps for mac, cuda for nvidia gpu, or \"cpu\"\n",
27-
"output_settings = suite2p.run_s2p(settings=settings, db=db)"
35+
"db_paths = suite2p.run_s2p(settings=settings, db=db)"
2836
]
2937
},
3038
{

notebooks/run_movie_avi_mp4.ipynb

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"metadata": {},
7+
"outputs": [],
8+
"source": [
9+
"import suite2p\n",
10+
"from suite2p import default_settings\n",
11+
"from suite2p.run_s2p import logger_setup\n",
12+
"\n",
13+
"# ** can use *.mp4 or *.avi files \n",
14+
"db = {\"data_path\": [\"/media/carsen/disk2/test_suite2p/M0/\"], \n",
15+
" \"input_format\": \"movie\",\n",
16+
" \"nplanes\": 1, \n",
17+
" \"nchannels\": 1, \n",
18+
" \"keep_movie_raw\": False, # optional, to keep the raw movie after registration\n",
19+
"}\n",
20+
"\n",
21+
"db[\"save_path0\"] = db[\"data_path\"][0]\n",
22+
"\n",
23+
"# initialize logger\n",
24+
"logger_setup(db[\"save_path0\"])\n",
25+
"\n",
26+
"# initialize settings\n",
27+
"settings = default_settings()\n",
28+
"settings[\"fs\"] = 30\n",
29+
"settings[\"tau\"] = 1.25 # timescale of gcamp to use for deconvolution\n",
30+
"settings[\"detection\"][\"threshold_scaling\"] = 1.0\n",
31+
"settings[\"detection\"][\"algorithm\"] = \"sparsery\"\n",
32+
"settings[\"torch_device\"] = \"mps\" # use mps for mac, cuda for nvidia gpu, or \"cpu\"\n",
33+
"db_paths = suite2p.run_s2p(settings=settings, db=db)"
34+
]
35+
},
36+
{
37+
"cell_type": "code",
38+
"execution_count": null,
39+
"metadata": {},
40+
"outputs": [],
41+
"source": []
42+
}
43+
],
44+
"metadata": {
45+
"kernelspec": {
46+
"display_name": "s2p",
47+
"language": "python",
48+
"name": "python3"
49+
},
50+
"language_info": {
51+
"codemirror_mode": {
52+
"name": "ipython",
53+
"version": 3
54+
},
55+
"file_extension": ".py",
56+
"mimetype": "text/x-python",
57+
"name": "python",
58+
"nbconvert_exporter": "python",
59+
"pygments_lexer": "ipython3",
60+
"version": "3.11.13"
61+
}
62+
},
63+
"nbformat": 4,
64+
"nbformat_minor": 2
65+
}

suite2p/io/movie.py

Lines changed: 49 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -114,46 +114,50 @@ def get_frames(self, cframes):
114114
nk += nt0
115115
return im
116116

117-
def movie_to_binary(settings):
117+
def movie_to_binary(dbs, settings, reg_file, reg_file_chan2):
118118
""" finds movie files and writes them to binaries
119119
120120
Parameters
121121
----------
122-
settings : dictionary
123-
"nplanes", "data_path", "save_path", "save_folder", "fast_disk",
124-
"nchannels", "keep_movie_raw", "look_one_level_down" (optional: "subfolders")
122+
dbs : list of dict
123+
Database dictionaries for each plane. Must contain keys "file_list",
124+
"nplanes", "nchannels", "batch_size", "h5py_key", and "functional_chan".
125+
Updated in-place with "Ly", "Lx", "nframes", "nframes_per_folder",
126+
"meanImg", and "meanImg_chan2".
127+
settings : dict
128+
Suite2p settings dictionary, saved alongside each plane's database.
129+
reg_file : list of file objects
130+
Opened binary files for writing each plane's functional channel data.
131+
reg_file_chan2 : list of file objects
132+
Opened binary files for writing each plane's second channel data
133+
(used only when nchannels > 1).
125134
126135
Returns
127136
-------
128-
settings : dictionary of first plane
129-
"Ly", "Lx", settings["reg_file"] or settings["raw_file"] is created binary
130-
137+
dbs : list of dict
138+
Updated database dictionaries with image dimensions, frame counts, and
139+
mean images populated.
131140
"""
132141
if not HAS_CV2:
133142
raise ImportError("cv2 is required for this file type, please 'pip install opencv-python-headless'")
134143

135-
settings1 = init_settings(settings)
136-
137-
nplanes = settings1[0]["nplanes"]
138-
nchannels = settings1[0]["nchannels"]
139-
140-
# open all binary files for writing
141-
settings1, filenames, reg_file, reg_file_chan2 = find_files_open_binaries(settings1)
142144

143-
ik = 0
144-
for j in range(settings["nplanes"]):
145-
settings1[j]["nframes_per_folder"] = np.zeros(len(filenames), np.int32)
145+
nplanes = dbs[0]["nplanes"]
146+
nchannels = dbs[0]["nchannels"]
147+
flist = dbs[0]["file_list"]
146148

149+
# todo: implement for multiple movies
150+
# for j in range(nplanes):
151+
# dbs[j]["nframes_per_folder"] = np.zeros(len(flist), np.int32)
147152

148153
ncp = nplanes * nchannels
149-
nbatch = ncp * int(np.ceil(settings1[0]["batch_size"] / ncp))
150-
logger.info(filenames)
154+
nbatch = ncp * int(np.ceil(dbs[0]["batch_size"] / ncp))
155+
logger.info(flist)
151156
t0 = time.time()
152-
with VideoReader(filenames=filenames) as vr:
153-
if settings1[0]["fs"]<=0:
154-
for settings in settings1:
155-
settings["fs"] = vr.fs
156-
157+
with VideoReader(filenames=flist) as vr:
158+
if settings["fs"]<=0:
159+
settings["fs"] = vr.fs
160+
157161
nframes_all = vr.cumframes[-1]
158162
nbatch = min(nbatch, nframes_all)
159163
nfunc = settings["functional_chan"] - 1 if nchannels > 1 else 0
@@ -167,47 +171,46 @@ def movie_to_binary(settings):
167171
nframes = im.shape[0]
168172
for j in range(0, nplanes):
169173
if ik == 0:
170-
settings1[j]["meanImg"] = np.zeros((im.shape[1], im.shape[2]),
174+
dbs[j]["meanImg"] = np.zeros((im.shape[1], im.shape[2]),
171175
np.float32)
172176
if nchannels > 1:
173-
settings1[j]["meanImg_chan2"] = np.zeros(
177+
dbs[j]["meanImg_chan2"] = np.zeros(
174178
(im.shape[1], im.shape[2]), np.float32)
175-
settings1[j]["nframes"] = 0
179+
dbs[j]["nframes"] = 0
176180
i0 = nchannels * ((j) % nplanes)
177181
im2write = im[np.arange(int(i0) +
178182
nfunc, nframes, ncp), :, :].astype(
179183
np.int16)
180184
reg_file[j].write(bytearray(im2write))
181-
settings1[j]["meanImg"] += im2write.astype(np.float32).sum(axis=0)
185+
dbs[j]["meanImg"] += im2write.astype(np.float32).sum(axis=0)
182186
if nchannels > 1:
183187
im2write = im[np.arange(int(i0) + 1 -
184188
nfunc, nframes, ncp), :, :].astype(
185189
np.int16)
186190
reg_file_chan2[j].write(bytearray(im2write))
187-
settings1[j]["meanImg_chan2"] += im2write.astype(
191+
dbs[j]["meanImg_chan2"] += im2write.astype(
188192
np.float32).sum(axis=0)
189-
settings1[j]["nframes"] += im2write.shape[0]
190-
#settings1[j]["nframes_per_folder"][ih5] += im2write.shape[0]
193+
dbs[j]["nframes"] += im2write.shape[0]
194+
191195
ik += nframes
192196
if ik % (nbatch * 4) == 0:
193197
logger.info("%d frames of binary, time %0.2f sec." %
194198
(ik, time.time() - t0))
195199

196200
# write settings files
197-
do_registration = settings1[0]["do_registration"]
198-
for settings in settings1:
199-
settings["Ly"] = im2write.shape[1]
200-
settings["Lx"] = im2write.shape[2]
201+
# update dbs with image dimensions and mean images
202+
do_registration = settings["run"]["do_registration"]
203+
for db in dbs:
204+
db["Ly"] = im2write.shape[1]
205+
db["Lx"] = im2write.shape[2]
201206
if not do_registration:
202-
settings["yrange"] = np.array([0, settings["Ly"]])
203-
settings["xrange"] = np.array([0, settings["Lx"]])
204-
settings["meanImg"] /= settings["nframes"]
205-
if nchannels > 1:
206-
settings["meanImg_chan2"] /= settings["nframes"]
207-
np.save(settings["settings_path"], settings)
208-
# close all binary files and write settings files
209-
for j in range(nplanes):
210-
reg_file[j].close()
207+
db["yrange"] = np.array([0, db["Ly"]])
208+
db["xrange"] = np.array([0, db["Lx"]])
209+
db["meanImg"] /= db["nframes"]
211210
if nchannels > 1:
212-
reg_file_chan2[j].close()
213-
return settings1[0]
211+
db["meanImg_chan2"] /= db["nframes"]
212+
# Save db and settings to each plane folder
213+
np.save(db["db_path"], db)
214+
np.save(db["settings_path"], settings)
215+
216+
return dbs

0 commit comments

Comments
 (0)