function varargout = runsim(varargin)
% RUNSIM Application M-file for runsim.fig
% FIG = RUNSIM launch runsim GUI.
% RUNSIM('callback_name', ...) invoke the named callback.
% Enter the name of the simulation data file (eg: "Z_XY") in the text box
% and press the "load" button. To run the simulation, press the "run"
% button. There should be a matlab script file named the same as the
% data file that was loaded with the prefix "runsim" (eg: "runsimZ_XY.m").
%
%% Copyright (C) by Charles. H. Anderson and Chris Eliasmith (All Rights Reserved)
%% Dept. Anatomy and Neurobiology
%% Washington Univ. School of Medicine
%% St. Louis, MO
%% cha@wustl.edu
%% eliasmith@uwaterloo.ca)
%% Version 3.8 1/21/04 by CHA
%% Version 3.6 12/5/03 by CHA
%% Version 3.0 8/20/03 by CHA, Substantial changes mainly to speed up simulations.
%%
%% Version 2.0 Many Changes 3/5/03 by CHA
%%
%% Version 2.1 4/2/03 CHA
%% Fixed Bandlimited Noise so default HighFreq = 30.
%% Added text to show `Min, Max Freq' when Bandlimited Noise is selected.
%% Added ability to change t_syn in ensembles with no explicit output connections.
%% This means the singleensemble example now runs!!
% Removed the filter order selection. 2/25/03 CHA
% Last Modified by GUIDE v2.5 31-Aug-2003 10:49:11
% Version 1.0 by John Harwell 10/29/01
%
global lastTimestamp
Version = 3.8; %% Present version set on 1/21/04 --cha
if nargin <= 1 % LAUNCH GUI
if( nargin == 1)
if(strncmp(lower(char(varargin{1})),'ver',3))
fprintf('NESIM Version %3.1f\n',Version);
return;
end
end
fig = openfig(mfilename,'reuse');
% Generate a structure of handles to pass to callbacks, and store it.
handles = guihandles(fig);
handles.fig = fig;
guidata(fig, handles);
set(fig, 'Name', 'NESIM: Neural Engineering Simulator');
if nargout > 0
varargout{1} = fig;
end
% if there is one argument it is the sim name that should be loaded
if (nargin == 1)
set(handles.simNameText, 'String', varargin{1});
loadUserData(varargin{1}, handles);
end
elseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACK
% This section of code makes all of the callbacks. DO NOT take it out !!!
try
[varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard
catch
disp(lasterr);
end
end
%| ABOUT CALLBACKS:
%| GUIDE automatically appends subfunction prototypes to this file, and
%| sets objects' callback properties to call them through the FEVAL
%| switchyard above. This comment describes that mechanism.
%|
%| Each callback subfunction declaration has the following form:
%| <SUBFUNCTION_NAME>(H, EVENTDATA, HANDLES, VARARGIN)
%|
%| The subfunction name is composed using the object's Tag and the
%| callback type separated by '_', e.g. 'slider2_Callback',
%| 'figure1_CloseRequestFcn', 'axis1_ButtondownFcn'.
%|
%| H is the callback object's handle (obtained using GCBO).
%|
%| EVENTDATA is empty, but reserved for future use.
%|
%| HANDLES is a structure containing handles of components in GUI using
%| tags as fieldnames, e.g. handles.figure1, handles.slider2. This
%| structure is created at GUI startup using GUIHANDLES and stored in
%| the figure's application data using GUIDATA. A copy of the structure
%| is passed to each callback. You can store additional information in
%| this structure at GUI startup, and you can change the structure
%| during callbacks. Call guidata(h, handles) after changing your
%| copy to replace the stored original so that subsequent callbacks see
%| the updates. Type "help guihandles" and "help guidata" for more
%| information.
%|
%| VARARGIN contains any extra arguments you have passed to the
%| callback. Specify the extra arguments by editing the callback
%| property in the inspector. By default, GUIDE sets the property to:
%| <MFILENAME>('<SUBFUNCTION_NAME>', gcbo, [], guidata(gcbo))
%| Add any extra arguments after the last argument, before the final
%| closing parenthesis.
% --------------------------------------------------------------------
function varargout = lengthOfRunText_Callback(h, eventdata, handles, varargin)
% Stub for Callback of the uicontrol handles.lengthOfRunText.
% --------------------------------------------------------------------
function varargout = stepText_Callback(h, eventdata, handles, varargin)
% Stub for Callback of the uicontrol handles.stepText.
% --------------------------------------------------------------------
function varargout = genEnsemble_Callback(h, eventdata, handles, varargin)
% Stub for Callback of the uicontrol handles.genEnsemble.
gen_Ensemble;
% --------------------------------------------------------------------
function varargout = loadConnectionData(handles)
% load data for the selected connction
global ConnectionIndex
connIndex = get(handles.connectionsPopupMenu, 'Value');
a = ConnectionIndex{connIndex};
connTo = a(1);
connFrom = a(2);
set(handles.timeConstText, 'String', num2str(a(3)));
% --------------------------------------------------------------------
function varargout = connectionsPopupMenu_Callback(h, eventdata, handles, varargin)
% Stub for Callback of the uicontrol handles.connectionsPopupMenu.
loadConnectionData(handles);
% --------------------------------------------------------------------
function varargout = ensemblePopupMenu_Callback(h, eventdata, handles, varargin)
% Stub for Callback of the uicontrol handles.ensemblePopupMenu.
% Update method
setEnsembleMethod(handles);
% --------------------------------------------------------------------
function varargout = methodPopupMenu_Callback(h, eventdata, handles, varargin)
% Stub for Callback of the uicontrol handles.methodPopupMenu.
global Ensemble
ensNumber = get(handles.ensemblePopupMenu, 'Value');
Ensemble(ensNumber).Method = get(handles.methodPopupMenu, 'Value') - 1;
set(handles.radiobutton2,'Value',0)
set(handles.radiobutton3,'Value',0)
% --------------------------------------------------------------------
% --- Executes on button press in radiobutton2.
function radiobutton2_Callback(hObject, eventdata, handles)
global Ensemble NumEns
set(handles.radiobutton3,'Value',0)
for(n=1:NumEns)
Ensemble(n).Method = 1;
end
setEnsembleMethod(handles)
% --- Executes on button press in radiobutton3.
function radiobutton3_Callback(hObject, eventdata, handles)
global Ensemble NumEns
set(handles.radiobutton2,'Value',0)
for(n=1:NumEns)
Ensemble(n).Method = 2;
end
setEnsembleMethod(handles)
% --------------------------------------------------------------------
% --------------------------------------------------------------------
function varargout = editSignalGenButton_Callback(h, eventdata, handles, varargin)
% Stub for Callback of the uicontrol handles.editSignalGenButton.
lor = str2double(get(handles.lengthOfRunText, 'String'));
gui_signal_generator(lor);
% --------------------------------------------------------------------
function setUserData(handles, userData)
% load user interface with userData's members
global Ensemble NumEns ConnectionIndex
for i = 1:NumEns
Ensemble(i).Method = userData.method(i);
end
ConnectionIndex = userData.ConnData;
set(handles.lengthOfRunText, 'String', num2str(userData.T));
set(handles.stepText, 'String', num2str(userData.dt));
set(handles.randomSeedText, 'String', num2str(userData.randomSeed));
set(handles.noiseLevelText, 'String', num2str(userData.noiseLevel));
setEnsembleMethod(handles);
loadConnectionData(handles);
% --------------------------------------------------------------------
function userData = getUserData(handles)
% get data from the user interface and return in a struct
global Ensemble NumEns ConnectionIndex
for i = 1:NumEns
userData.method(i) = Ensemble(i).Method;
end
userData.ConnData = ConnectionIndex;
userData.T = str2double(get(handles.lengthOfRunText, 'String'));
userData.dt = str2double(get(handles.stepText, 'String'));
userData.randomSeed = str2double(get(handles.randomSeedText, 'String'));
userData.noiseLevel = str2double(get(handles.noiseLevelText, 'String'));
% --------------------------------------------------------------------
function varargout = runButton_Callback(h, eventdata, handles, varargin)
runSimulation(handles, 0);
% --------------------------------------------------------------------
function varargout = runDirectButton_Callback(h, eventdata, handles, varargin)
runSimulation(handles, 1);
% --------------------------------------------------------------------
function varargout = runSimulation(handles, directOnlyIn);
global Ensemble NumEns ConnectionIndex
global SimName lastSavedName
p = getUserData(handles);
p.simName = get(handles.simNameText, 'String');
p.directOnly = directOnlyIn;
set(handles.fig, 'Pointer', 'watch');
checkSim(p.simName, handles);
nesim_main(p);
set(handles.fig, 'Pointer', 'arrow');
SimName = p.simName;
if(length(lastSavedName)==0)
lastSavedName = [SimName '_settings'];
end
%%% beep;
% check sim.txt and all related populations to see if sim needs to be
% updated - ray
function checkSim(simName, handles)
global lastTimestamp NeuronDataBase
global Ensemble NumEns
files{1} = [simName '.txt'];
for i=1:NumEns
files{i+1} = [Ensemble(i).Name '.mat'];
end
if (length(lastTimestamp) == 0 | needsUpdate(files, lastTimestamp))
setup_sim(handles);
end
function newer = needsUpdate(files, last)
for i=1:length(files)
newer = (last < timestamp(files{i}));
if (newer)
return;
end
end
function t = timestamp(filename) %% CHA 12/9/03
fileinfo = getNesimFileInfo(filename);
if(~isempty(fileinfo))
t = datenum(fileinfo.date);
else
errstr = sprintf('Error: cannot find file %s\n', filename);
beep;
error(errstr);
end
%%% Find a file in the local directory, then in matlabpath/neurondata
%%% Cannot use exist to do this!!!
function fileinfo = getNesimFileInfo(fname0)
fileinfo = dir(fname0);
if(~isempty(fileinfo));
fullfilename = fname0;
else
DataBaseStr = 'neurondata';
mpath = lower(path);
k = findstr(DataBaseStr,mpath);
kend = k+length(DataBaseStr)-1;
while((k>1)&(mpath(k)~=';'));
k=k-1;
end
NeuronDataBase = [mpath(k:kend) filesep];
fname = [NeuronDataBase fname0];
fileinfo = dir(fname);
if(~isempty(fileinfo))
fullfilename = fname;
else
fileinfo = [];
end
end
% --------------------------------------------------------------------
function varargout = closeButton_Callback(h, eventdata, handles, varargin)
% Stub for Callback of the uicontrol handles.closeButton.
close all;
% --------------------------------------------------------------------
function varargout = simNameText_Callback(h, eventdata, handles, varargin)
% Stub for Callback of the uicontrol handles.simNameText.
database = get(handles.simNameText, 'String');
loadUserData(database, handles);
% --------------------------------------------------------------------
function varargout = loadButton_Callback(h, eventdata, handles, varargin)
% Stub for Callback of the uicontrol handles.loadButton.
database = get(handles.simNameText, 'String');
SimDataFile = [database '.mat'];
if(~exist(SimDataFile))
fprintf('Cannot find simulation data %s\n',SimDataFile);
else
loadUserData(database, handles);
end
% --------------------------------------------------------------------
function varargout = loadUserData(database, handles);
global Ensemble NumEns Connections
global SimName lastSavedName
global lastTimestamp
SimDataFile = [database '.mat'];
if(~exist(SimDataFile))
fprintf('Cannot find simulation %s\n',SimDataFile);
return;
end
SimName = database;
lastSavedName = [SimName '_settings'];
load(SimDataFile);
% get ensemble names and load ensembles popup menu
for i = 1:NumEns
ensNames{i} = [num2str(i) ') ' Ensemble(i).Name];
Ensemble(i).Method = 1;
end
set(handles.ensemblePopupMenu, 'String', ensNames);
% set ensembles popup menu to first ensemble and set its method
set(handles.ensemblePopupMenu, 'Value', 1);
setEnsembleMethod(handles);
% initialize the connections popupmenu and initialize signal generators
loadConnectionsAndSignals(handles);
loadConnectionData(handles);
lastTimestamp = timestamp(SimDataFile);
% --------------------------------------------------------------------
function varargout = setEnsembleMethod(handles)
% set method assigned to selected ensemble
global Ensemble NumEns
ensMethod = get(handles.ensemblePopupMenu, 'Value');
set(handles.methodPopupMenu, 'Value', Ensemble(ensMethod).Method + 1);
% --------------------------------------------------------------------
function varargout = loadConnectionsAndSignals(handles)
% load connections popup menu and create signal generators class
global Connections NumConnections Ensemble NumEns
global NumSignalGenerators SignalGenerators SignalGeneratorDimension
global ConnectionIndex
NumExt = 0;
connIndex = 1;
NumSignalGenerators = 0;
for i = 1:NumEns
for j = 1:NumEns
syn = Connections(i,j).synapse;
% is this connection from a signal generator ?
if Connections(i,j).extID > 0
NumSignalGenerators = NumSignalGenerators + 1;
s = ['External Input ' num2str(NumSignalGenerators)];
SignalGeneratorDimension(NumSignalGenerators) = Ensemble(i).D;
end
% is this connection a Vector ?
if Connections(i,j).inputMode == 1
s = ['Vector ' Ensemble(j).title '->' Ensemble(i).title];
Conns{connIndex} = s;
ConnectionIndex{connIndex} = [i j syn.tc ];
connIndex = connIndex + 1;
elseif Connections(i,j).inputMode == 2
s = ['Function: ' Ensemble(j).title '->' Ensemble(i).title];
Conns{connIndex} = s;
ConnectionIndex{connIndex} = [i j syn.tc ];
connIndex = connIndex + 1;
end
end
end
NumConnections = connIndex - 1;
if(NumConnections==0) %% Special case of a single ensemble circuit.
Conns = 'None';
ConnectionIndex{1} = [1 1 0.00];
end
set(handles.connectionsPopupMenu, 'String', Conns);
if NumSignalGenerators > 0
SignalGenerators = repmat(struct( 'SigType', 'Ramp', ...
'Frequency', 5.0, ...
'FrequencyHigh', 30.0, ...
'Phase', 0.0, ...
'Amplitude', 0.5, ...
'dcOffset', 0.0, ...
'TimeOn', 0.0, ...
'TimeOff', 0.1, ...
'Filename', '' ), ...
NumSignalGenerators, 3);
end
InitPlotInfo
% --------------------------------------------------------------------
function InitPlotInfo
% load connections popup menu and create signal generators class
global Ensemble NumEns
global NumSignalGenerators SignalGeneratorDimension
global PlotInfo NumPlotInfo
NumPlotInfo = NumEns+NumSignalGenerators;
PlotInfo = makePlotStruct(0,'',0,0);
for(i=1:NumEns)
PlotInfo(i) = makePlotStruct(1,[Ensemble(i).title],i,Ensemble(i).D);
PlotInfo(i).directSolution=1; %% The default is to always plot
PlotInfo(i).inputValues=1; %% the direct solution and system input values.
PlotInfo(i).sel_components = num2str(1:Ensemble(i).D);
end
for(i=1:NumSignalGenerators)
PlotInfo(NumEns+i) = makePlotStruct(0,['Input ', num2str(i)],i,0);
PlotInfo(NumEns+i).sel_components = num2str(1:SignalGeneratorDimension(i));
end
% --------------------------------------------------------------------
function ps = makePlotStruct(typeIn, labelIn, id, D )
ps = struct('type', typeIn, ... % 0 External Input, 1 Neuron
'label', labelIn, ...
'ID', id, ...
'D', D, ...
'can_outputRasters', 0, ...
'can_outputCurrents', 0, ...
'can_outputVoltages', 0, ...
'can_outputAct', 0, ...
'sel_components', '', ...
'outputValues', 0, ...
'inputValues', 0, ...
'directSolution', 0, ...
'rasters', 0, ...
'somaCurrents', 0, ...
'somaVoltages', 0, ...
'act', 0, ...
'Filter_tc', 0.005, ... %% Filter tc for plotting outputs
'numNeurons', 4);
% --------------------------------------------------------------------
function varargout = plotsButton_Callback(h, eventdata, handles, varargin)
% Stub for Callback of the uicontrol handles.plotsButton.
global PlotInfo NumPlotInfo Ensemble
% update Plot Selections for the Ensemble Methods
for n=1:NumPlotInfo
PlotInfo(n).can_outputRasters = 0;
PlotInfo(n).can_outputCurrents = 0;
PlotInfo(n).can_outputVoltages = 0;
PlotInfo(n).can_outputAct = 0;
if(PlotInfo(n).type) % type = 0 -> Inputs, 2 Neurons
if (Ensemble(PlotInfo(n).ID).Method == 2)
PlotInfo(n).can_outputRasters = 1;
PlotInfo(n).can_outputCurrents = 1;
PlotInfo(n).can_outputVoltages = 1;
PlotInfo(n).can_outputAct = 0;
elseif (Ensemble(PlotInfo(n).ID).Method == 1)
PlotInfo(n).can_outputAct = 1;
PlotInfo(n).can_outputCurrents = 1;
end
end
end
gui_plot_3
% --------------------------------------------------------------------
function varargout = timeConstText_Callback(h, eventdata, handles, varargin)
% Stub for Callback of the uicontrol handles.timeConstText.
global ConnectionIndex
connIndex = get(handles.connectionsPopupMenu, 'Value');
a = ConnectionIndex{connIndex};
a(3) = str2double(get(handles.timeConstText, 'String'));
ConnectionIndex{connIndex} = a;
% --------------------------------------------------------------------
function varargout = noiseLevelText_Callback(h, eventdata, handles, varargin)
% Stub for Callback of the uicontrol handles.noiseLevelText.
% --------------------------------------------------------------------
function varargout = randomSeedText_Callback(h, eventdata, handles, varargin)
% Stub for Callback of the uicontrol handles.randomSeedText.
% --------------------------------------------------------------------
function varargout = exitMenuCallback(h, eventdata, handles, varargin)
delete(gcbf);
closeButton_Callback;
% --------------------------------------------------------------------
function varargout = openMenuCallback(h, eventdata, handles, varargin)
global PlotInfo NumPlotInfo
[okCancel, filename] = gui_textEntryDialog;
if (strcmp(okCancel, 'ok'))
if(exist([filename '.mat']));
fprintf('open file %s\n',filename);
load(filename);
setUserData(handles, ud);
else
fprintf('Cannot load settings file %s\n',filename);
end
end
% --------------------------------------------------------------------
function varargout = saveMenuCallback(h, eventdata, handles, varargin)
global NumSignalGenerators SignalGenerators PlotInfo NumPlotInfo
global SimName lastSavedName
[okCancel, filename] = gui_textEntryDialog;
if (strcmp(okCancel, 'ok'))
ud = getUserData(handles);
save(filename, 'PlotInfo', 'NumPlotInfo', ...
'SignalGenerators', 'NumSignalGenerators', 'ud');
fprintf('Save settings in %s\n',filename);
end
% --------------------------------------------------------------------
function varargout = saveSettingsResultsMenuCallback(h, eventdata, handles, varargin)
%%%%%%%%%
global ext_INPUTS InputDimension inputIndex
%%% Storage for the system variables, (1) Inputs to neurons, (2) Outputs, (3) Function Outputs
global sys_INPUTS In_Start In_End sys_OUTPUTS Out_Start Out_End F_OUTPUTS Fout_Start Fout_End
%%%% Storage for single neuron variables
global SpikeTimes SpikeCnt SpikeEnsOffset Activities ActEnsOffset Currents C_EnsOffset Voltages V_EnsOffset
%%% Time and noise
global T dt time Noise;
%%% Signals
global NumSignalGenerators SignalGenerators PlotInfo NumPlotInfo
%%% File name
global SimName lastSavedName
[okCancel, filename] = gui_textEntryDialog;
if (strcmp(okCancel, 'ok'))
ud = getUserData(handles);
save(filename, 'SimName', 'PlotInfo', 'NumPlotInfo', 'time', ...
'SignalGenerators', 'NumSignalGenerators', 'ud', ...
'SpikeTimes', 'SpikeCnt', 'SpikeEnsOffset', ...
'Activities', 'ActEnsOffset', 'Currents', 'C_EnsOffset', 'Voltages', 'V_EnsOffset', ...
'sys_INPUTS', 'In_Start', 'In_End', ...
'sys_OUTPUTS', 'Out_Start', 'Out_End', ...
'F_OUTPUTS', 'Fout_Start', 'Fout_End', ...
'ext_INPUTS', 'InputDimension', 'inputIndex' ...
);
fprintf('Saved Output of Simulation in %s\n',filename);
end
% --------------------------------------------------------------------
function varargout = simNameTextReturn_Callback(h, eventdata, handles, varargin)
% --------------------------------------------------------------------
function varargout = formPopupMenu_Callback(h, eventdata, handles, varargin)
% Stub for Callback of the uicontrol handles.formPopupMenu.
global ConnectionIndex
connIndex = get(handles.connectionsPopupMenu, 'Value');
a = ConnectionIndex{connIndex};
a(5) = get(handles.formPopupMenu, 'Value') - 1; %% ??? cha 8/27/03
ConnectionIndex{connIndex} = a;
% --------------------------------------------------------------------
function varargout = setupSimPushButton_Callback(h, eventdata, handles, varargin)
% Stub for Callback of the uicontrol handles.setupSimPushButton.
setup_sim(handles); %% Ray
% --------------------------------------------------------------------
function varargout = setup_sim(handles)
global PlotInfo NumPlotInfo
global NumSignalGenerators SignalGenerators
global Ensemble NumEns
global ConnectionIndex NumConnections
% save signal generator settings
for i=1:NumSignalGenerators
for j=1:3
savedSignalGenerators(i,j) = SignalGenerators(i,j);
end
end
% save synaptic time constant & filter orders & mode
for i=1:NumConnections
a = ConnectionIndex{i};
savedTime(i) = a(3);
end
% save plot selections
for i=1:NumPlotInfo
savedPlotInfo(i) = PlotInfo(i);
end
% save simulation methods
for i=1:NumEns
savedMethods(i) = Ensemble(i).Method;
end
database = get(handles.simNameText, 'String');
setupSim(database);
loadUserData(database, handles);
% restore plot selections
for i=1:NumPlotInfo
PlotInfo(i) = savedPlotInfo(i);
end
% restore signal generator settings
for i=1:NumSignalGenerators
for j=1:3
SignalGenerators(i,j) = savedSignalGenerators(i,j);
end
end
% restore simulation method
for i=1:NumEns
Ensemble(i).Method = savedMethods(i);
end
setEnsembleMethod(handles);
% restore Connection
for i=1:NumConnections
a = ConnectionIndex{i};
a(3) = savedTime(i);
ConnectionIndex{i} = a;
end
loadConnectionData(handles);