Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
03d938e
Fix launch manager go
ogeesan Jul 26, 2025
4119aff
create stopProtocol
ogeesan Jul 28, 2025
2df0058
Create setupEmulator.m
ogeesan Jul 28, 2025
7387a49
Move MockBpodObject into +BpodTest
ogeesan Jul 28, 2025
1d21d7e
Use Status.Verbose for disp()
ogeesan Jul 28, 2025
8646fe3
Major refactor of protocol logic
ogeesan Jul 28, 2025
50df585
Use anonymous funcs for callbacks
ogeesan Jul 28, 2025
7f4011b
Save current protocol path into session data
ogeesan Jul 28, 2025
bb49aa4
Missing item
ogeesan Jul 28, 2025
3150f8b
Create tests
ogeesan Jul 28, 2025
76b543b
Improve addpath/rmpath for protocols
ogeesan Jul 28, 2025
01585b5
Improve verbosity handling
ogeesan Jul 28, 2025
708ee13
Move integration tests into GUI/non-GUI folders
ogeesan Jul 29, 2025
e1d4836
Use verbosity for EndBpod
ogeesan Jul 29, 2025
fecb398
Fix error with emulator dialog box
ogeesan Jul 29, 2025
2973d26
Add GUI refresh skip if running without GUI
ogeesan Aug 2, 2025
2ef0b77
Create BpodSystem setup and teardown
ogeesan Aug 2, 2025
2c23ea9
Create getPath.m
ogeesan Aug 2, 2025
6a2f5f9
Create test protocols
ogeesan Aug 2, 2025
7349c42
Use setup fixture funcs
ogeesan Aug 2, 2025
b1205ff
Create test_protocolLaunch.m
ogeesan Aug 2, 2025
4ffb9c9
Refactor environment setup into func
ogeesan Aug 2, 2025
b6f0f1a
Add integrations
ogeesan Aug 2, 2025
6620d3c
Fix adding of Tests to Path
ogeesan Aug 2, 2025
9fe90a1
Refactor setup/teardown
ogeesan Aug 2, 2025
9ba43da
Improve ordering
ogeesan Aug 2, 2025
dc9b35c
Remove global var for EMU setup
ogeesan Aug 2, 2025
1679cb2
Add Tests to source-folder
ogeesan Aug 2, 2025
3b8b5ec
Use getPath
ogeesan Aug 2, 2025
e3b9fad
Add Tests/ to Windows testing source
ogeesan Aug 2, 2025
9dd8d55
Create test_RunProtocol.m
ogeesan Aug 2, 2025
e090157
Create click.m
ogeesan Aug 2, 2025
db016f1
Refactor dummy protocol construction
ogeesan Aug 10, 2025
9910210
Rename test protocols
ogeesan Aug 10, 2025
4a6d124
Set existing BpodSystem verbosity 0
ogeesan Aug 10, 2025
b882cef
Add softcode handler test
ogeesan Aug 10, 2025
0b3a1ee
Close phone home box
ogeesan Aug 10, 2025
e282da6
Remove global
ogeesan Aug 10, 2025
4d6af38
Fix name
ogeesan Aug 10, 2025
22ff665
Update cases
ogeesan Aug 10, 2025
d40425d
Improve documentation
ogeesan Aug 11, 2025
964856d
Reduce real machine time requirement
ogeesan Aug 11, 2025
2de419d
Make liquid warning non-modal
ogeesan Aug 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/runAllTests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ jobs:
- name: Setup environment
uses: matlab-actions/run-command@v2
with:
command: addpath('Tests'); setupGithubEnvironment;
command: addpath('Tests/'); setupGithubEnvironment;

# Runs a set of commands using the runners shell
- name: Run all tests
uses: matlab-actions/run-tests@v2
with:
source-folder: Functions/
select-by-folder: Tests/BpodLib/
source-folder: Functions/; Tests/
select-by-folder: Tests/BpodLib/; Tests/Integrations/

test-windows:
runs-on: windows-latest
Expand All @@ -48,11 +48,11 @@ jobs:
- name: Setup environment
uses: matlab-actions/run-command@v2
with:
command: addpath('Tests'); setupGithubEnvironment;
command: addpath('Tests/'); setupGithubEnvironment;

# Runs a set of commands using the runners shell
- name: Run all tests
uses: matlab-actions/run-tests@v2
with:
source-folder: Functions/
select-by-folder: Tests/BpodLib/
source-folder: Functions/; Tests/
select-by-folder: Tests/BpodLib/; Tests/Integrations/
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.asv
.vscode
7 changes: 4 additions & 3 deletions Bpod.m
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,7 @@ function Bpod(varargin)
end
end
end
BpodLib.calibration.liquid.io.report(BpodSystem.CalibrationTables.LiquidCal)
BpodLib.path.verifyPathing(BpodSystem);


function emulator_setup(varargin)
% Runs setup with emulator mode flag set to 'true'.
Expand All @@ -119,10 +118,12 @@ function emulator_setup(varargin)
BpodSystem.SetupHardware();
BpodSystem.InitializeGUI();
BpodSystem.Status.Initialized = true;
BpodLib.calibration.liquid.io.report(BpodSystem.CalibrationTables.LiquidCal)
BpodLib.path.verifyPathing(BpodSystem);
evalin('base', 'global BpodSystem')

function emulator_dialog
% Launches a GUI indicating that hardware connection has failed.
% Launches a non-modal GUI indicating that hardware connection has failed.
% Prompts the user to start emulator mode or close the program.
global BpodSystem
BpodErrorSound;
Expand Down
8 changes: 4 additions & 4 deletions Functions/+BpodLib/+BpodObject/+setup/updatePathAndSettings.m
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ function updatePathAndSettings(BpodSystem, varargin)
if strcmp(BpodLib.calibration.liquid.utils.checkCOM(BpodSystem), 'no')
if p.Results.verbose
warning('BpodLib:Calibration:Liquid:CheckCOM', 'Calibration file does not match the detected state machine''s USB serial port.');
msg = msgbox(sprintf("Detected state machine USB serial port (%s) does not match the port used to create the current liquid calibration: (%s).\nPlease either initialize a multi-machine setup or re-run calibration.", ...
BpodLib.utils.getCurrentCOM(BpodSystem), BpodSystem.CalibrationTables.LiquidCal.metadata.COM), ...
'Calibration USB Port mismatch', 'warn', 'modal');
uiwait(msg)
BpodSystem.GUIHandles.LiquidCalWarningMessageBox = ...
msgbox(sprintf("Detected state machine USB serial port (%s) does not match the port used to create the current liquid calibration: (%s).\nPlease either initialize a multi-machine setup or re-run calibration.", ...
BpodLib.utils.getCurrentCOM(BpodSystem), BpodSystem.CalibrationTables.LiquidCal.metadata.COM), ...
'Calibration USB Port mismatch', 'warn', 'non-modal');
end
end
catch err
Expand Down
6 changes: 6 additions & 0 deletions Functions/+BpodLib/+launcher/+ui/loadProtocols.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
function loadProtocols(BpodSystem)
% Update the list of available protocols in the GUI

ProtocolNames = BpodLib.launcher.findProtocols(BpodSystem);
set(BpodSystem.GUIHandles.ProtocolSelector, 'String', ProtocolNames);
end
9 changes: 9 additions & 0 deletions Functions/+BpodLib/+launcher/+ui/loadSettings.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
function loadSettings(BpodSystem, protocolName, subjectName)
% Populate UI with settings files for the selected subject and protocol

settingsFileNames = BpodLib.launcher.findSettings(BpodSystem.Path.DataFolder, protocolName, subjectName);

set(BpodSystem.GUIHandles.SettingsSelector, 'String', settingsFileNames);
set(BpodSystem.GUIHandles.SettingsSelector,'Value',1);

end
9 changes: 9 additions & 0 deletions Functions/+BpodLib/+launcher/+ui/loadSubjects.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
function loadSubjects(BpodSystem, protocolName)
% Load all subjects in the data folder that have a folder for the given protocol

subjectNames = BpodLib.launcher.findSubjects(BpodSystem.Path.DataFolder, protocolName, BpodSystem.GUIData.DummySubjectString);

set(BpodSystem.GUIHandles.SubjectSelector,'String',subjectNames);
set(BpodSystem.GUIHandles.SubjectSelector,'Value',1);

end
14 changes: 14 additions & 0 deletions Functions/+BpodLib/+launcher/+ui/setDataFilePath.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
function setDataFilePath(BpodSystem, protocolName, subjectName)

dataFolder = BpodSystem.Path.DataFolder;
dataFilePath = BpodLib.launcher.createDataFilePath(dataFolder, protocolName, subjectName);
localDir = dataFolder(max(find(dataFolder(1:end-1) == filesep)+1):end);
[~, fileName, ext] = fileparts(dataFilePath);
fileName = [fileName ext];

BpodSystem.Path.CurrentDataFile = dataFilePath;

set(BpodSystem.GUIHandles.DataFilePathDisplay, 'String',...
[filesep fullfile(localDir, subjectName, protocolName, 'Session Data') filesep],'interpreter','none');
set(BpodSystem.GUIHandles.DataFileDisplay, 'String', fileName);
end
20 changes: 20 additions & 0 deletions Functions/+BpodLib/+launcher/createDataFilePath.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
function dataFilePath = createDataFilePath(dataFolder, protocolName, subjectName)
% Create a file path for the data file to be saved
%
% Inputs
% ------
% dataFolder : char
% The path to the data folder (e.g. Local Data/Data/)
% protocolName : char
% The name of the protocol
% subjectName : char
% The name of the subject

dateInfo = datestr(now, 30);
dateInfo(dateInfo == 'T') = '_';
fileName = [subjectName '_' protocolName '_' dateInfo '.mat'];


dataFilePath = fullfile(dataFolder, subjectName, protocolName, 'Session Data', fileName);

end
11 changes: 11 additions & 0 deletions Functions/+BpodLib/+launcher/createDefaultSettingsFile.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
function createDefaultSettingsFile(dataFolder, subjectName, protocolName)
% Create a default (empty) settings file for the given subject and protocol
% Only creates the file if it does not already exist

defaultSettingsFilePath = fullfile(dataFolder, subjectName, protocolName, 'Session Settings', 'DefaultSettings.mat');
if ~exist(defaultSettingsFilePath)
ProtocolSettings = struct;
save(defaultSettingsFilePath, 'ProtocolSettings')
end

end
50 changes: 50 additions & 0 deletions Functions/+BpodLib/+launcher/findProtocols.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
function ProtocolNames = findProtocols(BpodSystem)
% ProtocolNames = findProtocols(BpodSystem)
% Returns a cell array of protocol names found in the ProtocolFolder


if strcmp(BpodSystem.Path.ProtocolFolder, BpodSystem.SystemSettings.ProtocolFolder) % todo: make this less janky?
startPos = 3;
else
startPos = 2;
end
Candidates = dir(BpodSystem.Path.ProtocolFolder);
ProtocolNames = cell(0);
nProtocols = 0;
for x = startPos:length(Candidates)
if Candidates(x).isdir
ProtocolFolder = fullfile(BpodSystem.Path.ProtocolFolder, Candidates(x).name);
Contents = dir(ProtocolFolder);
nItems = length(Contents);
Found = 0;
for y = 3:nItems
if strcmp(Contents(y).name, [Candidates(x).name '.m'])
Found = 1;
end
end
if Found
ProtocolName = Candidates(x).name;
else
ProtocolName = ['<' Candidates(x).name '>'];
end
nProtocols = nProtocols + 1;
ProtocolNames{nProtocols} = ProtocolName;
end
end

if isempty(ProtocolNames)
ProtocolNames = {'No Protocols Found'};
else
% Sort to put organizing directories first
Types = ones(1,nProtocols);
for i = 1:nProtocols
ProtocolName = ProtocolNames{i};
if ProtocolName(1) == '<'
Types(i) = 0;
end
end
[a, Order] = sort(Types);
ProtocolNames = ProtocolNames(Order);
end

end
18 changes: 18 additions & 0 deletions Functions/+BpodLib/+launcher/findSettings.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
function settingsFileNames = findSettings(dataFolder, protocolName, subjectName)
% Find all settings files in the Settings folder for a given protocol and subject

settingsPath = fullfile(dataFolder, subjectName, protocolName, 'Session Settings');
candidates = dir(settingsPath);
nSettingsFiles = 0;
settingsFileNames = cell(1);
for x = 3:length(candidates)
extension = candidates(x).name;
extension = extension(end-2:end);
if strcmp(extension, 'mat')
nSettingsFiles = nSettingsFiles + 1;
name = candidates(x).name;
settingsFileNames{nSettingsFiles} = name(1:end-4);
end
end

end
21 changes: 21 additions & 0 deletions Functions/+BpodLib/+launcher/findSubjects.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
function subjectNames = findSubjects(dataFolder, protocolName, dummySubjectString)
% Find all subjects in the data folder that have a folder for the given protocol

candidateSubjects = dir(dataFolder);
subjectNames = cell(1);
nSubjects = 1;
subjectNames{1} = dummySubjectString;
for x = 1:length(candidateSubjects)
if x > 2
if candidateSubjects(x).isdir
if ~strcmp(candidateSubjects(x).name, dummySubjectString)
testpath = fullfile(dataFolder,candidateSubjects(x).name,protocolName);
if exist(testpath) == 7
nSubjects = nSubjects + 1;
subjectNames{nSubjects} = candidateSubjects(x).name;
end
end
end
end
end
end
Loading
Loading