├── .gitignore ├── comp0p1.mid ├── comp1p1.mid ├── comp1p2.mid ├── comp2p1.mid ├── comp2p2.mid ├── comp3p1.mid ├── comp3p2.mid ├── comp4p1.mid ├── comp4p2.mid ├── comp4p3.mid ├── comp4p5.mid ├── makeRhythm1.png ├── makeRhythm1c.png ├── makeRhythm2.png ├── makeRhythm2c.png ├── makeRhythm1.m ├── makeRhythm1c1.m ├── makeRhythm2.m ├── makeRhythm1c3.m ├── plotFigures.m ├── makeRhythm2c1.m ├── makeRhythm2c3.m ├── experimentRhythms.m ├── README.md ├── rhythmModelFigures.m └── rhythmUI.m /.gitignore: -------------------------------------------------------------------------------- 1 | *.m~ 2 | *.mat 3 | -------------------------------------------------------------------------------- /comp0p1.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusicDynamicsLab/GrFNNRhythm/HEAD/comp0p1.mid -------------------------------------------------------------------------------- /comp1p1.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusicDynamicsLab/GrFNNRhythm/HEAD/comp1p1.mid -------------------------------------------------------------------------------- /comp1p2.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusicDynamicsLab/GrFNNRhythm/HEAD/comp1p2.mid -------------------------------------------------------------------------------- /comp2p1.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusicDynamicsLab/GrFNNRhythm/HEAD/comp2p1.mid -------------------------------------------------------------------------------- /comp2p2.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusicDynamicsLab/GrFNNRhythm/HEAD/comp2p2.mid -------------------------------------------------------------------------------- /comp3p1.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusicDynamicsLab/GrFNNRhythm/HEAD/comp3p1.mid -------------------------------------------------------------------------------- /comp3p2.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusicDynamicsLab/GrFNNRhythm/HEAD/comp3p2.mid -------------------------------------------------------------------------------- /comp4p1.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusicDynamicsLab/GrFNNRhythm/HEAD/comp4p1.mid -------------------------------------------------------------------------------- /comp4p2.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusicDynamicsLab/GrFNNRhythm/HEAD/comp4p2.mid -------------------------------------------------------------------------------- /comp4p3.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusicDynamicsLab/GrFNNRhythm/HEAD/comp4p3.mid -------------------------------------------------------------------------------- /comp4p5.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusicDynamicsLab/GrFNNRhythm/HEAD/comp4p5.mid -------------------------------------------------------------------------------- /makeRhythm1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusicDynamicsLab/GrFNNRhythm/HEAD/makeRhythm1.png -------------------------------------------------------------------------------- /makeRhythm1c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusicDynamicsLab/GrFNNRhythm/HEAD/makeRhythm1c.png -------------------------------------------------------------------------------- /makeRhythm2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusicDynamicsLab/GrFNNRhythm/HEAD/makeRhythm2.png -------------------------------------------------------------------------------- /makeRhythm2c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusicDynamicsLab/GrFNNRhythm/HEAD/makeRhythm2c.png -------------------------------------------------------------------------------- /makeRhythm1.m: -------------------------------------------------------------------------------- 1 | %% Network 2 | n1 = networkMake(1, 'hopf', alpha1, beta11, beta12, delta11, delta12, neps1, ... 3 | 'log', .375, 12, 321, 'tick', 2.^(-1:3), ... 4 | 'display', 2, 'save', 1); 5 | n1 = connectAdd(s, n1, 1, 'type', 'active'); 6 | n1.con{1}.w = 3.0; 7 | 8 | %% Model 9 | M = modelMake(@zdot, @cdot, s, n1); -------------------------------------------------------------------------------- /makeRhythm1c1.m: -------------------------------------------------------------------------------- 1 | %% Network 2 | n1 = networkMake(1, 'hopf', alpha1, beta11, beta12, delta11, delta12, neps1, ... 3 | 'log', .375, 12, 321, 'tick', 2.^(-1:3), ... 4 | 'display', 2, 'save', 1); 5 | n1 = connectAdd(s, n1, 1, 'type', 'active'); 6 | n1.con{1}.w = 3.0; 7 | 8 | %% Connections 9 | C = connectMake(n1, n1, 'gaus', 1, 1.05); 10 | 11 | n1 = connectAdd(n1, n1, C, 'weight', .10, 'type', '2freq', .05); 12 | 13 | %% Model 14 | M = modelMake(@zdot, @cdot, s, n1); 15 | -------------------------------------------------------------------------------- /makeRhythm2.m: -------------------------------------------------------------------------------- 1 | %% Networks 2 | n1 = networkMake(1, 'hopf', alpha1, beta11, beta12, 0, 0, neps1, ... 3 | 'log', .375, 12, 321, 'tick', 2.^(-1:3),... 4 | 'display', 2, 'save', 1); 5 | n1 = connectAdd(s, n1, 1, 'type', 'active'); 6 | n1.con{1}.w = 3.0; 7 | 8 | n2 = networkMake(2, 'hopf', alpha2, beta21, beta22, 0, 0, neps2, ... 9 | 'log', .375, 12, 321, ... 10 | 'display', 2, 'save', 1); 11 | %% Connections 12 | C = connectMake(n1, n2, 'gaus', 1, 1.05); 13 | 14 | n2 = connectAdd(n1, n2, C, 'weight', .40, 'type', '2freq', .05); 15 | 16 | %% Model 17 | M = modelMake(@zdot, @cdot, s, n1, n2); 18 | -------------------------------------------------------------------------------- /makeRhythm1c3.m: -------------------------------------------------------------------------------- 1 | %% Networks 2 | n1 = networkMake(1, 'hopf', alpha1, beta11, beta12, delta11, delta12, neps1, ... 3 | 'log', .375, 12, 321, 'tick', 2.^(-1:3),... 4 | 'display', 2, 'save', 1); 5 | 6 | 7 | %% Connections 8 | modes = [1/3 1/2 1/1 2/1 3/1]; 9 | amps = [1 1 1 1 1 ]; 10 | sds = 1.05*[1 1 1 1 1 ]; 11 | 12 | n1 = connectAdd(s, n1, 1, 'type', 'active'); 13 | n1.con{1}.w = 3.0; 14 | C = connectMake(n1, n1, 'gaus', 1, 1.05, 'modes', modes, 'amps', amps, 'sds', sds); 15 | n1 = connectAdd(n1, n1, C, 'weight', .10, 'type', '2freq', .05); 16 | 17 | 18 | %% Model 19 | M = modelMake(@zdot, @cdot, s, n1); 20 | -------------------------------------------------------------------------------- /plotFigures.m: -------------------------------------------------------------------------------- 1 | load iso44long.mat 2 | rhythmModelFigures 3 | max(yas)/sum(yas) 4 | pause 5 | 6 | load comp1p1.mat 7 | rhythmModelFigures 8 | max(yas)/sum(yas) 9 | pause 10 | 11 | load comp1p2.mat 12 | rhythmModelFigures 13 | max(yas)/sum(yas) 14 | pause 15 | 16 | load comp2p1.mat 17 | rhythmModelFigures 18 | max(yas)/sum(yas) 19 | pause 20 | 21 | load comp2p2.mat 22 | rhythmModelFigures 23 | max(yas)/sum(yas) 24 | pause 25 | 26 | load comp3p1.mat 27 | rhythmModelFigures 28 | max(yas)/sum(yas) 29 | pause 30 | 31 | load comp3p2.mat 32 | rhythmModelFigures 33 | max(yas)/sum(yas) 34 | pause 35 | 36 | load p1long.mat 37 | rhythmModelFigures 38 | max(yas)/sum(yas) 39 | pause 40 | 41 | load p2long.mat 42 | rhythmModelFigures 43 | max(yas)/sum(yas) 44 | pause 45 | 46 | load p3long.mat 47 | rhythmModelFigures 48 | max(yas)/sum(yas) 49 | pause 50 | 51 | load p5long.mat 52 | rhythmModelFigures 53 | max(yas)/sum(yas) 54 | pause 55 | -------------------------------------------------------------------------------- /makeRhythm2c1.m: -------------------------------------------------------------------------------- 1 | %% Networks 2 | n1 = networkMake(1, 'hopf', alpha1, beta11, beta12, 0, 0, neps1, ... 3 | 'log', .375, 12, 321, 'tick', 2.^(-1:3), ... 4 | 'display', 2, 'save', 1); 5 | n1 = connectAdd(s, n1, 1, 'type', 'active'); 6 | n1.con{1}.w = 3.0; 7 | 8 | n2 = networkMake(2, 'hopf', alpha2, beta21, beta22, 0, 0, neps2, ... 9 | 'log', .375, 12, 321, 'tick', 2.^(-1:3), ... 10 | 'display', 2, 'save', 1); 11 | %% Connections 12 | C = connectMake(n1, n1, 'gaus', 1, 1.05); 13 | 14 | %% Connections 15 | 16 | % Internal 17 | n1 = connectAdd(n1, n1, C, 'weight', .10, 'type', '2freq', .05); 18 | 19 | % Afferent 20 | n2 = connectAdd(n1, n2, C, 'weight', .40, 'type', '2freq', .05); 21 | 22 | % Internal 23 | n2 = connectAdd(n2, n2, C, 'weight', .10, 'type', '2freq', .05); 24 | 25 | % Efferent 26 | n1 = connectAdd(n2, n1, C, 'weight', .05, 'type', '2freq', .05); 27 | 28 | %% Model 29 | M = modelMake(@zdot, @cdot, s, n1, n2); -------------------------------------------------------------------------------- /makeRhythm2c3.m: -------------------------------------------------------------------------------- 1 | %% Networks 2 | n1 = networkMake(1, 'hopf', alpha1, beta11, beta12, 0, 0, neps1, ... 3 | 'log', .375, 12, 321, 'tick', 2.^(-1:3), ... 4 | 'display', 12, 'save', 1); 5 | n2 = networkMake(2, 'hopf', alpha2, beta21, beta22, 0, 0, neps2, ... 6 | 'log', .375, 12, 321, 'tick', 2.^(-1:3), ... 7 | 'display', 12, 'save', 1); 8 | n1 = connectAdd(s, n1, 1, 'type', 'active'); 9 | n1.con{1}.w = 3.0; 10 | 11 | %% Connections 12 | modes = [1/3 1/2 1/1 2/1 3/1]; 13 | amps = [1 1 1 1 1 ]; 14 | sds = 1.05*[1 1 1 1 1 ]; 15 | 16 | C = connectMake(n1, n1, 'gaus', 1, 1.05, 'modes', modes, 'amps', amps, 'sds', sds); 17 | 18 | %% Connections 19 | % Internal 20 | n1 = connectAdd(n1, n1, C, 'weight', w/4, 'type', '2freq', .05); 21 | 22 | % Afferent 23 | n2 = connectAdd(n1, n2, C, 'weight', w/.8, 'type', '2freq', .05); 24 | 25 | % Internal 26 | n2 = connectAdd(n2, n2, C, 'weight', w/3, 'type', '2freq', .05); 27 | 28 | % Efferent 29 | n1 = connectAdd(n2, n1, C, 'weight', w/8, 'type', '2freq', .05); 30 | 31 | %% Model 32 | M = modelMake(@zdot, @cdot, s, n1, n2); 33 | -------------------------------------------------------------------------------- /experimentRhythms.m: -------------------------------------------------------------------------------- 1 | %% Parameters 2 | Fs = 48; 3 | 4 | alpha1 = 1e-5; beta11 = 0; beta12 = -2; delta11 = 0; delta12 = 0; 5 | neps1 = 1; 6 | alpha2 = -0.4; beta21 = 1.75; beta22 =-1.25; delta21 = 0; delta22 = 0; 7 | neps2 = 1; 8 | w = 0.4; 9 | % alpha2 = -1; beta21 = 4; beta22 =-2.75; neps2 = 1; w = 1; 10 | lambda = -1; mu1 = 4; mu2 = -2.2; ceps = 1; kappa = 1; % Critical 11 | 12 | ampMult = 0.05; 13 | 14 | makeModel = 'makeRhythm2c3'; 15 | 16 | %% Complexity level 0 (isochronous) 17 | matfilename = sprintf('comp0p1.mat'); 18 | filename = sprintf('comp0p1.mid'); 19 | 20 | s = stimulusMake('mid', filename, [0 24], Fs, ... 21 | 'display', 4, 'inputType', 'active'); 22 | s.x = ampMult*s.x/rms(s.x); 23 | s.x = hilbert(s.x); 24 | 25 | disp(filename); 26 | eval(makeModel); 27 | M = odeRK4fs(M, s); 28 | rhythmModelFigures; 29 | save(matfilename) 30 | 31 | %% Complexity levels 1, 2 & 3 32 | for c = [1 2 3] 33 | for p = [1 2] 34 | matfilename = sprintf('comp%dp%d.mat', c, p); 35 | filename = sprintf('comp%dp%d.mid', c, p) 36 | 37 | s = stimulusMake(1, 'mid', filename, [0 24.5], Fs, 'inputType', 'active', ... 38 | 'display', 4); 39 | s.x = ampMult*s.x/rms(s.x); 40 | s.x = hilbert(s.x); 41 | eval(makeModel); 42 | M = odeRK4fs(M, s); 43 | rhythmModelFigures; 44 | save(matfilename) 45 | end 46 | end 47 | 48 | %% Complexity level 4 (missing pulse rhythm) 49 | 50 | for p = [1 2 3 4 5] 51 | matfilename = sprintf('comp4p%d.mat', p); 52 | filename = sprintf('comp4p%d.mid', p) 53 | 54 | s = stimulusMake(1, 'mid', filename, [0 24.5], Fs, 'inputType', 'active', ... 55 | 'display', 4); 56 | s.x = ampMult*s.x/rms(s.x); 57 | s.x = hilbert(s.x); 58 | eval(makeModel); 59 | M = odeRK4fs(M, s); 60 | rhythmModelFigures; 61 | save(matfilename) 62 | end 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GrFNNRhythm 2 | 3 | Entrainment of cortical rhythms to acoustic rhythms has been hypothesized to be the neural correlate of pulse and meter perception in music. A neurodynamic model by [Large, Herrera and Velasco (2015)](http://dx.doi.org/10.3389/fnsys.2015.00159) shows how self-organization of oscillations in interacting sensory and motor networks could be responsible for the formation of the pulse percept in complex rhythms. This model is one of the few consistent with neurophysiological evidence on the role of neural oscillation, and it explains a phenomenon (missing fundamental pulse) that other computational models fail to explain. This model provides a theoretical link between oscillatory neurodynamics and the induction of pulse and meter in musical rhythm. 4 | 5 | ![imageOfUI](https://MusicDynamicsLab.github.io/Figures/rhythmUIgrey.png) 6 | 7 | The **GrFNNRhythm** repository contains MATLAB code that runs models of beat perception in musical rhythm using [**The GrFNN Toolbox**](https://github.com/MusicDynamicsLab/GrFNNToolbox). A user interface implemented in `rhythmUI.m` allows the user to choose a stimulus of a given rhythmic complexity (from a straightforward isochronous rhythm to more rhythmically complex, syncopated rhythms) and process it through one of the following six GrFNN models: 8 | 9 | 1. One network with no internal connections. This model can be used by selecting "One Layer" in the dropdown menu. 10 | 11 | 2. One network with local (1:1) internal connections. Can be used by selecting "One Layer, local connection" in the dropdown menu. 12 | 13 | 3. One network with 1:1, 2:1, 3:1, 1:2, and 1:3 internal connections. Can be used by selecting "One Layer, harmonic connections" in the dropdown menu. 14 | 15 | 4. Two networks with local (1:1) afferent connections, no internal connections. Can be used by selecting "Two Layer, afferent only". 16 | 17 | 5. Two networks with local (1:1) afferent, efferent, and internal connections. Can be used by selecting "Two Layer, all, local". 18 | 19 | 6. Two networks with 1:1, 2:1, 3:1, 1:2, and 1:3 afferent, efferent, and internal connections. Can be used by selecting "Two Layer, all, harmonic". 20 | 21 | The final model is nearly identical (with some simplifications) to the model from [Large, Herrera and Velasco (2015)](http://dx.doi.org/10.3389/fnsys.2015.00159). It is also more-or-less the same as the [Velasco & Large (2011)](http://ismir2011.ismir.net/papers/PS2-3.pdf) model from ISMIR. The most important difference is that the connections from Layer 2 (motor) to Layer 1 (sensory) are excitatory, not inhibitory. 22 | -------------------------------------------------------------------------------- /rhythmModelFigures.m: -------------------------------------------------------------------------------- 1 | global s M 2 | 3 | begin = round((.5:1/s.fs:8.5)*s.fs); 4 | t = s.t(begin(1:end-1)); 5 | mf1 = s.x(begin(1:end-1)); 6 | 7 | figure(03) 8 | nfft = 6*length(mf1); 9 | y = fft(mf1, nfft); 10 | sf = s.fs/2*linspace(0,1,nfft/2+1); 11 | sy= abs(y(1:floor(nfft/2)+1))/nfft; 12 | 13 | plot(sf(2:end), sy(2:end)) % 14 | set(gca, 'XLim', [0, 5], 'XTick', [.5 .75 1 1.25 2 4]) 15 | grid 16 | 17 | title('Stimulus'); 18 | xlabel('Frequency'); 19 | ylabel('Amplitude'); 20 | 21 | %% Display Network 1: Image, mean field time series and FFT 22 | 23 | figure(11); 24 | imagesc(s.t, M.n{1}.f, abs(M.n{1}.Z)); axis xy 25 | set(gca, 'xscale', 'lin', 'yscale', 'log'); 26 | colormap(flipud(hot)); colorbar; 27 | set(gca, 'CLim', [.001 .8/sqrt(M.n{1}.e)]); 28 | title('Sensory Network'); 29 | 30 | %% 31 | figure(12); 32 | begin = round((s.t(end)-8:1/s.fs:s.t(end-1))*s.fs); 33 | t = s.t(begin); 34 | mf1 = real(sum(M.n{1}.Z(:,begin))); 35 | x = s.x(begin); 36 | 37 | t = t-t(1); 38 | plot(t, real(x)/max(real(x)), 'k', t, real(mf1)/max(real(mf1)), 'c', 'LineWidth', 1.5); 39 | 40 | title('Sensory Network'); 41 | 42 | %% FFT 43 | figure(13); 44 | nfft = 6*length(mf1); 45 | 46 | y = fft((mf1), nfft); 47 | f = s.fs/2*linspace(0,1,nfft/2+1); 48 | ya1= abs(y(1:floor(nfft/2)+1))/nfft; 49 | 50 | plot(f(2:end), ya1(2:end)/sum(ya1(2:end)), sf(2:end), sy(2:end)/sum(sy(2:end))) 51 | set(gca, 'XLim', [0, 5], 'XTick', [.5 .75 1 1.25 2 4]) 52 | grid 53 | 54 | title('Sensory Network'); 55 | xlabel('Frequency'); 56 | ylabel('Amplitude'); 57 | 58 | %% Display Network 2: Image, mean field time series and FFT 59 | if length(M.n)>1 60 | 61 | figure(21); 62 | 63 | imagesc(s.t, M.n{2}.f, abs(M.n{2}.Z)); axis xy 64 | set(gca, 'xscale', 'lin', 'yscale', 'log'); 65 | colormap(flipud(hot)); colorbar; 66 | set(gca, 'CLim', [.001 .8/sqrt(M.n{1}.e)]); 67 | title('Motor Network'); 68 | 69 | %% 70 | figure(22); 71 | 72 | t = s.t(begin); 73 | mf2 = real(mean(M.n{2}.Z(:,begin))); 74 | x = max(mf2)*s.x(begin); 75 | 76 | t = t-t(1); 77 | plot(t, real(x)/max(real(x)), 'k',t, real(mf2)/max(real(mf2)), 'c', 'LineWidth', 1.5); 78 | title('Motor Network'); 79 | 80 | %% FFT 81 | figure(23); 82 | 83 | y = fft(mf2, nfft); 84 | f = s.fs/2*linspace(0,1,nfft/2+1); 85 | ya2= abs(y(1:floor(nfft/2)+1))/nfft; 86 | 87 | plot(f(2:end), ya2(2:end)/sum(ya2(2:end)), sf(2:end), sy(2:end)/sum(sy(2:end))) % 88 | set(gca, 'XLim', [0, 5], 'XTick', [.5 .75 1 1.25 2 4]) 89 | grid 90 | 91 | title('Motor Network'); 92 | xlabel('Frequency'); 93 | ylabel('Amplitude'); 94 | 95 | end 96 | -------------------------------------------------------------------------------- /rhythmUI.m: -------------------------------------------------------------------------------- 1 | %% Create figure window 2 | function rhythmUI 3 | hf = figure; 4 | set(hf,'Visible','off','Toolbar','figure','Color',[.8 .8 .8],... 5 | 'Position',[100 100 1200 600],'Name','RhythmUI'); 6 | initialRun 7 | movegui(hf,'center') 8 | set(hf,'Visible','on') 9 | 10 | %% Initial run 11 | function initialRun 12 | hf = gcf; 13 | handles.hf = hf; 14 | 15 | valUI = guidata(handles.hf); 16 | if isempty(valUI) 17 | valUI.stimulus = 8; 18 | valUI.model = 6; 19 | end 20 | %% Create panel, dropdown menus, labels, buttons 21 | handles.hp1 = uipanel('Parent',hf,'BackgroundColor',[.8 .8 .8],'Units','Normalized',... 22 | 'Position',[.08 .5 .2 .45]); 23 | s1 = 'Choose the the stimulus'; 24 | s2 = 'Choose the model structure \n that will process the rhythm'; 25 | handles.dropdownmenu1 = uicontrol('Parent',handles.hp1,'Style','popupmenu',... 26 | 'String','Complexity level 0, Pattern 1','FontSize',11,'Value',valUI.stimulus,... 27 | 'Units','normalized','Position',[.05 .75 .9 .125],'TooltipString', s1); 28 | handles.dropdownmenu2 = uicontrol('Parent',handles.hp1,'Style','popupmenu',... 29 | 'String','One Layer','FontSize',11,'TooltipString', s2,'Value',valUI.model,... 30 | 'Units','normalized','Position',[.05 .45 .9 .125]); 31 | handles.pushbutton1 = uicontrol('Parent',handles.hp1,'Style','pushbutton',... 32 | 'String','Run','Fontsize',15,'Units','normalized','Position',[.05 .05 .45 .3]); 33 | handles.pushbutton2 = uicontrol('Parent',handles.hp1,'Style','pushbutton',... 34 | 'String','Pause','Fontsize',15,'Units','normalized','Position',[.51 .05 .45 .3]); 35 | handles.text1 = uicontrol('Parent',handles.hp1,'Style','text','String','Choose Stimulus',... 36 | 'Units','normalized','Position',[.04 .89 .9 .1],'HorizontalAlignment','left',... 37 | 'FontSize',15,'BackgroundColor',[.8 .8 .8]); 38 | handles.text1 = uicontrol('Parent',handles.hp1,'Style','text','String','Choose Model:',... 39 | 'Units','normalized','Position',[.04 .59 .9 .1],'HorizontalAlignment','left',... 40 | 'FontSize',15,'BackgroundColor',[.8 .8 .8]); 41 | 42 | set(handles.dropdownmenu1,'BackgroundColor','white'); 43 | complexity = {'Complexity level 0, Pattern 1';... 44 | 'Complexity level 1, Pattern 1';'Complexity level 1, Pattern 2';... 45 | 'Complexity level 2, Pattern 1';'Complexity level 2, Pattern 2';... 46 | 'Complexity level 3, Pattern 1';'Complexity level 3, Pattern 2';... 47 | 'Complexity level 4, Pattern 1';'Complexity level 4, Pattern 2';... 48 | 'Complexity level 4, Pattern 3';'Complexity level 4, Pattern 4'}; 49 | set(handles.dropdownmenu1, 'String', complexity); 50 | set(handles.dropdownmenu2,'BackgroundColor','white'); 51 | rhythmModel = {'One Layer';'One Layer, local connection';'One Layer, harmonic connection';... 52 | 'Two Layer, afferent only';'Two Layer, all, local';'Two Layer, all, harmonic'}; 53 | set(handles.dropdownmenu2, 'String', rhythmModel); 54 | 55 | %% Create axes 56 | handles.ax5 = axes('Parent',hf,'Units','normalized','Position',[.025 .05 .3 .4],... 57 | 'Visible','off'); 58 | handles.ax1 = axes('Parent',hf,'Units','normalized','Position',[.38 .05 .3 .25],... 59 | 'XTick',[],'YTick',[],'box','on'); zoom xon; 60 | handles.ax2 = axes('Parent',hf,'Units','normalized','Position',[.38 .38 .3 .25],... 61 | 'XTick',[],'YTick',[],'box','on'); 62 | handles.ax3 = axes('Parent',hf,'Units','normalized','Position',[.38 .72 .3 .25],... 63 | 'XTick',[],'YTick',[],'box','on'); 64 | handles.ax4 = axes('Parent',hf','Units','normalized','Position',[.73 .3 .25 .55],... 65 | 'Visible','off'); 66 | 67 | %% Define callback functions 68 | set(handles.pushbutton1,'Callback',{@runStop,handles}) 69 | set(handles.pushbutton2,'Callback',{@pauseResume,handles}) 70 | 71 | %% RUN button 72 | function runStop(source, ~, handles) 73 | uiresume(handles.hf) 74 | name = get(source,'String'); 75 | 76 | %% Clear axes 77 | cla(handles.ax1); 78 | set(handles.ax1,'XTick',[],'YTick',[],'box','on'); 79 | cla(handles.ax2); 80 | set(handles.ax2,'XTick',[],'YTick',[],'box','on'); 81 | cla(handles.ax3); 82 | set(handles.ax3,'XTick',[],'YTick',[],'box','on'); 83 | cla(handles.ax4); 84 | set(handles.ax4,'Visible','off'); 85 | cla(handles.ax5); 86 | set(handles.ax5,'Visible','off'); 87 | cb = findall(gcf,'tag','Colorbar'); 88 | delete(cb); 89 | tt = findall(gcf,'type','text'); 90 | delete(tt); 91 | set(source,'String','Pause') 92 | 93 | stimulusChoice = get(handles.dropdownmenu1, 'Value'); 94 | rhythmChoice = get(handles.dropdownmenu2, 'Value'); 95 | switch stimulusChoice 96 | case 1 97 | stimulus = 'comp0p1.mid'; 98 | case 2 99 | stimulus = 'comp1p1.mid'; 100 | case 3 101 | stimulus = 'comp1p2.mid'; 102 | case 4 103 | stimulus = 'comp2p1.mid'; 104 | case 5 105 | stimulus = 'comp2p2.mid'; 106 | case 6 107 | stimulus = 'comp3p1.mid'; 108 | case 7 109 | stimulus = 'comp3p2.mid'; 110 | case 8 111 | stimulus = 'comp4p1.mid'; 112 | case 9 113 | stimulus = 'comp4p2.mid'; 114 | case 10 115 | stimulus = 'comp4p3.mid'; 116 | case 11 117 | stimulus = 'comp4p5.mid'; 118 | end 119 | 120 | switch rhythmChoice 121 | case 1 122 | handles.image = 'makeRhythm1.png'; 123 | model = 'makeRhythm1'; 124 | case 2 125 | handles.image = 'makeRhythm1c.png'; 126 | model = 'makeRhythm1c1'; 127 | case 3 128 | handles.image = 'makeRhythm1c.png'; 129 | model = 'makeRhythm1c3'; 130 | case 4 131 | handles.image = 'makeRhythm2.png'; 132 | model = 'makeRhythm2'; 133 | case 5 134 | handles.image = 'makeRhythm2c.png'; 135 | model = 'makeRhythm2c1'; 136 | case 6 137 | handles.image = 'makeRhythm2c.png'; 138 | model = 'makeRhythm2c3'; 139 | end 140 | 141 | if strcmp(name,'Run') 142 | set(source,'String','Clear') 143 | integrate(stimulus,model,handles); 144 | else 145 | set(source,'String','Run') 146 | valUI.stimulus = get(handles.dropdownmenu1,'Value'); 147 | valUI.model = get(handles.dropdownmenu2,'Value'); 148 | guidata(handles.hf,valUI); 149 | initialRun; 150 | end 151 | %% Run rhythm function 152 | function integrate(stimulus,rhythm,handles) 153 | 154 | %% Parameters 155 | Fs = 50; 156 | alpha1 = 1e-5; beta11 = 0; beta12 = -2; delta11 = 0; delta12 = 0; 157 | neps1 = 1; 158 | alpha2 = -0.4; beta21 = 1.75; beta22 =-1.25; delta21 = 0; delta22 = 0; 159 | neps2 = 1; 160 | w = 0.4; 161 | lambda = -1; mu1 = 4; mu2 = -2.2; ceps = 1; kappa = 1; % Critical 162 | ampMult = 0.05; 163 | 164 | %% Run simulation 165 | global s M 166 | 167 | filename = stimulus; 168 | s = stimulusMake(1, 'mid', filename, [0 32.5], Fs, 'display', 2); 169 | 170 | s.x = ampMult*s.x/rms(s.x); 171 | s.x = hilbert(s.x); 172 | disp(filename); 173 | eval(rhythm); 174 | M.s{1}.sAx = handles.ax1; 175 | M.n{1}.nAx = handles.ax2; 176 | if exist('n2','var') 177 | M.n{2}.nAx = handles.ax3; 178 | else 179 | axes(handles.ax3); 180 | cla; 181 | end 182 | 183 | axes(handles.ax5); 184 | networkPic = imread(handles.image); 185 | image(networkPic); 186 | set(handles.ax5,'XTick',[],'YTick',[],'box','on'); 187 | axis off; 188 | axis image; 189 | axes(handles.ax4); 190 | if exist('C', 'var') 191 | net1 = getLim(n1); 192 | net2 = getLim(n1); 193 | imagesc(net1, net2, abs(C)); colormap(flipud(hot)); 194 | hcb = colorbar; 195 | set(hcb,'Location','NorthOutside') 196 | set(gca, 'XScale', 'Log', 'YScale', 'Log', 'XTick', n1.tick, 'YTick', n1.tick) 197 | grid on 198 | xlabel('Frequency of source oscillator (Hz)') 199 | ylabel('Frequency of target oscillator (Hz)') 200 | title('Connection Matrix') 201 | end 202 | 203 | try 204 | M = odeRK4fs(M); 205 | catch 206 | disp('User stopped integration') 207 | interrupted = 1; 208 | end 209 | set(handles.pushbutton1,'String','Run') 210 | %% Pause button 211 | function pauseResume(source,~,handles) 212 | pauseOrResumeStr = get(source,'String'); 213 | if(strcmp(pauseOrResumeStr,'Pause')) 214 | set(source,'String','Resume'); 215 | uiwait(handles.hf); 216 | else 217 | set(source,'String','Pause'); 218 | uiresume(handles.hf); 219 | end 220 | --------------------------------------------------------------------------------