Skip to content

Commit

Permalink
Merge pull request #1 from Gronemeyer: pymmcore-device-objects
Browse files Browse the repository at this point in the history
Hardware.yaml, refined ExperimentConfig, refactored imports, click->argparse CLI, flattened file structure, arducam support, streamlined file_path generation for saving data
  • Loading branch information
Gronemeyer authored Jan 20, 2025
2 parents ee640a6 + d277587 commit ca9b156
Show file tree
Hide file tree
Showing 22 changed files with 1,105 additions and 944 deletions.
31 changes: 31 additions & 0 deletions dev.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
memory_buffer_size: 10000
viewer_type: "static"

encoder:
type: "wheel"
port: "COM4"
baudrate: 57600
cpr: 2400
diameter_mm: 80
sample_interval_ms: 20
development_mode: False

cameras:
- id: "dev"
name: "devcam1"
backend: "micromanager"
micromanager_path: "C:/Program Files/Micro-Manager-2.0"


- id: "dev"
name: "devcam2"
backend: "micromanager"
micromanager_path: "C:/Program Files/Micro-Manager-thor"



# - id: "arducam"
# name: "arducam"
# backend: "opencv"
# properties:
# fps: 30
47 changes: 47 additions & 0 deletions hardware.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
memory_buffer_size: 10000
viewer_type: "static"

encoder:
type: "wheel"
port: "COM4"
baudrate: 57600
cpr: 2400
diameter_mm: 80
sample_interval_ms: 20
development_mode: False

cameras:
- id: "Dhyana"
name: "mesoscope"
backend: "micromanager"
micromanager_path: "C:/Program Files/Micro-Manager-2.0"
configuration_path: "C:/Program Files/Micro-Manager-2.0/mm-sipefield.cfg"
properties:
Dhyana:
Output Trigger Port: 2
Gain: "HDR"
fps: 49 # IMPORTANT: This is validated externally and is a value used merely to calculate experiment duration and frames to capture
Arduino-Shutter:
OnOff: "1"
Arduino-Switch:
Sequence: "On"
Core:
Shutter: "Arduino-Shutter"

- id: "ThorCam"
name: "pupil"
backend: "micromanager"
micromanager_path: "C:/Program Files/Micro-Manager-thor"
configuration_path: "C:/Program Files/Micro-Manager-2.0/ThorCam.cfg"
properties:
ThorCam:
Exposure: 20
fps: 30 # IMPORTANT: This is validated externally and is a value used merely to calculate experiment duration and frames to capture
ROI: [440, 305, 509, 509]


# - id: "arducam"
# name: "arducam"
# backend: "opencv"
# properties:
# fps: 30
127 changes: 63 additions & 64 deletions mesofield/__main__.py
Original file line number Diff line number Diff line change
@@ -1,84 +1,83 @@
"""Entry point for mesofield."""
"""CLI Interface entry point for mesofield python package"""

import os
# os.environ['NUMEXPR_MAX_THREADS'] = '4'
# os.environ['NUMEXPR_NUM_THREADS'] = '2'
# import numexpr as ne
import logging
import argparse

import click
from PyQt6.QtWidgets import QApplication

from mesofield.gui.maingui import MainWindow
from mesofield.config import ExperimentConfig
from mesofield.startup import Startup
'''
This is the client terminal command line interface
The client terminal commands are:
launch: Launch the mesofield acquisition interface
- dev: Set to True to launch in development mode with simulated MMCores
test_mda: Test the mesofield acquisition interface
'''


@click.group()
def cli():
"""mesofields Command Line Interface"""
pass

@cli.command()
@click.option('--dev', default=False, help='launch in development mode with simulated MMCores.')
@click.option('--params', default='params.json', help='Path to the config JSON file.')
def launch(dev, params):
""" Launch mesofield acquisition interface.
This function initializes and launches the mesofield acquisition application.
It sets up the necessary hardware and configuration based on
the provided parameters.
Parameters:
`dev (str)`: The device identifier to be used for the acquisition.
`params (str)`: The path to the configuration file. Default is the params.json file in the current directory.
"""


# Disable pymmcore-plus logger
package_logger = logging.getLogger('pymmcore-plus')

# Set the logging level to CRITICAL to suppress lower-level logs
package_logger.setLevel(logging.CRITICAL)

# Disable debugger warning about the use of frozen modules
os.environ["PYDEVD_DISABLE_FILE_VALIDATION"] = "1"



def launch(params):
"""Launch the mesofield acquisition interface."""
print('Launching mesofield acquisition interface...')
app = QApplication([])
config_path = params
config = ExperimentConfig(config_path, dev)
config.hardware.initialize_cores(config)
config = ExperimentConfig(params)
config.hardware.configure_engines(config)
print(config.hardware.cameras[0])
mesofield = MainWindow(config)
mesofield.show()
app.exec_()
app.exec()

@cli.command()
def controller():
"""Launch the mesofield controller."""
from mesofield.controller import Controller
from mesofield.gui.controller import Controller
app = QApplication([])
controller = Controller()
controller.show()
app.exec_()
c = Controller()
c.show()
app.exec()

@cli.command()
@click.option('--frames', default=100, help='Number of frames for the MDA test.')
def test_mda(frames):
"""
Run a test of the mesofield Multi-Dimensional Acquisition (MDA)
"""
"""Run a test of the mesofield Multi-Dimensional Acquisition (MDA)."""
from mesofield.startup import test_mda

@cli.command()
def run_mda():
def run_mda_command():
"""Run the Multi-Dimensional Acquisition (MDA) without the GUI."""
run_mda()


if __name__ == "__main__": # pragma: no cover
cli()




def main():
parser = argparse.ArgumentParser(description="mesofields Command Line Interface")
subparsers = parser.add_subparsers(dest='command', help='Available subcommands')

# Subcommand: launch
parser_launch = subparsers.add_parser('launch', help='Launch the mesofield acquisition interface')
parser_launch.add_argument('--params', default='dev.yaml',
help='Path to the config file')

# Subcommand: controller
parser_controller = subparsers.add_parser('controller', help='Launch the mesofield controller')

# Subcommand: test_mda
parser_test_mda = subparsers.add_parser('test_mda', help='Run a test MDA')
parser_test_mda.add_argument('--frames', type=int, default=100,
help='Number of frames for the MDA test')

# Subcommand: run_mda
subparsers.add_parser('run_mda', help='Run MDA without the GUI')

args = parser.parse_args()

if args.command == 'launch':
launch(args.params)
elif args.command == 'controller':
controller()
elif args.command == 'test_mda':
test_mda(args.frames)
elif args.command == 'run_mda':
run_mda_command()
else:
parser.print_help()

if __name__ == "__main__":
main()
Loading

0 comments on commit ca9b156

Please sign in to comment.