Skip to content

Commit fe19bac

Browse files
authored
Merge pull request #9 from nel-lab/get_com_coords
Merging, this also fixes #11 and #13
2 parents 57746c4 + 542e4ad commit fe19bac

File tree

6 files changed

+88
-75
lines changed

6 files changed

+88
-75
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,8 @@ dmypy.json
130130

131131
# pycharm
132132
.idea/
133+
134+
# test files
135+
tests/tmp
136+
tests/videos
137+

mesmerize_core/algorithms/cnmf.py

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,13 @@ def main(batch_path, uuid, data_path: str = None):
5858
Yr, dims, T = cm.load_memmap(fname_new)
5959
images = np.reshape(Yr.T, [T] + list(dims), order='F')
6060

61-
mean_projection_path = str(Path(input_movie_path).parent.joinpath(f'{uuid}_mean_projection.npy'))
62-
std_projection_path = str(Path(input_movie_path).parent.joinpath(f'{uuid}_std_projection.npy'))
63-
max_projection_path = str(Path(input_movie_path).parent.joinpath(f'{uuid}_max_projection.npy'))
64-
np.save(mean_projection_path, np.mean(images, axis=0))
65-
np.save(std_projection_path, np.std(images, axis=0))
66-
np.save(max_projection_path, np.max(images, axis=0))
67-
# in fname new load in memmap order C
61+
proj_paths = dict()
62+
for proj_type in ['mean', 'std', 'max']:
63+
p_img = getattr(np, f'nan{proj_type}')(images, axis=0)
64+
proj_paths[proj_type] = Path(input_movie_path).parent.joinpath(f'{uuid}_{proj_type}.npy')
65+
np.save(str(proj_paths[proj_type]), p_img)
6866

67+
# in fname new load in memmap order C
6968
cm.stop_server(dview=dview)
7069
c, dview, n_processes = cm.cluster.setup_cluster(
7170
backend='local',
@@ -90,33 +89,36 @@ def main(batch_path, uuid, data_path: str = None):
9089
print("Eval")
9190
cnm.estimates.evaluate_components(images, cnm.params, dview=dview)
9291

93-
output_path = str(get_full_data_path(input_movie_path).parent.joinpath(f"{uuid}.hdf5").resolve())
92+
output_path = get_full_data_path(input_movie_path).parent.joinpath(f"{uuid}.hdf5").resolve()
9493

95-
cnm.save(output_path)
94+
cnm.save(str(output_path))
9695

9796
Cn = cm.local_correlations(images.transpose(1, 2, 0))
9897
Cn[np.isnan(Cn)] = 0
9998

10099
corr_img_path = Path(input_movie_path).parent.joinpath(f'{uuid}_cn.npy').resolve()
101100
np.save(str(corr_img_path), Cn, allow_pickle=False)
102101

103-
if data_path is not None:
104-
cnmf_hdf5_path = Path(output_path).relative_to(data_path)
102+
# output dict for dataframe row (pd.Series)
103+
d = dict()
104+
105+
if data_path is not None: # relative paths
106+
cnmf_hdf5_path = output_path.relative_to(data_path)
105107
cnmf_memmap_path = Path(fname_new).relative_to(data_path)
106108
corr_img_path = corr_img_path.relative_to(data_path)
107-
else:
109+
for proj_type in proj_paths.keys():
110+
d[f"{proj_type}-projection-path"] = proj_paths[proj_type].relative_to(data_path)
111+
else: # absolute paths
108112
cnmf_hdf5_path = output_path
109113
cnmf_memmap_path = fname_new
114+
for proj_type in proj_paths.keys():
115+
d[f"{proj_type}-projection-path"] = proj_paths[proj_type]
110116

111-
d = dict()
112117
d.update(
113118
{
114119
"cnmf-hdf5-path": cnmf_hdf5_path,
115120
"cnmf-memmap-path": cnmf_memmap_path,
116121
"corr-img-path": corr_img_path,
117-
"mean-projection-path": mean_projection_path,
118-
"std-projection-path": std_projection_path,
119-
"max-projection-path": max_projection_path,
120122
"success": True,
121123
"traceback": None
122124
}

mesmerize_core/algorithms/cnmfe.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,11 @@ def main(batch_path, uuid, data_path: str = None):
4949
Yr, dims, T = cm.load_memmap(fname_new)
5050
images = np.reshape(Yr.T, [T] + list(dims), order='F')
5151

52-
mean_projection_path = str(Path(input_movie_path).parent.joinpath(f'{uuid}_mean_projection.npy'))
53-
std_projection_path = str(Path(input_movie_path).parent.joinpath(f'{uuid}_std_projection.npy'))
54-
max_projection_path = str(Path(input_movie_path).parent.joinpath(f'{uuid}_max_projection.npy'))
55-
np.save(mean_projection_path, np.mean(images, axis=0))
56-
np.save(std_projection_path, np.std(images, axis=0))
57-
np.save(max_projection_path, np.max(images, axis=0))
52+
proj_paths = dict()
53+
for proj_type in ['mean', 'std', 'max']:
54+
p_img = getattr(np, f'nan{proj_type}')(images, axis=0)
55+
proj_paths[proj_type] = Path(input_movie_path).parent.joinpath(f'{uuid}_{proj_type}.npy')
56+
np.save(str(proj_paths[proj_type]), p_img)
5857

5958
downsample_ratio = params['downsample_ratio']
6059
# in fname new load in memmap order C
@@ -63,11 +62,11 @@ def main(batch_path, uuid, data_path: str = None):
6362
images[::downsample_ratio], swap_dim=False, gSig=gSig
6463
)
6564

66-
pnr_output_path = str(Path(input_movie_path).parent.joinpath(f"{uuid}_pn.npy").resolve())
67-
cn_output_path = str(Path(input_movie_path).parent.joinpath(f"{uuid}_cn.npy").resolve())
65+
pnr_output_path = Path(input_movie_path).parent.joinpath(f"{uuid}_pn.npy").resolve()
66+
cn_output_path = Path(input_movie_path).parent.joinpath(f"{uuid}_cn.npy").resolve()
6867

69-
np.save(str(cn_output_path), cn_filter, allow_pickle=False)
7068
np.save(str(pnr_output_path), pnr, allow_pickle=False)
69+
np.save(str(cn_output_path), cn_filter, allow_pickle=False)
7170

7271
d = dict() # for output
7372

@@ -92,13 +91,17 @@ def main(batch_path, uuid, data_path: str = None):
9291
print("evaluating components")
9392
cnm.estimates.evaluate_components(images, cnm.params, dview=dview)
9493

95-
output_path = str(Path(input_movie_path).parent.joinpath(f"{uuid}.hdf5").resolve())
96-
cnm.save(output_path)
94+
output_path = Path(input_movie_path).parent.joinpath(f"{uuid}.hdf5").resolve()
95+
cnm.save(str(output_path))
9796

9897
if data_path is not None:
9998
cnmf_hdf5_path = Path(output_path).relative_to(data_path)
99+
for proj_type in proj_paths.keys():
100+
d[f"{proj_type}-projection-path"] = proj_paths[proj_type].relative_to(data_path)
100101
else:
101102
cnmf_hdf5_path = output_path
103+
for proj_type in proj_paths.keys():
104+
d[f"{proj_type}-projection-path"] = proj_paths[proj_type]
102105

103106
d.update(
104107
{
@@ -108,8 +111,8 @@ def main(batch_path, uuid, data_path: str = None):
108111

109112
if data_path is not None:
110113
cnmfe_memmap_path = Path(fname_new).relative_to(data_path)
111-
cn_output_path = Path(cn_output_path).relative_to(data_path)
112-
pnr_output_path = Path(pnr_output_path).relative_to(data_path)
114+
cn_output_path = cn_output_path.relative_to(data_path)
115+
pnr_output_path = pnr_output_path.relative_to(data_path)
113116
else:
114117
cnmfe_memmap_path = fname_new
115118

@@ -118,15 +121,12 @@ def main(batch_path, uuid, data_path: str = None):
118121
"cnmf-memmap-path": cnmfe_memmap_path,
119122
"corr-img-path": cn_output_path,
120123
"pnr-image-path": pnr_output_path,
121-
"mean-projection-path": mean_projection_path,
122-
"std-projection-path": std_projection_path,
123-
"max-projection-path": max_projection_path,
124124
"success": True,
125125
"traceback": None
126126
}
127127
)
128128

129-
print(d)
129+
print(f"Final output dict:\n{d}")
130130

131131
except:
132132
d = {"success": False, "traceback": traceback.format_exc()}

mesmerize_core/algorithms/mcorr.py

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,11 @@ def main(batch_path, uuid, data_path: str = None):
6868
Yr, dims, T = cm.load_memmap(str(get_full_data_path(output_path)))
6969
images = np.reshape(Yr.T, [T] + list(dims), order='F')
7070

71-
paths=[]
71+
proj_paths = dict()
7272
for proj_type in ['mean', 'std', 'max']:
73-
p_img = getattr(np, f"nan{proj_type}")(images, axis=0)
74-
proj_path = f"{uuid}_{proj_type}_projection.npy"
75-
np.save(str(Path(input_movie_path).parent.joinpath(proj_path)), p_img)
76-
paths.append(str(Path(input_movie_path).parent.joinpath(proj_path)))
77-
73+
p_img = getattr(np, f'nan{proj_type}')(images, axis=0)
74+
proj_paths[proj_type] = Path(input_movie_path).parent.joinpath(f'{uuid}_{proj_type}.npy')
75+
np.save(str(proj_paths[proj_type]), p_img)
7876

7977
print("Computing correlation image")
8078
Cns = local_correlations_movie_offline([mc.mmap_file[0]],
@@ -83,11 +81,11 @@ def main(batch_path, uuid, data_path: str = None):
8381
dview=dview)
8482
Cn = Cns.max(axis=0)
8583
Cn[np.isnan(Cn)] = 0
86-
cn_path = str(Path(input_movie_path).parent.joinpath(f'{uuid}_cn.npy'))
87-
np.save(cn_path, Cn, allow_pickle=False)
84+
cn_path = Path(input_movie_path).parent.joinpath(f'{uuid}_cn.npy')
85+
np.save(str(cn_path), Cn, allow_pickle=False)
8886

89-
if data_path is not None:
90-
cn_path = Path(cn_path).relative_to(data_path)
87+
# output dict for pandas series for dataframe row
88+
d = dict()
9189

9290
print("finished computing correlation image")
9391

@@ -96,26 +94,34 @@ def main(batch_path, uuid, data_path: str = None):
9694
x_shifts = mc.x_shifts_els
9795
y_shifts = mc.y_shifts_els
9896
shifts = [x_shifts, y_shifts]
99-
shift_path = str(Path(input_movie_path).parent.joinpath(f"{uuid}_shifts.npy"))
100-
np.save(shift_path, shifts)
97+
shift_path = Path(input_movie_path).parent.joinpath(f"{uuid}_shifts.npy")
98+
np.save(str(shift_path), shifts)
10199
else:
102100
shifts = mc.shifts_rig
103-
shift_path = str(Path(input_movie_path).parent.joinpath(f"{uuid}_shifts.npy"))
104-
np.save(shift_path, shifts)
101+
shift_path = Path(input_movie_path).parent.joinpath(f"{uuid}_shifts.npy")
102+
np.save(str(shift_path), shifts)
103+
104+
if data_path is not None:
105+
cn_path = cn_path.relative_to(data_path)
106+
output_path = get_full_data_path(output_path).relative_to(data_path)
107+
shift_path = shift_path.relative_to(data_path)
108+
for proj_type in proj_paths.keys():
109+
d[f"{proj_type}-projection-path"] = proj_paths[proj_type].relative_to(data_path)
110+
else:
111+
cn_path = cn_path
112+
output_path = get_full_data_path(output_path)
113+
shift_path = shift_path.resolve()
105114

106-
d = dict()
107115
d.update(
108116
{
109117
"mcorr-output-path": output_path,
110118
"corr-img-path": cn_path,
111-
"mean-projection-path": paths[0],
112-
"std-projection-path": paths[1],
113-
"max-projection-path": paths[2],
114119
"shifts": shift_path,
115120
"success": True,
116121
"traceback": None
117122
}
118123
)
124+
119125
except:
120126
d = {"success": False, "traceback": traceback.format_exc()}
121127
print("mc failed, stored traceback in output")

mesmerize_core/caiman_extensions/cnmf.py

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from functools import lru_cache
22
from pathlib import Path
3-
from typing import List, Tuple
3+
from typing import *
44

55
import numpy as np
66
import pandas as pd
@@ -121,7 +121,10 @@ def get_spatial_masks(self, ixs_components: np.ndarray, threshold: float = 0.01)
121121
# TODO: Cache this globally so that a common upper cache limit is valid for ALL batch items
122122
@staticmethod
123123
@lru_cache(5)
124-
def _get_spatial_contour_coors(cnmf_obj: CNMF):
124+
def _get_spatial_contours(cnmf_obj: CNMF, ixs_components: Optional[np.ndarray] = None):
125+
if ixs_components is None:
126+
ixs_components = cnmf_obj.estimates.idx_components
127+
125128
dims = cnmf_obj.dims
126129
if dims is None: # I think that one of these is `None` if loaded from an hdf5 file
127130
dims = cnmf_obj.estimates.dims
@@ -130,47 +133,46 @@ def _get_spatial_contour_coors(cnmf_obj: CNMF):
130133
dims = dims[1], dims[0]
131134

132135
contours = caiman_get_contours(
133-
cnmf_obj.estimates.A,
136+
cnmf_obj.estimates.A[:, ixs_components],
134137
dims,
135138
swap_dim=True
136139
)
137140

138141
return contours
139142

140143
@validate('cnmf')
141-
def get_spatial_contours(self, ixs_components: np.ndarray) -> List[dict]:
144+
def get_spatial_contours(
145+
self,
146+
ixs_components: Optional[np.ndarray] = None
147+
) -> Tuple[List[np.ndarray], List[np.ndarray]]:
142148
"""
143-
Get the contours for the spatial footprints
149+
Get the contour and center of mass for each spatial footprint
144150
145151
Parameters
146152
----------
147153
ixs_components: np.ndarray
148-
indices for which to return spatial contours
154+
indices for which to return spatial contours.
155+
if `None` just returns according to cnmf.estimates.idx_components
149156
150157
Returns
151158
-------
152159
153160
"""
154161
cnmf_obj = self.get_output()
155-
contours = self._get_spatial_contour_coors(cnmf_obj)
156-
157-
contours_selection = list()
158-
for i in range(len(contours)):
159-
if i in ixs_components:
160-
contours_selection.append(contours[i])
162+
contours = self._get_spatial_contours(cnmf_obj, ixs_components)
161163

162-
return contours_selection
164+
coordinates = list()
165+
coms = list()
163166

164-
@validate('cnmf')
165-
def get_spatial_contour_coors(self, ixs_components: np.ndarray) -> List[np.ndarray]:
166-
contours = self.get_spatial_contours(ixs_components)
167-
168-
coordinates = []
169167
for contour in contours:
170168
coors = contour['coordinates']
171-
coordinates.append(coors[~np.isnan(coors).any(axis=1)])
169+
coors = coors[~np.isnan(coors).any(axis=1)]
170+
coordinates.append(coors)
171+
172+
com = coors.mean(axis=0)
173+
coms.append(com)
172174

173-
return coordinates
175+
return coordinates, coms
174176

175177
@validate('cnmf')
176178
def get_temporal_components(self, ixs_components: np.ndarray = None, add_background: bool = False) -> np.ndarray:

mesmerize_core/caiman_extensions/mcorr.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def get_shifts(self, output_type: str, pw_rigid: bool = True) -> Union[np.ndarra
6969
return shifts
7070

7171
if pw_rigid:
72-
x_shifts, y_shifts = shifts
72+
return shifts
7373
else:
7474
n_pts = shifts.shape[0]
7575
n_lines = shifts.shape[1]
@@ -78,6 +78,4 @@ def get_shifts(self, output_type: str, pw_rigid: bool = True) -> Union[np.ndarra
7878

7979
for i in range(n_lines):
8080
ys.append(shifts[:, i])
81-
return xs, ys
82-
83-
81+
return xs, ys

0 commit comments

Comments
 (0)