From c68ef5510e45fa4bab172eec57b1f98bc29d6085 Mon Sep 17 00:00:00 2001 From: Gary Yendell Date: Wed, 26 Jul 2023 16:41:55 +0100 Subject: [PATCH] Add container runtime and developer environment Publish runtime container Update devcontainer to build and run C++ applictions Create full local eiger deployment Add development quickstart guide to README Add verbose build Add launch configs Update tickit-devices url --- .devcontainer/devcontainer.json | 51 ++++++----- .devcontainer/initializeCommand | 6 ++ .devcontainer/postCreateCommand | 28 ++++++ .dockerignore | 10 +++ .github/CONTRIBUTING.md | 4 +- .github/workflows/container.yml | 92 ++++++++++++++++++++ .vscode/extensions.json | 9 ++ .vscode/launch.json | 93 ++++++++++++++++++++ .vscode/settings.json | 21 +++++ Dockerfile | 58 ++++++------ README.md | 47 ++++++++-- deploy/eiger.yaml | 3 + deploy/fp1.json | 150 ++++++++++++++++++++++++++++++++ deploy/fp2.json | 150 ++++++++++++++++++++++++++++++++ deploy/fp3.json | 150 ++++++++++++++++++++++++++++++++ deploy/fp4.json | 150 ++++++++++++++++++++++++++++++++ deploy/fr1.json | 18 ++++ deploy/fr2.json | 18 ++++ deploy/fr3.json | 18 ++++ deploy/fr4.json | 18 ++++ deploy/layout.kdl | 32 +++++++ deploy/log4cxx.xml | 46 ++++++++++ deploy/odin_server.cfg | 29 ++++++ deploy/stEigerFan.sh | 5 ++ deploy/stFrameProcessor1.sh | 7 ++ deploy/stFrameProcessor2.sh | 7 ++ deploy/stFrameProcessor3.sh | 7 ++ deploy/stFrameProcessor4.sh | 7 ++ deploy/stFrameReceiver1.sh | 5 ++ deploy/stFrameReceiver2.sh | 5 ++ deploy/stFrameReceiver3.sh | 5 ++ deploy/stFrameReceiver4.sh | 5 ++ deploy/stMetaWriter.sh | 3 + deploy/stOdinServer.sh | 8 ++ python/setup.cfg | 2 + 35 files changed, 1210 insertions(+), 57 deletions(-) create mode 100644 .devcontainer/initializeCommand create mode 100644 .devcontainer/postCreateCommand create mode 100644 .dockerignore create mode 100644 .github/workflows/container.yml create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 deploy/eiger.yaml create mode 100644 deploy/fp1.json create mode 100644 deploy/fp2.json create mode 100644 deploy/fp3.json create mode 100644 deploy/fp4.json create mode 100644 deploy/fr1.json create mode 100644 deploy/fr2.json create mode 100644 deploy/fr3.json create mode 100644 deploy/fr4.json create mode 100644 deploy/layout.kdl create mode 100644 deploy/log4cxx.xml create mode 100644 deploy/odin_server.cfg create mode 100755 deploy/stEigerFan.sh create mode 100755 deploy/stFrameProcessor1.sh create mode 100755 deploy/stFrameProcessor2.sh create mode 100755 deploy/stFrameProcessor3.sh create mode 100755 deploy/stFrameProcessor4.sh create mode 100755 deploy/stFrameReceiver1.sh create mode 100755 deploy/stFrameReceiver2.sh create mode 100755 deploy/stFrameReceiver3.sh create mode 100755 deploy/stFrameReceiver4.sh create mode 100755 deploy/stMetaWriter.sh create mode 100755 deploy/stOdinServer.sh diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index f609365..f7e3c25 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,46 +1,55 @@ // For format details, see https://containers.dev/implementors/json_reference/ { - "name": "Python 3 Developer Container", + "name": "eiger-detector devcontainer", "build": { "dockerfile": "../Dockerfile", + "context": "..", "target": "developer" }, - "remoteEnv": { - // Allow X11 apps to run inside the container - "DISPLAY": "${localEnv:DISPLAY}" + "features": { + // add quality of life features for developers including git config integration + // note this is slow for the odin-data container - leaving out for now + "ghcr.io/devcontainers/features/common-utils:2": { + // don't upgrade to make this similar to the runtime container + "upgradePackages": false + } }, + // IMPORTANT for this devcontainer to work with docker VSCODE_REMOTE_USER must be + // set to vscode. You will run as vscode with full sudo rights. + // For podman it should be left blank. You will run as root but host mounts + // will be owned by your user. + "remoteUser": "${localEnv:VSCODE_REMOTE_USER}", "customizations": { "vscode": { - // Set *default* container specific settings.json values on container create. - "settings": { - "python.defaultInterpreterPath": "/venv/bin/python" - }, // Add the IDs of extensions you want installed when the container is created. "extensions": [ - "ms-python.python", - "github.vscode-github-actions", + "ms-python.vscode-pylance", "tamasfe.even-better-toml", "redhat.vscode-yaml", "ryanluker.vscode-coverage-gutters", + "epicsdeb.vscode-epics", "charliermarsh.ruff", - "ms-azuretools.vscode-docker" + "ms-vscode.cmake-tools", + "ms-vscode.cpptools" ] } }, - "features": { - // Some default things like git config - "ghcr.io/devcontainers/features/common-utils:2": { - "upgradePackages": false - } - }, + // You can place any outside of the container before-launch commands here + "initializeCommand": "bash .devcontainer/initializeCommand ${devcontainerId}", + // One time global setup commands inside the container + "postCreateCommand": "bash .devcontainer/postCreateCommand ${devcontainerId}", "runArgs": [ // Allow the container to access the host X11 display and EPICS CA "--net=host", - // Make sure SELinux does not disable with access to host filesystems like tmp + // Make sure SELinux does not disable write access to host filesystems like tmp "--security-opt=label=disable" ], - // Mount the parent as /workspaces so we can pip install peers as editable + // Mount the parent of the project folder so we can access peer projects "workspaceMount": "source=${localWorkspaceFolder}/..,target=/workspaces,type=bind", - // After the container is created, install the python project in editable form - "postCreateCommand": "pip install $([ -f dev-requirements.txt ] && echo '-c dev-requirements.txt') -e './python[dev]' && pre-commit install" + // mount in other useful files from the host + "mounts": [ + // add extra mounts below + // "source=${localWorkspaceFolder},target=/odin-data,type=bind" + "source=/dev/shm,target=/dev/shm,type=bind" + ] } diff --git a/.devcontainer/initializeCommand b/.devcontainer/initializeCommand new file mode 100644 index 0000000..732ec1f --- /dev/null +++ b/.devcontainer/initializeCommand @@ -0,0 +1,6 @@ +#!/bin/bash + +# custom initialization goes here - runs outside of the dev container +# just before the container is launched but after the container is created + +echo "devcontainerID ${1}" diff --git a/.devcontainer/postCreateCommand b/.devcontainer/postCreateCommand new file mode 100644 index 0000000..156a8f5 --- /dev/null +++ b/.devcontainer/postCreateCommand @@ -0,0 +1,28 @@ +#!/bin/bash + +# Custom initialization goes here if needed. +# Runs inside the dev container after the container is created + +################################################################################ +# When using docker we will not be root inside the container +# You may wish to change ownership of files you want the user to modify +################################################################################ + +# if [[ $USER != "root" ]] ; then +# # make sure the non-root user can build iocs and (mounted in) support modules +# # sudo chown -R ${USER}:${USER} add_folders_here_if needed +# fi + +################################################################################ +# Shell customizations for Generic IOC devcontainers +################################################################################ + +# pick a zsh theme that does not cause completion corruption in zsh vscode terminals +sed -i $HOME/.zshrc -e 's/ZSH_THEME="devcontainers"/ZSH_THEME="dst"/' + +# allow personalization of all devcontainers in this subdirectory +# by placing a .devcontainer_rc file in the workspace root +if [[ -f /workspaces/.devcontainer_rc ]] ; then + source /workspaces/.devcontainer_rc +fi + diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ca4c4fa --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +.dockerignore + +external +*build* +*prefix* +*.pyc +venv* +*.egg-info + +docs/build/ diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 85930ff..4be4eec 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,14 +1,14 @@ # Contribute to the project Contributions and issues are most welcome! All issues and pull requests are -handled through [GitHub](https://github.com/DiamondLightSource/odin-fastcs/issues). Also, please check for any existing issues before +handled through [GitHub](https://github.com/DiamondLightSource/eiger-detector/issues). Also, please check for any existing issues before filing a new one. If you have a great idea but it involves big changes, please file a ticket before making a pull request! We want to make sure you don't spend your time coding something that might not fit the scope of the project. ## Issue or Discussion? -Github also offers [discussions](https://github.com/DiamondLightSource/odin-fastcs/discussions) as a place to ask questions and share ideas. If +Github also offers [discussions](https://github.com/DiamondLightSource/eiger-detector/discussions) as a place to ask questions and share ideas. If your issue is open ended and it is not obvious when it can be "closed", please raise it as a discussion instead. diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml new file mode 100644 index 0000000..dbda3f0 --- /dev/null +++ b/.github/workflows/container.yml @@ -0,0 +1,92 @@ +name: Container CI + +on: + push: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 # All history + + - name: Cache Docker layers + uses: actions/cache@v2 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- + + - name: Log in to GitHub Docker Registry + if: github.event_name != 'pull_request' + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v1 + + - name: Build image + uses: docker/build-push-action@v4 + with: + context: . + file: Dockerfile + target: runtime + push: false + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache + + - name: Create tags for developer image + id: meta-developer + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }}-developer + tags: | + type=ref,event=tag + type=raw,value=latest + + - name: Push developer image + if: ${{ github.event_name == 'push' && github.ref_type == 'tag' }} + uses: docker/build-push-action@v4 + with: + context: . + file: Dockerfile + target: developer + tags: ${{ steps.meta-developer.outputs.tags }} + labels: ${{ steps.meta-developer.outputs.labels }} + push: ${{ github.event_name != 'pull_request' }} + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache + + - name: Create tags for runtime image + id: meta-runtime + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }}-runtime + tags: | + type=ref,event=tag + type=raw,value=latest + + - name: Push runtime image + if: ${{ github.event_name == 'push' && github.ref_type == 'tag' }} + uses: docker/build-push-action@v4 + with: + context: . + file: Dockerfile + target: runtime + tags: ${{ steps.meta-runtime.outputs.tags }} + labels: ${{ steps.meta-runtime.outputs.labels }} + push: ${{ github.event_name != 'pull_request' }} + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..7aa2c45 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + "recommendations": [ + "ms-vscode-remote.remote-containers", + "ms-vscode.cmake-tools", + "ms-vscode.cpptools", + "ms-python.python", + "ms-python.vscode-pylance", + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..e0c32e8 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,93 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Odin Control", + "type": "debugpy", + "request": "launch", + "module": "odin.main", + "justMyCode": false, + "console": "integratedTerminal", + "args": ["--config", "${workspaceFolder}/deploy/odin_server.cfg", "--logging", "info"] + }, + { + "name": "Meta Writer", + "type": "debugpy", + "request": "launch", + "module": "odin_data.meta_writer.meta_writer_app", + "justMyCode": false, + "console": "integratedTerminal", + "args": [ + "--writer", "eiger_detector.EigerMetaWriter", + "--sensor-shape", "4362", "4148", + "--data-endpoints", "tcp://127.0.0.1:10008,tcp://127.0.0.1:10018,tcp://127.0.0.1:10028,tcp://127.0.0.1:10038" + ] + }, + { + "name": "Debug Unit Test", + "type": "debugpy", + "request": "launch", + "justMyCode": false, + "program": "${file}", + "purpose": [ + "debug-test" + ], + "console": "integratedTerminal", + "env": { + // Enable break on exception when debugging tests (see: tests/conftest.py) + "PYTEST_RAISE": "1", + }, + }, + { + "name": "Eiger Fan", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/vscode_build/bin/eigerfan", + "args": ["--addr", "127.0.0.1", "--consumers", "4", "--sockets", "4", "--blocksize", "1000", "--threads", "2"], + "stopAtEntry": false, + "cwd": "${fileDirname}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Set Disassembly Flavor to Intel", + "text": "-gdb-set disassembly-flavor intel", + "ignoreFailures": true + } + ] + }, + { + "name": "FrameProcessor", + "type": "cppdbg", + "request": "launch", + "program": "/odin/bin/frameProcessor", + "args": ["--ctrl", "tcp://0.0.0.0:10004", "--config", "${workspaceFolder}/deploy/fp1.json"], + "stopAtEntry": false, + "cwd": "${fileDirname}", + "environment": [{"name": "HDF5_PLUGIN_PATH", "value": "/odin/h5plugin"}], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Set Disassembly Flavor to Intel", + "text": "-gdb-set disassembly-flavor intel", + "ignoreFailures": true + } + ] + }, + ], +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ad786fc --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,21 @@ +{ + "cmake.generator": "Unix Makefiles", + "cmake.sourceDirectory": "${workspaceFolder}/cpp", + "cmake.buildDirectory": "${workspaceFolder}/vscode_build", + "cmake.installPrefix": "/odin", + "cmake.configureArgs": [ + "-DODINDATA_ROOT_DIR=/odin" + ], + "cmake.buildArgs": ["VERBOSE=1"], + "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools", + "editor.formatOnSave": true, + "[python]": { + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit" + }, + "editor.defaultFormatter": "charliermarsh.ruff", + "editor.rulers": [ + 88 + ] + }, +} diff --git a/Dockerfile b/Dockerfile index 6309e7c..9206a08 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,27 +1,31 @@ -# The devcontainer should use the developer target and run as root with podman -# or docker with user namespaces. -ARG PYTHON_VERSION=3.11 -FROM python:${PYTHON_VERSION} as developer - -# Add any system dependencies for the developer/build environment here -RUN apt-get update && apt-get install -y --no-install-recommends \ - graphviz \ - && rm -rf /var/lib/apt/lists/* - -# Set up a virtual environment and put it in PATH -RUN python -m venv /venv -ENV PATH=/venv/bin:$PATH - -# The build stage installs the context into the venv -FROM developer as build -COPY . /context -WORKDIR /context -RUN pip install ./python - -# The runtime stage copies the built venv into a slim runtime container -FROM python:${PYTHON_VERSION}-slim as runtime -# Add apt-get system dependecies for runtime here if needed -COPY --from=build /venv/ /venv/ -ENV PATH=/venv/bin:$PATH - -ENTRYPOINT ["bash"] +FROM ghcr.io/odin-detector/odin-data-build:1.10.1-fastcs-dev3 AS developer + +FROM developer AS build + +# Root of eiger-detector +COPY . /odin/eiger-detector + +# C++ +WORKDIR /odin/eiger-detector +RUN mkdir -p build && cd build && \ + cmake -DCMAKE_INSTALL_PREFIX=/odin -DODINDATA_ROOT_DIR=/odin ../cpp && \ + make -j8 VERBOSE=1 && \ + make install + +# Python +WORKDIR /odin/eiger-detector/python +RUN python -m pip install .[sim] + +FROM ghcr.io/odin-detector/odin-data-runtime:1.10.1-fastcs-dev3 AS runtime + +COPY --from=build /odin /odin +COPY --from=build /venv /venv +COPY deploy /odin/eiger-deploy + +RUN rm -rf /odin/eiger-detector + +ENV PATH=/odin/bin:/odin/venv/bin:$PATH + +WORKDIR /odin + +CMD ["sh", "-c", "cd /odin/eiger-deploy && zellij --layout ./layout.kdl"] diff --git a/README.md b/README.md index 228b377..1b33ea5 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,46 @@ -eiger-detector -========= +# eiger-detector -Data Acquisition from the Eiger detector. +Data acquisition framework for the Eiger detector consisting of: -eigerfan: a fan-out of the Eiger zeromq push/pull stream. +- eigerfan: a fan-out of the Eiger zeromq push/pull stream +- EigerMetaWriter: A plugin for the odin-data meta_writer application +- EigerProcessPlugin: A plugin for the odin-data FrameProcessor +- EigerFrameDecoder: A plugin for the odin-data FrameReceiver -metalistener: A python application that listens for odin-data meta messages and writes data to a meta file +# Development -EigerProcessPlugin: Plugin for the odin-data FrameProcessor +A devcontainer is provided for simpler local development. To get started: -EigerFrameDecoder: Plugin for the odin-data FrameReceiver +1. Open the project in VSCode and re-open in devcontainer when prompted, or + open manually with `Dev Containers: Reopen in Container` +2. Install the recommended extensions for the workspace + (`> Extensions: Show Recommended Extensions`) +3. Build eiger-detector + i. `> CMake: Delete Cache and Reconfigure` (select gcc version in dropdown) + + ii. `> CMake: Install` + +4. Install the eiger-detector python package with dev dependencies and tickit simulator + + ii. `$ pip install -e './python[dev,sim]'` + +5. Run the dev deployment from the `deploy` directory with `$ zellij -l layout.kdl` + +It is then possible to edit the python applications and restart, or edit the C++ +applications, rebuild and restart. + +To run the tickit simulation, add `tickit-devices` to the workspace, pip install, and +run the `Eiger` launch config. + +To run the IOC, add fastcs-eiger to the workspace, pip install and run the `Eiger IOC` +launch config, which talks to the tickit sim by default. The generated `output.bob` can +then be opened in Phoebus for GUI control. + +Currently in development is fastcs-odin, which creates an EPICS IOC to control the odin +processes. To run this, add fastcs-odin to the workspace, pip install, and then run the +`Odin IOC` launch config, which by default talks to a control server at 127.0.0.1:8888. + +To debug any of the applications in the full deployment, stop that process and run the +launch config to run an equivalent process in the debugger. For example the Odin Control +launch config uses the same config file as the instance in the full deployment. \ No newline at end of file diff --git a/deploy/eiger.yaml b/deploy/eiger.yaml new file mode 100644 index 0000000..9a406f5 --- /dev/null +++ b/deploy/eiger.yaml @@ -0,0 +1,3 @@ +- type: tickit_devices.eiger.Eiger + inputs: {} + name: eiger diff --git a/deploy/fp1.json b/deploy/fp1.json new file mode 100644 index 0000000..9c0ea1a --- /dev/null +++ b/deploy/fp1.json @@ -0,0 +1,150 @@ +[ + { + "fr_setup": { + "fr_ready_cnxn": "tcp://127.0.0.1:10001", + "fr_release_cnxn": "tcp://127.0.0.1:10002" + }, + "meta_endpoint": "tcp://*:10008" + }, + { + "plugin": { + "load": { + "index": "eiger", + "name": "EigerProcessPlugin", + "library": "/odin/lib/libEigerProcessPlugin.so" + } + } + }, + { + "plugin": { + "load": { + "index": "offset", + "name": "OffsetAdjustmentPlugin", + "library": "/odin/lib/libOffsetAdjustmentPlugin.so" + } + } + }, + { + "plugin": { + "load": { + "index": "param", + "name": "ParameterAdjustmentPlugin", + "library": "/odin/lib/libParameterAdjustmentPlugin.so" + } + } + }, + { + "plugin": { + "load": { + "index": "hdf", + "name": "FileWriterPlugin", + "library": "/odin/lib/libHdf5Plugin.so" + } + } + }, + { + "plugin": { + "connect": { + "index": "eiger", + "connection": "frame_receiver" + } + } + }, + { + "plugin": { + "connect": { + "index": "offset", + "connection": "eiger" + } + } + }, + { + "plugin": { + "connect": { + "index": "param", + "connection": "offset" + } + } + }, + { + "plugin": { + "connect": { + "index": "hdf", + "connection": "param" + } + } + }, + { + "hdf": { + "dataset": { + "compressed_size": { + "datatype": "uint32", + "chunks": [1000] + } + } + } + }, + { + "hdf": { + "dataset": { + "uid": { + "datatype": "uint64", + "chunks": [1000] + } + } + } + }, + { + "param": { + "parameter": { + "uid": { + "adjustment": 1 + } + } + } + }, + { + "hdf": { + "process": { + "number": 4, + "rank": 0 + } + } + }, + { + "hdf": { + "file": { + "flush_error_duration": 10000, + "write_error_duration": 10000, + "close_error_duration": 10000, + "create_error_duration": 10000 + } + } + }, + { + "hdf": { + "file": { + "first_number": 1 + } + } + }, + { + "hdf": { + "dataset": { + "data": { + "indexes": true + } + } + } + }, + { + "hdf": { + "dataset": { + "data": { + "dims": [4362, 4148], + "chunks": [1, 4362, 4148] + } + } + } + } +] diff --git a/deploy/fp2.json b/deploy/fp2.json new file mode 100644 index 0000000..a10518b --- /dev/null +++ b/deploy/fp2.json @@ -0,0 +1,150 @@ +[ + { + "fr_setup": { + "fr_ready_cnxn": "tcp://127.0.0.1:10011", + "fr_release_cnxn": "tcp://127.0.0.1:10012" + }, + "meta_endpoint": "tcp://*:10018" + }, + { + "plugin": { + "load": { + "index": "eiger", + "name": "EigerProcessPlugin", + "library": "/odin/lib/libEigerProcessPlugin.so" + } + } + }, + { + "plugin": { + "load": { + "index": "offset", + "name": "OffsetAdjustmentPlugin", + "library": "/odin/lib/libOffsetAdjustmentPlugin.so" + } + } + }, + { + "plugin": { + "load": { + "index": "param", + "name": "ParameterAdjustmentPlugin", + "library": "/odin/lib/libParameterAdjustmentPlugin.so" + } + } + }, + { + "plugin": { + "load": { + "index": "hdf", + "name": "FileWriterPlugin", + "library": "/odin/lib/libHdf5Plugin.so" + } + } + }, + { + "plugin": { + "connect": { + "index": "eiger", + "connection": "frame_receiver" + } + } + }, + { + "plugin": { + "connect": { + "index": "offset", + "connection": "eiger" + } + } + }, + { + "plugin": { + "connect": { + "index": "param", + "connection": "offset" + } + } + }, + { + "plugin": { + "connect": { + "index": "hdf", + "connection": "param" + } + } + }, + { + "hdf": { + "dataset": { + "compressed_size": { + "datatype": "uint32", + "chunks": [1000] + } + } + } + }, + { + "hdf": { + "dataset": { + "uid": { + "datatype": "uint64", + "chunks": [1000] + } + } + } + }, + { + "param": { + "parameter": { + "uid": { + "adjustment": 1 + } + } + } + }, + { + "hdf": { + "process": { + "number": 4, + "rank": 1 + } + } + }, + { + "hdf": { + "file": { + "flush_error_duration": 10000, + "write_error_duration": 10000, + "close_error_duration": 10000, + "create_error_duration": 10000 + } + } + }, + { + "hdf": { + "file": { + "first_number": 1 + } + } + }, + { + "hdf": { + "dataset": { + "data": { + "indexes": true + } + } + } + }, + { + "hdf": { + "dataset": { + "data": { + "dims": [4362, 4148], + "chunks": [1, 4362, 4148] + } + } + } + } +] diff --git a/deploy/fp3.json b/deploy/fp3.json new file mode 100644 index 0000000..4702e43 --- /dev/null +++ b/deploy/fp3.json @@ -0,0 +1,150 @@ +[ + { + "fr_setup": { + "fr_ready_cnxn": "tcp://127.0.0.1:10021", + "fr_release_cnxn": "tcp://127.0.0.1:10022" + }, + "meta_endpoint": "tcp://*:10028" + }, + { + "plugin": { + "load": { + "index": "eiger", + "name": "EigerProcessPlugin", + "library": "/odin/lib/libEigerProcessPlugin.so" + } + } + }, + { + "plugin": { + "load": { + "index": "offset", + "name": "OffsetAdjustmentPlugin", + "library": "/odin/lib/libOffsetAdjustmentPlugin.so" + } + } + }, + { + "plugin": { + "load": { + "index": "param", + "name": "ParameterAdjustmentPlugin", + "library": "/odin/lib/libParameterAdjustmentPlugin.so" + } + } + }, + { + "plugin": { + "load": { + "index": "hdf", + "name": "FileWriterPlugin", + "library": "/odin/lib/libHdf5Plugin.so" + } + } + }, + { + "plugin": { + "connect": { + "index": "eiger", + "connection": "frame_receiver" + } + } + }, + { + "plugin": { + "connect": { + "index": "offset", + "connection": "eiger" + } + } + }, + { + "plugin": { + "connect": { + "index": "param", + "connection": "offset" + } + } + }, + { + "plugin": { + "connect": { + "index": "hdf", + "connection": "param" + } + } + }, + { + "hdf": { + "dataset": { + "compressed_size": { + "datatype": "uint32", + "chunks": [1000] + } + } + } + }, + { + "hdf": { + "dataset": { + "uid": { + "datatype": "uint64", + "chunks": [1000] + } + } + } + }, + { + "param": { + "parameter": { + "uid": { + "adjustment": 1 + } + } + } + }, + { + "hdf": { + "process": { + "number": 4, + "rank": 2 + } + } + }, + { + "hdf": { + "file": { + "flush_error_duration": 10000, + "write_error_duration": 10000, + "close_error_duration": 10000, + "create_error_duration": 10000 + } + } + }, + { + "hdf": { + "file": { + "first_number": 1 + } + } + }, + { + "hdf": { + "dataset": { + "data": { + "indexes": true + } + } + } + }, + { + "hdf": { + "dataset": { + "data": { + "dims": [4362, 4148], + "chunks": [1, 4362, 4148] + } + } + } + } +] diff --git a/deploy/fp4.json b/deploy/fp4.json new file mode 100644 index 0000000..9893f5c --- /dev/null +++ b/deploy/fp4.json @@ -0,0 +1,150 @@ +[ + { + "fr_setup": { + "fr_ready_cnxn": "tcp://127.0.0.1:10031", + "fr_release_cnxn": "tcp://127.0.0.1:10032" + }, + "meta_endpoint": "tcp://*:10038" + }, + { + "plugin": { + "load": { + "index": "eiger", + "name": "EigerProcessPlugin", + "library": "/odin/lib/libEigerProcessPlugin.so" + } + } + }, + { + "plugin": { + "load": { + "index": "offset", + "name": "OffsetAdjustmentPlugin", + "library": "/odin/lib/libOffsetAdjustmentPlugin.so" + } + } + }, + { + "plugin": { + "load": { + "index": "param", + "name": "ParameterAdjustmentPlugin", + "library": "/odin/lib/libParameterAdjustmentPlugin.so" + } + } + }, + { + "plugin": { + "load": { + "index": "hdf", + "name": "FileWriterPlugin", + "library": "/odin/lib/libHdf5Plugin.so" + } + } + }, + { + "plugin": { + "connect": { + "index": "eiger", + "connection": "frame_receiver" + } + } + }, + { + "plugin": { + "connect": { + "index": "offset", + "connection": "eiger" + } + } + }, + { + "plugin": { + "connect": { + "index": "param", + "connection": "offset" + } + } + }, + { + "plugin": { + "connect": { + "index": "hdf", + "connection": "param" + } + } + }, + { + "hdf": { + "dataset": { + "compressed_size": { + "datatype": "uint32", + "chunks": [1000] + } + } + } + }, + { + "hdf": { + "dataset": { + "uid": { + "datatype": "uint64", + "chunks": [1000] + } + } + } + }, + { + "param": { + "parameter": { + "uid": { + "adjustment": 1 + } + } + } + }, + { + "hdf": { + "process": { + "number": 4, + "rank": 3 + } + } + }, + { + "hdf": { + "file": { + "flush_error_duration": 10000, + "write_error_duration": 10000, + "close_error_duration": 10000, + "create_error_duration": 10000 + } + } + }, + { + "hdf": { + "file": { + "first_number": 1 + } + } + }, + { + "hdf": { + "dataset": { + "data": { + "indexes": true + } + } + } + }, + { + "hdf": { + "dataset": { + "data": { + "dims": [4362, 4148], + "chunks": [1, 4362, 4148] + } + } + } + } +] diff --git a/deploy/fr1.json b/deploy/fr1.json new file mode 100644 index 0000000..ad34568 --- /dev/null +++ b/deploy/fr1.json @@ -0,0 +1,18 @@ +[ + { + "decoder_type": "Eiger", + "decoder_path": "/odin/lib", + "rx_type": "zmq", + "rx_address": "127.0.0.1", + "rx_ports": "31600,", + "shared_buffer_name": "odin_buf_1", + "max_buffer_mem": 160000000, + "frame_ready_endpoint": "tcp://127.0.0.1:10001", + "frame_release_endpoint": "tcp://127.0.0.1:10002", + "decoder_config": { + "enable_packet_logging": false, + "frame_timeout_ms": 1000, + "detector_model": "16M" + } + } +] \ No newline at end of file diff --git a/deploy/fr2.json b/deploy/fr2.json new file mode 100644 index 0000000..f9465ee --- /dev/null +++ b/deploy/fr2.json @@ -0,0 +1,18 @@ +[ + { + "decoder_type": "Eiger", + "decoder_path": "/odin/lib", + "rx_type": "zmq", + "rx_address": "127.0.0.1", + "rx_ports": "31601,", + "shared_buffer_name": "odin_buf_2", + "max_buffer_mem": 160000000, + "frame_ready_endpoint": "tcp://127.0.0.1:10011", + "frame_release_endpoint": "tcp://127.0.0.1:10012", + "decoder_config": { + "enable_packet_logging": false, + "frame_timeout_ms": 1000, + "detector_model": "16M" + } + } +] \ No newline at end of file diff --git a/deploy/fr3.json b/deploy/fr3.json new file mode 100644 index 0000000..9ca4edc --- /dev/null +++ b/deploy/fr3.json @@ -0,0 +1,18 @@ +[ + { + "decoder_type": "Eiger", + "decoder_path": "/odin/lib", + "rx_type": "zmq", + "rx_address": "127.0.0.1", + "rx_ports": "31602,", + "shared_buffer_name": "odin_buf_3", + "max_buffer_mem": 160000000, + "frame_ready_endpoint": "tcp://127.0.0.1:10021", + "frame_release_endpoint": "tcp://127.0.0.1:10022", + "decoder_config": { + "enable_packet_logging": false, + "frame_timeout_ms": 1000, + "detector_model": "16M" + } + } +] \ No newline at end of file diff --git a/deploy/fr4.json b/deploy/fr4.json new file mode 100644 index 0000000..7daee99 --- /dev/null +++ b/deploy/fr4.json @@ -0,0 +1,18 @@ +[ + { + "decoder_type": "Eiger", + "decoder_path": "/odin/lib", + "rx_type": "zmq", + "rx_address": "127.0.0.1", + "rx_ports": "31603,", + "shared_buffer_name": "odin_buf_4", + "max_buffer_mem": 160000000, + "frame_ready_endpoint": "tcp://127.0.0.1:10031", + "frame_release_endpoint": "tcp://127.0.0.1:10032", + "decoder_config": { + "enable_packet_logging": false, + "frame_timeout_ms": 1000, + "detector_model": "16M" + } + } +] \ No newline at end of file diff --git a/deploy/layout.kdl b/deploy/layout.kdl new file mode 100644 index 0000000..2ba4ed7 --- /dev/null +++ b/deploy/layout.kdl @@ -0,0 +1,32 @@ +layout { + pane size=1 borderless=true { + plugin location="zellij:tab-bar" + } + pane split_direction="vertical" { + pane split_direction="horizontal" { + pane command="./stFrameReceiver1.sh" + pane command="./stFrameProcessor1.sh" + pane command="./stFrameReceiver2.sh" + pane command="./stFrameProcessor2.sh" + pane command="./stFrameReceiver3.sh" + pane command="./stFrameProcessor3.sh" + pane command="./stFrameReceiver4.sh" + pane command="./stFrameProcessor4.sh" + } + pane split_direction="horizontal" { + pane command="./stEigerFan.sh" + pane command="./stMetaWriter.sh" + pane command="bash" { + args "-c" "sleep 3; ./stOdinServer.sh" + } + pane command="tickit" { + args "all" "./eiger.yaml" + } + } + } + pane size=2 borderless=true { + plugin location="zellij:status-bar" + } +} +session_name "EIGER" +attach_to_session true diff --git a/deploy/log4cxx.xml b/deploy/log4cxx.xml new file mode 100644 index 0000000..42e726b --- /dev/null +++ b/deploy/log4cxx.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/deploy/odin_server.cfg b/deploy/odin_server.cfg new file mode 100644 index 0000000..3dbb72f --- /dev/null +++ b/deploy/odin_server.cfg @@ -0,0 +1,29 @@ +[server] +debug_mode = 0 +http_port = 8888 +http_addr = 0.0.0.0 +adapters = fp, fr, mw, ef + +[tornado] +logging = error + +[adapter.fp] +module = odin_data.control.odin_data_adapter.OdinDataAdapter +frame_processor = true +endpoints = 127.0.0.1:10004, 127.0.0.1:10014, 127.0.0.1:10024, 127.0.0.1:10034 +update_interval = 0.2 + +[adapter.fr] +module = odin_data.control.frame_receiver_adapter.FrameReceiverAdapter +endpoints = 127.0.0.1:10000, 127.0.0.1:10010, 127.0.0.1:10020, 127.0.0.1:10030 +update_interval = 0.2 + +[adapter.mw] +module = odin_data.control.meta_listener_adapter.MetaListenerAdapter +endpoints = 127.0.0.1:5659 +update_interval = 0.5 + +[adapter.ef] +module = eiger_detector.control.eiger_fan_adapter.EigerFanAdapter +endpoints = 127.0.0.1:5559 +update_interval = 0.5 diff --git a/deploy/stEigerFan.sh b/deploy/stEigerFan.sh new file mode 100755 index 0000000..4ee9a41 --- /dev/null +++ b/deploy/stEigerFan.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" + +/odin/bin/eigerfan -s 127.0.0.1 -n 4 -z 4 -b 1000 -t 2 --logconfig $SCRIPT_DIR/log4cxx.xml diff --git a/deploy/stFrameProcessor1.sh b/deploy/stFrameProcessor1.sh new file mode 100755 index 0000000..7ff892f --- /dev/null +++ b/deploy/stFrameProcessor1.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" + +export HDF5_PLUGIN_PATH=/odin/h5plugin + +/odin/bin/frameProcessor --ctrl=tcp://0.0.0.0:10004 --config=$SCRIPT_DIR/fp1.json --log-config $SCRIPT_DIR/log4cxx.xml diff --git a/deploy/stFrameProcessor2.sh b/deploy/stFrameProcessor2.sh new file mode 100755 index 0000000..f66f5ba --- /dev/null +++ b/deploy/stFrameProcessor2.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" + +export HDF5_PLUGIN_PATH=/odin/h5plugin + +/odin/bin/frameProcessor --ctrl=tcp://0.0.0.0:10014 --config=$SCRIPT_DIR/fp2.json --log-config $SCRIPT_DIR/log4cxx.xml diff --git a/deploy/stFrameProcessor3.sh b/deploy/stFrameProcessor3.sh new file mode 100755 index 0000000..dc3d75f --- /dev/null +++ b/deploy/stFrameProcessor3.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" + +export HDF5_PLUGIN_PATH=/odin/h5plugin + +/odin/bin/frameProcessor --ctrl=tcp://0.0.0.0:10024 --config=$SCRIPT_DIR/fp3.json --log-config $SCRIPT_DIR/log4cxx.xml diff --git a/deploy/stFrameProcessor4.sh b/deploy/stFrameProcessor4.sh new file mode 100755 index 0000000..2144537 --- /dev/null +++ b/deploy/stFrameProcessor4.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" + +export HDF5_PLUGIN_PATH=/odin/h5plugin + +/odin/bin/frameProcessor --ctrl=tcp://0.0.0.0:10034 --config=$SCRIPT_DIR/fp4.json --log-config $SCRIPT_DIR/log4cxx.xml diff --git a/deploy/stFrameReceiver1.sh b/deploy/stFrameReceiver1.sh new file mode 100755 index 0000000..f1fc003 --- /dev/null +++ b/deploy/stFrameReceiver1.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" + +/odin/bin/frameReceiver --io-threads 2 --ctrl=tcp://0.0.0.0:10000 --config=$SCRIPT_DIR/fr1.json --log-config $SCRIPT_DIR/log4cxx.xml diff --git a/deploy/stFrameReceiver2.sh b/deploy/stFrameReceiver2.sh new file mode 100755 index 0000000..ff06ffd --- /dev/null +++ b/deploy/stFrameReceiver2.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" + +/odin/bin/frameReceiver --io-threads 2 --ctrl=tcp://0.0.0.0:10010 --config=$SCRIPT_DIR/fr2.json --log-config $SCRIPT_DIR/log4cxx.xml diff --git a/deploy/stFrameReceiver3.sh b/deploy/stFrameReceiver3.sh new file mode 100755 index 0000000..8f4971e --- /dev/null +++ b/deploy/stFrameReceiver3.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" + +/odin/bin/frameReceiver --io-threads 2 --ctrl=tcp://0.0.0.0:10020 --config=$SCRIPT_DIR/fr3.json --log-config $SCRIPT_DIR/log4cxx.xml diff --git a/deploy/stFrameReceiver4.sh b/deploy/stFrameReceiver4.sh new file mode 100755 index 0000000..0aedc90 --- /dev/null +++ b/deploy/stFrameReceiver4.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" + +/odin/bin/frameReceiver --io-threads 2 --ctrl=tcp://0.0.0.0:10030 --config=$SCRIPT_DIR/fr4.json --log-config $SCRIPT_DIR/log4cxx.xml diff --git a/deploy/stMetaWriter.sh b/deploy/stMetaWriter.sh new file mode 100755 index 0000000..5f7d462 --- /dev/null +++ b/deploy/stMetaWriter.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +/venv/bin/eiger_meta_writer -w eiger_detector.EigerMetaWriter --sensor-shape 4362 4148 --data-endpoints tcp://127.0.0.1:10008,tcp://127.0.0.1:10018,tcp://127.0.0.1:10028,tcp://127.0.0.1:10038 diff --git a/deploy/stOdinServer.sh b/deploy/stOdinServer.sh new file mode 100755 index 0000000..8572800 --- /dev/null +++ b/deploy/stOdinServer.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" + +# Increase maximum fds available for ZeroMQ sockets +ulimit -n 2048 + +/venv/bin/eiger_control --config=$SCRIPT_DIR/odin_server.cfg --logging=info --access_logging=ERROR diff --git a/python/setup.cfg b/python/setup.cfg index 66fec9d..2395ac3 100644 --- a/python/setup.cfg +++ b/python/setup.cfg @@ -50,6 +50,8 @@ dev = requests typer pyzmq +sim = + tickit-devices @ git+https://github.com/DiamondLightSource/tickit-devices@eiger-stream2 [options.entry_points] # Include a command line script