diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 007d463..a452a7e 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -8,6 +8,13 @@ "bonsai.sgen" ], "rollForward": false + }, + "docfx": { + "version": "2.78.3", + "commands": [ + "docfx" + ], + "rollForward": false } } } \ No newline at end of file diff --git a/.editorconfig b/.editorconfig index 40a3202..0595f32 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,42 +1,37 @@ -# To learn more about .editorconfig see https://aka.ms/editorconfigdocs -############################### -# Core EditorConfig Options # -############################### root = true -# All files [*] indent_style = space -# XML project files -[*.{csproj,vcxproj,vcxproj.filters,props,targets,ruleset,proj,projitems,shproj,wixproj,slnx}] +#-------------------------------------------------------------------------------------------------- +# XML, JSON, and web files +#-------------------------------------------------------------------------------------------------- +[*.{xml,csproj,vcxproj,vcxproj.filters,shproj,props,targets,config,nuspec,resx,vsixmanifest,wxs,vstemplate,slnx}] indent_size = 2 -# XML files -[*.{xml,bonsai,config,nuspec,resx,vsct,wxs}] +[*.json] indent_size = 2 -# JSON/YAML files -[*.{json,yaml,yml}] -indent_size = 2 - -# Web files [*.{html,css}] indent_size = 2 -# Code files -[*.{c,cpp,cs,csx,h,hpp,ixx}] +#-------------------------------------------------------------------------------------------------- +# C++ +#-------------------------------------------------------------------------------------------------- +[*.{c,cpp,h,hpp,ixx}] indent_size = 4 charset = utf-8-bom trim_trailing_whitespace = true insert_final_newline = true -############################### -# .NET Coding Conventions # -############################### -[*.{cs}] -# Organize usings -dotnet_sort_system_directives_first = true +#-------------------------------------------------------------------------------------------------- +# C# +#-------------------------------------------------------------------------------------------------- +[*.{cs,csx}] +indent_size = 4 +charset = utf-8-bom +trim_trailing_whitespace = true +insert_final_newline = true # Language keyword vs full type name # Do not create a message because explicitly sized types can be convenient in interop where bit size matters diff --git a/.gitattributes b/.gitattributes index 14da18d..601a4e2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8,6 +8,7 @@ # Config *.gitignore text *.gitattributes text +*.gitmodules text eol=lf *.editorconfig text *.git-blame-ignore-revs text *.sln text @@ -15,24 +16,21 @@ *.props text *.targets text *.csproj text -*.vcxproj text *.wixproj text *.config text *.json text *.xml text -*.yaml text *.yml text # Code *.manifest text +*.vsixmanifest text +*.vstemplate text *.resx text *.cs text *.bonsai text *.wxs text -# Designer files -*.Designer.cs text linguist-generated=false - # Documents LICENSE text *.md text diff=markdown @@ -42,4 +40,4 @@ LICENSE text *.png binary *.ico binary *.gif binary -*.svg text \ No newline at end of file +*.svg text diff --git a/.github/workflows/UclOpen.Acquisition.yml b/.github/workflows/UclOpen.Acquisition.yml new file mode 100644 index 0000000..80c5305 --- /dev/null +++ b/.github/workflows/UclOpen.Acquisition.yml @@ -0,0 +1,348 @@ +# ======================================================================================================================================================================= +# UclOpen.Acquisition CI/CD +# ======================================================================================================================================================================= +# Index: +# * Build, test, and package .NET +# * Build documentation +# * Render workflow images +# * Publish packages to GitHub +# * Publish packages to NuGet.org +# * Publish documentation +# ======================================================================================================================================================================= +# Note that this is a generic workflow meant for all Bonsai packages. Minor local modifications are fine, see https://github.com/bonsai-rx/prefect for more information. +# ======================================================================================================================================================================= +name: UclOpen.Acquisition +on: + push: + # This prevents tag pushes from triggering this workflow + branches: ['**'] + pull_request: + release: + types: [published] + workflow_dispatch: + inputs: + publish-documentation: + description: "Publish documentation to GitHub Pages?" + default: "false" +env: + DOTNET_NOLOGO: true + DOTNET_CLI_TELEMETRY_OPTOUT: true + DOTNET_GENERATE_ASPNET_CERTIFICATE: false + ContinuousIntegrationBuild: true +jobs: + # ===================================================================================================================================================================== + # Build, test, and package .NET + # ___ _ _ _ _ _ _ _ _ _ ___ _____ + # | _ )_ _(_) |__| | | |_ ___ __| |_ __ _ _ _ __| | _ __ __ _ __| |____ _ __ _ ___ | \| | __|_ _| + # | _ \ || | | / _` |_ | _/ -_|_-< _|_ / _` | ' \/ _` | | '_ \/ _` / _| / / _` / _` / -_) _| .` | _| | | + # |___/\_,_|_|_\__,_( ) \__\___/__/\__( ) \__,_|_||_\__,_| | .__/\__,_\__|_\_\__,_\__, \___| (_)_|\_|___| |_| + # |/ |/ |_| |___/ + # ===================================================================================================================================================================== + build: + strategy: + fail-fast: false + matrix: + platform: + - name: Windows x64 + os: windows-latest + rid: win-x64 + - name: Linux x64 + os: ubuntu-22.04 + rid: linux-x64 + configuration: ['debug', 'release'] + include: + - platform: + rid: win-x64 + configuration: release + collect-packages: true + name: ${{matrix.platform.name}} ${{matrix.configuration}} + runs-on: ${{matrix.platform.os}} + outputs: + need-workflow-image-render: ${{steps.configure-build.outputs.need-workflow-image-render}} + steps: + # ----------------------------------------------------------------------- Checkout + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + # ----------------------------------------------------------------------- Set up tools + - name: Set up .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.x + + # ----------------------------------------------------------------------- Configure build + - name: Configure build + id: configure-build + uses: bonsai-rx/configure-build@v1 + + # ----------------------------------------------------------------------- Build + - name: Restore + run: dotnet restore + + - name: Build + run: dotnet build --no-restore --configuration ${{matrix.configuration}} + + # ----------------------------------------------------------------------- Pack + - name: Pack + id: pack + run: dotnet pack --no-restore --no-build --configuration ${{matrix.configuration}} + + # ----------------------------------------------------------------------- Test + - name: Test .NET Framework 4.7.2 + run: dotnet test --no-restore --no-build --configuration ${{matrix.configuration}} --verbosity normal --framework net472 + - name: Test .NET 8 + run: dotnet test --no-restore --no-build --configuration ${{matrix.configuration}} --verbosity normal --framework net8.0 + - name: Test .NET 8 Windows + if: matrix.platform.rid == 'win-x64' + run: dotnet test --no-restore --no-build --configuration ${{matrix.configuration}} --verbosity normal --framework net8.0-windows + + # ----------------------------------------------------------------------- Collect artifacts + - name: Collect NuGet packages + uses: actions/upload-artifact@v4 + if: matrix.collect-packages && steps.pack.outcome == 'success' && always() + with: + name: Packages + if-no-files-found: error + path: artifacts/package/${{matrix.configuration}}/** + + # ===================================================================================================================================================================== + # Build documentation + # ___ _ _ _ _ _ _ _ + # | _ )_ _(_) |__| | __| |___ __ _ _ _ __ ___ _ _| |_ __ _| |_(_)___ _ _ + # | _ \ || | | / _` | / _` / _ \/ _| || | ' \/ -_) ' \ _/ _` | _| / _ \ ' \ + # |___/\_,_|_|_\__,_| \__,_\___/\__|\_,_|_|_|_\___|_||_\__\__,_|\__|_\___/_||_| + # ===================================================================================================================================================================== + build-documentation: + name: Build documentation + runs-on: ubuntu-latest + steps: + # ----------------------------------------------------------------------- Checkout + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + # ----------------------------------------------------------------------- Set up tools + - name: Set up .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.x + + - name: Set up .NET tools + run: dotnet tool restore + + # ----------------------------------------------------------------------- Restore + - name: Restore + run: dotnet restore + + # ----------------------------------------------------------------------- Build metadata + - name: Build metadata + id: build-metadata + run: dotnet docfx metadata docs/docfx.json --noRestore + + # ----------------------------------------------------------------------- Build documentation + - name: Build documentation + id: build-documentation + run: dotnet docfx build docs/docfx.json + + # ----------------------------------------------------------------------- Collect artifacts + - name: Collect documentation metadata + uses: actions/upload-artifact@v4 + if: steps.build-metadata.outcome == 'success' && always() + with: + name: DocumentationMetadata + if-no-files-found: error + path: artifacts/docs/api/ + + - name: Collect documentation artifact + uses: actions/upload-artifact@v4 + if: steps.build-documentation.outcome == 'success' && always() + with: + name: DocumentationWebsite + if-no-files-found: error + path: artifacts/docs/site/ + + # ===================================================================================================================================================================== + # Render workflow images + # ___ _ _ __ _ _ + # | _ \___ _ _ __| |___ _ _ __ __ _____ _ _| |__/ _| |_____ __ __ (_)_ __ __ _ __ _ ___ ___ + # | / -_) ' \/ _` / -_) '_| \ V V / _ \ '_| / / _| / _ \ V V / | | ' \/ _` / _` / -_|_-< + # |_|_\___|_||_\__,_\___|_| \_/\_/\___/_| |_\_\_| |_\___/\_/\_/ |_|_|_|_\__,_\__, \___/__/ + # |___/ + # ===================================================================================================================================================================== + workflow-images: + name: Render workflow images + runs-on: windows-latest + needs: build + if: needs.build.outputs.need-workflow-image-render == 'true' + steps: + # ----------------------------------------------------------------------- Checkout + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + # ----------------------------------------------------------------------- Download built packages + - name: Download packages for rendering + uses: actions/download-artifact@v4 + with: + name: Packages + path: artifacts/packages/ + + # ----------------------------------------------------------------------- Set up Bonsai environments + - name: Set up Bonsai environments + uses: bonsai-rx/setup-bonsai@v1 + with: + environment-paths: '**/.bonsai/' + inject-packages: artifacts/packages/*.nupkg + + # ----------------------------------------------------------------------- Render + - name: Render images + id: render + run: pwsh ./docs/export-images.ps1 -OutputFolder artifacts/docs/site/ -Verbose + + # ----------------------------------------------------------------------- Collect artifacts + - name: Collect images + uses: actions/upload-artifact@v4 + if: steps.render.outcome == 'success' && always() + with: + name: DocumentationWorkflowImages + if-no-files-found: error + path: artifacts/docs/site/ + + # ===================================================================================================================================================================== + # Publish packages to GitHub + # ___ _ _ _ _ _ _ ___ _ _ _ _ _ + # | _ \_ _| |__| (_)__| |_ _ __ __ _ __| |____ _ __ _ ___ ___ | |_ ___ / __(_) |_| || |_ _| |__ + # | _/ || | '_ \ | (_-< ' \ | '_ \/ _` / _| / / _` / _` / -_|_-< | _/ _ \ | (_ | | _| __ | || | '_ \ + # |_| \_,_|_.__/_|_/__/_||_| | .__/\__,_\__|_\_\__,_\__, \___/__/ \__\___/ \___|_|\__|_||_|\_,_|_.__/ + # |_| |___/ + # ===================================================================================================================================================================== + publish-github: + name: Publish packages to GitHub + runs-on: ubuntu-latest + needs: build + permissions: + # Needed to attach files to releases + contents: write + # Needed to upload to GitHub Packages + packages: write + if: github.event_name == 'push' || github.event_name == 'release' + steps: + # ----------------------------------------------------------------------- Set up .NET + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.x + + # ----------------------------------------------------------------------- Download built packages + - name: Download built packages + uses: actions/download-artifact@v4 + with: + name: Packages + path: artifacts/packages/ + + # ----------------------------------------------------------------------- Upload release assets + - name: Upload release assets + if: github.event_name == 'release' + run: gh release upload --repo ${{github.repository}} ${{github.event.release.tag_name}} artifacts/packages/* --clobber + env: + GH_TOKEN: ${{github.token}} + + # ----------------------------------------------------------------------- Push to GitHub Packages + - name: Push to GitHub Packages + run: dotnet nuget push "artifacts/packages/*.nupkg" --skip-duplicate --no-symbols --api-key ${{secrets.GITHUB_TOKEN}} --source https://nuget.pkg.github.com/${{github.repository_owner}} + env: + # This is a workaround for https://github.com/NuGet/Home/issues/9775 + DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER: 0 + + # ===================================================================================================================================================================== + # Publish packages to NuGet.org + # ___ _ _ _ _ _ _ _ _ ___ _ + # | _ \_ _| |__| (_)__| |_ _ __ __ _ __| |____ _ __ _ ___ ___ | |_ ___ | \| |_ _ / __|___| |_ ___ _ _ __ _ + # | _/ || | '_ \ | (_-< ' \ | '_ \/ _` / _| / / _` / _` / -_|_-< | _/ _ \ | .` | || | (_ / -_) _|_/ _ \ '_/ _` | + # |_| \_,_|_.__/_|_/__/_||_| | .__/\__,_\__|_\_\__,_\__, \___/__/ \__\___/ |_|\_|\_,_|\___\___|\__(_)___/_| \__, | + # |_| |___/ |___/ + # ===================================================================================================================================================================== + publish-packages-nuget-org: + name: Publish packages to NuGet.org + runs-on: ubuntu-latest + environment: public-release + needs: build + if: github.event_name == 'release' + steps: + # ----------------------------------------------------------------------- Set up .NET + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.x + + # ----------------------------------------------------------------------- Download built packages + - name: Download built packages + uses: actions/download-artifact@v4 + with: + name: Packages + path: artifacts/packages/ + + # ----------------------------------------------------------------------- Push to NuGet.org + - name: Push to NuGet.org + run: dotnet nuget push "artifacts/packages/*.nupkg" --api-key ${{secrets.NUGET_API_KEY}} --source ${{vars.NUGET_API_URL}} + env: + # This is a workaround for https://github.com/NuGet/Home/issues/9775 + DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER: 0 + + + # ===================================================================================================================================================================== + # Publish documentation + # ___ _ _ _ _ _ _ _ _ + # | _ \_ _| |__| (_)__| |_ __| |___ __ _ _ _ __ ___ _ _| |_ __ _| |_(_)___ _ _ + # | _/ || | '_ \ | (_-< ' \ / _` / _ \/ _| || | ' \/ -_) ' \ _/ _` | _| / _ \ ' \ + # |_| \_,_|_.__/_|_/__/_||_| \__,_\___/\__|\_,_|_|_|_\___|_||_\__\__,_|\__|_\___/_||_| + # ===================================================================================================================================================================== + publish-documentation: + name: Publish documentation + runs-on: ubuntu-latest + # Publishing is not strictly necessary here, but if we're going to do a public release we want to wait to publish the docs until it goes out + needs: [build-documentation, workflow-images, publish-packages-nuget-org] + permissions: + # Both required by actions/deploy-pages + pages: write + id-token: write + environment: + # Intentionally not using the "default" github-pages environment as it's not compatible with this workflow + name: documentation-website + url: ${{steps.publish.outputs.page_url}} + # Only run if the workflow isn't dying and build-documentation was successful and either A) we're releasing or B) we have continuous deployment enabled + if: | + !cancelled() && !failure() && needs.build-documentation.result == 'success' + && (github.event_name == 'release' + || (github.event_name == 'workflow_dispatch' && github.event.inputs.publish-documentation == 'true') + || (vars.CONTINUOUS_DOCUMENTATION && github.event_name != 'pull_request') + ) + steps: + # ----------------------------------------------------------------------- Download documentation website components + # It is intentional that we use two independent download steps here as it ensures that workflow images are permitted + # to overwrite any conflicts in the docfx output but not the other way around. + - name: Download documentation website + uses: actions/download-artifact@v4 + with: + name: DocumentationWebsite + + - name: Download workflow images + if: ${{needs.workflow-images.result == 'success'}} + uses: actions/download-artifact@v4 + with: + name: DocumentationWorkflowImages + + # ----------------------------------------------------------------------- Collect artifacts + - name: Upload final documentation website artifact + uses: actions/upload-pages-artifact@v3 + with: + path: '.' + + # ----------------------------------------------------------------------- Publish to GitHub Pages + - name: Publish to GitHub Pages + id: publish + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index d858cd8..b075f2a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -.bonsai/Bonsai.exe* -.bonsai/Packages/ -.bonsai/Settings/ .vs/ -artifacts/ \ No newline at end of file +**/.bonsai/Bonsai.exe* +**/.bonsai/Packages/ +**/.bonsai/Settings/ +/artifacts/ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..cad3e2e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "docs/bonsai-docfx"] + path = docs/bonsai-docfx + url = https://github.com/bonsai-rx/docfx-tools diff --git a/Directory.Build.props b/Directory.Build.props index 018a9cf..91586df 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/Directory.Build.targets b/Directory.Build.targets index 22ce16a..b7ac253 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,3 +1,3 @@ - - + + \ No newline at end of file diff --git a/UclOpen.Acquisition.sln b/UclOpen.Acquisition.sln index 7534410..d8cb92e 100644 --- a/UclOpen.Acquisition.sln +++ b/UclOpen.Acquisition.sln @@ -10,6 +10,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UclOpen.Core", "src\UclOpen EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UclOpen.Video", "src\UclOpen.Video\UclOpen.Video.csproj", "{742346D0-82F2-CEF3-C93F-FC2D6BDA7E11}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{DEE5DD87-39C1-BF34-B639-A387DCCF972B}" + ProjectSection(SolutionItems) = preProject + build\Common.csproj.props = build\Common.csproj.props + build\Common.csproj.targets = build\Common.csproj.targets + build\Common.Tests.csproj.props = build\Common.Tests.csproj.props + build\icon.png = build\icon.png + build\Package.props = build\Package.props + build\Project.csproj.props = build\Project.csproj.props + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/build/Common.Tests.csproj.props b/build/Common.Tests.csproj.props new file mode 100644 index 0000000..c42b25f --- /dev/null +++ b/build/Common.Tests.csproj.props @@ -0,0 +1,6 @@ + + + false + false + + \ No newline at end of file diff --git a/build/Common.csproj.props b/build/Common.csproj.props index 991d585..1099119 100644 --- a/build/Common.csproj.props +++ b/build/Common.csproj.props @@ -4,58 +4,77 @@ For everything else, update or create Project.csproj.props --> - + - true - true + Debug + AnyCPU + + + + + 12.0 true - latest strict enable + true + + + true + $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../artifacts')) + + + $(ArtifactsPath)/wsl - + true Dependency;BonsaiLibrary - true - false + + icon.png + $(MSBuildThisFileDirectory)icon.png + + LICENSE + $(MSBuildThisFileDirectory)../LICENSE + + README.md + $(MSBuildThisFileDirectory)../docs/README.md + $(MSBuildThisFileDirectory)README.nuget.md + $(MSBuildProjectDirectory)\README.md + $(MSBuildProjectDirectory)\README.nuget.md + + + false + true snupkg + + false true - + + $(WarningsAsErrors);NU1701;CS7035 + + true true - - $(WarningsAsErrors);NU1701;CS7035 - $(MSBuildThisFileDirectory)../.bonsai/Bonsai.exe - - - false - false - - - - - - - - $(MSBuildThisFileDirectory)$(PackageIcon) - $(MSBuildThisFileDirectory)../$(PackageLicenseFile) - $(MSBuildThisFileDirectory)../$(PackageReadmeFile) - $(MSBuildThisFileDirectory)../docs/$(PackageReadmeFile) - $(ProjectDir)$(PackageReadmeFile) - - + + \ No newline at end of file diff --git a/build/Common.csproj.targets b/build/Common.csproj.targets index de6795e..07f4916 100644 --- a/build/Common.csproj.targets +++ b/build/Common.csproj.targets @@ -1,20 +1,35 @@ - - - + + + + + + $(TargetName.ToLowerInvariant()) + DotnetTool + + + 1591,1573 + + + - + 0 - $(VersionPrefix)-dev$(DevVersion) + 42.42.42-dev$(DevVersion) $(CiBuildVersion) @@ -23,4 +38,9 @@ + + + + + \ No newline at end of file diff --git a/build/Package.props b/build/Package.props index 328544e..a75e8ef 100644 --- a/build/Package.props +++ b/build/Package.props @@ -1,10 +1,9 @@ - - Copyright © - - README.md - - + Bonsai Rx UclOpen + https://ucl-open.github.io/acquisition + + University College London + Copyright © University College London and Contributors \ No newline at end of file diff --git a/build/Version.props b/build/Project.csproj.props similarity index 58% rename from build/Version.props rename to build/Project.csproj.props index 454e3ba..1d004b4 100644 --- a/build/Version.props +++ b/build/Project.csproj.props @@ -1,5 +1,5 @@ - 0.1.0 + annotations \ No newline at end of file diff --git a/build/icon.png b/build/icon.png new file mode 100644 index 0000000..e845695 Binary files /dev/null and b/build/icon.png differ diff --git a/README.md b/docs/README.md similarity index 50% rename from README.md rename to docs/README.md index 531779b..36e5210 100644 --- a/README.md +++ b/docs/README.md @@ -10,22 +10,11 @@ This repository provides a toolkit of Bonsai-based workflows and operators for h - **[ucl-open-rigs](https://github.com/ucl-open/ucl-open-rigs)** – shared, versioned descriptions of experimental rigs - **[rig-template](https://github.com/ucl-open/rig-template)** – the primary entry point for creating new experiment repositories, using Copier -- **acquisition** – Bonsai workflows and operators for hardware control and data collection (this repository) +- **acquisition** – Bonsai workflows and operators for hardware control and data acquisition (this repository) -Most users will not be working and making commits directly to `acquisition`, instead using it as a Bonsai package, published to [Nuget](https://nuget.org) and installed through the Bosnai package manager. Experimental repositories built using the rig-template come with this dependency baked-in. +Each of these repositories is developed in tandem and is dependent on the others. As development is ongoing, published versions of each are intended to be locked to one another; for example, `v0.1.0` of `acquisition` is compatible with `v0.1.0` of `ucl-open-rigs` and `rig-template`. ---- - -## Design principles - -This repository is guided by a small set of design principles: - -- Keep acquisition logic generic and reusable -- Bind workflows to rig contracts, not to specific logic -- Separate hardware description from experimental logic -- Prefer composition of small operators over monolithic workflows - ---- +In general, lab members and experimentalists will not work directly on this repository. Instead, `acquisition` is published as a Bonsai package (via NuGet) and consumed automatically by experiment repositories created using the `rig-template`. ## What this repository is @@ -44,9 +33,41 @@ The repository focuses on *how data is acquired*, not on *what an experiment doe - An experiment repository - A place for task logic or behavioural protocols -- A lab-specific wiring configuration +- A repository of rig or wiring descriptions -Rig-specific details belong in `ucl-open-rigs`; experiment-specific logic belongs in experiment repositories. +Experiment-specific logic belongs in experiment repositories. + +--- + +## Repository structure (conceptual) + +While details may evolve, the repository contains: + +- **Reusable workflows** – common acquisition patterns composed from operators +- **Operators** – low-level abstractions over hardware or data streams +- **Examples** – minimal Bonsai workflows demonstrating intended usage + +The emphasis is on *composition*: complex acquisition behaviour is built from small, reusable operators rather than monolithic workflows. + +--- + +## Using this repository + +In most cases, you will **not interact with this repository directly**. + +The most common usage is **automatic**, via: + +- An experiment repository created from the [rig-template](https://github.com/ucl-open/rig-template) +- The template’s dependency configuration, which pulls in `acquisition` +- Integration with the [ucl-open-rigs](https://github.com/ucl-open/ucl-open-rigs) repository + +Acquisition workflows are added as a dependency, version-pinned by default, and available immediately within Bonsai without manual installation. + +In general, lab members and experimentalists will encounter `acquisition` only indirectly via the template and acquisition stack, rather than by cloning and working with this repository directly. + +You typically work directly with this repository only when adding reusable workflows or operators, extending support for new hardware, or improving shared abstractions. + +If you find yourself copying workflows out of this repository, you are most likely doing something outside the intended framework. --- @@ -60,8 +81,6 @@ In particular: - Device names, channels, and capabilities are resolved via rig definitions - Changes to hardware or wiring are handled by updating the rig, not by editing workflows -This keeps acquisition code portable across rigs that satisfy the same contract. - --- ## How it fits into experiments @@ -70,12 +89,10 @@ Typical usage looks like this: 1. An experiment repository is created from the [rig-template](https://github.com/ucl-open/rig-template) 2. The template pulls in `acquisition` and `ucl-open-rigs`, with versions locked to each other -3. A rig definition is selected or extended -4. Acquisition workflows are configured using ucl-open/acquisition operators on that rig +3. A rig definition is extended from the template +4. Acquisition workflows are built in Bonsai using `acquisition` operators 5. Experiments trigger and coordinate acquisition, but do not reimplement it -Experiments depend on acquisition *behaviour*, not on device-level details. - --- ## Versioning and dependency locking @@ -98,4 +115,4 @@ You typically work directly with this repository only when: - Extending support for new classes of hardware - Improving shared abstractions used across labs -If you find yourself copying workflows into experiment repositories, there is usually something wrong. \ No newline at end of file +If you find yourself copying workflows into experiment repositories, there is usually something wrong. diff --git a/docs/bonsai-docfx b/docs/bonsai-docfx new file mode 160000 index 0000000..d33401b --- /dev/null +++ b/docs/bonsai-docfx @@ -0,0 +1 @@ +Subproject commit d33401b473d647237d88b3eaa73b0dae3fc08ea7 diff --git a/docs/build.ps1 b/docs/build.ps1 new file mode 100644 index 0000000..01ad8f5 --- /dev/null +++ b/docs/build.ps1 @@ -0,0 +1,19 @@ +[CmdletBinding()] param ( + [string[]]$docfxArgs +) +Set-StrictMode -Version 3.0 +$ErrorActionPreference = 'Stop' +$PSNativeCommandUseErrorActionPreference = $true + +Push-Location $PSScriptRoot +try { + $libPaths = @() + $libPaths += Get-ChildItem "..\artifacts\bin\*\release_net4*" -Directory | Select-Object -Expand FullName + $libPaths += "..\artifacts\package\release" + + ./export-images.ps1 $libPaths + dotnet docfx metadata + dotnet docfx build $docfxArgs +} finally { + Pop-Location +} diff --git a/docs/docfx.json b/docs/docfx.json new file mode 100644 index 0000000..219094e --- /dev/null +++ b/docs/docfx.json @@ -0,0 +1,84 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/docfx/main/schemas/docfx.schema.json", + "metadata": [ + { + "src": [ + { + "src": "../src/", + "files": "**/*.csproj", + "exclude": "**/*.Tests.csproj" + } + ], + "output": "../artifacts/docs/api/", + "enumSortOrder": "declaringOrder", + "memberLayout": "separatePages", + "filter": "filter.yml" + } + ], + "build": { + "content": [ + { + "files": [ + "*.md", + "toc.yml", + "{articles,tutorials,examples}/**/*.md", + "{articles,tutorials,examples}/**/toc.yml" + ], + "exclude": "README.md" + }, + { + "src": "../artifacts/docs/api/", + "dest": "api", + "files": "**/*.yml" + } + ], + "resource": [ + { + "files": [ + "images/**", + "workflows/**/*.{bonsai,svg}", + "{articles,tutorials,examples}/**/*.{bonsai,svg}" + ] + }, + { + "src": "../build/", + "files": "icon.png" + } + ], + "overwrite": [ + "apidoc/**/*.md" + ], + "output": "../artifacts/docs/site/", + "template": [ + "default", + "modern", + "bonsai-docfx/template", + "template" + ], + "sitemap": { + "baseUrl": "https://ucl-open.github.io/acquisition" + }, + "globalMetadata": { + "_appName": "UclOpen.Acquisition", + "_appTitle": "UclOpen.Acquisition", + "_appFooter": "© University College London and Contributors. Made with docfx", + "_appLogoPath": "logo.svg", + "_appFaviconPath": "icon.png", + "_enableNewTab": true, + "_enableSearch": true, + "_gitContribute": { + "apiSpecFolder": "docs/apidoc" + } + }, + "markdownEngineProperties": { + "markdigExtensions": [ + "attributes", + "customcontainers" + ] + }, + "xref": [ + "https://bonsai-rx.org/docs/xrefmap.yml", + "https://horizongir.github.io/reactive/xrefmap.yml" + ] + } +} \ No newline at end of file diff --git a/docs/export-images.ps1 b/docs/export-images.ps1 new file mode 100644 index 0000000..e613b87 --- /dev/null +++ b/docs/export-images.ps1 @@ -0,0 +1,44 @@ +[CmdletBinding()] param ( + [string[]]$LibrarySources, + [bool]$UseGalleryForWorkflowsDirectory=$false, + [bool]$UseGalleryForExamplesDirectory=$true, + [string]$OutputFolder=$null +) +Set-StrictMode -Version 3.0 +$ErrorActionPreference = 'Stop' +$PSNativeCommandUseErrorActionPreference = $true + +if ($OutputFolder) { + $OutputFolder = Join-Path (Get-Location) $OutputFolder +} + +function Process-Workflow-Collection([bool]$useGallery, [string]$workflowPath, [string]$environmentPath) { + $libPath = $LibrarySources + + if ($useGallery) { + $libPath = @() + $galleryPath = Join-Path $environmentPath 'Gallery' + $null = New-Item -ItemType Directory -Path $galleryPath -Force + foreach ($librarySource in $LibrarySources) { + Get-ChildItem -Path $librarySource -Filter *.nupkg | Copy-Item -Destination $galleryPath + } + } + + $bootstrapperPath = (Join-Path $environmentPath 'Bonsai.exe') + .\bonsai-docfx\modules\Export-Image.ps1 -libPath $libPath -workflowPath $workflowPath -bootstrapperPath $bootstrapperPath -outputFolder $OutputFolder -documentationRoot $PSScriptRoot +} + +Push-Location $PSScriptRoot +try { + if (Test-Path -Path 'workflows/') { + Process-Workflow-Collection $UseGalleryForWorkflowsDirectory './workflows' '../.bonsai/' + } + + if (Test-Path -Path 'examples/') { + foreach ($environment in (Get-ChildItem -Path 'examples/' -Filter '.bonsai' -Recurse -FollowSymlink -Directory)) { + Process-Workflow-Collection $UseGalleryForExamplesDirectory ($environment.Parent.FullName) ($environment.FullName) + } + } +} finally { + Pop-Location +} diff --git a/docs/filter.yml b/docs/filter.yml new file mode 100644 index 0000000..472eb43 --- /dev/null +++ b/docs/filter.yml @@ -0,0 +1,4 @@ +apiRules: +- exclude: + hasAttribute: + uid: System.ObsoleteAttribute diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..ba991fe --- /dev/null +++ b/docs/index.md @@ -0,0 +1,5 @@ +--- +_layout: landing +--- + +[!INCLUDE [](README.md)] diff --git a/docs/template/public/main.css b/docs/template/public/main.css new file mode 100644 index 0000000..fdb72e4 --- /dev/null +++ b/docs/template/public/main.css @@ -0,0 +1 @@ +@import "bonsai.css"; diff --git a/docs/template/public/main.js b/docs/template/public/main.js new file mode 100644 index 0000000..af7fafa --- /dev/null +++ b/docs/template/public/main.js @@ -0,0 +1,13 @@ +import WorkflowContainer from "./workflow.js" + +export default { + defaultTheme: 'light', + iconLinks: [{ + icon: 'github', + href: 'https://github.com/ucl-open/acquisition', + title: 'GitHub' + }], + start: () => { + WorkflowContainer.init(); + } +} diff --git a/docs/toc.yml b/docs/toc.yml new file mode 100644 index 0000000..3daf8b9 --- /dev/null +++ b/docs/toc.yml @@ -0,0 +1,2 @@ +- name: API + href: ../artifacts/docs/api/ diff --git a/docs/workflows/.gitignore b/docs/workflows/.gitignore new file mode 100644 index 0000000..e2beea4 --- /dev/null +++ b/docs/workflows/.gitignore @@ -0,0 +1,2 @@ +*.layout +*.svg diff --git a/global.json b/global.json index 7da2763..989a69c 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { "version": "8.0.100", - "rollForward": "latestMajor" + "rollForward": "latestMinor" } } \ No newline at end of file diff --git a/src/UclOpen.Core/Properties/launchSettings.json b/src/UclOpen.Core/Properties/launchSettings.json new file mode 100644 index 0000000..4af4f46 --- /dev/null +++ b/src/UclOpen.Core/Properties/launchSettings.json @@ -0,0 +1,10 @@ +{ + "profiles": { + "Bonsai": { + "commandName": "Executable", + "executablePath": "$(BonsaiExecutablePath)", + "commandLineArgs": "--lib:\"$(TargetDir).\"", + "nativeDebugging": true + } + } +} \ No newline at end of file diff --git a/src/UclOpen.Core/UclOpen.Core.csproj b/src/UclOpen.Core/UclOpen.Core.csproj index 0406e6b..21b1ae2 100644 --- a/src/UclOpen.Core/UclOpen.Core.csproj +++ b/src/UclOpen.Core/UclOpen.Core.csproj @@ -2,9 +2,8 @@ A package providing common classes and types for UclOpen experiments. - Bonsai Rx UclOpen Core + $(PackageTags) Core net472 - 0.1.2 diff --git a/src/UclOpen.Devices/SerialDevice.bonsai b/src/UclOpen.Devices/SerialDevice.bonsai index 1b5dd97..7df7f70 100644 --- a/src/UclOpen.Devices/SerialDevice.bonsai +++ b/src/UclOpen.Devices/SerialDevice.bonsai @@ -105,11 +105,14 @@ - + SerialMessages + + + SerialCommands @@ -127,12 +130,13 @@ - + + \ No newline at end of file diff --git a/src/UclOpen.Devices/TriggeredSpinnaker.bonsai b/src/UclOpen.Devices/TriggeredSpinnaker.bonsai index 1f4fdfa..9ae65c8 100644 --- a/src/UclOpen.Devices/TriggeredSpinnaker.bonsai +++ b/src/UclOpen.Devices/TriggeredSpinnaker.bonsai @@ -30,8 +30,10 @@ - - + + + + diff --git a/src/UclOpen.Devices/UclOpen.Devices.csproj b/src/UclOpen.Devices/UclOpen.Devices.csproj index 0694cab..9a132a8 100644 --- a/src/UclOpen.Devices/UclOpen.Devices.csproj +++ b/src/UclOpen.Devices/UclOpen.Devices.csproj @@ -2,9 +2,8 @@ A package providing common hardware and control functionality for all UCL Open experiments. - Bonsai Rx UclOpen Devices + $(PackageTags) Devices net472 - 0.1.2 diff --git a/src/UclOpen.Logging/UclOpen.Logging.csproj b/src/UclOpen.Logging/UclOpen.Logging.csproj index d498c75..7a69277 100644 --- a/src/UclOpen.Logging/UclOpen.Logging.csproj +++ b/src/UclOpen.Logging/UclOpen.Logging.csproj @@ -2,9 +2,8 @@ UclOpen Logging Bonsai library. - Bonsai Rx UclOpen Logging + $(PackageTags) Logging net472 - 0.1.2 diff --git a/src/UclOpen.Video/Properties/launchSettings.json b/src/UclOpen.Video/Properties/launchSettings.json new file mode 100644 index 0000000..4af4f46 --- /dev/null +++ b/src/UclOpen.Video/Properties/launchSettings.json @@ -0,0 +1,10 @@ +{ + "profiles": { + "Bonsai": { + "commandName": "Executable", + "executablePath": "$(BonsaiExecutablePath)", + "commandLineArgs": "--lib:\"$(TargetDir).\"", + "nativeDebugging": true + } + } +} \ No newline at end of file diff --git a/src/UclOpen.Video/UclOpen.Video.csproj b/src/UclOpen.Video/UclOpen.Video.csproj index f47d3c5..c87ac9f 100644 --- a/src/UclOpen.Video/UclOpen.Video.csproj +++ b/src/UclOpen.Video/UclOpen.Video.csproj @@ -2,9 +2,8 @@ A package providing common video acquisition functionality for all UCL Open experiments. - Bonsai Rx UclOpen Video + $(PackageTags) Video net472 - 0.1.2