diff --git a/README.md b/README.md index a1d052e..2d8ad09 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,43 @@ -# CNELAB -Multi-channel reviewing Matlab GUI -Million thanks to BioSigPlot +#CNELab -Our official website (under constructing) -www.cnelab.org +Getting started with CNELab + +Getting started with CNELab is fairly easy. It only took a few minutes to complete this tutorial step by step. + +Preparations + +We recommend using the latest Matlab release version, currently R2016a. However, most features of CNELab should be backward compatible up to R2014a. Starting R2014b, Matlab updated on its graphic system. CNELab experienced a major performance drop (especially in plotting speed) in R2014b and R2015a. Thus, it is not recommended to use R2014b, R2015a or any version before R2014a. + +CNELab depends on several basic toolboxes of Matlab. Most of time they already come with your license. + +Signal Processing Toolbox. + +Statistics and Machine Learning Toolbox. +Wavelet Toolbox. +You can type ver in Matlab command window to verify. + +Install CNELab + +If do not have CNELab yet, please refer to our download page. Once you download the zip file, unzip it and put it anywhere you prefer. + +Change your current Matlab path to the root folder of CNELab, where you can see files such as cnelab.m and setup.m. + +Run setup.m by typing it in command window (ignore the prompt sign >>): + +>> setup +If you receive no error message, congratulations ! + +More on setup.m + +Although setup automatically removes existed CNELab from Matlab Path, it is always a good practice to manually delete the CNELab folder. + +setup will check if your java JVM version used in Matlab lands in 1 . 7 . * . Most of time you should not worry about it as Matlab shipped its version with specific JVM after R2013b. Type version -java to verify yourself. + +setup tries to recompile c++ mexfunctions in CNELab to your system environment. However, our release already contains compiled mexfunctions that can be immediately used in 64-bit of MacOS/Windows computer. Only if it is a unix or 32-bit system should you be careful. If you received a mex compile error, you would have to check your c++ compiler on maltab and manually compile them. Type mex -setup c++ to verify yourself. + +Start with demo + +The best way to learn CNELab is to use it: + +>> cnelab +Open $CNELAB_ROOT/demo/demo.cds to explore yourself. \ No newline at end of file diff --git a/db/cfg/defaultconfig.cfg b/db/cfg/defaultconfig.cfg index 20882ff..62e3e5a 100755 Binary files a/db/cfg/defaultconfig.cfg and b/db/cfg/defaultconfig.cfg differ diff --git a/lib/FDR/FDR.m b/lib/FDR/FDR.m new file mode 100644 index 0000000..6ca044c --- /dev/null +++ b/lib/FDR/FDR.m @@ -0,0 +1,21 @@ +function [pID,pN] = FDR(p,q) +% FORMAT pt = FDR(p,q) +% +% p - vector of p-values +% q - False Discovery Rate level +% +% pID - p-value threshold based on independence or positive dependence +% pN - Nonparametric p-value threshold +%______________________________________________________________________________ +% @(#)FDR.m 1.3 Tom Nichols 02/01/18 + +p = sort(p(:)); +V = length(p); +I = (1:V)'; + +cVID = 1; +cVN = sum(1./(1:V)); + +pID = p(max(find(p<=I/V*q/cVID))); +pN = p(max(find(p<=I/V*q/cVN))); + diff --git a/src/class/AverageMapWindow.m b/src/class/AverageMapWindow.m index 2f7d228..bb41444 100644 --- a/src/class/AverageMapWindow.m +++ b/src/class/AverageMapWindow.m @@ -74,7 +74,7 @@ peak_ contact_ unit - interp_method + interp_scatter_ extrap_method pos_t @@ -92,6 +92,9 @@ export_picture_win cmax + style_menu + map_interp_menu + map_scatter_menu end properties (Dependent=true) @@ -121,7 +124,7 @@ neg map_val - + interp_scatter end methods @@ -149,7 +152,7 @@ function varinitial(obj) obj.width=300; obj.height=300; obj.unit='dB'; - obj.interp_method='natural'; + obj.interp_scatter='interp'; obj.extrap_method='linear'; obj.interp_missing_=0; obj.symmetric_scale_=1; @@ -195,6 +198,9 @@ function buildfig(obj) obj.save_map_menu=uimenu(obj.save_menu,'label','Map','callback',@(src,evts) ExportMapCallback(obj)); + obj.style_menu=uimenu(obj.fig,'label','Style'); + obj.map_interp_menu=uimenu(obj.style_menu,'label','Interpolate','callback',@(src,evt) MapCallback(obj,src)); + obj.map_scatter_menu=uimenu(obj.style_menu,'label','Scatter','callback',@(src,evt) MapCallback(obj,src)); columnName={'Selected','FileName'}; columnFormat={'logical','char'}; columnEditable=[true,false]; @@ -309,7 +315,7 @@ function buildfig(obj) 'units','normalized','position',[0.5,0.25,0.45,0.25],'value',obj.peak,... 'callback',@(src,evts) PeakCallback(obj,src)); - obj.contact_radio=uicontrol('parent',hp_display,'style','radiobutton','string','Contact',... + obj.contact_radio=uicontrol('parent',hp_display,'style','radiobutton','string','Channel Name',... 'units','normalized','position',[0.5,0,0.45,0.25],'value',obj.contact,... 'callback',@(src,evts) ContactCallback(obj,src)); @@ -325,6 +331,7 @@ function buildfig(obj) obj.pos=obj.pos_; obj.neg=obj.neg_; + obj.interp_scatter=obj.interp_scatter_; end function OnClose(obj) @@ -388,6 +395,9 @@ function loadMap(obj) end len=length(obj.MapFiles); + if ischar(FileName) + FileName={FileName}; + end for i=1:length(FileName) obj.MapFiles_{len+i}=fullfile(FilePath,FileName{i}); end @@ -442,6 +452,7 @@ function ComputeCallback(obj) mv=obj.map_val; %************************************************************** vmax=-inf; + chanpos=obj.all_chan_pos(obj.chan_ind,:); for i=1:size(mv,2) %********************* if obj.interp_missing @@ -450,13 +461,25 @@ function ComputeCallback(obj) val=mv(:,i); end %********************* - spatialmap_grid(obj.SpatialMapFig(i),val,obj.interp_method,... - obj.extrap_method,map_channames,map_pos(:,1),map_pos(:,2),map_pos(:,3),obj.width,obj.height,... + spatialmap_grid(obj.SpatialMapFig(i),val,obj.interp_scatter,... + map_pos(:,1),map_pos(:,2),obj.width,obj.height,... obj.min_clim,obj.max_clim,obj.color_bar,obj.resize); h=findobj(obj.SpatialMapFig(i),'-regexp','tag','SpatialMapAxes'); - if obj.contact - plot_contact(h,allchanpos(:,1),allchanpos(:,2),allchanpos(:,3),obj.height,obj.width,[],... - ~ismember(allchanpos,map_pos,'rows'),[],[]); + + if obj.contact||strcmp(obj.interp_scatter,'scatter') + if obj.contact + cn=map_channames; + else + cn=[]; + end + + if strcmp(obj.interp_scatter,'scatter') + plot_contact(h,mapv,allchanpos(:,1),allchanpos(:,2),allchanpos(:,3),obj.height,obj.width,cn,... + ~ismember(allchanpos,chanpos,'rows'),[],[]); + else + plot_contact(h,[],allchanpos(:,1),allchanpos(:,2),allchanpos(:,3),obj.height,obj.width,cn,... + ~ismember(allchanpos,chanpos,'rows'),[],[]); + end end if obj.peak @@ -776,7 +799,7 @@ function deleteMap(obj) obj.height=round(obj.height/oldval*val); chanpos=obj.all_chan_pos(obj.chan_ind,:); - + allchanpos=obj.all_chan_pos; if ~NoSpatialMapFig(obj) for i=1:length(obj.SpatialMapFig) if ishandle(obj.SpatialMapFig(i)) @@ -786,9 +809,20 @@ function deleteMap(obj) if ~isempty(h) delete(findobj(h,'Tag','contact')); figure(obj.SpatialMapFig(i)) - if obj.contact - plot_contact(h,obj.all_chan_pos(:,1),obj.all_chan_pos(:,2),obj.all_chan_pos(:,3),obj.height,obj.width,[],... - ~ismember(obj.all_chan_pos,chanpos,'rows')); + if obj.contact||strcmp(obj.interp_scatter,'scatter') + if obj.contact + cn=obj.channames; + else + cn=[]; + end + + if strcmp(obj.interp_scatter,'scatter') + plot_contact(h,obj.map_val,allchanpos(:,1),allchanpos(:,2),allchanpos(:,3),obj.height,obj.width,cn,... + ~ismember(allchanpos,chanpos,'rows'),[],[]); + else + plot_contact(h,[],allchanpos(:,1),allchanpos(:,2),allchanpos(:,3),obj.height,obj.width,cn,... + ~ismember(allchanpos,chanpos,'rows'),[],[]); + end end end end @@ -829,7 +863,24 @@ function deleteMap(obj) set(obj.pos_slider,'enable','off'); end end + function val=get.interp_scatter(obj) + val=obj.interp_scatter_; + end + function set.interp_scatter(obj,val) + obj.interp_scatter_=val; + + if obj.valid + switch val + case 'interp' + set(obj.map_interp_menu,'checked','on'); + set(obj.map_scatter_menu,'checked','off'); + case 'scatter' + set(obj.map_scatter_menu,'checked','on'); + set(obj.map_interp_menu,'checked','off'); + end + end + end function val=get.neg(obj) val=obj.neg_; end @@ -971,11 +1022,11 @@ function ContactCallback(obj,src) for i=1:length(obj.SpatialMapFig) h=findobj(obj.SpatialMapFig(i),'-regexp','Tag','SpatialMapAxes'); if ~isempty(h) - delete(findobj(h,'Tag','contact')); figure(obj.SpatialMapFig(i)) + delete(findobj(h,'Tag','names')); if obj.contact - plot_contact(h,obj.all_chan_pos(:,1),obj.all_chan_pos(:,2),obj.all_chan_pos(:,3),obj.height,obj.width,[],... - ~ismember(obj.all_chan_pos,chanpos,'rows'),[],[]); + plot_contact(h,[],obj.all_chan_pos(:,1),obj.all_chan_pos(:,2),obj.all_chan_pos(:,3),obj.height,obj.width,obj.channames,... + ~ismember(obj.all_chan_pos,chanpos,'rows')); end end @@ -1099,10 +1150,10 @@ function UpdateFigure(obj,src) %********************* h=findobj(obj.SpatialMapFig(i),'-regexp','Tag','SpatialMapAxes'); if ~isempty(h) - if strcmpi(obj.interp_method,'natural') + if strcmpi(obj.interp_scatter,'natural') [x,y]=meshgrid((1:obj.width)/obj.width,(1:obj.height)/obj.height); - F= scatteredInterpolant(map_pos(:,1),map_pos(:,2),val,obj.interp_method,obj.extrap_method); + F= scatteredInterpolant(map_pos(:,1),map_pos(:,2),val,obj.interp_scatter,obj.extrap_method); mapvq=F(x,y); % mapvq = gaussInterpolant(col,row,mapv{i}',x,y); else @@ -1182,6 +1233,17 @@ function ExportMapCallback(obj) fclose(fid); end end + function MapCallback(obj,src) + switch src + case obj.map_interp_menu + obj.interp_scatter='interp'; + case obj.map_scatter_menu + obj.interp_scatter='scatter'; + end + + UpdateFigure(obj,src); + + end end end diff --git a/src/methods/plot_contact.m b/src/methods/plot_contact.m index 1e8aecb..50e7764 100644 --- a/src/methods/plot_contact.m +++ b/src/methods/plot_contact.m @@ -178,7 +178,7 @@ function plot_contact(axe,mapv,col,row,r,h,w,channames,varargin) offset=rotation_m*offset; for i=1:length(all_channames) if badchan(i) - c=[0.5,0.5,0.5]; + c=[1,1,1]; else c=[0,0,0]; end