Skip to content
Draft
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
9 changes: 9 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[run]
source = navigate
omit =
*/config.py
*/config-*.py

[report]
exclude_lines =
pragma: no cover
12 changes: 9 additions & 3 deletions .github/workflows/push_checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
runs-on: ${{ matrix.operating-system }}
strategy:
matrix:
python-version: ["3.9"]
python-version: ["3.9", "3.13"]
operating-system: [windows-latest] # [ubuntu-latest, windows-latest]
env:
MPLBACKEND: Agg # https://github.com/microsoft/azure-pipelines-tasks/issues/16426
Expand All @@ -26,10 +26,16 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e '.[dev]'
python -m pip install uv

# sync dependencies from uv.lock
uv sync
uv sync --group dev

python -m pip install -e . --no-deps
- name: Test with pytest
run: |
python3 -m pytest
uv run pytest
- name: Codecov
uses: codecov/codecov-action@v3.1.0
with:
Expand Down
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,21 @@ navigate
**navigate** is an open source Python package for control of light-sheet microscopes.
It allows for easily reconfigurable hardware setups and automated acquisition routines.

### Quick install
### Quick install with UV

Download and install [UV](https://uv.readthedocs.io/en/latest/installation.html).

```
cd path/to/navigate
uv sync

# Install optional dependencies for development
uv sync --group dev --group docs
```

To test, run 'uv run navigate -sh' to launch in synthetic hardware mode.

### Quick install with Miniconda

Download and install [Miniconda](https://docs.conda.io/en/latest/miniconda.html#latest-miniconda-installer-links).

Expand Down
43 changes: 22 additions & 21 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,40 @@ classifiers = [
"Operating System :: MacOS :: MacOS X",
"Operating System :: Microsoft :: Windows",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
]

requires-python = ">=3.9.7"
dependencies = [
'matplotlib-inline==0.1.3',
'PyYAML==6.0',
'pyserial==3.5',
'PIPython==2.6.0.1',
'nidaqmx==0.5.7',
'tifffile==2021.11.2',
'scipy==1.7.3',
'pyusb==1.2.1',
'pandas==1.3.5',
'pandastable==0.12.2.post1',
'opencv-python==4.5.5.62',
'numpy==1.22.0; sys_platform != "darwin"',
'numpy==1.21.6; sys_platform == "darwin"',
'scikit-image==0.19.1',
'zarr==2.14.2',
'fsspec==2022.8.2; sys_platform != "darwin"',
'fsspec==2022.5.0; sys_platform == "darwin"',
'h5py==3.7.0',
'requests==2.28.1',
'matplotlib-inline',
"pyyaml>=6.0.2",
'pyserial>=3.5',
'PIPython>=2.6.0.1',
'nidaqmx>=0.5.7',
"tifffile>=2024.2",
"scipy>=1.7.3",
"pandas>=2.1",
'pandastable>=0.12.2.post1',
"opencv-python>=4.10",
"numpy>=2.0",
"scikit-image>=0.22",
'zarr<3.0.1',
"fsspec>=2024.3.1",
"h5py>=3.11",
"requests>=2.31",
'psutil==6.0.0',
]

[project.scripts]
navigate = "navigate.main:main"

[project.optional-dependencies]
[dependency-groups]
dev = [
"pytest",
"pytest-xvfb",
Expand All @@ -66,7 +68,6 @@ docs = [
"sphinx-copybutton",
"sphinx-issues",
"sphinx-design",
"pyyaml",
"pydata_sphinx_theme==0.10.0rc2",
"sphinx-toolbox",
]
Expand Down
3,583 changes: 3,583 additions & 0 deletions requirements.txt

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/navigate/config/configuration_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@
"Input",
"string",
None,
"Example: D:\WaveKitX64\MirrorFiles\Beads.wcs",
r"Example: D:\WaveKitX64\MirrorFiles\Beads.wcs",
],
"n_modes": ["Number of Modes", "Input", "int", None, "Example: 32", 32],
}
Expand Down
4 changes: 2 additions & 2 deletions src/navigate/controller/sub_controllers/camera_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ def create_camera_maps(self):
save_path_offset = Path(save_dir).joinpath(save_name_offset)
save_path_variance = Path(save_dir).joinpath(save_name_variance)

tifffile.imsave(save_path_offset, self.off)
tifffile.imsave(save_path_variance, self.var)
tifffile.imwrite(save_path_offset, self.off)
tifffile.imwrite(save_path_variance, self.var)

def display_plot(self):
"""Display the offset and variance maps."""
Expand Down
2 changes: 1 addition & 1 deletion src/navigate/controller/sub_controllers/keystrokes.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def __init__(self, main_view: MainApp, parent_controller: Any) -> None:
self.multi_table = main_view.settings.multiposition_tab.multipoint_list.pt

#: MultiPositionTable: Multiposition Table
self.multi_table.rowheader.bind(
self.multi_table.row_header.bind(
"<Double-Button-1>", self.multi_controller.handle_double_click
)

Expand Down
9 changes: 6 additions & 3 deletions src/navigate/controller/sub_controllers/multiposition.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,9 @@ def move_to_position(self) -> None:

def insert_row_func(self) -> None:
"""Insert a row in the Multi-Position Acquisition Interface."""
self.table.model.addRow(self.table.currentrow)
insert_at = max(self.table.currentrow, 0)
self.table.model.insertRow(insert_at)
self.table.currentrow = insert_at
self.table.update_rowcolors()
self.table.redraw()
self.table.tableChanged()
Expand Down Expand Up @@ -356,8 +358,9 @@ def append_position(self, position: dict) -> None:
self.table.model.df = self.table.model.df.reindex(columns=headers)

# temp = list(map(lambda k: position[k], position))
self.table.model.df = self.table.model.df.append(
pd.DataFrame([temp], columns=headers), ignore_index=True
new_row = pd.DataFrame([temp], columns=headers)
self.table.model.df = pd.concat(
[self.table.model.df, new_row], ignore_index=True
)
self.table.currentrow = self.table.model.df.shape[0] - 1
self.table.update_rowcolors()
Expand Down
2 changes: 1 addition & 1 deletion src/navigate/model/data_sources/tiff_data_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ def write(self, data: npt.ArrayLike, **kw) -> None:
data : npt.ArrayLike
Data to write to file.
kw : dict
Keyword arguments to pass to tifffile.imsave.
Keyword arguments to pass to tifffile.imwrite.
"""
self.mode = "w"

Expand Down
3 changes: 1 addition & 2 deletions src/navigate/model/devices/APIs/thorlabs/kcube_inertial.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@
Tested on Thorlabs KIM001.
"""


import ctypes
import ctypes.wintypes
from enum import IntEnum

CODING = "ascii"

__dll = ctypes.WinDLL(
"C:\Program Files\Thorlabs\Kinesis\Thorlabs.MotionControl.KCube.InertialMotor.dll"
r"C:\Program Files\Thorlabs\Kinesis\Thorlabs.MotionControl.KCube.InertialMotor.dll"
)


Expand Down
45 changes: 24 additions & 21 deletions src/navigate/model/devices/APIs/thorlabs/kcube_steppermotor.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import ctypes
import ctypes.wintypes
from enum import IntEnum

# from System import Decimal # necessary for real world units

"""
Expand All @@ -29,7 +30,7 @@
CODING = "ascii"

__dll = ctypes.WinDLL(
"C:\Program Files\Thorlabs\Kinesis\Thorlabs.MotionControl.KCube.StepperMotor.dll"
r"C:\Program Files\Thorlabs\Kinesis\Thorlabs.MotionControl.KCube.StepperMotor.dll"
)


Expand Down Expand Up @@ -418,6 +419,7 @@ def KST_StartPolling(serial_no, milliseconds):
__dll.SCC_StopPolling.argtypes = [ctypes.c_char_p]
__dll.SCC_StopPolling.restype = ctypes.c_short


def KST_StopPolling(serial_no):
"""
Stops the internal polling loop.
Expand Down Expand Up @@ -470,17 +472,16 @@ def KST_RequestPosition(serial_no):


def KST_MoveToPosition(serial_no, position):
"""Move to position
"""
"""Move to position"""
return __dll.SCC_MoveToPosition(serial_no.encode(CODING), int(position))


__dll.SCC_GetPosition.argtypes = [ctypes.c_char_p]
__dll.SCC_GetPosition.restype = ctypes.c_int


def KST_GetCurrentPosition(serial_no):
"""Get the current position
"""Get the current position

Parmeters
---------
Expand All @@ -492,18 +493,18 @@ def KST_GetCurrentPosition(serial_no):
int
Current position.
"""
# check if polling is active, if not RequestPosition
if __dll.SCC_PollingDuration(serial_no.encode(CODING))==0:
# check if polling is active, if not RequestPosition
if __dll.SCC_PollingDuration(serial_no.encode(CODING)) == 0:
KST_RequestPosition(serial_no)

return __dll.SCC_GetPosition(serial_no.encode(CODING))


__dll.SCC_MoveAbsolute.argtypes = [ctypes.c_char_p]
__dll.SCC_MoveAbsolute.restype = ctypes.c_short
__dll.SCC_MoveAbsolute.errcheck = errcheck


def KST_MoveAbsolute(serial_no):
"""
Move absolute to set position.
Expand All @@ -520,7 +521,7 @@ def KST_MoveAbsolute(serial_no):
int
The error code or 0 if successful.
"""

return __dll.SCC_MoveAbsolute(serial_no.encode(CODING))


Expand All @@ -545,7 +546,7 @@ def KST_SetAbsolutePosition(serial_no, position):
int
The error code or 0 if successful.
"""

return __dll.SCC_SetMoveAbsolutePosition(serial_no.encode(CODING), int(position))


Expand Down Expand Up @@ -578,13 +579,16 @@ def KST_MoveJog(serial_no, jog_direction):
The error code or 0 if successful.
"""

return __dll.SCC_MoveJog(serial_no.encode(CODING), MOT_TravelDirection(jog_direction))
return __dll.SCC_MoveJog(
serial_no.encode(CODING), MOT_TravelDirection(jog_direction)
)


__dll.SCC_StopProfiled.argtypes = [ctypes.c_char_p]
__dll.SCC_StopProfiled.restype = ctypes.c_short
__dll.SCC_StopProfiled.errcheck = errcheck


def KST_MoveStop(serial_no):
"""
Halt motion
Expand All @@ -605,7 +609,7 @@ def KST_MoveStop(serial_no):
# SCC_StopImmediate(char const * serialNo)
# NOTE: for stopping using the current velocity params use:
# return __dll.SCC_StopProfiled(serial_no.encode(CODING))

return __dll.SCC_StopProfiled(serial_no.encode(CODING))


Expand All @@ -615,15 +619,14 @@ def KST_MoveStop(serial_no):


def KST_HomeDevice(serial_no):
"""Home Device
"""
"""Home Device"""
return __dll.SCC_Home(serial_no.encode(CODING))


def KST_SetVelocityParams(serial_no, velocity):
"""Set velocity profile required for move
"""
"""Set velocity profile required for move"""
current_velocity = 0
current_accel = 0

__dll.SCC_GetVelParams(serial_no.encode(CODING), current_velocity, current_accel)
__dll.SCC_SetVelParams(serial_no.encode(CODING), current_accel, velocity)
__dll.SCC_SetVelParams(serial_no.encode(CODING), current_accel, velocity)
4 changes: 2 additions & 2 deletions src/navigate/model/features/image_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@

# Third Party Imports
import numpy as np
from tifffile import imsave
from tifffile import imwrite

# Local imports
import navigate
Expand Down Expand Up @@ -257,7 +257,7 @@ def save_image(self, frame_ids):
+ str(t_idx).zfill(6)
+ ".tif"
)
imsave(
imwrite(
os.path.join(self.mip_directory, mip_name),
self.mip[c_save_idx, :, :],
)
Expand Down
2 changes: 1 addition & 1 deletion src/navigate/model/features/volume_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ def end_data_func(self):
if self.debug:
import tifffile

tifffile.imsave(
tifffile.imwrite(
"volume_search_2d_debug_result.tif", self.volumes_selected
)
return self.end_flag
Expand Down
Loading
Loading