Skip to content

Commit e5174f3

Browse files
committed
2 parents 0e8784f + 6dcd921 commit e5174f3

File tree

6 files changed

+205
-7
lines changed

6 files changed

+205
-7
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,3 @@ dj_local_conf_old.json
114114
**/*~
115115
**/#*#
116116
**/.#*
117-
docker-compose.y*ml

CHANGELOG.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,11 @@
22

33
Observes [Semantic Versioning](https://semver.org/spec/v2.0.0.html) standard and [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) convention.
44

5-
## [0.3.2] - 2022-12-14
6-
7-
+ Update - PrairieView metadata includes recording start time
8-
9-
## [0.3.1] - Unreleased
5+
## [0.4.0] - 2022-12-14
106

117
+ Add - mkdocs documentation
128
+ Add - improved docstrings for mkdocs
9+
+ Add - EXTRACT trigger and loader tools
1310

1411
## [0.3.0] - 2022-10-7
1512

@@ -40,6 +37,7 @@ Observes [Semantic Versioning](https://semver.org/spec/v2.0.0.html) standard and
4037

4138
+ Add - Readers for: `ScanImage`, `Suite2p`, `CaImAn`.
4239

40+
[0.4.0]: https://github.com/datajoint/element-interface/releases/tag/0.4.0
4341
[0.3.0]: https://github.com/datajoint/element-interface/releases/tag/0.3.0
4442
[0.2.1]: https://github.com/datajoint/element-interface/releases/tag/0.2.1
4543
[0.2.0]: https://github.com/datajoint/element-interface/releases/tag/0.2.0

docs/docker-compose.yaml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# MODE="LIVE|QA|PUSH" PACKAGE=element_interface UPSTREAM_REPO=https://github.com/datajoint/element-interface.git HOST_UID=$(id -u) docker compose -f docs/docker-compose.yaml up --build
2+
#
3+
# navigate to http://localhost/
4+
version: "2.4"
5+
services:
6+
docs:
7+
build:
8+
dockerfile: docs/.docker/Dockerfile
9+
context: ../
10+
args:
11+
- PACKAGE
12+
image: ${PACKAGE}-docs
13+
environment:
14+
- PACKAGE
15+
- UPSTREAM_REPO
16+
- MODE
17+
- GOOGLE_ANALYTICS_KEY
18+
- PATCH_VERSION
19+
volumes:
20+
- ../docs:/main/docs
21+
- ../${PACKAGE}:/main/${PACKAGE}
22+
user: ${HOST_UID}:anaconda
23+
ports:
24+
- 80:80
25+
command:
26+
- sh
27+
- -c
28+
- |
29+
git config --global --add safe.directory /main
30+
set -e
31+
export PATCH_VERSION=$$(cat /main/$${PACKAGE}/version.py | grep -oE '\d+\.\d+\.[a-z0-9]+')
32+
if echo "$${MODE}" | grep -i live &>/dev/null; then
33+
mkdocs serve --config-file ./docs/mkdocs.yaml -a 0.0.0.0:80
34+
elif echo "$${MODE}" | grep -iE "qa|push" &>/dev/null; then
35+
echo "INFO::Delete gh-pages branch"
36+
git branch -D gh-pages || true
37+
echo "INFO::Fetch upstream gh-pages"
38+
git fetch $${UPSTREAM_REPO} gh-pages:gh-pages && git switch gh-pages || git switch --orphan gh-pages && git commit --allow-empty -m "init commit"
39+
echo "INFO::mike"
40+
mike deploy --config-file ./docs/mkdocs.yaml -u $$(grep -oE '\d+\.\d+' /main/$${PACKAGE}/version.py) latest
41+
mike set-default --config-file ./docs/mkdocs.yaml latest
42+
if echo "$${MODE}" | grep -i qa &>/dev/null; then
43+
mike serve --config-file ./docs/mkdocs.yaml -a 0.0.0.0:80
44+
elif echo "$${MODE}" | grep -i push &>/dev/null; then
45+
echo "INFO::Push gh-pages to upstream"
46+
git push $${UPSTREAM_REPO} gh-pages
47+
fi
48+
else
49+
echo "Unexpected mode..."
50+
exit 1
51+
fi
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import os
2+
import numpy as np
3+
from pathlib import Path
4+
from datetime import datetime
5+
6+
7+
class EXTRACT_loader:
8+
def __init__(self, extract_dir: str):
9+
"""Initialize EXTRACT loader class
10+
11+
Args:
12+
extract_dir (str): string, absolute file path to EXTRACT directory
13+
14+
Raises:
15+
FileNotFoundError: Could not find EXTRACT results
16+
"""
17+
from scipy.io import loadmat
18+
19+
try:
20+
extract_file = next(Path(extract_dir).glob("*_extract_output.mat"))
21+
except StopInteration:
22+
raise FileNotFoundError(
23+
f"EXTRACT output result file is not found at {extract_dir}."
24+
)
25+
26+
results = loadmat(extract_file)
27+
28+
self.creation_time = datetime.fromtimestamp(os.stat(extract_file).st_ctime)
29+
self.S = results["output"][0]["spatial_weights"][0] # (Height, Width, MaskId)
30+
self.T = results["output"][0]["temporal_weights"][0] # (Time, MaskId)
31+
32+
def load_results(self):
33+
"""Load the EXTRACT results
34+
35+
Returns:
36+
masks (dict): Details of the masks identified with the EXTRACT segmentation package.
37+
"""
38+
from scipy.sparse import find
39+
40+
S_transposed = self.S.transpose([2, 0, 1]) # MaskId, Height, Width
41+
42+
masks = []
43+
44+
for mask_id, s in enumerate(S_transposed):
45+
ypixels, xpixels, weights = find(s)
46+
masks.append(
47+
dict(
48+
mask_id=mask_id,
49+
mask_npix=len(weights),
50+
mask_weights=weights,
51+
mask_center_x=int(np.average(xpixels, weights=weights) + 0.5),
52+
mask_center_y=int(np.average(ypixels, weights=weights) + 0.5),
53+
mask_center_z=None,
54+
mask_xpix=xpixels,
55+
mask_ypix=ypixels,
56+
mask_zpix=None,
57+
)
58+
)
59+
return masks
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import os
2+
from typing import Union
3+
from pathlib import Path
4+
from textwrap import dedent
5+
from datetime import datetime
6+
7+
8+
class EXTRACT_trigger:
9+
m_template = dedent(
10+
"""
11+
% Load Data
12+
data = load('{scanfile}');
13+
M = data.M;
14+
15+
% Input Paramaters
16+
config = struct();
17+
{parameters_list_string}
18+
19+
% Run EXTRACT
20+
output = extractor(M, config);
21+
save('{output_fullpath}', 'output');
22+
"""
23+
)
24+
25+
def __init__(
26+
self,
27+
scanfile: Union[str, Path],
28+
parameters: dict,
29+
output_dir: Union[str, Path],
30+
) -> None:
31+
"""A helper class to trigger EXTRACT analysis in element-calcium-imaging.
32+
33+
Args:
34+
scanfile (Union[str, Path]): Full path of the scan
35+
parameters (dict): EXTRACT input paramaters.
36+
output_dir (Union[str, Path]): Directory to store the outputs of EXTRACT analysis.
37+
"""
38+
assert isinstance(parameters, dict)
39+
40+
self.scanfile = Path(scanfile)
41+
self.output_dir = Path(output_dir)
42+
self.parameters = parameters
43+
44+
def write_matlab_run_script(self):
45+
"""Compose a matlab script and save it with the name run_extract.m.
46+
47+
The composed script is basically the formatted version of the m_template attribute."""
48+
49+
self.output_fullpath = (
50+
self.output_dir / f"{self.scanfile.stem}_extract_output.mat"
51+
)
52+
53+
m_file_content = self.m_template.format(
54+
**dict(
55+
parameters_list_string="\n".join(
56+
[
57+
f"config.{k} = '{v}';"
58+
if isinstance(v, str)
59+
else f"config.{k} = {str(v).lower()};"
60+
if isinstance(v, bool)
61+
else f"config.{k} = {v};"
62+
for k, v in self.parameters.items()
63+
]
64+
),
65+
scanfile=self.scanfile.as_posix(),
66+
output_fullpath=self.output_fullpath.as_posix(),
67+
)
68+
).lstrip()
69+
70+
self.m_file_fp = self.output_dir / "run_extract.m"
71+
72+
with open(self.m_file_fp, "w") as f:
73+
f.write(m_file_content)
74+
75+
def run(self):
76+
"""Run the matlab run_extract.m script."""
77+
78+
self.write_matlab_run_script()
79+
80+
current_dir = Path.cwd()
81+
os.chdir(self.output_dir)
82+
83+
try:
84+
import matlab.engine
85+
86+
eng = matlab.engine.start_matlab()
87+
eng.run_extract()
88+
except Exception as e:
89+
raise e
90+
finally:
91+
os.chdir(current_dir)

element_interface/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""Package metadata"""
22

3-
__version__ = "0.3.2"
3+
__version__ = "0.4.0"

0 commit comments

Comments
 (0)