No BSD License  

Highlights from
NESim

image thumbnail
from NESim by Chris Eliasmith
General package for large-scale biologically plausible simulations (with GUI).

runsim(varargin)
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);

Contact us at files@mathworks.com