Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/compile-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,4 @@ jobs:

- name: Compile mmCoreAndDevices and ScopeOne
shell: bash
run: ./scripts/build-linux.sh
run: ./scripts/build-unix.sh
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ config/*

build/**
ref/**

**/.DS_Store
64 changes: 52 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ As an open-source project, ScopeOne builds on existing community efforts to redu
Download the latest release package from the [Releases](https://github.com/Experimental-Microscopy-Lab/ScopeOne/releases) page and extract it. Run `ScopeOne.exe` to start the application.

**System Requirements:**

- Windows 10/11 (64-bit)
- Micro-Manager device adapters for your hardware

Expand All @@ -38,6 +39,7 @@ There is an example dual-camera .cfg file in the config folder, just change the
### For Developers

**Prerequisites:**

- [CMake](https://cmake.org/download/) 4.1.0
- [Visual Studio 2022](https://visualstudio.microsoft.com/vs/) (MSVC v143 toolset)
- [Qt](https://www.qt.io/development/download-qt-installer-oss) 6.9.1 (msvc2022_64)
Expand All @@ -63,37 +65,53 @@ ScopeOne/
**Windows Build Steps:**

1. Build and install `ScopeOneCore`:

```powershell
cmake -S ScopeOneCore -B ScopeOneCore/build
cmake --build ScopeOneCore/build --config Release --parallel
cmake --install ScopeOneCore/build --config Release
```

2. Build the GUI application:

```powershell
cmake -S . -B build
cmake --build build --config Release --parallel
```

3. Run:

```powershell
.\build\Release\ScopeOne.exe
```

**Linux Build Steps (experimental):**
**Linux and macOS Build Steps (experimental):**

Linux and macOS use the same native build flow. Use the top-level `micro-manager` repository to configure the native build, then compile `MMDevice`, `MMCore`, and the required device adapters. Create a symlink so ScopeOne can find the `mmCoreAndDevices` tree at the path expected by the current CMake files.

On Linux, use the top-level `micro-manager` repository to configure the native build, then compile only `MMDevice` and `MMCore`. Create a symlink so ScopeOne can find the `mmCoreAndDevices` tree at the path expected by the current CMake files.
Run `./scripts/build-unix.sh` from the ScopeOne repository root on Linux or macOS to automate the complete sequence below.

Run `./scripts/build-linux.sh` from the ScopeOne repository root to automate the complete sequence below.
1. Install common build dependencies.

Linux:

1. Install common build dependencies:
```bash
sudo apt install \
git subversion build-essential cmake autoconf automake libtool autoconf-archive \
pkg-config libboost-all-dev qt6-base-dev libopencv-dev libtiff-dev zlib1g-dev
```

macOS:

```bash
xcode-select --install
brew install \
git subversion cmake autoconf automake libtool autoconf-archive \
pkg-config boost qt opencv libtiff zlib
```

2. Clone Micro-Manager and create the `mmCoreAndDevices` symlink:

```bash
cd /path/to/ScopeOne/ScopeOneCore
mkdir -p external
Expand All @@ -107,43 +125,62 @@ git submodule update --init --recursive
```

3. Configure Micro-Manager without the Java application layer:

```bash
./autogen.sh
./configure --without-java --enable-static
```

4. Build the native core components:

```bash
make -C mmCoreAndDevices/MMDevice -j"$(nproc)"
make -C mmCoreAndDevices/MMCore -j"$(nproc)"
# Adjust `-j4` to match your CPU cores
make -C mmCoreAndDevices/MMDevice -j4
make -C mmCoreAndDevices/MMCore -j4
```

Device adapters are runtime plugins and are not required for this compile verification. Build the required adapters separately in their own directories when running ScopeOne with hardware or a demo configuration. ScopeOne currently links Linux MMCore from:
5. Build the specific device adapters you need. The DemoCamera adapter is included for testing and demonstration purposes. You can build additional adapters as needed.

```text
ScopeOneCore/external/mmCoreAndDevices/MMCore/.libs/libMMCore.a
```bash
make -C mmCoreAndDevices/DeviceAdapters/DemoCamera -j4
```

5. Build and install `ScopeOneCore`:
6. Build and install `ScopeOneCore`:

```bash
cd /path/to/ScopeOne
cmake -S ScopeOneCore -B ScopeOneCore/build -DCMAKE_BUILD_TYPE=Release
cmake --build ScopeOneCore/build --parallel
cmake --install ScopeOneCore/build
```

6. Build the GUI application:
7. Build the GUI application:

```bash
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel
```

The Linux executable is expected at:
The Linux or macOS executable is expected at:

```text
build/ScopeOne
```

To run `config/MMConfig_demo.cfg`, copy the DemoCamera runtime adapter next to the ScopeOne executable.

Linux:

```bash
cp -L ScopeOneCore/external/mmCoreAndDevices/DeviceAdapters/DemoCamera/.libs/libmmgr_dal_DemoCamera.so.0 build/
```

macOS uses an extensionless Mach-O bundle rather than the static `.a` file:

```bash
cp ScopeOneCore/external/mmCoreAndDevices/DeviceAdapters/DemoCamera/.libs/libmmgr_dal_DemoCamera build/
```

## 🤖 Automation and AI Agents

The desktop app exposes a language-neutral local control API and shared-memory frame channel. An AI agent does not run inside ScopeOne or depend on Python. A tool adapter can discover supported operation groups with the `capabilities` request, read a structured observation with `state_snapshot`, and invoke the exposed camera, stage, mosaic, processing, image analysis, experiment, recording, layer, and markup operations. Requests may carry an ID that is echoed by the app for correlation.
Expand Down Expand Up @@ -180,15 +217,18 @@ Use `scopeone` as the server name, `stdio` as the transport, the absolute path t
The MCP tool set mirrors the Local API operation catalog, including system state, configuration, preview layers, automatic display levels, source alignment, markups, device properties, exposure, ROI, stages, stage mosaics, processing, experiments, recording sessions, frame transfer, and analysis. Agents can read the current frame of any image layer, monitor live acquisition and writer progress, and optionally export or display particle masks. ScopeOne remains the authority for parameter validation and hardware read-back, and MCP tool calls are visible in the desktop UI through the same application state used by manual controls.

## 🔬 Tested Devices

- Yokogawa CSU X1
- Hamamatsu C13440
- Andor 897D

The current validation list is still short, but the codebase has been cleaned to remove early hard-coded device assumptions. In principle, ScopeOne should follow Micro-Manager device compatibility.

## 🖥️ Tested System Configurations

- Windows 10 Version 21H2, Dual Intel(R) Xeon(R) E5-2637 v3, 64 GB RAM, NVIDIA Quadro K620
- Windows 11 Version 25H2, Intel(R) Core(TM) Ultra 5 125U, 64 GB RAM
- Fedora Linux 44 (Workstation Edition), Intel(R) Core(TM) i7-7700, 32 GB RAM
- macOS 26.5.2, Apple M1 Pro, 16 GB RAM

We build and test ScopeOne on the above machines, which are comparatively older and weaker than many typical optical lab computers. However, ScopeOne still provides smooth real-time preview and processing on them.
41 changes: 28 additions & 13 deletions scripts/build-linux.sh → scripts/build-unix.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,26 @@ EXTERNAL_DIR="$CORE_DIR/external"
MM_REPO_DIR="$EXTERNAL_DIR/micro-manager"
MMCORE_LINK="$EXTERNAL_DIR/mmCoreAndDevices"
BUILD_TYPE="${BUILD_TYPE:-Release}"
JOBS="${JOBS:-}"

if [[ "$(uname -s)" != Linux* ]]; then
echo "This script is intended for Linux builds." >&2
exit 1
fi
case "$(uname -s)" in
Linux*)
PLATFORM_NAME="Linux"
DEMO_ADAPTER_NAME="libmmgr_dal_DemoCamera.so.0"
DEFAULT_JOBS="$(nproc)"
;;
Darwin*)
PLATFORM_NAME="macOS"
DEMO_ADAPTER_NAME="libmmgr_dal_DemoCamera"
DEFAULT_JOBS="$(sysctl -n hw.logicalcpu)"
;;
*)
echo "This script supports only Linux and macOS." >&2
exit 1
;;
esac

if [[ -z "$JOBS" ]]; then
if command -v nproc >/dev/null 2>&1; then
JOBS="$(nproc)"
else
JOBS="1"
fi
fi
JOBS="${JOBS:-$DEFAULT_JOBS}"
DEMO_ADAPTER="$MMCORE_LINK/DeviceAdapters/DemoCamera/.libs/$DEMO_ADAPTER_NAME"

step() {
printf '\n==> %s\n' "$1"
Expand All @@ -44,7 +50,7 @@ for command_name in git cmake make; do
require_command "$command_name"
done

step "Preparing Micro-Manager checkout"
step "Preparing Micro-Manager checkout for $PLATFORM_NAME"
run mkdir -p "$EXTERNAL_DIR"

if [[ -d "$MM_REPO_DIR/.git" ]]; then
Expand All @@ -70,6 +76,7 @@ step "Building required Micro-Manager components"
run ./configure --without-java --enable-static
run make -C "$MMCORE_LINK/MMDevice" -j "$JOBS"
run make -C "$MMCORE_LINK/MMCore" -j "$JOBS"
run make -C "$MMCORE_LINK/DeviceAdapters/DemoCamera" -j "$JOBS"
)

step "Building and installing ScopeOneCore"
Expand All @@ -81,5 +88,13 @@ step "Building ScopeOne GUI"
run cmake -S "$ROOT_DIR" -B "$ROOT_DIR/build" -DCMAKE_BUILD_TYPE="$BUILD_TYPE"
run cmake --build "$ROOT_DIR/build" --parallel "$JOBS"

step "Copying DemoCamera adapter"
if [[ ! -f "$DEMO_ADAPTER" ]]; then
echo "DemoCamera adapter was not found: $DEMO_ADAPTER" >&2
exit 1
fi
run cp -L "$DEMO_ADAPTER" "$ROOT_DIR/build/"

step "Done"
echo "GUI executable: $ROOT_DIR/build/ScopeOne"
echo "Demo configuration: $ROOT_DIR/config/MMConfig_demo.cfg"
5 changes: 4 additions & 1 deletion src/ConsoleWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <QComboBox>
#include <QCoreApplication>
#include <QFont>
#include <QFontDatabase>
#include <QLabel>
#include <QMutex>
#include <QMutexLocker>
Expand Down Expand Up @@ -123,7 +124,9 @@ namespace scopeone::ui

m_consoleTextEdit = new QTextEdit(this);
m_consoleTextEdit->setReadOnly(true);
m_consoleTextEdit->setFont(QFont("Consolas", 9));
QFont consoleFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
consoleFont.setPointSize(9);
m_consoleTextEdit->setFont(consoleFont);
m_consoleTextEdit->setStyleSheet(
"QTextEdit {"
" background-color: #1e1e1e;"
Expand Down
8 changes: 0 additions & 8 deletions src/PreviewWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

#include "scopeone/ImageSceneModel.h"
#include "scopeone/ScopeOneCore.h"
#include <QSurfaceFormat>
#include <QPainter>
#include <QMouseEvent>
#include <QKeyEvent>
Expand Down Expand Up @@ -178,13 +177,6 @@ namespace scopeone::ui
update();
});

QSurfaceFormat requestedFormat;
requestedFormat.setVersion(4, 6);
requestedFormat.setProfile(QSurfaceFormat::CoreProfile);
requestedFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
requestedFormat.setDepthBufferSize(0);
setFormat(requestedFormat);

setMinimumSize(256, 256);
setMouseTracking(true);
setFocusPolicy(Qt::StrongFocus);
Expand Down
12 changes: 10 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
#include <QApplication>
#include <QIcon>
#include <QSurfaceFormat>
#include <memory>
#include "AppVersion.h"
#include "scopeone/ScopeOneCore.h"
#include "ConsoleWidget.h"
#include "MainWindow.h"

// Create the shared core before the main window
int main(int argc, char* argv[])
int main(int argc, char *argv[])
{
QSurfaceFormat format;
// macOS supports OpenGL only up to 4.1, and ScopeOne currently uses no features introduced after 4.1
format.setVersion(4, 1);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
format.setDepthBufferSize(0);
QSurfaceFormat::setDefaultFormat(format);

QApplication app(argc, argv);
QCoreApplication::setApplicationName(QStringLiteral(SCOPEONE_APP_NAME));
QCoreApplication::setApplicationVersion(QStringLiteral(SCOPEONE_APP_VERSION_STRING));
Expand Down
Loading