Skip to content

Commit bd18f10

Browse files
authored
Merge pull request #1514 from flatironinstitute/dev
Dev to main for release 1.12.2
2 parents 881e627 + 587c4ba commit bd18f10

38 files changed

+461
-363
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,6 @@ Special thanks to the following people for letting us use their datasets in demo
168168

169169
Also a special thanks to:
170170
* Eric Thompson, for various strong contributions to code and demos, both before and during his employment at the Flatiron Institute.
171-
* Cai Changjia, for Volpy
172171
* Ethan Blackwood, for several contributions in various areas
173172

174173
# License

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.12.1
1+
1.12.2

bin/caiman_gui.py

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,23 @@
1616
from caiman.source_extraction.cnmf.cnmf import load_CNMF
1717
from caiman.source_extraction.cnmf.params import CNMFParams
1818

19+
##############################
20+
# This is a tool that can help you visualise dumps of the CNMF object,
21+
# generated as demonstrated in demo_pipeline.
22+
#
23+
# If you're already using it, that's fine, but there are better tools
24+
# out there (such as the Mesmerize-vis package). To use, point it at the
25+
# hdf5 file that CLI demo or jupyter notebook made, or have your own code
26+
# call the save method on the CNMF object, and then feed that (and then the
27+
# mmap file) into this script when it asks, and you'll see your ROIs and
28+
# be able to experiment with thresholding (and re-save with those different
29+
# thresholds).
30+
#
31+
# mesmerize-vis offers a better approach to these things, and is much more
32+
# recent and better maintained.
33+
34+
35+
1936
# Always start by initializing Qt (only once per application)
2037
app = QtWidgets.QApplication([])
2138

@@ -66,7 +83,7 @@ def make_color_img(img, gain=255, min_max=None, out_type=np.uint8):
6683
M = FileDialog()
6784
d, f = os.path.split(cnm_obj.mmap_file)
6885
cnm_obj.mmap_file = M.getOpenFileName(caption='Load memory mapped file',
69-
directory=d, filter=f + ';;*.mmap')[0]
86+
filter=f + ';;*.mmap')[0]
7087

7188
if fpath[-3:] == 'nwb':
7289
mov = caiman.load(cnm_obj.mmap_file,
@@ -405,23 +422,23 @@ def move(event):
405422

406423

407424
## PARAMS
408-
params = [{'name': 'min_cnn_thr', 'type': 'float', 'value': 0.99, 'limits': (0, 1),'step':0.01},
409-
{'name': 'cnn_lowest', 'type': 'float', 'value': 0.1, 'limits': (0, 1),'step':0.01},
410-
{'name': 'rval_thr', 'type': 'float', 'value': 0.85, 'limits': (-1, 1),'step':0.01},
411-
{'name': 'rval_lowest', 'type': 'float', 'value': -1, 'limits': (-1, 1),'step':0.01},
412-
{'name': 'min_SNR', 'type': 'float', 'value': 2, 'limits': (0, 20),'step':0.1},
413-
{'name': 'SNR_lowest', 'type': 'float', 'value': 0, 'limits': (0, 20),'step':0.1},
414-
{'name': 'RESET', 'type': 'action'},
425+
params = [{'name': 'min_cnn_thr', 'type': 'float', 'value': 0.99, 'limits': (0, 1), 'step':0.01},
426+
{'name': 'cnn_lowest', 'type': 'float', 'value': 0.1, 'limits': (0, 1), 'step':0.01},
427+
{'name': 'rval_thr', 'type': 'float', 'value': 0.85, 'limits': (-1, 1), 'step':0.01},
428+
{'name': 'rval_lowest', 'type': 'float', 'value': -1, 'limits': (-1, 1), 'step':0.01},
429+
{'name': 'min_SNR', 'type': 'float', 'value': 2, 'limits': (0, 20), 'step':0.1},
430+
{'name': 'SNR_lowest', 'type': 'float', 'value': 0, 'limits': (0, 20), 'step':0.1},
431+
{'name': 'RESET', 'type': 'action'},
415432
{'name': 'SHOW BACKGROUND', 'type': 'action'},
416-
{'name': 'SHOW NEURONS', 'type': 'action'}
433+
{'name': 'SHOW NEURONS', 'type': 'action'}
417434
]
418435

419436
## Create tree of Parameter objects
420437
pars = Parameter.create(name='params', type='group', children=params)
421438

422439

423440
params_action = [{'name': 'Filter components', 'type': 'bool', 'value': True, 'tip': "Filter components"},
424-
{'name': 'View components', 'type': 'list', 'values': ['All','Accepted',
441+
{'name': 'View components', 'type': 'list', 'limits': ['All','Accepted',
425442
'Rejected', 'Unassigned'], 'value': 'All'},
426443
{'name': 'ADD GROUP', 'type': 'action'},
427444
{'name': 'REMOVE GROUP', 'type': 'action'},

caiman/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
#!/usr/bin/env python
22

3-
import pkg_resources
3+
import importlib.metadata
4+
45
from caiman.base.movies import movie, load, load_movie_chain, _load_behavior, play_movie
56
from caiman.base.timeseries import concatenate
67
from caiman.cluster import start_server, stop_server
78
from caiman.mmapping import load_memmap, save_memmap, save_memmap_each, save_memmap_join
89
from caiman.summary_images import local_correlations
910

10-
__version__ = pkg_resources.get_distribution('caiman').version
11+
__version__ = importlib.metadata.version('caiman')

caiman/base/movies.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ def bin_median(self, window: int = 10) -> np.ndarray:
187187
median image
188188
189189
"""
190-
T, d1, d2 = np.shape(self)
190+
T, d1, d2 = self.shape
191191
num_windows = int(T // window)
192192
num_frames = num_windows * window
193193
return np.nanmedian(np.nanmean(np.reshape(self[:num_frames], (window, num_windows, d1, d2)), axis=0), axis=0)
@@ -207,7 +207,7 @@ def bin_median_3d(self, window=10):
207207
median image
208208
209209
"""
210-
T, d1, d2, d3 = np.shape(self)
210+
T, d1, d2, d3 = self.shape
211211
num_windows = int(T // window)
212212
num_frames = num_windows * window
213213
return np.nanmedian(np.nanmean(np.reshape(self[:num_frames], (window, num_windows, d1, d2, d3)), axis=0),
@@ -465,18 +465,18 @@ def computeDFF(self, secsWindow: int = 5, quantilMin: int = 8, method: str = 'on
465465
if np.min(self) <= 0 and method != 'only_baseline':
466466
raise ValueError("All pixels must be positive")
467467

468-
numFrames, linePerFrame, pixPerLine = np.shape(self)
468+
numFrames, linePerFrame, pixPerLine = self.shape
469469
downsampfact = int(secsWindow * self.fr)
470470
logger.debug(f"Downsample factor: {downsampfact}")
471471
elm_missing = int(np.ceil(numFrames * 1.0 / downsampfact) * downsampfact - numFrames)
472472
padbefore = int(np.floor(elm_missing / 2.))
473473
padafter = int(np.ceil(elm_missing / 2.))
474474

475-
logger.debug(f'Initial Size Image: {np.shape(self)}')
475+
logger.debug(f'Initial Size Image: {self.shape}')
476476
sys.stdout.flush()
477477
mov_out = movie(np.pad(self.astype(np.float32), ((padbefore, padafter), (0, 0), (0, 0)), mode='reflect'),
478478
**self.__dict__)
479-
numFramesNew, linePerFrame, pixPerLine = np.shape(mov_out)
479+
numFramesNew, linePerFrame, pixPerLine = mov_out.shape
480480

481481
# compute baseline quickly
482482
logger.debug("binning data ...")
@@ -540,7 +540,7 @@ def IPCA(self, components: int = 50, batch: int = 1000) -> tuple[np.ndarray, np.
540540
"""
541541

542542
# vectorize the images
543-
num_frames, h, w = np.shape(self)
543+
num_frames, h, w = self.shape
544544
frame_size = h * w
545545
frame_samples = np.reshape(self, (num_frames, frame_size)).T
546546

@@ -611,7 +611,7 @@ def IPCA_stICA(self,
611611
joint_ics = ica.fit_transform(eigenstuff)
612612

613613
# extract the independent frames
614-
_, h, w = np.shape(self)
614+
_, h, w = self.shape
615615
frame_size = h * w
616616
ind_frames = joint_ics[:frame_size, :]
617617
ind_frames = np.reshape(ind_frames.T, (componentsICA, h, w))
@@ -623,7 +623,7 @@ def IPCA_denoise(self, components: int = 50, batch: int = 1000):
623623
Create a denoised version of the movie using only the first 'components' components
624624
"""
625625
_, _, clean_vectors = self.IPCA(components, batch)
626-
self = self.__class__(np.reshape(np.float32(clean_vectors.T), np.shape(self)), **self.__dict__)
626+
self = self.__class__(np.reshape(np.float32(clean_vectors.T), self.shape), **self.__dict__)
627627
return self
628628

629629
def local_correlations(self,
@@ -1214,7 +1214,7 @@ def load(file_name: Union[str, list[str]],
12141214

12151215
if input_arr.ndim == 2:
12161216
if shape is not None:
1217-
_, T = np.shape(input_arr)
1217+
_, T = input_arr.shape
12181218
d1, d2 = shape
12191219
input_arr = np.transpose(np.reshape(input_arr, (d1, d2, T), order='F'), (2, 0, 1))
12201220
else:
@@ -1361,13 +1361,13 @@ def load_movie_chain(file_list: list[str],
13611361
if m.ndim == 2:
13621362
m = m[np.newaxis, :, :]
13631363

1364-
_, h, w = np.shape(m)
1364+
_, h, w = m.shape
13651365
m = m[:, top:h - bottom, left:w - right]
13661366
else:
13671367
if m.ndim == 3:
13681368
m = m[np.newaxis, :, :, :]
13691369

1370-
_, h, w, d = np.shape(m)
1370+
_, h, w, d = m.shape
13711371
m = m[:, top:h - bottom, left:w - right, z_top:d - z_bottom]
13721372

13731373
mov.append(m)

caiman/base/rois.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -123,14 +123,14 @@ def extract_binary_masks_from_structural_channel(Y,
123123
def mask_to_2d(mask):
124124
# todo todocument
125125
if mask.ndim > 2:
126-
_, d1, d2 = np.shape(mask)
126+
_, d1, d2 = mask.shape
127127
dims = d1, d2
128128
return scipy.sparse.coo_matrix(np.reshape(mask[:].transpose([1, 2, 0]), (
129129
np.prod(dims),
130130
-1,
131131
), order='F'))
132132
else:
133-
dims = np.shape(mask)
133+
dims = mask.shape
134134
return scipy.sparse.coo_matrix(np.reshape(mask, (
135135
np.prod(dims),
136136
-1,
@@ -140,7 +140,7 @@ def mask_to_2d(mask):
140140
def get_distance_from_A(masks_gt, masks_comp, min_dist=10) -> list:
141141
# todo todocument
142142

143-
_, d1, d2 = np.shape(masks_gt)
143+
_, d1, d2 = masks_gt.shape
144144
dims = d1, d2
145145
A_ben = scipy.sparse.csc_matrix(np.reshape(masks_gt[:].transpose([1, 2, 0]), (
146146
np.prod(dims),
@@ -214,7 +214,7 @@ def nf_match_neurons_in_binary_masks(masks_gt,
214214
"""
215215
logger = logging.getLogger("caiman")
216216

217-
_, d1, d2 = np.shape(masks_gt)
217+
_, d1, d2 = masks_gt.shape
218218
dims = d1, d2
219219

220220
# transpose to have a sparse list of components, then reshaping it to have a 1D matrix red in the Fortran style
@@ -244,8 +244,8 @@ def nf_match_neurons_in_binary_masks(masks_gt,
244244

245245
# compute precision and recall
246246
TP = np.sum(np.array(costs) < thresh_cost) * 1.
247-
FN = np.shape(masks_gt)[0] - TP
248-
FP = np.shape(masks_comp)[0] - TP
247+
FN = masks_gt.shape[0] - TP
248+
FP = masks_comp.shape[0] - TP
249249
TN = 0
250250

251251
performance = dict()
@@ -259,9 +259,9 @@ def nf_match_neurons_in_binary_masks(masks_gt,
259259
idx_tp_ben = matches[0][idx_tp] # ground truth
260260
idx_tp_cnmf = matches[1][idx_tp] # algorithm - comp
261261

262-
idx_fn = np.setdiff1d(list(range(np.shape(masks_gt)[0])), matches[0][idx_tp])
262+
idx_fn = np.setdiff1d(list(range(masks_gt.shape[0])), matches[0][idx_tp])
263263

264-
idx_fp = np.setdiff1d(list(range(np.shape(masks_comp)[0])), matches[1][idx_tp])
264+
idx_fp = np.setdiff1d(list(range(masks_comp.shape[0])), matches[1][idx_tp])
265265

266266
idx_fp_cnmf = idx_fp
267267

@@ -736,8 +736,8 @@ def distance_masks(M_s:list, cm_s: list[list], max_dist: float, enclosed_thr: Op
736736
test_comp = test_comp.copy()[:, :]
737737

738738
# the number of components for each
739-
nb_gt = np.shape(gt_comp)[-1]
740-
nb_test = np.shape(test_comp)[-1]
739+
nb_gt = gt_comp.shape[-1]
740+
nb_test = test_comp.shape[-1]
741741
D = np.ones((nb_gt, nb_test))
742742

743743
cmgt_comp = np.array(cmgt_comp)

caiman/behavior/behavior.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def select_roi(img: np.ndarray, n_rois: int = 1) -> list:
4646
fig = plt.figure()
4747
plt.imshow(img, cmap=matplotlib.cm.gray)
4848
pts = fig.ginput(0, timeout=0)
49-
mask = np.zeros(np.shape(img), dtype=np.int32)
49+
mask = np.zeros(img.shape, dtype=np.int32)
5050
pts = np.asarray(pts, dtype=np.int32)
5151
cv2.fillConvexPoly(mask, pts, (1, 1, 1), lineType=cv2.LINE_AA)
5252
masks.append(mask)
@@ -317,11 +317,11 @@ def extract_components(mov_tot,
317317
mov_tot = mov_tot / norm_fact[:, np.newaxis, np.newaxis, np.newaxis]
318318
else:
319319
norm_fact = np.array([1., 1.])
320-
c, T, d1, d2 = np.shape(mov_tot)
320+
c, T, d1, d2 = mov_tot.shape
321321

322322
else:
323323
norm_fact = 1
324-
T, d1, d2 = np.shape(mov_tot)
324+
T, d1, d2 = mov_tot.shape
325325
c = 1
326326

327327
tt = time.time()

caiman/caimanmanager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def do_check_install(targdir: str, inplace: bool = False) -> None:
127127

128128

129129
def do_run_pytest(targdir: str) -> None:
130-
out, err, ret = runcmd(["pytest", "--verbose", "--pyargs", "caiman"])
130+
out, err, ret = runcmd(["pytest", "--verbose", "-W", "ignore::sklearn.exceptions.ConvergenceWarning", "--pyargs", "caiman"])
131131
if ret != 0:
132132
print(f"pytest failed with return code {ret}")
133133
sys.exit(ret)

caiman/cluster.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -222,12 +222,12 @@ def setup_cluster(backend:str = 'multiprocessing',
222222

223223
if backend == 'multiprocessing' or backend == 'local':
224224
if backend == 'local':
225-
logger.warn('The local backend is an alias for the multiprocessing backend, and the alias may be removed in some future version of Caiman')
225+
logger.warning('The local backend is an alias for the multiprocessing backend, and the alias may be removed in some future version of Caiman')
226226
if len(multiprocessing.active_children()) > 0:
227227
if ignore_preexisting:
228-
logger.warn('Found an existing multiprocessing pool. '
229-
'This is often indicative of an already-running CaImAn cluster. '
230-
'You have configured the cluster setup to not raise an exception.')
228+
logger.warning('Found an existing multiprocessing pool. '
229+
'This is often indicative of an already-running CaImAn cluster. '
230+
'You have configured the cluster setup to not raise an exception.')
231231
else:
232232
raise Exception(
233233
'A cluster is already running. Terminate with dview.terminate() if you want to restart.')
@@ -256,7 +256,7 @@ def setup_cluster(backend:str = 'multiprocessing',
256256

257257
elif backend == "single" or single_thread:
258258
if single_thread:
259-
logger.warn('The single_thread flag to setup_cluster() is deprecated and may be removed in the future')
259+
logger.warning('The single_thread flag to setup_cluster() is deprecated and may be removed in the future')
260260
dview = None
261261
c = None
262262
n_processes = 1

caiman/components_evaluation.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,17 @@ def compute_event_exceptionality(traces: np.ndarray,
6767
erfc: ndarray
6868
probability at each time step of observing the N consecutive actual trace values given the distribution of noise
6969
70-
noise_est: ndarray
71-
the components ordered according to the fitness
70+
std_r:
71+
Standard deviation of r
72+
73+
mode:
74+
Mode of the traces
7275
"""
7376
if N == 0:
7477
# Without this, numpy ranged syntax does not work correctly, and also N=0 is conceptually incoherent
7578
raise Exception("FATAL: N=0 is not a valid value for compute_event_exceptionality()")
7679

77-
T = np.shape(traces)[-1]
80+
T = traces.shape[-1]
7881
if use_mode_fast:
7982
md = caiman.utils.stats.mode_robust_fast(traces, axis=1)
8083
else:
@@ -85,7 +88,6 @@ def compute_event_exceptionality(traces: np.ndarray,
8588
# only consider values under the mode to determine the noise standard deviation
8689
ff1 = -ff1 * (ff1 < 0)
8790
if robust_std:
88-
8991
# compute 25 percentile
9092
ff1 = np.sort(ff1, axis=1)
9193
ff1[ff1 == 0] = np.nan
@@ -138,7 +140,7 @@ def find_activity_intervals(C, Npeaks: int = 5, tB=-3, tA=10, thres: float = 0.3
138140
# todo todocument
139141
logger = logging.getLogger("caiman")
140142

141-
K, T = np.shape(C)
143+
K, T = C.shape
142144
L:list = []
143145
for i in range(K):
144146
if np.sum(np.abs(np.diff(C[i, :]))) == 0:
@@ -208,7 +210,7 @@ def classify_components_ep(Y, A, C, b, f, Athresh=0.1, Npeaks=5, tB=-3, tA=10, t
208210
"""
209211
logger = logging.getLogger("caiman")
210212

211-
K, _ = np.shape(C)
213+
K, _ = C.shape
212214
A = csc_matrix(A)
213215
AA = (A.T * A).toarray()
214216
nA = np.sqrt(np.array(A.power(2).sum(0)))
@@ -415,7 +417,7 @@ def evaluate_components(Y: np.ndarray,
415417
tB = np.minimum(-2, np.floor(-5. / 30 * final_frate))
416418
tA = np.maximum(5, np.ceil(25. / 30 * final_frate))
417419
logger.info(f'{tB=},{tA=}')
418-
dims, T = np.shape(Y)[:-1], np.shape(Y)[-1]
420+
dims, T = Y.shape[:-1], Y.shape[-1]
419421

420422
Yr = np.reshape(Y, (np.prod(dims), T), order='F')
421423

@@ -427,7 +429,7 @@ def evaluate_components(Y: np.ndarray,
427429

428430
logger.debug('Removing Baseline')
429431
if remove_baseline:
430-
num_samps_bl = np.minimum(np.shape(traces)[-1]// 5, 800)
432+
num_samps_bl = np.minimum(traces.shape[-1]// 5, 800)
431433
slow_baseline = False
432434
if slow_baseline:
433435

@@ -441,7 +443,7 @@ def evaluate_components(Y: np.ndarray,
441443
padbefore = int(np.floor(elm_missing / 2.))
442444
padafter = int(np.ceil(elm_missing / 2.))
443445
tr_tmp = np.pad(traces.T, ((padbefore, padafter), (0, 0)), mode='reflect')
444-
numFramesNew, num_traces = np.shape(tr_tmp)
446+
numFramesNew, num_traces = tr_tmp.shape
445447
# compute baseline quickly
446448
logger.debug("binning data ...")
447449
tr_BL = np.reshape(tr_tmp, (downsampfact, numFramesNew // downsampfact, num_traces), order='F')

0 commit comments

Comments
 (0)