diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..628ca34
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Data/**
+Calibration Files/**
\ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..b80dd73
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,10 @@
+[submodule "Protocols/Matching"]
+ path = Protocols/Matching
+ url = https://github.com/tsgouvea/BpodProtocols_Matching.git
+[submodule "Protocols/FI_2AFC"]
+ path = Protocols/FI_2AFC
+ url = https://github.com/tsgouvea/BpodProtocols_FI_2AFC.git
+[submodule "Protocols/Olf2AFC"]
+ path = Protocols/Olf2AFC
+ url = https://github.com/tsgouvea/BpodProtocols_Olf2AFC.git
+ branch = junya
diff --git a/Calibration Files/LiquidCalibration.mat b/Calibration Files/LiquidCalibration.mat
index b31c2a7..f08886c 100644
Binary files a/Calibration Files/LiquidCalibration.mat and b/Calibration Files/LiquidCalibration.mat differ
diff --git a/Functions/Internal Functions/FindArduinoPorts.m b/Functions/Internal Functions/FindArduinoPorts.m
index 8186193..c118f15 100644
--- a/Functions/Internal Functions/FindArduinoPorts.m
+++ b/Functions/Internal Functions/FindArduinoPorts.m
@@ -11,7 +11,20 @@
end
ArduinoPorts = ArduinoPorts(1:nPorts);
elseif ismac
-
+ [trash, RawSerialPortList] = system('ls /dev/tty.usbmodem*');
+ string = strtrim(RawSerialPortList);
+ PortStringPositions = strfind(string, '/dev/tty.usbmodem');
+ nPorts = length(PortStringPositions);
+ CandidatePorts = cell(1,nPorts);
+ nGoodPorts = 0;
+ for x = 1:nPorts
+ if PortStringPositions(x)+20 <= length(string)
+ CandidatePort = strtrim(string(PortStringPositions(x):PortStringPositions(x)+20));
+ nGoodPorts = nGoodPorts + 1;
+ CandidatePorts{nGoodPorts} = CandidatePort;
+ end
+ end
+ ArduinoPorts = CandidatePorts(1:nGoodPorts);
else
[trash, RawSerialPortList] = system('ls /dev/ttyACM*');
string = strtrim(RawSerialPortList);
diff --git a/Protocols/FI_2AFC b/Protocols/FI_2AFC
new file mode 160000
index 0000000..220128a
--- /dev/null
+++ b/Protocols/FI_2AFC
@@ -0,0 +1 @@
+Subproject commit 220128aea1a2bf67f90b87ba75242acaccd46957
diff --git a/Protocols/Light2AFC/Light2AFC.m b/Protocols/Light2AFC/Light2AFC.m
deleted file mode 100644
index 54e5f09..0000000
--- a/Protocols/Light2AFC/Light2AFC.m
+++ /dev/null
@@ -1,150 +0,0 @@
-%{
-----------------------------------------------------------------------------
-
-This file is part of the Sanworks Bpod repository
-Copyright (C) 2016 Sanworks LLC, Sound Beach, New York, USA
-
-----------------------------------------------------------------------------
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, version 3.
-
-This program is distributed WITHOUT ANY WARRANTY and without even the
-implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-%}
-function Light2AFC
-% This protocol is a starting point for a visual 2AFC task.
-% After initiating each trial with a center-poke,
-% the subject is rewarded for choosing the port that is lit.
-% Written by Josh Sanders, 5/2015.
-%
-% SETUP
-% You will need:
-% - A Bpod MouseBox (or equivalent) configured with 3 ports.
-% > Connect the left port in the box to Bpod Port#1.
-% > Connect the center port in the box to Bpod Port#2.
-% > Connect the right port in the box to Bpod Port#3.
-% > Make sure the liquid calibration tables for ports 1 and 3 have
-% calibration curves with several points surrounding 3ul.
-
-global BpodSystem
-
-%% Define parameters
-S = BpodSystem.ProtocolSettings; % Load settings chosen in launch manager into current workspace as a struct called S
-if isempty(fieldnames(S)) % If settings file was an empty struct, populate struct with default settings
- S.GUI.RewardAmount = 3; %ul
- S.GUI.CueDelay = 0.2; % How long the mouse must poke in the center to activate the goal port
- S.GUI.ResponseTime = 5; % How long until the mouse must make a choice, or forefeit the trial
- S.GUI.RewardDelay = 0; % How long the mouse must wait in the goal port for reward to be delivered
- S.GUI.PunishDelay = 3; % How long the mouse must wait in the goal port for reward to be delivered
-end
-
-% Initialize parameter GUI plugin
-BpodParameterGUI('init', S);
-
-%% Define trials
-MaxTrials = 1000;
-TrialTypes = ceil(rand(1,1000)*2);
-BpodSystem.Data.TrialTypes = []; % The trial type of each trial completed will be added here.
-
-%% Initialize plots
-BpodSystem.ProtocolFigures.SideOutcomePlotFig = figure('Position', [200 200 1000 200],'name','Outcome plot','numbertitle','off', 'MenuBar', 'none', 'Resize', 'off');
-BpodSystem.GUIHandles.SideOutcomePlot = axes('Position', [.075 .3 .89 .6]);
-SideOutcomePlot(BpodSystem.GUIHandles.SideOutcomePlot,'init',2-TrialTypes);
-BpodNotebook('init');
-
-%% Main trial loop
-for currentTrial = 1:MaxTrials
- S = BpodParameterGUI('sync', S); % Sync parameters with BpodParameterGUI plugin
- R = GetValveTimes(S.GUI.RewardAmount, [1 3]); LeftValveTime = R(1); RightValveTime = R(2); % Update reward amounts
- switch TrialTypes(currentTrial) % Determine trial-specific state matrix fields
- case 1
- LeftPokeAction = 'LeftRewardDelay'; RightPokeAction = 'Punish'; StimulusOutput = {'PWM1', 255};
- case 2
- LeftPokeAction = 'Punish'; RightPokeAction = 'RightRewardDelay'; StimulusOutput = {'PWM3', 255};
- end
- sma = NewStateMatrix(); % Assemble state matrix
- sma = AddState(sma, 'Name', 'WaitForPoke', ...
- 'Timer', 0,...
- 'StateChangeConditions', {'Port2In', 'CueDelay'},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'CueDelay', ...
- 'Timer', S.GUI.CueDelay,...
- 'StateChangeConditions', {'Port2Out', 'WaitForPoke', 'Tup', 'WaitForPortOut'},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'WaitForPortOut', ...
- 'Timer', 0,...
- 'StateChangeConditions', {'Port2Out', 'WaitForResponse'},...
- 'OutputActions', StimulusOutput);
- sma = AddState(sma, 'Name', 'WaitForResponse', ...
- 'Timer', S.GUI.ResponseTime,...
- 'StateChangeConditions', {'Port1In', LeftPokeAction, 'Port3In', RightPokeAction, 'Tup', 'exit'},...
- 'OutputActions', StimulusOutput);
- sma = AddState(sma, 'Name', 'LeftRewardDelay', ...
- 'Timer', S.GUI.RewardDelay,...
- 'StateChangeConditions', {'Tup', 'LeftReward', 'Port1Out', 'CorrectEarlyWithdrawal'},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'RightRewardDelay', ...
- 'Timer', S.GUI.RewardDelay,...
- 'StateChangeConditions', {'Tup', 'RightReward', 'Port3Out', 'CorrectEarlyWithdrawal'},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'LeftReward', ...
- 'Timer', LeftValveTime,...
- 'StateChangeConditions', {'Tup', 'Drinking'},...
- 'OutputActions', {'ValveState', 1});
- sma = AddState(sma, 'Name', 'RightReward', ...
- 'Timer', RightValveTime,...
- 'StateChangeConditions', {'Tup', 'Drinking'},...
- 'OutputActions', {'ValveState', 4});
- sma = AddState(sma, 'Name', 'Drinking', ...
- 'Timer', 0,...
- 'StateChangeConditions', {'Port1Out', 'DrinkingGrace', 'Port3Out', 'DrinkingGrace'},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'DrinkingGrace', ...
- 'Timer', .5,...
- 'StateChangeConditions', {'Tup', 'exit', 'Port1In', 'Drinking', 'Port3In', 'Drinking'},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'Punish', ...
- 'Timer', S.GUI.PunishDelay,...
- 'StateChangeConditions', {'Tup', 'exit'},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'CorrectEarlyWithdrawal', ...
- 'Timer', 0,...
- 'StateChangeConditions', {'Tup', 'exit'},...
- 'OutputActions', {});
- SendStateMatrix(sma);
- RawEvents = RunStateMatrix;
- if ~isempty(fieldnames(RawEvents)) % If trial data was returned
- BpodSystem.Data = AddTrialEvents(BpodSystem.Data,RawEvents); % Computes trial events from raw data
- BpodSystem.Data = BpodNotebook('sync', BpodSystem.Data); % Sync with Bpod notebook plugin
- BpodSystem.Data.TrialSettings(currentTrial) = S; % Adds the settings used for the current trial to the Data struct (to be saved after the trial ends)
- BpodSystem.Data.TrialTypes(currentTrial) = TrialTypes(currentTrial); % Adds the trial type of the current trial to data
- UpdateSideOutcomePlot(TrialTypes, BpodSystem.Data);
- SaveBpodSessionData; % Saves the field BpodSystem.Data to the current data file
- end
- HandlePauseCondition; % Checks to see if the protocol is paused. If so, waits until user resumes.
- if BpodSystem.BeingUsed == 0
- return
- end
-end
-
-function UpdateSideOutcomePlot(TrialTypes, Data)
-global BpodSystem
-Outcomes = zeros(1,Data.nTrials);
-for x = 1:Data.nTrials
- if ~isnan(Data.RawEvents.Trial{x}.States.Drinking(1))
- Outcomes(x) = 1;
- elseif ~isnan(Data.RawEvents.Trial{x}.States.Punish(1))
- Outcomes(x) = 0;
- elseif ~isnan(Data.RawEvents.Trial{x}.States.CorrectEarlyWithdrawal(1))
- Outcomes(x) = 2;
- else
- Outcomes(x) = 3;
- end
-end
-SideOutcomePlot(BpodSystem.GUIHandles.SideOutcomePlot,'update',Data.nTrials+1,2-TrialTypes,Outcomes);
diff --git a/Protocols/Matching b/Protocols/Matching
new file mode 160000
index 0000000..fa7219b
--- /dev/null
+++ b/Protocols/Matching
@@ -0,0 +1 @@
+Subproject commit fa7219b0a7030d1fdc300880c4f202cb34e216ec
diff --git a/Protocols/Olf2AFC b/Protocols/Olf2AFC
new file mode 160000
index 0000000..bd9b2e1
--- /dev/null
+++ b/Protocols/Olf2AFC
@@ -0,0 +1 @@
+Subproject commit bd9b2e111c656793654802a0f8fce498d3ee4ee2
diff --git a/Protocols/Operant/Operant.m b/Protocols/Operant/Operant.m
deleted file mode 100644
index 443af66..0000000
--- a/Protocols/Operant/Operant.m
+++ /dev/null
@@ -1,146 +0,0 @@
-%{
-----------------------------------------------------------------------------
-
-This file is part of the Sanworks Bpod repository
-Copyright (C) 2016 Sanworks LLC, Sound Beach, New York, USA
-
-----------------------------------------------------------------------------
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, version 3.
-
-This program is distributed WITHOUT ANY WARRANTY and without even the
-implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-%}
-function Operant
-% This protocol introduces a naive mouse to water available in ports 1 and 3.
-% Written by Josh Sanders, 5/2015.
-%
-% SETUP
-% You will need:
-% - A Bpod MouseBox (or equivalent) configured with 3 ports.
-% - Place masking tape over the center port (Port 2).
-
-global BpodSystem
-
-%% Define parameters
-S = BpodSystem.ProtocolSettings; % Load settings chosen in launch manager into current workspace as a struct called S
-if isempty(fieldnames(S)) % If settings file was an empty struct, populate struct with default settings
- S.GUI.CurrentBlock = 1; % Training level % 1 = Direct Delivery at both ports 2 = Poke for delivery
- S.GUI.RewardAmount = 5; %ul
- S.GUI.PortOutRegDelay = 0.5; % How long the mouse must remain out before poking back in
-end
-
-% Initialize parameter GUI plugin
-BpodParameterGUI('init', S);
-
-%% Define trials
-nSinglePokeTrials = 5; % Number of trials where each poke is rewarded
-nDoublePokeTrials = 5; % Number of trials requiring 2 pokes per reward
-nTriplePokeTrials = 5; % Number of trials requiring 3 pokes per reward
-nRandomTrials = 850; % Number of randomly interleaved single, double and triple poke trials
-MaxTrials = nSinglePokeTrials+nDoublePokeTrials+nTriplePokeTrials+nRandomTrials;
-TrialTypes = [ones(1,nSinglePokeTrials) ones(1,nDoublePokeTrials)*2 ones(1,nTriplePokeTrials)*3 ceil(rand(1,nRandomTrials)*3)];
-BpodSystem.Data.TrialTypes = []; % The trial type of each trial completed will be added here.
-
-%% Initialize plots
-% TrialType Outcome Plot (displays each future trial type, and scores completed trials as correct/incorrect
-BpodSystem.ProtocolFigures.OutcomePlotFig = figure('Position', [200 200 1000 200],'name','Outcome plot','numbertitle','off', 'MenuBar', 'none', 'Resize', 'off');
-BpodSystem.GUIHandles.OutcomePlot = axes('Position', [.075 .3 .89 .6]);
-TrialTypeOutcomePlot(BpodSystem.GUIHandles.OutcomePlot,'init',TrialTypes);
-% Bpod Notebook (to record text notes about the session or individual trials)
-BpodNotebook('init');
-
-%% Main trial loop
-for currentTrial = 1:MaxTrials
- S = BpodParameterGUI('sync', S); % Sync parameters with BpodParameterGUI plugin
- R = GetValveTimes(S.GUI.RewardAmount, [1 3]); LeftValveTime = R(1); RightValveTime = R(2); % Update reward amounts
- switch TrialTypes(currentTrial) % Determine trial-specific state matrix fields
- case 1
- StateOnLeftPoke1 = 'LeftReward'; StateOnRightPoke1 = 'RightReward';
- StateOnLeftPoke2 = 'LeftReward'; StateOnRightPoke2 = 'RightReward';
- case 2
- StateOnLeftPoke1 = 'WaitForPokeOut1'; StateOnRightPoke1 = 'WaitForPokeOut1';
- StateOnLeftPoke2 = 'LeftReward'; StateOnRightPoke2 = 'RightReward';
- case 3
- StateOnLeftPoke1 = 'WaitForPokeOut1'; StateOnRightPoke1 = 'WaitForPokeOut1';
- StateOnLeftPoke2 = 'WaitForPokeOut2'; StateOnRightPoke2 = 'WaitForPokeOut2';
- end
- sma = NewStateMatrix(); % Assemble state matrix
- sma = AddState(sma, 'Name', 'WaitForPoke1', ...
- 'Timer', 0,...
- 'StateChangeConditions', {'Port1In', StateOnLeftPoke1, 'Port3In', StateOnRightPoke1},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'WaitForPokeOut1', ...
- 'Timer', S.GUI.PortOutRegDelay,...
- 'StateChangeConditions', {'Port1Out', 'EnforcePokeOut1', 'Port3Out', 'EnforcePokeOut1'},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'EnforcePokeOut1', ...
- 'Timer', S.GUI.PortOutRegDelay,...
- 'StateChangeConditions', {'Tup', 'WaitForPoke2'},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'WaitForPoke2', ...
- 'Timer', 0,...
- 'StateChangeConditions', {'Port1In', StateOnLeftPoke2, 'Port3In', StateOnRightPoke2},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'WaitForPokeOut2', ...
- 'Timer', S.GUI.PortOutRegDelay,...
- 'StateChangeConditions', {'Port1Out', 'EnforcePokeOut2', 'Port3Out', 'EnforcePokeOut2'},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'EnforcePokeOut2', ...
- 'Timer', S.GUI.PortOutRegDelay,...
- 'StateChangeConditions', {'Tup', 'WaitForPoke3'},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'WaitForPoke3', ...
- 'Timer', 0,...
- 'StateChangeConditions', {'Port1In', 'LeftReward', 'Port3In', 'RightReward'},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'LeftReward', ...
- 'Timer', LeftValveTime,...
- 'StateChangeConditions', {'Tup', 'Drinking'},...
- 'OutputActions', {'ValveState', 1});
- sma = AddState(sma, 'Name', 'RightReward', ...
- 'Timer', RightValveTime,...
- 'StateChangeConditions', {'Tup', 'Drinking'},...
- 'OutputActions', {'ValveState', 4});
- sma = AddState(sma, 'Name', 'Drinking', ...
- 'Timer', 10,...
- 'StateChangeConditions', {'Tup', 'exit', 'Port1Out', 'ConfirmPortOut', 'Port3Out', 'ConfirmPortOut'},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'ConfirmPortOut', ...
- 'Timer', S.GUI.PortOutRegDelay,...
- 'StateChangeConditions', {'Tup', 'exit', 'Port1In', 'Drinking', 'Port3In', 'Drinking'},...
- 'OutputActions', {});
- SendStateMatrix(sma);
- RawEvents = RunStateMatrix;
- if ~isempty(fieldnames(RawEvents)) % If trial data was returned
- BpodSystem.Data = AddTrialEvents(BpodSystem.Data,RawEvents); % Computes trial events from raw data
- BpodSystem.Data = BpodNotebook('sync', BpodSystem.Data); % Sync with Bpod notebook plugin
- BpodSystem.Data.TrialSettings(currentTrial) = S; % Adds the settings used for the current trial to the Data struct (to be saved after the trial ends)
- BpodSystem.Data.TrialTypes(currentTrial) = TrialTypes(currentTrial); % Adds the trial type of the current trial to data
- UpdateOutcomePlot(TrialTypes, BpodSystem.Data);
- SaveBpodSessionData; % Saves the field BpodSystem.Data to the current data file
- end
- HandlePauseCondition; % Checks to see if the protocol is paused. If so, waits until user resumes.
- if BpodSystem.BeingUsed == 0
- return
- end
-end
-
-function UpdateOutcomePlot(TrialTypes, Data)
-% Determine outcomes from state data and score as the SideOutcomePlot plugin expects
-global BpodSystem
-Outcomes = zeros(1,Data.nTrials);
-for x = 1:Data.nTrials
- if ~isnan(Data.RawEvents.Trial{x}.States.Drinking(1))
- Outcomes(x) = 1;
- else
- Outcomes(x) = 3;
- end
-end
-TrialTypeOutcomePlot(BpodSystem.GUIHandles.OutcomePlot,'update',Data.nTrials+1,TrialTypes,Outcomes);
diff --git a/Protocols/PsychToolboxSound/PsychToolboxSound.m b/Protocols/PsychToolboxSound/PsychToolboxSound.m
deleted file mode 100644
index 5040bb5..0000000
--- a/Protocols/PsychToolboxSound/PsychToolboxSound.m
+++ /dev/null
@@ -1,191 +0,0 @@
-%{
-----------------------------------------------------------------------------
-
-This file is part of the Sanworks Bpod repository
-Copyright (C) 2016 Sanworks LLC, Sound Beach, New York, USA
-
-----------------------------------------------------------------------------
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, version 3.
-
-This program is distributed WITHOUT ANY WARRANTY and without even the
-implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-%}
-function PsychToolboxSound
-% This protocol demonstrates a 2AFC task using PsychToolbox to generate sound stimuli.
-% Subjects initialize each trial with a poke into port 2. After a delay, a tone plays.
-% Subjects are rewarded for responding left for low-pitch tones, and right for high.
-% Written by Josh Sanders, 4/2016
-%
-% SETUP
-% You will need:
-% - Windows 7 or Ubuntu 14.XX with the -lowlatency package installed
-% - ASUS Xonar DX 7-channel sound card installed. If using Windows, install
-% the drivers from the ASUS website, and configure the latency to 1ms in the ASUS config panel.
-% - PsychToolbox 3 installed
-% - The Xonar DX comes with an RCA cable. Use an RCA to BNC adapter to
-% connect channel 3 to one of Bpod's BNC input channels for a record of the
-% exact time each sound played.
-
-global BpodSystem
-
-%% Define parameters
-S = BpodSystem.ProtocolSettings; % Load settings chosen in launch manager into current workspace as a struct called S
-if isempty(fieldnames(S)) % If settings file was an empty struct, populate struct with default settings
- S.GUI.TrainingLevel = 2; % Configurable reward condition schemes. 'BothCorrect' rewards either side.
- S.GUIMeta.TrainingLevel.Style = 'popupmenu'; % the GUIMeta field is used by the ParameterGUI plugin to customize UI objects.
- S.GUIMeta.TrainingLevel.String = {'BothCorrect', '2AFC'};
- S.GUI.SoundDuration = 0.5; % Duration of sound (s)
- S.GUI.SinWaveFreqLeft = 500; % Frequency of left cue
- S.GUI.SinWaveFreqRight = 2000; % Frequency of right cue
- S.GUI.RewardAmount = 5; % in ul
- S.GUI.StimulusDelayDuration = 0; % Seconds before stimulus plays on each trial
- S.GUI.TimeForResponse = 5; % Seconds after stimulus sampling for a response
- S.GUI.PunishTimeoutDuration = 2; % Seconds to wait on errors before next trial can start
- S.GUI.PunishSound = 1; % if 1, plays a white noise pulse on error. if 0, no sound is played.
- S.GUIMeta.PunishSound.Style = 'checkbox';
- S.GUIPanels.Task = {'TrainingLevel', 'RewardAmount', 'PunishSound'}; % GUIPanels organize the parameters into groups.
- S.GUIPanels.Sound = {'SinWaveFreqLeft', 'SinWaveFreqRight', 'SoundDuration'};
- S.GUIPanels.Time = {'StimulusDelayDuration', 'TimeForResponse', 'PunishTimeoutDuration'};
-end
-
-% Initialize parameter GUI plugin
-BpodParameterGUI('init', S);
-
-%% Define trials
-MaxTrials = 5000;
-TrialTypes = ceil(rand(1,MaxTrials)*2);
-BpodSystem.Data.TrialTypes = []; % The trial type of each trial completed will be added here.
-
-%% Initialize plots
-% Side Outcome Plot
-BpodSystem.ProtocolFigures.SideOutcomePlotFig = figure('Position', [200 200 1000 200],'name','Outcome plot','numbertitle','off', 'MenuBar', 'none', 'Resize', 'off');
-BpodSystem.GUIHandles.SideOutcomePlot = axes('Position', [.075 .3 .89 .6]);
-SideOutcomePlot(BpodSystem.GUIHandles.SideOutcomePlot,'init',2-TrialTypes);
-% Bpod Notebook (to record text notes about the session or individual trials)
-BpodNotebook('init');
-% Total Reward display (online display of the total amount of liquid reward earned)
-TotalRewardDisplay('init');
-
-%% Define stimuli and send to sound server
-SF = 192000; % Sound card sampling rate
-LeftSound = GenerateSineWave(SF, S.GUI.SinWaveFreqLeft, S.GUI.SoundDuration); % Sampling freq (hz), Sine frequency (hz), duration (s)
-RightSound = GenerateSineWave(SF, S.GUI.SinWaveFreqRight, S.GUI.SoundDuration); % Sampling freq (hz), Sine frequency (hz), duration (s)
-PunishSound = (rand(1,SF*.5)*2) - 1;
-% Generate early withdrawal sound
-W1 = GenerateSineWave(SF, 1000, .5); W2 = GenerateSineWave(SF, 1200, .5); EarlyWithdrawalSound = W1+W2;
-P = SF/100; Interval = P;
-for x = 1:50 % Gate waveform to create pulses
- EarlyWithdrawalSound(P:P+Interval) = 0;
- P = P+(Interval*2);
-end
-
-% Program sound server
-PsychToolboxSoundServer('init')
-PsychToolboxSoundServer('Load', 1, LeftSound);
-PsychToolboxSoundServer('Load', 2, RightSound);
-PsychToolboxSoundServer('Load', 3, PunishSound);
-PsychToolboxSoundServer('Load', 4, EarlyWithdrawalSound);
-
-% Set soft code handler to trigger sounds
-BpodSystem.SoftCodeHandlerFunction = 'SoftCodeHandler_PlaySound';
-
-%% Main trial loop
-for currentTrial = 1:MaxTrials
- S = BpodParameterGUI('sync', S); % Sync parameters with BpodParameterGUI plugin
- LeftSound = GenerateSineWave(SF, S.GUI.SinWaveFreqLeft, S.GUI.SoundDuration); % Sampling freq (hz), Sine frequency (hz), duration (s)
- RightSound = GenerateSineWave(SF, S.GUI.SinWaveFreqRight, S.GUI.SoundDuration); % Sampling freq (hz), Sine frequency (hz), duration (s)
- PsychToolboxSoundServer('Load', 1, LeftSound);
- PsychToolboxSoundServer('Load', 2, RightSound);
- R = GetValveTimes(S.GUI.RewardAmount, [1 3]); LeftValveTime = R(1); RightValveTime = R(2); % Update reward amounts
- switch TrialTypes(currentTrial) % Determine trial-specific state matrix fields
- case 1
- OutputActionArgument = {'SoftCode', 1, 'BNCState', 1};
- LeftActionState = 'Reward'; RightActionState = 'Punish'; CorrectWithdrawalEvent = 'Port1Out';
- ValveCode = 1; ValveTime = LeftValveTime;
- case 2
- OutputActionArgument = {'SoftCode', 2, 'BNCState', 1};
- LeftActionState = 'Punish'; RightActionState = 'Reward'; CorrectWithdrawalEvent = 'Port3Out';
- ValveCode = 4; ValveTime = RightValveTime;
- end
- sma = NewStateMatrix(); % Assemble state matrix
- sma = AddState(sma, 'Name', 'WaitForCenterPoke', ...
- 'Timer', 0,...
- 'StateChangeConditions', {'Port2In', 'Delay'},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'Delay', ...
- 'Timer', S.GUI.StimulusDelayDuration,...
- 'StateChangeConditions', {'Tup', 'DeliverStimulus'},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'DeliverStimulus', ...
- 'Timer', S.GUI.SoundDuration,...
- 'StateChangeConditions', {'Tup', 'WaitForResponse', 'Port2Out', 'EarlyWithdrawal'},...
- 'OutputActions', OutputActionArgument);
- sma = AddState(sma, 'Name', 'EarlyWithdrawal', ...
- 'Timer', 0,...
- 'StateChangeConditions', {'Tup', 'EarlyWithdrawalPunish'},...
- 'OutputActions', {'SoftCode', 255});
- sma = AddState(sma, 'Name', 'WaitForResponse', ...
- 'Timer', S.GUI.TimeForResponse,...
- 'StateChangeConditions', {'Tup', 'exit', 'Port1In', LeftActionState, 'Port3In', RightActionState},...
- 'OutputActions', {'PWM1', 255, 'PWM3', 255});
- sma = AddState(sma, 'Name', 'Reward', ...
- 'Timer', ValveTime,...
- 'StateChangeConditions', {'Tup', 'Drinking'},...
- 'OutputActions', {'ValveState', ValveCode});
- sma = AddState(sma, 'Name', 'Drinking', ...
- 'Timer', 10,...
- 'StateChangeConditions', {'Tup', 'exit', CorrectWithdrawalEvent, 'exit'},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'Punish', ...
- 'Timer', S.GUI.PunishTimeoutDuration,...
- 'StateChangeConditions', {'Tup', 'exit'},...
- 'OutputActions', {'SoftCode', 3});
- sma = AddState(sma, 'Name', 'EarlyWithdrawalPunish', ...
- 'Timer', S.GUI.PunishTimeoutDuration,...
- 'StateChangeConditions', {'Tup', 'exit'},...
- 'OutputActions', {'SoftCode', 4});
- SendStateMatrix(sma); % Send the state matrix to the Bpod device
- RawEvents = RunStateMatrix; % Run the trial and return events
- if ~isempty(fieldnames(RawEvents)) % If trial data was returned (i.e. if not final trial, interrupted by user)
- BpodSystem.Data = AddTrialEvents(BpodSystem.Data,RawEvents); % Computes trial events from raw data
- BpodSystem.Data = BpodNotebook('sync', BpodSystem.Data); % Sync with Bpod notebook plugin
- BpodSystem.Data.TrialSettings(currentTrial) = S; % Adds the settings used for the current trial to the Data struct (to be saved after the trial ends)
- BpodSystem.Data.TrialTypes(currentTrial) = TrialTypes(currentTrial); % Adds the trial type of the current trial to data
- UpdateSideOutcomePlot(TrialTypes, BpodSystem.Data);
- UpdateTotalRewardDisplay(S.GUI.RewardAmount, currentTrial);
- SaveBpodSessionData; % Saves the field BpodSystem.Data to the current data file
- end
- HandlePauseCondition; % Checks to see if the protocol is paused. If so, waits until user resumes.
- if BpodSystem.BeingUsed == 0 % If protocol was stopped, exit the loop
- return
- end
-end
-
-function UpdateSideOutcomePlot(TrialTypes, Data)
-% Determine outcomes from state data and score as the SideOutcomePlot plugin expects
-global BpodSystem
-Outcomes = zeros(1,Data.nTrials);
-for x = 1:Data.nTrials
- if ~isnan(Data.RawEvents.Trial{x}.States.Reward(1))
- Outcomes(x) = 1;
- elseif ~isnan(Data.RawEvents.Trial{x}.States.Punish(1))
- Outcomes(x) = 0;
- else
- Outcomes(x) = 3;
- end
-end
-SideOutcomePlot(BpodSystem.GUIHandles.SideOutcomePlot,'update',Data.nTrials+1,2-TrialTypes,Outcomes);
-
-function UpdateTotalRewardDisplay(RewardAmount, currentTrial)
-% If rewarded based on the state data, update the TotalRewardDisplay
-global BpodSystem
- if ~isnan(BpodSystem.Data.RawEvents.Trial{currentTrial}.States.Reward(1))
- TotalRewardDisplay('add', RewardAmount);
- end
\ No newline at end of file
diff --git a/Protocols/PsychToolboxSound/SoftCodeHandler_PlaySound.m b/Protocols/PsychToolboxSound/SoftCodeHandler_PlaySound.m
deleted file mode 100644
index d3ba318..0000000
--- a/Protocols/PsychToolboxSound/SoftCodeHandler_PlaySound.m
+++ /dev/null
@@ -1,6 +0,0 @@
-function SoftCodeHandler_PlaySound(SoundID)
-if SoundID ~= 255
- PsychToolboxSoundServer('Play', SoundID);
-else
- PsychToolboxSoundServer('StopAll');
-end
\ No newline at end of file
diff --git a/Protocols/README.md b/Protocols/README.md
new file mode 100644
index 0000000..cc2d760
--- /dev/null
+++ b/Protocols/README.md
@@ -0,0 +1,2 @@
+# BpodProtocols
+Submodule for Bpod containing protocols
diff --git a/Protocols/ToneClouds4BPod/GenerateToneCloud.m b/Protocols/ToneClouds4BPod/GenerateToneCloud.m
deleted file mode 100644
index 3883030..0000000
--- a/Protocols/ToneClouds4BPod/GenerateToneCloud.m
+++ /dev/null
@@ -1,127 +0,0 @@
-function [out, cloud, cloud_toplot] = GenerateToneCloud(rewarded, r, StimSettings)
-%{
-GENERATETONECLOUD: Generates Cloud of tones
-
-This function is based on MakeToneCloud (written by P.Z.) which can be found in SoundSection.m
-Not all features have been imported to this version.
-
-% To do:
-error handling
-%}
-
-%r is as defined by PZ (0 to 1), 0 meaning that the probability of target and non target freq is the same
-
-global BpodSystem
-
-nTones = StimSettings.nTones;
-ToneOverlap = StimSettings.ToneOverlap;
-ToneDuration = StimSettings.ToneDuration;
-minFreq = StimSettings.minFreq;
-maxFreq = StimSettings.maxFreq;
-SamplingRate = StimSettings.SamplingRate;
-nTones_noEvidence = StimSettings.Noevidence;
-Volume = StimSettings.Volume;
-
-nFreq = StimSettings.nFreq; % Number of different frequencies to sample from
-toneFreq = logspace(log10(minFreq),log10(maxFreq),nFreq); % Nfreq logly distributed
-SoundCal = BpodSystem.CalibrationTables.SoundCal;
-toneAtt = polyval(SoundCal(1,1).Coefficient,toneFreq)';
-
-diffSPL = Volume - SoundCal(1,1).TargetSPL;
-attFactor = sqrt(10.^(diffSPL./10));
-
-att = toneAtt.*repmat(attFactor,nFreq,1);
-
-nTones_Evidence = nTones - nTones_noEvidence; % Number of tones with controlled evidence
-ramp = StimSettings.ramp; % Fraction of tone duration that is used for the envelope
-
-seed = 1;
-% if ~isnan(seed)
-% rand('twister',seed);
-% end
-
-noEvidence_ind = randi(nFreq,1,nTones_noEvidence); % Frequency indices of no evidence tones
-
-pTarget = (1/2+r/2);
-%boundy = [nFreq/3 2/3*nFreq]; % debugging purposes
-
-
-switch true
- case strcmp(rewarded,'low')
-
- Evidence_ind = randi(nFreq/3,1,nTones_Evidence)+nFreq*2/3; % Fill everything with nontarget (high)
-
- %this gives exactly the number of tones according to the pTarget
- %nTarget = round(nTones_Evidence*pTarget); % Number of tones with target frequencies
- %ind_replace = randperm(nTones_Evidence); % Indices to replace with target frequencies
- %Evidence_ind(ind_replace(1:nTarget))=randi(nFreq/3,1,nTarget); % Replace with target freqs (low)
-
- %this draws a independent random numbers for each slot
- %note that the amount of slots with target freq will vary from
- %trial to trial, even when the same pTarget
- ind_replace = find(rand(1,nTones_Evidence) -1;
- SideList = SideList(ValidTrials);
- OutcomeRecord = OutcomeRecord(ValidTrials);
- SidedEvidenceStrength = SidedEvidenceStrength(ValidTrials);
- nTrials = sum(ValidTrials);
- LeftTrials = zeros(1,nTrials);
- LeftTrials((SideList == 0) & (OutcomeRecord == 1)) = 1;
- LeftTrials((SideList == 0) & (OutcomeRecord == 0)) = 0;
- LeftTrials((SideList == 1) & (OutcomeRecord == 1)) = 0;
- LeftTrials((SideList == 1) & (OutcomeRecord == 0)) = 1;
-
- Xdata = BpodSystem.GUIHandles.PsychometricData(:,1);
- Ydata = BpodSystem.GUIHandles.PsychometricData(:,2);
- nBins = length(Xdata);
- for i = 1:nBins
- Ydata(i) = mean(LeftTrials(SidedEvidenceStrength==Xdata(i)));
- end
-
- set(BpodSystem.GUIHandles.PsychometricLine, 'xdata', Xdata, 'ydata', Ydata);
- BpodSystem.GUIHandles.PsychometricData(:,1) = Xdata;
- BpodSystem.GUIHandles.PsychometricData(:,2) = Ydata;
- set(AxesHandle,'XLim',[-1 1], 'Ylim', [0 1]);
-end
-
-end
-
diff --git a/Protocols/ToneClouds4BPod/SoftCodeHandler_PlaySound.m b/Protocols/ToneClouds4BPod/SoftCodeHandler_PlaySound.m
deleted file mode 100644
index d3ba318..0000000
--- a/Protocols/ToneClouds4BPod/SoftCodeHandler_PlaySound.m
+++ /dev/null
@@ -1,6 +0,0 @@
-function SoftCodeHandler_PlaySound(SoundID)
-if SoundID ~= 255
- PsychToolboxSoundServer('Play', SoundID);
-else
- PsychToolboxSoundServer('StopAll');
-end
\ No newline at end of file
diff --git a/Protocols/ToneClouds4BPod/StimulusPlot.m b/Protocols/ToneClouds4BPod/StimulusPlot.m
deleted file mode 100644
index 45fac09..0000000
--- a/Protocols/ToneClouds4BPod/StimulusPlot.m
+++ /dev/null
@@ -1,59 +0,0 @@
-
-function StimulusPlot(AxesHandle, Action, varargin)
-%%
-% Plug in to Plot Stimulus
-% AxesHandle = handle of axes to plot on
-% Action = specific action for plot, "init" - initialize OR "update" - update plot
-
-%Example usage:
-% StimulusPlot(AxesHandle,'init',Stimulus)
-
-% Fede
-
-%% Code Starts Here
-global BpodSystem
-
-switch Action
- case 'init'
- %initialize pokes plot
-
- axes(AxesHandle);
-
- nStim = varargin{1};
-
- %plot in specified axes
-
- for i=1:nStim
- BpodSystem.GUIHandles.Stimulus(i) = line([0 0],[0 0]);
- end
-
- BpodSystem.GUIHandles.RTline = line([0/0 0/0],[0 18],'Color',[1 0 0]);
-
- ylabel(AxesHandle, 'Frequency', 'FontSize', 18);
- xlabel(AxesHandle, 'Time', 'FontSize', 18);
- hold(AxesHandle, 'on');
-
- case 'update'
-
- Stimulus = varargin{1};
- StimulusDetails = varargin{2};
-
- for i=1:size(BpodSystem.GUIHandles.Stimulus,2)
- set(BpodSystem.GUIHandles.Stimulus(i),'XData', (1:size(Stimulus,2))/1920);
- set(BpodSystem.GUIHandles.Stimulus(i),'YData',Stimulus(i,:));
- if length(varargin)>2
- tDeliverStimulus = varargin{3};
- set(BpodSystem.GUIHandles.RTline,'XData',[tDeliverStimulus tDeliverStimulus]);
- end
- end
-
- set(BpodSystem.GUIHandles.StimulusPlot,'YLim',[1 18],'XLim', [1 size(Stimulus,2)]/1920);
-
- title_str = [];
- fnames = fields(StimulusDetails);
- for i=1:length(fnames)
- title_str = [title_str ' ' fnames{i} ': ' num2str(StimulusDetails.(fnames{i}),'%2.2f')];
- end
- set(get(BpodSystem.GUIHandles.StimulusPlot, 'Title'), 'String', title_str);
-end
-
diff --git a/Protocols/ToneClouds4BPod/TC4B_PulsePalProgram.mat b/Protocols/ToneClouds4BPod/TC4B_PulsePalProgram.mat
deleted file mode 100644
index c12206c..0000000
Binary files a/Protocols/ToneClouds4BPod/TC4B_PulsePalProgram.mat and /dev/null differ
diff --git a/Protocols/ToneClouds4BPod/ToneClouds4BPod.m b/Protocols/ToneClouds4BPod/ToneClouds4BPod.m
deleted file mode 100644
index 6e38af3..0000000
--- a/Protocols/ToneClouds4BPod/ToneClouds4BPod.m
+++ /dev/null
@@ -1,475 +0,0 @@
-function ToneClouds4BPod
-
-% This protocol implements ToneClouds (developed by P. Znamenskiy) on Bpod
-% Based on PsychoToolboxSound (written by J.Sanders)
-
-% Written by F.Carnevale, 2/2015.
-% Modified by J. Sanders 3/2016.
-
-global BpodSystem
-
-%% Define parameters
-S = BpodSystem.ProtocolSettings; % Load settings chosen in launch manager into current workspace as a struct called S
-if isempty(fieldnames(S)) % If settings file was an empty struct, populate struct with default settings
- % Stimulation Parameters
- S.GUI.UseStimulation = 0;
- S.GUIMeta.UseStimulation.Style = 'checkbox';
- S.GUI.TrainDelay = 0.008;
- S.GUI.PulseWidth = 0.001;
- S.GUI.PulseInterval = 0.1;
- S.GUI.StimProbability = 1;
- S.GUIPanels.Stimulation = {'UseStimulation', 'TrainDelay', 'PulseWidth', 'PulseInterval', 'StimProbability'};
-
- % Protocol parameters
- % 1. Define parameters and values (with legacy syntax)
- S.GUI.Subject = BpodSystem.GUIData.SubjectName;
- S.GUI.Stage = 3;
- % 2. Parameter types and meta-data (assumes "edit" style if no meta info is specified)
- S.GUIMeta.Stage.Style = 'popupmenu';
- S.GUIMeta.Stage.String = {'Direct', 'NextCorrectPoke', 'OnlyCorrectPoke'};
- % Assigns each parameter to a panel on the GUI (assumes "Parameters" panel if not specified)
- S.GUIPanels.Protocol = {'Subject', 'Stage'};
-
- % Stimulus parameters
- S.GUI.UseMiddleOctave = 1;
- S.GUI.DifficultyLow = 1;
- S.GUI.DifficultyHigh = 1;
- S.GUI.nDifficulties = 0;
- S.GUI.ToneOverlap = 0;
- S.GUI.ToneDuration = 0.03;
- S.GUI.SoundMaxDuration = 1;
- S.GUI.NoEvidence = 0;
- S.GUI.AudibleHuman = 1;
- S.GUI.UseMiddleOctave = 1;
- S.GUIMeta.UseMiddleOctave.Style = 'popupmenu';
- S.GUIMeta.UseMiddleOctave.String = {'no', 'yes'};
- S.GUIMeta.AudibleHuman.Style = 'checkbox';
- S.GUIPanels.StimulusSettings = {'UseMiddleOctave', 'DifficultyLow', 'DifficultyHigh', 'nDifficulties'...
- 'ToneOverlap', 'ToneDuration', 'SoundMaxDuration', 'NoEvidence', 'AudibleHuman'};
-
- % Reward parameters
- S.GUI.RewardAmount = 2.5;
- S.GUI.PunishSound = 1;
- S.GUI.FreqSide = 1;
- S.GUIMeta.FreqSide.Style = 'popupmenu';
- S.GUIMeta.FreqSide.String = {'LowLeft', 'LowRight'};
- S.GUIMeta.PunishSound.Style = 'checkbox';
- S.GUIPanels.RewardSettings = {'RewardAmount', 'FreqSide', 'PunishSound'};
-
- % Trial structure
- S.GUI.TimeForResponse = 10;
- S.GUI.TimeForReversal = 5;
- S.GUI.TimeoutDuration = 4;
- S.GUIPanels.TrialStructure = {'TimeForResponse', 'TimeForReversal', 'TimeoutDuration'};
-
- % Prestimulus delay
- S.GUI.PrestimDistribution = 1;
- S.GUIMeta.PrestimDistribution.Style = 'popupmenu';
- S.GUIMeta.PrestimDistribution.String = {'Delta', 'Uniform', 'Exponential'};
- S.GUI.PrestimDurationStart = 0.050;
- S.GUI.PrestimDurationEnd = 0.050;
- S.GUI.PrestimDurationStep = 0.050;
- S.GUI.PrestimDurationNtrials = 50;
- S.GUI.PrestimDurationCurrent = S.GUI.PrestimDurationStart;
- S.GUIMeta.PrestimDurationCurrent.Style = 'text';
- S.GUIPanels.PrestimulusDelay = {'PrestimDistribution', 'PrestimDurationStart', 'PrestimDurationEnd',...
- 'PrestimDurationStep', 'PrestimDurationNtrials', 'PrestimDurationCurrent'};
-
- % Antibias
- S.GUI.Antibias = 1;
- S.GUIMeta.Antibias.Style = 'popupmenu';
- S.GUIMeta.Antibias.String = {'no', 'yes'};
- S.GUIPanels.Antibias = {'Antibias'};
-
-end
-% Set frequency range
-if S.GUI.AudibleHuman
- minFreq = 2000; maxFreq = 10000;
-else
- minFreq = 5000; maxFreq = 40000;
-end
-% Blank Pulse Pal Parameters
-S.InitialPulsePalParameters = struct;
-% Other Stimulus settings (not in the GUI)
-StimulusSettings.ToneOverlap = S.GUI.ToneOverlap;
-StimulusSettings.ToneDuration = S.GUI.ToneDuration;
-StimulusSettings.minFreq = minFreq;
-StimulusSettings.maxFreq = maxFreq;
-StimulusSettings.SamplingRate = 192000; % Sound card sampling rate;
-StimulusSettings.UseMiddleOctave = S.GUIMeta.UseMiddleOctave(S.GUI.UseMiddleOctave);
-StimulusSettings.Noevidence = S.GUI.NoEvidence;
-StimulusSettings.nFreq = 18; % Number of different frequencies to sample from
-StimulusSettings.ramp = 0.005;
-StimulusSettings.Volume = 60;
-
-%% Define trials
-MaxTrials = 5000;
-TrialTypes = ceil(rand(1,MaxTrials)*2); % correct side for each trial
-EvidenceStrength = nan(1,MaxTrials); % evidence strength for each trial
-PrestimDuration = nan(1,MaxTrials); % prestimulation delay period for each trial
-Outcomes = nan(1,MaxTrials);
-StimulationTrials = zeros(1,MaxTrials);
-AccumulatedReward=0;
-
-BpodSystem.Data.TrialTypes = []; % The trial type of each trial completed will be added here.
-BpodSystem.Data.EvidenceStrength = []; % The evidence strength of each trial completed will be added here.
-BpodSystem.Data.PrestimDuration = []; % The evidence strength of each trial completed will be added here.
-BpodSystem.Data.StimulationTrials = [];
-
-%% Initialize plots
-
-% Initialize parameter GUI plugin
-BpodParameterGUI('init', S);
-
-% Outcome plot
-BpodSystem.ProtocolFigures.OutcomePlotFig = figure('Position', [50 50 1000 163],'name','Outcome plot','numbertitle','off', 'MenuBar', 'none', 'Resize', 'off');
-BpodSystem.GUIHandles.OutcomePlot = axes('Position', [.075 .3 .89 .6]);
-OutcomePlot(BpodSystem.GUIHandles.OutcomePlot,'init',2-TrialTypes);
-
-% Notebook
-%BpodNotebook('init');
-
-% Performance
-% PerformancePlot(BpodSystem.GUIHandles.PerformancePlot,'init');
-SlidingWindowSize = 30; % Size of sliding window average, units = trials
-TrialGroups{1} = [1]; TrialGroups{2} = [2]; % Groups of trial types to plot %correct
-TrialGroupNames{1} = 'Left'; TrialGroupNames{2} = 'Right'; % Names of consecutive groups
-PerformancePlot('init', TrialGroups, TrialGroupNames, SlidingWindowSize);
-
-% Psychometric
-BpodSystem.ProtocolFigures.PsychoPlotFig = figure('Position', [50 50 400 300],'name','Pshycometric plot','numbertitle','off', 'MenuBar', 'none', 'Resize', 'off');
-BpodSystem.GUIHandles.PsychoPlot = axes('Position', [.2 .25 .75 .65]);
-PsychoPlot(BpodSystem.GUIHandles.PsychoPlot,'init');
-
-% Stimulus plot
-%BpodSystem.ProtocolFigures.StimulusPlotFig = figure('Position', [50 50 500 300],'name','Stimulus plot','numbertitle','off', 'MenuBar', 'none', 'Resize', 'off');
-%BpodSystem.GUIHandles.StimulusPlot = axes('Position', [.15 .2 .75 .65]);
-%StimulusPlot(BpodSystem.GUIHandles.StimulusPlot,'init',StimulusSettings.nFreq);
-
-%%% Pokes plot
-state_colors = struct( ...
- 'WaitForCenterPoke', [0.5 0.5 1],...
- 'Delay',0.3*[1 1 1],...
- 'DeliverStimulus', 0.75*[1 1 0],...
- 'GoSignal',[0.5 1 1],...
- 'WaitForLeftPoke',[.2,.2,1],...
- 'WaitForRightPoke',[.7,.7,1],...
- 'Reward',[0,1,0],...
- 'Drinking',[0,0,1],...
- 'Punish',[1,0,0],...
- 'EarlyWithdrawal',[1,0.3,0],...
- 'EarlyWithdrawalPunish',[1,0,0],...
- 'WaitForResponse',0.75*[0,1,1],...
- 'CorrectWithdrawalEvent',[1,0,0],...
- 'exit',0.2*[1 1 1]);
-
-poke_colors = struct( ...
- 'L', 0.6*[1 0.66 0], ...
- 'C', [0 0 0], ...
- 'R', 0.9*[1 0.66 0]);
-
-PokesPlot('init', state_colors, poke_colors);
-
-
-%% Define stimuli and send to sound server
-
-SF = StimulusSettings.SamplingRate;
-AttenuationFactor = .5;
-PunishSound = (rand(1,SF*.5)*AttenuationFactor) - AttenuationFactor*.5;
-
-% Program sound server
-PsychToolboxSoundServer('init')
-PsychToolboxSoundServer('Load', 2, 0);
-PsychToolboxSoundServer('Load', 3, PunishSound);
-
-% Set soft code handler to trigger sounds
-BpodSystem.SoftCodeHandlerFunction = 'SoftCodeHandler_PlaySound';
-
-BpodSystem.ProtocolFigures.InitialMsg = msgbox({'', ' Edit your settings and click OK when you are ready to start! ', ''},'ToneCloud Protocol...');
-
-uiwait(BpodSystem.ProtocolFigures.InitialMsg);
-S = BpodParameterGUI('sync', S); % Sync parameters with BpodParameterGUI plugin
-UsingStimulation = 0;
-if S.GUI.UseStimulation
- PulsePal;
- load TC4B_PulsePalProgram;
- ProgramPulsePal(ParameterMatrix);
- S.InitialPulsePalParameters = ParameterMatrix;
- UsingStimulation = 1;
-end
-% Set timer for this session
-SessionBirthdate = tic;
-
-% Control the step up of prestimulus period and stimulus duration
-controlStep_Prestim = 0; % valid trial counter
-tic
-%% Main trial loop
-for currentTrial = 1:MaxTrials
-
- S = BpodParameterGUI('sync', S); % Sync parameters with BpodParameterGUI plugin
-
- if S.GUI.UseStimulation
- StimulationTrials(currentTrial) = rand < S.GUI.StimProbability;
- if (~UsingStimulation)
- PulsePal;
- load TC4B_PulsePalProgram;
- ProgramPulsePal(ParameterMatrix);
- S.InitialPulsePalParameters = ParameterMatrix;
- UsingStimulation = 1;
- end
- ProgramPulsePalParam(1, 'Phase1Duration', S.GUI.PulseWidth);
- ProgramPulsePalParam(1, 'InterPulseInterval', S.GUI.PulseInterval);
- ProgramPulsePalParam(1, 'PulseTrainDelay', S.GUI.TrainDelay);
- if StimulationTrials(currentTrial)
- ProgramPulsePalParam(1,'LinkTriggerChannel1', 1);
- else
- ProgramPulsePalParam(1,'LinkTriggerChannel1', 0);
- end
- else
- if UsingStimulation
- ProgramPulsePalParam(1,'LinkTriggerChannel1', 0);
- UsingStimulation = 0;
- end
- StimulationTrials(currentTrial) = 0;
- end
- if S.GUI.AudibleHuman, minFreq = 200; maxFreq = 2000; else minFreq = 5000; maxFreq = 40000; end
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %Prestimulation Duration
-
- if currentTrial==1 %start from the start
- S.GUI.PrestimDurationCurrent = S.GUI.PrestimDurationStart;
- end
-
- controlStep_nRequiredValid_Prestim = S.GUI.PrestimDurationNtrials;
-
- if S.GUI.PrestimDurationStart controlStep_nRequiredValid_Prestim
-
- controlStep_Prestim = 0; %restart counter
-
- % step up, unless we are at the max
- if S.GUI.PrestimDurationCurrent + S.GUI.PrestimDurationStep > S.GUI.PrestimDurationEnd
- S.GUI.PrestimDurationCurrent = S.GUI.PrestimDurationEnd;
- else
- S.GUI.PrestimDurationCurrent = S.GUI.PrestimDurationCurrent + S.GUI.PrestimDurationStep;
- end
- end
- else
- S.GUI.PrestimDurationCurrent = S.GUI.PrestimDurationStart;
- end
-
-
- switch S.GUI.PrestimDistribution
- case 1
- PrestimDuration(currentTrial) = S.GUI.PrestimDurationCurrent;
- case 2'
- PrestimDuration(currentTrial) = rand+S.GUI.PrestimDurationCurrent-0.5;
- case 3
- PrestimDuration(currentTrial) = exprnd(S.GUI.PrestimDurationCurrent);
- end
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
- R = BpodLiquidCalibration('GetValveTimes', S.GUI.RewardAmount, [1 3]); % Update reward amounts
- LeftValveTime = R(1); RightValveTime = R(2);
-
- % Update stimulus settings
- StimulusSettings.nTones = floor((S.GUI.SoundMaxDuration-S.GUI.ToneDuration*S.GUI.ToneOverlap)/(S.GUI.ToneDuration*(1-S.GUI.ToneOverlap)));
- StimulusSettings.ToneOverlap = S.GUI.ToneOverlap;
- StimulusSettings.ToneDuration = S.GUI.ToneDuration;
- StimulusSettings.minFreq = minFreq;
- StimulusSettings.maxFreq = maxFreq;
- StimulusSettings.UseMiddleOctave = S.GUI.UseMiddleOctave(S.GUI.UseMiddleOctave);
- StimulusSettings.Noevidence = S.GUI.NoEvidence;
- StimulusSettings.Volume = 60;
-
- switch TrialTypes(currentTrial) % Determine trial-specific state matrix fields
-
- case 1 % Left is rewarded
- if strcmp(S.GUIMeta.FreqSide.String{S.GUI.FreqSide},'LowLeft')
- TargetOctave = 'low';
- else
- TargetOctave = 'high';
- end
-
- LeftActionState = 'Reward';
- if S.GUI.Stage == 3
- RightActionState = 'Punish';
- else
- RightActionState = 'WaitForLeftPoke';
- end
- CorrectWithdrawalEvent = 'Port1Out';
- ValveCode = 1; ValveTime = LeftValveTime;
-
- case 2 % Right is rewarded
-
- if strcmp(S.GUIMeta.FreqSide.String{S.GUI.FreqSide},'LowRight')
- TargetOctave = 'low';
- else
- TargetOctave = 'high';
- end
-
- if S.GUI.Stage == 3
- LeftActionState = 'Punish';
- else
- LeftActionState = 'WaitForRightPoke';
- end
- RightActionState = 'Reward';
- CorrectWithdrawalEvent = 'Port3Out';
- ValveCode = 4; ValveTime = RightValveTime;
- end
-
- if S.GUI.PunishSound
- PsychToolboxSoundServer('Load', 3, PunishSound);
- else
- PsychToolboxSoundServer('Load', 3, 0);
- end
-
- switch S.GUI.Stage
-
- case 1 % Training stage 1: Direct sides - Poke and collect water
-% S.GUI.DifficultyLow.enable = 'off';
-% S.GUI.DifficultyHigh.enable = 'off';
-% S.GUI.nDifficulties.enable = 'off';
- S.GUI.TimeoutDuration = 0;
-% S.GUI.TimeoutDuration.enable = 'off';
- EvidenceStrength(currentTrial) = 1;
- StimulusStateChangeConditions = {'Tup', 'Reward'};
- PostRewardState = 'exit';
- case 2 % Training stage 2: Full task, but may switch error to correct choice
- DifficultySet = [S.GUI.DifficultyLow S.GUI.DifficultyLow:(S.GUI.DifficultyHigh-S.GUI.DifficultyLow)/(S.GUI.nDifficulties-1):S.GUI.DifficultyHigh S.GUI.DifficultyHigh];
- DifficultySet = unique(DifficultySet);
- EvidenceStrength(currentTrial) = DifficultySet(randi(size(DifficultySet,2)));
- StimulusStateChangeConditions = {'Port2Out', 'WaitForResponse'};
- PostRewardState = 'Drinking';
- case 3 % Full task
- DifficultySet = [S.GUI.DifficultyLow S.GUI.DifficultyLow:(S.GUI.DifficultyHigh-S.GUI.DifficultyLow)/(S.GUI.nDifficulties-1):S.GUI.DifficultyHigh S.GUI.DifficultyHigh];
- DifficultySet = unique(DifficultySet);
- EvidenceStrength(currentTrial) = DifficultySet(randi(size(DifficultySet,2)));
- StimulusStateChangeConditions = {'Port2Out', 'WaitForResponse'};
- PostRewardState = 'Drinking';
- end
-
- [Sound, Cloud, Cloud_toplot] = GenerateToneCloud(TargetOctave, EvidenceStrength(currentTrial), StimulusSettings);
- PsychToolboxSoundServer('Load', 1, Sound);
-
- sma = NewStateMatrix(); % Assemble state matrix
-
- sma = AddState(sma, 'Name', 'WaitForCenterPoke', ...
- 'Timer', 0,...
- 'StateChangeConditions', {'Port2In', 'Delay'},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'Delay', ...
- 'Timer', PrestimDuration(currentTrial),...
- 'StateChangeConditions', {'Tup', 'DeliverStimulus', 'Port2Out', 'EarlyWithdrawal'},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'DeliverStimulus', ...
- 'Timer', S.GUI.SoundMaxDuration,...
- 'StateChangeConditions', StimulusStateChangeConditions,...
- 'OutputActions', {'SoftCode', 1, 'BNCState', UsingStimulation});
- sma = AddState(sma, 'Name', 'EarlyWithdrawal', ...
- 'Timer', 0,...
- 'StateChangeConditions', {'Tup', 'EarlyWithdrawalPunish'},...
- 'OutputActions', {'SoftCode', 255, 'BNCState', 0});
- sma = AddState(sma, 'Name', 'WaitForResponse', ...
- 'Timer', S.GUI.TimeForResponse,...
- 'StateChangeConditions', {'Tup', 'exit', 'Port1In', LeftActionState, 'Port3In', RightActionState},...
- 'OutputActions', {'SoftCode', 255, 'BNCState', 0});
- sma = AddState(sma, 'Name', 'WaitForLeftPoke', ...
- 'Timer', S.GUI.TimeForReversal,...
- 'StateChangeConditions', {'Tup', 'Punish', 'Port1In', 'Reward'}, ...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'WaitForRightPoke', ...
- 'Timer', S.GUI.TimeForReversal,...
- 'StateChangeConditions', {'Tup', 'Punish', 'Port3In', 'Reward'}, ...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'Reward', ...
- 'Timer', ValveTime,...
- 'StateChangeConditions', {'Tup', PostRewardState},...
- 'OutputActions', {'ValveState', ValveCode});
- sma = AddState(sma, 'Name', 'Drinking', ...
- 'Timer', 10,...
- 'StateChangeConditions', {CorrectWithdrawalEvent, 'exit', 'Tup', 'exit'},...
- 'OutputActions', {});
- sma = AddState(sma, 'Name', 'Punish', ...
- 'Timer', S.GUI.TimeoutDuration,...
- 'StateChangeConditions', {'Tup', 'exit'},...
- 'OutputActions', {'SoftCode', 3});
- sma = AddState(sma, 'Name', 'EarlyWithdrawalPunish', ...
- 'Timer', S.GUI.TimeoutDuration,...
- 'StateChangeConditions', {'Tup', 'exit'},...
- 'OutputActions', {});
-
- SendStateMatrix(sma);
- RawEvents = RunStateMatrix;
-
- if ~isempty(fieldnames(RawEvents)) % If trial data was returned
- BpodSystem.Data = AddTrialEvents(BpodSystem.Data,RawEvents); % Computes trial events from raw data
- %BpodSystem.Data = BpodNotebook('sync', BpodSystem.Data); % Sync with Bpod notebook plugin
- BpodSystem.Data.TrialSettings(currentTrial) = S; % Adds the settings used for the current trial to the Data struct (to be saved after the trial ends)
- BpodSystem.Data.TrialTypes(currentTrial) = TrialTypes(currentTrial); % Adds the trial type of the current trial to data
- BpodSystem.Data.EvidenceStrength(currentTrial) = EvidenceStrength(currentTrial); % Adds the evidence strength of the current trial to data
- BpodSystem.Data.StimulationTrials(currentTrial) = StimulationTrials(currentTrial);
- BpodSystem.Data.PrestimDuration(currentTrial) = PrestimDuration(currentTrial); % Adds the evidence strength of the current trial to data
- BpodSystem.Data.StimulusSettings = StimulusSettings; % Save Stimulus settings
- BpodSystem.Data.Cloud{currentTrial} = Cloud; % Saves Stimulus
-
- %Outcome
- if ~isnan(BpodSystem.Data.RawEvents.Trial{currentTrial}.States.Reward(1))
- Outcomes(currentTrial) = 1;
- AccumulatedReward = AccumulatedReward+S.GUI.RewardAmount;
- controlStep_Prestim = controlStep_Prestim+1; % update because this is a valid trial
- %controlStep_Sound = controlStep_Sound+1; % update because this is a valid trial
- elseif ~isnan(BpodSystem.Data.RawEvents.Trial{currentTrial}.States.Punish(1))
- Outcomes(currentTrial) = 0;
- controlStep_Prestim = controlStep_Prestim+1; % update because this is a valid trial
- %controlStep_Sound = controlStep_Sound+1; % update because this is a valid trial
- else
- Outcomes(currentTrial) = -1;
- end
-
- BpodSystem.Data.Outcomes(currentTrial) = Outcomes(currentTrial);
- BpodSystem.Data.AccumulatedReward = AccumulatedReward;
- UpdatePerformancePlot(TrialTypes, Outcomes,SessionBirthdate);
- UpdatePsychoPlot(TrialTypes, Outcomes);
- tDeliverStimulus = diff(BpodSystem.Data.RawEvents.Trial{1, 1}.States.DeliverStimulus);
- %UpdateStimulusPlot(Cloud_toplot,tDeliverStimulus);
- PokesPlot('update');
- if S.GUI.Antibias==2 %apply antibias
- if Outcomes(currentTrial)==0
- TrialTypes(currentTrial+1)=TrialTypes(currentTrial);
- end
- end
- UpdateOutcomePlot(TrialTypes, Outcomes);
- SaveBpodSessionData; % Saves the field BpodSystem.Data to the current data file
- end
- if BpodSystem.BeingUsed == 0
- PsychToolboxSoundServer('close');
- return
- end
-
-end
-
-function UpdateOutcomePlot(TrialTypes, Outcomes)
-global BpodSystem
-EvidenceStrength = BpodSystem.Data.EvidenceStrength;
-nTrials = BpodSystem.Data.nTrials;
-OutcomePlot(BpodSystem.GUIHandles.OutcomePlot,'update',nTrials+1,2-TrialTypes,Outcomes,EvidenceStrength);
-
-function UpdatePerformancePlot(TrialTypes, Outcomes,SessionBirthdate)
-global BpodSystem
-nTrials = BpodSystem.Data.nTrials;
-%PerformancePlot(BpodSystem.GUIHandles.PerformancePlot,'update',nTrials,2-TrialTypes,Outcomes,SessionBirthdate);
-PerformancePlot('update', TrialTypes, Outcomes, nTrials);
-
-function UpdatePsychoPlot(TrialTypes, Outcomes)
-global BpodSystem
-EvidenceStrength = BpodSystem.Data.EvidenceStrength;
-nTrials = BpodSystem.Data.nTrials;
-PsychoPlot(BpodSystem.GUIHandles.PsychoPlot, 'update',nTrials,2-TrialTypes,Outcomes,EvidenceStrength);
-
-function UpdateStimulusPlot(Cloud,tDeliverStimulus)
-global BpodSystem
-CloudDetails.EvidenceStrength = BpodSystem.Data.EvidenceStrength(end);
-StimulusPlot(BpodSystem.GUIHandles.StimulusPlot,'update',Cloud,CloudDetails,tDeliverStimulus);
\ No newline at end of file
diff --git a/Settings Files/BpodSystemSettings.mat b/Settings Files/BpodSystemSettings.mat
index 4d35bbf..d0d228f 100644
Binary files a/Settings Files/BpodSystemSettings.mat and b/Settings Files/BpodSystemSettings.mat differ