diff --git a/+bot/+internal/+util/toolboxdir.m b/+bot/+internal/+util/toolboxdir.m deleted file mode 100644 index ea36b19..0000000 --- a/+bot/+internal/+util/toolboxdir.m +++ /dev/null @@ -1,8 +0,0 @@ -function toolboxFolderPath = toolboxdir() - - thisFolderPath = fileparts( mfilename('fullpath') ); - splitFolderPath = strsplit(thisFolderPath, filesep); - - % Move 3 folders up: - toolboxFolderPath = fullfile( splitFolderPath{1:end-3} ); -end diff --git a/.github/workflows/create_release.yml b/.github/workflows/create_release.yml new file mode 100644 index 0000000..d3da71b --- /dev/null +++ b/.github/workflows/create_release.yml @@ -0,0 +1,176 @@ +# Test the toolbox across all supported releases of MATLAB, package toolbox, create release +# Adapted from: https://github.com/mathworks/climatedatastore/blob/main/.github/workflows/release.yml + +name: Create new release + +# Run workflow when a tag is created +on: + push: + tags: + - 'v*' + +jobs: + # This workflow contains: + # 1. a matrixed test job run across a bunch of releases of MATLAB + # 2. a reporting job that summarizes the tests, and updates release badge + test: + strategy: + fail-fast: false + matrix: + MATLABVersion: [R2020b, R2021a, R2021b, R2022a, R2022b, R2023a, R2023b, R2024a, R2024b] + # The type of runner that the job will run on + runs-on: ubuntu-latest + + steps: + # Checks-out the repository under $GITHUB_WORKSPACE, so the job can access it + - uses: actions/checkout@v4 + + - name: Set up MATLAB + uses: matlab-actions/setup-matlab@v2 + with: + release: ${{ matrix.MATLABVersion }} + + # Runs all tests in the project. Put results in a version specific subdirectory + - name: Run tests + uses: matlab-actions/run-command@v2 + with: + command: | + addpath(genpath("tools")); + testToolbox('ReportSubdirectory',"${{ matrix.MATLABVersion }}", 'CreateBadge', false) + + # Save the contents of the report directory from each release into an artifact. + - name: Save Report Directory + uses: actions/upload-artifact@v4 + if: always() + with: + name: reports-${{ matrix.MATLABVersion }} + path: docs/reports + + # Report on what releases tested successfully. + # Generate a draft release based on the tag + # Recreate the tag with the final version of files + release: + needs: test + if: always() + runs-on: ubuntu-latest + env: + TOOLBOX_FILE_NAME: Brain_Observatory_Toolbox + + steps: + # Use deploy key to push back to protected branch + - name: Checkout repository using deploy key + uses: actions/checkout@v4 + with: + ref: refs/heads/main + ssh-key: ${{ secrets.DEPLOY_KEY }} + + - name: Set up MATLAB + uses: matlab-actions/setup-matlab@v2 + + # Copy all the reports down into the container + - uses: actions/download-artifact@v4 + with: + pattern: reports-* + path: docs/reports + merge-multiple: true + + # Generate the JSON for the releases tested badge + - name: Generate tested with badge + uses: matlab-actions/run-command@v2 + with: + command: addpath(genpath("tools")), createTestedWithBadgeforToolbox("${{ github.ref_name }}") + + # Publish test results from all the releases + - name: Publish Test Results + uses: EnricoMi/publish-unit-test-result-action@v2 + if: always() + with: + junit_files: "docs/reports/*/test-results.xml" + + # Package the MLTBX + - name: Package Toolbox + uses: matlab-actions/run-command@v2 + with: + command: | + addpath(genpath("tools")); + packageToolbox("specific","${{ github.ref_name }}") + + # Define the versionNumber using underscores, as this is used in the MLTBX + - name: Set version number + id: set_version + run: | + versionNumber=$(echo "${{ github.ref_name }}" | sed 's/\./_/g') + echo "versionNumber=$versionNumber" >> $GITHUB_ENV + + # Save the MLTBX. + - name: Save packaged toolbox + uses: actions/upload-artifact@v4 + with: + name: ${{TOOLBOX_FILE_NAME}}${{ env.versionNumber }}.mltbx + path: releases/${{TOOLBOX_FILE_NAME}}_${{ env.versionNumber }}.mltbx + + # Commit the updated Contents.m + - name: Commit updated Contents.m file + continue-on-error: true + run: | + git config user.name "${{ github.workflow }} by ${{ github.actor }}" + git config user.email "<>" + git status + git add code/Contents.m + git commit -m "Final checkins for release ${{ github.ref_name }}" + git fetch + git push + + # Commit the JSON for the MATLAB releases test badge to gh-badges branch + - name: Checkout gh-badges branch + uses: actions/checkout@v4 + with: + ref: gh-badges + path: gh-badges + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Push to gh-badges + run: | + mkdir -p gh-badges/.github/badges/${{ github.ref_name }} + cp .github/badges/${{ github.ref_name }}/tested_with.json gh-badges/.github/badges/${{ github.ref_name }}/tested_with.json + cd gh-badges + + git config user.name "${{ github.workflow }} by ${{ github.actor }}" + git config user.email "<>" + + # Only proceed with commit and push if changes are detected + if [[ $(git add .github/badges/* --dry-run | wc -l) -gt 0 ]]; then + git add .github/badges/* + git commit -m "Update tested with badge for release" + git push -f + else + echo "Nothing to commit" + fi + + # Retag the repo so that the updated files are included in the release tag + - name: Update tag + if: always() + continue-on-error: true + run: | + git config user.name "${{ github.workflow }} by ${{ github.actor }}" + git config user.email "<>" + + # Delete the existing tag locally and remotely + git tag -d "${{ github.ref_name }}" + git push origin --delete "${{ github.ref_name }}" + + # Recreate the tag with a message, including [skip ci] to prevent CI workflows + git tag -a "${{ github.ref_name }}" -m "Release ${{ github.ref_name }} [skip ci]" + + # Push the new tag to the remote repository + git push origin "${{ github.ref_name }}" + + # Create the release + - name: Create GitHub Release + uses: ncipollo/release-action@v1 + with: + draft: true + artifacts: "releases/${{TOOLBOX_FILE_NAME}}_${{ env.versionNumber }}.mltbx" + generateReleaseNotes: true + body: "![MATLAB Versions Tested](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2F${{github.repository}}%2Fgh-badges%2F.github%2Fbadges%2F${{ github.ref_name }}%2Ftested_with.json)" + diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml new file mode 100644 index 0000000..b58510d --- /dev/null +++ b/.github/workflows/run_tests.yml @@ -0,0 +1,93 @@ +name: Run tests + +on: + # Triggers the workflow on push or pull request events for the "main" branch + push: + branches: [ "main" ] + paths-ignore: + - '*md' + - '.github/**' + - 'docs/reports/**' + pull_request: + branches: [ "main" ] + + # Allows for manually running this workflow from the Actions tab + workflow_dispatch: + +jobs: + # This workflow contains a single job called "test" + test: + name: Test toolbox code + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out the repository under $GITHUB_WORKSPACE, so the job can access it + - name: Check out repo + uses: actions/checkout@v4 + with: + ref: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }} + + - name: Set up MATLAB + uses: matlab-actions/setup-matlab@v2 + + # Check for MATLAB code issues in the project. + - name: Check for MATLAB code issues + uses: matlab-actions/run-command@v2 + if: always() + with: + command: addpath(genpath("tools")), codecheckToolbox() + + # Upload code issues report + - name: Upload SARIF file + uses: github/codeql-action/upload-sarif@v3 + with: + # Path to SARIF file relative to the root of the repository + sarif_file: docs/reports/code_issues.sarif + + # Runs all tests in the project. + - name: Run tests + uses: matlab-actions/run-command@v2 + if: always() + with: + command: addpath(genpath("tools")), testToolbox() + + # Commit updated SVG badges for the issues and tests (if changed) + - name: Commit svg badges if updated + if: always() + continue-on-error: true + run: | + git config user.name "${{ github.workflow }} by ${{ github.actor }}" + git config user.email "<>" + git fetch + + if [[ $(git add .github/badges/* --dry-run | wc -l) -gt 0 ]]; then + git add .github/badges/* + git commit -m "Update code issues and tests badges" + git push -f + else + echo "Nothing to commit" + fi + + - name: Upload code coverage report to Codecov + uses: codecov/codecov-action@v4 + if: always() + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: docs/reports/codecoverage.xml + + # Publish test results + - name: Publish test results + uses: EnricoMi/publish-unit-test-result-action@v2 + if: always() + with: + files: "docs/reports/test-results.xml" + + # Save the contents of the reports directory as an artifact + - name: Save reports directory + uses: actions/upload-artifact@v4 + if: always() + with: + name: reports + path: docs/reports diff --git a/.gitignore b/.gitignore index 2b58b48..ffeca6b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ # BOT Data Cache Cache/ +# Ignore everything in docs/reports +docs/reports/* + # Autosave files *.asv *.m~ diff --git a/+bot/+behavior/+item/+internal/+abstract/Item.m b/code/+bot/+behavior/+item/+internal/+abstract/Item.m similarity index 100% rename from +bot/+behavior/+item/+internal/+abstract/Item.m rename to code/+bot/+behavior/+item/+internal/+abstract/Item.m diff --git a/+bot/+behavior/+item/EphysSession.m b/code/+bot/+behavior/+item/EphysSession.m similarity index 99% rename from +bot/+behavior/+item/EphysSession.m rename to code/+bot/+behavior/+item/EphysSession.m index f9ab29d..2297f88 100644 --- a/+bot/+behavior/+item/EphysSession.m +++ b/code/+bot/+behavior/+item/EphysSession.m @@ -1074,9 +1074,13 @@ function displayScalarObject(self) function tableRow = findManifestTableRow(obj, itemId) % Ensure ID is correct type itemId = uint32(round(itemId)); - - tableRow = bot.listSessions(obj.DATASET, obj.DATASET_TYPE, ... - "Id", itemId, "IncludeBehaviorOnly", true); + for i = 0:1 + tableRow = bot.listSessions(obj.DATASET, obj.DATASET_TYPE, ... + "Id", itemId, "IncludeBehaviorOnly", logical(i)); + if ~isempty(tableRow) + break + end + end end end diff --git a/+bot/+behavior/+item/Experiment.m b/code/+bot/+behavior/+item/Experiment.m similarity index 100% rename from +bot/+behavior/+item/Experiment.m rename to code/+bot/+behavior/+item/Experiment.m diff --git a/+bot/+behavior/+item/OphysSession.m b/code/+bot/+behavior/+item/OphysSession.m similarity index 96% rename from +bot/+behavior/+item/OphysSession.m rename to code/+bot/+behavior/+item/OphysSession.m index 3081fdf..1e357f6 100644 --- a/+bot/+behavior/+item/OphysSession.m +++ b/code/+bot/+behavior/+item/OphysSession.m @@ -161,9 +161,13 @@ function initLinkedItems(obj) function tableRow = findManifestTableRow(obj, itemId) % Ensure ID is correct type itemId = uint32(round(itemId)); - - tableRow = bot.listSessions(obj.DATASET, obj.DATASET_TYPE, ... - "Id", itemId, "IncludeBehaviorOnly", true); + for i = 0:1 + tableRow = bot.listSessions(obj.DATASET, obj.DATASET_TYPE, ... + "Id", itemId, "IncludeBehaviorOnly", logical(i)); + if ~isempty(tableRow) + break + end + end end end diff --git a/+bot/+external/+fex/+filedownload/FileDownloadProgressMonitor.m b/code/+bot/+external/+fex/+filedownload/FileDownloadProgressMonitor.m similarity index 100% rename from +bot/+external/+fex/+filedownload/FileDownloadProgressMonitor.m rename to code/+bot/+external/+fex/+filedownload/FileDownloadProgressMonitor.m diff --git a/+bot/+external/+fex/+filedownload/downloadFile.m b/code/+bot/+external/+fex/+filedownload/downloadFile.m similarity index 100% rename from +bot/+external/+fex/+filedownload/downloadFile.m rename to code/+bot/+external/+fex/+filedownload/downloadFile.m diff --git a/+bot/+external/+fex/+filedownload/license.txt b/code/+bot/+external/+fex/+filedownload/license.txt similarity index 100% rename from +bot/+external/+fex/+filedownload/license.txt rename to code/+bot/+external/+fex/+filedownload/license.txt diff --git a/+bot/+external/+matnwb/+io/getMatType.m b/code/+bot/+external/+matnwb/+io/getMatType.m similarity index 100% rename from +bot/+external/+matnwb/+io/getMatType.m rename to code/+bot/+external/+matnwb/+io/getMatType.m diff --git a/+bot/+internal/+abstract/FileResource.m b/code/+bot/+internal/+abstract/FileResource.m similarity index 100% rename from +bot/+internal/+abstract/FileResource.m rename to code/+bot/+internal/+abstract/FileResource.m diff --git a/+bot/+internal/+abstract/LocalFileCache.m b/code/+bot/+internal/+abstract/LocalFileCache.m similarity index 100% rename from +bot/+internal/+abstract/LocalFileCache.m rename to code/+bot/+internal/+abstract/LocalFileCache.m diff --git a/+bot/+internal/+behavior/+cache/CloudCacher.m b/code/+bot/+internal/+behavior/+cache/CloudCacher.m similarity index 100% rename from +bot/+internal/+behavior/+cache/CloudCacher.m rename to code/+bot/+internal/+behavior/+cache/CloudCacher.m diff --git a/+bot/+internal/+behavior/+mixin/HasLinkedFile.m b/code/+bot/+internal/+behavior/+mixin/HasLinkedFile.m similarity index 100% rename from +bot/+internal/+behavior/+mixin/HasLinkedFile.m rename to code/+bot/+internal/+behavior/+mixin/HasLinkedFile.m diff --git a/+bot/+internal/+behavior/Cache.m b/code/+bot/+internal/+behavior/Cache.m similarity index 100% rename from +bot/+internal/+behavior/Cache.m rename to code/+bot/+internal/+behavior/Cache.m diff --git a/+bot/+internal/+behavior/LinkedFile.m b/code/+bot/+internal/+behavior/LinkedFile.m similarity index 100% rename from +bot/+internal/+behavior/LinkedFile.m rename to code/+bot/+internal/+behavior/LinkedFile.m diff --git a/+bot/+internal/+fileresource/+abstract/S3Bucket.m b/code/+bot/+internal/+fileresource/+abstract/S3Bucket.m similarity index 100% rename from +bot/+internal/+fileresource/+abstract/S3Bucket.m rename to code/+bot/+internal/+fileresource/+abstract/S3Bucket.m diff --git a/+bot/+internal/+fileresource/+mixin/HasFileResource.m b/code/+bot/+internal/+fileresource/+mixin/HasFileResource.m similarity index 100% rename from +bot/+internal/+fileresource/+mixin/HasFileResource.m rename to code/+bot/+internal/+fileresource/+mixin/HasFileResource.m diff --git a/+bot/+internal/+fileresource/+visualbehavior/VBEphysS3Bucket.m b/code/+bot/+internal/+fileresource/+visualbehavior/VBEphysS3Bucket.m similarity index 100% rename from +bot/+internal/+fileresource/+visualbehavior/VBEphysS3Bucket.m rename to code/+bot/+internal/+fileresource/+visualbehavior/VBEphysS3Bucket.m diff --git a/+bot/+internal/+fileresource/+visualbehavior/VBOphysS3Bucket.m b/code/+bot/+internal/+fileresource/+visualbehavior/VBOphysS3Bucket.m similarity index 100% rename from +bot/+internal/+fileresource/+visualbehavior/VBOphysS3Bucket.m rename to code/+bot/+internal/+fileresource/+visualbehavior/VBOphysS3Bucket.m diff --git a/+bot/+internal/+fileresource/+visualcoding/VCEphysS3Bucket.m b/code/+bot/+internal/+fileresource/+visualcoding/VCEphysS3Bucket.m similarity index 100% rename from +bot/+internal/+fileresource/+visualcoding/VCEphysS3Bucket.m rename to code/+bot/+internal/+fileresource/+visualcoding/VCEphysS3Bucket.m diff --git a/+bot/+internal/+fileresource/+visualcoding/VCOphysS3Bucket.m b/code/+bot/+internal/+fileresource/+visualcoding/VCOphysS3Bucket.m similarity index 100% rename from +bot/+internal/+fileresource/+visualcoding/VCOphysS3Bucket.m rename to code/+bot/+internal/+fileresource/+visualcoding/VCOphysS3Bucket.m diff --git a/+bot/+internal/+fileresource/WebApi.m b/code/+bot/+internal/+fileresource/WebApi.m similarity index 100% rename from +bot/+internal/+fileresource/WebApi.m rename to code/+bot/+internal/+fileresource/WebApi.m diff --git a/+bot/+internal/+metadata/+utility/convertStringArrayIdToInteger.m b/code/+bot/+internal/+metadata/+utility/convertStringArrayIdToInteger.m similarity index 100% rename from +bot/+internal/+metadata/+utility/convertStringArrayIdToInteger.m rename to code/+bot/+internal/+metadata/+utility/convertStringArrayIdToInteger.m diff --git a/+bot/+internal/+metadata/+utility/itemTableTypeConversionMap.m b/code/+bot/+internal/+metadata/+utility/itemTableTypeConversionMap.m similarity index 100% rename from +bot/+internal/+metadata/+utility/itemTableTypeConversionMap.m rename to code/+bot/+internal/+metadata/+utility/itemTableTypeConversionMap.m diff --git a/+bot/+internal/+metadata/+utility/itemTableVariableRenameMap.m b/code/+bot/+internal/+metadata/+utility/itemTableVariableRenameMap.m similarity index 100% rename from +bot/+internal/+metadata/+utility/itemTableVariableRenameMap.m rename to code/+bot/+internal/+metadata/+utility/itemTableVariableRenameMap.m diff --git a/+bot/+internal/+metadata/VisualBehaviorEphysManifest.m b/code/+bot/+internal/+metadata/VisualBehaviorEphysManifest.m similarity index 100% rename from +bot/+internal/+metadata/VisualBehaviorEphysManifest.m rename to code/+bot/+internal/+metadata/VisualBehaviorEphysManifest.m diff --git a/+bot/+internal/+metadata/VisualBehaviorOphysManifest.m b/code/+bot/+internal/+metadata/VisualBehaviorOphysManifest.m similarity index 100% rename from +bot/+internal/+metadata/VisualBehaviorOphysManifest.m rename to code/+bot/+internal/+metadata/VisualBehaviorOphysManifest.m diff --git a/+bot/+internal/+nwb/+file/+vb/BehaviorNWBFile.m b/code/+bot/+internal/+nwb/+file/+vb/BehaviorNWBFile.m similarity index 100% rename from +bot/+internal/+nwb/+file/+vb/BehaviorNWBFile.m rename to code/+bot/+internal/+nwb/+file/+vb/BehaviorNWBFile.m diff --git a/+bot/+internal/+nwb/+file/+vb/OphysNWBFile.m b/code/+bot/+internal/+nwb/+file/+vb/OphysNWBFile.m similarity index 100% rename from +bot/+internal/+nwb/+file/+vb/OphysNWBFile.m rename to code/+bot/+internal/+nwb/+file/+vb/OphysNWBFile.m diff --git a/+bot/+internal/+nwb/+reader/+vb/Contents.m b/code/+bot/+internal/+nwb/+reader/+vb/Contents.m similarity index 100% rename from +bot/+internal/+nwb/+reader/+vb/Contents.m rename to code/+bot/+internal/+nwb/+reader/+vb/Contents.m diff --git a/+bot/+internal/+nwb/+reader/+vb/read_cell_specimen_table.m b/code/+bot/+internal/+nwb/+reader/+vb/read_cell_specimen_table.m similarity index 100% rename from +bot/+internal/+nwb/+reader/+vb/read_cell_specimen_table.m rename to code/+bot/+internal/+nwb/+reader/+vb/read_cell_specimen_table.m diff --git a/+bot/+internal/+nwb/+reader/+vb/read_eyetracking_timetable.m b/code/+bot/+internal/+nwb/+reader/+vb/read_eyetracking_timetable.m similarity index 100% rename from +bot/+internal/+nwb/+reader/+vb/read_eyetracking_timetable.m rename to code/+bot/+internal/+nwb/+reader/+vb/read_eyetracking_timetable.m diff --git a/+bot/+internal/+nwb/+reader/+vb/read_lick_timetable.m b/code/+bot/+internal/+nwb/+reader/+vb/read_lick_timetable.m similarity index 100% rename from +bot/+internal/+nwb/+reader/+vb/read_lick_timetable.m rename to code/+bot/+internal/+nwb/+reader/+vb/read_lick_timetable.m diff --git a/+bot/+internal/+nwb/+reader/+vb/read_rewards_timetable.m b/code/+bot/+internal/+nwb/+reader/+vb/read_rewards_timetable.m similarity index 100% rename from +bot/+internal/+nwb/+reader/+vb/read_rewards_timetable.m rename to code/+bot/+internal/+nwb/+reader/+vb/read_rewards_timetable.m diff --git a/+bot/+internal/+nwb/+reader/+vb/read_trials_timetable.m b/code/+bot/+internal/+nwb/+reader/+vb/read_trials_timetable.m similarity index 100% rename from +bot/+internal/+nwb/+reader/+vb/read_trials_timetable.m rename to code/+bot/+internal/+nwb/+reader/+vb/read_trials_timetable.m diff --git a/+bot/+internal/+nwb/+reader/readDynamicTable.m b/code/+bot/+internal/+nwb/+reader/readDynamicTable.m similarity index 100% rename from +bot/+internal/+nwb/+reader/readDynamicTable.m rename to code/+bot/+internal/+nwb/+reader/readDynamicTable.m diff --git a/+bot/+internal/+nwb/+reader/readGeneralMetadata.m b/code/+bot/+internal/+nwb/+reader/readGeneralMetadata.m similarity index 100% rename from +bot/+internal/+nwb/+reader/readGeneralMetadata.m rename to code/+bot/+internal/+nwb/+reader/readGeneralMetadata.m diff --git a/+bot/+internal/+nwb/+reader/readOphysMetadata.m b/code/+bot/+internal/+nwb/+reader/readOphysMetadata.m similarity index 100% rename from +bot/+internal/+nwb/+reader/readOphysMetadata.m rename to code/+bot/+internal/+nwb/+reader/readOphysMetadata.m diff --git a/+bot/+internal/+nwb/+reader/readRigMetadata.m b/code/+bot/+internal/+nwb/+reader/readRigMetadata.m similarity index 100% rename from +bot/+internal/+nwb/+reader/readRigMetadata.m rename to code/+bot/+internal/+nwb/+reader/readRigMetadata.m diff --git a/+bot/+internal/+nwb/+reader/readSubjectMetadata.m b/code/+bot/+internal/+nwb/+reader/readSubjectMetadata.m similarity index 100% rename from +bot/+internal/+nwb/+reader/readSubjectMetadata.m rename to code/+bot/+internal/+nwb/+reader/readSubjectMetadata.m diff --git a/+bot/+internal/+nwb/+reader/readTaskMetadata.m b/code/+bot/+internal/+nwb/+reader/readTaskMetadata.m similarity index 100% rename from +bot/+internal/+nwb/+reader/readTaskMetadata.m rename to code/+bot/+internal/+nwb/+reader/readTaskMetadata.m diff --git a/+bot/+internal/+nwb/LinkedNWBFile.m b/code/+bot/+internal/+nwb/LinkedNWBFile.m similarity index 100% rename from +bot/+internal/+nwb/LinkedNWBFile.m rename to code/+bot/+internal/+nwb/LinkedNWBFile.m diff --git a/+bot/+internal/+nwb/deindex_table_from_datasets.m b/code/+bot/+internal/+nwb/deindex_table_from_datasets.m similarity index 100% rename from +bot/+internal/+nwb/deindex_table_from_datasets.m rename to code/+bot/+internal/+nwb/deindex_table_from_datasets.m diff --git a/+bot/+internal/+nwb/has_path.m b/code/+bot/+internal/+nwb/has_path.m similarity index 100% rename from +bot/+internal/+nwb/has_path.m rename to code/+bot/+internal/+nwb/has_path.m diff --git a/+bot/+internal/+nwb/nwb_ephys.m b/code/+bot/+internal/+nwb/nwb_ephys.m similarity index 100% rename from +bot/+internal/+nwb/nwb_ephys.m rename to code/+bot/+internal/+nwb/nwb_ephys.m diff --git a/+bot/+internal/+nwb/readAttributesToStruct.m b/code/+bot/+internal/+nwb/readAttributesToStruct.m similarity index 100% rename from +bot/+internal/+nwb/readAttributesToStruct.m rename to code/+bot/+internal/+nwb/readAttributesToStruct.m diff --git a/+bot/+internal/+nwb/readDatasetsToStruct.m b/code/+bot/+internal/+nwb/readDatasetsToStruct.m similarity index 100% rename from +bot/+internal/+nwb/readDatasetsToStruct.m rename to code/+bot/+internal/+nwb/readDatasetsToStruct.m diff --git a/+bot/+internal/+nwb/struct_from_attributes.m b/code/+bot/+internal/+nwb/struct_from_attributes.m similarity index 100% rename from +bot/+internal/+nwb/struct_from_attributes.m rename to code/+bot/+internal/+nwb/struct_from_attributes.m diff --git a/+bot/+internal/+nwb/table_from_datasets.m b/code/+bot/+internal/+nwb/table_from_datasets.m similarity index 100% rename from +bot/+internal/+nwb/table_from_datasets.m rename to code/+bot/+internal/+nwb/table_from_datasets.m diff --git a/+bot/+internal/+nwb/xarray_from_dataset.m b/code/+bot/+internal/+nwb/xarray_from_dataset.m similarity index 100% rename from +bot/+internal/+nwb/xarray_from_dataset.m rename to code/+bot/+internal/+nwb/xarray_from_dataset.m diff --git a/+bot/+internal/+util/castTableVariables.m b/code/+bot/+internal/+util/castTableVariables.m similarity index 100% rename from +bot/+internal/+util/castTableVariables.m rename to code/+bot/+internal/+util/castTableVariables.m diff --git a/+bot/+internal/+util/getLocalFileSize.m b/code/+bot/+internal/+util/getLocalFileSize.m similarity index 100% rename from +bot/+internal/+util/getLocalFileSize.m rename to code/+bot/+internal/+util/getLocalFileSize.m diff --git a/+bot/+internal/+util/getToolboxVersion.m b/code/+bot/+internal/+util/getToolboxVersion.m similarity index 100% rename from +bot/+internal/+util/getToolboxVersion.m rename to code/+bot/+internal/+util/getToolboxVersion.m diff --git a/+bot/+internal/+util/getWebFileSize.m b/code/+bot/+internal/+util/getWebFileSize.m similarity index 100% rename from +bot/+internal/+util/getWebFileSize.m rename to code/+bot/+internal/+util/getWebFileSize.m diff --git a/+bot/+internal/+util/isVerLessThan.m b/code/+bot/+internal/+util/isVerLessThan.m similarity index 100% rename from +bot/+internal/+util/isVerLessThan.m rename to code/+bot/+internal/+util/isVerLessThan.m diff --git a/+bot/+internal/+util/resolveDataset.m b/code/+bot/+internal/+util/resolveDataset.m similarity index 100% rename from +bot/+internal/+util/resolveDataset.m rename to code/+bot/+internal/+util/resolveDataset.m diff --git a/+bot/+internal/+util/structcat.m b/code/+bot/+internal/+util/structcat.m similarity index 100% rename from +bot/+internal/+util/structcat.m rename to code/+bot/+internal/+util/structcat.m diff --git a/+bot/+internal/+util/structmerge.m b/code/+bot/+internal/+util/structmerge.m similarity index 100% rename from +bot/+internal/+util/structmerge.m rename to code/+bot/+internal/+util/structmerge.m diff --git a/code/+bot/+internal/+util/toolboxdir.m b/code/+bot/+internal/+util/toolboxdir.m new file mode 100644 index 0000000..3df1d4d --- /dev/null +++ b/code/+bot/+internal/+util/toolboxdir.m @@ -0,0 +1,8 @@ +function toolboxFolderPath = toolboxdir() + + thisFolderPath = fileparts( mfilename('fullpath') ); + filesepLoc = regexp(thisFolderPath, filesep); + + % Get path of folder 3 levels up: + toolboxFolderPath = extractBefore(thisFolderPath, filesepLoc(end-2)); +end diff --git a/+bot/+internal/+util/uriJoin.m b/code/+bot/+internal/+util/uriJoin.m similarity index 100% rename from +bot/+internal/+util/uriJoin.m rename to code/+bot/+internal/+util/uriJoin.m diff --git a/+bot/+internal/BinarySearchSortedList_MATLAB.m b/code/+bot/+internal/BinarySearchSortedList_MATLAB.m similarity index 100% rename from +bot/+internal/BinarySearchSortedList_MATLAB.m rename to code/+bot/+internal/BinarySearchSortedList_MATLAB.m diff --git a/+bot/+internal/BinarySearchSortedList_double_mex.c b/code/+bot/+internal/BinarySearchSortedList_double_mex.c similarity index 100% rename from +bot/+internal/BinarySearchSortedList_double_mex.c rename to code/+bot/+internal/BinarySearchSortedList_double_mex.c diff --git a/+bot/+internal/BinarySearchSortedList_int32_mex.c b/code/+bot/+internal/BinarySearchSortedList_int32_mex.c similarity index 100% rename from +bot/+internal/BinarySearchSortedList_int32_mex.c rename to code/+bot/+internal/BinarySearchSortedList_int32_mex.c diff --git a/+bot/+internal/BrainObservatoryAPI.m b/code/+bot/+internal/BrainObservatoryAPI.m similarity index 100% rename from +bot/+internal/BrainObservatoryAPI.m rename to code/+bot/+internal/BrainObservatoryAPI.m diff --git a/+bot/+internal/Cache.m b/code/+bot/+internal/Cache.m similarity index 100% rename from +bot/+internal/Cache.m rename to code/+bot/+internal/Cache.m diff --git a/+bot/+internal/CloudCacher.m b/code/+bot/+internal/CloudCacher.m similarity index 100% rename from +bot/+internal/CloudCacher.m rename to code/+bot/+internal/CloudCacher.m diff --git a/+bot/+internal/GetUniqueUID.m b/code/+bot/+internal/GetUniqueUID.m similarity index 100% rename from +bot/+internal/GetUniqueUID.m rename to code/+bot/+internal/GetUniqueUID.m diff --git a/+bot/+internal/ObjectCacher.m b/code/+bot/+internal/ObjectCacher.m similarity index 100% rename from +bot/+internal/ObjectCacher.m rename to code/+bot/+internal/ObjectCacher.m diff --git a/+bot/+internal/OnDemandProperty.m b/code/+bot/+internal/OnDemandProperty.m similarity index 100% rename from +bot/+internal/OnDemandProperty.m rename to code/+bot/+internal/OnDemandProperty.m diff --git a/+bot/+internal/Preferences.m b/code/+bot/+internal/Preferences.m similarity index 100% rename from +bot/+internal/Preferences.m rename to code/+bot/+internal/Preferences.m diff --git a/+bot/+internal/README.mlx b/code/+bot/+internal/README.mlx similarity index 100% rename from +bot/+internal/README.mlx rename to code/+bot/+internal/README.mlx diff --git a/+bot/+internal/SimpleMap.m b/code/+bot/+internal/SimpleMap.m similarity index 100% rename from +bot/+internal/SimpleMap.m rename to code/+bot/+internal/SimpleMap.m diff --git a/+bot/+internal/fetch_ABO_query.m b/code/+bot/+internal/fetch_ABO_query.m similarity index 100% rename from +bot/+internal/fetch_ABO_query.m rename to code/+bot/+internal/fetch_ABO_query.m diff --git a/+bot/+internal/fetch_mex_handles.m b/code/+bot/+internal/fetch_mex_handles.m similarity index 100% rename from +bot/+internal/fetch_mex_handles.m rename to code/+bot/+internal/fetch_mex_handles.m diff --git a/+bot/+internal/merge_tables.m b/code/+bot/+internal/merge_tables.m similarity index 100% rename from +bot/+internal/merge_tables.m rename to code/+bot/+internal/merge_tables.m diff --git a/+bot/+internal/prepareForDemo.m b/code/+bot/+internal/prepareForDemo.m similarity index 100% rename from +bot/+internal/prepareForDemo.m rename to code/+bot/+internal/prepareForDemo.m diff --git a/+bot/+internal/reset.m b/code/+bot/+internal/reset.m similarity index 100% rename from +bot/+internal/reset.m rename to code/+bot/+internal/reset.m diff --git a/+bot/+item/+concrete/EphysSession.m b/code/+bot/+item/+concrete/EphysSession.m similarity index 100% rename from +bot/+item/+concrete/EphysSession.m rename to code/+bot/+item/+concrete/EphysSession.m diff --git a/+bot/+item/+concrete/OphysSession.m b/code/+bot/+item/+concrete/OphysSession.m similarity index 100% rename from +bot/+item/+concrete/OphysSession.m rename to code/+bot/+item/+concrete/OphysSession.m diff --git a/+bot/+item/+internal/+abstract/Item.m b/code/+bot/+item/+internal/+abstract/Item.m similarity index 100% rename from +bot/+item/+internal/+abstract/Item.m rename to code/+bot/+item/+internal/+abstract/Item.m diff --git a/+bot/+item/+internal/+abstract/LinkedFilesItem.m b/code/+bot/+item/+internal/+abstract/LinkedFilesItem.m similarity index 100% rename from +bot/+item/+internal/+abstract/LinkedFilesItem.m rename to code/+bot/+item/+internal/+abstract/LinkedFilesItem.m diff --git a/+bot/+item/+internal/+enum/Dataset.m b/code/+bot/+item/+internal/+enum/Dataset.m similarity index 100% rename from +bot/+item/+internal/+enum/Dataset.m rename to code/+bot/+item/+internal/+enum/Dataset.m diff --git a/+bot/+item/+internal/+enum/DatasetType.m b/code/+bot/+item/+internal/+enum/DatasetType.m similarity index 100% rename from +bot/+item/+internal/+enum/DatasetType.m rename to code/+bot/+item/+internal/+enum/DatasetType.m diff --git a/+bot/+item/+internal/+enum/ItemType.m b/code/+bot/+item/+internal/+enum/ItemType.m similarity index 100% rename from +bot/+item/+internal/+enum/ItemType.m rename to code/+bot/+item/+internal/+enum/ItemType.m diff --git a/+bot/+item/+internal/+enum/OnDemandState.m b/code/+bot/+item/+internal/+enum/OnDemandState.m similarity index 100% rename from +bot/+item/+internal/+enum/OnDemandState.m rename to code/+bot/+item/+internal/+enum/OnDemandState.m diff --git a/+bot/+item/+internal/+mixin/Metrics.m b/code/+bot/+item/+internal/+mixin/Metrics.m similarity index 100% rename from +bot/+item/+internal/+mixin/Metrics.m rename to code/+bot/+item/+internal/+mixin/Metrics.m diff --git a/+bot/+item/+internal/+mixin/OnDemandProps.m b/code/+bot/+item/+internal/+mixin/OnDemandProps.m similarity index 100% rename from +bot/+item/+internal/+mixin/OnDemandProps.m rename to code/+bot/+item/+internal/+mixin/OnDemandProps.m diff --git a/+bot/+item/+internal/EphysManifest.m b/code/+bot/+item/+internal/EphysManifest.m similarity index 100% rename from +bot/+item/+internal/EphysManifest.m rename to code/+bot/+item/+internal/EphysManifest.m diff --git a/+bot/+item/+internal/Manifest.m b/code/+bot/+item/+internal/Manifest.m similarity index 100% rename from +bot/+item/+internal/Manifest.m rename to code/+bot/+item/+internal/Manifest.m diff --git a/+bot/+item/+internal/OphysManifest.m b/code/+bot/+item/+internal/OphysManifest.m similarity index 100% rename from +bot/+item/+internal/OphysManifest.m rename to code/+bot/+item/+internal/OphysManifest.m diff --git a/+bot/+item/Cell.m b/code/+bot/+item/Cell.m similarity index 100% rename from +bot/+item/Cell.m rename to code/+bot/+item/Cell.m diff --git a/+bot/+item/Channel.m b/code/+bot/+item/Channel.m similarity index 100% rename from +bot/+item/Channel.m rename to code/+bot/+item/Channel.m diff --git a/+bot/+item/Experiment.m b/code/+bot/+item/Experiment.m similarity index 100% rename from +bot/+item/Experiment.m rename to code/+bot/+item/Experiment.m diff --git a/+bot/+item/Probe.m b/code/+bot/+item/Probe.m similarity index 100% rename from +bot/+item/Probe.m rename to code/+bot/+item/Probe.m diff --git a/+bot/+item/Session.m b/code/+bot/+item/Session.m similarity index 100% rename from +bot/+item/Session.m rename to code/+bot/+item/Session.m diff --git a/+bot/+item/Unit.m b/code/+bot/+item/Unit.m similarity index 100% rename from +bot/+item/Unit.m rename to code/+bot/+item/Unit.m diff --git a/+bot/+util/StimulusAlignedResp.m b/code/+bot/+util/StimulusAlignedResp.m similarity index 100% rename from +bot/+util/StimulusAlignedResp.m rename to code/+bot/+util/StimulusAlignedResp.m diff --git a/+bot/+util/autoConfigureByEnvironment.m b/code/+bot/+util/autoConfigureByEnvironment.m similarity index 100% rename from +bot/+util/autoConfigureByEnvironment.m rename to code/+bot/+util/autoConfigureByEnvironment.m diff --git a/+bot/+util/convertEphysToRaster.m b/code/+bot/+util/convertEphysToRaster.m similarity index 100% rename from +bot/+util/convertEphysToRaster.m rename to code/+bot/+util/convertEphysToRaster.m diff --git a/+bot/+util/convert_fluorescence_trace_into_raster_format.m b/code/+bot/+util/convert_fluorescence_trace_into_raster_format.m similarity index 100% rename from +bot/+util/convert_fluorescence_trace_into_raster_format.m rename to code/+bot/+util/convert_fluorescence_trace_into_raster_format.m diff --git a/+bot/+util/getPreferences.m b/code/+bot/+util/getPreferences.m similarity index 100% rename from +bot/+util/getPreferences.m rename to code/+bot/+util/getPreferences.m diff --git a/+bot/+util/ophyssessionfilter.m b/code/+bot/+util/ophyssessionfilter.m similarity index 100% rename from +bot/+util/ophyssessionfilter.m rename to code/+bot/+util/ophyssessionfilter.m diff --git a/+bot/+util/showReferences.m b/code/+bot/+util/showReferences.m similarity index 100% rename from +bot/+util/showReferences.m rename to code/+bot/+util/showReferences.m diff --git a/+bot/README.m b/code/+bot/README.m similarity index 100% rename from +bot/README.m rename to code/+bot/README.m diff --git a/+bot/getCells.m b/code/+bot/getCells.m similarity index 100% rename from +bot/getCells.m rename to code/+bot/getCells.m diff --git a/+bot/getChannels.m b/code/+bot/getChannels.m similarity index 100% rename from +bot/getChannels.m rename to code/+bot/getChannels.m diff --git a/+bot/getExperiments.m b/code/+bot/getExperiments.m similarity index 100% rename from +bot/getExperiments.m rename to code/+bot/getExperiments.m diff --git a/+bot/getProbes.m b/code/+bot/getProbes.m similarity index 100% rename from +bot/getProbes.m rename to code/+bot/getProbes.m diff --git a/+bot/getSessions.m b/code/+bot/getSessions.m similarity index 94% rename from +bot/getSessions.m rename to code/+bot/getSessions.m index 78c9de4..dc60bb8 100644 --- a/+bot/getSessions.m +++ b/code/+bot/getSessions.m @@ -87,9 +87,11 @@ warning('off', 'BOT:ListSessions:BehaviorOnlyNotPresent') for iName = string(datasetNames') for jType = string(datasetTypes') - sessionTable = bot.listSessions(iName, jType, "IncludeBehaviorOnly", true); - ids = sessionTable.id; - sessionIdMap(ids)={{iName, jType}}; + for k = 0:1 + sessionTable = bot.listSessions(iName, jType, "IncludeBehaviorOnly", logical(k)); + ids = sessionTable.id; + sessionIdMap(ids)={{iName, jType}}; + end end end warning('on', 'BOT:ListSessions:BehaviorOnlyNotPresent') diff --git a/+bot/getUnits.m b/code/+bot/getUnits.m similarity index 100% rename from +bot/getUnits.m rename to code/+bot/getUnits.m diff --git a/+bot/listCells.m b/code/+bot/listCells.m similarity index 100% rename from +bot/listCells.m rename to code/+bot/listCells.m diff --git a/+bot/listChannels.m b/code/+bot/listChannels.m similarity index 100% rename from +bot/listChannels.m rename to code/+bot/listChannels.m diff --git a/+bot/listExperiments.m b/code/+bot/listExperiments.m similarity index 100% rename from +bot/listExperiments.m rename to code/+bot/listExperiments.m diff --git a/+bot/listProbes.m b/code/+bot/listProbes.m similarity index 100% rename from +bot/listProbes.m rename to code/+bot/listProbes.m diff --git a/+bot/listSessions.m b/code/+bot/listSessions.m similarity index 99% rename from +bot/listSessions.m rename to code/+bot/listSessions.m index 5816c5d..a131318 100644 --- a/+bot/listSessions.m +++ b/code/+bot/listSessions.m @@ -47,7 +47,7 @@ % Note: This function can support returning sessions from multiple % datasets, but this functionality is currently not enabled - datasetNames = [dataset.Name]; + datasetNames = dataset.Name; datasetType = string(datasetType); if options.IncludeBehaviorOnly diff --git a/+bot/listUnits.m b/code/+bot/listUnits.m similarity index 100% rename from +bot/listUnits.m rename to code/+bot/listUnits.m diff --git a/.gitattributes b/code/.gitattributes similarity index 100% rename from .gitattributes rename to code/.gitattributes diff --git a/Contents.m b/code/Contents.m similarity index 93% rename from Contents.m rename to code/Contents.m index 9f5067b..1728aa4 100644 --- a/Contents.m +++ b/code/Contents.m @@ -1,8 +1,8 @@ -% Brain Observatory Toolbox +% Brain-Observatory-Toolbox % Version 0.9.4 19-feb-2024 % -% Copyright (c) 2017, Ethan Meyers -% ---------------------------------- +% Copyright (c) 2024, Ethan Meyers +% -------------------------------- % % A MATLAB toolbox for accessing and using the public neural % recording datasets from the Allen Brain Observatory. diff --git a/examples/VisualBehavior_OphysQuickstart.mlx b/code/examples/VisualBehavior_OphysQuickstart.mlx similarity index 100% rename from examples/VisualBehavior_OphysQuickstart.mlx rename to code/examples/VisualBehavior_OphysQuickstart.mlx diff --git a/examples/VisualCoding_BehaviorTutorial.mlx b/code/examples/VisualCoding_BehaviorTutorial.mlx similarity index 100% rename from examples/VisualCoding_BehaviorTutorial.mlx rename to code/examples/VisualCoding_BehaviorTutorial.mlx diff --git a/examples/VisualCoding_DecodingTutorial.mlx b/code/examples/VisualCoding_DecodingTutorial.mlx similarity index 100% rename from examples/VisualCoding_DecodingTutorial.mlx rename to code/examples/VisualCoding_DecodingTutorial.mlx diff --git a/examples/VisualCoding_EphysDemo.mlx b/code/examples/VisualCoding_EphysDemo.mlx similarity index 100% rename from examples/VisualCoding_EphysDemo.mlx rename to code/examples/VisualCoding_EphysDemo.mlx diff --git a/examples/VisualCoding_EphysQuickstart.mlx b/code/examples/VisualCoding_EphysQuickstart.mlx similarity index 100% rename from examples/VisualCoding_EphysQuickstart.mlx rename to code/examples/VisualCoding_EphysQuickstart.mlx diff --git a/examples/VisualCoding_EphysTutorial.mlx b/code/examples/VisualCoding_EphysTutorial.mlx similarity index 100% rename from examples/VisualCoding_EphysTutorial.mlx rename to code/examples/VisualCoding_EphysTutorial.mlx diff --git a/examples/VisualCoding_OphysDemo.mlx b/code/examples/VisualCoding_OphysDemo.mlx similarity index 100% rename from examples/VisualCoding_OphysDemo.mlx rename to code/examples/VisualCoding_OphysDemo.mlx diff --git a/examples/VisualCoding_OphysQuickstart.mlx b/code/examples/VisualCoding_OphysQuickstart.mlx similarity index 100% rename from examples/VisualCoding_OphysQuickstart.mlx rename to code/examples/VisualCoding_OphysQuickstart.mlx diff --git a/examples/VisualCoding_OphysTutorial.mlx b/code/examples/VisualCoding_OphysTutorial.mlx similarity index 100% rename from examples/VisualCoding_OphysTutorial.mlx rename to code/examples/VisualCoding_OphysTutorial.mlx diff --git a/tools/+bottools/projectdir.m b/tools/+bottools/projectdir.m new file mode 100644 index 0000000..692cc63 --- /dev/null +++ b/tools/+bottools/projectdir.m @@ -0,0 +1,4 @@ +function folderPath = botProjectdir() +% projectdir - Get project root directory for a matlab toolbox code repository + folderPath = fileparts(fileparts(fileparts(mfilename('fullpath')))); +end diff --git a/tools/MLToolboxInfo.json b/tools/MLToolboxInfo.json new file mode 100644 index 0000000..4cc068f --- /dev/null +++ b/tools/MLToolboxInfo.json @@ -0,0 +1,14 @@ +{ + "Namespace" : "bot", + "ToolboxOptions": { + "Identifier": "85a3255c-4ff5-42ef-9c10-b441318b4322", + "ToolboxName": "Brain-Observatory-Toolbox", + "AuthorName": "Ethan Meyers", + "AuthorEmail": "", + "AuthorCompany": "", + "Summary": "A MATLAB toolbox for interacting with the Allen Brain Observatory", + "Description": "A MATLAB toolbox for accessing and using the neural recording public datasets from the Allen Brain Observatory. Available datasets: Available datasets: Visual Coding, Visual Behavior (Neuropixels and 2-Photon Calcium Imaging)", + "MinimumMatlabRelease": "", + "MaximumMatlabRelease": "" + } +} diff --git a/tools/tasks/codecheckToolbox.m b/tools/tasks/codecheckToolbox.m new file mode 100644 index 0000000..5f2b270 --- /dev/null +++ b/tools/tasks/codecheckToolbox.m @@ -0,0 +1,5 @@ +function codecheckToolbox() + installMatBox("commit") + projectRootDirectory = bottools.projectdir(); + matbox.tasks.codecheckToolbox(projectRootDirectory) +end diff --git a/tools/tasks/createTestedWithBadgeforToolbox.m b/tools/tasks/createTestedWithBadgeforToolbox.m new file mode 100644 index 0000000..c773024 --- /dev/null +++ b/tools/tasks/createTestedWithBadgeforToolbox.m @@ -0,0 +1,8 @@ +function createTestedWithBadgeforToolbox(versionNumber) + arguments + versionNumber (1,1) string + end + installMatBox() + projectRootDirectory = bottools.projectdir(); + matbox.tasks.createTestedWithBadgeforToolbox(versionNumber, projectRootDirectory) +end diff --git a/tools/tasks/installMatBox.m b/tools/tasks/installMatBox.m new file mode 100644 index 0000000..f69ca57 --- /dev/null +++ b/tools/tasks/installMatBox.m @@ -0,0 +1,63 @@ +function installMatBox(mode) +% installMatBox - Install MatBox from latest release or latest commit + +% Todo: +% - If MatBox release has been updated on remote, should reinstall. + + arguments + mode (1,1) string {mustBeMember(mode, ["release", "commit"])} = "release" + end + + if mode == "release" + installFromRelease() % local function + elseif mode == "commit" + installFromCommit() % local function + end +end + +function installFromRelease() + addonsTable = matlab.addons.installedAddons(); + isMatchedAddon = addonsTable.Name == "MatBox"; + + if ~isempty(isMatchedAddon) && any(isMatchedAddon) + matlab.addons.enableAddon('MatBox') + else + info = webread('https://api.github.com/repos/ehennestad/MatBox/releases/latest'); + assetNames = {info.assets.name}; + isMltbx = startsWith(assetNames, 'MatBox'); + + mltbx_URL = info.assets(isMltbx).browser_download_url; + + % Download matbox + tempFilePath = websave(tempname, mltbx_URL); + cleanupObj = onCleanup(@(fp) delete(tempFilePath)); + + % Install toolbox + matlab.addons.install(tempFilePath); + end +end + + +function installFromCommit() + % Download latest zipped version of repo + url = "https://github.com/ehennestad/MatBox/archive/refs/heads/main.zip"; + tempFilePath = websave(tempname, url); + cleanupObj = onCleanup(@(fp) delete(tempFilePath)); + + % Unzip in temporary location + unzippedFiles = unzip(tempFilePath, tempdir); + unzippedFolder = unzippedFiles{1}; + if endsWith(unzippedFolder, filesep) + unzippedFolder = unzippedFolder(1:end-1); + end + + % Move to installation location + [~, repoFolderName] = fileparts(unzippedFolder); + targetFolder = fullfile(userpath, "Add-Ons"); + targetFolder = fullfile(targetFolder, repoFolderName); + if isfolder(targetFolder); rmdir(targetFolder, "s"); end + movefile(unzippedFolder, targetFolder); + + % Add to MATLAB's search path + addpath(genpath(targetFolder)) +end \ No newline at end of file diff --git a/tools/tasks/packageToolbox.m b/tools/tasks/packageToolbox.m new file mode 100644 index 0000000..9035af6 --- /dev/null +++ b/tools/tasks/packageToolbox.m @@ -0,0 +1,9 @@ +function packageToolbox(releaseType, versionString) + arguments + releaseType {mustBeTextScalar,mustBeMember(releaseType,["build","major","minor","patch","specific"])} = "build" + versionString {mustBeTextScalar} = ""; + end + installMatBox() + projectRootDirectory = bottools.projectdir(); + matbox.tasks.packageToolbox(projectRootDirectory, releaseType, versionString) +end diff --git a/tools/tasks/testToolbox.m b/tools/tasks/testToolbox.m new file mode 100644 index 0000000..8530a45 --- /dev/null +++ b/tools/tasks/testToolbox.m @@ -0,0 +1,21 @@ +function testToolbox(varargin) + installMatBox() + projectRootDirectory = bottools.projectdir(); + + addpath(fullfile(projectRootDirectory, 'code')) + botPrefs = bot.util.getPreferences(); + if botPrefs.CacheDirectory == "" || ~isfolder(botPrefs.CacheDirectory) + botPrefs.DialogMode = "Command Window"; + tempCache = fullfile(tempdir, 'bot_cache'); + if ~isfolder(tempCache) + fprintf('Making cache directory "%s"', tempCache) + mkdir(tempCache); + end + cleanupObj = onCleanup(@(fp) rmdir(tempCache, "s")); + botPrefs.CacheDirectory = tempCache; + botPrefs.AutoDownloadNwb = false; + disp(botPrefs) + end + + matbox.tasks.testToolbox(projectRootDirectory, varargin{:}) +end diff --git a/+bot/+internal/test.m b/tools/tests/test.m similarity index 98% rename from +bot/+internal/test.m rename to tools/tests/test.m index 2076b9a..554c415 100644 --- a/+bot/+internal/test.m +++ b/tools/tests/test.m @@ -4,6 +4,7 @@ % Todo: % [ ] set up test cache... % [ ] test live scripts + %% Test methods block methods (Test) @@ -328,9 +329,10 @@ function testFactoryBehaviorOnlySessions(testCase) end function testOphysQuickStart(testCase) - captured = evalc('run(''VisualCoding_OphysQuickstart.mlx'')'); - testCase.verifyClass(captured, 'char') - close all + quickStartPath = fullfile(bot.internal.util.toolboxdir, 'examples', 'VisualCoding_OphysQuickstart.mlx'); + captured = evalc('run(quickStartPath)'); + testCase.verifyClass(captured, 'char') + close all end end end \ No newline at end of file