feat(examples): add first-level GLM analysis (single animal, multi-run) #1551
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Docs | |
| on: | |
| push: | |
| branches: [main] | |
| tags: ["v*"] | |
| pull_request: | |
| branches: [main] | |
| workflow_dispatch: | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v8.1.0 | |
| with: | |
| python-version: "3.14" | |
| - name: Install dependencies | |
| run: uv sync --frozen --all-extras | |
| - name: Install system dependencies for napari screenshots | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| xvfb \ | |
| libegl1 \ | |
| libgl1 \ | |
| libglu1-mesa \ | |
| libx11-xcb1 \ | |
| libxkbcommon-x11-0 \ | |
| libxcb-cursor0 \ | |
| libxcb-icccm4 \ | |
| libxcb-image0 \ | |
| libxcb-keysyms1 \ | |
| libxcb-randr0 \ | |
| libxcb-render-util0 \ | |
| libxcb-shape0 \ | |
| libxcb-shm0 \ | |
| libxcb-sync1 \ | |
| libxcb-xfixes0 \ | |
| libxcb-xinerama0 | |
| - name: Cache Nunez-Elizalde dataset | |
| uses: actions/cache@v6 | |
| with: | |
| path: ~/.cache/confusius/nunez-elizalde-2022-bids | |
| key: ${{ runner.os }}-nunez-elizalde-bids-${{ hashFiles('tools/prefetch_doc_datasets.py') }} | |
| restore-keys: | | |
| ${{ runner.os }}-nunez-elizalde-bids- | |
| - name: Cache Cybis Pereira dataset | |
| uses: actions/cache@v6 | |
| with: | |
| path: ~/.cache/confusius/cybis-pereira-2026-bids | |
| key: ${{ runner.os }}-cybis-pereira-2026-bids-${{ hashFiles('tools/prefetch_doc_datasets.py') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cybis-pereira-2026-bids- | |
| - name: Cache Khallaf dataset | |
| uses: actions/cache@v6 | |
| with: | |
| path: ~/.cache/confusius/khallaf-2026-bids | |
| key: ${{ runner.os }}-khallaf-2026-bids-${{ hashFiles('tools/prefetch_doc_datasets.py') }} | |
| restore-keys: | | |
| ${{ runner.os }}-khallaf-2026-bids- | |
| - name: Cache Pepe Mariani template | |
| uses: actions/cache@v6 | |
| with: | |
| path: ~/.cache/confusius/pepe-mariani-2026-template | |
| key: ${{ runner.os }}-pepe-mariani-2026-template-${{ hashFiles('tools/prefetch_doc_datasets.py') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pepe-mariani-2026-template- | |
| - name: Cache BrainGlobe atlases | |
| uses: actions/cache@v6 | |
| with: | |
| path: ~/.brainglobe | |
| key: ${{ runner.os }}-brainglobe-${{ hashFiles('tools/prefetch_doc_datasets.py') }} | |
| restore-keys: | | |
| ${{ runner.os }}-brainglobe- | |
| - name: Pre-fetch docs datasets | |
| # Single source of truth for every dataset the docs pipeline loads | |
| # (userguide image generators and gallery examples). Running it before | |
| # both downstream steps guarantees they hit a warm cache, which the | |
| # gallery renderer relies on: it enforces light/dark output parity, | |
| # and download progress on a cold cache would otherwise show up in | |
| # one pass but not the other. | |
| run: uv run tools/prefetch_doc_datasets.py | |
| - name: Ensure docs images directories exist | |
| run: | | |
| mkdir -p docs/images/gui | |
| mkdir -p docs/images/qc | |
| mkdir -p docs/images/visualization | |
| mkdir -p docs/images/home | |
| - name: Cache generated docs images | |
| id: cache-doc-images | |
| uses: actions/cache@v6 | |
| with: | |
| path: | | |
| docs/images/gui/*.png | |
| docs/images/gui/*.gif | |
| docs/images/qc/*.png | |
| docs/images/qc/*.gif | |
| docs/images/visualization/*.png | |
| docs/images/visualization/*.gif | |
| docs/images/home/*.png | |
| docs/images/home/*.gif | |
| key: ${{ runner.os }}-docs-images-${{ hashFiles('uv.lock', 'docs/images/**/generate.py', 'tools/prefetch_doc_datasets.py', 'src/**/*.py') }} | |
| restore-keys: | | |
| ${{ runner.os }}-docs-images- | |
| - name: Generate documentation images | |
| if: steps.cache-doc-images.outputs.cache-hit != 'true' | |
| env: | |
| QT_QPA_PLATFORM: "xcb" | |
| PYOPENGL_PLATFORM: "glx" | |
| LIBGL_ALWAYS_SOFTWARE: "1" | |
| run: | | |
| xvfb-run -a uv run docs/images/gui/generate.py | |
| xvfb-run -a uv run docs/images/qc/generate.py | |
| xvfb-run -a uv run docs/images/visualization/generate.py | |
| xvfb-run -a uv run docs/images/atlas/generate.py | |
| xvfb-run -a uv run docs/images/home/generate.py | |
| - name: Ensure gallery cache directory exists | |
| run: mkdir -p .gallery-cache | |
| - name: Cache gallery artifacts | |
| uses: actions/cache@v6 | |
| with: | |
| path: .gallery-cache | |
| key: ${{ runner.os }}-gallery-${{ hashFiles('uv.lock', 'docs/examples/**/*.py', 'tools/gallery/**/*.py', 'tools/build_gallery.py') }} | |
| restore-keys: | | |
| ${{ runner.os }}-gallery- | |
| - name: Build example gallery | |
| env: | |
| QT_QPA_PLATFORM: "xcb" | |
| PYOPENGL_PLATFORM: "glx" | |
| LIBGL_ALWAYS_SOFTWARE: "1" | |
| CONFUSIUS_BINDER_REF: ${{ github.head_ref || github.ref_name }} | |
| run: xvfb-run -a uv run python tools/build_gallery.py | |
| - name: Build documentation | |
| run: uv run zensical build --clean --strict | |
| - name: Upload site artifact | |
| uses: actions/upload-artifact@v7.0.1 | |
| with: | |
| name: site-${{ github.sha }} | |
| path: site/ | |
| retention-days: 14 | |
| - name: Upload gallery artifact | |
| uses: actions/upload-artifact@v7.0.1 | |
| with: | |
| name: gallery-built-${{ github.sha }} | |
| path: | | |
| docs/examples/_built/ | |
| docs/examples/index.md | |
| retention-days: 14 | |
| - name: Upload generated images artifact | |
| uses: actions/upload-artifact@v7.0.1 | |
| with: | |
| name: docs-images-${{ github.sha }} | |
| path: docs/images/ | |
| retention-days: 14 | |
| deploy-preview: | |
| needs: build | |
| if: github.event_name == 'pull_request' && github.actor != 'dependabot[bot]' | |
| runs-on: ubuntu-latest | |
| concurrency: | |
| group: docs-publish | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Download site artifact | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: site-${{ github.sha }} | |
| path: site/ | |
| - name: Deploy PR preview | |
| uses: peaceiris/actions-gh-pages@v4 | |
| with: | |
| personal_token: ${{ secrets.DOCS_DEPLOY_TOKEN }} | |
| external_repository: confusius-tools/confusius-docs | |
| publish_branch: main | |
| publish_dir: site/ | |
| destination_dir: pr-preview/pr-${{ github.event.number }} | |
| keep_files: true | |
| - name: Update pr-preview/versions.json for mike version switcher | |
| env: | |
| GH_TOKEN: ${{ secrets.DOCS_DEPLOY_TOKEN }} | |
| run: | | |
| PR_NUM="${{ github.event.number }}" | |
| RESPONSE=$(gh api repos/confusius-tools/confusius-docs/contents/pr-preview/versions.json 2>/dev/null || echo "") | |
| if [ -n "$RESPONSE" ]; then | |
| SHA=$(echo "$RESPONSE" | jq -r '.sha') | |
| OLD_CONTENT=$(echo "$RESPONSE" | jq -r '.content | gsub("\\n"; "") | @base64d') | |
| else | |
| SHA="" | |
| OLD_CONTENT="[]" | |
| fi | |
| NEW_ENTRY="{\"version\":\"pr-${PR_NUM}\",\"title\":\"PR #${PR_NUM} Preview\",\"aliases\":[]}" | |
| NEW_CONTENT=$(echo "$OLD_CONTENT" | jq --argjson e "$NEW_ENTRY" \ | |
| '[.[] | select(.version != $e.version)] + [$e]') | |
| if [ "$NEW_CONTENT" = "$OLD_CONTENT" ]; then | |
| echo "pr-preview/versions.json already up to date, skipping" | |
| else | |
| CONTENT_B64=$(printf '%s' "$NEW_CONTENT" | base64 -w 0) | |
| PAYLOAD=$(jq -n --arg sha "$SHA" --arg c "$CONTENT_B64" \ | |
| '{message:"chore: update pr-preview/versions.json",content:$c,sha:($sha|if .=="" then null else . end)} | del(..|nulls)') | |
| echo "$PAYLOAD" | gh api repos/confusius-tools/confusius-docs/contents/pr-preview/versions.json \ | |
| -X PUT --input - | |
| fi | |
| - name: Post preview URL comment | |
| uses: marocchino/sticky-pull-request-comment@v3 | |
| with: | |
| message: | | |
| 📖 Doc preview: https://confusius.tools/pr-preview/pr-${{ github.event.number }}/ | |
| deploy-docs: | |
| needs: build | |
| if: github.event_name != 'pull_request' | |
| runs-on: ubuntu-latest | |
| concurrency: | |
| group: docs-publish | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v8.1.0 | |
| with: | |
| python-version: "3.14" | |
| - name: Install dependencies | |
| run: uv sync --frozen --all-extras | |
| - name: Download gallery artifact | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: gallery-built-${{ github.sha }} | |
| path: docs/examples/ | |
| - name: Download generated images artifact | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: docs-images-${{ github.sha }} | |
| path: docs/images/ | |
| - name: Verify gallery artifacts | |
| run: | | |
| if [ ! -f "docs/examples/_built/io/confusius_xarray_101.md" ]; then | |
| echo "Gallery files missing after artifact download:" | |
| ls -la docs/examples/_built/ 2>/dev/null || echo "(directory does not exist)" | |
| exit 1 | |
| fi | |
| if [ ! -f "docs/examples/index.md" ]; then | |
| echo "Gallery index missing after artifact download" | |
| exit 1 | |
| fi | |
| - name: Clone confusius-docs | |
| run: | | |
| git clone --depth 1 \ | |
| "https://x-access-token:${{ secrets.DOCS_DEPLOY_TOKEN }}@github.com/confusius-tools/confusius-docs.git" \ | |
| /tmp/confusius-docs | |
| git -C /tmp/confusius-docs config user.name "github-actions[bot]" | |
| git -C /tmp/confusius-docs config user.email "github-actions[bot]@users.noreply.github.com" | |
| - name: Deploy dev docs | |
| if: github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch' | |
| working-directory: /tmp/confusius-docs | |
| run: uv run --project ${{ github.workspace }} mike deploy --config-file ${{ github.workspace }}/zensical.toml --branch main --push --update-aliases dev latest | |
| - name: Deploy release docs | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| working-directory: /tmp/confusius-docs | |
| run: | | |
| VERSION="${GITHUB_REF#refs/tags/v}" | |
| uv run --project ${{ github.workspace }} mike deploy --config-file ${{ github.workspace }}/zensical.toml --branch main --push "$VERSION" |