This repository has been archived by the owner on Nov 26, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #72 from kushalkolar/inscopix-importer
Inscopix importer
- Loading branch information
Showing
9 changed files
with
272 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
docs/source/user_guides/viewer/modules/inscopix_importer.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
.. _module_InscopixImporter: | ||
|
||
Inscopix Importer | ||
***************** | ||
|
||
The Inscopix Importer module can be used to open ``.isxd`` movies created by Inscopix acquisition software | ||
|
||
.. note:: You must have your own license for activating/running the Inscopix Data Processing Software (IDPS) and downloading the IDPS API and ``isx`` library. Mesmerize only provides an implementation of ``isx`` to read ``.isxd`` movies into the application. | ||
|
||
In order to use the importer you will need to add the path to the parent dir containing the ``isx`` library to your ``PYTHONPATH`` environment variable. | ||
|
||
For example if your ``isx`` dir is located at: | ||
|
||
``` | ||
/home/user/Inscopix Data Processing 1.6.0/Inscopix Data Processing.linux/Contents/API/Python/isx`` | ||
``` | ||
|
||
Then you will need to add the path to the parent dir, for example: | ||
|
||
``` | ||
export PYTHONPATH="/home/user/Inscopix Data Processing 1.6.0/Inscopix Data Processing.linux/Contents/API/Python:$PYTHONPATH" | ||
``` | ||
|
||
**Usage:** | ||
|
||
1. Enter the path to the ``.isxd`` or click the ``...`` and choose the file. | ||
|
||
2. Click the button to load the file into the :ref:`Viewer Work Environment <ViewerWorkEnv>`. | ||
|
||
The sampling rate (framerate) of the video is automatically imported from the ``isxd`` file. | ||
|
||
.. note:: Memory usage is quite high when loading files, you will need at least twice as much RAM as the size of the file you're trying to open. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import isx | ||
import numpy as np | ||
import click | ||
from multiprocessing import shared_memory | ||
from tqdm import tqdm | ||
|
||
|
||
@click.command() | ||
@click.option('--isx-path', type=str) | ||
@click.option('--shm-meta-array-name', type=str) | ||
def load_file(isx_path, shm_meta_array_name):#shm_name, shm-size, shm-dtype): | ||
""" | ||
isx_path: full path to the isx file to open | ||
shm_meta_array_name: same of the shared memory array that is used to pass | ||
array metadata (shape, dtype, name) to effectively communication with the | ||
parent mesmerize instance | ||
shm-name: name of the parent shared array that contains the | ||
""" | ||
movie = isx.Movie.read(isx_path) | ||
|
||
meta = movie.get_acquisition_info() | ||
|
||
d = \ | ||
{ | ||
'fps': 1000 / movie.timing.period.to_msecs(), | ||
'origin': meta['Microscope Type'], | ||
'date': '00000000_000000', | ||
'orig_meta': meta | ||
} | ||
|
||
# total number of frames in the recording | ||
nframes = movie.timing.num_samples | ||
|
||
# shape of each frame | ||
frame0 = movie.get_frame_data(0) | ||
|
||
# image shape | ||
shape = (*frame0.shape, nframes) | ||
|
||
# calculate number of bytes required for the shared memory | ||
nbytes = np.prod(shape) * np.dtype(movie.data_type).itemsize | ||
|
||
# created a shared memory buffer | ||
shm = shared_memory.SharedMemory(create=True, size=nbytes) | ||
|
||
# create shared numpy array backed by the shared memory buffer | ||
imgseq = np.ndarray(shape, dtype=np.dtype(movie.data_type), buffer=shm.buf) | ||
|
||
# fill the array with the inscopix data | ||
for i in tqdm(range(nframes)): | ||
imgseq[..., i] = movie.get_frame_data(i) | ||
|
||
# communicate the array metadata to access the shared array from within mesmerize | ||
shm_metadata = shared_memory.SharedMemory(name=shm_meta_array_name) | ||
array_metadata = np.ndarray((5,), dtype=np.dtype('<U64'), buffer=shm_metadata.buf) | ||
|
||
array_metadata[0] = shm.name | ||
array_metadata[1] = np.dtype(movie.data_type).name | ||
array_metadata[2] = ','.join(str(s) for s in shape) | ||
array_metadata[3] = str(d['fps']) | ||
array_metadata[4] = str(d['origin']) | ||
|
||
print(f'imgdata address: {shm.name}') | ||
print(array_metadata) | ||
|
||
shm.close() | ||
|
||
|
||
if __name__ == '__main__': | ||
load_file() | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import numpy as np | ||
from ...common.qdialogs import * | ||
from ..core.common import ViewerUtils | ||
from PyQt5 import QtWidgets | ||
from ..core import ViewerWorkEnv | ||
from ..core.data_types import ImgData | ||
from multiprocessing.shared_memory import SharedMemory | ||
import os | ||
from subprocess import Popen | ||
|
||
|
||
class Widget(QtWidgets.QWidget): | ||
def __init__(self, parent): | ||
QtWidgets.QWidget.__init__(self, parent=parent) | ||
self.vboxlayout = QtWidgets.QVBoxLayout(self) | ||
self.hboxlayout = QtWidgets.QHBoxLayout(self) | ||
|
||
self.label_choose_file = QtWidgets.QLabel() | ||
self.label_choose_file.setText("Choose `.isxd` file") | ||
self.vboxlayout.addWidget(self.label_choose_file) | ||
|
||
self.line_edit_path = QtWidgets.QLineEdit() | ||
self.line_edit_path.setPlaceholderText("Path to `.isxd` file") | ||
self.line_edit_path.returnPressed.connect(self.parent().load_file) | ||
self.hboxlayout.addWidget(self.line_edit_path) | ||
|
||
self.btn_open_file_dialog = QtWidgets.QPushButton() | ||
self.btn_open_file_dialog.setText("...") | ||
self.btn_open_file_dialog.clicked.connect(self.parent().file_dialog) | ||
self.hboxlayout.addWidget(self.btn_open_file_dialog) | ||
|
||
self.vboxlayout.addLayout(self.hboxlayout) | ||
|
||
self.btn_load_file = QtWidgets.QPushButton() | ||
self.btn_load_file.setText("Load File") | ||
self.btn_load_file.clicked.connect(self.parent().load_file) | ||
self.vboxlayout.addWidget(self.btn_load_file) | ||
|
||
|
||
class ModuleGUI(QtWidgets.QDockWidget): | ||
def __init__(self, parent, viewer_reference): | ||
self.vi = ViewerUtils(viewer_reference) | ||
QtWidgets.QDockWidget.__init__(self, parent) | ||
self.setFloating(True) | ||
self.setWindowTitle('Inscopix Importer') | ||
|
||
self.widget = Widget(parent=self) | ||
|
||
self.setWidget(self.widget) | ||
|
||
# self.setLayout(self.vboxlayout) | ||
@use_open_file_dialog("Choose .isxd file", "", exts=["*.isxd"]) | ||
def file_dialog(self, path, *args, **kwargs): | ||
self.widget.line_edit_path.setText(path) | ||
|
||
@present_exceptions("File open error", "The following error occurred when opening the file") | ||
def load_file(self, *args, **kwargs): | ||
shm = SharedMemory(create=True, size=5 * np.dtype('<U64').itemsize) | ||
|
||
# get array metadata, shared memory buffer name, dtype, and shape | ||
array_metadata = np.ndarray(shape=(5,), dtype=np.dtype('<U64'), buffer=shm.buf) | ||
|
||
importer_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '_inscopix_importer.py') | ||
|
||
file_path = self.widget.line_edit_path.text() | ||
|
||
cmd = ['python', importer_path, '--isx-path', file_path, '--shm-meta-array-name', shm.name] | ||
print(cmd) | ||
proc = Popen( | ||
cmd, | ||
env=os.environ.copy() | ||
) | ||
proc.wait() | ||
|
||
# read the metadata | ||
name = array_metadata[0] | ||
dtype = array_metadata[1] | ||
shape = array_metadata[2] | ||
|
||
# open the shared buffer | ||
existing_shm = SharedMemory(name=array_metadata[0]) | ||
|
||
shape = tuple(map(int, shape.split(','))) | ||
|
||
_imgseq = np.ndarray(shape, dtype=np.dtype(dtype), buffer=existing_shm.buf) | ||
|
||
imgseq = np.zeros(shape=shape, dtype=np.dtype(dtype)) | ||
imgseq[:] = _imgseq[:] | ||
|
||
d = \ | ||
{ | ||
'fps': float(array_metadata[3]), | ||
'origin': array_metadata[4], | ||
'date': '00000000_000000' | ||
} | ||
|
||
imgdata = ImgData(imgseq, d) | ||
|
||
self.vi.viewer.workEnv = ViewerWorkEnv(imgdata) | ||
self.vi.update_workEnv() | ||
|
||
existing_shm.close() | ||
|