├── EIF1DRFfastslowSyn.c ├── FA.m ├── MakeFigure3.m ├── MakeFigure5.m ├── MakeFigure6.m ├── MakeFigure7.m ├── MakeFigure_1C_4E.m ├── MakeFigure_4BCD.m ├── README.md ├── RF2D3layer.m ├── SimulationFig3.m ├── SimulationFig4.m ├── SimulationFig4E.m ├── SimulationFig5.m ├── SimulationFig6AC.m ├── SimulationFig7.m ├── WrappedGauss2D.m ├── corr_d.m ├── data ├── FA_data.mat ├── FA_data_dist.mat ├── FA_model_Jex25.mat ├── FA_model_broadInh_Jex25.mat ├── FA_model_fastInh_Jex25.mat ├── FA_model_slowInh_Jex25_dist.mat ├── Fig3data.mat ├── RF2D3layer_fixW_Jex25_Jix15_MacroChaos_rasters.mat ├── RF2D3layer_fixW_Jex25_Jix15_Ntrial10_Nrep20_Re.mat ├── RF2D3layer_fixW_broadInh_Jex25_Jix15_inI_dt0d01_Nc500_spkcount_nws1.mat ├── RF2D3layer_fixW_fastInh_Jex25_Jix15_inI_dt0d01_Nc500_spkcount_nws1.mat ├── RF2D3layer_fixW_slowInh_Jex25_Jix15_inI_dt0d01_Nc500_spkcount_nws1.mat ├── RF2D_broadRec_tausyni1.mat ├── RF2D_broadRec_tausyni8.mat ├── RF2D_broadRec_uniformW_tausyni_sum.mat ├── RF2D_uniformW_tausyni1.mat └── RF2D_uniformW_tausyni8.mat ├── demo.m ├── fa_Yu ├── README ├── assignopts.m ├── cosmoother_fa.m ├── crossvalidate_fa.m ├── example.m ├── fastfa.m ├── fastfa_estep.m ├── indepGaussEval.m ├── indepGaussFit.m ├── logdet.m └── simdata_fa.m ├── figtools ├── FigLabel.m ├── FigurePlottingTools.docx ├── HF_matchAspectRatio.m ├── HF_setFigProps.m ├── HF_viewsave.m ├── HF_whiten.m ├── axesDivide.m ├── checkField.m ├── errorhull.m ├── narrow_colorbar.m ├── parsePairs.m ├── placeFigures.m ├── plotarea.m ├── setPlotOpt.m └── setgetDirs.m ├── genXspk.m ├── gen_weights.m ├── raster2D_ani.m ├── spkcounts.m └── spktime2count.c /EIF1DRFfastslowSyn.c: -------------------------------------------------------------------------------- 1 | /* To use function from matlab, first compile by entering this into the Matlab command window: 2 | mex EIF1DRF2tausyn.c 3 | Then call the function like this: 4 | [s,Isynrecord,vr]=EIF1DRFfastslowSyn(sx, Wrf,Wrr,param); 5 | */ 6 | 7 | /* sx is the feedforward presynaptic spike trains, which should be 3xNsx where Nsx is the number of spikes. 8 | sx(1,:) is spike times, sx(2,:) is the index of the neuron (from 1 to Nx) 9 | Wrr is a vector of connections among the recurrent layer, containing postsynaptic cell indices, 10 | sorted by the index of the presynaptic cell. The block of postsynaptic cell indices for each presynaptic 11 | cell is sorted as excitatory followed by inhibitory cells. I use fixed number of projections Kab to each population. 12 | For example, Wrr[j*(Kee+Kie)] to Wrr[j*{Kee+Kie)+Kee-1] are connections from j to E pop and 13 | Wrr[j*(Kee+Kie)+Kee] to Wrr[(j+1)*{Kee+Kie)-1] are connections from j to I pop. 14 | Wrf is a vector of connections from the feedforward layer to the recurrent layer, sorted by the index of the presynaptic cell. 15 | The block of postsynaptic cell indices for each presynaptic cell is sorted as excitatory followed by inhibitory cells. 16 | 17 | param is a struc w/ fields: Ne, Ni, Nx, Jx, Jr, Kx, Kr, 18 | gl, Cm, vlb, vth, DeltaT, vT, vl, vre, tref, tausyn, V0, T, dt, 19 | maxns, Irecord, Psyn 20 | Jx=[Jex; Jix]; Jr=[Jee, Jei; Jie, Jii]; 21 | Kx=[Kex; Kix]; Kr=[Kee, Kei; Kie, Kii]; 22 | taursyn: syn rise time const, 3x(Nsyntype), rows: X, E, I; cols: syn type 23 | taudsyn: syn decay time const, 3x(Nsyntype), rows: X, E, I; cols: syn type 24 | Psyn(i,j): percentage of synapse j for (X, E, I (i=1,2,3)) 25 | 26 | 27 | Kab is the number of projections from each cell in pop b=e,i,x to all cells in pop a=e,i 28 | Iapp is the constant external input. It should be a vector of size Nx1 or 1xN where N is the number of cells in the network. 29 | Ne, Ni are the number of excitatory, inhibitory cells, N=Ne+Ni. 30 | Nx is the number of neurons in feedforward layer. 31 | Jab is the synaptic strength of connections from b=e,i,x to a=e,i. 32 | 33 | C,gl,vl,DeltaT,VT,tref,Vth,Vre,Vlb are EIF neuron params 34 | They are each 2x1 vectors, for exc and inh neurons separately. 35 | For example, C(1) is the capacitance of exc neurons and C(2) of inh neurons 36 | tausynb is the time-constant of the synapses from neurons in population b=x,e,i. 37 | post-synaptic currents are of the form (1/tausynb)*exp(-t/tausynb) where t>0 is 38 | the time evolved since the presynaptic spike. 39 | V0 is vector of all membrane potential initial conditions. 40 | It should be Nx1 where N=Ne+Ni is the number of neurons in the recurrent network 41 | The first Ne elements are for exc neurons, the last Ni for inh neurons 42 | dt is bin size for time 43 | maxns is maximum number of spikes allowed for all neurons together 44 | Irecord is a 1x(Nrecord) matrix indicating for which neurons we should record 45 | the synaptic inputs and membrane potential. The first Ne elements are for exc neurons, 46 | the last Ni for inh neurons 47 | 48 | 49 | Outputs: 50 | s is a 2x(maxns) matrix of spikes 51 | s(1,:) contains spike times. 52 | s(2,:) contains indices of neurons that spike 53 | When there are fewer than maxns spikes, extra space in s will be filled 54 | with zeros. This should be truncated in matlab by writing s=s(:,s(1,:)>0); 55 | Isynrecord,vr are the recorded synaptic inputs and voltage respectively. 56 | 57 | */ 58 | 59 | 60 | 61 | #include "mex.h" 62 | #include "math.h" 63 | #include "time.h" 64 | #include "matrix.h" 65 | 66 | 67 | /* A fast approximation of the exp function */ 68 | static union 69 | { 70 | double d; 71 | struct { 72 | #ifdef LITTLE_ENDIAN 73 | int j,i; 74 | #else 75 | int i,j; 76 | #endif 77 | } n; 78 | } _eco; 79 | #define EXP_A (1048576/0.69314718055994530942) 80 | #define EXP_C 60801 81 | #define EXP(y) (_eco.n.i = EXP_A*(y) + (1072693248 - EXP_C), _eco.d) 82 | 83 | 84 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 85 | { 86 | 87 | int Ntref[2],Ni,Ne,Nx,Kee,Kie,Kei,Kii,Kex,Kix,k,j,i,N,Nt,m1,m2,maxns,ns,Nrecord,jj,nskiprecord,tempflag,Nsx, Nw; 88 | double dt,*s,*v,*v0,*Isynrecord, *Psyn; 89 | double *Isyn, *Isynprime; 90 | int *Wrr, *Wrf, *Pr; 91 | double *taudsyn,*taursyn,*vr,*sx,Jex,Jix,*iXspkInd; 92 | double Jee,Jei,Jie,Jii,T,*Irecord,*C,*Vleak,*DeltaT,*VT,*tref,*gl,*Vth,*Vre,*Vlb,xloc,yloc; 93 | int *refstate,iXspike,jspike,*postcellX,*postcellE,*postcellI,postcell, Nsyn, isyn, Nsyntype,Ke,Ki,Kx, *syntype; 94 | const mxArray *mxTmp; 95 | double *temp1,*temp2, Isyntot; 96 | 97 | 98 | 99 | /****** 100 | * Import variables from matlab 101 | * This is messy looking and is specific to mex. 102 | * Ignore if you're implementing this outside of mex. 103 | *******/ 104 | sx = mxGetPr(prhs[0]); 105 | m1 = mxGetM(prhs[0]); 106 | Nsx = mxGetN(prhs[0]); 107 | if(m1!=2){ 108 | mexErrMsgTxt("sx should be Nsxx2"); 109 | } 110 | 111 | Wrf = (int *)mxGetData(prhs[1]); 112 | Nw = mxGetM(prhs[1]); 113 | m1 = mxGetN(prhs[1]); 114 | if(m1!=1){ 115 | mexErrMsgTxt("Weight matrix Wrf must be Nwx1 where Nw is numer of connections."); 116 | } 117 | 118 | Wrr = (int *)mxGetData(prhs[2]); 119 | Nw = mxGetM(prhs[2]); 120 | m1 = mxGetN(prhs[2]); 121 | if(m1!=1){ 122 | mexErrMsgTxt("Weight matrix Wrr must be Nwx1 where Nw is numer of connections."); 123 | } 124 | 125 | /* check if prhs[3] is a struct */ 126 | if(mxIsStruct(prhs[3])!=1){ 127 | mexErrMsgTxt("The 4th input should be the parameter struct."); 128 | } 129 | 130 | 131 | /* Number of exc neurons in each direction. */ 132 | mxTmp = mxGetField(prhs[3],0,"Ne"); 133 | Ne=(int)mxGetPr(mxTmp)[0]; 134 | 135 | /* Number of inh neurons in each direction. */ 136 | mxTmp = mxGetField(prhs[3],0,"Ni"); 137 | Ni=(int)mxGetPr(mxTmp)[0]; 138 | 139 | /* Number of neurons in the ffwd layer in each direction. */ 140 | mxTmp = mxGetField(prhs[3],0,"Nx"); 141 | Nx=(int)mxGetPr(mxTmp)[0]; 142 | 143 | mxTmp = mxGetField(prhs[3],0,"Jx"); 144 | Jex=mxGetPr(mxTmp)[0]; 145 | Jix=mxGetPr(mxTmp)[1]; 146 | 147 | mxTmp = mxGetField(prhs[3],0,"Jr"); 148 | Jee= mxGetPr(mxTmp)[0]; 149 | Jie= mxGetPr(mxTmp)[1]; 150 | Jei= mxGetPr(mxTmp)[2]; 151 | Jii= mxGetPr(mxTmp)[3]; 152 | 153 | mxTmp = mxGetField(prhs[3],0,"Kx"); 154 | Kex= (int)mxGetPr(mxTmp)[0]; 155 | Kix= (int)mxGetPr(mxTmp)[1]; 156 | 157 | mxTmp = mxGetField(prhs[3],0,"Kr"); 158 | Kee= (int)mxGetPr(mxTmp)[0]; 159 | Kie= (int)mxGetPr(mxTmp)[1]; 160 | Kei= (int)mxGetPr(mxTmp)[2]; 161 | Kii= (int)mxGetPr(mxTmp)[3]; 162 | 163 | mxTmp = mxGetField(prhs[3],0,"Cm"); 164 | C=mxGetPr(mxTmp); 165 | m1 = mxGetN(mxTmp); 166 | m2 = mxGetM(mxTmp); 167 | if(m1*m2!=2) 168 | mexErrMsgTxt("All neuron parameters should be 2x1"); 169 | mxTmp = mxGetField(prhs[3],0,"gl"); 170 | gl=mxGetPr(mxTmp); 171 | m1 = mxGetN(mxTmp); 172 | m2 = mxGetM(mxTmp); 173 | if(m1*m2!=2) 174 | mexErrMsgTxt("All neuron parameters should be 2x1"); 175 | mxTmp = mxGetField(prhs[3],0,"vl"); 176 | Vleak=mxGetPr(mxTmp); 177 | m1 = mxGetN(mxTmp); 178 | m2 = mxGetM(mxTmp); 179 | if(m1*m2!=2) 180 | mexErrMsgTxt("All neuron parameters should be 2x1"); 181 | 182 | mxTmp = mxGetField(prhs[3],0,"DeltaT"); 183 | DeltaT=mxGetPr(mxTmp); 184 | m1 = mxGetN(mxTmp); 185 | m2 = mxGetM(mxTmp); 186 | if(m1*m2!=2) 187 | mexErrMsgTxt("All neuron parameters should be 2x1"); 188 | 189 | mxTmp = mxGetField(prhs[3],0,"vT"); 190 | VT=mxGetPr(mxTmp); 191 | m1 = mxGetN(mxTmp); 192 | m2 = mxGetM(mxTmp); 193 | if(m1*m2!=2) 194 | mexErrMsgTxt("All neuron parameters should be 2x1"); 195 | mxTmp = mxGetField(prhs[3],0,"tref"); 196 | tref=mxGetPr(mxTmp); 197 | m1 = mxGetN(mxTmp); 198 | m2 = mxGetM(mxTmp); 199 | if(m1*m2!=2) 200 | mexErrMsgTxt("All neuron parameters should be 2x1"); 201 | mxTmp = mxGetField(prhs[3],0,"vth"); 202 | Vth=mxGetPr(mxTmp); 203 | m1 = mxGetN(mxTmp); 204 | m2 = mxGetM(mxTmp); 205 | if(m1*m2!=2) 206 | mexErrMsgTxt("All neuron parameters should be 2x1"); 207 | mxTmp = mxGetField(prhs[3],0,"vre"); 208 | Vre=mxGetPr(mxTmp); 209 | m1 = mxGetN(mxTmp); 210 | m2 = mxGetM(mxTmp); 211 | if(m1*m2!=2) 212 | mexErrMsgTxt("All neuron parameters should be 2x1"); 213 | mxTmp = mxGetField(prhs[3],0,"vlb"); 214 | Vlb=mxGetPr(mxTmp); 215 | m1 = mxGetN(mxTmp); 216 | m2 = mxGetM(mxTmp); 217 | if(m1*m2!=2) 218 | mexErrMsgTxt("All neuron parameters should be 2x1"); 219 | 220 | mxTmp = mxGetField(prhs[3],0,"taursyn"); 221 | m1=mxGetN(mxTmp); 222 | m2=mxGetM(mxTmp); 223 | if(m2!=3) 224 | mexErrMsgTxt("size(taursyn,1) should be 3"); 225 | Nsyntype=m1; 226 | taursyn=mxGetPr(mxTmp); 227 | 228 | mxTmp = mxGetField(prhs[3],0,"taudsyn"); 229 | m1=mxGetN(mxTmp); 230 | m2=mxGetM(mxTmp); 231 | if(m2!=3) 232 | mexErrMsgTxt("size(taudsyn,1) should be 3"); 233 | if(m1!=Nsyntype) 234 | mexErrMsgTxt("size(taursyn,1) should equal size(taudsyn,2)"); 235 | taudsyn=mxGetPr(mxTmp); 236 | 237 | mxTmp = mxGetField(prhs[3],0,"Psyn"); 238 | Psyn=mxGetPr(mxTmp); 239 | m2=mxGetM(mxTmp); 240 | if(m2!=3) 241 | mexErrMsgTxt("size(Psyn,1) should be 3"); 242 | m1=mxGetN(mxTmp); 243 | if(m1!=Nsyntype) 244 | mexErrMsgTxt("size(Psyn,2) should equal size(taursyn,2)"); 245 | 246 | syntype=mxMalloc(m1*m2*sizeof(int)); 247 | Nsyn = 0; 248 | for(isyn=0;isynN+1) 341 | mexErrMsgTxt("Indices in Irecord must be between 1 and N"); 342 | for(isyn=0;isyn=Nx){ 376 | mexPrintf("\n %d %d %d %d %d\n",(int)round(*(iXspkInd-1)/dt),iXspike,i,jspike,(int)round((*iXspkInd)-1)); 377 | mexErrMsgTxt("Out of bounds index in sx."); 378 | } 379 | Pr=&Wrf[jspike*Kx]; 380 | /* 381 | for(k=0;k=N){ 384 | mexPrintf("\n Wrf j=%d, postcell=%d\n",j, postcell); 385 | mexErrMsgTxt("postcell out of bounds"); 386 | } 387 | if (postcell=N){ 402 | mexPrintf("\n Wrf j=%d, postcell=%d\n",j, postcellX[k]); 403 | mexErrMsgTxt("postcell out of bounds"); 404 | } 405 | Pr++; 406 | } 407 | 408 | for(isyn=0;isyn1) 442 | v[j]=Vth[0]; 443 | else 444 | v[j]=Vre[0]; 445 | refstate[j]--; 446 | } 447 | 448 | /* If a spike occurs */ 449 | if(v[j]>=Vth[0] && refstate[j]<=0 && ns=N){ 462 | mexPrintf("\n Wrf j=%d, postcell=%d\n",j, postcell); 463 | mexErrMsgTxt("postcell out of bounds"); 464 | } 465 | if (postcell=N){ 480 | mexPrintf("\n exc j=%d, postcell=%d\n",j, postcellE[k]); 481 | mexErrMsgTxt("postcell out of bounds");} 482 | Pr++; 483 | } 484 | for(isyn=0;isyn1) 509 | v[j]=Vth[1]; 510 | else 511 | v[j]=Vre[1]; 512 | refstate[j]--; 513 | } 514 | 515 | /* If a spike occurs */ 516 | if(v[j]>=Vth[1] && refstate[j]<=0 && ns=N){ 528 | mexPrintf("\n Wrf j=%d, postcell=%d\n",j, postcell); 529 | mexErrMsgTxt("postcell out of bounds"); 530 | } 531 | if (postcell=N){ 547 | mexPrintf("\n inh j=%d, postcell=%d\n",j, postcellI[k]); 548 | mexErrMsgTxt("postcell out of bounds"); 549 | } 550 | Pr++; 551 | } 552 | for(isyn=0;isynN+1) 571 | mexErrMsgTxt("Indices in Irecord must be between 1 and N"); 572 | for(isyn=0;isyn=maxns) 581 | mexWarnMsgTxt("Maximum number of spikes reached, simulation terminated."); 582 | 583 | /* Free allocated memory */ 584 | mxFree(v); 585 | mxFree(refstate); 586 | mxFree(Isyn); 587 | mxFree(Isynprime); 588 | mxFree(temp1); 589 | mxFree(temp2); 590 | mxFree(postcellX); 591 | mxFree(postcellE); 592 | mxFree(postcellI); 593 | mxFree(syntype); 594 | } 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | -------------------------------------------------------------------------------- /FA.m: -------------------------------------------------------------------------------- 1 | % run after SimulationFig4E.m & spkcounts.m 2 | % spike counts data provided for nws=1 (set Nnws=1) 3 | 4 | addpath(genpath([pwd '/fa_Yu/'])); 5 | clear 6 | 7 | data_folder='data/'; 8 | 9 | Inh='slow'; fnamesave=[data_folder 'FA_model_Jex25.mat']; % Fig. 4b, Fig. 5b bottom (Nc=500, Nsample=1) 10 | % Inh='fast'; fnamesave=[data_folder 'FA_model_fastInh_Jex25.mat']; % Fig. 4c 11 | % Inh='broad'; fnamesave=[data_folder 'FA_model__broadInh_Jex25.mat']; % Fig. 4d, Fig. 5c bottom (Nc=500, Nsample=1) 12 | 13 | dim='2D'; 14 | 15 | testp.inE=[0]; 16 | testp.inI=[.2 .35]; 17 | Jx=25*[1;0.6]; 18 | dt=0.01; 19 | 20 | Nws=8; % number of weight matrix realizations 21 | Nsample=80; % 10 samples per weight matrix realization 22 | Np=2; 23 | M=5; % latent dimensionality to fit data 24 | Nc=50; % neuron number 25 | numFolds=2; % number of cross-validation folds 26 | corr=zeros(Nsample,Np); %mean correlation 27 | sumLL=zeros(M,Nsample,Np); % cross-validated log likelihood 28 | LLopt=zeros(Nsample,Np); % mode that maximizes the cross-validated log likelihood 29 | Lambda=zeros(M,Nsample,Np); % eigenvalues 30 | COVm=zeros(Nsample,Np); % mean covariance (raw) 31 | Qm=zeros(Nsample,Np); % residual covarince 32 | eigvector1=NaN(Nc,Nsample,Np); % first eigenvector 33 | SIGN=zeros(Nsample,Np); % sign of the mean of the first eigenvector 34 | zDimList=1:M; 35 | 36 | for nws=1:Nws 37 | fname=sprintf('%sRF2D3layer_fixW_%sInh_Jex25_Jix15_inI_dt0d01_Nc500_spkcount_nws%d',data_folder,Inh,nws); 38 | data=load(fname); 39 | idx=randperm(Nc*10); 40 | 41 | for pid=1:2 42 | for k=1:10 43 | ss=(nws-1)*10+k; 44 | Y=data.spkcount(pid).Y(idx((k-1)*Nc+1:k*Nc),:); 45 | COV=cov(Y'); 46 | U=triu(ones(size(COV)),1); 47 | R=corrcov(COV); 48 | corr(ss,pid)=mean(R(U==1)); 49 | dim = crossvalidate_fa(Y, 'zDimList', zDimList,'showPlots',false,'numFolds',numFolds); 50 | 51 | sumLL(:,ss,pid)=[dim.sumLL]; 52 | LLopt(ss,pid) = find(sumLL(:,ss,pid) == max(sumLL(:,ss,pid)),1); 53 | 54 | L=dim(M).estParams.L; 55 | LL=L*L'; 56 | [V,D]=eig(LL); 57 | la=diag(D); 58 | [m,I]=max(la); 59 | la=sort(la,'descend'); 60 | Lambda(:,ss,pid)=la(1:M); 61 | eigvector1(:,ss,pid)=V(:,I)*sign(sum(V(:,I))); 62 | SIGN(ss,pid)=sign(sum(V(:,I))); 63 | 64 | L1=dim(1).estParams.L; 65 | LL1=L1*L1'; 66 | Q=COV-LL1; 67 | COVm(ss,pid)=mean(COV(U==1)); 68 | Qm(ss,pid)=mean(Q(U==1)); 69 | 70 | end 71 | end 72 | end 73 | figure 74 | colorAU= [0 0.5000 0.4000; 75 | 0.9290 0.6940 0.1250]; 76 | state={'Unattended','Attended'}; 77 | hold on 78 | for pid=1:Np 79 | errorbar(1:M, mean(Lambda(:,:,pid),2),std(Lambda(:,:,pid),[],2)/sqrt(Nsample),'-','color',colorAU(pid,:)) 80 | text(.8, 1-pid*.1,state{pid},'unit','n','Horiz','center','color',colorAU(pid,:)) 81 | end 82 | xlabel('eigenmode') 83 | ylabel('eigenvalue') 84 | 85 | save(fnamesave,'corr','COVm','Qm','LLopt','Lambda','eigvector1','fname','M','Nc','numFolds','Nsample','testp') 86 | 87 | 88 | -------------------------------------------------------------------------------- /MakeFigure3.m: -------------------------------------------------------------------------------- 1 | function MakeFigure3(varargin) 2 | 3 | addpath(genpath([pwd '/figtools/'])); 4 | 5 | %% PARSE ARGUMENTS 6 | P = parsePairs(varargin); 7 | checkField(P,'FIG',1); checkField(P,'Save',1); checkField(P,'View',1); checkField(P,'Recompute',1); 8 | 9 | % SETUP BASICS 10 | cDir = ''; 11 | setPlotOpt('plos','path',cDir,'cols',2,'height',13); 12 | inpath=[cDir 'data/']; 13 | outpath=[cDir '']; 14 | Sep = '/'; 15 | 16 | % PREPARE FIGURE 17 | figure(P.FIG); clf; set(P.FIG,FigOpt{:}); HF_matchAspectRatio; 18 | DC = axesDivide([0.6 1.5 1.5 1.],[.6 1.5 3],[0.1 0.08 0.85 0.9], [.3 .6 .6],[0.5 .7 ])'; 19 | temp = axesDivide([0.6 1.5 1.5 1.],[1 1 1 1 2],[0.1 0.08 0.85 0.85], [.3 .6 .6],[0.2 1 .2 1])'; 20 | DC3=temp(4,:); 21 | 22 | DC([1 4],:)=[]; 23 | 24 | Labels = {'A','','D','B','','E','C','','F'}; LdPos = [-0.07,0.02]; 25 | for i = 1:numel(DC) 26 | AH(i) = axes('Pos',DC{i}); hold on; 27 | % FigLabel(Labels{i},LdPos); 28 | end 29 | for i = 1:numel(DC3) 30 | AH3(i) = axes('Pos',DC3{i}); hold on; 31 | end 32 | for iA=[5 6] 33 | axes(AH(iA)); 34 | axis off 35 | DC2=DC(iA); 36 | DC2{1}(3)=DC2{1}(3)*.6; 37 | DC2{1}(1)=DC2{1}(1); 38 | DC2{1}(4)=DC2{1}(4)/2; 39 | DC2{1}(2)=DC2{1}(2)+DC2{1}(4); 40 | DC2{2}=DC2{1}; 41 | DC2{2}(2)=DC2{1}(2)-DC2{1}(4)*.6; 42 | DC2{2}(1)=DC2{1}(1)+DC2{1}(3)*.4; 43 | DC2{3}=DC2{2}; 44 | DC2{3}(2)=DC2{2}(2)-DC2{2}(4)*.6; 45 | DC2{3}(1)=DC2{2}(1)+DC2{2}(3)*.4; 46 | for i = 1:numel(DC2) 47 | AH2(i,iA) = axes('Pos',DC2{i}); hold on; 48 | end 49 | end 50 | 51 | HF_setFigProps; 52 | 53 | % sample raster 54 | Nc=200; % # of sampled neurons 55 | t1=1000;t2=1400; 56 | if P.Recompute 57 | LF_generateData([inpath 'RF2D_uniformW_tausyni8'],Nc,t1,t2); 58 | LF_generateData([inpath 'RF2D_uniformW_tausyni1'],Nc,t1,t2); 59 | end 60 | 61 | % START PLOTTING 62 | 63 | T0=[4600 4618 4628]; % snapshot time 64 | 65 | data{2,2}=load([inpath 'RF2D_broadRec_tausyni8'],'s0','rate','R'); 66 | data{2,1}=load([inpath 'RF2D_broadRec_tausyni1'],'s0','rate','R'); 67 | data{1,2}=load([inpath 'RF2D_uniformW_tausyni8'],'ts','Ic','rate','R','taursyni','taudsyni','taursyne','taudsyne'); 68 | data{1,1}=load([inpath 'RF2D_uniformW_tausyni1'],'ts','Ic','rate','R','taursyni','taudsyni','taursyne','taudsyne'); 69 | 70 | Ne1=200; 71 | colororder=lines(3); 72 | 73 | for jj=1:2 74 | iA=jj; 75 | axes(AH(iA)); 76 | taursyni=data{1,jj}.taursyni;taudsyni=data{1,jj}.taudsyni; 77 | taursyne=data{1,jj}.taursyni;taudsyne=data{1,jj}.taudsyne; 78 | syn_t=linspace(0,30,201); 79 | synE=(exp(-syn_t./taursyne)-exp(-syn_t./taudsyne))/(taursyni-taudsyne); 80 | synI=(exp(-syn_t./taursyni)-exp(-syn_t./taudsyni))/(taursyni-taudsyni); 81 | plot(syn_t,synE,'-','color',colororder(jj,:)); 82 | plot(syn_t,synI,'--','color',colororder(jj,:)); 83 | if jj==1 84 | plot([15 20], [.5 .5],'k') 85 | text(23,.5,'EPSC','unit','data','color','k') 86 | plot([15 20], [.3 .3],'--k') 87 | text(23,.3,'IPSC','unit','data','color','k') 88 | plot([0 5],[-.1 -.1],'k') 89 | text(0,-0.3,'5 ms','unit','data','color','k') 90 | end 91 | ylim([-.1 .5]) 92 | axis off 93 | end 94 | 95 | ii=1; 96 | for jj=1:2 97 | iA=2*ii+jj; 98 | axes(AH(iA)); 99 | ts=data{ii,jj}.ts; 100 | Ic=data{ii,jj}.Ic; 101 | for mm=1:Nc 102 | plot(ts{mm},mm*ones(size(ts{mm})),'k.','markersize',3) 103 | end 104 | axis([t1 t2 1 Nc]) 105 | xlabel('time (ms)') 106 | ylabel('neuron ID') 107 | end 108 | ii=2; 109 | for jj=1:2 110 | iA=2*ii+jj; 111 | s0=data{ii,jj}.s0; 112 | for k=1:3 113 | t1=T0(k); 114 | axes(AH2(k,iA)) 115 | Is=find(s0(1,:)<=t1 & s0(1,:)>t1-1 & s0(2,:)t1 & Ic(mm)-1/4 \sigma_e'}; 86 | for ss=1:2 87 | iA=ss+1; 88 | axes(AH(iA)); 89 | colororder=copper(numel(data2.taui_use)); 90 | for j = 1:1:numel(data2.taui_use) 91 | plot(data2.wavenums, data2.Lambdas(ss).maxreallam(j,:),'color',colororder(j,:)) 92 | text(.7,.1*(j-1)+.1,sprintf('%.1f ms',data2.taui_use(j)),'unit','n','color',colororder(j,:)) 93 | end 94 | xlim([0 5]) 95 | plot(xlim,[0 0],'k--') 96 | xlabel('Wavenumber') 97 | ylabel('Max Re(\lambda)') 98 | title(Titles{ss}) 99 | end 100 | 101 | HF_setFigProps; 102 | 103 | % SAVE FIGURES 104 | % set(gcf, 'Renderer', 'opengl') 105 | set(gcf, 'Renderer', 'painters') 106 | HF_viewsave('path',outpath,'name',name,'view',P.View,'save',P.Save,'format','pdf','res',600); 107 | 108 | -------------------------------------------------------------------------------- /MakeFigure6.m: -------------------------------------------------------------------------------- 1 | function MakeFigure6(varargin) 2 | 3 | addpath(genpath('~/Dropbox/Matlab_codes/BE_figTools/')) 4 | %% PARSE ARGUMENTS 5 | P = parsePairs(varargin); 6 | checkField(P,'FIG',1); checkField(P,'Save',1); checkField(P,'View',1); checkField(P,'Recompute',0); 7 | 8 | % SETUP BASICS 9 | cDir = ''; 10 | setPlotOpt('custom','path',cDir,'cols',1,'height',9); 11 | inpath=[cDir 'data/']; 12 | outpath=[cDir '']; 13 | Sep = '/'; 14 | 15 | % PREPARE FIGURE 16 | figure(P.FIG); clf; set(P.FIG,FigOpt{:}); HF_matchAspectRatio; 17 | DC = axesDivide(2,2,[0.13 0.13 0.8 0.8], 0.5, .6)'; 18 | 19 | Labels = {'A','B','C','D'}; LdPos = [-0.07,0.04]; 20 | for i = 1:numel(DC) 21 | AH(i) = axes('Pos',DC{i}); hold on; 22 | set(gca,'linewidth',1) 23 | set(gca,'fontsize',8) 24 | % FigLabel(Labels{i},LdPos); 25 | end 26 | 27 | if P.Recompute 28 | LF_generateData(fname,inpath); 29 | end 30 | 31 | HF_setFigProps; 32 | 33 | % START PLOTTING 34 | % load(fname); 35 | 36 | data=load([inpath 'FA_model_slowInh_Jex25_dist']); 37 | load([inpath 'FA_data_dist']) 38 | 39 | colorAU= [0 0.5000 0.4000; 40 | 0.9290 0.6940 0.1250]; 41 | 42 | M=5; 43 | colororder=copper(M); 44 | 45 | %%%%%%%%%%%% V4 data %%%%%%%%%%%%%%%%%%% 46 | % discard data points at distances at zero and >2mm 47 | d1=d1(2:14); % distance between electrodes 48 | cov_d=cov_d(2:14,:); 49 | cov_d_std=cov_d_std(2:14,:); 50 | cov_d_Npair=cov_d_Npair(2:14,:); 51 | LL_d=LL_d(2:14,:,:); 52 | LL_d_std=LL_d_std(2:14,:,:); 53 | LL_d_Npair=LL_d_Npair(2:14,:,:); 54 | 55 | % average across sessions 56 | for pid=1:2 57 | for kk=1:length(d1) 58 | for mm=1:M 59 | for trial=1:72 60 | LL_d_tot{kk,mm,trial,pid}=LL_d_tot{kk,mm,trial,pid}*Lambda(mm,trial,pid); 61 | end 62 | LL_d(kk,mm,pid)=mean([LL_d_tot{kk,mm,:,pid}]); 63 | LL_d_std(kk,mm,pid)=std([LL_d_tot{kk,mm,:,pid}]); 64 | LL_d_Npair(kk,mm,pid)=length([LL_d_tot{kk,mm,:,pid}]); 65 | end 66 | 67 | end 68 | end 69 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 70 | 71 | iA=1; 72 | axes(AH(iA)); 73 | M=5; 74 | Ntrial=size(data.cov_d,2); 75 | for pid=1:2 76 | shadedErrorBar(data.daxis,mean(data.cov_d(1:20,:,pid),2),std(data.cov_d(1:20,:,pid),[],2)./sqrt(Ntrial),{'color',colorAU(pid,:),'linewidth',1}) 77 | end 78 | ylim([-.1 .8]) 79 | xlim([0 .5]) 80 | text(.6,.9,'Unattended','unit','n','Horiz','left','color',colorAU(1,:),'fontsize',8) 81 | text(.6,.7,'Attended','unit','n','Horiz','left','color',colorAU(2,:),'fontsize',8) 82 | set(gca,'xtick',[0,.25 .5]) 83 | xlabel('distance (a.u.)') 84 | ylabel('Covariance') 85 | title('Model') 86 | 87 | iA=3; 88 | axes(AH(iA)); 89 | for mm=1:M 90 | data.LL_d{1}(1:20,mm,:)=data.LL_d{1}(1:20,mm,:).*permute(repmat(data.Lambda(mm,:,1),[20,1]),[1,3,2]); 91 | shadedErrorBar(data.daxis,mean(data.LL_d{1}(1:20,mm,:),3),... 92 | std(data.LL_d{1}(1:20,mm,:),[],3)./sqrt(Ntrial),{'color',colororder(mm,:),'linewidth',1}) 93 | text(1.,1-.1*mm,sprintf('%d',mm),'unit','n','color',colororder(mm,:),'fontsize',8) 94 | end 95 | text(1.,1,'mode','Horiz','c','unit','n','color','k','fontsize',8) 96 | xlim([0 .5]) 97 | ylim([-.05 0.2 ]) 98 | set(gca,'xtick',[0,.25 .5]) 99 | xlabel('distance (a.u.)') 100 | ylabel('\lambda_iv_i*v_i^T') 101 | 102 | iA=2; 103 | axes(AH(iA)); 104 | for pid=1:2 105 | shadedErrorBar(d1*.4,cov_d(:,pid),cov_d_std(:,pid)./sqrt(cov_d_Npair(:,pid)),{'color',colorAU(pid,:),'linewidth',1}) 106 | end 107 | title('V4 data') 108 | xlabel('distance (mm)') 109 | set(gca','xtick',0:1:3) 110 | xlim([0 2.1]) 111 | ylim([-0.05 .4]) 112 | 113 | iA=4; 114 | axes(AH(iA)); 115 | for mm=1:M 116 | shadedErrorBar(d1*.4,LL_d(:,mm,1),LL_d_std(:,mm,1)./sqrt(LL_d_Npair(:,mm,1)),{'color',colororder(mm,:),'linewidth',1}) 117 | end 118 | xlim([0 2.1]) 119 | ylim([-.05 0.3]) 120 | set(gca','xtick',0:1:3) 121 | xlabel('distance (mm)') 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | HF_setFigProps; 132 | 133 | % SAVE FIGURES 134 | % set(gcf, 'Renderer', 'opengl') 135 | set(gcf, 'Renderer', 'painters') 136 | HF_viewsave('path',outpath,'name',name,'view',P.View,'save',P.Save,'format','pdf','res',600); 137 | -------------------------------------------------------------------------------- /MakeFigure7.m: -------------------------------------------------------------------------------- 1 | function MakeFigure7(varargin) 2 | 3 | addpath(genpath([pwd '/figtools/'])); 4 | 5 | %% PARSE ARGUMENTS 6 | P = parsePairs(varargin); 7 | checkField(P,'FIG',1); checkField(P,'Save',1); checkField(P,'View',1); checkField(P,'Recompute',1); 8 | 9 | % SETUP BASICS 10 | cDir = ''; 11 | setPlotOpt('custom','path',cDir,'cols',2,'height',10); 12 | inpath=[cDir 'data/']; 13 | outpath=[cDir '']; 14 | Sep = '/'; 15 | 16 | % PREPARE FIGURE 17 | figure(P.FIG); clf; set(P.FIG,FigOpt{:}); HF_matchAspectRatio; 18 | DC = axesDivide([2 1 2 1 1.5],4,[0.07 0.1 0.9 0.83], [.15 .8 .15 .6], 0.4)'; 19 | temp = axesDivide([2 1 2 1 1.5],[1 1 .8 1.2],[0.07 0.1 0.9 0.83], [.15 .8 .15 1], [0.4 .5 .6])'; 20 | DC=DC(:); 21 | DC(5:5:20)=temp(5:5:20); 22 | DC{15}=DC{10}; 23 | DC{15}(2)=DC{15}(2)+DC{15}(4)*.5; 24 | DC{15}(1)=DC{15}(1)+DC{15}(3)*.5; 25 | DC{15}(4)=DC{15}(4)*.5; 26 | DC{15}(3)=DC{15}(3)*.5; 27 | 28 | DC{20}(4)=DC{20}(4)*.9; 29 | DC{21}=DC{20}; 30 | DC{20}(2)=DC{20}(2)+DC{20}(4)*1.1; 31 | 32 | Labels = {'A','B','C','D','E','F'}; LdPos = [-0.065,0.02]; 33 | 34 | for i = 1:numel(DC) 35 | AH(i) = axes('Pos',DC{i}); hold on; 36 | % FigLabel(Labels{i},LdPos); 37 | % AH2(i) = axes('Pos',DC2{i}); hold on; 38 | end 39 | 40 | T0=1864+1.1e4; 41 | 42 | fname1=[inpath 'RF2D3layer_fixW_Jex25_Jix15_Ntrial10_Nrep20_Re.mat']; 43 | fname2=[inpath 'RF2D3layer_fixW_Jex25_Jix15_MacroChaos_rasters.mat']; 44 | 45 | if P.Recompute 46 | LF_generateData(fname1); 47 | LF_ffwdinput(fname2,T0) 48 | end 49 | 50 | HF_setFigProps; 51 | 52 | Titles={'Unattended','Attended'}; 53 | colorAU= [0 0.5000 0.4000; 54 | 0.9290 0.6940 0.1250]; 55 | 56 | % START PLOTTING 57 | load(fname1) 58 | load(fname2) 59 | 60 | Ne1=200; 61 | Nrep=20; 62 | tf=-100:100; 63 | sig_f=2; 64 | hf=exp(-tf.^2/(2*sig_f^2)); 65 | hf=hf/sum(hf); 66 | 67 | for pid=1:2 68 | for row=1:4 69 | if row<=3 70 | iA=(row-1)*5+pid*2-1; 71 | axes(AH(iA)) 72 | re2=imfilter(Re2{pid,Reps(row),trial},hf); 73 | re2=re2(t1:t2); 74 | plot((t1:t2)-t1,re2) 75 | xlim([0 t2-t1]) 76 | ylim([0 150]) 77 | set(gca,'xtick',[]) 78 | plot((T0-t1)*[1 1],ylim,'k--') 79 | if row==1 80 | title(Titles{pid}) 81 | end 82 | if pid==1 && row==2 83 | h_text=text(-.3,.5,'popuplation rate (sp/s)','unit','n','color','k','horiz','center'); 84 | set(h_text, 'rotation', 90) 85 | end 86 | if pid==1 87 | text(0.2,0.8,sprintf('trial %d',row),'unit','n','color','k','horiz','center'); 88 | end 89 | 90 | iA=(row-1)*5+pid*2; 91 | axes(AH(iA)) 92 | s2=res(pid,row).s2; 93 | Is=find(s2(1,:)<=T0 & s2(1,:)>T0-2 & s2(2,:)(T0-500)); 213 | Input_s1=zeros(200,200); 214 | t=linspace(0,500,5001); 215 | epsc= @(t) 0.2*(exp(-t./param(2).taudsyn(1,1))-exp(-t./param(2).taursyn(1,1)))/(param(2).taudsyn(1,1)-param(2).taursyn(1,1))+0.8*(exp(-t./param(2).taudsyn(1,2))-exp(-t./param(2).taursyn(1,2)))/(param(2).taudsyn(1,2)-param(2).taursyn(1,2)); 216 | for k=1:200^2 217 | tsps=s1(1,s1(2,:)k-0.1); 218 | Input_s1(k)=sum(epsc(T0-tsps)); 219 | end 220 | 221 | pex0=param(2).Prx(1); 222 | pix0=param(2).Prx(2); 223 | Ne=200^2;Ni=100^2; 224 | Kex=ceil(pex0*Ne); 225 | Kix=ceil(pix0*Ni); 226 | Kx=Kex+Kix; 227 | rng(Wseed) 228 | [Wrr2,Wrf2]=gen_weights(param(2).Ne,param(2).Ni,param(2).Nx,param(2).sigmaRX,param(2).sigmaRR,param(2).Prr,param(2).Prx,'2D'); 229 | clear Wrr2 230 | Input=zeros(200,200); 231 | for k=1:200^2 232 | post=Wrf2((k-1)*Kx+1:(k-1)*Kx+Kex); 233 | [c,post]=hist(post,unique(post)); 234 | Input(post)=Input(post)+c'.*Input_s1(k); 235 | end 236 | rng('shuffle') 237 | save(fname,'Input_s1','Input','-append') 238 | 239 | function LF_generateData(fname) 240 | load(fname) 241 | t_h=0:500; 242 | hs=(exp(-t_h/100)-exp(-t_h/2))./(100-2); 243 | hf=(exp(-t_h/5)-exp(-t_h/1))./(5-1); 244 | Tw=200; % sliding window size 245 | Tburn=1000; 246 | Nstep=10; %step size for sliding window 247 | Nt=ceil((T-Tburn-Tw)/Nstep); 248 | Re2_s=zeros(Nt,Nrep); 249 | re1syn_s=cell(Np,Ntrial); 250 | Rvar=cell(Np,Ntrial); 251 | Rmean_s=cell(Np,Ntrial); 252 | Re2m=cell(Np,Ntrial); 253 | for pid=1:Np 254 | for trial=1:Ntrial 255 | Re2m{pid,trial}=zeros(size(Re2{pid,1,trial})); 256 | for nrep=1:Nrep 257 | re2_s=(imfilter(Re2{pid,nrep,trial}(Tburn+1:end),ones(1,Tw)/Tw)); 258 | re2_s=re2_s(Tw/2+1:Nstep:end-Tw/2-1); 259 | Re2_s(:,nrep)=re2_s'; 260 | Re2m{pid,trial}=Re2m{pid,trial}+Re2{pid,nrep,trial}; 261 | end 262 | Re2m{pid,trial}=Re2m{pid,trial}/Nrep; 263 | Rvar{pid,trial}=var(Re2_s,[],2); 264 | Rmean_s{pid,trial}=mean(Re2_s,2); 265 | re1syn_s{pid,trial}=Re1{pid,trial}; 266 | re1syn_s{pid,trial}=imfilter(re1syn_s{pid,trial}(Tburn+1:end),ones(1,Tw)/Tw); 267 | re1syn_s{pid,trial}=re1syn_s{pid,trial}(Tw/2+1:Nstep:end-Tw/2-1); 268 | end 269 | end 270 | save(fname,'Rvar','Rmean_s','re1syn_s','Nstep','Re2m','-append') 271 | 272 | 273 | -------------------------------------------------------------------------------- /MakeFigure_1C_4E.m: -------------------------------------------------------------------------------- 1 | function MakeFigure_1C_4E(varargin) 2 | % Fig. 1C, Fig 4E & Fig. S6A-C,F-H 3 | % no distance 4 | addpath(genpath([pwd '/figtools/'])); 5 | 6 | %% PARSE ARGUMENTS 7 | P = parsePairs(varargin); 8 | checkField(P,'FIG',1); checkField(P,'Save',1); checkField(P,'View',1); checkField(P,'Recompute',0); 9 | 10 | % SETUP BASICS 11 | cDir = ''; 12 | setPlotOpt('plos','path',cDir,'cols',1.5,'height',16); 13 | inpath=[cDir 'data/']; 14 | outpath=[cDir '']; 15 | Sep = '/'; 16 | 17 | % PREPARE FIGURE 18 | figure(P.FIG); clf; set(P.FIG,FigOpt{:}); HF_matchAspectRatio; 19 | DC = axesDivide(3 ,4,[0.12 0.08 0.8 0.86], [0.4 .6], .4); 20 | for kk=1:4 21 | iA=kk+4; 22 | DC{iA}(4)=DC{iA}(4)*.75; 23 | end 24 | Labels = {'A1','B1','C1','D1','A2','B2','C2','D2','A3','B3','C3','D3'}; LdPos = [-0.07,0.04]; 25 | for i = 1:numel(DC) 26 | AH(i) = axes('Pos',DC{i}); hold on; 27 | % FigLabel(Labels{i},LdPos); 28 | end 29 | fname=[inpath 'GPFA_sim2']; 30 | if P.Recompute 31 | LF_generateData(fname,inpath); 32 | set(gca,'linewidth',1) 33 | end 34 | 35 | HF_setFigProps; 36 | 37 | % START PLOTTING 38 | % load(fname); 39 | data(1)=load([inpath 'FA_data'],'Lambda','COVm','Qm','eigvector1'); 40 | data(2)=load([inpath 'FA_model_Jex25'],'Lambda','COVm','Qm','eigvector1'); 41 | data(3)=load([inpath 'FA_model_fastInh_Jex25'],'Lambda','COVm','Qm','eigvector1'); 42 | data(4)=load([inpath 'FA_model_broadInh_Jex25'],'Lambda','COVm','Qm','eigvector1'); 43 | 44 | eigvector{1}=[[data(1).eigvector1{:,1}]',[data(1).eigvector1{:,2}]']; 45 | eigvector{2}=reshape(data(2).eigvector1(:,:,[3 6]),[],2); 46 | eigvector{3}=reshape(data(3).eigvector1,[],2); 47 | eigvector{4}=reshape(data(4).eigvector1,[],2); 48 | data(2).Lambda=data(2).Lambda(:,:,[3 6]); 49 | data(2).COVm=data(2).COVm(:,[3 6]); 50 | data(2).Qm=data(2).Qm(:,[3 6]); 51 | 52 | colorAU= [0 0.5000 0.4000; 53 | 0.9290 0.6940 0.1250]; 54 | Titles={'V4 data','model','model w/ fast Inh','model w/ broad Inh'}; 55 | YLims2={[0 20],[0 40],[0 10],[0 100]}; 56 | for kk=1:4 57 | iA=kk; 58 | axes(AH(iA)); 59 | M=5; 60 | Ntrial=size(data(kk).Lambda,2); 61 | for pid=1:2 62 | errorbar(1:M,mean(data(kk).Lambda(1:M,:,pid),2),std(data(kk).Lambda(1:M,:,pid),[],2)/sqrt(Ntrial),'color',colorAU(pid,:),'linewidth',1) 63 | end 64 | ylim(YLims2{kk}) 65 | xlim([0 5]) 66 | set(gca,'xtick',0:5) 67 | set(gca,'ytick',[0 YLims2{kk}(2)/2 YLims2{kk}(2)]) 68 | if kk==4 69 | xlabel('eigenmode') 70 | end 71 | ylabel('eigenvalue') 72 | title(Titles{kk}) 73 | if kk==1 74 | text(.6,.9,'Unattended','unit','n','Horiz','left','color',colorAU(1,:),'fontsize',8) 75 | text(.6,.7,'Attended','unit','n','Horiz','left','color',colorAU(2,:),'fontsize',8) 76 | end 77 | end 78 | 79 | for kk=1:4 80 | iA=kk+4; 81 | axes(AH(iA)); 82 | edges=-.5:.05:.5; 83 | for pid=1:2 84 | [h, edges0]=histcounts(eigvector{kk}(:,pid),edges); 85 | stairs(edges(1:end-1),h/sum(h),'color',colorAU(pid,:),'linewidth',1) 86 | end 87 | if kk==1 88 | ylim([0 .3]) 89 | else 90 | ylim([0 .24]) 91 | end 92 | plot([0 0],ylim,'k--','linewidth',1) 93 | xlim([-.5 .5]) 94 | set(gca,'xtick',[-.5 0 .5]) 95 | set(gca,'ytick',[]) 96 | title('1st mode') 97 | xlabel('projection weight') 98 | end 99 | 100 | YLims1={[-0.02 1],[0 .8],[0 .08],[-.2 .6]}; 101 | for kk=1:4 102 | iA=kk+8; 103 | axes(AH(iA)); 104 | Ns=size(data(kk).COVm,1); 105 | dw=0.2; 106 | Xoffset=[-.2 .2]; 107 | for pid=1:2 108 | Xpos=[1 2]+Xoffset(pid); 109 | plot(ones(Ns,1)*Xpos+dw*(rand(Ns,2)-0.5), [data(kk).COVm(:,pid), data(kk).Qm(:,pid)],'.','color',colorAU(pid,:),'markersize',5) 110 | plot(Xpos(1)+[-dw dw],mean(data(kk).COVm(:,pid))*[1 1],'k-','linewidth',1) 111 | plot(Xpos(2)+[-dw dw],mean(data(kk).Qm(:,pid))*[1 1],'k-','linewidth',1) 112 | errorbar(Xpos(1),mean(data(kk).COVm(:,pid)),std(data(kk).COVm(:,pid)),'k-','CapSize',5) 113 | errorbar(Xpos(2),mean(data(kk).Qm(:,pid)),std(data(kk).Qm(:,pid)),'k-','CapSize',5) 114 | end 115 | ylim(YLims1{kk}) 116 | xlim([0.5 2.5]) 117 | ylabel('covariance') 118 | set(gca,'xtick',[1 2]) 119 | set(gca,'xticklabel',{'raw','residual'}) 120 | end 121 | 122 | 123 | 124 | HF_setFigProps; 125 | 126 | % SAVE FIGURES 127 | % set(gcf, 'Renderer', 'opengl') 128 | set(gcf, 'Renderer', 'painters') 129 | HF_viewsave('path',outpath,'name',name,'view',P.View,'save',P.Save,'format','pdf','res',600); 130 | -------------------------------------------------------------------------------- /MakeFigure_4BCD.m: -------------------------------------------------------------------------------- 1 | function MakeFigure_4BCD(varargin) 2 | 3 | addpath(genpath([pwd '/figtools/'])); 4 | 5 | %% PARSE ARGUMENTS 6 | P = parsePairs(varargin); 7 | checkField(P,'FIG',1); checkField(P,'Save',1); checkField(P,'View',1); checkField(P,'Recompute',0); 8 | 9 | % SETUP BASICS 10 | cDir = ''; 11 | setPlotOpt('manuscript','path',cDir,'cols',1.5,'height',12); 12 | inpath=[cDir 'data/']; 13 | outpath=[cDir '']; 14 | Sep = '/'; 15 | 16 | % PREPARE FIGURE 17 | figure(P.FIG); clf; set(P.FIG,FigOpt{:}); HF_matchAspectRatio; 18 | pos=[0.1 0.1 0.85 0.85]; 19 | DC = axesDivide(2,2,pos, 0.4, .6)'; 20 | DC(1)=DC(2); 21 | DC{1}(4)=DC{1}(4)*.45; 22 | DC{2}(4)=DC{2}(4)*.45; 23 | DC{1}(2)=DC{1}(2)+DC{1}(4)/.45*.55; 24 | 25 | 26 | Labels = {'A','B','C','D','E','F','G'}; LdPos = [-0.07,0.02]; 27 | for i = 1:numel(DC) 28 | AH(i) = axes('Pos',DC{i}); hold on; 29 | % FigLabel(Labels{i},LdPos); 30 | end 31 | HF_setFigProps; 32 | 33 | colorAU= [0 0.5000 0.4000; 34 | 0.9290 0.6940 0.1250]; 35 | state={'Unattended','Attended'}; 36 | 37 | fnames=[inpath 'Fig3data.mat']; 38 | load(fnames) 39 | Ntrial=size(Corr,3); 40 | Np=length(testp.inI); 41 | 42 | % START PLOTTING 43 | 44 | for iA=1:2 45 | axes(AH(iA)); 46 | plot(0:1e-3:20,Re{iA},'color',colorAU(iA,:)) 47 | axis([0 20 0 400]) 48 | text(.5,.9,state{iA},'unit','n','Horiz','center','color','k') 49 | xlabel('Time (sec)') 50 | if iA==2 51 | text(-0.2,1.2,'Pop. rate (Hz)','unit','n','Horiz','center','color','k','Rot',90) 52 | end 53 | end 54 | 55 | iA=3; 56 | axes(AH(iA)); 57 | errorbar(testp.inI,mean(Corr(:,1,:),3),std(Corr(:,1,:),[],3)/sqrt(Ntrial),'k','linewidth',1) 58 | plot(testp.inI(3), mean(Corr(3,1,:),3),'o','color',colorAU(1,:)) 59 | plot(testp.inI(6), mean(Corr(6,1,:),3),'o','color',colorAU(2,:)) 60 | axis([.05 .45 .055 .1]) 61 | set(gca,'ytick',[.06 .08 .1]) 62 | xlabel('Attention drive to inh') 63 | ylabel('Correlation (MT-MT)') 64 | 65 | iA=4; 66 | axes(AH(iA)); 67 | errorbar(testp.inI,mean(Corr(:,2,:),3),std(Corr(:,2,:),[],3)/sqrt(Ntrial),'k','linewidth',1) 68 | plot(testp.inI(3), mean(Corr(3,2,:),3),'o','color',colorAU(1,:)) 69 | plot(testp.inI(6), mean(Corr(6,2,:),3),'o','color',colorAU(2,:)) 70 | axis([.05 .45 .015 .04]) 71 | set(gca,'ytick',[.02 .03 .04]) 72 | xlabel('Attention drive to inh') 73 | ylabel('Correlation (V1-MT)') 74 | 75 | 76 | HF_setFigProps; 77 | 78 | % SAVE FIGURES 79 | % set(gcf, 'Renderer', 'opengl') 80 | set(gcf, 'Renderer', 'painters') 81 | HF_viewsave('path',outpath,'name',name,'view',P.View,'save',P.Save,'format','pdf','res',600); 82 | 83 | 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This folder contains Matlab (R2015a) and C codes for the manuscript: 2 | Huang C, Ruff DA, Pyle R, Rosenbaum R, Cohen MR and Doiron B (2019) “Circuit models of low dimensional shared variability in cortical networks”, Neuron 101, 337-348, doi: https://doi.org/10.1016/j.neuron.2018.11.034. 3 | 4 | ++++++++++++++++++++++++++++++++ 5 | 6 | To use, first compile all the C codes with the mex compiler in Matlab. Specifically, in the Matlab command line, run the following commands: 7 | mex EIF1DRFfastslowSyn.c 8 | mex spktime2count.c 9 | 10 | Scripts of different network simulations are named Simulation_FigX.m, where X is the Figure number. 11 | 12 | Scripts for generating corresponding figures are MakeFigureX.m. 13 | 14 | RF2D3layer.m is the main simulation function. It contains default parameter values and uses the mex file EIF1DRFfastslowSyn.c for integration. 15 | 16 | demo.m is a demonstration code for two-layer network simulations. 17 | 18 | FA.m is a script for factor analysis, which uses the codes from /fa_Yu/, courtesy of Byron Yu. 19 | 20 | figtools/ folder contains utility functions for figure formatting, courtesy of Bernhard Englitz. 21 | 22 | data/ folder contains part of the data used for plotting figures. 23 | 24 | corr_d.m computes correlation as a function of distance. 25 | 26 | spkcounts.m converts spike time data to spike counts. 27 | 28 | raster2D_ani.m generates movie of spike rasters from 2D spatial networks. 29 | 30 | +++++++++++++++++++++++++++++++++++ 31 | 32 | One simulation of a two-layer network for 20 sec takes about 1.5 hours CPU time and under 3 gb memory. 33 | (Simulation_Fig2.m) 34 | 35 | One simulation of a three-layer network for 20 sec takes about 3.5 hours CPU time and under 3 gb memory. 36 | (Simulation_Fig3.m, Simulation_Fig4.m, Simulation_Fig6.m) 37 | 38 | -------------------------------------------------------------------------------- /RF2D3layer.m: -------------------------------------------------------------------------------- 1 | function RF2D3layer(varargin) 2 | % RF2D3layer(option, ParamChange) 3 | 4 | % param is a struc w/ fields: Ne, Ni, Nx, Jx, Jr, Kx, Kr, 5 | % gl, Cm, vlb, vth, DeltaT, vT, vl, vre, tref, tausyn, V0, T, dt, 6 | % maxns, Irecord, Psyn 7 | % Jx=[Jex; Jix]; Jr=[Jee, Jei; Jie, Jii]; 8 | % Kx=[Kex; Kix]; Kr=[Kee, Kei; Kie, Kii]; % out-degrees are fixed 9 | % taursyn: syn rise time const, 3x(Nsyntype), rows: X, E, I; cols: syn type 10 | % taudsyn: syn decay time const, 3x(Nsyntype), rows: X, E, I; cols: syn type 11 | % Psyn(i,j): percentage of synapse j for (X, E, I (i=1,2,3)) 12 | % sigmaRR=[sigmaee, sigmaei; sigmaie, sigmaii]; 13 | % sigmaRX=[sigmaeX; sigmaiX]; 14 | 15 | % Wrr is a vector of connections among the recurrent layer, containing postsynaptic cell indices, 16 | % sorted by the index of the presynaptic cell. The block of postsynaptic cell indices for each presynaptic 17 | % cell is sorted as excitatory followed by inhibitory cells. I use fixed number of projections Kab to each population. 18 | % For example, Wrr[j*(Kee+Kie)] to Wrr[j*{Kee+Kie)+Kee-1] are connections from j to E pop and 19 | % Wrr[j*(Kee+Kie)+Kee] to Wrr[(j+1)*{Kee+Kie)-1] are connections from j to I pop. 20 | % Wrf is a vector of connections from the feedforward layer to the recurrent layer, sorted by the index of the presynaptic cell. 21 | % The block of postsynaptic cell indices for each presynaptic cell is sorted as excitatory followed by inhibitory cells. 22 | 23 | % conversion of neuron ID (exc) to (x,y) coordinate in [1, Ne1]x[1, Ne1]: 24 | % exc. ID [1, Ne], x=ceil(I/Ne1); y=(mod((I-1),Ne1)+1); ID=(x-1)*Ne1+y 25 | % inh. ID [Ne+1, Ne+Ni], x=ceil((I-Ne)/Ni1); y=(mod((I-Ne-1),Ni1)+1); ID=(x-1)*Ni1+y+Ne; 26 | 27 | % sx: spike trains from Layer0 28 | % sx(1,:) contains spike times. 29 | % sx(2,:) contains indices of neurons that spike 30 | % s1: spike trains from Layer1 31 | % s2: spike trains from Layer2 32 | % 33 | % data save in filename 34 | % options is a struct w/ fields: 35 | % 'save','CompCorr','plotPopR','fixW','loadS1','Layer1only'. Default values are 0. 36 | % ParamChange is a cell of 2 columns, 37 | % the 1st column is variable names and 38 | % the 2nd column is the values. 39 | 40 | % if options.save is 1, ParamChange needs to have field 'filename'. 41 | % if options.CompCorr is 1, ParamChange needs to have field 'Nc',e.g. Nc=[500 500]; 42 | % # of neurons to sample from Layer2 & Layer3. 43 | % if options.fixW is 1, ParamChange needs to have field 'Wseed1' & 'Wseed2'. 44 | 45 | nVarargs = length(varargin); 46 | switch nVarargs 47 | case 1 48 | option = varargin{1}; 49 | case 2 50 | option = varargin{1}; 51 | ParamChange = varargin{2}; 52 | end 53 | 54 | if ~isfield(option, 'save') option.save=0; end 55 | if ~isfield(option, 'CompCorr') option.CompCorr=0; end 56 | if ~isfield(option, 'loadS1') option.loadS1=0; end 57 | if ~isfield(option, 'fixW') option.fixW=0; end 58 | if ~isfield(option, 'plotPopR') option.plotPopR=0; end 59 | if ~isfield(option, 'Layer1only') option.Layer1only=0; end 60 | 61 | if option.save==1 62 | if ~ismember('filename',ParamChange(:,1)) 63 | error('No filename to save data') 64 | end 65 | end 66 | if option.CompCorr==1 67 | if ~ismember('Nc',ParamChange(:,1)) 68 | error('No Nc (1x2): # of neurons to sample to compute correlations') 69 | end 70 | end 71 | if option.loadS1==1 72 | if ~ismember('s1_fname',ParamChange(:,1)) 73 | error('No s1_fname') 74 | end 75 | end 76 | if option.fixW==1 77 | if ~ismember('Wseed1',ParamChange(:,1))|| ~ismember('Wseed2',ParamChange(:,1)) 78 | error('No Wseed1 or Wseed2') 79 | end 80 | end 81 | 82 | %% define parameters 83 | dim ='2D'; 84 | % Number of neurons in network 85 | Ne11=200; % Number in each direction 86 | Ni11=100; %100; 87 | Ne21=200; % Number in each direction 88 | Ni21=100; %100; 89 | Nx1=50; % feedforward layer 90 | 91 | param(1).Ne=Ne11*Ne11; 92 | param(1).Ni=Ni11*Ni11; 93 | param(1).Nx=Nx1*Nx1; 94 | param(2).Ne=Ne21*Ne21; 95 | param(2).Ni=Ni21*Ni21; 96 | param(2).Nx=Ne11*Ne11; 97 | param(1).N=param(1).Ne+param(1).Ni; 98 | param(2).N=param(2).Ne+param(2).Ni; 99 | 100 | % stimulus param 101 | p_stim.Nstim=1; 102 | p_stim.stim_type='Uncorr'; 103 | p_stim.rX=.01; % Rate of neurons in feedforward layer (kHz), size 1xNstim cell of element 1xNsource array 104 | p_stim.Nsource=1; % # of sources for global correlation, size 1xNstim 105 | % p_stim.taucorr=10; % temporal jitter for 'LocalCorr' & 'GlobalCorr' 106 | % p_stim.sigmac=0; % local corr width 107 | % p_stim.cx=0; 108 | 109 | % stim_type= 'LocalCorr'; correlation width 'sigmac' 110 | % stim_type='spatialInput'; Gaussian inputs centered at 'center' with width 'sigmac' and mean rate 'rX' 111 | % center=[.5 .5]; 112 | % sigmac=.15; % size 1xNstim 113 | % stim_type= 'GlobalCorr'; % cell of size 1xNstim 114 | 115 | T=20000; % Total sim time (in msec) 116 | 117 | % static currents to Layer 3 118 | inE=0; 119 | inI=4; 120 | 121 | % Connection widths 122 | param(1).sigmaRX=.05*ones(2,1); 123 | param(1).sigmaRR=.1*ones(2,2); 124 | param(2).sigmaRX=.1*ones(2,1); 125 | param(2).sigmaRR=.2*ones(2,2); 126 | 127 | % number of neurons to record synaptic inputs and voltages from 128 | nrecordE0=zeros(1,2); 129 | nrecordI0=zeros(1,2); 130 | 131 | % Synaptic time constants 132 | param(2).taudsyn=[5 100; 5, 100; 8, 100]; % rows: X, E, I, column for different syn types 133 | param(2).taursyn=[1 2; 1, 2; 1, 2]; % rows: X, E, I 134 | param(2).Psyn=[.2 .8; 1, 0; 1, 0]; % percentage of diff syn currents 135 | 136 | param(1).taudsyn=[5; 5; 8]; % rows: X, E, I 137 | param(1).taursyn=[1; 1; 1]; 138 | param(1).Psyn=[1; 1; 1]; 139 | 140 | % Connection probabilities (kind of, see use below) 141 | param(1).Prr=[.01, .04; .03, .04]; 142 | param(2).Prr=[.01, .04; .03, .04]; 143 | param(1).Prx=[ .1; .05]; 144 | param(2).Prx=[ .05; .0]; 145 | 146 | % Connection strengths (scaled by sqrt(N) later) 147 | param(1).Jr=[80 -240; 40, -300]; 148 | param(2).Jr=[80 -240; 40, -300]; 149 | param(1).Jx=[140; 100]; 150 | param(2).Jx=[25; 0]; 151 | 152 | param(1).Iapp=[0;0]; 153 | param(2).Iapp=[inE;inI]; 154 | 155 | dt=.01; % bin size % 0.01 156 | Tburn=1000; % Burn-in period 157 | 158 | % change parameters 159 | if nVarargs==2 160 | for i=1:size(ParamChange,1) 161 | eval([ParamChange{i,1} '= ParamChange{i,2};']); 162 | end 163 | end 164 | % param(2).Iapp=[inE;inI]; 165 | fprintf('\ninE=%.2f, inI=%.2f\n',param(2).Iapp(1),param(2).Iapp(2)) 166 | 167 | if option.loadS1 168 | p_stim.s1_fname=s1_fname; 169 | end 170 | 171 | %% initialization 172 | 173 | for par=1:2 174 | param(par).dt=dt; 175 | param(par).maxns=param(par).N*T*.06; 176 | param(par).T=T; 177 | % EIF neuron paramters 178 | param(par).gl=[1/15 1/10]; % E, I 179 | param(par).Cm=[1 1]; 180 | param(par).vlb=[-100 -100]; 181 | param(par).vth=[-10 -10]; 182 | param(par).DeltaT=[2 .5]; 183 | param(par).vT=[-50 -50]; %mV 184 | param(par).vre=[-65 -65]; 185 | param(par).tref=[1.5 .5]; 186 | V0min=param(par).vre(1); 187 | V0max=param(par).vT(1); 188 | param(par).vl=param(par).Iapp'.*[15, 10]-60; 189 | 190 | param(par).V0=(V0max-V0min).*rand(param(par).N,1)+V0min; 191 | % param(par).V0=data.param(par).V0; 192 | param(par).Kr=ceil(param(par).Prr.*[param(par).Ne, param(par).Ne; param(par).Ni,param(par).Ni]); 193 | param(par).Kx=ceil(param(par).Prx.*[param(par).Ne; param(par).Ni]); 194 | 195 | param(par).Irecord=[randi(param(par).Ne,1,nrecordE0(par)), (randi(param(par).Ni,1,nrecordI0(par))+param(par).Ne)];% neuron indice to record synaptic currents and Vm 196 | param(par).Jr=param(par).Jr/sqrt(param(par).N); 197 | param(par).Jx=param(par).Jx/sqrt(param(par).N); 198 | 199 | % % Effective connection weights 200 | q=param(par).Ne/param(par).N; 201 | wrx=(param(par).Jx).*param(par).Prx*param(par).Nx/param(par).N; 202 | wrr=(param(par).Jr).*param(par).Prr.*[q, 1-q; q, 1-q]; 203 | % For balanced state to exist this vector should be decreasing 204 | fprintf('\nThis list should be decreasing for\n a balanced state to exist: %.2f %.2f %.2f\n\n',wrx(1)/wrx(2),abs(wrr(1,2)/wrr(2,2)),abs(wrr(1,1)/wrr(2,1))); 205 | % and these values should be >1 206 | fprintf('\nAlso, this number should be greater than 1: %.2f\n\n',abs(wrr(2,2)/wrr(1,1))); 207 | if par==1 208 | param(par).Imean=p_stim.rX*wrx*param(par).N+param(par).Iapp; 209 | disp(sprintf('\nFiring rates for large N: %.2f %.2f\n',-(wrr*param(par).N)\(p_stim.rX*wrx*param(par).N+param(par).Iapp)*1e3)) 210 | end 211 | end 212 | 213 | 214 | %% generate input spike trains 215 | if option.loadS1==0 216 | sx=genXspk(p_stim,param(1).Nx,T); 217 | end 218 | 219 | %% Simulation 220 | 221 | % Simulate Network 222 | if((param(2).N)<=200000) 223 | disp('simulation starts') 224 | % Random initial membrane potentials 225 | if option.loadS1 226 | load(s1_fname,'s1') 227 | s1=s1(:,s1(1,:)<=T); 228 | disp('load s1') 229 | else 230 | if option.fixW 231 | param(1).Wseed=Wseed1; 232 | rng(Wseed1) 233 | fprintf('seed%d for Wrr1, Wrf1\n',Wseed1) 234 | end 235 | disp('generating Wrr1, Wrf1') 236 | tic 237 | [Wrr1,Wrf1]=gen_weights(param(1).Ne,param(1).Ni,param(1).Nx,param(1).sigmaRX,param(1).sigmaRR,param(1).Prr, param(1).Prx,'2D'); 238 | elapsetime=toc; 239 | fprintf('elapsetime=%.2f sec\n',elapsetime) 240 | disp('simulating Layer1') 241 | tic 242 | [s1,Isyn1,Vm1]=EIF1DRFfastslowSyn(sx, Wrf1,Wrr1,param(1)); 243 | s1=s1(:,s1(2,:)~=0); 244 | elapsetime=toc; 245 | fprintf('complete Layer1, elapsetime=%.2f sec\n',elapsetime) 246 | end 247 | clear Wrr1 Wrf1; 248 | 249 | if option.Layer1only==0 250 | if option.fixW 251 | param(2).Wseed=Wseed2; 252 | rng(Wseed2) 253 | fprintf('seed%d for Wrr2, Wrf2\n',Wseed2) 254 | end 255 | disp('generating Wrr2, Wrf2') 256 | tic 257 | [Wrr2,Wrf2]=gen_weights(param(2).Ne,param(2).Ni,param(2).Nx,param(2).sigmaRX,param(2).sigmaRR,param(2).Prr,param(2).Prx,'2D'); 258 | elapsetime=toc; 259 | fprintf('elapsetime=%.2f sec\n',elapsetime) 260 | disp('simulating Layer2') 261 | Re1=nnz(s1(1,:)>Tburn & s1(2,:)<=param(1).Ne)/(param(1).Ne*(T-Tburn)); % Hz 262 | param(par).Imean=Re1*(param(2).Jx).*param(2).Prx*param(2).Nx+param(par).Iapp; 263 | fprintf('mean current to Layer2, E: %.2f, I: %.2f\n\n', param(2).Imean(1), param(2).Imean(2)) 264 | tic; 265 | [s2,Isyn2,Vm2]=EIF1DRFfastslowSyn(s1(:,s1(2,:)<=param(1).Ne), Wrf2,Wrr2,param(2)); 266 | s2=s2(:,s2(2,:)~=0); 267 | elapsetime=toc; 268 | fprintf('complete Layer2, elapsetime=%.2f sec\n',elapsetime) 269 | clear Wrr2 Wrf2; 270 | end 271 | else 272 | error('N too large') % Your computer probably can't handle this 273 | end 274 | disp('simulation ends') 275 | 276 | %% average rate for each ppl 277 | if option.Layer1only 278 | nuSim(1)=1000*nnz(s1(1,:)>Tburn & s1(2,:)<=param(1).Ne)/(param(1).Ne*(T-Tburn)); % Hz 279 | nuSim(2)=1000*nnz(s1(1,:)>Tburn & s1(2,:)>param(1).Ne)/(param(1).Ni*(T-Tburn)); 280 | nuSim(3)=1000*nnz(sx(1,:)>Tburn & sx(1,:)Tburn & s2(2,:)<=param(2).Ne)/(param(2).Ne*(T-Tburn)); % Hz 284 | nuSim(2)=1000*nnz(s2(1,:)>Tburn & s2(2,:)>param(2).Ne)/(param(2).Ni*(T-Tburn)); 285 | nuSim(3)=1000*nnz(s1(1,:)>Tburn & s1(2,:)<=param(1).Ne)/(param(1).Ne*(T-Tburn)); % Hz 286 | nuSim(4)=1000*nnz(s1(1,:)>Tburn & s1(2,:)>param(1).Ne)/(param(1).Ni*(T-Tburn)); 287 | if option.loadS1 288 | data=load(s1_fname,'nuSim'); 289 | nuSim(5)=data.nuSim(5); 290 | else 291 | nuSim(5)=1000*nnz(sx(1,:)>Tburn & sx(1,:)0.25 & Iy<0.75 & Iy>0.25); 70 | I1=randsample(I1,Nc); 71 | % compute spike counts using sliding window 72 | Tw=200; 73 | Tburn=1000; 74 | time=0:1:T; 75 | re0=zeros(Nc,length(time)); 76 | for mm=1:Nc 77 | re0(mm,:)=hist(s1(1,I1(mm)-1/40; 85 | re1=re1(ind1,:); 86 | COV=cov(re1'); 87 | R = corrcov(COV); 88 | U=triu(ones(size(R)),1); 89 | Cbar_tauf(ff)=mean(R(U==1)); % average corr. 90 | COVbar_tauf(ff)=mean(COV(U==1)); % average cov. 91 | end 92 | save(filename,'Cbar_tauf','COVbar_tauf','tauf_range','filter','Nc','-append') 93 | 94 | %% Collect data after all simulations 95 | 96 | % taui_range = [.5 2:1:15]; 97 | % filename=@(Wtype,taudsyni) strrep(sprintf('data/RF%s2layer_%s_tausyni%.03g',... 98 | % dim, Wtype, taudsyni),'.','d'); 99 | % 100 | % Wtypes={'broadRec', 'uniformW'}; 101 | % 102 | % Ntau=length(taudi_range); 103 | % for type=1:2 104 | % res(type).filename=cell(1,Ntau); 105 | % res(type).Corr=zeros(Ntau,1); 106 | % res(type).COV=zeros(Ntau,1); 107 | % res(type).nu=zeros(Ntau,2); 108 | % res(type).FF=zeros(Ntau,1); 109 | % res(type).re=cell(1,Ntau); 110 | % res(type).Cee_d=zeros(Ntau,20); 111 | % res(type).COVee_d=zeros(Ntau,20); 112 | % res(type).Cbar_tauf=zeros(Ntau,4); 113 | % res(type).COVbar_tauf=zeros(Ntau,4); 114 | % 115 | % for k=1:Ntau 116 | % taudsyni=taudi_range(k); 117 | % load(filename(Wtypes{type},taudsyni)) 118 | % 119 | % time=0:1:T;Ne=200^2; 120 | % res(type).filename{k}=filename(Wtypes{type},taudsyni); 121 | % res(type).Corr(k)=Cbar(1); 122 | % res(type).COV(k)=COVbar(1); 123 | % res(type).nu(k,:)=nuSim(1:2); 124 | % res(type).FF(k)=mean(var2./rate2)/5; 125 | % res(type).re{k}=hist(s0(1,s0(2,:)<=Ne),time)/Ne*1e3; 126 | % res(type).Cee_d(k,:)=C(:,1)'; 127 | % res(type).COVee_d(k,:)=COV_d(:,1)'; 128 | % res(type).Cbar_tauf(k,:)=Cbar_tauf; 129 | % res(type).COVbar_tauf(k,:)=COVbar_tauf; 130 | % end 131 | % end 132 | % save('data/RF2D_broadRec_uniformW_tausyni_sum.mat','res','taudi_range','daxis','tauf_range','filter','Nc') 133 | % 134 | 135 | 136 | -------------------------------------------------------------------------------- /SimulationFig4.m: -------------------------------------------------------------------------------- 1 | % simulation of the three-layer network (Fig. 4) 2 | % vary the static input (muE, muI) to Layer 3 E & I neurons 3 | % meaure noise correlations within Layer 3, and those between Layer 2 and 3 4 | % each simulation takes about 3.5 hours and 3 gb memory 5 | 6 | clear 7 | 8 | data_folder='data/'; 9 | 10 | testp.inE=[0.]; 11 | testp.inI=[0.1 .15 .2 .25 .3 .35 .4]; 12 | 13 | %%%%%%%%%%%% for job array on cluster %%%%%%%%%%%%%%%% 14 | rng('shuffle'); 15 | AI = getenv('PBS_ARRAYID'); 16 | job_dex = str2num(AI); 17 | seed_offset = randi(floor(intmax/10)); 18 | rng(job_dex + seed_offset); 19 | % job_dex range from 1 to 350 % Ntrial=50 per inI 20 | 21 | Np=length(testp.inI)*length(testp.inE); 22 | pid=mod(job_dex-1,Np)+1; 23 | trial=ceil(job_dex/Np); 24 | ip1=1; 25 | ip2=pid; 26 | 27 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 28 | 29 | tic 30 | 31 | dim='2D'; 32 | 33 | opt.save=1; % save data 34 | opt.CompCorr=1; % compute correlations 35 | Nc=[500 500]; % # of E neurons sampled from Layer 3 & 2 36 | opt.loadS1=0; 37 | opt.plotPopR=0; % plot population rate 38 | opt.fixW=0; 39 | % Wseed1=Wseed1_range(nws); 40 | % Wseed2=Wseed2_range(nws); 41 | 42 | inE=testp.inE(ip1); % input to Layer 3 exc. neurons 43 | inI=testp.inI(ip2); % input to Layer 3 inh. neurons 44 | Jx=25*[1;0.6]; % ffwd strength from Layer 2 to 3 45 | Prx=[ .05; .05]; 46 | dt=.01; % (ms) 47 | T=20000; % (ms) 48 | filename=sprintf('%sRF%s3layer_Jex%.03g_Jix%.03g_inE%.03g_inI%.03g_ID%.0f_dt%.03g',... 49 | data_folder,dim,Jx(1),Jx(2),inE,inI,trial,dt); 50 | filename=strrep(filename,'.','d') 51 | 52 | ParamChange={'param(2).Iapp', [inE;inI]; 'filename', filename;... 53 | 'dt', dt; 'T', T; 'Nc',Nc;'param(2).Jx',Jx; 'param(2).Prx',Prx}; 54 | if opt.loadS1 55 | ParamChange=[ParamChange;{'s1_fname',s1_fname}]; 56 | end 57 | if opt.fixW 58 | ParamChange=[ParamChange;{'Wseed1',Wseed1; 'Wseed2',Wseed2}]; 59 | end 60 | 61 | RF2D3layer(opt, ParamChange) 62 | 63 | %% run after finishing all simulations 64 | % data_folder='data/'; 65 | % dim='2D'; 66 | % dt=0.01; 67 | % 68 | % Jx=25*[1;0.6]; 69 | % testp.inE=[0]; 70 | % testp.inI=[0.1 .15 .2 .25 .3 .35 .4]; 71 | % 72 | % Ntrial=50; 73 | % Np=length(testp.inI)*length(testp.inE); 74 | % 75 | % res.nu=zeros(Np,5,Ntrial); 76 | % res.Corr=zeros(Np,3,Ntrial); 77 | % res.COV=zeros(Np,3,Ntrial); 78 | % res.FF=zeros(Np,1,Ntrial); 79 | % res.Cee_d=zeros(Np,20,Ntrial); 80 | % res.Cex_d=zeros(Np,20,Ntrial); 81 | % res.COVee_d=zeros(Np,20,Ntrial); 82 | % res.COVex_d=zeros(Np,20,Ntrial); 83 | % res.inI=zeros(Np,1); 84 | % res.inE=zeros(Np,1); 85 | % res.Imean=zeros(Np,2,Ntrial); 86 | % fnames=cell(Np,Ntrial); 87 | % 88 | % % T=2e4; 89 | % % time=0:1:T; 90 | % % Ne2=200^2; 91 | % 92 | % fnamesave=sprintf('%sRF%s3layer_Jex%.03g_Jix%.03g_dt%.03g_inI_sum',... 93 | % data_folder,dim,Jx(1),Jx(2),dt); 94 | % fnamesave=strrep(fnamesave,'.','d'); 95 | % 96 | % for pid=1:Np 97 | % inE=testp.inE(1); 98 | % inI=testp.inI(pid); 99 | % res.inI(pid)=inI; 100 | % res.inE(pid)=inE; 101 | % for trial=1:Ntrial 102 | % filename=sprintf('%sRF%s3layer_Jex%.03g_Jix%.03g_inE%.03g_inI%.03g_ID%.0f_dt%.03g',... 103 | % data_folder,dim,Jx(1),Jx(2),inE,inI,trial,dt); 104 | % filename=strrep(filename,'.','d'), 105 | % data=load(filename,'COVbar','Cbar','var2','rate2','nuSim','C','COV_d','daxis','param'); 106 | % fnames{pid,trial}=filename; 107 | % res.COV(pid,:,trial)=data.COVbar; 108 | % res.Corr(pid,:,trial)=data.Cbar; 109 | % res.FF(pid,:,trial)=mean(data.var2./data.rate2)/5; 110 | % res.nu(pid,:,trial)=data.nuSim; 111 | % res.Cee_d(pid,:,trial)=data.C(:,1)'; 112 | % res.Cex_d(pid,:,trial)=data.C(:,2)'; 113 | % res.COVee_d(pid,:,trial)=data.COV_d(:,1)'; 114 | % res.COVex_d(pid,:,trial)=data.COV_d(:,2)'; 115 | % res.Imean(pid,:, trial)=data.param(2).Imean; 116 | % % re{pid,trial}=hist(data.s2(1,data.s2(2,:)<=Ne2),time)/Ne2*1e3; 117 | % end 118 | % end 119 | % daxis=data.daxis; 120 | % save(fnamesave,'res','testp','daxis','fnames','-append') 121 | 122 | -------------------------------------------------------------------------------- /SimulationFig4E.m: -------------------------------------------------------------------------------- 1 | % Simulations for factor analysis (Fig. 4E, Fig. 5B,C right, Fig. 6A,C and Fig. S6) 2 | % with fixed connectivity matrices 3 | % change the inhibitory time constant or projection width in Layer 3 4 | % Inh='slow','fast' or 'broad' 5 | % spike trains from Layer 2 are shared for the three inh conditions 6 | % run Inh='slow' first 7 | 8 | clear 9 | 10 | data_folder='data/'; 11 | 12 | Wseed1_range=[8541; 45134; 48395; 3547; 14845; 71109; 99911; 98570;... 13 | 68790; 16203 ]; 14 | 15 | Wseed2_range=[800281; 141887; 421762; 915736; 792208; 959493; ... 16 | 157614; 970593; 957167; 485376]; 17 | 18 | testp.inE=[0]; 19 | testp.inI=[.2 .35]; % muI for Unatt. & att. conditions 20 | 21 | Inh='slow'; % Fig. 4E, Fig. 5B and Fig. 6A,C 22 | % Inh='fast'; % Fig. S6A-E 23 | % Inh='broad'; % Fig. 5C, Fig. S6F-J 24 | 25 | %%%%%%%%%%%% for job array on cluster %%%%%%%%%%%%%%%% 26 | rng('shuffle'); 27 | AI = getenv('PBS_ARRAYID'); 28 | job_dex = str2num(AI); 29 | seed_offset = randi(floor(intmax/10)); 30 | rng(job_dex + seed_offset); 31 | % job_dex range from 1 to Ntrial*Np*Nnws 32 | 33 | Np=length(testp.inI)*length(testp.inE); 34 | Ntrial=15; 35 | Nnws=8; 36 | 37 | pid=mod(job_dex-1,Np)+1; 38 | trial=mod(ceil(job_dex/Np)-1, Ntrial)+1; 39 | nws=ceil(job_dex/(Np*Ntrial)); 40 | ip1=1; 41 | ip2=pid; 42 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 43 | 44 | tic 45 | 46 | dim='2D'; 47 | 48 | opt.save=1; % save data 49 | opt.CompCorr=1; % compute correlations 50 | Nc=[500 500]; % # of E neurons sampled from Layer 3 & 2 51 | if strcmp(Inh,'slow') 52 | opt.loadS1=0; % generate spike trains from Layer 2 53 | else 54 | opt.loadS1=1; % use stored spike trains from Layer 2 55 | end 56 | opt.plotPopR=0; % plot population rate 57 | opt.fixW=1; % rng(Wseed1) before generating Wrr1, Wrf1; rng(Wseed2) before generating Wrr2, Wrf2 58 | Wseed1=Wseed1_range(nws); 59 | Wseed2=Wseed2_range(nws); 60 | 61 | inE=testp.inE(ip1); 62 | inI=testp.inI(ip2); 63 | Jx=25*[1;0.6]; 64 | Prx=[ .05; .05]; 65 | dt=.01; 66 | T=20000; % (ms) 67 | s1_fname=strrep(sprintf('%sRF%s3layer_fixW_slowInh_Jex%.03g_Jix%.03g_inE%.03g_inI%.03g_ID%.0f_dt%.03g_nws%.03g',... 68 | data_folder,dim,Jx(1),Jx(2),inE,inI,trial,dt,nws),'.','d'), 69 | 70 | filename=strrep(sprintf('%sRF%s3layer_fixW_%sInh_Jex%.03g_Jix%.03g_inE%.03g_inI%.03g_ID%.0f_dt%.03g_nws%.03g',... 71 | data_folder,dim,Inh,Jx(1),Jx(2),inE,inI,trial,dt,nws),'.','d'), 72 | 73 | ParamChange={'param(2).Iapp', [inE;inI]; 'filename', filename;... 74 | 'dt', dt; 'T', T; 'Nc',Nc;'param(2).Jx',Jx; 'param(2).Prx',Prx}; 75 | 76 | switch Inh 77 | case 'slow' 78 | ParamChange=[ParamChange;{'param(2).taudsyn(3,1)', 1;'param(2).taursyn(3,1)', 8}]; 79 | case 'fast' 80 | ParamChange=[ParamChange;{'param(2).taudsyn(3,1)', 1;'param(2).taursyn(3,1)', .5}]; 81 | case 'broad' 82 | ParamChange=[ParamChange;{'param(2).sigmaRR', [.1 .2; .1 .2]}]; 83 | end 84 | 85 | if opt.loadS1 86 | ParamChange=[ParamChange;{'s1_fname',s1_fname}]; 87 | end 88 | if opt.fixW 89 | ParamChange=[ParamChange;{'Wseed1',Wseed1; 'Wseed2',Wseed2}]; 90 | end 91 | 92 | RF2D3layer(opt, ParamChange) 93 | 94 | %% after all simulations, run spkcounts.m, then FA.m 95 | -------------------------------------------------------------------------------- /SimulationFig5.m: -------------------------------------------------------------------------------- 1 | % codes for the neural field model in Fig 5A & B,C left 2 | 3 | %% Fig. 5A 4 | % provides wavenumber containing max real lam > 0 againt tau, sigma changes 5 | 6 | clear 7 | 8 | data_folder='data/'; 9 | fnamesave=[data_folder 'neuralfield_stability']; 10 | 11 | efit = @(mu)(mu.^2 .* (mu > 0)); 12 | ifit = @(mu)(mu.^2 .* (mu > 0)); 13 | 14 | Ne = 10000; 15 | Ni = 10000; 16 | 17 | Jee = 1; 18 | Jei = -2; 19 | Jie = 1.5; 20 | Jii = -2.5; 21 | pee = .008; 22 | pei = .008; 23 | pie = .008; 24 | pii = .008; 25 | KeeIn=pee*Ne; 26 | KeiIn=(pei*Ni)*Ni/Ne; 27 | KieIn=(pie*Ne)*Ne/Ni; 28 | KiiIn=pii*Ni; 29 | 30 | wee0=KeeIn*Jee; 31 | wei0=KeiIn*Jei; 32 | wie0=KieIn*Jie; 33 | wii0=KiiIn*Jii; 34 | W0 = [wee0 wei0;wie0 wii0]; 35 | 36 | Fin = [0.48 0.32]; % external inputs for [mu_e, mu_i] 37 | 38 | reg = .012; % initial condition for firing rate re (kHz) 39 | rig = .010; % initial condition for firing rate ri (kHz) 40 | 41 | taue=5; % (ms) 42 | taui=5; 43 | 44 | sigmae=.1; % spatial connection width 45 | sigmai=.1; 46 | 47 | mu_i_range=[.32 .5]; % .32 for Unatt., .5 for Att. condition 48 | for ss=1:2 49 | Fin(2) = mu_i_range(ss); 50 | % find steady state for rates 51 | q = .05; 52 | eps = 1e-6; 53 | change = 1; 54 | iter = 1; 55 | while (change > q*eps) 56 | ue = Fin(1) + wee0*reg + wei0*rig; % total current to e 57 | ui = Fin(2) + wie0*reg + wii0*rig; % total current to i 58 | 59 | renext = efit(ue); 60 | rinext = ifit(ui); 61 | changee = abs(renext-reg)/reg; 62 | changei = abs(rinext-rig)/rig; 63 | change = abs(changee + changei)/2; 64 | reg = (1-q)*reg + q*renext; 65 | rig = (1-q)*rig + q*rinext; 66 | iter = iter+1; 67 | if (iter > 50000) 68 | change = 0; 69 | end 70 | end 71 | 72 | % Calculate eigenvalues 73 | sigmai_use = .05:(.00125/2):.2; 74 | taui_use = 2.5:(.125/4):25; 75 | 76 | maxreallamplot=zeros(numel(sigmai_use),numel(taui_use)); 77 | maxreallamindex=zeros(numel(sigmai_use),numel(taui_use)); 78 | Fmodes=0:1:5; 79 | [f1,f2]=meshgrid(Fmodes,Fmodes); 80 | wavenums=sqrt(sort(unique(f1.^2+f2.^2))); 81 | 82 | for i = 1:numel(sigmai_use) 83 | for j = 1:numel(taui_use) 84 | maxreallam = zeros(1,numel(wavenums)); % eigenvalue w/ larger real part for each wave number 85 | % Fourier coefficients of W's, wn: wave number 86 | weet=@(wn)(wee0*exp(-2*wn.^2*pi^2*sigmae^2)); 87 | weit=@(wn)(wei0*exp(-2*wn.^2*pi^2*sigmai_use(i)^2)); 88 | wiet=@(wn)(wie0*exp(-2*wn.^2*pi^2*sigmae^2)); 89 | wiit=@(wn)(wii0*exp(-2*wn.^2*pi^2*sigmai_use(i)^2)); 90 | Wt=@(wn)([weet(wn) weit(wn); wiet(wn) wiit(wn)]); 91 | 92 | Tau_e = taue; 93 | Tau_i = taui_use(j); 94 | 95 | Tau = [-1/Tau_e 0; 0 -1/Tau_i]; 96 | 97 | ge = 2*ue; 98 | gi = 2*ui; 99 | 100 | GTau=[ge/Tau_e 0; 0 gi/Tau_i]; 101 | 102 | for k=1:numel(wavenums) 103 | Matrix = Tau + GTau*Wt(wavenums(k)); 104 | maxreallam(k)=max(real(eig(Matrix))); 105 | end 106 | [maxreallamplot(i,j),maxreallamindex(i,j)] = max(real(maxreallam)); 107 | end 108 | end 109 | 110 | maxReWavNum = maxreallamindex.*(maxreallamplot>=0); % 0 for negative eigenvalues 111 | maxReWavNum(maxReWavNum==0) = maxReWavNum(maxReWavNum==0) -1; % convert from index to wn, -1 for negative eigenvalues 112 | maxReWavNum(maxReWavNum>0) = wavenums(maxReWavNum(maxReWavNum>0)); % convert from index to wn 113 | res(ss).maxReWavNum=maxReWavNum; 114 | res(ss).muI=Fin(2); 115 | 116 | end 117 | 118 | save(fnamesave,'res','sigmai_use','taui_use','wavenums','taue','Fin') 119 | 120 | %% Fig. 5B,C left 121 | % eigenval (max real) vs wn, for various taui 122 | 123 | fnamesave=[data_folder 'neuralfield_Lambda']; 124 | 125 | Fin = [0.48 0.32]; 126 | 127 | reg = .012; 128 | rig = .010; 129 | 130 | taue=5; 131 | taui_use = 5:2.5:15; 132 | sigmae=.1; 133 | 134 | ss=0; 135 | for sigmai=[.1 .15] 136 | ss=ss+1; 137 | weet=@(wn)(wee0*exp(-2*wn.^2*pi^2*sigmae^2)); 138 | weit=@(wn)(wei0*exp(-2*wn.^2*pi^2*sigmai^2)); 139 | wiet=@(wn)(wie0*exp(-2*wn.^2*pi^2*sigmae^2)); 140 | wiit=@(wn)(wii0*exp(-2*wn.^2*pi^2*sigmai^2)); 141 | Wt=@(wn)([weet(wn) weit(wn); wiet(wn) wiit(wn)]); 142 | 143 | % find steady state for rates 144 | q = .05; 145 | eps = 1e-6; 146 | change = 1; 147 | iter = 1; 148 | while (change > q*eps) 149 | ue = Fin(1) + wee0*reg + wei0*rig; 150 | ui = Fin(2) + wie0*reg + wii0*rig; 151 | 152 | renext = efit(ue); 153 | rinext = ifit(ui); 154 | changee = abs(renext-reg)/reg; 155 | changei = abs(rinext-rig)/rig; 156 | change = abs(changee + changei)/2; 157 | reg = (1-q)*reg + q*renext; 158 | rig = (1-q)*rig + q*rinext; 159 | iter = iter+1; 160 | if (iter > 50000) 161 | change = 0; 162 | end 163 | end 164 | % Calculate eigenvalues 165 | Fmodes=0:1:5; 166 | [f1,f2]=meshgrid(Fmodes,Fmodes); 167 | wavenums=sqrt(sort(unique(f1.^2+f2.^2))); 168 | maxreallam=zeros(numel(taui_use),numel(wavenums)); 169 | 170 | for j = 1:1:numel(taui_use) 171 | Tau_e = taue; 172 | Tau_i = taui_use(j); 173 | 174 | Tau = [-1/Tau_e 0; 0 -1/Tau_i]; 175 | 176 | ge = 2*ue; 177 | gi = 2*ui; 178 | 179 | GTau=[ge/Tau_e 0; 0 gi/Tau_i]; 180 | 181 | for k=1:numel(wavenums) 182 | Matrix = Tau + GTau*Wt(wavenums(k)); 183 | maxreallam(j,k)=max(real(eig(Matrix))); 184 | end % k loop 185 | end % j loop 186 | Lambdas(ss).sigmai=sigmai; 187 | Lambdas(ss).maxreallam=maxreallam; 188 | end 189 | 190 | save(fnamesave,'Lambdas','wavenums','taui_use','taue','sigmae','Fin') 191 | -------------------------------------------------------------------------------- /SimulationFig6AC.m: -------------------------------------------------------------------------------- 1 | % run SimulationFig4E.m first 2 | % compute covariance components from Factor analysis as a function of distance 3 | 4 | addpath(genpath([pwd '/fa_Yu/'])); 5 | rng('shuffle'); 6 | dim='2D'; 7 | type='slowInh'; 8 | 9 | testp.inE=[0]; 10 | testp.inI=[.2 .35]; 11 | Jx=25*[1;0.6]; 12 | dt=0.01; 13 | 14 | data_folder='data/'; 15 | 16 | Nsample=10; % number of sampling 17 | Np=2; 18 | Ntrial=15; 19 | M=30; % latent dimensionality to fit data 20 | Nc=500; % number of neuorns per sampling 21 | Ne1=200; 22 | Ne=Ne1^2; % number of neuorn in Layer 3 Exc. pop. 23 | numFolds=2; % number of cross-validation folds 24 | Nws=8; % number of weight matrices realizations 25 | zDimList=M; 26 | Tw=140; % time window for spike counts 27 | Tburn=1000; 28 | T=2e4; 29 | Nt=floor((T-Tburn)/Tw); % number of spike counts 30 | T=Nt*Tw+Tburn; 31 | 32 | fnamesave=strrep(sprintf('%sFA_model_%s_Jex%.03g_dist',data_folder,type,Jx(1)),'.','d'), 33 | 34 | %%%%%%%%%%% collect spike counts from Layer 3 Eec. pop. %%%%%%%%%%%%% 35 | fname_sc=@(nws) strrep(sprintf('%sRF2D3layer_fixW_%s_Jex%.03g_Jix%.03g_inI_dt0d01_Nc%d_spkcount_nws%d',... 36 | data_folder,type, Jx(1),Jx(2),Ne,nws),'.','d'), 37 | Ic2=1:Ne; 38 | for nws=1:Nws 39 | for pid=1:Np 40 | E2{pid}=zeros(Ne, Nt*Ntrial); 41 | for trial=1:Ntrial 42 | inE=testp.inE(1); 43 | inI=testp.inI(pid); 44 | filename=strrep(sprintf('%sRF%s3layer_fixW_%s_Jex%.03g_Jix%.03g_inE%.03g_inI%.03g_ID%.0f_dt%.03g_nws%.03g',... 45 | data_folder,dim,type,Jx(1),Jx(2),inE,inI,trial,dt,nws),'.','d'), % simulated with SimulationFig4E.m 46 | 47 | % compute spike counts using sliding window 48 | load(filename,'s2') 49 | s2=s2(:,s2(1,:)>=Tburn&s2(1,:)<=T&s2(2,:)<=Ne); 50 | s2(1,:)=s2(1,:)-Tburn; 51 | E2{pid}(:,(trial-1)*Nt+1:trial*Nt)=spktime2count(s2,Ic2,Tw,floor((T-Tburn)/Tw),1); 52 | end 53 | 54 | if max(E2{pid}(:))<127 55 | E2{pid}=int8(E2{pid}); % spike counts are saved as int8 type 56 | else 57 | fprintf('max E2{%d} >127',pid) % exceed the range of int8 type 58 | end 59 | 60 | end 61 | save(fname_sc(nws),'E2','T','Tw','Tburn','filename','testp') 62 | end 63 | 64 | 65 | %%%%%%%%% compute Cov components vs. distance using Factor analysis %%%%%%%%%%%%% 66 | for nws=1:Nws 67 | 68 | load(fname_sc(nws)) 69 | FR_th=2; %firing rate threshold for sampling (Hz) 70 | Ic0=1:Ne; 71 | idx2=ones(Ne,1); 72 | for pid=1:Np 73 | idx2=idx2.*(mean(E2{pid},2)/Tw*1e3>FR_th); 74 | end 75 | for k=1:Nsample 76 | ss=(nws-1)*Nsample+k; 77 | Ic2=randsample(Ic0(idx2>0),Nc); 78 | 79 | Ix2=(ceil((Ic2)/Ne1))/Ne1; % x,y index for neural location 80 | Iy2=(mod((Ic2-1),Ne1)+1)/Ne1; 81 | Dx = pdist2(Ix2',Ix2','euclidean'); 82 | Dx(Dx>0.5)=1-Dx(Dx>0.5); % periodic boundary condition 83 | Dy = pdist2(Iy2',Iy2','euclidean'); 84 | Dy(Dy>0.5)=1-Dy(Dy>0.5); % periodic boundary condition 85 | Dist=sqrt(Dx.^2+Dy.^2); % pairwise distance 86 | dmax=0.5; 87 | dd=0.025; 88 | daxis1=0:dd:0.7; % distance axis 89 | U=triu(ones(size(Dist)),1); 90 | [n, ind] = histc(Dist(U==1),daxis1); % sort according to distance 91 | n=n(1:end-1); % discard last bin (d>dmax) 92 | 93 | if nws==1&&k==1 94 | LL_d={zeros(length(n),M,Nsample*Nws),zeros(length(n),M,Nsample*Nws)}; 95 | cov_d=zeros(length(n),Nsample*Nws,Np); 96 | LL_dxy={zeros(length(nx),length(ny),M,Nsample*Nws),zeros(length(nx),length(ny),M,Nsample*Nws)}; 97 | Lambda=zeros(M,Nsample*Nws,Np); 98 | end 99 | 100 | for pid=1:Np 101 | Y=double(E2{pid}(Ic2,:)); 102 | COV=cov(Y'); 103 | dim = crossvalidate_fa(Y, 'zDimList', zDimList,'showPlots',false,'numFolds',numFolds); 104 | 105 | L=dim(1).estParams.L; 106 | LL=L*L'; 107 | [V,D]=eig(LL); 108 | la=diag(D); 109 | [la,I]=sort(la,'descend'); 110 | Lambda(:,ss,pid)=la(1:M); 111 | 112 | for mm=1:M 113 | LL_tmp=V(:,I(mm))*V(:,I(mm))'; 114 | LL_tmp=LL_tmp(U==1); % covariance components 115 | 116 | for nn=1:length(n) 117 | LL_d{pid}(nn,mm,ss)=mean(LL_tmp(ind==nn)); 118 | end 119 | 120 | end 121 | COV=COV(U==1); 122 | for nn=1:length(n) 123 | cov_d(nn,ss,pid)=mean(COV(ind==nn)); % total covariance 124 | end 125 | 126 | end 127 | end 128 | end 129 | daxis1=daxis1(1:end-1)+dd/2; 130 | save(fnamesave,'Tw','Lambda','LL_d','daxis1','cov_d','fname','M',... 131 | 'Nc','numFolds','Nsample','testp') 132 | -------------------------------------------------------------------------------- /SimulationFig7.m: -------------------------------------------------------------------------------- 1 | % for simulations to study macroscopic chaos (Fig. 7) 2 | % fix the spike trains from Layer 2 (s1) and connectivities (Wrr2, Wrf2) 3 | 4 | clear 5 | 6 | data_folder='data/'; 7 | 8 | Wseed1_range=[8541; 45134; 48395; 3547; 14845; 71109; 99911; 98570;... 9 | 68790; 16203 ]; 10 | 11 | Wseed2_range=[800281; 141887; 421762; 915736; 792208; 959493; ... 12 | 157614; 970593; 957167; 485376]; 13 | 14 | testp.inE=[0]; 15 | testp.inI=[.2 .35]; 16 | 17 | %%%%%%%%%%%% for job array on cluster %%%%%%%%%%%%%%%% 18 | rng('shuffle'); 19 | AI = getenv('PBS_ARRAYID'); 20 | job_dex = str2num(AI); 21 | seed_offset = randi(floor(intmax/10)); 22 | rng(job_dex + seed_offset); 23 | % job_dex from 1 to 400 (Nrep*Ntrial*Np*Nnws) 24 | 25 | Np=length(testp.inI)*length(testp.inE); 26 | Nrep=20; % # of repeats per condition 27 | Ntrial=10; % # of realizations of connectivity and Layer 2 spike trains 28 | 29 | pid=mod(job_dex-1,Np)+1; 30 | trial=mod(ceil(job_dex/Np)-1,Ntrial)+1; 31 | nrep=ceil(job_dex/(Np*Ntrial)); 32 | nws=trial; 33 | ip1=1; 34 | ip2=pid; 35 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 36 | 37 | tic 38 | 39 | dim='2D'; 40 | 41 | opt.save=1; % save data 42 | opt.CompCorr=0; % compute correlations 43 | Nc=[500 500]; % # of E neurons sampled from Layer 2 & 1 44 | opt.loadS1=1; % use stored spike trains from Layer 2 45 | opt.plotPopR=0; % plot population rate 46 | opt.fixW=1; 47 | Wseed1=Wseed1_range(nws); 48 | Wseed2=Wseed2_range(nws); 49 | opt.savecurrent=0; 50 | 51 | inE=testp.inE(ip1); 52 | inI=testp.inI(ip2); 53 | Jx=25*[1; 0.6]; 54 | Prx=[ .05; .05]; 55 | dt=.01; 56 | T=20000; % (ms) 57 | s1_fname=strrep(sprintf('%sRF%s3layer_fixW_slowInh_Jex%.03g_Jix%.03g_inE%.03g_inI%.03g_ID%.0f_dt%.03g_nws1',... 58 | data_folder,dim,Jx(1),Jx(2),inE,.2,trial,dt),'.','d'); 59 | 60 | filename=strrep(sprintf('%sRF%s3layer_fixW_Jex%.03g_Jix%.03g_inE%.03g_inI%.03g_dt%.03g_nws%.03g_nrep%.03g',... 61 | data_folder,dim,Jx(1),Jx(2),inE,inI,dt,nws,nrep),'.','d'); 62 | 63 | ParamChange={'param(2).Iapp', [inE;inI]; 'filename', filename;... 64 | 'dt', dt; 'T', T; 'Nc',Nc;'param(2).Jx',Jx; 'param(2).Prx',Prx}; 65 | if opt.loadS1 66 | ParamChange=[ParamChange;{'s1_fname',s1_fname}]; 67 | end 68 | if opt.fixW 69 | ParamChange=[ParamChange;{'Wseed1',Wseed1; 'Wseed2',Wseed2}]; 70 | end 71 | 72 | RF2D3layer(opt, ParamChange) 73 | 74 | %% collect population rates after all simulations 75 | % data_folder='data/'; 76 | % dim='2D'; 77 | % inE=0; 78 | % inI=.2; 79 | % Jx=25*[1; 0.6]; 80 | % Prx=[ .05; .05]; 81 | % dt=0.01; 82 | % Nrep=20; 83 | % Ntrial=10; 84 | % T=2e4; 85 | % time=0:1:T; 86 | % Ne2=200^2; 87 | % Ne1=200^2; 88 | % Np=1; 89 | % pid=1; 90 | % fnamesave=sprintf('%sRF2D3layer_fixW_Jex%.03g_Jix%.03g_Ntrial%.03g_Nrep%.03g_Re',... 91 | % data_folder,Jx(1),Jx(2),Ntrial,Nrep); 92 | % fnamesave=strrep(fnamesave,'.','d') 93 | % for trial=1:Ntrial 94 | % nws=trial; 95 | % for nrep=1:Nrep 96 | % filename=sprintf('%sRF%s3layer_fixW_Jex%.03g_Jix%.03g_inE%.03g_inI%.03g_dt%.03g_nws%.03g_nrep%.03g',... 97 | % data_folder,dim,Jx(1),Jx(2),inE,inI,dt,nws,nrep); 98 | % filename=strrep(filename,'.','d') 99 | % data=load(filename,'s2','p_stim'); 100 | % Re2{pid,nrep,trial}=hist(data.s2(1,data.s2(2,:)<=Ne2),time)/Ne2*1e3; 101 | % end 102 | % s1_fname=data.p_stim.s1_fname; 103 | % load(s1_fname,'s1') 104 | % Re1{pid,trial}=hist(s1(1,s1(2,:)<=Ne1),time)/Ne1*1e3; 105 | % end 106 | % save(fnamesave,'Re2','Re1','Ntrial','Nrep','Np','Jx','Prx','Ne1','Ne2','inE','inI','T') 107 | 108 | %% collect spike times (s2, s1) for raster plots (Fig. 7B,C) 109 | % data_folder='data/'; 110 | % trial=7; % sim # of Layer 2 111 | % Reps=[9 10 12]; % repetition # of Layer 3 112 | % t1=1.1e4; % start time; 113 | % t2=1.4e4; % end time 114 | % 115 | % testp.inI=[.2 .35]; % Unatt: inI=.2; Att: inI=.35; 116 | % Jx=25*[1; 0.6]; 117 | % inE=0; 118 | % dt=0.01; 119 | % nws=trial; 120 | % Ne=200^2; 121 | % fnamesave=sprintf('%sRF2D3layer_fixW_Jex%.03g_Jix%.03g_MacroChaos_rasters',data_folder,Jx(1),Jx(2)); 122 | % for pid=1:2 123 | % inI=testp.inI(pid); 124 | % for kk=1:3 125 | % nrep=Reps(kk); 126 | % filename=sprintf('%sRF2D3layer_fastslowJx_fixW_Jex%.03g_Jix%.03g_inE%.03g_inI%.03g_dt%.03g_nws%.03g_nrep%.03g',... 127 | % data_folder,Jx(1),Jx(2),inE,inI,dt,nws,nrep); 128 | % filename=strrep(filename,'.','d') 129 | % load(filename,'s2','p_stim','param'); 130 | % res(pid,kk).s2=s2(:,s2(1,:)>t1&s2(1,:)t1&s1(1,:)0); 42 | 43 | Ix10=(ceil(I1/N11))/N11; 44 | Iy10=(mod((I1-1),N11)+1)/N11; 45 | 46 | Ix20=(ceil(I2/N21))/N21; 47 | Iy20=(mod((I2-1),N21)+1)/N21; 48 | I1=I1(Ix10<0.75 & Ix10>0.25 & Iy10<0.75 & Iy10>0.25); 49 | I2=I2(Ix20<0.75 & Ix20>0.25 & Iy20<0.75 & Iy20>0.25); 50 | 51 | Ic1=randsample(I1,Nc(1)); 52 | Ic2=randsample(I2,Nc(2)); 53 | end 54 | 55 | % compute spike counts using sliding window 56 | Tw=200; % sliding window size 57 | Tburn=1000; 58 | time=0:1:T; 59 | 60 | re1=zeros(Nc(1),length(time)); 61 | re2=zeros(Nc(2),length(time)); 62 | 63 | for mm=1:Nc(1) 64 | re1(mm,:)=hist(s1(1,Ic1(mm)-1/42; 73 | ind2=mean(re2_s,2)>2; 74 | re1_s=re1_s(ind1,:); 75 | re2_s=re2_s(ind2,:); 76 | 77 | switch dim 78 | case '1D' 79 | Ix1=Ic1(ind1)/N1; Nc(1)=length(Ix1); 80 | Ix2=Ic2(ind2)/N2; Nc(2)=length(Ix2); 81 | D = pdist2([Ix2;Ix1],[Ix2;Ix1],'euclidean'); 82 | D(D>0.5)=1-D(D>0.5); % periodic boundary condition 83 | case '2D' 84 | Ix1=(ceil((Ic1(ind1))/N11))/N11; 85 | Iy1=(mod((Ic1(ind1)-1),N11)+1)/N11; 86 | Nc(1)=length(Ix1); 87 | Ix2=(ceil((Ic2(ind2))/N21))/N21; 88 | Iy2=(mod((Ic2(ind2)-1),N21)+1)/N21; 89 | Nc(2)=length(Ix2); 90 | D = pdist2([[Ix2;Ix1],[Iy2;Iy1]],[[Ix2;Ix1],[Iy2;Iy1]],'euclidean'); 91 | end 92 | 93 | COV=cov([re2_s; re1_s]'); 94 | Var=diag(COV); 95 | var2=Var(1:Nc(2));var1=Var(Nc(2)+1:end); 96 | rate1=mean(re1_s,2); 97 | rate2=mean(re2_s,2); 98 | 99 | R = COV./sqrt(Var*Var'); 100 | % Dx = pdist2([Ix2;Ix1],[Ix2;Ix1],'euclidean'); 101 | % Dx(Dx>0.5)=1-Dx(Dx>0.5); % periodic boundary condition 102 | % Dy = pdist2([Iy2;Iy1],[Iy2;Iy1],'euclidean'); 103 | % Dy(Dy>0.5)=1-Dy(Dy>0.5); % periodic boundary condition 104 | % D=sqrt(Dx.^2+Dy.^2); 105 | 106 | dmax=0.5; 107 | dd=0.025; 108 | U=triu(ones(size(R)),1); 109 | Utemp=zeros(size(U)); 110 | Utemp(1:Nc(2), 1:Nc(2))=U(1:Nc(2), 1:Nc(2)); % index for corr. within recurrent layer (E & I) 111 | [Crr, COVrr, cbar_rr, COVbar_rr, daxis]=corr_dist(R,COV,D,Utemp, dd, dmax); 112 | Utemp=zeros(size(U)); 113 | Utemp(1:Nc(2), Nc(2)+1:end)=U(1:Nc(2), Nc(2)+1:end); % index for corr. btwn R & F 114 | [Crf, COVrf, cbar_rf, COVbar_rf, daxis]=corr_dist(R,COV,D,Utemp, dd, dmax); 115 | Utemp=zeros(size(U)); 116 | Utemp(Nc(2)+1:end, Nc(2)+1:end)=U(Nc(2)+1:end, Nc(2)+1:end); % index for corr. btwn F & F 117 | [Cff, COVff, cbar_ff, COVbar_ff, daxis]=corr_dist(R,COV,D,Utemp, dd, dmax); 118 | 119 | C_d=[Crr,Crf,Cff]; 120 | COV_d=[COVrr,COVrf,COVff]; 121 | Cbar=[cbar_rr, cbar_rf, cbar_ff]; 122 | COVbar=[COVbar_rr, COVbar_rf, COVbar_ff]; 123 | end 124 | 125 | function [c, cov_m,cbar, COVbar,daxis]=corr_dist(R,COV,D,U, dd, dmax) 126 | % sort corr by distance according to index matrix U 127 | % U is of same size as R & D 128 | R=R(U==1); 129 | D=D(U==1); 130 | COV=COV(U==1); 131 | % dmax=0.5; 132 | % dd=0.025; 133 | daxis=0:dd:dmax; 134 | [n, ind] = histc(D,daxis); 135 | n=n(1:end-1); % discard last bin (d>dmax) 136 | c=zeros(length(n),1); 137 | cov_m=zeros(length(n),1); 138 | for k=1:length(n) 139 | c(k)=mean(R(ind==k)); 140 | cov_m(k)=mean(COV(ind==k)); 141 | end 142 | daxis=daxis(1:end-1)+dd/2; % center pts 143 | cbar=mean(R(D<=dmax)); % average corr. 144 | COVbar=mean(COV(D<=dmax)); 145 | end 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /data/FA_data.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcc11/SpatialNeuronNet/7e528ddb54c3b50e91fce755e13398cb79c27d93/data/FA_data.mat -------------------------------------------------------------------------------- /data/FA_data_dist.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcc11/SpatialNeuronNet/7e528ddb54c3b50e91fce755e13398cb79c27d93/data/FA_data_dist.mat -------------------------------------------------------------------------------- /data/FA_model_Jex25.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcc11/SpatialNeuronNet/7e528ddb54c3b50e91fce755e13398cb79c27d93/data/FA_model_Jex25.mat -------------------------------------------------------------------------------- /data/FA_model_broadInh_Jex25.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcc11/SpatialNeuronNet/7e528ddb54c3b50e91fce755e13398cb79c27d93/data/FA_model_broadInh_Jex25.mat -------------------------------------------------------------------------------- /data/FA_model_fastInh_Jex25.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcc11/SpatialNeuronNet/7e528ddb54c3b50e91fce755e13398cb79c27d93/data/FA_model_fastInh_Jex25.mat -------------------------------------------------------------------------------- /data/FA_model_slowInh_Jex25_dist.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcc11/SpatialNeuronNet/7e528ddb54c3b50e91fce755e13398cb79c27d93/data/FA_model_slowInh_Jex25_dist.mat -------------------------------------------------------------------------------- /data/Fig3data.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcc11/SpatialNeuronNet/7e528ddb54c3b50e91fce755e13398cb79c27d93/data/Fig3data.mat -------------------------------------------------------------------------------- /data/RF2D3layer_fixW_Jex25_Jix15_MacroChaos_rasters.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcc11/SpatialNeuronNet/7e528ddb54c3b50e91fce755e13398cb79c27d93/data/RF2D3layer_fixW_Jex25_Jix15_MacroChaos_rasters.mat -------------------------------------------------------------------------------- /data/RF2D3layer_fixW_Jex25_Jix15_Ntrial10_Nrep20_Re.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcc11/SpatialNeuronNet/7e528ddb54c3b50e91fce755e13398cb79c27d93/data/RF2D3layer_fixW_Jex25_Jix15_Ntrial10_Nrep20_Re.mat -------------------------------------------------------------------------------- /data/RF2D3layer_fixW_broadInh_Jex25_Jix15_inI_dt0d01_Nc500_spkcount_nws1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcc11/SpatialNeuronNet/7e528ddb54c3b50e91fce755e13398cb79c27d93/data/RF2D3layer_fixW_broadInh_Jex25_Jix15_inI_dt0d01_Nc500_spkcount_nws1.mat -------------------------------------------------------------------------------- /data/RF2D3layer_fixW_fastInh_Jex25_Jix15_inI_dt0d01_Nc500_spkcount_nws1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcc11/SpatialNeuronNet/7e528ddb54c3b50e91fce755e13398cb79c27d93/data/RF2D3layer_fixW_fastInh_Jex25_Jix15_inI_dt0d01_Nc500_spkcount_nws1.mat -------------------------------------------------------------------------------- /data/RF2D3layer_fixW_slowInh_Jex25_Jix15_inI_dt0d01_Nc500_spkcount_nws1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcc11/SpatialNeuronNet/7e528ddb54c3b50e91fce755e13398cb79c27d93/data/RF2D3layer_fixW_slowInh_Jex25_Jix15_inI_dt0d01_Nc500_spkcount_nws1.mat -------------------------------------------------------------------------------- /data/RF2D_broadRec_tausyni1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcc11/SpatialNeuronNet/7e528ddb54c3b50e91fce755e13398cb79c27d93/data/RF2D_broadRec_tausyni1.mat -------------------------------------------------------------------------------- /data/RF2D_broadRec_tausyni8.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcc11/SpatialNeuronNet/7e528ddb54c3b50e91fce755e13398cb79c27d93/data/RF2D_broadRec_tausyni8.mat -------------------------------------------------------------------------------- /data/RF2D_broadRec_uniformW_tausyni_sum.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcc11/SpatialNeuronNet/7e528ddb54c3b50e91fce755e13398cb79c27d93/data/RF2D_broadRec_uniformW_tausyni_sum.mat -------------------------------------------------------------------------------- /data/RF2D_uniformW_tausyni1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcc11/SpatialNeuronNet/7e528ddb54c3b50e91fce755e13398cb79c27d93/data/RF2D_uniformW_tausyni1.mat -------------------------------------------------------------------------------- /data/RF2D_uniformW_tausyni8.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcc11/SpatialNeuronNet/7e528ddb54c3b50e91fce755e13398cb79c27d93/data/RF2D_uniformW_tausyni8.mat -------------------------------------------------------------------------------- /demo.m: -------------------------------------------------------------------------------- 1 | % demo code for two-layer network simulations (related to Fig. 3) 2 | % calls RF2D3layer.m for network simulation 3 | 4 | clear 5 | 6 | Wtype='broadRec'; taudsyni=8; % (ms) % Fig. 3Aiv 7 | % Wtype='broadRec'; taudsyni=0.5; % (ms) % Fig. 3Aii 8 | % Wtype='uniformW'; taudsyni=8; % Fig. 3Aiii 9 | % Wtype='uniformW'; taudsyni=0.5; % Fig. 3Ai 10 | data_folder='data/'; % folder name to store data 11 | dim='2D'; 12 | 13 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 14 | 15 | tic 16 | 17 | 18 | %%%%%%%% set options and parameters to change %%%%%%%%%%% 19 | opt.save=1; % save data 20 | opt.CompCorr=1; % compute correlations 21 | Nc=[500 500]; % # of E neurons sampled from Layer 2 & 1 22 | opt.Layer1only=1; % 1 for two-layer network, 0 for three-layer network 23 | opt.loadS1=0; 24 | opt.plotPopR=1; % plot population rate 25 | opt.fixW=0; % use the same weight matrices for multiple simulations 26 | % Wseed1=Wseed1_range(nws); % ransom seed for generating weight matrices 27 | % Wseed2=Wseed2_range(nws); 28 | 29 | dt=.05; % time step size for integration 30 | T=2000; % total simulation time (ms) 31 | filename=strrep(sprintf('%sRF%s2layer_%s_tausyni%.03g_test',... 32 | data_folder,dim, Wtype, taudsyni),'.','d'), 33 | 34 | % parameters to change, default parameters are in RF2D3layer.m 35 | ParamChange={'filename', filename;... 36 | 'dt', dt; 'T', T; 'Nc',Nc;'param(1).taudsyn(3)', taudsyni}; 37 | if strcmp(Wtype,'uniformW') 38 | ParamChange=[ParamChange;{'param(1).sigmaRX', 10*ones(2,1); 39 | 'param(1).sigmaRR',10*ones(2,2)}]; 40 | end 41 | if opt.fixW 42 | ParamChange=[ParamChange;{'Wseed1',Wseed1; 'Wseed2',Wseed2}]; 43 | end 44 | 45 | %%%%%%%% run simulation %%%%%%%%%%% 46 | RF2D3layer(opt, ParamChange) 47 | 48 | %%%%%% plot correlation vs distance %%%%%%%%%%%%% 49 | load(filename,'C','daxis') 50 | figure 51 | plot(daxis,C,'linewidth',1) 52 | hold on 53 | colororder=lines(3); 54 | text(.7, 0.9,'Corr (E2-E2)','unit','n','Horiz','l','color',colororder(1,:)) 55 | text(.7, 0.8,'Corr (E2-E1)','unit','n','Horiz','l','color',colororder(2,:)) 56 | text(.7, 0.7,'Corr (E1-E1)','unit','n','Horiz','l','color',colororder(3,:)) 57 | xlabel('distance (a.u.)') 58 | ylabel('correlation') 59 | 60 | %%%%%%% raster movie %%%%%%%%%%%%%%%% 61 | load(filename,'s1') 62 | t1=0; % start time (ms) 63 | t2=1000; % end time (ms) 64 | raster2D_ani(s1,t1,t2,200) 65 | 66 | -------------------------------------------------------------------------------- /fa_Yu/README: -------------------------------------------------------------------------------- 1 | Matlab code for Factor Analysis 2 | 3 | Version 1.01 October 8, 2011 4 | 5 | @ 2011 Byron Yu byronyu@cmu.edu 6 | 7 | ================ 8 | VERSION HISTORY 9 | ================ 10 | 11 | In notes below, + denotes new feature, - denotes bug fix or removal. 12 | 13 | Version 1.01 -- October 8, 2011 14 | + Model comparison can now include a zero latent dimension model, 15 | which corresponds to an independent Gaussian model. Added 16 | indepGaussFit.m and indepGaussEval.m. Edited crossvalidate_fa.m. 17 | 18 | Version 1.00 -- September 18, 2011 19 | + Added crossvalidate_fa.m 20 | 21 | 22 | =================== 23 | HOW TO GET STARTED 24 | =================== 25 | 26 | See example.m. 27 | 28 | 1) Put data in 'X' (data dimensionality x number of data points) 29 | 30 | 2) To compare latent dimensionalities, do cross-validation: 31 | 32 | dim = crossvalidate_fa(X); 33 | 34 | The latent dimensionalities considered can be specified as an 35 | optional argument: 36 | 37 | dim = crossvalidate_fa(X, 'zDimList', zDimList); 38 | 39 | where zDimList is a vector containing latent dimensionalities. By 40 | default, zDimList = 1:10. 41 | 42 | 3) Identify the optimal latent dimensionality from the plots. 43 | Prediction error and LL should give similar answers. 44 | 45 | 4) The FA parameters for the optimal latent dimensionality can be 46 | found in dim(i).estParams, where dim(i).zDim is the optimal latent 47 | dimensionality. 48 | 49 | 5) To obtain low-dimensional projections, call 50 | 51 | Z = fastfa_estep(X, dim(i).estParams); 52 | 53 | Note that this gives low-d projections of the training data. For 54 | low-d projections of test data, replace 'X' with test data. 55 | 56 | 57 | ================================================ 58 | WHAT DOES THE WARNING ABOUT PRIVATE NOISE MEAN? 59 | ================================================ 60 | 61 | The private noise variance (or uniqueness, in FA speak) for one or 62 | more data dimensions may be driven to zero. 63 | 64 | There are four possible causes: 65 | 66 | 1) Highly correlated pairs (or groups) of data dimensions 67 | 68 | Solution: Remove offending rows from 'X' 69 | 70 | 2) Private noise variance floor is set too high. By default, it is 71 | set to 0.01 times the raw variance for each data dimension. 72 | 73 | Solution: Specify a smaller 'minVarFrac' using this optional 74 | argument to fastfa.m 75 | 76 | 3) The latent dimensionality is too large. The extra dimensions in 77 | the latent space may be dedicated to explaining particular data 78 | dimensions perfectly, thus giving zero private noise for those 79 | data dimensions. 80 | 81 | Solution: Reduce latent dimensionality 'zDim' 82 | 83 | 4) You have encountered a Heywood case. It's an issue with 84 | maximum-likelihood parameter learning, whereby more likelihood 85 | can be gained by setting a private noise to 0 than by finding a 86 | compromise. This is a corner case of FA that has been known 87 | since the 1930's. Various Bayesian FA models have been proposed, 88 | but here we simply set a minimum private noise variance for each 89 | data dimension as a percentage of its raw data variance. 90 | 91 | Two possible solutions: 92 | a) Do nothing. The private variance is automatically capped at 93 | some minimum non-zero value. 94 | b) Remove the offending rows from 'X'. 95 | 96 | For more about Heywood cases, see: 97 | 98 | "Bayesian Estimation in Unrestricted Factor Analysis: A Treatment 99 | for Heywood Cases" 100 | J. K. Martin and R. P. McDonald. 101 | Psychometrika, 40, 4, 505-17, Dec 1975. 102 | 103 | -------------------------------------------------------------------------------- /fa_Yu/assignopts.m: -------------------------------------------------------------------------------- 1 | function remain = assignopts (opts, varargin) 2 | % assignopts - assign optional arguments (matlab 5 or higher) 3 | % 4 | % REM = ASSIGNOPTS(OPTLIST, 'VAR1', VAL1, 'VAR2', VAL2, ...) 5 | % assigns, in the caller's workspace, the values VAL1,VAL2,... to 6 | % the variables that appear in the cell array OPTLIST and that match 7 | % the strings 'VAR1','VAR2',... . Any VAR-VAL pairs that do not 8 | % match a variable in OPTLIST are returned in the cell array REM. 9 | % The VAR-VAL pairs can also be passed to ASSIGNOPTS in a cell 10 | % array: REM = ASSIGNOPTS(OPTLIST, {'VAR1', VAL1, ...}); 11 | % 12 | % By default ASSIGNOPTS matches option names using the strmatch 13 | % defaults: matches are case sensitive, but a (unique) prefix is 14 | % sufficient. If a 'VAR' string is a prefix for more than one 15 | % option in OPTLIST, and does not match any of them exactly, no 16 | % assignment occurs and the VAR-VAL pair is returned in REM. 17 | % 18 | % This behaviour can be modified by preceding OPTLIST with one or 19 | % both of the following flags: 20 | % 'ignorecase' implies case-insensitive matches. 21 | % 'exact' implies exact string matches. 22 | % Both together imply case-insensitive, but otherwise exact, matches. 23 | % 24 | % ASSIGNOPTS useful for processing optional arguments to a function. 25 | % Thus in a function which starts: 26 | % function foo(x,y,varargin) 27 | % z = 0; 28 | % assignopts({'z'}, varargin{:}); 29 | % the variable z can be given a non-default value by calling the 30 | % function thus: foo(x,y,'z',4); When used in this way, a list 31 | % of currently defined variables can easily be obtained using 32 | % WHO. Thus if we define: 33 | % function foo(x,y,varargin) 34 | % opt1 = 1; 35 | % opt2 = 2; 36 | % rem = assignopts('ignorecase', who, varargin); 37 | % and call foo(x, y, 'OPT1', 10, 'opt', 20); the variable opt1 38 | % will have the value 10, the variable opt2 will have the 39 | % (default) value 2 and the list rem will have the value {'opt', 40 | % 20}. 41 | % 42 | % See also WARNOPTS, WHO. 43 | 44 | ignorecase = 0; 45 | exact = 0; 46 | 47 | % check for flags at the beginning 48 | while (~iscell(opts)) 49 | switch(lower(opts)) 50 | case 'ignorecase', 51 | ignorecase = 1; 52 | case 'exact', 53 | exact = 1; 54 | otherwise, 55 | error(['unrecognized flag :', opts]); 56 | end 57 | 58 | opts = varargin{1}; 59 | varargin = varargin{2:end}; 60 | end 61 | 62 | % if passed cell array instead of list, deal 63 | if length(varargin) == 1 & iscell(varargin{1}) 64 | varargin = varargin{1}; 65 | end 66 | 67 | if rem(length(varargin),2)~=0, 68 | error('Optional arguments and values must come in pairs') 69 | end 70 | 71 | done = zeros(1, length(varargin)); 72 | 73 | origopts = opts; 74 | if ignorecase 75 | opts = lower(opts); 76 | end 77 | 78 | for i = 1:2:length(varargin) 79 | 80 | opt = varargin{i}; 81 | if ignorecase 82 | opt = lower(opt); 83 | end 84 | 85 | % look for matches 86 | 87 | if exact 88 | match = strmatch(opt, opts, 'exact'); 89 | else 90 | match = strmatch(opt, opts); 91 | end 92 | 93 | % if more than one matched, try for an exact match ... if this 94 | % fails we'll ignore this option. 95 | 96 | if (length(match) > 1) 97 | match = strmatch(opt, opts, 'exact'); 98 | end 99 | 100 | % if we found a unique match, assign in the corresponding value, 101 | % using the *original* option name 102 | 103 | if length(match) == 1 104 | assignin('caller', origopts{match}, varargin{i+1}); 105 | done(i:i+1) = 1; 106 | end 107 | end 108 | 109 | varargin(find(done)) = []; 110 | remain = varargin; 111 | -------------------------------------------------------------------------------- /fa_Yu/cosmoother_fa.m: -------------------------------------------------------------------------------- 1 | function [Ycs, Vcs] = cosmoother_fa(Y, params) 2 | % 3 | % [Ycs, Vcs] = cosmoother_fa(Y, params) 4 | % 5 | % Performs leave-neuron-out prediction for FA or PPCA. 6 | % 7 | % INPUTS: 8 | % 9 | % Y - test data (# neurons x # data points) 10 | % params - model parameters fit to training data using fastfa.m 11 | % 12 | % OUTPUTS: 13 | % 14 | % Ycs - leave-neuron-out prediction mean (# neurons x # data points) 15 | % Vcs - leave-neuron-out prediction variance (# neurons x 1) 16 | % 17 | % Note: the choice of FA vs. PPCA does not need to be specified because 18 | % the choice is reflected in params.Ph. 19 | % 20 | % @ 2009 Byron Yu -- byronyu@stanford.edu 21 | 22 | L = params.L; 23 | Ph = params.Ph; 24 | d = params.d; 25 | 26 | [yDim, xDim] = size(L); 27 | I = eye(xDim); 28 | 29 | Ycs = zeros(size(Y)); 30 | if nargout == 2 31 | % One variance for each observed dimension 32 | % Doesn't depend on observed data 33 | Vcs = zeros(yDim, 1); 34 | end 35 | 36 | for i = 1:yDim 37 | % Indices 1:yDim with i removed 38 | mi = [1:(i-1) (i+1):yDim]; 39 | 40 | Phinv = 1./Ph(mi); % (yDim-1) x 1 41 | LRinv = (L(mi,:) .* repmat(Phinv, 1, xDim))'; % xDim x (yDim - 1) 42 | LRinvL = LRinv * L(mi,:); % xDim x xDim 43 | 44 | term2 = L(i,:) * (I - LRinvL / (I + LRinvL)); % 1 x xDim 45 | 46 | dif = bsxfun(@minus, Y(mi,:), d(mi)); 47 | Ycs(i,:) = d(i) + term2 * LRinv * dif; 48 | 49 | if nargout == 2 50 | Vcs(i) = L(i,:)*L(i,:)' + Ph(i) - term2 * LRinvL * L(i,:)'; 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /fa_Yu/crossvalidate_fa.m: -------------------------------------------------------------------------------- 1 | function dim = crossvalidate_fa(X, varargin) 2 | % 3 | % dim = crossvalidate_fa(X, ...) 4 | % 5 | % Cross-validation to determine optimal latent dimensionality for 6 | % factor analysis 7 | % 8 | % xDim: data dimensionality 9 | % N: number of data points 10 | % 11 | % INPUTS: 12 | % 13 | % X - data matrix (xDim x N) 14 | % 15 | % OUTPUTS: 16 | % 17 | % dim - structure whose ith entry (corresponding to the ith latent 18 | % dimensionality) has fields 19 | % zDim -- latent dimensionality 20 | % sumPE -- cross-validated prediction error 21 | % sumLL -- cross-validated log likelihood 22 | % estParams -- FA parameters estimated using all data 23 | % 24 | % OPTIONAL ARGUMENTS: 25 | % 26 | % numFolds - number of cross-validation folds (default: 4) 27 | % zDimList - latent dimensionalities to compare (default: [1:10]) 28 | % Note: dimensionality 0 corresponds to an independent 29 | % Gaussian model, where all variance is private. 30 | % showPlots - logical specifying whether to show CV plots 31 | % (default: true) 32 | % verbose - logical specifying whether to show CV details 33 | % (default: false) 34 | % 35 | % @ 2011 Byron Yu byronyu@cmu.edu 36 | 37 | numFolds = 4; 38 | zDimList = 1:10; 39 | showPlots = true; 40 | verbose = false; 41 | extraOpts = assignopts(who, varargin); 42 | 43 | [xDim, N] = size(X); 44 | 45 | % Randomly reorder data points 46 | % rand('state', 0); 47 | rng('shuffle') 48 | X = X(:, randperm(N)); 49 | 50 | % Set cross-validation folds 51 | fdiv = floor(linspace(1, N+1, numFolds+1)); 52 | 53 | for i = 1:length(zDimList) 54 | zDim = zDimList(i); 55 | 56 | fprintf('Processing latent dimensionality = %d\n', zDim); 57 | 58 | dim(i).zDim = zDim; 59 | dim(i).sumPE = 0; 60 | dim(i).sumLL = 0; 61 | 62 | for cvf = 0:numFolds 63 | if cvf == 0 64 | fprintf(' Training on all data.\n'); 65 | else 66 | fprintf(' Cross-validation fold %d of %d.\n', cvf, numFolds); 67 | end 68 | 69 | % Set cross-validation masks 70 | testMask = false(1, N); 71 | if cvf > 0 72 | testMask(fdiv(cvf):fdiv(cvf+1)-1) = true; 73 | end 74 | trainMask = ~testMask; 75 | 76 | Xtrain = X(:, trainMask); 77 | Xtest = X(:, testMask); 78 | 79 | % Remove observed dimension if it takes on the same value for 80 | % every training data point 81 | dimToKeep = (var(Xtrain, 1, 2) > 0); 82 | Xtrain = Xtrain(dimToKeep,:); 83 | Xtest = Xtest(dimToKeep,:); 84 | if any(~dimToKeep) 85 | fprintf('Warning: Removing observed dimension(s) showing zero training variance.\n'); 86 | end 87 | 88 | % Check if training data covariance is full rank 89 | if rcond(cov(Xtrain')) < 1e-8 90 | fprintf('ERROR: Training data covariance matrix ill-conditioned.\n'); 91 | keyboard 92 | end 93 | 94 | if verbose 95 | fprintf(' (train, test, data dim) = (%d, %d, %d)\n',... 96 | size(Xtrain,2), size(Xtest, 2), size(Xtrain, 1)); 97 | end 98 | 99 | % Fit model parameters to training data 100 | if zDim == 0 101 | estParams = indepGaussFit(Xtrain); 102 | else 103 | % fastfa.m does the heavy lifting 104 | % (here, choose not to use private noise variance floor) 105 | estParams = fastfa(Xtrain, zDim, 'minVarFrac', -Inf); 106 | end 107 | 108 | if cvf == 0 109 | % Save parameters 110 | dim(i).estParams = estParams; 111 | else 112 | % sse: prediction error on test data 113 | % LL: test likelihood 114 | if zDim == 0 115 | [LL, sse] = indepGaussEval(Xtest, estParams); 116 | else 117 | [blah, LL] = fastfa_estep(Xtest, estParams); 118 | 119 | Xcs = cosmoother_fa(Xtest, estParams); 120 | sse = sum((Xcs(:) - Xtest(:)).^2); 121 | end 122 | 123 | dim(i).sumPE = dim(i).sumPE + sse; 124 | dim(i).sumLL = dim(i).sumLL + LL; 125 | end 126 | end 127 | end 128 | 129 | if showPlots 130 | figure; 131 | 132 | % Prediction error versus latent dimensionality 133 | subplot(2, 1, 1); 134 | sumPE = [dim.sumPE]; 135 | plot(zDimList, sumPE); 136 | xlabel('Latent dimensionality'); 137 | ylabel('Cross-validated Pred Error'); 138 | 139 | hold on; 140 | istar = find(sumPE == min(sumPE)); 141 | plot(zDimList(istar), sumPE(istar), '*', 'markersize', 5); 142 | fprintf('Optimal latent dimensionality (PE) = %d\n', zDimList(istar)); 143 | 144 | % LL versus latent dimensionality 145 | subplot(2, 1, 2); 146 | sumLL = [dim.sumLL]; 147 | plot(zDimList, sumLL); 148 | xlabel('Latent dimensionality'); 149 | ylabel('Cross-validated LL'); 150 | 151 | hold on; 152 | istar = find(sumLL == max(sumLL)); 153 | plot(zDimList(istar), sumLL(istar), '*', 'markersize', 5); 154 | fprintf('Optimal latent dimensionality (LL) = %d\n', zDimList(istar)); 155 | end -------------------------------------------------------------------------------- /fa_Yu/example.m: -------------------------------------------------------------------------------- 1 | % Generate fake data using FA model 2 | % Data dimensionality: 20 3 | % Latent dimensionality: 5 4 | params.L = randn(20, 5); 5 | params.Ph = 0.1 * (1:20)'; 6 | params.mu = ones(20, 1); 7 | 8 | X = simdata_fa(params, 100); 9 | 10 | % Cross-validation 11 | dim = crossvalidate_fa(X); 12 | 13 | % Identify optimal latent dimensionality 14 | istar = ([dim.sumLL] == max([dim.sumLL])); 15 | 16 | % Project training data into low-d space 17 | Z = fastfa_estep(X, dim(istar).estParams); -------------------------------------------------------------------------------- /fa_Yu/fastfa.m: -------------------------------------------------------------------------------- 1 | function [estParams, LL] = fastfa(X, zDim, varargin) 2 | % 3 | % [estParams, LL] = fastfa(X, zDim, ...) 4 | % 5 | % Factor analysis and probabilistic PCA. 6 | % 7 | % xDim: data dimensionality 8 | % zDim: latent dimensionality 9 | % N: number of data points 10 | % 11 | % INPUTS: 12 | % 13 | % X - data matrix (xDim x N) 14 | % zDim - number of factors 15 | % 16 | % OUTPUTS: 17 | % 18 | % estParams.L - factor loadings (xDim x zDim) 19 | % estParams.Ph - diagonal of uniqueness matrix (xDim x 1) 20 | % estParams.d - data mean (xDim x 1) 21 | % LL - log likelihood at each EM iteration 22 | % 23 | % OPTIONAL ARGUMENTS: 24 | % 25 | % typ - 'fa' (default) or 'ppca' 26 | % tol - stopping criterion for EM (default: 1e-8) 27 | % cyc - maximum number of EM iterations (default: 1e8) 28 | % minVarFrac - fraction of overall data variance for each observed dimension 29 | % to set as the private variance floor. This is used to combat 30 | % Heywood cases, where ML parameter learning returns one or more 31 | % zero private variances. (default: 0.01) 32 | % (See Martin & McDonald, Psychometrika, Dec 1975.) 33 | % verbose - logical that specifies whether to display status messages 34 | % (default: false) 35 | % 36 | % Code adapted from ffa.m by Zoubin Ghahramani. 37 | % 38 | % @ 2009 Byron Yu -- byronyu@stanford.edu 39 | 40 | typ = 'fa'; 41 | tol = 1e-8; 42 | cyc = 1e8; 43 | minVarFrac = 0.01; 44 | verbose = false; 45 | assignopts(who, varargin); 46 | 47 | % randn('state', 0); 48 | rng('shuffle') 49 | [xDim, N] = size(X); 50 | 51 | % Initialization of parameters 52 | cX = cov(X', 1); 53 | if rank(cX) == xDim 54 | scale = exp(2*sum(log(diag(chol(cX))))/xDim); 55 | else 56 | % cX may not be full rank because N < xDim 57 | fprintf('WARNING in fastfa.m: Data matrix is not full rank.\n'); 58 | r = rank(cX); 59 | e = sort(eig(cX), 'descend'); 60 | scale = geomean(e(1:r)); 61 | end 62 | L = randn(xDim,zDim)*sqrt(scale/zDim); 63 | Ph = diag(cX); 64 | d = mean(X, 2); 65 | 66 | varFloor = minVarFrac * diag(cX); 67 | 68 | I = eye(zDim); 69 | const = -xDim/2*log(2*pi); 70 | LLi = 0; 71 | LL = []; 72 | 73 | for i = 1:cyc 74 | % ======= 75 | % E-step 76 | % ======= 77 | iPh = diag(1./Ph); 78 | iPhL = iPh * L; 79 | MM = iPh - iPhL / (I + L' * iPhL) * iPhL'; 80 | beta = L' * MM; % zDim x xDim 81 | 82 | cX_beta = cX * beta'; % xDim x zDim 83 | EZZ = I - beta * L + beta * cX_beta; 84 | 85 | % Compute log likelihood 86 | LLold = LLi; 87 | ldM = sum(log(diag(chol(MM)))); 88 | LLi = N*const + N*ldM - 0.5*N*sum(sum(MM .* cX)); 89 | if verbose 90 | fprintf('EM iteration %5i lik %8.1f \r', i, LLi); 91 | end 92 | LL = [LL LLi]; 93 | 94 | % ======= 95 | % M-step 96 | % ======= 97 | L = cX_beta / EZZ; 98 | Ph = diag(cX) - sum(cX_beta .* L, 2); 99 | 100 | if isequal(typ, 'ppca') 101 | Ph = mean(Ph) * ones(xDim, 1); 102 | end 103 | if isequal(typ, 'fa') 104 | % Set minimum private variance 105 | Ph = max(varFloor, Ph); 106 | end 107 | 108 | if i<=2 109 | LLbase = LLi; 110 | elseif (LLi < LLold) 111 | disp('VIOLATION'); 112 | elseif ((LLi-LLbase) < (1+tol)*(LLold-LLbase)) 113 | break; 114 | end 115 | end 116 | 117 | if verbose 118 | fprintf('\n'); 119 | end 120 | 121 | if any(Ph == varFloor) 122 | fprintf('Warning: Private variance floor used for one or more observed dimensions in FA.\n'); 123 | end 124 | 125 | estParams.L = L; 126 | estParams.Ph = Ph; 127 | estParams.d = d; 128 | -------------------------------------------------------------------------------- /fa_Yu/fastfa_estep.m: -------------------------------------------------------------------------------- 1 | function [Z, LL] = fastfa_estep(X, params) 2 | % 3 | % [Z, LL] = fastfa_estep(X, params) 4 | % 5 | % Compute the low-dimensional points and data likelihoods using a 6 | % previously learned FA or PPCA model. 7 | % 8 | % xDim: data dimensionality 9 | % zDim: latent dimensionality 10 | % N: number of data points 11 | % 12 | % INPUTS: 13 | % 14 | % X - data matrix (xDim x N) 15 | % params - learned FA or PPCA parameters (structure with fields L, Ph, d) 16 | % 17 | % OUTPUTS: 18 | % 19 | % Z.mean - posterior mean (zDim x N) 20 | % Z.cov - posterior covariance (zDim x zDim), which is the same for all data 21 | % LL - log-likelihood of data 22 | % 23 | % Note: the choice of FA vs. PPCA does not need to be specified because 24 | % the choice is reflected in params.Ph. 25 | % 26 | % Code adapted from ffa.m by Zoubin Ghaharamani. 27 | % 28 | % @ 2009 Byron Yu -- byronyu@stanford.edu 29 | 30 | [xDim, N] = size(X); 31 | zDim = size(params.L, 2); 32 | 33 | L = params.L; 34 | Ph = params.Ph; 35 | d = params.d; 36 | 37 | Xc = bsxfun(@minus, X, d); 38 | XcXc = Xc * Xc'; 39 | 40 | I=eye(zDim); 41 | 42 | const=-xDim/2*log(2*pi); 43 | 44 | iPh = diag(1./Ph); 45 | iPhL = iPh * L; 46 | MM = iPh - iPhL / (I + L' * iPhL) * iPhL'; 47 | beta = L' * MM; % zDim x xDim 48 | 49 | Z.mean = beta * Xc; % zDim x N 50 | Z.cov = I - beta * L; % zDim x zDim; same for all observations 51 | 52 | LL = N*const + 0.5*N*logdet(MM) - 0.5 * sum(sum(MM .* XcXc)); 53 | -------------------------------------------------------------------------------- /fa_Yu/indepGaussEval.m: -------------------------------------------------------------------------------- 1 | function [LL, sse] = indepGaussEval(X, params) 2 | % 3 | % [LL, sse] = indepGaussEval(X, params) 4 | % 5 | % Evaluate log likelihood and sum-of-squared prediction error given 6 | % an independent Gaussian model 7 | % 8 | % xDim: data dimensionality 9 | % N: number of data points 10 | % 11 | % INPUT: 12 | % 13 | % X - data matrix (xDim x N) 14 | % params - parameters of independent Gaussian model 15 | % (structure with fields d and Ph) 16 | % 17 | % OUTPUTS: 18 | % 19 | % LL - log likehood of data 20 | % sse - sum-of-squared prediction error 21 | % 22 | % @ 2011 Byron Yu -- byronyu@cmu.edu 23 | 24 | [xDim, N] = size(X); 25 | 26 | Ph = params.Ph; 27 | d = params.d; 28 | 29 | Xc2 = bsxfun(@minus, X, d).^2; 30 | Xstd = bsxfun(@rdivide, Xc2, Ph); 31 | 32 | LL = -0.5 * (N*xDim*log(2*pi) + N*sum(log(Ph)) + sum(Xstd(:))); 33 | 34 | sse = sum(Xc2(:)); -------------------------------------------------------------------------------- /fa_Yu/indepGaussFit.m: -------------------------------------------------------------------------------- 1 | function estParams = indepGaussFit(X) 2 | % 3 | % estParams = indepGaussFit(X) 4 | % 5 | % Fit parameters of an independent Gaussian model 6 | % 7 | % xDim: data dimensionality 8 | % N: number of data points 9 | % 10 | % INPUT: 11 | % 12 | % X - data matrix (xDim x N) 13 | % 14 | % OUTPUTS: 15 | % 16 | % estParams.d - mean of each observed dimension (xDim x 1) 17 | % estParams.Ph - variance of each observed dimension (xDim x 1) 18 | % 19 | % @ 2011 Byron Yu -- byronyu@cmu.edu 20 | 21 | % Note: parameter names are analogous to those in fastfa.m 22 | estParams.Ph = var(X, 1, 2); 23 | estParams.d = mean(X, 2); 24 | -------------------------------------------------------------------------------- /fa_Yu/logdet.m: -------------------------------------------------------------------------------- 1 | function y = logdet(A) 2 | % log(det(A)) where A is positive-definite. 3 | % This is faster and more stable than using log(det(A)). 4 | 5 | % Written by Tom Minka 6 | % (c) Microsoft Corporation. All rights reserved. 7 | 8 | U = chol(A); 9 | y = 2*sum(log(diag(U))); 10 | -------------------------------------------------------------------------------- /fa_Yu/simdata_fa.m: -------------------------------------------------------------------------------- 1 | function X = simdata_fa(params, N) 2 | % 3 | % X = simdata_fa(params, N) 4 | % 5 | % Generate fake data using FA model 6 | % 7 | % xDim: data dimensionality 8 | % zDim: latent dimensionality 9 | % 10 | % INPUTS: 11 | % 12 | % params - structure containing FA parameters 13 | % L (xDim x zDim) 14 | % Ph (xDim x 1) 15 | % mu (xDim x 1) 16 | % N - number of data points to generate 17 | % 18 | % OUTPUTS: 19 | % 20 | % X - generated fake data (xDim x N) 21 | % 22 | % @ 2011 Byron Yu byronyu@cmu.edu 23 | 24 | randn('state', 0); 25 | 26 | L = params.L; 27 | Ph = params.Ph; 28 | mu = params.mu; 29 | 30 | [xDim, zDim] = size(params.L); 31 | 32 | Z = randn(zDim, N); 33 | ns = bsxfun(@times, randn(xDim, N), sqrt(Ph)); 34 | 35 | X = bsxfun(@plus, L * Z + ns, mu); -------------------------------------------------------------------------------- /figtools/FigLabel.m: -------------------------------------------------------------------------------- 1 | function h=FigLabel(string,pos,varargin) 2 | 3 | AxisPos = get(gca,'Position'); 4 | pos = [pos(1)/AxisPos(3),pos(2)/AxisPos(4)]; 5 | pos(2) = pos(2)+1; 6 | 7 | h=text(0,0,string); 8 | set(h,'Units','normalized','HorizontalAlignment','Left',... 9 | 'Position',pos,varargin{:},'Tag','Label'); 10 | -------------------------------------------------------------------------------- /figtools/FigurePlottingTools.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcc11/SpatialNeuronNet/7e528ddb54c3b50e91fce755e13398cb79c27d93/figtools/FigurePlottingTools.docx -------------------------------------------------------------------------------- /figtools/HF_matchAspectRatio.m: -------------------------------------------------------------------------------- 1 | function HF_matchAspectRatio(varargin) 2 | 3 | P = parsePairs(varargin); 4 | if ~isfield(P,'Area') P.Area = 'print'; end 5 | if ~isfield(P,'Factor') P.Factor = 1; end 6 | 7 | PP = get(gcf,'PaperPosition'); 8 | AR = PP(4)/PP(3); 9 | FP = get(gcf,'Position'); 10 | 11 | PPI = get(0,'screenpixelsperinch'); 12 | 13 | % The cmConvFactor is the pixels per cm 14 | % switch lower(HF_getHostname) 15 | % case {'thot'}; cmConvFactor = 44.9; % assuming MacBook13" 16 | % case {'ganesha'}; cmConvFactor = 57; % assuming rMBP 15" 17 | % case {'genone','deeppurple'}; cmConvFactor = 50.9; % assuming Thinkpad x300 18 | % otherwise cmConvFactor = 40; warning('Probably need to add correct scaling factor for computer'); 19 | % end 20 | cmConvFactor = 44.9; 21 | 22 | inConvFactor = 2.54*cmConvFactor ; 23 | 24 | switch P.Area 25 | case 'keep'; 26 | FArea = FP(3)*FP(4); 27 | Xnew = round(sqrt(FArea/AR)); 28 | Ynew = round(Xnew*AR); 29 | FP(3:4) = [Xnew,Ynew]; 30 | 31 | case 'print'; 32 | cUnits = get(gcf,'PaperUnits'); 33 | switch cUnits 34 | case 'inches'; ConvFactor = inConvFactor; 35 | case 'centimeters'; ConvFactor = cmConvFactor; 36 | otherwise error('Not Implemented for selected Units'); 37 | end 38 | FP(3:4) = round(ConvFactor*PP(3:4)/P.Factor); 39 | otherwise 40 | end 41 | 42 | set(gcf,'Position',FP) 43 | -------------------------------------------------------------------------------- /figtools/HF_setFigProps.m: -------------------------------------------------------------------------------- 1 | function HF_setFigProps(varargin) 2 | 3 | P = parsePairs(varargin); 4 | checkField(P,'FIG',gcf); 5 | checkField(P,'AxisOpt',''); 6 | checkField(P,'AxisLabelOpt',''); 7 | checkField(P,'TitleOpt',''); 8 | checkField(P,'LabelOpt',''); 9 | 10 | if evalin('caller','exist(''AxisOpt'',''var'')') P.AxisOpt = evalin('caller','AxisOpt'); end; 11 | if evalin('caller','exist(''LineOpt'',''var'')') P.LineOpt = evalin('caller','LineOpt'); end; 12 | if evalin('caller','exist(''AxisLabelOpt'',''var'')'); P.AxisLabelOpt = evalin('caller','AxisLabelOpt'); end; 13 | if evalin('caller','exist(''TitleOpt'',''var'')'); P.TitleOpt = evalin('caller','TitleOpt'); end; 14 | if evalin('caller','exist(''LabelOpt'',''var'')'); P.LabelOpt = evalin('caller','LabelOpt'); end; 15 | 16 | % ASSIGN AXES PROPERTIES 17 | if ~isempty(P.AxisOpt) 18 | cAxes = get(P.FIG,'Children'); 19 | Types = get(cAxes,'Type'); 20 | Ind = strcmp(Types,'axes'); 21 | cAxes = cAxes(Ind); 22 | set(cAxes,P.AxisOpt{:}); 23 | end 24 | 25 | % ASSIGN AXIS LABEL PROPERTIES 26 | if exist('cAxes','var') && ~isempty(P.AxisLabelOpt) 27 | for iA=1:length(cAxes) 28 | cAxisLabelHandles = [get(cAxes(iA),'XLabel'),get(cAxes(iA),'YLabel'),get(cAxes(iA),'ZLabel')]; 29 | set(cAxisLabelHandles,P.AxisLabelOpt{:}); 30 | end 31 | end 32 | 33 | % ASSIGN AXIS LABEL PROPERTIES 34 | if exist('cAxes','var') && ~isempty(P.TitleOpt) 35 | for iA=1:length(cAxes) 36 | cTitleHandles = get(cAxes(iA),'Title'); 37 | set(cTitleHandles,P.TitleOpt{:} ); 38 | end 39 | end 40 | 41 | % ASSIGN AXIS LABEL PROPERTIES 42 | if exist('cAxes','var') && ~isempty(P.LabelOpt) 43 | for iA=1:length(cAxes) 44 | cChildren = get(cAxes(iA),'Children'); 45 | cTypes = get(cChildren,'Tag'); 46 | Ind = strcmp(cTypes,'Label'); 47 | cChildren = cChildren(Ind); 48 | set(cChildren,P.LabelOpt{:} ); 49 | end 50 | end 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /figtools/HF_viewsave.m: -------------------------------------------------------------------------------- 1 | function HF_viewsave(varargin) 2 | % Helper function for saving and viewing figure output 3 | % 4 | % Options: 5 | % -name : file name (without extension) 6 | % -path : file path (if left out, set to empty) 7 | % -view [{0},1] : 8 | % -format [{epsc2},epsc,pdf,jpg,tif,...] : graphics file format 9 | % -tag [{=format}] : file extension 10 | % -res [{400}] : dpi resolution 11 | % -fullpage [{0},1] : places the figure on a full A4 page 12 | % -label [String] : places a figure label underneath the figure 13 | 14 | % Dirs = setgetDirs; 15 | if ispc Sep = '\'; else Sep = '/'; end 16 | 17 | % PARSE ARGUMENTS 18 | if isstr(varargin{3}) % new format 19 | P = parsePairs(varargin); 20 | else % old format 21 | P.name = varargin{2}; P.view = varargin{3}; 22 | P.path = [Dirs.Root,'project',Sep,varargin{1},Sep,'figures']; 23 | if length(varargin)>1 P.format = varargin{4}; end 24 | if length(varargin)>2 P.tag = varargin{5}; end 25 | if length(varargin)>3 P.res = varargin{6}; end 26 | end 27 | 28 | if P.save 29 | 30 | % SET DEFAULT ARGUMENTS 31 | checkField(P,'name'); 32 | checkField(P,'view',0); 33 | checkField(P,'format','pdf'); 34 | checkField(P,'tag',P.format); 35 | checkField(P,'res',400); 36 | checkField(P,'path',[]); 37 | checkField(P,'fullpage',0); 38 | checkField(P,'label',[]); 39 | checkField(P,'colorspace',''); 40 | if ~isempty(P.path) & ~P.path(end)==Sep P.path(end+1) = Sep; end 41 | outfile = [P.path,P.name]; 42 | 43 | % PLACE FIGURE ON A FULL PAGE 44 | global Fullpage; if Fullpage P.fullpage = 1; end 45 | if P.fullpage 46 | if length(P.format)>2 & P.format(1:3)=='eps' 47 | P.format = P.format(2:end); % avoid EPS, since it would not allow full pages 48 | end 49 | set(gcf,'PaperType','A4'); PS = get(gcf,'PaperSize'); 50 | PP = get(gcf,'PaperPosition'); 51 | PP = [(PS-PP(3:4))/2,PP(3:4)]; set(gcf,'PaperPosition',PP); 52 | end 53 | 54 | % ADD FIGURE LABEL 55 | % Requires some Postscript modifications to work 56 | % first search for (label) e.g. (Figure 1) s 57 | % get Position (stated above it), e.g. 1506 2369 mt 58 | % move down (increase second value) 59 | % and change viewing box at beginning of PS, e.g. 291 127 2643 2380 rc 60 | % In general the position format is xstart,ystart,xstop,ystop 61 | % Probably implement this in a Perl script 62 | if ~isempty(P.label) 63 | PP = get(gcf,'PaperPosition'); 64 | if PP(2)<0.5 % MOVE FIGURE UPWARDS 65 | PP(2) = 0.5; set(gcf,'PaperPosition',PP); 66 | end 67 | % AP = [PP(1)+PP(3)/2,PP(2)-0.5,PP(3),0.4]; 68 | AP = [0.5,-.5,.1,.1]; 69 | h=axes('OuterPosition',[0,0,1,1],'visible','off'); 70 | text(AP(1),AP(2),P.label,'Units','normalized',... 71 | 'FontSize',14,'FontWeight','bold',... 72 | 'HorizontalAlignment','Center'); 73 | end 74 | 75 | % SET SPECIAL OPTIONS DEPENDING ON THE RENDERER 76 | switch lower(get(gcf,'Renderer')) 77 | case 'painters'; 78 | otherwise if ~isfield(P,'res') | isempty(P.res) P.res = 400; end 79 | end 80 | 81 | % SET TAG FOR FILETYPE 82 | P.format = lower(P.format); 83 | switch P.format 84 | case {'ps','psc','psc2'}; P.tag = 'ps'; 85 | case {'eps','epsc2','epsc'}; P.tag = 'eps'; 86 | case {'meta'}; P.tag = 'emf'; 87 | otherwise P.tag = P.format; 88 | end 89 | outfiletag = [outfile,'.',P.tag]; 90 | 91 | % DELETE PREVIOUS VERSION OF OUTPUT FILE 92 | if exist(outfiletag,'file') delete(outfiletag); end 93 | 94 | % PRINT THE FIGURE 95 | %'-loose' : could be useful for EPS printing 96 | print(gcf,['-d',P.format],[P.colorspace],['-r',num2str(P.res)],[outfile,'.',P.tag]); 97 | 98 | % CHECK FOR VIEWER PROGRAMS 99 | switch computer 100 | case {'MAC','MACI','MACI64'}; 101 | case 'PCWIN'; 102 | isDistiller = exist('C:\Programme\acroread.lnk','file'); 103 | isReader = exist('C:\Programme\acroread.lnk','file'); 104 | end 105 | 106 | % CONVERT TO PDF IF FILE IS EPS 107 | if strcmp(P.tag,'eps') 108 | if isunix 109 | if exist([outfile,'.pdf'],'file') delete([outfile,'.pdf']); end 110 | system(['pstopdf ',outfiletag,' ',outfile,'.pdf']); 111 | else 112 | if isDistiller system(['C:\Programme\acrodist.lnk ',outfiletag]); 113 | else LF_DistError; 114 | end 115 | end 116 | end 117 | 118 | % VIEW FILE 119 | if P.view 120 | switch computer 121 | case {'MAC','MACI','MACI64'}; 122 | outfile=strrep(outfile,' ','\ '); 123 | switch P.format 124 | case {'ps','psc','psc2','eps','epsc','epsc2','pdf'} 125 | system(['osascript -e "tell application \"Preview\" to close document \"',P.name,'.pdf\" " 2>/dev/null ']); 126 | system(['osascript -e "tell application \"Preview\" to close document \"',outfile,'.pdf\" " 2>/dev/null ']); 127 | system(['open -a Preview ',outfile,'.pdf']); 128 | otherwise 129 | system(['osascript -e "tell application \"Preview\" to close document \"',P.name,'.',P.tag,'\" " 2>/dev/null']); 130 | system(['osascript -e "tell application \"Preview\" to close document \"',outfile,'.',P.tag,'\" " 2>/dev/null ']); 131 | system(['open -a Preview ',outfile,'.',P.tag]); 132 | end 133 | 134 | case 'PCWIN'; 135 | switch P.format 136 | case {'ps','psc','psc2','eps','epsc','epsc2','pdf'} 137 | if isReader system(['C:\Programme\acroread.lnk ',outfile,'.pdf']); 138 | else LF_ReaderError 139 | end 140 | otherwise 141 | fprintf('No Viewer Programm set!'); 142 | end 143 | 144 | case {'GLNX','GLNXA64'} 145 | switch P.format 146 | case 'pdf' 147 | [s,e] = system(['evince -w ',outfile,'.pdf']); 148 | otherwise 149 | [s,e] = system(['eog -g ',outfile,'.',P.format,' &']); 150 | end 151 | 152 | otherwise fprintf(['Computertype not implemented: ',computer,'\n']); 153 | end 154 | end 155 | 156 | end 157 | function LF_DistError 158 | error('EPS file cannot be converted to PDF, since Distiller was not found.'); 159 | 160 | function LF_ReaderError 161 | error('PDF cannot be displayed, since the Acrobat Reader was not found.'); -------------------------------------------------------------------------------- /figtools/HF_whiten.m: -------------------------------------------------------------------------------- 1 | function Col = HF_whiten(Col,whitePart) 2 | Col = Col + whitePart*([1,1,1]-Col); -------------------------------------------------------------------------------- /figtools/axesDivide.m: -------------------------------------------------------------------------------- 1 | function [DivC,AH] = axesDivide(varargin) 2 | % DivC = HF_axesDivide(DivX,DivY,X0,Y0,SepXs,SepYs) 3 | % DivC = HF_axesDivide(DivX,DivY,Pos0,SepXs,SepYs) 4 | % 5 | % DivX : Vector of relative Sizes in X-Direction 6 | % DivY : Vector of relative Sizes in Y-Direction 7 | % X0 : Outer Boundary in X-Direction 8 | % Y0 : Outer Boundary in Y-Direction 9 | % SepXs : X Separation between the subplots (one less than the DivX) 10 | % SepYs : Y Separation between the subplots (one less than the DivY) 11 | 12 | AH = []; 13 | 14 | if length(varargin)>0 & ischar(varargin{end}) 15 | Option = varargin{end}; 16 | varargin = varargin(1:end-1); 17 | else Option = ''; 18 | end 19 | 20 | for i=1:5 21 | if length(varargin)1 & round(DivX)==DivX DivX = repmat(1,DivX,1); end 42 | if length(DivY)==1 & DivY>1 & round(DivY)==DivY DivY = repmat(1,DivY,1); end 43 | 44 | % If SepXs or SepYs is just one number, use it for all separations 45 | if length(SepXs)==1 & length(SepXs)~=(length(DivX)-1) 46 | SepXs = repmat(SepXs,1,length(DivX)-1); end 47 | if length(SepYs)==1 & length(SepYs)~=(length(DivY)-1) 48 | SepYs = repmat(SepYs,1,length(DivY)-1); end 49 | 50 | NX = (sum(DivX)+sum(SepXs)); NY = (sum(DivY)+sum(SepYs)); 51 | DivY = fliplr(DivY); SepYs = fliplr(SepYs); 52 | DivX = DivX/NX; DivY = DivY/NY; 53 | SepXs = SepXs/NX; SepYs = SepYs/NY; 54 | X = DivX*X0(2); Y = DivY*Y0(2); 55 | SepXs = SepXs*X0(2); SepYs = SepYs*Y0(2); 56 | for i=1:length(DivY) 57 | for j=1:length(DivX) 58 | DivC{i,j} = [X0(1)+sum(X(1:j-1))+sum(SepXs(1:j-1)),... 59 | Y0(1)+sum(Y(1:i-1))+sum(SepYs(1:i-1)),X(j),Y(i)]; 60 | end 61 | end; DivC = flipud(DivC); 62 | 63 | switch lower(Option) 64 | case {'c','create'}; 65 | AH = zeros(size(DivC)); 66 | for i=1:numel(DivC) AH(i) = axes('Pos',DivC{i}); end 67 | case ''; 68 | otherwise error('Option not implemented.'); 69 | end 70 | -------------------------------------------------------------------------------- /figtools/checkField.m: -------------------------------------------------------------------------------- 1 | function checkField(P,Field,DefVal,Type) 2 | 3 | persistent AllFields; 4 | 5 | if nargin==1 % CHECK FOR FIELDS THAT DO NOT EXIST (ARE NOT TESTED ABOVE) 6 | WrongFields = setdiff(fieldnames(P),AllFields); 7 | if ~isempty(WrongFields) error(['Field ',WrongFields{1},' does not exist!']); 8 | end 9 | return; 10 | else 11 | AllFields{end+1} = Field; AllFields = unique(AllFields); 12 | end 13 | 14 | if ~isempty(P) FN = fieldnames(P); else FN = {}; end 15 | ApproxMatch = strcmp(lower(FN),lower(Field)); 16 | if sum(ApproxMatch)% A POTENTIALLY INEXACT MATCH EXiSTS 17 | if ~sum(strcmp(FN,Field)) % NO EXACT MATCH, CORRECT TO 18 | UserField = FN{ApproxMatch}; 19 | fprintf(['Argument name ''',UserField,''' corrected to ''',Field,'''\n']); 20 | P(1).(Field) = P.(UserField); 21 | P = rmfield(P,UserField); 22 | end 23 | else % NO MATCH, NOT EVEN INEXACT EXISTS 24 | if ~exist('DefVal','var') 25 | error(['checkField : The argument ''',Field,''' needs to be assigned!']); 26 | else 27 | P(1).(Field) = DefVal; 28 | end 29 | end 30 | assignin('caller','P',P); -------------------------------------------------------------------------------- /figtools/errorhull.m: -------------------------------------------------------------------------------- 1 | function h = errorhull(X,M,S,varargin) 2 | % Errorhull plots an area around a curve, 3 | % which is determined by the local standarddeviations at each point 4 | % It thus provides a nices way of diaplaying variability than the command errorbar. 5 | % Arguments are similar to errorbar: 6 | % X : X values 7 | % M : mean of Y values (as Column Vector) 8 | % S : errors in Y direction (as Column Vector, can have two columns for different upper/lower bounds) 9 | % PlotOpt: linespec style line options 10 | % HullCol: Color of the error hull (area) 11 | % 12 | % example: errorhull([1:10],rand(1,10)+1,rand(1,10)/5+.5,'r.-',[.8,.8,.8]) 13 | 14 | P = parsePairs(varargin); 15 | checkField(P,'Color',[0,0,1]); 16 | checkField(P,'FaceColor',HF_whiten(P.Color,0.5)) 17 | checkField(P,'Alpha',0.5); 18 | checkField(P,'LineWidth',1); 19 | checkField(P,'LineStyle','-'); 20 | 21 | % ONLY OPENGL CAN RENDER TRANSPARENCY 22 | if P.Alpha<1 set(gcf,'Renderer','OpenGL'); end 23 | 24 | % CHECK IF UPPER AND LOWER BOUNDS ARE THE SAME OR DIFFERENT 25 | if isempty(find(size(M)==1)) error('Means have to be a vector!'); end 26 | if size(X,1) height (in pixels). 8 | % 9 | % COLORBAR without arguments either adds a new vertical color scale 10 | % or updates an existing colorbar. 11 | % 12 | % H = COLORBAR(...) returns a handle to the colorbar axis. 13 | 14 | % Clay M. Thompson 10-9-92 15 | % Copyright (c) 1984-98 by The MathWorks, Inc. 16 | % $Revision: 5.31 $ $Date: 1998/07/24 18:08:03 $ 17 | 18 | % If called with COLORBAR(H) or for an existing colorbar, don't change 19 | % the NextPlot property. 20 | 21 | % Aug. '00 - modified, to make it narrower (A.Shcherbina) 22 | changeNextPlot = 1; 23 | 24 | if nargin<1, loc = 'vert'; end 25 | 26 | % Catch colorbar('delete') special case -- must be called by the deleteFcn. 27 | if nargin==1 & strcmp(loc,'delete'), 28 | ax = gcbo; 29 | if strcmp(get(ax,'tag'),'TMW_COLORBAR'), ax=get(ax,'parent'); end 30 | ud = get(ax,'userdata'); 31 | if isfield(ud,'PlotHandle') & ishandle(ud.PlotHandle) & ... 32 | isfield(ud,'origPos') & ~isempty(ud.origPos) 33 | units = get(ud.PlotHandle,'units'); 34 | set(ud.PlotHandle,'units','normalized'); 35 | set(ud.PlotHandle,'position',ud.origPos); 36 | set(ud.PlotHandle,'units',units); 37 | end 38 | if isfield(ud,'DeleteProxy') & ishandle(ud.DeleteProxy) 39 | delete(ud.DeleteProxy) 40 | end 41 | if ~isempty(legend) 42 | legend % Update legend 43 | end 44 | return 45 | end 46 | 47 | ax = []; 48 | if nargin==1, 49 | if ishandle(loc) 50 | ax = loc; 51 | if ~strcmp(get(ax,'type'),'axes'), 52 | error('Requires axes handle.'); 53 | end 54 | units = get(ax,'units'); set(ax,'units','pixels'); 55 | rect = get(ax,'position'); set(ax,'units',units) 56 | if rect(3) > rect(4), loc = 'horiz'; else loc = 'vert'; end 57 | changeNextPlot = 0; 58 | end 59 | end 60 | 61 | % Determine color limits by context. If any axes child is an image 62 | % use scale based on size of colormap, otherwise use current CAXIS. 63 | 64 | ch = get(gcda,'children'); 65 | hasimage = 0; t = []; 66 | cdatamapping = 'direct'; 67 | 68 | for i=1:length(ch), 69 | typ = get(ch(i),'type'); 70 | if strcmp(typ,'image'), 71 | hasimage = 1; 72 | cdatamapping = get(ch(i), 'CDataMapping'); 73 | elseif strcmp(typ,'surface') & ... 74 | strcmp(get(ch(i),'FaceColor'),'texturemap') % Texturemapped surf 75 | hasimage = 2; 76 | cdatamapping = get(ch(i), 'CDataMapping'); 77 | elseif strcmp(typ,'patch') | strcmp(typ,'surface') 78 | cdatamapping = get(ch(i), 'CDataMapping'); 79 | end 80 | end 81 | 82 | if ( strcmp(cdatamapping, 'scaled') ) 83 | % Treat images and surfaces alike if cdatamapping == 'scaled' 84 | t = caxis; 85 | % d = (t(2) - t(1))/size(colormap,1); 86 | % t = [t(1)+d/2 t(2)-d/2]; 87 | else 88 | if hasimage, 89 | t = [1, size(colormap,1)]; 90 | else 91 | t = [1.5 size(colormap,1)+.5]; 92 | end 93 | end 94 | 95 | h = gcda; 96 | 97 | if nargin==0, 98 | % Search for existing colorbar 99 | ch = get(findobj(gcf,'type','image','tag','TMW_COLORBAR'),{'parent'}); ax = []; 100 | for i=1:length(ch), 101 | ud = get(ch{i},'userdata'); 102 | d = ud.PlotHandle; 103 | if prod(size(d))==1 & isequal(d,h), 104 | ax = ch{i}; 105 | pos = get(ch{i},'Position'); 106 | if pos(3)0, handle = ax; end 209 | 210 | %-------------------------------- 211 | function h = gcda 212 | %GCDA Get current data axes 213 | 214 | h = datachildren(gcf); 215 | if isempty(h) | any(h == gca) 216 | h = gca; 217 | else 218 | h = h(1); 219 | end 220 | 221 | -------------------------------------------------------------------------------- /figtools/parsePairs.m: -------------------------------------------------------------------------------- 1 | function S = parsePairs(Cell) 2 | 3 | %Structures varargin input and checks for invalid input. The input has to 4 | %come in 'argument','value' pairs, where 'argument' is a variable of type 5 | %char. The parameters are extracted from the varargin cell and ordered in 6 | %the structure S. 7 | S = []; 8 | if mod(length(Cell),2)==1 error('Number of input arguments is not even!'); end 9 | for i=1:length(Cell)/2 10 | if ~ischar(Cell{2*i-1}) error('One of the cells is not a Name.'); end 11 | eval(['S.',Cell{2*i-1},' = Cell{2*i};']); 12 | end -------------------------------------------------------------------------------- /figtools/placeFigures.m: -------------------------------------------------------------------------------- 1 | function FIGs = placeFigures(varargin) 2 | % Automatically place figures in a grid (underlying HF_axesDivide allows noneven splits) 3 | 4 | %% PARSE ARGUMENTS 5 | P = parsePairs(varargin); 6 | checkField(P,'Figures','all'); 7 | checkField(P,'XY','auto'); 8 | checkField(P,'Toolbar','none'); 9 | checkField(P,'Menubar','none'); 10 | checkField(P,'Position','screen'); 11 | checkField(P,'XMargin',0.02); 12 | checkField(P,'YMargin','auto'); 13 | 14 | %% GET FIGURES TO BE ORGANIZED 15 | FIGs = get(0,'Children'); 16 | if ~strcmp(P.Figures,'all') FIGs = P.Figures; %intersect(FIGs,P.Figures); 17 | else FIGs = sort(FIGs,'ascend'); 18 | end 19 | 20 | %% ADAPT GRID TO AVAILABLE FIGURES 21 | NFigs = length(FIGs); 22 | if ~iscell(P.XY) 23 | if strcmp(P.XY,'auto') 24 | P.XY = [ceil(sqrt(NFigs)),ceil(sqrt(NFigs))]; 25 | end 26 | YHeight = P.XY(2); 27 | NGrid = P.XY(1)*P.XY(2); 28 | else % GRID IS A CELL, ASYMMETRIC DIVISION 29 | NGrid = length(P.XY{1})*length(P.XY{2}); 30 | YHeight = mean(P.XY{2}); 31 | end 32 | if NGrid < NFigs 33 | fprintf('WARNING : Adapting grid to the number of figures!\n'); 34 | P.XY(1) = ceil(NFigs/P.XY(1)); 35 | end 36 | 37 | %% ADAPT MARGINS 38 | Opts = {}; MAdd = 1; 39 | if ~isempty(P.Toolbar) Opts = {Opts{:},'Toolbar',P.Toolbar}; MAdd = MAdd+1; end 40 | if ~isempty(P.Toolbar) Opts = {Opts{:},'Menubar',P.Menubar}; MAdd = MAdd + 1; end 41 | 42 | %% CREATE FIGURE POSITIONS 43 | if strcmp(P.YMargin,'auto') P.YMargin = 0.07*MAdd*YHeight; end 44 | if strcmp(P.Position,'screen') P.Position = get(0,'ScreenSize') + [1,1,-2,-80];end 45 | if ~iscell(P.XY) 46 | Positions = HF_axesDivide(P.XY(1),P.XY(2),P.Position,P.XMargin,P.YMargin); 47 | else 48 | Positions = HF_axesDivide(P.XY{1},P.XY{2},P.Position,P.XMargin,P.YMargin); 49 | end 50 | Positions = Positions'; 51 | 52 | %% POSITION FIGURES 53 | for i=1:NFigs 54 | % figure(FIGs(i)); % raise figures : too slow 55 | cOpts = {Opts{:},'Position',round(Positions{i})}; 56 | set(FIGs(i),cOpts{:}); 57 | end 58 | 59 | if ~nargout clear FIGs; end -------------------------------------------------------------------------------- /figtools/plotarea.m: -------------------------------------------------------------------------------- 1 | function h = plotarea(X,M,varargin) 2 | % Errorhull plots an area around a curve, 3 | % which is determined by the local standarddeviations at each point 4 | % It thus provides a nices way of diaplaying variability than the command errorbar. 5 | % Arguments are similar to errorbar: 6 | % X : X values 7 | % M : mean of Y values (as Column Vector) 8 | % S : errors in Y direction (as Column Vector, can have two columns for different upper/lower bounds) 9 | % PlotOpt: linespec style line options 10 | % HullCol: Color of the error hull (area) 11 | % 12 | % example: errorhull([1:10],rand(1,10)+1,rand(1,10)/5+.5,'r.-',[.8,.8,.8]) 13 | 14 | P = parsePairs(varargin); 15 | checkField(P,'Color',[0,0,1]); 16 | checkField(P,'FaceColor',HF_whiten(P.Color,0.5)) 17 | checkField(P,'Alpha',0.5); 18 | checkField(P,'LineWidth',1); 19 | checkField(P,'LineStyle','-'); 20 | 21 | % ONLY OPENGL CAN RENDER TRANSPARENCY 22 | if P.Alpha<1 set(gcf,'Renderer','OpenGL'); end 23 | 24 | % CHECK IF UPPER AND LOWER BOUNDS ARE THE SAME OR DIFFERENT 25 | if isempty(find(size(M)==1)) error('Means have to be a vector!'); end 26 | if size(X,1)=2 & ~isempty(cVar{2}) tmp = ['FontWeight', cVar{2}, tmp]; end 122 | if length(cVar)>=3 & ~isempty(cVar{3}) tmp = ['FontName', cVar{3}, tmp]; 123 | else tmp = ['FontName', FontName, tmp]; 124 | end; eval([VarName,'=tmp;']); 125 | end 126 | 127 | % Test options 128 | if exist('MaxHeight','var') LF_CheckHeight(P.height,MaxHeight,LocalUnits); end 129 | % if ~exist(inpath,'file') error(['Path ',inpath,' does not exist!']); end 130 | % if ~exist(outpath,'file') error(['Path ',outpath,' does not exist!']); end 131 | 132 | % Assign variables in caller Workspace 133 | Vars = {'gvec','Sep','inpath','outpath',... 134 | 'FigOpt','TitleOpt','LabelOpt','AxisLabelOpt','AxisOpt','TextOpt',... 135 | 'LegendOpt','LineOpt','MarkerOpt','PointOpt'}; 136 | for i=1:length(Vars) 137 | if exist(Vars{i},'var') eval(['assignin(''caller'',Vars{i},',Vars{i},');']); end 138 | end 139 | if isfield(P,'FIG') 140 | figure(P.FIG); clf; set(gcf,FigOpt{:}); 141 | HF_matchAspectRatio; 142 | end 143 | if isfield(P,'Bare') & P.Bare == 1; 144 | set(gcf,'MenuBar','none','Toolbar','none'); 145 | end 146 | Stack = dbstack; assignin('caller','name',Stack(2).name); 147 | 148 | 149 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 150 | function W = LF_CheckHeight(Height,Max,Units) 151 | if Height>Max warning(['Height must be smaller than ',n2s(Max),' ',Units]); end 152 | 153 | function W = LF_Cols(Cols,SelCol) 154 | ind = find(Cols(1,:)==SelCol); 155 | if ~isempty(ind) W = Cols(2,ind); 156 | else error('Desired Columns not available!'); 157 | end -------------------------------------------------------------------------------- /figtools/setgetDirs.m: -------------------------------------------------------------------------------- 1 | function Dirs = setgetDirs(varargin) 2 | % If no Arguments are given, return all the globally defined directories, 3 | % plus the standard directory 4 | % User supplied directories overwrite the one in GV and the Default Dirs. 5 | % 6 | % current Directories are: Speaker, STRF, TIT, TIIT, Results, Colormaps 7 | % 8 | % CALL: setgetDirs('STRF','C:\project\STRFs') 9 | global Dirs; 10 | if ~isempty(varargin) & iscell(varargin) & iscell(varargin{1}) varargin = varargin{1}; end 11 | Sep = HF_getSep; 12 | 13 | % GET COMPUTER FOR SPECIAL CASES 14 | Hostname = HF_getHostname; 15 | 16 | % Default directories: 17 | DDirs.Root= LF_sysPath; 18 | switch lower(Hostname) 19 | case 'plethora'; 20 | DDirs.Ferrets = 'D:\Data\'; 21 | DDirs.Dropbox = 'C:\Users\dzb\Documents\My Dropbox\'; 22 | case 'genone'; 23 | DDirs.Dropbox = LF_sysPath('Dropbox'); 24 | otherwise 25 | DDirs.Ferrets = LF_sysPath('project','Records','Ferrets'); 26 | DDirs.Dropbox = LF_sysPath('Dropbox'); 27 | end 28 | DDirs.Speaker= LF_sysPath('project','Speakers'); 29 | DDirs.G = LF_sysPath('project','Records','G'); 30 | DDirs.Kv = LF_sysPath('project','Records','Kv'); 31 | DDirs.W = LF_sysPath('project','Records','W'); 32 | DDirs.S = LF_sysPath('project','Records','S'); 33 | DDirs.SD = LF_sysPath('project','Records','SD'); 34 | DDirs.R = LF_sysPath('project','Records','R'); 35 | DDirs.M = LF_sysPath('project','Records','M'); 36 | DDirs.CBL = LF_sysPath('project','Records','CBL'); 37 | DDirs.CBA = LF_sysPath('project','Records','CBA'); 38 | DDirs.STRF = LF_sysPath('project','STRFs'); 39 | DDirs.WAR = LF_sysPath('project','WARs'); 40 | DDirs.WAV = LF_sysPath('project','STRFs','WAV'); 41 | DDirs.Records = LF_sysPath('project','Records'); 42 | DDirs.bcluster = LF_sysPath('project','Records','bcluster'); 43 | DDirs.Export = LF_sysPath('project','Records','Export'); 44 | DDirs.Analysa = LF_sysPath('project','Records','Analysa'); 45 | DDirs.Notes = LF_sysPath('project','Records','Notes'); 46 | DDirs.TIT = LF_sysPath('project','STRFs','TITemplates'); 47 | DDirs.TIIT = LF_sysPath('project','STRFs','TIITemplates'); 48 | DDirs.Results = LF_sysPath('project','Records','Results'); 49 | DDirs.TmpResults = LF_sysPath('tmp','Results'); 50 | DDirs.invitro = LF_sysPath('project','ExtraEPSC'); 51 | DDirs.TTNfigures = LF_sysPath('project','TTNdata','Paper','figures'); 52 | if ispc DDirs.mfiles = LF_sysPath('Bernhard','mfiles'); 53 | else DDirs.mfiles = LF_sysPath('mfiles'); end 54 | DDirs.SpikeTimes = LF_sysPath('project','Records','SpikeTimes'); 55 | DDirs.VarDelay = LF_sysPath('project','ART_VarDelay'); 56 | DDirs.MNTBmodel = LF_sysPath('project','ART_MNTBmodel'); 57 | DDirs.MNTBwavedev = LF_sysPath('project','ART_MNTBwavedev'); 58 | DDirs.iPPdetect = LF_sysPath('project','ART_iPPdetect'); 59 | DDirs.AVCNwaveforms = LF_sysPath('project','ART_AVCNwaveforms'); 60 | DDirs.AVCNcluster = LF_sysPath('project','ART_AVCNcluster'); 61 | DDirs.AVCNwavefit = LF_sysPath('project','ART_AVCNwavefit'); 62 | DDirs.NeuroFEM = LF_sysPath('project','ART_NeuroFEM'); 63 | DDirs.ArrayDrive = LF_sysPath('project','ART_ArrayDrive'); 64 | DDirs.Colormaps = LF_sysPath('project','STRFs','Colormaps'); 65 | DDirs.NoiseCorr = LF_sysPath('project','ART_NoiseCorr'); 66 | DDirs.Shepard = LF_sysPath('Dropbox','Projects','Shepard'); 67 | DDirs.ShepardPhys = [DDirs.Shepard,'ART_ShepardPhys',Sep]; 68 | DDirs.ShepardBehave = [DDirs.Shepard,'ART_ShepardBehave',Sep]; 69 | DDirs.StimSpace = LF_sysPath('Dropbox','Projects','ART_StimSpace'); 70 | DDirs.ART_MANTA = LF_sysPath('Dropbox','Projects','ART_MANTA'); 71 | DDirs.ITBarrel=LF_sysPath('Dropbox','Projects','ART_ITBarrel'); 72 | DDirs.Interneuron = LF_sysPath('Dropbox','Projects','IrregularInterneuron'); 73 | DDirs.ISH2012 = LF_sysPath('Dropbox','Wissen','Publications','Conferences','ISH','2012','Submission'); 74 | DDirs.Texture = LF_sysPath('Dropbox','Psychophysics','ART_TextureDetection'); 75 | DDirNames = fieldnames(DDirs); 76 | DDirString = DDirNames{1}; 77 | for i=2:length(DDirNames) DDirString = [DDirString,' | ',DDirNames{i}]; end 78 | 79 | % collect and set the User input directories to Dirs (global) 80 | UDirs = cell2struct(varargin(2:2:end),varargin(1:2:end),2); 81 | UDirNames = fieldnames(UDirs); 82 | for i=1:length(UDirNames) 83 | UDirs.(UDirNames{i}) = sysPathConcat(UDirs.(UDirNames{i})); 84 | if ~strmatch(UDirNames{i},DDirNames) 85 | warning(['PathName not in the list of default-path names: ', DDirString]); 86 | end 87 | Dirs.(UDirNames{i}) = UDirs.(UDirNames{i}); 88 | end 89 | 90 | % set the remaining paths to the default paths, if they have not been set via User or GV 91 | if ~isempty(Dirs) 92 | for i=1:length(DDirNames) 93 | if ~sum(strcmp(DDirNames{i},fieldnames(Dirs))) 94 | Dirs.(DDirNames{i}) = DDirs.(DDirNames{i}); 95 | end 96 | end 97 | else 98 | Dirs = DDirs; 99 | end 100 | 101 | function Path = LF_sysPath(varargin) 102 | global Dirs; 103 | if ~isempty(Dirs) & isfield(Dirs,'Root') Root = Dirs.Root; 104 | else 105 | if isunix cd('~/'); Root = pwd; 106 | elseif strmatch(architecture,'PCWIN') 107 | Name = getenv('computername'); 108 | switch Name 109 | case 'PLETHORA'; Root = 'D:\'; 110 | otherwise Root = 'C:\'; 111 | end 112 | end 113 | Dirs.Root = Root; 114 | end 115 | Path = sysPathConcat(Root,varargin); -------------------------------------------------------------------------------- /genXspk.m: -------------------------------------------------------------------------------- 1 | function sx=genXspk(p,Nx,T) 2 | % generate spike trains of Layer 1 3 | % p: param struct 4 | % Nx: # of neurons in Layer 1 5 | % T: total simulation time 6 | switch p.stim_type 7 | case 'LocalCorr' 8 | cx=p.cx; 9 | rX=p.rX; 10 | Nx1=sqrt(Nx); 11 | kc=round(Nx*cx); 12 | nspikes=round(T*1.1*rX/cx); 13 | tempspikes=sort(rand(nspikes,1)*(T)); % uniform distribution 14 | sx=zeros(2,kc*numel(tempspikes)); 15 | for j=1:numel(tempspikes) 16 | sx(1,(j-1)*kc+1:j*kc)=tempspikes(j)+randn(kc,1)*p.taucorr; 17 | 18 | %%% Localized correlations 19 | spikeloc=rand(1,2); 20 | spikeindXs=mod(round((randn(kc,1)*p.sigmac+spikeloc(1))*Nx1)-1,Nx1); 21 | spikeindYs=mod(round((randn(kc,1)*p.sigmac+spikeloc(2))*Nx1)-1,Nx1); 22 | sx(2,(j-1)*kc+1:j*kc)=spikeindXs*Nx1+spikeindYs+1; 23 | end 24 | 25 | case 'Uncorr' 26 | % Generate uncorrelated spike trains for the feedforward layer 27 | sx=[]; 28 | Nsource=p.Nsource; 29 | rX=p.rX; 30 | for ns=1:Nsource 31 | tempspikes=cumsum(-log(rand(1,round(rX(ns)*(Nx/Nsource)*T*1.1)))/(rX(ns)*(Nx/Nsource))); 32 | tempspikes=tempspikes(tempspikes0); 33 | sx_temp=zeros(2,numel(tempspikes)); 34 | sx_temp(1,:)=tempspikes; 35 | sx_temp(2,:)=ceil(rand(1,size(sx_temp,2))*Nx/Nsource)+(ns-1)*Nx/Nsource; 36 | sx=[sx,sx_temp]; 37 | end 38 | 39 | case 'GlobalCorr' 40 | sx=[]; 41 | Nsource=p.Nsource; 42 | rX=p.rX;cx=p.cx; 43 | for ns=1:Nsource 44 | % divid Nx for ns sources of correlation 45 | %%% globally correlated input 46 | kc_global=round(ceil(Nx/Nsource)*cx(ns)); 47 | nspikes=round(T*1.1*rX(ns)/cx(ns)); 48 | % tempspikes=sort(rand(nspikes,1)*(T-4*dt)+2*dt); % uniform distribution 49 | tempspikes=cumsum(-log(rand(1,nspikes))/(rX(ns)/cx(ns))); 50 | sx_temp=zeros(2,kc_global*numel(tempspikes)); 51 | for j=1:numel(tempspikes) 52 | sx_temp(1,(j-1)*kc_global+1:j*kc_global)=tempspikes(j)+randn(kc_global,1)*p.taucorr; 53 | 54 | %%% Global correlations 55 | spikeinds=randi(ceil(Nx/Nsource),1,kc_global)+ceil(Nx/Nsource)*(ns-1); 56 | sx_temp(2,(j-1)*kc_global+1:j*kc_global)=spikeinds; 57 | end 58 | sx=[sx, sx_temp]; 59 | end 60 | 61 | case 'MultiSource' % when sigmaRx is not global 62 | sx=[]; 63 | Nsource=p.Nsource; 64 | rX=p.rX;cx=p.cx; 65 | for ns=1:Nsource 66 | % divid Nx for ns sources of correlation 67 | %%% globally correlated input 68 | kc_global=round(ceil(Nx/Nsource)*cx(ns)); 69 | nspikes=round(T*1.1*rX(ns)/cx(ns)); 70 | tempspikes=cumsum(-log(rand(1,nspikes))/(rX(ns)/cx(ns))); 71 | % tempspikes=sort(rand(nspikes,1)*(T-4*dt)+2*dt); % uniform distribution 72 | sx_temp=zeros(2,kc_global*numel(tempspikes)); 73 | for j=1:numel(tempspikes) 74 | sx_temp(1,(j-1)*kc_global+1:j*kc_global)=tempspikes(j)+randn(kc_global,1)*p.taucorr; 75 | 76 | %%% Global correlations 77 | spikeinds=randi(ceil(Nx/Nsource),1,kc_global)*Nsource-(ns-1); 78 | % mixed in space, mod(sx1,Nsource)=0, 79 | % mod(sx2,Nsource)=1, etc 80 | sx_temp(2,(j-1)*kc_global+1:j*kc_global)=spikeinds; 81 | end 82 | sx=[sx, sx_temp]; 83 | end 84 | case 'spatialInput' % sigmac: spatial spread, centered at [.5 .5] 85 | % peak rate is rX 86 | % fr=@(x,y) rX*exp(-((x-.5).^2+(y-.5).^2)/(2*sigmac^2))/(2*pi*sigmac^2); 87 | % %mean rate is rX 88 | % fr=@(x,y) rX*exp(-((x-.5).^2+(y-.5).^2)); 89 | % center=[.5 .5]+[0.02, 0]; 90 | rX=p.rX; 91 | center=p.center; 92 | Nx1=round(sqrt(Nx)); 93 | CircRandN=@(mu,sigma,min,max,n)(mod(round(sigma*randn(n,1)+mu)-min,max-min+1)+min); 94 | mrate=rX*(2*pi*sigmac^2); 95 | tempspikes=cumsum(-log(rand(1,round(mrate*Nx*T*1.2)))/(mrate*Nx)); 96 | tempspikes=tempspikes(tempspikes0); 97 | sx=zeros(2,numel(tempspikes)); 98 | sx(1,:)=tempspikes; 99 | Ix=CircRandN(center(1)*Nx1,(sigmac*Nx1),1,Nx1,numel(tempspikes)); 100 | Iy=CircRandN(center(2)*Nx1,(sigmac*Nx1),1,Nx1,numel(tempspikes)); 101 | sx(2,:)=(Ix-1)*Nx1+Iy; 102 | end 103 | 104 | [~,J]=sort(sx(1,:)); 105 | sx=sx(:,J); 106 | sx=sx(:,sx(1,:)>0&sx(1,:)<=T); 107 | 108 | -------------------------------------------------------------------------------- /gen_weights.m: -------------------------------------------------------------------------------- 1 | function [Wrr,Wrf]=gen_weights(Ne,Ni,Nx,sigmaRX,sigmaRR,Prr,Prx,dimension) 2 | % sigmaRR=[sigmaee, sigmaei; sigmaie, sigmaii]; 2x2 3 | % sigmaRX=[sigmaeX; sigmaiX]; 4 | % dimension='1D' or '2D' 5 | 6 | % sort post syn index 7 | 8 | switch dimension 9 | 10 | case '2D' 11 | % x, y range: [1 Ne1], [1,Ni1], [1 Nx1] 12 | % exc. ID [1, Ne], x=ceil(I/Ne1); y=(mod((I-1),Ne1)+1); I=(x-1)*Ne1+y 13 | % inh. ID [Ne+1, Ne+Ni], x=ceil((I-Ne)/Ni1); y=(mod((I-Ne-1),Ni1)+1); I=(x-1)*Ni1+y+Ne; 14 | 15 | % Connection widths 16 | sigmaeX=sigmaRX(1); 17 | sigmaiX=sigmaRX(2); 18 | sigmaee=sigmaRR(1,1); 19 | sigmaei=sigmaRR(1,2); 20 | sigmaie=sigmaRR(2,1); 21 | sigmaii=sigmaRR(2,2); 22 | 23 | pee0=Prr(1,1); 24 | pei0=Prr(1,2); 25 | pie0=Prr(2,1); 26 | pii0=Prr(2,2); 27 | pex0=Prx(1); 28 | pix0=Prx(2); 29 | 30 | Ne1=sqrt(Ne); 31 | Ni1=sqrt(Ni); 32 | Nx1=sqrt(Nx); 33 | betaee=sigmaee*(Ne1); 34 | betaei=sigmaei*(Ne1); 35 | betaie=sigmaie*(Ni1); 36 | betaii=sigmaii*(Ni1); 37 | betaex=sigmaeX*(Ne1); 38 | betaix=sigmaiX*(Ni1); 39 | % Kab is the total number of projections a neuron from 40 | % pop b makes to ALL neurons in pop a 41 | Kee=ceil(pee0*Ne); 42 | Kei=ceil(pei0*Ne); 43 | 44 | Kie=ceil(pie0*Ni); 45 | Kii=ceil(pii0*Ni); 46 | 47 | Kex=ceil(pex0*Ne); 48 | Kix=ceil(pix0*Ni); 49 | 50 | CircRandN=@(mu,sigma,min,max,n)(mod(round(sigma*randn(n,1)+mu)-min,max-min+1)+min); 51 | 52 | Ke=Kee+Kie; % Number of excitatory and inhibitory connections per cell 53 | Ki=Kei+Kii; 54 | Kx=Kex+Kix; 55 | Wrr=zeros(Ke*Ne+Ki*Ni,1,'int32'); % recurrent connections 56 | Wrf=zeros(Kx*Nx,1,'int32'); % feedforward connections 57 | 58 | for j=1:Ne 59 | % E pre, E post 60 | x_pre=ceil(j/Ne1); 61 | y_pre=mod(j-1,Ne1)+1; 62 | x_post=CircRandN(x_pre,betaee,1,Ne1,Kee); 63 | y_post=CircRandN(y_pre,betaee,1,Ne1,Kee); 64 | Wrr((1+(j-1)*Ke):(Kee+(j-1)*Ke))=sort((x_post-1)*Ne1+y_post); 65 | 66 | % E pre, I post 67 | x_pre=ceil(j/Ne1)*Ni1/Ne1; 68 | y_pre=(mod(j-1,Ne1)+1)*Ni1/Ne1; 69 | x_post=CircRandN(x_pre,betaie,1,Ni1,Kie); 70 | y_post=CircRandN(y_pre,betaie,1,Ni1,Kie); 71 | Wrr((Kee+1+(j-1)*Ke):(Kee+Kie+(j-1)*Ke))=sort((x_post-1)*Ni1+y_post+Ne); 72 | end 73 | for j=1:Ni 74 | % I pre, E post 75 | x_pre=ceil(j/Ni1)*Ne1/Ni1; 76 | y_pre=(mod(j-1,Ni1)+1)*Ne1/Ni1; 77 | x_post=CircRandN(x_pre,betaei,1,Ne1,Kei); 78 | y_post=CircRandN(y_pre,betaei,1,Ne1,Kei); 79 | Wrr((Ne*Ke+1+(j-1)*Ki):(Ne*Ke+Kei+(j-1)*Ki))=sort((x_post-1)*Ne1+y_post); 80 | % I pre, I post 81 | x_pre=ceil(j/Ni1); 82 | y_pre=(mod(j-1,Ni1)+1); 83 | x_post=CircRandN(x_pre,betaii,1,Ni1,Kii); 84 | y_post=CircRandN(y_pre,betaii,1,Ni1,Kii); 85 | Wrr((Ne*Ke+Kei+1+(j-1)*Ki):(Ne*Ke+Kei+Kii+(j-1)*Ki))=sort((x_post-1)*Ni1+y_post+Ne); 86 | end 87 | 88 | for j=1:Nx 89 | % X pre, E post 90 | x_pre=ceil(j/Nx1)*Ne1/Nx1; 91 | y_pre=(mod(j-1,Nx1)+1)*Ne1/Nx1; 92 | x_post=CircRandN(x_pre,betaex,1,Ne1,Kex); 93 | y_post=CircRandN(y_pre,betaex,1,Ne1,Kex); 94 | Wrf((Kx*(j-1)+1):(Kx*(j-1)+Kex))=sort((x_post-1)*Ne1+y_post); 95 | % X pre, I post 96 | x_pre=ceil(j/Nx1)*Ni1/Nx1; 97 | y_pre=(mod(j-1,Nx1)+1)*Ni1/Nx1; 98 | x_post=CircRandN(x_pre,betaix,1,Ni1,Kix); 99 | y_post=CircRandN(y_pre,betaix,1,Ni1,Kix); 100 | Wrf((Kex+1+(j-1)*Kx):(j*Kx))=sort((x_post-1)*Ni1+y_post+Ne); 101 | end 102 | 103 | case '1D' 104 | % Connection widths 105 | sigmaeX=sigmaRX(1); 106 | sigmaiX=sigmaRX(2); 107 | sigmaee=sigmaRR(1,1); 108 | sigmaei=sigmaRR(1,2); 109 | sigmaie=sigmaRR(2,1); 110 | sigmaii=sigmaRR(2,2); 111 | 112 | % Connection widths in units of neuron indices 113 | pee0=Prr(1,1); 114 | pei0=Prr(1,2); 115 | pie0=Prr(2,1); 116 | pii0=Prr(2,2); 117 | pex0=Prx(1); 118 | pix0=Prx(2); 119 | 120 | betaee=sigmaee*(Ne); 121 | betaei=sigmaei*(Ne); 122 | betaie=sigmaie*(Ni); 123 | betaii=sigmaii*(Ni); 124 | betaex=sigmaeX*(Ne); 125 | betaix=sigmaiX*(Ni); 126 | 127 | % Kab is the total number of projections a neuron from 128 | % pop b makes to ALL neurons in pop a 129 | Kee=ceil(pee0*Ne); 130 | Kei=ceil(pei0*Ne); 131 | 132 | Kie=ceil(pie0*Ni); 133 | Kii=ceil(pii0*Ni); 134 | 135 | Kex=ceil(pex0*Ne); 136 | Kix=ceil(pix0*Ni); 137 | 138 | CircRandN=@(mu,sigma,min,max,n)(mod(round(sigma*randn(n,1)+mu)-min,max-min+1)+min); 139 | 140 | Ke=Kee+Kie; % Number of excitatory and inhibitory connections per cell 141 | Ki=Kei+Kii; 142 | Kx=Kex+Kix; 143 | Wrr=zeros(Ke*Ne+Ki*Ni,1,'int32'); % recurrent connections 144 | Wrf=zeros(Kx*Nx,1,'int32'); % feedforward connections 145 | 146 | for j=1:Ne 147 | % E pre, E post 148 | Wrr((1+(j-1)*Ke):(Kee+(j-1)*Ke))=(CircRandN(j,betaee,1,Ne,Kee)); 149 | 150 | % E pre, I post 151 | Wrr((Kee+1+(j-1)*Ke):(Kee+Kie+(j-1)*Ke))=(CircRandN(j/Ne*Ni+Ne,betaie,Ne+1,Ni+Ne,Kie)); 152 | end 153 | for j=1:Ni 154 | % I pre, E post 155 | Wrr((Ne*Ke+1+(j-1)*Ki):(Ne*Ke+Kei+(j-1)*Ki))=(CircRandN(j/Ni*Ne,betaei,1,Ne,Kei)); 156 | % I pre, I post 157 | Wrr((Ne*Ke+Kei+1+(j-1)*Ki):(Ne*Ke+Kei+Kii+(j-1)*Ki))=(CircRandN(j+Ne,betaii,Ne+1,Ne+Ni,Kii)); 158 | end 159 | 160 | for j=1:Nx 161 | % X pre, E post 162 | Wrf((Kx*(j-1)+1):(Kx*(j-1)+Kex))=(CircRandN(j/Nx*Ne,betaex,1,Ne,Kex)); 163 | % X pre, I post 164 | Wrf((Kex+1+(j-1)*Kx):(j*Kx))=(CircRandN(j/Nx*Ni+Ne,betaix,Ne+1,Ne+Ni,Kix)); 165 | end 166 | 167 | end 168 | -------------------------------------------------------------------------------- /raster2D_ani.m: -------------------------------------------------------------------------------- 1 | function [varargout]=raster2D_ani(s0,t0,t1,Ne1) 2 | % generate movie of spike rasters from 2D spatial network 3 | % s0: spike train data, s(1,:): spike times, s(2,:): neuron ID 4 | % t0: starting time of the movie 5 | % t1: end time 6 | % Ne1: # of neurons per dimension 7 | % varargout is a struct of frames 8 | 9 | dta=2; % bin size for raster animation 10 | timea=t0:dta:t1; % Timeframes 11 | % timea=dta:dta:T; % Timeframes 12 | % spkduration=1; % Duration of each spike in raster 13 | fig1=figure; 14 | set(gcf,'color','w') 15 | set(gcf,'position',[350 100 550 450]) 16 | % winsize = get(fig1,'Position'); 17 | % winsize(1:2) = [0 0]; 18 | numframes=numel(timea); 19 | % A=moviein(numframes,fig1,winsize); 20 | A(1:numframes) = struct('cdata', [],'colormap', []); 21 | for i=1:numframes 22 | 23 | % Find exc spikes in this time bin 24 | if(i==1) 25 | Is=find(s0(1,:)<=timea(i)& s0(1,:)>timea(i)-dta & s0(2,:)>0); 26 | if size(s0,1)==2 27 | x=ceil(s0(2,Is)/Ne1); 28 | y=mod(s0(2,Is)-1,Ne1)+1; 29 | else 30 | x=s0(2,Is); 31 | y=s0(3,Is); 32 | end 33 | if isempty(Is) 34 | x=[0];y=[0]; 35 | end 36 | h=plot(x,y,'k.','MarkerSize',5); % plot command 37 | set(h,'XDataSource','x'); 38 | set(h,'YDataSource','y'); 39 | axis([0 Ne1 0 Ne1]) 40 | xlabel('neuron location (X)','fontsize',18) 41 | ylabel('neuron location (Y)','fontsize',18) 42 | set(gca,'fontsize',15) 43 | set(gca,'xtick',[0 100 200]) 44 | set(gca,'ytick',[0 100 200]) 45 | else 46 | Is=find(s0(1,:)<=timea(i) & s0(1,:)>timea(i)-dta & s0(2,:)>0); 47 | end 48 | 49 | % Plot Raster 50 | if size(s0,1)==2 51 | x=ceil(s0(2,Is)/Ne1); 52 | y=mod(s0(2,Is)-1,Ne1)+1; 53 | pause(.1) 54 | else 55 | x=s0(2,Is); 56 | y=s0(3,Is); 57 | end 58 | 59 | refreshdata(h,'caller') 60 | drawnow 61 | 62 | title(sprintf('t=%d msec',round(timea(i))-t0)) 63 | A(i)=getframe(fig1); 64 | end 65 | if nargout==1 66 | varargout{1}=A; 67 | end -------------------------------------------------------------------------------- /spkcounts.m: -------------------------------------------------------------------------------- 1 | % run after Simulation_Fig4.m 2 | % testp.inI=[.2 .35]; 3 | % Inh='slow','fast' or 'broad'; 4 | % filename=strrep(sprintf('%sRF2D3layer_fixW_%sInh_Jex25_Jix15_inE0_inI%.03g_ID%.0f_dt0d01_nws1',... 5 | % data_folder,Inh,inI,trial),'.','d'); 6 | 7 | rng('shuffle'); 8 | 9 | %%%%%%%%%%%% for job array on cluster %%%%%%%%%%%%%%%% 10 | AI = getenv('PBS_ARRAYID'); 11 | job_dex = str2num(AI); 12 | seed_offset = randi(floor(intmax/10)); 13 | rng(job_dex + seed_offset); 14 | % job_dex range from 1 to Nnws 15 | Nnws=8; 16 | nws=job_dex; 17 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 18 | 19 | Inh='slow'; 20 | % Inh='fast'; 21 | % Inh='broad'; 22 | 23 | dim='2D'; 24 | testp.inE=[0]; 25 | testp.inI=[.2 .35]; 26 | Jx=25*[1;0.6]; 27 | dt=0.01; 28 | 29 | data_folder='data/'; 30 | 31 | Ntrial=15; 32 | Np=length(testp.inI); 33 | T=2e4; 34 | Tw=140; % window size 35 | Tburn=1000; 36 | Nt=floor((T-Tburn)/Tw); % # of trials 37 | T=Nt*Tw+Tburn; 38 | binedges=Tburn:Tw:T; 39 | Ne1=200; 40 | Nc=500; % sample size of neurons 41 | FR_th=2; %firing rate threshold for sampling (Hz) 42 | 43 | fnamesave=sprintf('%sRF2D3layer_fixW_%sInh_Jex%.03g_Jix%.03g_inI_dt0d01_Nc%d_spkcount_nws%d',... 44 | data_folder,Inh, Jx(1),Jx(2),Nc,nws); 45 | fnamesave=strrep(fnamesave,'.','d'), 46 | 47 | %%%%%%%%% compute rates %%%%%%%%%%%%% 48 | Ic2=1:Ne1^2; 49 | for pid=1:Np 50 | rate=zeros(1,Ne1^2); 51 | for trial=1:Ntrial 52 | inE=testp.inE(1); 53 | inI=testp.inI(pid); 54 | 55 | filename=strrep(sprintf('%sRF%s3layer_fixW_%sInh_Jex%.03g_Jix%.03g_inE%.03g_inI%.03g_ID%.0f_dt%.03g_nws%.03g',... 56 | data_folder,dim,Inh,Jx(1),Jx(2),inE,inI,trial,dt,nws),'.','d'), 57 | 58 | load(filename,'s2'); 59 | s2=s2(:,s2(1,:)>Tburn&s2(1,:)<=T&s2(2,:)<=Ne1^2); 60 | rate=rate+hist(s2(2,:),Ic2)/(T-Tburn)*1e3; 61 | end 62 | rate=rate/Ntrial; 63 | spkcount(pid).rate=rate; 64 | end 65 | idx=ones(1,Ne1^2); 66 | for pid=1:Np 67 | idx=idx.*(spkcount(pid).rate>FR_th); 68 | end 69 | Ic2=randsample(Ic2(idx>0),Nc); 70 | clear idx rate; 71 | save(fnamesave,'spkcount','Ic2') 72 | 73 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 74 | % load(fnamesave,'Ic2') 75 | 76 | Ic2=sort(Ic2); 77 | for pid=1:2 78 | spkcount(pid).Y=zeros(Nc, Nt*Ntrial); 79 | for trial=1:Ntrial 80 | inE=testp.inE(1); 81 | inI=testp.inI(pid); 82 | 83 | filename=strrep(sprintf('%sRF%s3layer_fixW_%sInh_Jex%.03g_Jix%.03g_inE%.03g_inI%.03g_ID%.0f_dt%.03g_nws%.03g',... 84 | data_folder,dim,Inh,Jx(1),Jx(2),inE,inI,trial,dt,nws),'.','d'), 85 | load(filename,'s2'); 86 | % compute spike counts using sliding window 87 | s2=s2(:,s2(1,:)>=Tburn&s2(1,:)<=T&s2(2,:)<=Ne1^2); 88 | s2(1,:)=s2(1,:)-Tburn; 89 | re2=spktime2count(s2,Ic2,Tw,floor((T-Tburn)/Tw),0); 90 | spkcount(pid).Y(:,(trial-1)*Nt+1:trial*Nt)=re2; 91 | end 92 | end 93 | save(fnamesave,'Tburn','T','Tw','spkcount','Ic2','testp') 94 | 95 | -------------------------------------------------------------------------------- /spktime2count.c: -------------------------------------------------------------------------------- 1 | /* Y=spktime2count(s,idx, Tw, Ncount,option) */ 2 | 3 | /* transform spike trains to spike counts 4 | Y is neuron # x trial # 5 | counts are non-overlapping 6 | option=1, if neuronIdx is continuous and sorted, 0 if not 7 | count from t=0; 8 | */ 9 | 10 | 11 | #include "mex.h" 12 | #include "math.h" 13 | #include "time.h" 14 | #include "matrix.h" 15 | 16 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 17 | { 18 | 19 | int i,j,k, ID,count, temp, Nid, m1,m2,Ns, Ncount,ID1,ID2,option; 20 | double *neuronIdx, *s; 21 | double Tw, T, *Pr,ts, *Y; 22 | 23 | /****** 24 | * Import variables from matlab 25 | * This is messy looking and is specific to mex. 26 | * Ignore if you're implementing this outside of mex. 27 | *******/ 28 | s = mxGetPr(prhs[0]); 29 | m1 = mxGetM(prhs[0]); 30 | Ns = mxGetN(prhs[0]); 31 | if(m1!=2){ 32 | mexErrMsgTxt("s should be 2xNs"); 33 | } 34 | 35 | neuronIdx = mxGetPr(prhs[1]); 36 | Nid = mxGetM(prhs[1]); 37 | m1 = mxGetN(prhs[1]); 38 | if(m1!=1){ 39 | temp=Nid; 40 | Nid=m1; 41 | m1=temp; 42 | } 43 | if(m1!=1){ 44 | mexErrMsgTxt("neuron id needs to be a vector or a row."); 45 | } 46 | 47 | Tw = mxGetScalar(prhs[2]); 48 | 49 | Ncount = (int)mxGetScalar(prhs[3]); 50 | 51 | option = (int)mxGetScalar(prhs[4]); /* 1, if neuronIdx is continuous and sorted, 0 if not */ 52 | if(option){ 53 | ID1=neuronIdx[0]; 54 | ID2=neuronIdx[Nid-1]; 55 | /* mexPrintf("ID1=%d,ID2=%d,option=%d",ID1,ID2,option); */ 56 | 57 | } 58 | 59 | 60 | /* Allocate output vector */ 61 | 62 | /* mexPrintf("Ns=%d, Ncount=%d, Nid=%d",Ns,Ncount,Nid); 63 | mexErrMsgTxt("stop"); */ 64 | 65 | plhs[0] = mxCreateDoubleMatrix(Nid, Ncount, mxREAL); 66 | Y=mxGetPr(plhs[0]); 67 | 68 | /* main codes */ 69 | 70 | for(i=0;iID1-0.1&ID