Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
358c0d6
add extract_utils.py for EXTRACT
tdincer Dec 1, 2022
c3cd4b2
Merge branch 'main' of https://github.com/tdincer/element-interface
tdincer Dec 1, 2022
210bd9a
Merge branch 'datajoint:main' into main
tdincer Dec 1, 2022
87afa22
add docstring
tdincer Dec 1, 2022
74c2781
Merge branch 'main' of https://github.com/tdincer/element-interface
tdincer Dec 1, 2022
99c4fb8
fix ugly template style
tdincer Dec 2, 2022
4fd50a7
remove return run_status
tdincer Dec 13, 2022
6ebf019
switch from write to save
tdincer Dec 13, 2022
04b8f69
add loader and trigger
tdincer Dec 14, 2022
e8d5b0a
update changelog
tdincer Dec 14, 2022
7cffc25
add creation_time
tdincer Dec 14, 2022
d2eb1e8
Update element_interface/extract_loader.py
tdincer Dec 14, 2022
2ab366d
Update element_interface/extract_loader.py
tdincer Dec 14, 2022
e3ff2ad
Update element_interface/extract_loader.py
tdincer Dec 14, 2022
c18aa11
Update element_interface/extract_loader.py
tdincer Dec 14, 2022
e5ed418
Update element_interface/extract_trigger.py
tdincer Dec 14, 2022
d93c2de
Update element_interface/extract_loader.py
tdincer Dec 14, 2022
3517d13
Update element_interface/extract_loader.py
tdincer Dec 14, 2022
1796c52
Update element_interface/extract_trigger.py
tdincer Dec 14, 2022
8554cc3
Update element_interface/extract_trigger.py
tdincer Dec 14, 2022
bca1a5a
Update element_interface/extract_trigger.py
tdincer Dec 14, 2022
f25669e
Update element_interface/extract_loader.py
tdincer Dec 14, 2022
caa89c8
update changelog
tdincer Dec 14, 2022
6115c2e
Merge branch 'main' of https://github.com/tdincer/element-interface
tdincer Dec 14, 2022
bb1f15f
Update element_interface/extract_trigger.py
tdincer Dec 14, 2022
1bf75cc
Update element_interface/extract_trigger.py
tdincer Dec 14, 2022
0b5dc06
Update element_interface/extract_loader.py
tdincer Dec 14, 2022
e03c967
final touches
tdincer Dec 14, 2022
1583e02
Merge branch 'main' of https://github.com/tdincer/element-interface
tdincer Dec 14, 2022
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
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

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

## [0.3.1] - Unreleased
## [0.4.0] - 2022-12-14

+ Add - mkdocs documentation
+ Add - improved docstrings for mkdocs
+ Add - EXTRACT trigger and loader tools

## [0.3.0] - 2022-10-7

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

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

[0.4.0]: https://github.com/datajoint/element-interface/releases/tag/0.4.0
[0.3.0]: https://github.com/datajoint/element-interface/releases/tag/0.3.0
[0.2.1]: https://github.com/datajoint/element-interface/releases/tag/0.2.1
[0.2.0]: https://github.com/datajoint/element-interface/releases/tag/0.2.0
Expand Down
59 changes: 59 additions & 0 deletions element_interface/extract_loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import os
import numpy as np
from pathlib import Path
from datetime import datetime


class EXTRACT_loader:
def __init__(self, extract_dir: str):
"""Initialize EXTRACT loader class

Args:
extract_dir (str): string, absolute file path to EXTRACT directory

Raises:
FileNotFoundError: Could not find EXTRACT results
"""
from scipy.io import loadmat

try:
extract_file = next(Path(extract_dir).glob("*_extract_output.mat"))
except StopInteration:
raise FileNotFoundError(
f"EXTRACT output result file is not found at {extract_dir}."
)

results = loadmat(extract_file)

self.creation_time = datetime.fromtimestamp(os.stat(extract_file).st_ctime)
self.S = results["output"][0]["spatial_weights"][0] # (Height, Width, MaskId)
self.T = results["output"][0]["temporal_weights"][0] # (Time, MaskId)

def load_results(self):
"""Load the EXTRACT results

Returns:
masks (dict): Details of the masks identified with the EXTRACT segmentation package.
"""
from scipy.sparse import find

S_transposed = self.S.transpose([2, 0, 1]) # MaskId, Height, Width

masks = []

for mask_id, s in enumerate(S_transposed):
ypixels, xpixels, weights = find(s)
masks.append(
dict(
mask_id=mask_id,
mask_npix=len(weights),
mask_weights=weights,
mask_center_x=int(np.average(xpixels, weights=weights) + 0.5),
mask_center_y=int(np.average(ypixels, weights=weights) + 0.5),
mask_center_z=None,
mask_xpix=xpixels,
mask_ypix=ypixels,
mask_zpix=None,
)
)
return masks
91 changes: 91 additions & 0 deletions element_interface/extract_trigger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import os
from typing import Union
from pathlib import Path
from textwrap import dedent
from datetime import datetime


class EXTRACT_trigger:
m_template = dedent(
"""
% Load Data
data = load('{scanfile}');
M = data.M;

% Input Paramaters
config = struct();
{parameters_list_string}

% Run EXTRACT
output = extractor(M, config);
save('{output_fullpath}', 'output');
"""
)

def __init__(
self,
scanfile: Union[str, Path],
parameters: dict,
output_dir: Union[str, Path],
) -> None:
"""A helper class to trigger EXTRACT analysis in element-calcium-imaging.

Args:
scanfile (Union[str, Path]): Full path of the scan
parameters (dict): EXTRACT input paramaters.
output_dir (Union[str, Path]): Directory to store the outputs of EXTRACT analysis.
"""
assert isinstance(parameters, dict)

self.scanfile = Path(scanfile)
self.output_dir = Path(output_dir)
self.parameters = parameters

def write_matlab_run_script(self):
"""Compose a matlab script and save it with the name run_extract.m.

The composed script is basically the formatted version of the m_template attribute."""

self.output_fullpath = (
self.output_dir / f"{self.scanfile.stem}_extract_output.mat"
)

m_file_content = self.m_template.format(
**dict(
parameters_list_string="\n".join(
[
f"config.{k} = '{v}';"
if isinstance(v, str)
else f"config.{k} = {str(v).lower()};"
if isinstance(v, bool)
else f"config.{k} = {v};"
for k, v in self.parameters.items()
]
),
scanfile=self.scanfile.as_posix(),
output_fullpath=self.output_fullpath.as_posix(),
)
).lstrip()

self.m_file_fp = self.output_dir / "run_extract.m"

with open(self.m_file_fp, "w") as f:
f.write(m_file_content)

def run(self):
"""Run the matlab run_extract.m script."""

self.write_matlab_run_script()

current_dir = Path.cwd()
os.chdir(self.output_dir)

try:
import matlab.engine

eng = matlab.engine.start_matlab()
eng.run_extract()
except Exception as e:
raise e
finally:
os.chdir(current_dir)
2 changes: 1 addition & 1 deletion element_interface/version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Package metadata"""

__version__ = "0.3.1"
__version__ = "0.4.0"