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

Use Path.resolve() consistently to prevent UNC/drive letter ambiguity #304

Open
wants to merge 3 commits into
base: master
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,6 @@ dmypy.json
tests/tmp
tests/videos
tests/ground_truths*

# VSCode
.vscode/
45 changes: 25 additions & 20 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@

# -- Project information -----------------------------------------------------

project = 'mesmerize-core'
copyright = '2023, Kushal Kolar, Caitlin Lewis, Arjun Putcha'
author = 'Kushal Kolar, Caitlin Lewis, Arjun Putcha'
project = "mesmerize-core"
copyright = "2023, Kushal Kolar, Caitlin Lewis, Arjun Putcha"
author = "Kushal Kolar, Caitlin Lewis, Arjun Putcha"

# The full version, including alpha/beta/rc tags
release = mesmerize_core.__version__
Expand All @@ -35,7 +35,7 @@
autodoc_typehints = "description"

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
Expand All @@ -48,51 +48,56 @@
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'pydata_sphinx_theme'
html_theme = "pydata_sphinx_theme"
html_theme_options = {"page_sidebar_items": ["class_page_toc"]}
autoclass_content = "both"

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_static_path = ["_static"]

autodoc_member_order = 'bysource'
autodoc_member_order = "bysource"


def _setup_navbar_side_toctree(app: Any):
def add_class_toctree_function(app: Any, pagename: Any, templatename: Any, context: Any, doctree: Any):
def add_class_toctree_function(
app: Any, pagename: Any, templatename: Any, context: Any, doctree: Any
):
def get_class_toc() -> Any:
soup = BeautifulSoup(context["body"], "html.parser")

matches = soup.find_all('dl')
matches = soup.find_all("dl")
if matches is None or len(matches) == 0:
return ""
items = []
deeper_depth = matches[0].find('dt').get('id').count(".")
deeper_depth = matches[0].find("dt").get("id").count(".")
for match in matches:
match_dt = match.find('dt')
if match_dt is not None and match_dt.get('id') is not None:
current_title = match_dt.get('id')
current_depth = match_dt.get('id').count(".")
match_dt = match.find("dt")
if match_dt is not None and match_dt.get("id") is not None:
current_title = match_dt.get("id")
current_depth = match_dt.get("id").count(".")
current_link = match.find(class_="headerlink")
if current_link is not None:
if deeper_depth > current_depth:
deeper_depth = current_depth
if deeper_depth == current_depth:
items.append({
"title": current_title.split('.')[-1],
"link": current_link["href"],
"attributes_and_methods": []
})
items.append(
{
"title": current_title.split(".")[-1],
"link": current_link["href"],
"attributes_and_methods": [],
}
)
if deeper_depth < current_depth:
items[-1]["attributes_and_methods"].append(
{
"title": current_title.split('.')[-1],
"title": current_title.split(".")[-1],
"link": current_link["href"],
}
)
return items

context["get_class_toc"] = get_class_toc

app.connect("html-page-context", add_class_toctree_function)
Expand Down
20 changes: 12 additions & 8 deletions mesmerize_core/algorithms/cnmf.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Performs CNMF in a separate process"""

import click
import caiman as cm
from caiman.source_extraction.cnmf import cnmf as cnmf
Expand Down Expand Up @@ -32,7 +33,7 @@ def run_algo(batch_path, uuid, data_path: str = None):
input_movie_path = str(df.paths.resolve(input_movie_path))

# make output dir
output_dir = Path(batch_path).parent.joinpath(str(uuid))
output_dir = Path(batch_path).parent.joinpath(str(uuid)).resolve()
output_dir.mkdir(parents=True, exist_ok=True)

params = item["params"]
Expand Down Expand Up @@ -95,14 +96,14 @@ def run_algo(batch_path, uuid, data_path: str = None):
print("performing eval")
cnm.estimates.evaluate_components(images, cnm.params, dview=dview)

output_path = output_dir.joinpath(f"{uuid}.hdf5").resolve()
output_path = output_dir.joinpath(f"{uuid}.hdf5")

cnm.save(str(output_path))

Cn = cm.local_correlations(images, swap_dim=False)
Cn[np.isnan(Cn)] = 0

corr_img_path = output_dir.joinpath(f"{uuid}_cn.npy").resolve()
corr_img_path = output_dir.joinpath(f"{uuid}_cn.npy")
np.save(str(corr_img_path), Cn, allow_pickle=False)

# output dict for dataframe row (pd.Series)
Expand All @@ -115,12 +116,14 @@ def run_algo(batch_path, uuid, data_path: str = None):

# save paths as relative path strings with forward slashes
cnmf_hdf5_path = str(PurePosixPath(output_path.relative_to(output_dir.parent)))
cnmf_memmap_path = str(PurePosixPath(cnmf_memmap_path.relative_to(output_dir.parent)))
cnmf_memmap_path = str(
PurePosixPath(cnmf_memmap_path.relative_to(output_dir.parent))
)
corr_img_path = str(PurePosixPath(corr_img_path.relative_to(output_dir.parent)))
for proj_type in proj_paths.keys():
d[f"{proj_type}-projection-path"] = str(PurePosixPath(proj_paths[proj_type].relative_to(
output_dir.parent
)))
d[f"{proj_type}-projection-path"] = str(
PurePosixPath(proj_paths[proj_type].relative_to(output_dir.parent))
)

d.update(
{
Expand All @@ -136,10 +139,11 @@ def run_algo(batch_path, uuid, data_path: str = None):
d = {"success": False, "traceback": traceback.format_exc()}

cm.stop_server(dview=dview)

runtime = round(time.time() - algo_start, 2)
df.caiman.update_item_with_results(uuid, d, runtime)


@click.command()
@click.option("--batch-path", type=str)
@click.option("--uuid", type=str)
Expand Down
12 changes: 6 additions & 6 deletions mesmerize_core/algorithms/cnmfe.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def run_algo(batch_path, uuid, data_path: str = None):
# resolve full path
input_movie_path = str(df.paths.resolve(input_movie_path))

output_dir = Path(batch_path).parent.joinpath(str(uuid))
output_dir = Path(batch_path).parent.joinpath(str(uuid)).resolve()
output_dir.mkdir(parents=True, exist_ok=True)

params = item["params"]
Expand Down Expand Up @@ -81,15 +81,13 @@ def run_algo(batch_path, uuid, data_path: str = None):
params_dict = {**cnmfe_params_dict, **params["main"]}

cnmfe_params_dict = CNMFParams(params_dict=params_dict)
cnm = cnmf.CNMF(
n_processes=n_processes, dview=dview, params=cnmfe_params_dict
)
cnm = cnmf.CNMF(n_processes=n_processes, dview=dview, params=cnmfe_params_dict)
print("Performing CNMFE")
cnm = cnm.fit(images)
print("evaluating components")
cnm.estimates.evaluate_components(images, cnm.params, dview=dview)

cnmf_hdf5_path = output_dir.joinpath(f"{uuid}.hdf5").resolve()
cnmf_hdf5_path = output_dir.joinpath(f"{uuid}.hdf5")
cnm.save(str(cnmf_hdf5_path))

# save output paths to outputs dict
Expand All @@ -106,7 +104,9 @@ def run_algo(batch_path, uuid, data_path: str = None):
move_file(fname_new, cnmf_memmap_path)

# save path as relative path strings with forward slashes
cnmfe_memmap_path = str(PurePosixPath(cnmf_memmap_path.relative_to(output_dir.parent)))
cnmfe_memmap_path = str(
PurePosixPath(cnmf_memmap_path.relative_to(output_dir.parent))
)

d.update(
{
Expand Down
15 changes: 8 additions & 7 deletions mesmerize_core/algorithms/mcorr.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,15 @@ def run_algo(batch_path, uuid, data_path: str = None):
Cn[np.isnan(Cn)] = 0
cn_path = output_dir.joinpath(f"{uuid}_cn.npy")
np.save(str(cn_path), Cn, allow_pickle=False)

print("finished computing correlation image")

print("finished computing correlation image")

# Compute shifts
if opts.motion["pw_rigid"] == True:
x_shifts = mc.x_shifts_els
y_shifts = mc.y_shifts_els
shifts = [x_shifts, y_shifts]
if hasattr(mc, 'z_shifts_els'):
if hasattr(mc, "z_shifts_els"):
shifts.append(mc.z_shifts_els)
shift_path = output_dir.joinpath(f"{uuid}_shifts.npy")
np.save(str(shift_path), shifts)
Expand All @@ -125,12 +124,14 @@ def run_algo(batch_path, uuid, data_path: str = None):

# save paths as relative path strings with forward slashes
cn_path = str(PurePosixPath(cn_path.relative_to(output_dir.parent)))
mcorr_memmap_path = str(PurePosixPath(mcorr_memmap_path.relative_to(output_dir.parent)))
mcorr_memmap_path = str(
PurePosixPath(mcorr_memmap_path.relative_to(output_dir.parent))
)
shift_path = str(PurePosixPath(shift_path.relative_to(output_dir.parent)))
for proj_type in proj_paths.keys():
d[f"{proj_type}-projection-path"] = str(PurePosixPath(proj_paths[proj_type].relative_to(
output_dir.parent
)))
d[f"{proj_type}-projection-path"] = str(
PurePosixPath(proj_paths[proj_type].relative_to(output_dir.parent))
)

d.update(
{
Expand Down
2 changes: 1 addition & 1 deletion mesmerize_core/arrays/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"LazyArrayRCB",
"LazyArrayResiduals",
"LazyTiff",
"LazyVideo"
"LazyVideo",
]
36 changes: 20 additions & 16 deletions mesmerize_core/arrays/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class LazyArray(ABC):
"""
Base class for arrays that exhibit lazy computation upon indexing
"""

@property
@abstractmethod
def dtype(self) -> str:
Expand Down Expand Up @@ -122,10 +123,7 @@ def as_numpy(self):
def save_hdf5(self, filename: Union[str, Path]):
pass

def __getitem__(
self,
item: Union[int, Tuple[slice_or_int_or_range]]
):
def __getitem__(self, item: Union[int, Tuple[slice_or_int_or_range]]):
if isinstance(item, int):
indexer = item

Expand Down Expand Up @@ -161,21 +159,25 @@ def __getitem__(

if start is not None:
if start > self.n_frames:
raise IndexError(f"Cannot index beyond `n_frames`.\n"
f"Desired frame start index of <{start}> "
f"lies beyond `n_frames` <{self.n_frames}>")
raise IndexError(
f"Cannot index beyond `n_frames`.\n"
f"Desired frame start index of <{start}> "
f"lies beyond `n_frames` <{self.n_frames}>"
)
if stop is not None:
if stop > self.n_frames:
raise IndexError(f"Cannot index beyond `n_frames`.\n"
f"Desired frame stop index of <{stop}> "
f"lies beyond `n_frames` <{self.n_frames}>")
raise IndexError(
f"Cannot index beyond `n_frames`.\n"
f"Desired frame stop index of <{stop}> "
f"lies beyond `n_frames` <{self.n_frames}>"
)

if step is None:
step = 1

# convert indexer to slice if it was a range, allows things like decord.VideoReader slicing
indexer = slice(start, stop, step) # in case it was a range object

# dimension_0 is always time
frames = self._compute_at_indices(indexer)

Expand All @@ -193,7 +195,9 @@ def __getitem__(
return self._compute_at_indices(indexer)

def __repr__(self):
return f"{self.__class__.__name__} @{hex(id(self))}\n" \
f"{self.__class__.__doc__}\n" \
f"Frames are computed only upon indexing\n" \
f"shape [frames, x, y]: {self.shape}\n"
return (
f"{self.__class__.__name__} @{hex(id(self))}\n"
f"{self.__class__.__doc__}\n"
f"Frames are computed only upon indexing\n"
f"shape [frames, x, y]: {self.shape}\n"
)
Loading
Loading