% BDT: Biomet Database Tool % BDT opens the database interface tool which allows the user to plot % data from a database or save it data to file. % % BDT(figure_handle) applies BDT's capabilities to the figure specified % by the figure_handle. % % Author: Jeremiah Smith % Started: 12/1/06 % Last Edit: 6/3/08 % Version: 1.07 % Tested on: Matlab 7.4.0 (R2007a), 7.3 (R2006b), 7.2 (R2006a), 7.04; % Kubuntu 7.04 32-bit, Ubuntu 8.04 32-bit, Windows XP 32-bit/64-bit and % Windows Vista 32-bit, Mac OS X % Untested: Matlab <7.0 % Requirements: Matlab 7+ (untested on earlier versions) % Database Toolbox (for database related functions) % JDBC and/or ODBC drivers (for non-MS Access and MySQL % databases respectively) % Description: % Tool to load, analyze, and visualize data in ODBC databases. Funding % has been provided by the US Department of Energy USDOE-TCP % Grant #DE-FG02-03ER6384 (T.J. Griffis and J.M. Baker) and the National % Science Foundation Career Award, NSF-ATM-0546476 (T.J. Griffis). % % Possible Future Improvements: % Non-square selection polygons % Set Axis Bounds % % Known Issues: % Figures with hidden handles do not work yet % Context menus may not work after an operation. Left click will reset % the menu so the next right click will work. This is only an issue % on Linux/Mac OS X based systems. I do not currently understand why % this happens. function bdt(varargin) % Apply BDT to an existing figure if nargin == 1 if ~~ishandle(varargin{1}) T = fig_handle(varargin{1}); % Get figure handle % Error check if ~strcmp(get(T,'Type'),'figure') error('Cannot find the figure.') end cm_refresh(varargin{1},[]) set(varargin{1},'Closerequestfcn',{@fig_close},'WindowButtonDownFcn',{@Button_Down},'Interruptible','off'); set(varargin{1},'WindowButtonUpFcn',{@Button_Up}); figure(T) % Bring it forward return end end prefs('GUI') % Load preferences Un = get(0,'Units'); set(0,'Units','pixels') Pscreen = get(0,'ScreenSize'); set(0,'Units','characters') Cscreen = get(0,'ScreenSize'); FigPos = get(0,'DefaultFigurePosition'); screen = FigPos; screen([1 3]) = Cscreen(3)/Pscreen(3).*screen([1 3]); screen([2 4]) = Cscreen(4)/Pscreen(4).*screen([2 4]); set(0,'Units',Un) h = 1.769; % Height of buttons s = .35; % Spacing between buttons width = 166; height = 18.602+h+s; if nargin == 2 Pos = gui_position(varargin{1},width,height); % If called from an existing GUI else Pos = [screen(1)+screen(3)/2-width/2 screen(2)+screen(4)/2-height/2 width height]; % If called alone end %Main Window gui.main = figure('HandleVisibility','off',... 'IntegerHandle','off',... 'Menubar','none',... 'NumberTitle','off',... 'Name','Biomet Database Tool',... 'Tag','BDT',... 'Color',BGColor,... 'Units','characters',... 'Userdata','BDT_Dialog',... 'Position',Pos,... 'CloseRequestFcn',{@fig_close}); % Text gui.database_text = uicontrol(gui.main,'Style','text','HorizontalAlignment','left','FontSize',10,'String','Databases','Units','characters','BackgroundColor',BGColor,'Position',[2 16.952+h+s 15 1.385]); gui.tables_text = uicontrol(gui.main,'Style','text','HorizontalAlignment','left','FontSize',10,'String','Tables','Units','characters','BackgroundColor',BGColor,'Position',[35 16.952+h+s 15 1.385]); gui.xcolumns_text = uicontrol(gui.main,'Style','text','HorizontalAlignment','left','FontSize',10,'String','Data (x-axis)','Units','characters','BackgroundColor',BGColor,'Position',[68 16.952+h+s 22 1.385]); gui.ycolumns_text = uicontrol(gui.main,'Style','text','HorizontalAlignment','left','FontSize',10,'String','Data (y-axis)','Units','characters','BackgroundColor',BGColor,'Position',[101 16.952+h+s 22 1.385]); gui.saveto_text = uicontrol(gui.main,'Style','text','HorizontalAlignment','left','FontSize',8,'String','Save to:','Units','characters','BackgroundColor',BGColor,'Position',[134 3.4+h+s 8.5 1.154]); gui.Lsaveto_text = uicontrol(gui.main,'Style','text','HorizontalAlignment','left','FontSize',8,'String','Load from:','Units','characters','BackgroundColor',BGColor,'Position',[134 3.4 11 1.154]); % Listboxes gui.database_listbox = uicontrol(gui.main,'Style','listbox','FontSize',10,'BackgroundColor','white','String','No databases yet.','Units','characters','Position',[2 1 31 16.102+h+s]); gui.tables_listbox = uicontrol(gui.main,'Style','listbox','FontSize',10,'BackgroundColor','white','String','No tables yet.','Units','characters','Position',[35 1 31 16.102+h+s]); gui.xcolumns_listbox = uicontrol(gui.main,'Style','listbox','FontSize',10,'BackgroundColor','white','String','','Max',2,'Units','characters','Position',[68 1 31 16.102+h+s],'Value',[]); gui.ycolumns_listbox = uicontrol(gui.main,'Style','listbox','FontSize',10,'BackgroundColor','white','String','','Max',2,'Units','characters','Position',[101 1 31 16.102+h+s],'Value',[]); % Buttons Filt.Filters.String = []; % Initialize Filt.Filters.Eval = []; % Initialize gui.info_button = uicontrol(gui.main,'Style','push','Units','characters','String','Column Information','BackgroundColor',BGColor,'Position',[134 (1+7*s+7*h)+h+s 30 h]); gui.filters_button = uicontrol(gui.main,'Style','push','Units','characters','String','Filters','Userdata',Filt,'BackgroundColor',BGColor,'Position',[134 (1+6*s+6*h)+h+s 19 h]); gui.conditions_button = uicontrol(gui.main,'Style','push','Units','characters','String','Conditions','BackgroundColor',BGColor,'Position',[134 (1+5*s+5*h)+h+s 19 h]); gui.file_button = uicontrol(gui.main,'Style','push','FontSize',8,'Units','characters','String','File','BackgroundColor',BGColor,'Position',[143 (1+s+h)+h+s 7 h]); gui.workspace_button = uicontrol(gui.main,'Style','push','FontSize',8,'Units','characters','String','Workspace','BackgroundColor',BGColor,'Position',[150 (1+s+h)+h+s 14 h]); gui.Lfile_button = uicontrol(gui.main,'Style','push','FontSize',8,'Units','characters','String','File','BackgroundColor',BGColor,'Position',[144.5 (1+s+h) 5.5 h]); gui.Lworkspace_button = uicontrol(gui.main,'Style','push','FontSize',8,'Units','characters','String','Workspace','BackgroundColor',BGColor,'Position',[150 (1+s+h) 14 h]); gui.help_button = uicontrol(gui.main,'Style','push','Units','characters','String','Help','BackgroundColor',BGColor,'Position',[150 (1+3*s+3*h)+h+s 14 h],'Callback',{@bdt_help,gui.main}); gui.plot_button = uicontrol(gui.main,'Style','push','Units','characters','String','Plot','BackgroundColor',BGColor,'Position',[134 1 14.5 h]); gui.subplot_button = uicontrol(gui.main,'Style','push','Units','characters','String','Subplot','BackgroundColor',BGColor,'Position',[149.5 1 14.5 h]); % Checkboxes gui.filter_checkbox = uicontrol(gui.main,'Style','checkbox','Units','characters','String','Enable','BackgroundColor',BGColor,'Position',[154 (1+6*s+6*h)+h+s 12 h]); gui.conditions_checkbox = uicontrol(gui.main,'Style','checkbox','Units','characters','String','Enable','BackgroundColor',BGColor,'Position',[154 (1+5*s+5*h)+h+s 12 h]); gui.normalize_checkbox = uicontrol(gui.main,'Style','checkbox','Units','characters','String','Normalize','BackgroundColor',BGColor,'Position',[134 (1+4*s+4*h)+h+s 14 h]); gui.hold_checkbox = uicontrol(gui.main,'Style','checkbox','Units','characters','String','Hold Graph','BackgroundColor',BGColor,'Position',[150 (1+4*s+4*h)+h+s 16 h],'Value',1); gui.new_checkbox = uicontrol(gui.main,'Style','checkbox','Units','characters','String','New Figure','BackgroundColor',BGColor,'Position',[134 (1+3*s+3*h)+h+s 16 h],'Value',1); % Edit box gui.filename_edit = uicontrol(gui.main,'Style','edit','HorizontalAlignment','left','BackgroundColor','white','Units','characters','String','File_Name','Position',[134 (1+2*s+2*h)+h+s 30 h]); DB(gui); % Populate the Database listbox prefs('ORDER BY') set(gui.Lfile_button,'UserData',ord) % Set Callbacks set(cell2mat(struct2cell(gui)),'KeyPressFcn',{@BDT_Key,gui}) set(gui.xcolumns_listbox,'Callback',{@ColSel,gui}) set(gui.ycolumns_listbox,'Callback',{@ColSel,gui}) set(gui.database_listbox,'Callback',{@Tables,gui}) set(gui.tables_listbox,'Callback',{@Columns,gui}) set(gui.info_button,'Callback',{@ColInfo,gui}) set(gui.filters_button,'Callback',{@analyze,gui.main}) set(gui.conditions_button,'Callback',{@Conditions,gui}) set(gui.file_button,'Callback',{@SaveToFile,gui}) set(gui.workspace_button,'Callback',{@SaveToWork,gui}) set(gui.plot_button,'Callback',{@PlotData,gui}) set(gui.subplot_button,'Callback',{@SubplotData,gui}) set(gui.Lfile_button,'Callback',{@LoadData,gui}) set(gui.Lworkspace_button,'Callback',{@LoadWorkspace,gui}) % Set all GUI objects' Units to Normalized g = cell2mat(struct2cell(gui)); set(g,'Units','normalized') %% Preferences function prefs(varargin) % Import preferences into the caller function if nargin == 0 || nargin == 1 && ~~strcmp(varargin{1},'GUI') % Interface Background Color Possibilities % BGColor = [0 0 0]; % Black % BGColor = [1 1 1]; % White % BGColor = [1 0 0]; % Red % BGColor = [0 1 0]; % Green % BGColor = [0 0 1]; % Blue % BGColor = [1 0 1]; % Magenta % BGColor = [0 1 1]; % Cyan % BGColor = [1 1 0]; % Yellow % BGColor = [0 .5 .5]; % Turquoise % BGColor = [.6 .6 .6]; % Grey % BGColor = [1 .6 0]; % Blaze Orange % BGColor = [1 .6824 .2745]; % Light Orange % BGColor = [.2745 .5098 1]; % Light Blue % BGColor = [.5 0 1]; % Purple % BGColor = [1 .6 .6]; % Peach % BGColor = [.745 .8353 .9765]; % Microsoft Office Blue BGColor = get(0,'DefaultUicontrolBackgroundcolor'); % Default Color end if nargin == 0 || nargin == 1 && ~~strcmp(varargin{1},'JDBC Source') % Leave empty unless using the J_file = ''; % JDBC sources file location, include the file name end if nargin == 0 || nargin == 1 && ~~strcmp(varargin{1},'JDBC') % JDBC source information. Keep in mind that passwords stored here are % highly insecure. This is a plain text file and can be very easily % read. % Example % JDBC = {'Database' 'Driver' 'URL' 'Login' 'Password'; % 'my_data','com.mysql.jdbc.Driver','jdbc:mysql://127.0.0.1:3306/','my_login','Pa5sWerD'}; JDBC = {'Database' 'Driver' 'URL' 'Login' 'Password'; }; end if nargin == 0 || nargin == 1 && ~~strcmp(varargin{1},'DB') % List of databases to exclude from the databases list ex = {'Excel Files','dBASE Files','MS Access Database'}; % Meta Data suffixes metatrigger = 1; % 1 = show meta data (slower), 0 = don't show meta data (faster) meta = {'general','_notes','_info','_units'}; % Meta data table suffixes, must be a cell array end if nargin == 0 || nargin == 1 && ~~strcmp(varargin{1},'ORDER BY') % List of columns to order data by ord = {'DDOY','Time'}'; end if nargin == 0 || nargin == 1 && ~~strcmp(varargin{1},'precision') precC = 15; % dlmwrite precision, digits precN = 15; % num2str precision, digits end if nargin == 0 || nargin == 1 && ~~strcmp(varargin{1},'plot') % Plot Defaults Marker = 'none'; % Type of marker MarkerSize = 3; % Size of the markers MarkerEdgeColor = 'auto'; % Color of the marker's edge MarkerFaceColor = 'none'; % Color of the inside marker area LineStyle = '-'; % Type of line, 'none' for no line connecting points LineWidth = .5; % Width of the lines connecting points Color = 'blue'; % Color describing the color of the connecting lines % Blue Scatter Plot % Marker = '.'; % Type of marker % MarkerSize = 4; % Size of the markers, >= 5 = large, < 5 = small % MarkerEdgeColor = 'auto'; % Color of the marker's edge % MarkerFaceColor = 'none'; % Color of the inside marker area % LineStyle = 'none'; % Type of line, 'none' for no line connecting points % LineWidth = .5; % Width of the lines connecting points % Color = [0 0 1]; % Color vector describing the color of the connecting lines % Plot Color Orders ColorOrderWhite = [0 0 1;... % Blue 0 .5 0;... % Dark green 1 0 0;... % Red 0 .75 .75;... % Cyan .75 0 .75;... % Magenta .75 .75 0;... % Dark Yellow .25 .25 .25;... % Dark Grey -- End Default Colors 1 .6 0;... % Blaze Orange .21 .36 .64;... % Navy Blue .45 .92 .15;... % Lime Green .93 .84 .12;... % Orangish .4 .78 .48;... % Pastel Green .5 0 1]; % Purple ColorOrderBlack = [1 1 0;... % Yellow 1 0 1;... % Pink 0 1 1;... % Cyan 1 0 0;... % Red 0 1 0;... % Green 0 0 1;... % Blue .75 .75 .75;... % Light Grey -- End Default Colors .27 .98 .6;... % Pastel Green .14 .54 .93;... % Light Blue .5 0 1;... % Purple 1 .6 0;... % Blaze Orange 1 1 1;... % White .59 .89 .82;... % Blue Grey .59 .73 .84]; % Pastel Blue end if nargin == 0 || nargin == 1 && ~~strcmp(varargin{1},'plot_selection') % Plot Selection Defaults Marker = 'o'; % Type of marker MarkerSize = 4; % Size of the markers MarkerEdgeColor = 'auto'; % Color of the marker's edge MarkerFaceColor = 'none'; % Color of the inside marker area LineStyle = 'none'; % Type of line, 'none' for no line connecting points LineWidth = .5; % Width of the lines connecting points % Color = 'red'; % Supplying a color will override the existing color logic end % DO NOT EDIT ANYTHING BELOW THIS LINE % Get list of variables clear varargin temp = whos; list = []; for i=1:1:length(temp) list{i} = temp(i).name; end % Save list to caller function's workspace for i=1:1:length(temp) eval(['assignin(''caller'',''' list{i} ''',' list{i} ')']) end %% Populate DB Listbox function DB(gui) % Clean the database list of common database entries which cannot be % accessed including 'Excel Files', 'dBASE Files', and 'MS Access Database' prefs('DB') % Load preferences h = gui.database_listbox; if exist('getdatasources') == 2 || exist('getdatasources') == 5 list = getdatasources; if ~isnumeric(list) list = list'; else list = {}; end else list = {}; end % Add other sources listed in preferences prefs('JDBC') JDBC(1,:) = []; % Remove the first row JDBC_sources = JDBC(:,1);clear JDBC prefs('JDBC Source') if ~isempty(J_file) if exist(J_file,'file') == 2 load(J_file) JDBC_sources = [JDBC_sources;srcs(:,1)]; end end list = sort(unique([list;JDBC_sources])); % Remove ODBC.INI if it was created if ~~ispc Win = getenv('WINDIR'); % Get Windows directory CurDir = cd; % Get Current Directory if ~strcmp(Win,CurDir) if exist('ODBC.ini','file') == 2 delete('ODBC.INI') end end end f = ismember(list,ex); % Logical array of Matching values list(f) = []; % Remove values that are also found in the exclusion list if ~~ishandle(h) set(h,'String',sort(list),'Value',1,'ListboxTop',1) end % If there are no databases remove the Databases and Tables listboxes if ~~isempty(list) Resize_BDT(gui,1) end Info = get(gui.xcolumns_listbox,'UserData'); if ~~isempty(Info) Info.Login = ''; Info.Pass = ''; Info.DB = ''; Info.Table = ''; Info.DDOY = 0; Info.Col_List = []; Info.Data_List = []; Info.XList = []; Info.YList = []; Info.PrevX = []; Info.PrevY = []; else Info.Login = ''; Info.Pass = ''; Info.DB = ''; Info.Table = ''; Info.DDOY = 0; Info.Col_list = []; Info.XList = []; Info.YList = []; Info.PrevX = []; Info.PrevY = []; Info.Col_List = []; end set([gui.xcolumns_listbox gui.ycolumns_listbox],'String',Info.Data_List,'UserData',Info,'Value',[],'ListboxTop',1) set(gui.tables_listbox,'String','No tables yet.','UserData',Info,'Value',1,'ListboxTop',1) ListboxTop([gui.xcolumns_listbox gui.ycolumns_listbox]) % Error check %% Resize BDT function Resize_BDT(gui,varargin) % Resize BDT so it doesn't have the table and database lisboxes % gui = structure of BDT's handles % If there is no databases listed then do not resize it DB = get(gui.database_listbox,'String'); if ~~isempty(DB) && nargin == 1 return end g = cell2mat(struct2cell(gui)); set(g,'Units','characters'); Pos = get(gui.database_listbox,'Position'); if Pos(1) > 0 % 'Remove' the Database and Tables listboxes hs = Pos(1); % Horizontal spacing lbw = Pos(3); % Listbox width for i=2:1:length(g) Pos = get(g(i),'Position'); Pos(1) = Pos(1) - 2*hs - 2*lbw; % Remove two listbox widths and two horizontal spacings set(g(i),'Position',Pos) end Pos = get(gui.main,'Position'); Pos(1) = Pos(1)+hs+lbw; Pos(3) = Pos(3) - 2*hs - 2*lbw; else % 'Restore' the Database and Tables listboxes Pos = get(gui.xcolumns_listbox,'Position'); hs = Pos(1); % Horizontal spacing lbw = Pos(3); % Listbox width for i=2:1:length(g) Pos = get(g(i),'Position'); Pos(1) = Pos(1) + 2*hs + 2*lbw; % Remove two listbox widths and two horizontal spacings set(g(i),'Position',Pos) end Pos = get(gui.main,'Position'); Pos(1) = Pos(1)-hs-lbw; Pos(3) = Pos(3) + 2*hs + 2*lbw; end % Ensure it's on screen set(0,'Units','characters'); ScreenSize = get(0,'ScreenSize'); if Pos(1)+Pos(3) < 5 % Left Side Pos(1) = 0; end if Pos(1) > ScreenSize(3)-5 % Right Side Pos(1) = ScreenSize(3)-Pos(3); end if Pos(2) < 2-Pos(4) % Bottom Pos(2) = 3; end if Pos(2) > ScreenSize(4)-Pos(4)-2 % Top Pos(2) = ScreenSize(4)-Pos(4)-2; end set(0,'Units','pixels') set(gui.main,'Position',Pos) set(g,'Units','normalized') %% Populate Tables Listbox function Tables(h,eventdata,gui) V = get(h,'Value'); % Get the values of the tables selected S = get(h,'String'); % Get the list of databases LoginInfo = get(h,'Userdata'); if ~~isempty(S) if ~~ispc switch computer case 'PCWIN' winopen('C:\WINDOWS\system32\odbcad32.exe &') delete(gui.main) msgbox('No databases found. BDT will now close and the ODBC database setup tool will be brought up so databases can be setup.','No Databases') case 'PCWIN64' msgbox('64bit ODBC drivers for MS Access do not yet exist therefore 64bit Windows users must use JDBC drivers.','No Databases') end else msgbox(sprintf('No JDBC databases found.'),'Not Databases') end return end DB = S{V}; % Selected DB Prefs.Login = ''; Prefs.Pass = ''; err = 0; while err == 0 || err == 1 if err == 0 conn = connect(DB,Prefs.Login,Prefs.Pass); % Connect to database elseif err == 1 if ~isempty(LoginInfo) f = find(strcmp(LoginInfo(:,1),DB) == 1); else f = []; end if ~isempty(f) Prefs.Login = LoginInfo{f,2}; Prefs.Pass = LoginInfo{f,3}; conn = connect(DB,Prefs.Login,Prefs.Pass); % Connect to database else [Prefs.Login Prefs.Pass] = logindlg('Title','Database Login'); if ~~isnumeric(Prefs.Login) return end conn = connect(DB,Prefs.Login,Prefs.Pass); % Connect to database if ~~isempty(conn.Message) % Check to see if the connection works LoginInfo = [LoginInfo;{DB Prefs.Login Prefs.Pass}]; set(h,'Userdata',LoginInfo) % Save login info end end end err = db_error(conn.Message); % Error check if err == -1 return end if err == 2 dbmeta = dmd(conn); t = tables(dbmeta, 'cata'); % Get tables in database close(conn); end end sys = ismember(t,'SYSTEM TABLE'); % Find the system tables in the DB f = find(sys == 1); r = size(sys,1); t(f-r,:) = []; % Remove system tables t = t(:,1); % Remove the table type column; Prefs.DB = DB; t = metatables(t); % Remove meta tables from the list Info = get(gui.xcolumns_listbox,'UserData'); Info.Login = Prefs.Login; Info.Pass = Prefs.Pass; Info.DB = Prefs.DB; Info.Col_List = []; Info.XList = []; Info.YList = []; Info.Table = []; Info.DDOY = []; set(gui.tables_listbox,'String',t,'Userdata',Info,'Value',1) % Populate the tables listbox set(gui.xcolumns_listbox,'String',Info.Data_List,'Userdata',Info,'Value',[]) set(gui.ycolumns_listbox,'String',Info.Data_List,'Userdata',Info,'Value',[]) ListboxTop([gui.tables_listbox gui.xcolumns_listbox gui.ycolumns_listbox]) %% Populate Columns Listbox function Columns(h,eventdata,gui) Prefs = get(gui.xcolumns_listbox,'Userdata'); if ~isempty(Prefs) V = get(h,'Value'); % Get the values of the tables selected S = get(h,'String'); % Get the list of databases if ~~isempty(S) return elseif ~~strcmp(S,'No tables yet.') return end Table = S{V}; % Selected DB conn = connect(Prefs.DB,Prefs.Login,Prefs.Pass); SQL = ['SELECT * FROM `' Table '`']; curs = exec(conn,SQL); curs = fetch(curs,1); if ~isempty(curs.Message) colnames = ''; else colnames = columnnames(curs); % Get column names from cursor close(conn); % Close connection eval(['colnames = {' colnames '}'';']) % Reorganize column names end % Determine if DDOY exists prefs('ORDER BY') f = find(ismember(ord,colnames),1,'first'); if ~isempty(f) Prefs.DDOY = ord{f}; else Prefs.DDOY = 0; end Prefs.Table = Table; Prefs.PrevX = []; Prefs.PrevY = []; Prefs.XList = []; Prefs.YList = []; Prefs.Col_List = colnames; set(gui.xcolumns_listbox,'String',[colnames';Prefs.Data_List],'Userdata',Prefs,'Value',[]) set(gui.ycolumns_listbox,'String',[colnames';Prefs.Data_List],'Userdata',Prefs,'Value',[]) ListboxTop([gui.xcolumns_listbox gui.ycolumns_listbox]) % Error check end %% Column Selection function ColSel(h,eventdata,gui) Prefs = get(gui.xcolumns_listbox,'Userdata'); if ~isempty(Prefs) V = get(h,'Value'); switch h case gui.xcolumns_listbox Add = setdiff(V,Prefs.XList); % Added columns Remove = setdiff(Prefs.XList,V); % Removed columns Prefs.PrevX = Prefs.XList; XList = Prefs.XList; YList = Prefs.YList; % Add XList = [XList Add]; % Remove if ~isempty(Remove) f = ismember(XList,Remove); % Find the values to remove XList(f) = []; % Remove them from XList if length(f) > length(YList) YList(f(1:length(YList))) = []; % Remove them from YList elseif length(f) <= length(YList) YList(f) = []; % Remove them from YList end % If there has been a change, update it if length(YList) ~= length(Prefs.YList) set(gui.ycolumns_listbox,'Value',sort(unique(YList))) ListboxTop(gui.ycolumns_listbox) % Error check uicontrol(gui.xcolumns_listbox); % Return focus to the X listbox else if YList ~= Prefs.YList set(gui.ycolumns_listbox,'Value',sort(unique(YList))) ListboxTop(gui.ycolumns_listbox) % Error check uicontrol(gui.xcolumns_listbox); % Return focus to the X listbox end end end Prefs.XList = XList; Prefs.YList = YList; case gui.ycolumns_listbox Add = setdiff(V,Prefs.YList); % Added columns Remove = setdiff(Prefs.YList,V); % Removed columns Prefs.PrevY = Prefs.YList; XList = Prefs.XList; YList = Prefs.YList; % Add if ~isempty(Add) YList = [YList Add]; % Add to YList if ~isempty(XList) if length(YList) > length(XList) XList = [XList XList(end)*ones(1,length(YList)-length(XList))]; end end end % Remove if ~isempty(Remove) f = ismember(YList,Remove); YList(f) = []; % Remove columns if ~isempty(XList) XList(f) = []; % Remove columns end if length(XList) ~= length(Prefs.XList) Prefs.PrevX = Prefs.XList; Prefs.XList = XList; set(gui.xcolumns_listbox,'Value',sort(unique(XList))) ListboxTop(gui.xcolumns_listbox) % Error check else if sort(unique(XList)) ~= sort(unique(Prefs.XList)) Prefs.PrevX = Prefs.XList; Prefs.XList = XList; set(gui.xcolumns_listbox,'Value',sort(unique(XList))) ListboxTop(gui.xcolumns_listbox) % Error check end end end Prefs.XList = XList; Prefs.YList = YList; end % Save Prefs set([gui.xcolumns_listbox gui.ycolumns_listbox],'Userdata',Prefs) ListboxTop([gui.xcolumns_listbox gui.ycolumns_listbox]) % Error check end %% Column Information function ColInfo(h,eventdata,gui) Prefs = get(gui.xcolumns_listbox,'Userdata'); if ~isempty(Prefs.Col_List) || ~isempty(Prefs.Data_List) col = UnCol(gui); % Get list of unique selected columns [junk f junk] = intersect(col,Prefs.Col_List); junk = col(sort(f)); Dcol = setxor(col,junk); % Non-database columns col = junk; % Database columns clear junk % Get the first row of every column if ~isempty(col) DBPrefs = setdbprefs; setdbprefs('DataReturnFormat','cellarray'); SQL = ['SELECT ' SQLCol(col) ' FROM `' Prefs.Table '`']; conn = connect(Prefs.DB,Prefs.Login,Prefs.Pass); curs = exec(conn,SQL); curs = fetch(curs,1); Data = curs.Data; if ~~isempty(col) return end SQL = ['SELECT COUNT(`' col{1} '`) FROM `' Prefs.Table '`']; % Get the number of rows curs = exec(conn,SQL); curs = fetch(curs); Rows = curs.Data; Types = []; if ~~iscell(Data) for i=1:1:length(Data) temp = Data{i}; w = whos('temp'); switch w.class case 'char' Types = [Types;{[col{i} ': Text']}]; case 'double' Types = [Types;{[col{i} ': Numeric']}]; otherwise Types = [Types;{[col{i} ': Unknown']}]; end end else w = whos('Data'); switch w.class case 'char' Types = [Types;{[col{1} ': Text']}]; case 'double' Types = [Types;{[col{1} ': Numeric']}]; otherwise Types = [Types;{[col{1} ': Unknown']}]; end end Info = [{[num2str(Rows{1}) ' rows in each column'];'';['Database: ' Prefs.DB];['Table: ' Prefs.Table];'';'------- Database Data Types -------'};Types]; else Info = []; end % Non-database data types if ~isempty(Dcol) Data = get(gui.help_button,'UserData'); % Load Data [junk f junk] = intersect(Prefs.Data_List,Dcol); Types = []; for i=1:1:length(Dcol) temp = Data{f(i)}; w = whos(['temp']); switch w.class case 'char' Types = [Types;{[Dcol{i} ': Text (' num2str(size(Data{i},1)) ' x ' num2str(size(Data{i},2)) ')']}]; case 'double' Types = [Types;{[Dcol{i} ': Numeric (' num2str(size(Data{i},1)) ' x ' num2str(size(Data{i},2)) ')']}]; otherwise Types = [Types;{[Dcol{i} ': Unknown (' num2str(size(Data{i},1)) ' x ' num2str(size(Data{i},2)) ')']}]; end end Info = [Info;' ';'------- Non-database Data Types -------';Types]; end if ~isempty(col) met = metatables(Prefs.DB,Prefs.Table,Prefs.Login,Prefs.Pass); % Get meta data tables MetData = {' ';' ';'--------- Meta Data ---------'}; % Check for a General Table if ~~any(ismember(met,'General')) met(end) = []; % Remove the General Table SQL = 'SELECT General FROM General'; curs = exec(conn,SQL); if ~~isempty(curs.Message) curs = fetch(curs); MetData = [MetData;curs.Data]; end end % Get information from the General column in the correct meta table for i=1:1:length(met) SQL = ['SELECT General FROM `' met{i} '`']; curs = exec(conn,SQL); if ~~isempty(curs.Message) curs = fetch(curs); MetData = [MetData;' ';'General---';curs.Data]; end end % Get information from the columns selected if ~isempty(met) for i=1:1:length(col) SQL = ['SELECT `' col{i} '` FROM `' met{1} '`']; curs = exec(conn,SQL); if ~~isempty(curs.Message) curs = fetch(curs); MetData = [MetData;' ';[col{i} '---'];curs.Data]; end end end close(conn); setdbprefs('DataReturnFormat',DBPrefs.DataReturnFormat) % Restore previous return type if length(MetData) > 3 % If there is any metadata f = ismember(MetData,'null'); MetData(f) = []; % Remove nulls Info = [Info;MetData]; end end prefs('GUI') % Load Preferences Pos = gui_position(gui.main,50,20); % Display the Info gui.info = figure('HandleVisibility','off',... 'IntegerHandle','off',... 'Menubar','none',... 'NumberTitle','off',... 'Name','BDT: Column Information',... 'Tag','BDT',... 'Units','characters',... 'Color',BGColor,... 'Userdata','BDT_Dialog',... 'Position',Pos); gui.listbox = uicontrol(gui.info,'Style','listbox','Units','normalized','BackgroundColor',BGColor,'String',Info,'UserData',Info,'Max',2,'Position',[0 0 1 1],'Value',[]); set(gui.info,'ResizeFCN',{@curve_fit_resize,gui.listbox}) curve_fit_resize(gui.info,[],gui.listbox) % Size the contents of the window else errordlg('You must first select a database and table.','Error') end %% Save Data to ... function [XData YData VList DVList Trigger ND col] = SaveTo(gui,F,Prefs) % gui = structure of handles from main GUI % F = file/variable name to save the data to % XData = x data % YData = y data % VList = list of index values of the database data selected % DVList = list of index values of the non-database data selected % Trigger = 0 for no non-database data, 1 for non-database data % ND = non-database data % Load Data [XData YData XCol YCol YN NPlots Prefs EString XSource YSource] = CommonPlot(gui,Prefs); clear YN NPlots EString % Separate unmatched pairs LX = length(XData); LY = length(YData); if LX > LY YData2 = {}; XData2 = XData(LY+1:end); XData(LY+1:end) = []; else YData2 = YData(LX+1:end); YData(LX+1:end) = []; XData2 = {}; end clear LX LY % Load Filter Data Filters = get(gui.filters_button,'UserData'); if ~isfield(Filters,'Commands') Filters.Commands = []; end if ~isfield(Filters,'Others') Filters.Others = []; end if ~isfield(Filters,'Axes_List') Filters.Axes_List = []; end Ev = Filters.Commands; % Evaluation cell array list = evalin('base','who'); list = [list list]; % Get Other Plots/Variables if ~isempty(Filters.Others) for i=1:1:size(Filters.Others,1) if ~~isnumeric(Filters.Others{i,2}) if length(Filters.Others{i,1}) >= 3 list = [list;[strtrim(Filters.Others{i,1}(1:3)) Filters.Others(i,2)]]; % Remove X and Y variable origins (Y1 = DDOY to Y1) else list = [list;Filters.Others(i,:)]; end end end end % Update Handles if ~isempty(Filters.Axes_List) axs = cell2mat(Filters.Axes_List(:,2)); else axs = []; end figs = []; for i=1:1:length(axs) figs(i) = fig_handle(axs(i)); end figs = unique(figs); % List of unique figures for i=1:1:size(list,1) if ~~isnumeric(list{i,2}) list{i,2} = update_handles(list{i,2},figs); % Update handles end end emp = []; % Initialize empty array for i=1:1:size(list,1) if ~~isempty(list{i,2}) emp = [emp;i]; end end list(emp,:) = []; % Remove rows clear emp axs % Apply Filters for i=1:1:size(Ev,1) % Iterate over the Execution Queue % Execute 'Filters' if ~~strcmp(Ev{i,2},'filter') for k=1:1:length(XData) try Filt = Filters; [XData{k} YData{k} Filt] = analyze_eval(XData{k},YData{k},Filt,Ev{i},[]); catch temp = lasterror; errordlg(temp.message,temp.identifier) end end elseif ~~strcmp(Ev{i,2},'command') % Execute commands % Check for workspace variables for j=1:1:size(list,1) % Iterate over the variable list if exist(list{j,1},'var') ~= 1 % Only if the variable doesnt' currently exist in the workspace f = findstr(Ev{i}{1},list{j,1}); % Search for the current variable for k=1:1:length(f) if exist(list{j,1},'var') ~= 1 load = 1; % Load toggle, 0 = don't load, 1 = load into workspace % Check character before if f(k) >= 2 temp = double(lower(Ev{i}{1}(f(k)-1))); % Convert the letter to its numeric equivalent if temp >= 97 && temp <= 122 || temp == 95 % If the preceding character is a letter or _ load = 0; % The found variable name is part of a larger variable name end end % Check character after if f(k) + length(list{j,1})+1 <= length(Ev{i}{1}) temp = double(lower(Ev{i}{1}(f(k)+length(list{j,1})))); % Convert the letter to its numeric equivalent if temp >=97 && temp <= 122 || temp >= 48 && temp <= 57 || temp == 95 load = 0; % The found variable name is part of a larger variable name end % Structure case if temp == 46 if f(k) + length(list{j,1})+2 >= length(Ev{i}{1}{1}) temp = double(lower(Ev{i}{1}(f(k)+length(list{j,1})+1))); % Convert the letter to its numeric equivalent if temp < 97 || temp > 122 % Not a valid field if the first character isn't a letter load = 0; end else load = 0; end end end % Load if load == 1 if ~isnumeric(list{j,2}) eval([list{j,1} ' = evalin(''base'',list{j,1});']) % Load variable from workspace else if ~~ishandle(list{j,2}) if ~~strcmp(list{j,1}(1),'X') eval([list{j,1} ' = get(list{j,2},''XData'');']) % Load X data from plot else eval([list{j,1} ' = get(list{j,2},''YData'');']) % Load Y data from plot end end end end end end end end % Evaluate Function try eval(Ev{i}{1}) catch % Error Catch temp = lasterror; errordlg({temp.message;'';'Failed to execute:';Ev{i}{1}},temp.identifier) end end end % Recombine Data XData = [XData;XData2]; YData = [YData;YData2]; clear XData2 YData2 % Prep Outputs col = [Prefs.Col_List;Prefs.Data_List]; VList = Prefs.YList(Prefs.YList <= length(Prefs.Col_List)); DVList = Prefs.YList(Prefs.YList > length(Prefs.Col_List)) - length(Prefs.Col_List); ND = get(gui.help_button,'UserData'); % Non-database data if ~isempty(DVList) Trigger = 1; else Trigger = 0; end %% Save to File function SaveToFile(h,eventdata,gui) % h = handle of Save to File button % eventdata = unused % gui = structure of handles from main GUI Prefs = get(gui.xcolumns_listbox,'Userdata'); prefs('precision') if ~~isempty(Prefs.XList) && ~~isempty(Prefs.YList) errordlg('You must first select data.','Error') return end % Filename F = get(gui.filename_edit,'String'); % Filename from edit box f = findstr(F,'.'); % Determine if there is an extension mat = 0; if ~~isempty(f) F = [F '.dat']; % Add an extension if there is none else if length(F) > 4 if ~~strcmp(F(end-3:end),'.mat') mat = 1; end end end [XData YData VList DVList Trigger ND col] = SaveTo(gui,F,Prefs); % Execute common save to code % Reformat data for text output V = []; Data = {}; for i=1:1:max([length(YData) length(XData)]) % Shuffle XData and YData into one cell array if i <= length(XData) Data = [Data;XData(i)]; V = [V;Prefs.XList(i)]; end if i <= length(YData) Data = [Data;YData(i)]; V = [V;Prefs.YList(i)]; end end clear XData YData % Check for dimension mismatch EString = []; for i=2:1:length(Data) if length(Data{i}) ~= length(Data{1}) EString = [EString '\n' col{V(i)} ' (' num2str(size(Data{i},1)) 'x' num2str(size(Data{i},2)) ')']; end end if ~isempty(EString) EString = ['Dimension mismatch:\n\n' col{V(1)} ' (' num2str(size(Data{1},1)) 'x' num2str(size(Data{1},2)) ')' EString]; errordlg(sprintf(EString),'Error') return end % .mat case if mat == 1 Columns = col(V); save(F,'Data','Columns') % Notify User S = get(gui.filename_edit,'String'); set(gui.filename_edit,'String','File Write Successful.','BackgroundColor','green') pause(1) set(gui.filename_edit,'String',S,'BackgroundColor','white') return end % Save Header Data = Data'; try Source = []; Trigger2 = 0; if length(find(V <= length(Prefs.Col_List))) == length(V) % All database sources Source = ['"' Prefs.DB ' > ' Prefs.Table '"']; elseif length(find(V > length(Prefs.Col_List))) == length(V) % All non-database sources if ~any(abs(strcmp(ND(V,2),ND{V(1),2})-1)) % All the same non-database sources Source = ND{V(1),2}; else Trigger2 = 1; end else Trigger2 = 1; end % Mixed sources case if ~~Trigger2 for i=1:1:length(Prefs.XList) if Prefs.XList(i) <= length(Prefs.Col_List) Source = [Source '"' Prefs.DB ' > ' Prefs.Table '",']; else Source = [Source '"' ND{Prefs.XList(i)-length(Prefs.Col_List),2} '",']; end if Prefs.YList(i) <= length(Prefs.Col_List) Source = [Source '"' Prefs.DB ' > ' Prefs.Table '",']; else Source = [Source '"' ND{Prefs.YList(i)-length(Prefs.Col_List),2} '",']; end end end dlmwrite(F,['Generated on ' datestr(now,'mmmm dd, yyyy at HH:MM:SS')],'Delimiter','','Newline','PC'); dlmwrite(F,Source(1:end-1),'-append','Delimiter','','Newline','PC'); dlmwrite(F,SQLCol(col(V)),'-append','Delimiter','','NewLine','PC'); % Append Data c = length(Data); % Number of columns r = length(Data{1}); % Number of rows Ch = 0; % Character trigger for i=1:1:c if ~~iscell(Data{i}) if ~~ischar(Data{i}{1}) Ch = 1; % There is a cell with characters, cannot use dlmwrite end else if ~~ischar(Data{i}(1)) Ch = 1; % There is a cell with characters, cannot use dlmwrite end end end if Ch == 0 Data = cell2mat(Data); % Convert data to a numeric array dlmwrite(F,Data,'-append','Delimiter',',','NewLine','PC','Precision',precC); else fid = fopen(F,'a'); % Open the file for appending for i=1:1:r line = []; for j=1:1:c if ~iscell(Data{j}) line = [line ',' num2str(Data{j}(i),precN)]; elseif ~~iscell(Data{j}) && ~~strcmp(Data{j}{i}(1),'"') && ~~strcmp(Data{j}{i}(end),'"') line = [line ',' Data{j}{i}]; elseif ~~iscell(Data{j}) && ~strcmp(Data{j}{i}(1),'"') && ~strcmp(Data{j}{i}(end),'"') line = [line ',"' Data{j}{i} '"']; end end fwrite(fid,[line(2:end) char(13) char(10)]); % 13 and 10 together yield a new line in Windows end fclose(fid); end % Notify User S = get(gui.filename_edit,'String'); set(gui.filename_edit,'String','File Write Successful.','BackgroundColor','green') pause(1) set(gui.filename_edit,'String',S,'BackgroundColor','white') catch S = get(gui.filename_edit,'String'); set(gui.filename_edit,'String','Error Writing File.','BackgroundColor','red') pause(1) set(gui.filename_edit,'String',S,'BackgroundColor','white') if ~~exist('fig','var') fclose(fid); end delete(F) % Delete the file if there is an error end %% Save All function SaveAll(h,evetndata,gui) % Save all plots on a specific graph/figure % Temporary % Filename F = get(gui.filename_edit,'String'); % Filename from edit box f = findstr(F,'.'); % Determine if there is an extension mat = 0; if ~~isempty(f) F = [F '.dat']; % Add an extension if there is none else if length(F) > 4 if ~~strcmp(F(end-3:end),'.mat') mat = 1; end end end %% Save to Workspace function SaveToWork(h,eventdata,gui) Prefs = get(gui.xcolumns_listbox,'Userdata'); F = get(gui.filename_edit,'String'); if ~~isempty(Prefs.XList) && ~~isempty(Prefs.YList) errordlg('You must first select data.','Error') return end [XData YData VList DVList Trigger ND col] = SaveTo(gui,F,Prefs); % Execute common save to code % Recombine X and Y data V = []; Data = {}; for i=1:1:max([length(YData) length(XData)]) % Shuffle XData and YData into one cell array if i <= length(XData) Data = [Data;XData(i)]; V = [V;Prefs.XList(i)]; end if i <= length(YData) Data = [Data;YData(i)]; V = [V;Prefs.YList(i)]; end end clear XData YData DVList Prefs VList Trigger eventdata h i ND % If all columns are numeric convert it to a numeric array typ = zeros(length(Data),1); % Data type leng = typ; % Data length for i=1:1:length(Data) typ(i) = isnumeric(Data{i}); leng(i) = length(Data{i}); end if ~~isempty(setxor(typ,1)) && ~~isempty(setxor(leng/max(leng),1)) Data = cell2mat(Data'); end % Save to Workspace try % Output data assignin('base',[F '_columns'],col(V)) assignin('base',F,Data) % Notify User S = get(gui.filename_edit,'String'); set(gui.filename_edit,'String','Variable Write Successful.','BackgroundColor','green') pause(1) set(gui.filename_edit,'String',S,'BackgroundColor','white') catch errordlg('Unable to save variable to workspace. Ensure the name entered is a proper variable name.','Error') end %% Unique Columns function [col DDOY] = UnCol(gui) % Get the list of unique columns from the two column listboxes Prefs = get(gui.xcolumns_listbox,'UserData'); col = [Prefs.Col_List;Prefs.Data_List]; V1 = get(gui.xcolumns_listbox,'Value'); V2 = get(gui.ycolumns_listbox,'Value'); % Check for DDOY f = find(ismember(col,'DDOY'),1); if ~isempty(f) DDOY = 1; end V = sort(unique([V1 V2])); col = col(V); % Unique list of properly ordered columns %% SQL Column List function S = SQLCol(col) % List of columns properly formatted for an SQL statement if ~isempty(col) if ~iscell(col) S = ['`' col '`']; else S = ['`' col{1} '`']; end for i=2:1:length(col) S = [S ',`' col{i} '`']; end else S = []; end %% Plot function PlotData(h,eventdata,gui) Prefs = get(gui.xcolumns_listbox,'Userdata'); NFig = get(gui.new_checkbox,'Value'); % New Figure checkbox value if ~isempty(Prefs) [XData YData XCol YCol YN NPlots Prefs EString XSource YSource] = CommonPlot(gui,Prefs); % Load variables common to both plotting functions if ~~isempty(XData) if ~isempty(EString) errordlg(EString,'Error') end return end % Plot V = get(gui.hold_checkbox,'Value'); % Determine if hold is active if V == 1 Held = 'Add'; for i=1:1:NPlots YData{i} = YData{i}./YN(i); % Normalize the Y component end if NFig == 1 fig = figure; ax = axes; hold(ax,'on') old_graph = 0; % Not an old graph else CFig = get(0,'CurrentFigure'); if ~~isempty(CFig) fig = figure; ax = axes; hold(ax,'on') old_graph = 0; % Not an old graph else old_graph = 1; % Using an old graph fig = CFig; figure(fig) % Bring it forward ax = get(fig,'CurrentAxes'); % Handle of current axes if ~~isempty(ax) ax = axes; % Create a new axis if there is none else NextPlot = get(ax,'NextPlot'); if ~~strcmp(NextPlot,'replace') answer = questdlg('Warning: Hold is currently off of the current axis. Would you like to Add to the current axis contents, Replace the current axis contents, or Cancel?','Continue?','Add','Replace','Cancel','Add'); switch answer case 'Add' Held = 'replace'; hold(ax,'on') xlabel(ax,'') ylabel(ax,'') set(fig,'Name','','NumberTitle','on') case 'Replace' Held = 'replace'; case 'Cancel' return end end end end end prefs('plot') % Load plot preferences % Color Selection C = get(ax,'Color'); if sum(C) >= 1.5 ColorOrder = ColorOrderWhite; else ColorOrder = ColorOrderBlack; end if length(YData) > length(ColorOrder) n = ceil(length(YData)/length(ColorOrder)); % Determine number of times to replicate color order ColorOrder = repmat(ColorOrder,n,1); % Repeat the color array enough times so that there will be a color for every plot end clear ColorOrderWhite ColorOrderBlack n for i=1:1:length(XData) P(i) = plot(ax,XData{i},YData{i},'Marker',Marker,... 'MarkerSize',MarkerSize,'LineStyle',LineStyle,'LineWidth',... LineWidth,'MarkerFaceColor',MarkerFaceColor,'MarkerEdgeColor',... MarkerEdgeColor,'Color',ColorOrder(i,:),'Visible','off'); % Plot all of the data at once end switch Held case 'replace' hold(ax,'off') case 'Add' hold(ax,'on') end for i=1:1:NPlots Info.DB = Prefs.DB; % Source Database Info.Table = Prefs.Table; % Source Table if ~~strcmp(XSource{i},'Database') && exist(XSource{i},'file') ~= 2 Info.XDB = Prefs.DB; % X Source Database else Info.XDB = XSource{i}; % X Source end if i <= length(XCol) Info.XAxis = XCol{i}; % Source of X axis data else Info.XAxis = []; end if ~~strcmp(YSource{i},'Database') && exist(YSource{i},'file') ~= 2 Info.YDB = Prefs.DB; % X Source Database else Info.YDB = YSource{i}; % X Source end Info.YAxis = YCol{i}; % Source of Y axis data Info.Norm = YN(i); % Normalization factor Info.Indices = []; % Selected Indices Info.SHandle = []; % Handle of selection plot Info.Login = Prefs.Login; % Save Login Info.Pass = Prefs.Pass; % Save password Info.PastHandles = P(i); % Start past handles list set(P(i),'Userdata',Info) end label_check(gca) % Update axis labels cm(fig,gca) cm_refresh(fig,[]) set(fig,'Closerequestfcn',{@fig_close},'WindowButtonDownFcn',{@Button_Down},'Interruptible','off'); set(fig,'WindowButtonUpFcn',{@Button_Up}); else for i=1:1:NPlots fig = figure; prefs('plot') % Load plot preferences P(i) = plot(XData{i},YData{i}./YN(i),'Color',Color,'Marker',Marker,... 'MarkerSize',MarkerSize,'LineStyle',LineStyle,'LineWidth',... LineWidth,'MarkerFaceColor',MarkerFaceColor,'MarkerEdgeColor',... MarkerEdgeColor,'Visible','off'); if i <= length(XCol) set(fig,'Name',[XCol{i} ' vs ' YCol{i}],'Numbertitle','off') Info.XAxis = XCol{i}; % Source of X axis data XCol{i}(XCol{i} == '_') = ' '; xlabel(XCol{i}) else set(fig,'Name',[YCol{i}],'Numbertitle','off') Info.XAxis = []; % No X Source end Info.YAxis = YCol{i}; % Source of Y axis data YCol{i}(YCol{i} == '_') = ' '; ylabel(YCol{i}) if ~~strcmp(XSource{i},'Database') Info.DB = Prefs.DB; % Source Database Info.Table = Prefs.Table; % Source Table else Info.DB = XSource{i}; % Source file/workspace Info.Table = ''; % Not from a database end if ~~strcmp(XSource{i},'Database') && exist(XSource{i},'file') ~= 2 Info.XDB = Prefs.DB; % X Source Database else Info.XDB = XSource{i}; % X Source end if i <= length(XCol) Info.XAxis = XCol{i}; % Source of X axis data else Info.XAxis = []; end if ~~strcmp(YSource{i},'Database') && exist(YSource{i},'file') ~= 2 Info.YDB = Prefs.DB; % X Source Database else Info.YDB = YSource{i}; % X Source end Info.Norm = YN(i); % Normalization factor Info.Indices = []; % Selected Indices Info.SHandle = []; % Handle of selection plot Info.Login = Prefs.Login; % Save Login Info.Pass = Prefs.Pass; % Save password Info.PastHandles = P; % Start past handles list set(P(i),'Userdata',Info) cm(fig,gca) cm_refresh(fig,[]) label_check(gca) % Update axis labels set(fig,'Closerequestfcn',{@fig_close},'WindowButtonDownFcn',{@Button_Down},'Interruptible','off'); set(fig,'WindowButtonUpFcn',{@Button_Up}); end end % Apply Filters Filt = get(gui.filters_button,'UserData'); % Load filter/command information if get(gui.filter_checkbox,'Value') == 1 && ~~isfield(Filt,'Commands') active = []; for i=1:1:length(P) active = [active;{['X' num2str(i)] P(i)};{['Y' num2str(i)] P(i)}]; end active2 = analyze_exec(Filt.Commands,active,Filt.Others,Filt.Axes_List,fig,Filt); for i=1:2:size(active2,1) eval(['X = ' active2{i,1} ';clear ' active2{i,1}]) eval(['Y = ' active2{i+1,1} ';clear ' active2{i+1,1}]) P = get(active2{i,2}); % Get all plot data P.UserData.Filters.String = []; % Erase command list, they were just run P.UserData.Filters.Eval = []; if length(X) == length(Y) set(active2{i+1,2},'YData',Y,'UserData',P.UserData) else errordlg([active2{i,1} ' dimensions to not agree with ' active2{i+1,1} '. Plot not replotted.'],'Dimension Error') set(active2{i,2},'UserData',P.UserData) end end end if exist('active2','var') == 1 set(cell2mat(active2(:,2)),'Visible','on') else set(P,'Visible','on') end % Display Plot Errors if ~isempty(EString) errordlg(EString,'Failed Plots') end else errordlg('You must first select a database and table.','Error'); end %% Mouse Button Down function Button_Down(h,eventdata) FData = get(h,'Userdata'); % Figure's Userdata cm_refresh(h,[]) switch get(h,'selectiontype') case 'alt' return otherwise rbbox end % Find all axes axs = Ax_Handles(h); % Get axis handles pos = get(axs,'Position'); % Get Positions relative to each graph pos = get(axs,'CurrentPoint'); if ~~iscell(pos) pos = cell2mat(pos); % Convert from cell array to numeric array end pos = pos(1:2:end,1:2); % Crop out bad points % Save Data FData.Pos1 = pos; % First box corner FData.Axs = axs; % Axes handles set(h,'Userdata',FData) % Save %% Mouse Button Up function Button_Up(h,eventdata) temp = copymove_plots([],[]); if ~~temp return end FData = get(h,'Userdata'); % Figure's Userdata PArea = .5; % Area around point selection (cm) % Selection Type Information ext = 0; switch get(h,'selectiontype') case 'alt' return case 'extend' ext = 1; % Sentinel value for extended click end % Get Positions relative to each graph pos = get(FData.Axs,'CurrentPoint'); if ~~iscell(pos) pos = cell2mat(pos); % Convert from cell array to numeric array end pos = pos(1:2:end,1:2); % Crop out bad points % Get Axes Limits FData.XLim = get(FData.Axs,'XLim'); if ~~iscell(FData.XLim) FData.XLim = cell2mat(FData.XLim); end FData.YLim = get(FData.Axs,'YLim'); if ~~iscell(FData.YLim) FData.YLim = cell2mat(FData.YLim); end % Save Data FData.Pos2 = pos; % Second box corner set(h,'Userdata',FData) % Save % Calculate Bounds per Axes b = []; s = 0; for i=1:1:length(FData.Axs) % X Bounds if (FData.Pos1(i,1) < FData.XLim(i,1) && FData.Pos2(i,1) < FData.XLim(i,1)) || (FData.Pos1(i,1) > FData.XLim(i,2) && FData.Pos2(i,1) > FData.XLim(i,2)) s = 1; % Sentinel value end % Y Bounds if (FData.Pos1(i,2) < FData.YLim(i,1) && FData.Pos2(i,2) < FData.YLim(i,1)) || (FData.Pos1(i,2) > FData.YLim(i,2) && FData.Pos2(i,2) > FData.YLim(i,2)) s = 1; % Sentinel value end if s == 0 % X Bounds XMin = min([FData.Pos1(i,1) FData.Pos2(i,1)]); XMax = max([FData.Pos1(i,1) FData.Pos2(i,1)]); if XMin < FData.XLim(i,1) XLower = FData.XLim(i,1); else XLower = XMin; end if XMax > FData.XLim(i,2) XUpper = FData.XLim(i,2); else XUpper = XMax; end % Y Bounds YMin = min([FData.Pos1(i,2) FData.Pos2(i,2)]); YMax = max([FData.Pos1(i,2) FData.Pos2(i,2)]); if YMin < FData.YLim(i,1) YLower = FData.YLim(i,1); else YLower = YMin; end if YMax > FData.YLim(i,2) YUpper = FData.YLim(i,2); else YUpper = YMax; end b = [b;{[XLower XUpper YLower YUpper]}]; else b = [b;{[]}]; % If none of the bounds enclose the given axis end s = 0; % Reset sentinel value end FData.Box = b; % Save the bounds % Plot Selection for i=1:1:length(FData.Axs) P = Plot_Handles(FData.Axs(i)); % Get all plot handles Held = get(FData.Axs(i),'NextPlot'); hold(FData.Axs(i),'on') for j=1:1:length(P) PData = get(P(j),'Userdata'); if ~~isempty(PData) PData.Norm = 1; PData.Indices = []; PData.SHandle = []; end % Delete All Previous Selection Data if not shift-click if ~~ishandle(PData.SHandle) delete(PData.SHandle) end PData.SHandle = []; if ext == 0 PData.Indices = []; end % Load Plot Data X = get(P(j),'XData'); Y = get(P(j),'YData'); if ~isempty(FData.Box{i}) if FData.Box{i}(1) == FData.Box{i}(2) || FData.Box{i}(3) == FData.Box{i}(4) % SINGLE POINT SELECTION set(FData.Axs(i),'Units','centimeters') Position = get(FData.Axs(i),'Position'); % Get the size in centimeters set(FData.Axs(i),'Units','normalized') XRate = (abs(FData.XLim(i,2)-FData.XLim(i,1)))/Position(3); YRate = (abs(FData.YLim(i,2)-FData.YLim(i,1)))/Position(4); dx = XRate*PArea/2; dy = YRate*PArea/2; % Find points within the area FX = find(X >= FData.Box{i}(1)-dx & X <= FData.Box{i}(1)+dx); FY = find(Y >= FData.Box{i}(3)-dy & Y <= FData.Box{i}(3)+dy); F = intersect(FX,FY); clear FX FY % Find data point closest to clicked point if ~isempty(F) D = sqrt((X(F(1))-FData.Box{i}(1))^2+(Y(F(1))-FData.Box{i}(3))^2); loc = F(1); % Location in the found index of the closest point for k=2:1:length(F) D_temp = sqrt((X(F(k))-FData.Box{i}(1))^2+(Y(F(k))-FData.Box{i}(3))^2); if D_temp < D D = D_temp; loc = F(k); end end F = loc; else F = []; end else % Find Indices of Selected Data FX = find(X >= min(FData.Box{i}(1:2)) & X <= max(FData.Box{i}(1:2))); FY = find(Y >= min(FData.Box{i}(3:4)) & Y <= max(FData.Box{i}(3:4))); F = intersect(FX,FY); clear FX FY end else F = []; end % Get Plot Color Color = get(P(j),'Color'); Color = abs(Color-.3); % Combine Previous Selection Plot and Current Selection Plot PData.Indices = unique([PData.Indices F]); % Check Visibility Vis = get(P(j),'Visible'); if ~~ischar(Vis) if ~strcmp(Vis,'on') Vis = 0; else Vis = 1; end end if Vis == 1 % Plot Selection prefs('plot_selection') % Load selection plot preferences PData.SHandle = plot(FData.Axs(i),X(PData.Indices),Y(PData.Indices),'LineStyle',LineStyle,'Marker',Marker,'MarkerSize',MarkerSize,'Color',Color,'MarkerFaceColor',MarkerFaceColor,'MarkerEdgeColor',MarkerEdgeColor); set(PData.SHandle,'Tag','selection'); if ~isempty(PData.SHandle) PostPlot(P(j),PData.SHandle) end % Save Data to Plot's Userdata set(P(j),'Userdata',PData) PostPlot_DisplayUpdate(P(j)) % Update each Data window end end if ~~strcmp(Held,'replace') hold(FData.Axs(i),'off') end end % Update the Related Data List if ~~isfield(FData,'Related') if ~~ishandle(FData.Related) RelatedData_Update(h) end end %% Context Menu function cm(fig,ax) % ax = axis for contextmenu to be applied to % fig = figure handle of the current window F.context = uicontextmenu('Parent',fig); % Figure context menu F.analyse = uimenu(F.context,'Label','Analyze','Callback',{@analyze,fig}); F.search = uimenu(F.context,'Label','Search Plots','Callback',{@search_plot,fig}); F.invert = uimenu(F.context,'Label','Invert Selection','Callback',{@invert,fig}); F.info = uimenu(F.context,'Label','Plot Info','Callback',{@cm_info,[]}); F.legend = uimenu(F.context,'Label','Legend','Callback',{@cm_legend,fig}); F.duplicate = uimenu(F.context,'Label','Duplicate Graph','Callback',{@cm_duplicate,fig}); F.copy = uimenu(F.context,'Label','Copy Plots','Callback',{@copymove_plots}); F.move = uimenu(F.context,'Label','Move Plots','Callback',{@copymove_plots}); F.quick = uimenu(F.context,'Label','Quick Options'); F.publish = uimenu(F.quick,'Label','Publication','Callback',{@cm_publication,fig}); F.default_white = uimenu(F.quick,'Label','Default White','Callback',{@cm_default,fig,'white'}); F.default_black = uimenu(F.quick,'Label','Default Black','Callback',{@cm_default,fig,'black'}); F.ExportData = uimenu(F.context,'Label','Export All Data','Callback',{@save_all}); F.help = uimenu(F.context,'Label','Help','Callback',{@bdt_help,fig}); F.exit = uimenu(F.context,'Label','Exit BDT','Callback',{@exit_bdt,fig}); gui.context = uicontextmenu('Parent',fig); % Axes context menu gui.delete = uimenu(gui.context,'Label','Delete Points','Callback',{@cm_delete_points}); gui.analyze = uimenu(gui.context,'Label','Analyze','Callback',{@analyze,fig}); gui.info = uimenu(gui.context,'Label','Plot Info','Callback',{@cm_info,[]}); gui.plottools = uimenu(gui.context,'Label','Plot Tools'); gui.search = uimenu(gui.plottools,'Label','Search Plots','Callback',{@search_plot,ax}); gui.normalize = uimenu(gui.plottools,'Label','Normalize','Callback',{@cm_normalize,[]}); gui.legend = uimenu(gui.plottools,'Label','Legend','Callback',{@cm_legend,ax}); gui.display = uimenu(gui.plottools,'Label','Display Data','Callback',{@PostPlot_Display,ax}); gui.invert = uimenu(gui.plottools,'Label','Invert Selection','Callback',{@invert,ax}); gui.copy = uimenu(gui.plottools,'Label','Copy Plots','Callback',{@copymove_plots}); gui.move = uimenu(gui.plottools,'Label','Move Plots','Callback',{@copymove_plots}); gui.duplicate = uimenu(gui.plottools,'Label','Duplicate Graph','Callback',{@cm_duplicate,fig}); gui.clear = uimenu(gui.plottools,'Label','Clear Axes','Callback',{@cm_clear}); gui.tools = uimenu(gui.context,'Label','Database Tools'); gui.related = uimenu(gui.tools,'Label','Related Data','Callback',{@PostPlot_Related}); gui.BDT = uimenu(gui.tools,'Label','Biomet Database Tool','Callback',{@bdt}); gui.axis = uimenu(gui.context,'Label','Axis Properties'); gui.color = uimenu(gui.axis,'Label','Color'); gui.black = uimenu(gui.color,'Label','Black','Tag','Color','Callback',{@cm_ax_prop,ax}); gui.white = uimenu(gui.color,'Label','White','Tag','Color','Callback',{@cm_ax_prop,ax}); gui.clear = uimenu(gui.color,'Label','None','Tag','Color','Callback',{@cm_ax_prop,ax}); gui.grid = uimenu(gui.axis,'Label','Grid','Callback',{@cm_grid,ax}); gui.box = uimenu(gui.axis,'Label','Box','Callback',{@cm_box,ax}); gui.xscale = uimenu(gui.axis,'Label','X Scale'); gui.xscale_log = uimenu(gui.xscale,'Label','log','Tag','XScale','Callback',{@cm_ax_prop,ax}); gui.xscale_lin = uimenu(gui.xscale,'Label','linear','Tag','XScale','Callback',{@cm_ax_prop,ax}); gui.yscale = uimenu(gui.axis,'Label','Y Scale'); gui.yscale_log = uimenu(gui.yscale,'Label','log','Tag','YScale','Callback',{@cm_ax_prop,ax}); gui.yscale_lin = uimenu(gui.yscale,'Label','linear','Tag','YScale','Callback',{@cm_ax_prop,ax}); gui.font = uimenu(gui.axis,'Label','Font'); font_list = listfonts; % Get the list of available fonts for i=1:15:length(font_list)-1 gui.(['fontset' num2str(floor(i/15+1))]) = uimenu(gui.font,'Label',['Font Set ' num2str(floor(i/15+1))]); for j=1:1:15 if i+j-1 <= length(font_list) gui.(['font' num2str(i+j-1)]) = uimenu(gui.(['fontset' num2str(floor(i/15+1))]),'Label',font_list{i+j-1},'Tag','FontName','Callback',{@cm_ax_prop,ax}); end end end gui.fontsize = uimenu(gui.axis,'Label','Font Size'); sizes = [8 9 10 10.5 11 12:2:26]'; % List of sizes for i=1:1:length(sizes) gui.(['fontsize' num2str(i)]) = uimenu(gui.fontsize,'Label',num2str(sizes(i)),'Tag','FontSize','Callback',{@cm_ax_prop,ax}); end gui.fontweight = uimenu(gui.axis,'Label','Font Weight'); gui.light = uimenu(gui.fontweight,'Label','light','Tag','FontWeight','Callback',{@cm_ax_prop,ax}); gui.normal = uimenu(gui.fontweight,'Label','normal','Tag','FontWeight','Callback',{@cm_ax_prop,ax}); gui.demi = uimenu(gui.fontweight,'Label','demi','Tag','FontWeight','Callback',{@cm_ax_prop,ax}); gui.bold = uimenu(gui.fontweight,'Label','bold','Tag','FontWeight','Callback',{@cm_ax_prop,ax}); gui.fontangle = uimenu(gui.axis,'Label','Font Angle'); gui.normal = uimenu(gui.fontangle,'Label','normal','Tag','FontAngle','Callback',{@cm_ax_prop,ax}); gui.italic = uimenu(gui.fontangle,'Label','italic','Tag','FontAngle','Callback',{@cm_ax_prop,ax}); gui.oblique = uimenu(gui.fontangle,'Label','oblique','Tag','FontAngle','Callback',{@cm_ax_prop,ax}); gui.ExportData = uimenu(gui.context,'Label','Export All Data','Callback',{@save_all}); gui.help = uimenu(gui.context,'Label','Help','Callback',{@bdt_help,fig}); gui.exit = uimenu(gui.context,'Label','Exit BDT','Callback',{@exit_bdt,fig}); set(ax,'UIContextMenu',gui.context) set(fig,'UIContextMenu',F.context) %% Context Menu: Invert Selection function invert(h,eventdata,h2) % Invert the selection of the graph % h = handle of menu entry % eventdata = unused % h2 = handle of figure, axis, or plot handle % Get the correct plot handles switch get(h2,'Type') case 'figure' p = Plot_Handles(Ax_Handles(h2)); case 'axes' p = Plot_Handles(h2); case 'line' p = h2; end clear h eventdata h2 % Invert each selection for i=1:1:length(p) X = get(p(i),'XData'); Y = get(p(i),'YData'); PData = get(p(i),'UserData'); if ~~ishandle(PData.SHandle) I = (1:1:length(X))'; % Create an index I(PData.Indices) = []; % Remove old indices PData.Indices = I; % Save new indices % Get Plot Color Color = get(p(i),'Color'); Color = abs(Color-.3); % Plot the new selection prefs('plot_selection') % Load selection plot preferences delete(PData.SHandle) % Remove old selection PData.SHandle = plot(get(p(i),'Parent'),X(I),Y(I),'LineStyle',LineStyle,'Marker',Marker,'MarkerSize',MarkerSize,'Color',Color,'MarkerFaceColor',MarkerFaceColor,'MarkerEdgeColor',MarkerEdgeColor,'Tag','selection'); set(p(i),'UserData',PData) PostPlot_DisplayUpdate(p(i)) % Update each Data window PostPlot(p(i),PData.SHandle) end end %% Context Menu: Box function cm_box(h,evendata,ax) % Toggle the box on the axis % h = context menu entry handle % eventdata = unused % ax = axis handle box(ax) %% Context Menu: Quick Options (Publication) function cm_publication(h,eventdata,fig) % Set the figure properties to publication properties % h = context menu entry handle % eventdata = unused % fig = figure handle ax = Ax_Handles(fig); set(fig,'Color','white') % Figure background color set(ax,'FontName','Arial','Color','none','YColor','Black','XColor','Black') % Font style and axis color set(findobj(fig,'Type','text'),'Color','black') XL = get(ax,'XLabel'); % X Label handle YL = get(ax,'YLabel'); % Y Label handle if ~~iscell(XL) XL = cell2mat(XL); YL = cell2mat(YL); end set(XL,'Color','black') set(YL,'Color','black') for i=1:1:length(ax) box(ax(i),'on') end %% Context Menu: Quick Options (Default) function cm_default(h,evendata,fig,C) % Set the figure properties to properties % h = context menu entry handle % eventdata = unused % fig = figure handle ax = Ax_Handles(fig); if ~~strcmp(C,'white') C2 = [.8 .8 .8]; C3 = 'black'; colordef white else C2 = [.2 .2 .2]; C3 = 'white'; colordef black end set(fig,'Color',C2) set(ax,'Color',C,'FontName','Helvetica','YColor',C3,'XColor',C3) XL = get(ax,'XLabel'); % X Label handle YL = get(ax,'YLabel'); % Y Label handle if ~~iscell(XL) XL = cell2mat(XL); YL = cell2mat(YL); end set(XL,'Color',C3) set(YL,'Color',C3) % All Text T = findobj(fig,'Type','text'); set(T,'Color',C3) %% Context Menu: Legend function varargout = cm_legend(h,eventdata,ax) % Create a legend for an axis based on the existing plots % h = handle of context menu entry % evendata = unused % ax = axis handle or figure handle if ~~strcmp(get(ax,'Type'),'figure') ax = Ax_Handles(ax); % Get handles of all axes on the figure end L = []; for i=1:1:length(ax) legend(ax(i),'off') % Turn off any existing legend p = Plot_Handles(ax(i)); % Get all the plot handles on the axis if ~isempty(p) pdata = get(p,'UserData'); if ~iscell(pdata) pdata = {pdata}; end list = []; % Initalize for j=1:1:length(pdata) if ~~isstruct(pdata{j}) if ~~isfield(pdata{j},'YAxis') f = findstr(pdata{j}.YAxis,'_'); % Find all underscores pdata{j}.YAxis(f) = ' '; % Replace all underscores with spaces list = [list;{pdata{j}.YAxis}]; end else list = [list;{''}]; % There is no data for this plot end end L = legend(ax(i),list,'Location','best'); box(L,'off') % Turn off the legend's box else legend(ax(i),'off') end end if ~~isempty(h) varargout{1} = L; else varargout = []; end %% Context Menu: Axis Property function cm_ax_prop(h,eventdata,ax) % Generic axis property function Prop = get(h,'Tag'); Val = get(h,'Label'); switch Prop case 'FontSize' Val = str2num(Val); end set(ax,Prop,Val); %% Context Menu: Grid Toggle function cm_grid(h,eventdata,ax) % Toggle the grid grid(ax) %% Context Menu: Command Line (keypress) function cm_command_keypress(h,eventdata,execute) % If tab is pressed, move the selection to the execute button % h = edit box handle % evendata = unused % execute = handle of next object to make focus fig = fig_handle(h); % Figure handle key = get(fig,'CurrentKey'); % Last key pressed pause(.1) if ~~strcmp(key,'tab') % Remove all tabs S = get(h,'String'); % Get the current listbox text temp = []; if ~iscell(S) for i=1:1:size(S,1) temp{i} = S(i,:); end S = temp'; clear temp end % Remove tabs for i=1:1:length(S) f = findstr(S{i},char(9)); S{i}(f) = []; end % Update command edit box set(h,'String',S) uicontrol(execute) % Switch focus to the execute button end %% Context Menu: Clear function cm_clear(h,eventdata) % Clear the current axes of all plots and labels ui = get(h,'Parent'); % Handle of Context Menu fig = get(ui,'Parent'); % Figure handle ax = findobj(fig,'UIContextMenu',ui); % Handle of axes cla(ax) xlabel(ax,'') ylabel(ax,'') title(ax,'') legend(ax,'off') set(fig,'NumberTitle','off','Name','') %% Context Menu: Duplicate Figure function cm_duplicate(h,eventdata,fig) Pos = get(fig,'Position'); % Get current figure position Pos(1) = Pos(1) + 40; Pos(2) = Pos(2) - 40; Ax = Ax_Handles(fig); % Get axis handles Color = get(fig,'Color'); % Prepare Legend Data leg = findobj(fig,'Tag','legend'); % Legends if ~isempty(leg) temp = get(leg,'UserData'); if ~iscell(temp) temp = {temp}; end leg_parents = []; for i=1:1:length(temp) leg_parents(i) = temp{i}.PlotHandle; end else leg_parents = []; end % Create a new figure fig2 = figure; set(fig2,'Position',Pos,'Color',Color) % Copy Each Axis and then copy all the plots on it for i=1:1:length(Ax) Pos = get(Ax(i),'Position'); Ax2(i) = copyobj(Ax(i),fig2); f = ismember(leg_parents,Ax(i)); f = leg(f); % Previous legend's handle if ~isempty(f) % If the recently copied axis is the parent of a legend L = cm_legend([],[],Ax2(i)); % Create a legend on it Pos = get(f,'Position'); % Get the previous legend's position set(L,'Position',Pos) % Set the same position for the new legend end end % Update Plot and Axis handles s = findobj(fig2,'Tag','selection'); % Find all selection plots delete(s) % Remove all selection plots, their handles cannot be properly updated p = Plot_Handles(fig2); % Find all other plot handles PData = get(p,'Userdata'); % Plot Data if ~iscell(PData) PData = {PData}; end for i=1:1:length(p) PData{i}.SHandle = []; PData{i}.Indices = []; PData{i}.Norm = 1; set(p(i),'Userdata',PData{i}) PostPlot(p(i),p(i)) end Ax2 = setdiff(Ax2,findobj(fig2,'Tag','legend')); % Remove legends from axis list for i=1:1:length(Ax2) cm(fig2,Ax2(i)) end % Update Figure's Userdata FData = get(fig,'Userdata'); FData.Related = []; FData.Info = []; set(fig2,'Userdata',FData) % Button Up and Down function callbacks set(fig2,'Closerequestfcn',{@fig_close},'WindowButtonDownFcn',{@Button_Down},'Interruptible','off'); set(fig2,'WindowButtonUpFcn',{@Button_Up}); %% Context Menu: Delete Points function cm_delete_points(h,eventdata) fig = fig_handle(h); % Get figure handle P = Plot_Handles(fig); % Get plot handles P_final = []; % Delete old graphs and replot without deleted points for i=1:1:length(P) PData = get(P(i),'Userdata'); % Plot Data Vis = get(P(i),'Visible'); if ~~strcmp(Vis,'on') % If the plot is visible if ~isempty(PData.Indices) % If a part of the plot is selected delete(PData.SHandle) % Delete old selection plot PData.SHandle = []; % Plot Properties ax = get(P(i),'Parent'); % Axis the plot was originally plotted on Color = get(P(i),'Color'); LineStyle = get(P(i),'LineStyle'); LineWidth = get(P(i),'LineWidth'); Marker = get(P(i),'Marker'); MarkerSize = get(P(i),'MarkerSize'); MarkerFaceColor = get(P(i),'MarkerFaceColor'); MarkerEdgeColor = get(P(i),'MarkerEdgeColor'); % Replot after cropping X = get(P(i),'XData'); % Get X Data Y = get(P(i),'YData'); % Get Y Data Y(PData.Indices) = NaN; % 'Erase' Data PData.Indices = []; % Clear Indices delete(P(i)) % Delete old plot Held = get(ax,'NextPlot'); hold(ax,'on') P_temp = plot(ax,X,Y,'Color',Color,'LineStyle',LineStyle,... 'LineWidth',LineWidth,'Marker',Marker,'MarkerFaceColor',... MarkerFaceColor,'MarkerEdgeColor',MarkerEdgeColor,... 'MarkerSize',MarkerSize); PostPlot(P_temp,P_temp) if ~strcmp(Held,'add') hold(ax,'off') end PData.PastHandles = [PData.PastHandles;P_temp]; % Add current handle to list of previous handles set(P_temp,'Userdata',PData) % Save plot data PostPlot_DisplayRep(P_temp) % Repopulate Data window P_final = [P_final;P_temp]; else P_final = [P_final;P(i)]; end else P_final = [P_final;P(i)]; end end cm_Update(fig,P,P_final,h) % Update Plot Info Handles %% Context Menu: Plot Information function cm_info(h,eventdata,Pos) % Create or, if Pos is not empty, recreate the Plot Info window % h = handle of context menu entry % eventdata = unused % Pos = position of previous Plot Info window Graph = fig_handle(h); % Get figure handle cm_refresh(Graph,[]); % Update menus and handles Info = get(Graph,'Userdata'); % Figure information axs = Ax_Handles(Graph); % Get axes' handles p = Plot_Handles(axs); % Get plot handles % Check for existing Plot Info Window if ~~isempty(Pos) if ~isempty(Info) if ~~isstruct(Info) if ~~isfield(Info,'Info') if ~~ishandle(Info.Info) figure(Info.Info) return end end end end end if ~~isempty(p) return end % Figure Position H = 1.538; % Height of elements s = .4; % Spacing b = .3; % Vertical offset if ~isempty(Pos) if ~~ishandle(Info.Info) delete(Info.Info) end Pos(3:4) = [135,length(p)*H+s*(length(p)-1)+2*b]; else Pos = gui_position(Graph,135,length(p)*H+s*(length(p)-1)+2*b); end % Creat GUI prefs('GUI') % Load preferences fig.main = figure('HandleVisibility','off',... 'IntegerHandle','off',... 'Menubar','none',... 'NumberTitle','off',... 'Name','BDT: Plot Information',... 'Tag','BDT',... 'Units','characters',... 'Userdata','BDT_Dialog',... 'Color',BGColor,... 'Position',Pos); x = []; for i=1:1:length(p) Color = get(p(i),'Color'); V = strcmp(get(p(i),'Visible'),'on'); Info = get(p(i),'Userdata'); % Check if ~~isempty(Info) Info.XAxis = 'Unknown'; Info.YAxis = 'Unknown'; Info.DB = 'Unknown'; end if ~isfield(Info,'XAxis') Info.XAxis = 'Unknown'; end if ~isfield(Info,'YAxis') Info.YAxis = 'Unknown'; end if ~isfield(Info,'DB') Info.DB = 'Unknown'; end % x(1) = uicontrol(fig.main,'Style','text','FontSize',10,'HorizontalAlignment','left','Units','characters','String','','BackgroundColor',Color,'Position',[2 (b+s*(i-1)+H*(i-1)) 7 H],'Userdata',p(i),'Tag','Color'); x(1) = plot_sample(fig.main,p(i),[2 (b+s*(i-1)+H*(i-1)) 13 H]); set(x(1),'Userdata',p(i)) x(2) = uicontrol(fig.main,'Style','text','FontSize',10,'HorizontalAlignment','center','Units','characters','String',Info.XAxis,'BackgroundColor',BGColor,'Position',[16 (b+s*(i-1)+H*(i-1)) 20 H],'Userdata',p(i)); x(3) = uicontrol(fig.main,'Style','text','FontSize',10,'HorizontalAlignment','center','Units','characters','String',Info.YAxis,'BackgroundColor',BGColor,'Position',[37 (b+s*(i-1)+H*(i-1)) 20 H],'Userdata',p(i)); x(4) = uicontrol(fig.main,'Style','text','FontSize',10,'HorizontalAlignment','center','Units','characters','String',Info.DB,'BackgroundColor',BGColor,'Position',[58 (b+s*(i-1)+H*(i-1)) 20 H],'Userdata',p(i)); x(5) = uicontrol(fig.main,'Style','push','FontSize',10,'HorizontalAlignment','center','Units','characters','String','Info','BackgroundColor',BGColor,'Position',[108 (b+s*(i-1)+H*(i-1)) 12 H],'Callback',{@cm_PlotInfo,p(i)},'Interruptible','off','Userdata',p(i)); x(6) = uicontrol(fig.main,'Style','push','FontSize',10,'HorizontalAlignment','center','Units','characters','String','Delete','BackgroundColor',BGColor,'Position',[121 (b+s*(i-1)+H*(i-1)) 12 H],'Callback',{@cm_delete,h,fig.main,p(i)},'Interruptible','off','Userdata',p(i)); x(7) = uicontrol(fig.main,'Style','checkbox','FontSize',10,'HorizontalAlignment','center','Units','characters','String','Visible','BackgroundColor',BGColor,'Position',[79 (b+s*(i-1)+H*(i-1)) 12 H],'Value',V,'Callback',{@cm_visible,p(i)},'Interruptible','off','Userdata',p(i)); x(8) = uicontrol(fig.main,'Style','push','FontSize',10,'HorizontalAlignment','center','Units','characters','String','Normalize','BackgroundColor',BGColor,'Position',[92 (b+s*(i-1)+H*(i-1)) 15 H],'Callback',{@cm_normalize,p(i)},'Interruptible','off','Userdata',p(i)); set(x,'Units','normalized') end % Update plot figure's handle list Handles = get(Graph,'Userdata'); Handles.Info = fig.main; set(Graph,'Userdata',Handles) %% Context Menu: Update function cm_Update(fig,P,P2,h) % Update the handles of the Plot Info window Info = get(fig,'Userdata'); if ~~isfield(Info,'Info') if ~~ishandle(Info.Info) for i=1:1:length(P) f = findobj(Info.Info,'Userdata',P(i)); f2 = findobj(Info.Info,'String','Info'); Info_button = intersect(f,f2); % Info button handle f2 = findobj(Info.Info,'String','Visible'); Visible_radio = intersect(f,f2); % Visible radio handle f2 = findobj(Info.Info,'String','Normalize'); Normalize_button = intersect(f,f2); % Normalize button handle f2 = findobj(Info.Info,'String','Delete'); Delete_button = intersect(f,f2); % Delete button handle % Set Updated Callbacks set(Info_button,'Callback',{@cm_PlotInfo,P2(i)},'Userdata',P2(i)) set(Visible_radio,'Callback',{@cm_visible,P2(i)},'Userdata',P2(i)) set(Delete_button,'Callback',{@cm_delete,h,Info.Info,P2(i)},'Userdata',P2(i)) set(Normalize_button,'Callback',{@cm_normalize,P2(i)},'Userdata',P2(i)) end end end %% Context Menu: Plot Information (Info) function cm_PlotInfo(h,eventdata,p) % Display information about a specific plot prefs % Load Preferences % Get Matlab version info Ver = ver('Matlab'); if ~isempty(Ver) Ver = str2num(Ver.Version(1:3)); % Version number else Ver = 0; end for i=1:1:length(p) if ~~ishandle(p(i)) PData = get(p(i),'Userdata'); X = get(p(i),'XData'); Y = get(p(i),'YData'); Color = get(p(i),'Color'); % Organize Info S = []; l1 = 0; % Trigger for a space after DB, Table, X, and Y Source. If they dont' exist it won't be added. if ~isempty(PData) if ~~isfield(PData,'XDB') if ~isempty(PData.XDB) && ~strcmp(PData.XDB,'Database') S = [S;{['Origin: ' PData.XDB]}]; l1 = 1; elseif ~isempty(PData.XDB) && ~~strcmp(PData.XDB,'Database') if ~~isfield(PData,'DB') S = [S;{['Database: ' PData.DB]}]; if ~~isfield(PData,'Table') if ~isempty(PData.Table) S = [S;{['Table: ' PData.Table]}]; end end l1 = 1; end end end if ~~isfield(PData,'XSource') if ~isempty(PData.XSource) S = [S;{['Origin: ' PData.XSource]}]; l1 = 1; end end if ~~isfield(PData,'XAxis') S = [S;{['X Source: ' PData.XAxis]};{' '}]; l1 = 1; end if ~~isfield(PData,'YDB') if ~isempty(PData.YDB) && ~strcmp(PData.YDB,'Database') S = [S;{['Origin: ' PData.YDB]}]; l1 = 1; elseif ~isempty(PData.YDB) && ~~strcmp(PData.YDB,'Database') if ~~isfield(PData,'DB') S = [S;{['Database: ' PData.DB]}]; if ~~isfield(PData,'Table') if ~isempty(PData.Table) S = [S;{['Table: ' PData.Table]}]; end end l1 = 1; end end end if ~~isfield(PData,'YSource') if ~isempty(PData.YSource) S = [S;{['Origin: ' PData.YSource]}]; l1 = 1; end end if ~~isfield(PData,'YAxis') S = [S;{['Y Source: ' PData.YAxis]}]; end if ~~isfield(PData,'Comments') if ~isempty(PData.Comments) S = [S;{' '};{'Comments:'};PData.Comments]; end end if l1 == 1 S = [S;{' '}]; end if str2num(num2str(PData.Norm)) == PData.Norm S = [S;{['Normalization Factor: ' num2str(PData.Norm)]}]; else S = [S;{['Normalization Factor: ~' num2str(PData.Norm)]}]; end Y = Y*PData.Norm; % Un-normalize else PData.Norm = 1; PData.SHandle = []; PData.Indices = []; end NVal = length(Y); % Number of values N = length(find(isnan(X) == 1)); % Number of NaN's in X S = [S;{['Number of Values: ' num2str(NVal)]}]; S = [S;{['NaN''s in X: ' num2str(N)]}]; N = length(find(isnan(Y) == 1)); % Number of NaN's in X S = [S;{['NaN''s in Y: ' num2str(N)]}]; S = [S;{' '}]; S = [S;{'--------- Statistics ---------'}]; S = [S;{['X Min/Max: (' num2str(min(X)) ') , (' num2str(max(X)) ')']}]; S = [S;{['Y Min/Max: (' num2str(min(Y)) ') , (' num2str(max(Y)) ')']}]; S = [S;{['Y Mean: ' num2str(nanmean(Y))]}]; S = [S;{['Y Standard Deviation: ' num2str(nanstd(Y))]}]; S = [S;{['Y Median: ' num2str(nanmedian(Y))]}]; if Ver > 7 S = [S;{['Y Mode: ' num2str(mode(Y))]}]; end % Selected Data if ~~ishandle(PData.SHandle) XSel = get(PData.SHandle,'XData'); YSel = get(PData.SHandle,'YData'); if ~isempty(XSel) S = [S;' ']; S = [S;{'--- Selection Statistics ---'}]; NVal2 = length(YSel); % Number of values S = [S;{['Number of Values: ' num2str(NVal2)]}]; S = [S;{['X Min/Max: (' num2str(min(XSel)) ') , (' num2str(max(XSel)) ')']}]; S = [S;{['Y Min/Max: (' num2str(min(YSel)) ') , (' num2str(max(YSel)) ')']}]; S = [S;{['Y Mean: ' num2str(nanmean(YSel))]}]; S = [S;{['Y Standard Deviation: ' num2str(nanstd(YSel))]}]; S = [S;{['Y Median: ' num2str(nanmedian(YSel))]}]; if Ver > 7 S = [S;{['Y Mode: ' num2str(mode(YSel))]}]; end end end % Meta Data if metatrigger == 1 && ~~isfield(PData,'DB') if ~strcmp(PData.DB,'workspace') && ~strcmp(PData.DB,'Created Index') && exist(PData.DB,'file') ~= 2 MetData = []; % Initialize met = metatables(PData.DB,PData.Table,PData.Login,PData.Pass); % Get meta tables if ~isempty(met) DBPrefs = setdbprefs; setdbprefs('DataReturnFormat','cellarray'); conn = connect(PData.DB,PData.Login,PData.Pass); % Connect to database if ~~isempty(conn.Message) MetData = {' ';' ';'--------- Meta Data ---------'}; if ~~any(ismember(met,'General')) met(ismember(met,'General')) = []; % Remove the general table SQL = 'SELECT General from General'; curs = exec(conn,SQL); if ~~isempty(curs.Message) curs = fetch(curs); if ~isempty(curs.Data) MetData = [MetData;curs.Data]; end end end for j=1:1:length(met) SQL = ['SELECT General from `' met{j} '`']; curs = exec(conn,SQL); if ~~isempty(curs.Message) curs = fetch(curs); if ~isempty(curs.Data) MetData = [MetData;' ';'General -----';curs.Data]; end end SQL = ['SELECT `' PData.XAxis '` FROM `' met{j} '`']; curs = exec(conn,SQL); if ~~isempty(curs.Message) curs = fetch(curs); if ~isempty(curs.Data) MetData = [MetData;' ';[PData.XAxis ' -----'];curs.Data]; end end SQL = ['SELECT `' PData.YAxis '` FROM `' met{j} '`']; curs = exec(conn,SQL); if ~~isempty(curs.Message) curs = fetch(curs); if ~isempty(curs.Data) MetData = [MetData;' ';[PData.YAxis ' -----'];curs.Data]; end end end close(conn); setdbprefs('DataReturnFormat',DBPrefs.DataReturnFormat) % Restore previous return type end end else MetData = []; end % Remove nulls f = ismember(MetData,'null'); MetData(f) = []; else MetData = []; end % Display the Info Pos = gui_position(h,45,18); fig = figure('HandleVisibility','off',... 'IntegerHandle','off',... 'Menubar','none',... 'NumberTitle','off',... 'Name','BDT: Column Information',... 'Tag','BDT',... 'Units','characters',... 'Userdata','BDT_Dialog',... 'Color',BGColor,... 'Position',Pos); listbox = uicontrol(fig,'Style','listbox','Units','characters','String',' ','BackgroundColor',BGColor,'Position',[0 2 45 16],'Max',2,'Value',[]); ax = plot_sample(fig,p(i),[0 0 45 2]); set(listbox,'Units','normalized','String',[S;MetData],'UserData',[S;MetData]) ListboxTop(listbox) % Error check set(fig,'ResizeFCN',{@curve_fit_resize,listbox}) curve_fit_resize(fig,[],listbox) else errordlg('Failure to save correct handle to button.','Handle Error') end end %% Context Menu: Plot Information (Normalize) function cm_normalize(h,eventdata,p) % p = handle of plot to be normalized fig = []; if ~~isempty(p) Handle = fig_handle(h); % Get figure handle if ~~strcmp(get(Handle,'Type'),'figure') Handle = get(Handle,'CurrentAxes'); else return end p = Plot_Handles(Handle); % Get a list of all plot handles on the selected axes end for j=1:1:length(p) Handle = fig_handle(p(j)); % Get figure handle if ~~strcmp(get(Handle,'Type'),'figure') FData = get(Handle,'Userdata'); if ~~isstruct(FData) if ~~isfield(FData,'Info') if ~~ishandle(FData.Info) fig = FData.Info; Info = findobj(fig,'Userdata',p(j)); PInfo = findobj(Info,'String','Info'); % Handle of Info Button Visible = findobj(Info,'String','Visible'); % Handle of Visible checkbox Delete = findobj(Info,'String','Delete'); % Handle of Delete Button Normalize = findobj(Info,'String','Normalize'); % Handle of Normalize Button else FData.Info = []; set(Handle,'Userdata',FData) % Update handle end end end end % Load Info ax = get(p(j),'Parent'); % Axis handle of the parent axis to the plot PData = get(p(j),'Userdata'); % Get plot information Color = get(p(j),'Color'); % Get plot color Vis = get(p(j),'Visible'); % Get plot visbility LineW = get(p(j),'LineWidth'); % Get plot line width X = get(p(j),'XData'); % Get X data Y = get(p(j),'YData'); % Get Y data LineStyle = get(p(j),'LineStyle'); % Plot's line style MarkerSize = get(p(j),'MarkerSize'); % Plot's marker size MarkerStyle = get(p(j),'Marker'); % Plot's marker style MarkerFaceColor = get(p(j),'MarkerFaceColor'); % Plot's marker face color Ax_menu = get(ax,'UIContextMenu'); % Get the handle of the axes' context menu context_menu = findobj(Ax_menu,'Label','Plot Info'); % Delete old selection if ~~ishandle(PData.SHandle) delete(PData.SHandle) PData.SHandle = []; end delete(p(j)) % Remove the old plot Held = get(ax,'NextPlot'); % Determine what the hold status was hold(ax,'on') if PData.Norm == 1 N = max(abs(Y)); % Find Normalization factor PData.Norm = N; Y = Y/N; else Y = Y*PData.Norm; PData.Norm = 1; end P = plot(ax,X,Y,'Color',Color,'LineStyle',LineStyle,'LineWidth',LineW,'Marker',MarkerStyle,'MarkerSize',MarkerSize,'MarkerFaceColor',MarkerFaceColor); % Replot PostPlot(P,P) PData.SHandle = plot(ax,X(PData.Indices),Y(PData.Indices),'Color',abs(Color-.3),'LineStyle','none','Marker','o','MarkerSize',4); set(PData.SHandle,'Tag','selection') PData.PastHandles = [PData.PastHandles;P]; % Add current plot handle to list of previous plot handles set(P,'Userdata',PData) if ~~strcmp(Held,'replace') hold(ax,'off') % If the hold was originally off, restore it end set(P,'Userdata',PData,'Visible',Vis) % Save plot data to the plot handle % Update Plot Info if ~~ishandle(fig) set(Normalize,'Callback',{@cm_normalize,P},'UserData',P); % Update Normalize button callback with latest plot handle set(PInfo,'Callback',{@cm_PlotInfo,P},'UserData',P); % Update Info button callback with latest plot handle set(Visible,'Callback',{@cm_visible,P},'UserData',P); % Update Visible checkbox callback with latest plot handle set(Delete,'Callback',{@cm_delete,context_menu,fig,P},'UserData',P); % Update Delete button callback with latest plot handle end end %% Context Menu: Plot Information (Delete) function cm_delete(h,eventdata,plot,fig,p) Pos = get(fig,'Position'); % Get figure position ax = get(p,'Parent'); % Current axis handle Fig = fig_handle(p); % Figure where plot is located PData = get(p,'Userdata'); if ~~ishandle(PData.SHandle) delete(PData.SHandle) end delete(p) % Delete the plot delete(fig) % Close the plot information window cm_info(Fig,[],Pos) % Open the information window back up label_check(ax) % Recheck labels %% Context Menu: Plot Information (Visible) function cm_visible(h,eventdata,p) Info = get(p,'Userdata'); % Get plot data V = get(h,'Value'); if V == 1 V = 'on'; else V = 'off'; end set(p,'Visible',V) if ~~ishandle(Info.SHandle) set(Info.SHandle,'Visible',V) end %% Subplot function SubplotData(h,eventdata,gui) Prefs = get(gui.xcolumns_listbox,'Userdata'); V = get(gui.hold_checkbox,'Value'); % Status of Hold Graph checkbox if ~isempty(Prefs) [XData YData XCol YCol YN NPlots Prefs EString XSource YSource] = CommonPlot(gui,Prefs); % Load variables common to both plotting functions if ~~isempty(XData) if ~isempty(EString) errordlg(EString,'Error') end return end % Plot if NPlots == 1 PlotData([],[],gui) % Don't use subplot if there is only one graph return end if NPlots == 2 || NPlots == 3 % Column Subplot fig = figure; for i=1:1:NPlots subplot(NPlots,1,i) prefs('plot') % Load plot preferences P(i) = plot(XData{i},YData{i}./YN(i),'Color',Color,'Marker',Marker,... 'MarkerSize',MarkerSize,'LineStyle',LineStyle,'LineWidth',... LineWidth,'MarkerFaceColor',MarkerFaceColor,'MarkerEdgeColor',... MarkerEdgeColor,'Visible','off'); if V == 1 hold(gca,'on') end PostPlot(P(i),P(i)) if i <= length(XCol) Info.XAxis = XCol{i}; % Source of X axis data XCol{i}(XCol{i} == '_') = ' '; xlabel(XCol{i}) else Info.XAxis = []; % No X Source end Info.YAxis = YCol{i}; % Source of Y axis data YCol{i}(YCol{i} == '_') = ' '; ylabel(YCol{i}) if ~~strcmp(XSource{i},'Database') Info.DB = Prefs.DB; % Source Database Info.Table = Prefs.Table; % Source Table else Info.DB = XSource{i}; % Source file/workspace Info.Table = ''; % Not from a database end if ~~strcmp(XSource{i},'Database') && exist(XSource{i},'file') ~= 2 Info.XDB = Prefs.DB; % X Source Database else Info.XDB = XSource{i}; % X Source end if i <= length(XCol) Info.XAxis = XCol{i}; % Source of X axis data else Info.XAxis = []; end if ~~strcmp(YSource{i},'Database') && exist(YSource{i},'file') ~= 2 Info.YDB = Prefs.DB; % X Source Database else Info.YDB = YSource{i}; % X Source end Info.Norm = YN(i); % Normalization factor Info.Indices = []; % Selected Indices Info.SHandle = []; % Handle of selection plot Info.Login = Prefs.Login; % Save Login Info.Pass = Prefs.Pass; % Save password Info.PastHandles = P(i); % Start past handles list set(P(i),'Userdata',Info) cm(fig,gca) % Set the Context Menu end else C = floor(sqrt(NPlots)); % Number of Columns, squarish subplot arrays R = ceil(NPlots/C); % Number of Rows fig = figure; % Plot for i=1:1:R k = 1; while C*i-C+k <= NPlots && k <= C if C*i-C+k == NPlots && C*i-C+k < C*R subplot(R,C,C*i-C+k:R*C) % Last plot of an odd number of plots else subplot(R,C,C*i-C+k) % Any other plot end prefs('plot') P(C*i-C+k) = plot(XData{C*i-C+k},YData{C*i-C+k}./YN(C*i-C+k),'Color',Color,'Marker',Marker,... 'MarkerSize',MarkerSize,'LineStyle',LineStyle,'LineWidth',... LineWidth,'MarkerFaceColor',MarkerFaceColor,'MarkerEdgeColor',... MarkerEdgeColor,'Visible','off'); if V == 1 hold(gca,'on') end PostPlot(P(C*i-C+k),P(C*i-C+k)) if C*i-C+k <= length(XCol) Info.XAxis = XCol{C*i-C+k}; % Source of X axis data XCol{C*i-C+k}(XCol{C*i-C+k} == '_') = ' '; else Info.XAxis = ''; XCol{C*i-C+k} = ''; end if C*i-C+k <= length(XCol) Info.YAxis = YCol{C*i-C+k}; % Source of Y axis data YCol{C*i-C+k}(YCol{C*i-C+k} == '_') = ' '; else Info.YAxis = ''; YCol{C*i-C+k} = ''; end xlabel(XCol{C*i-C+k}) ylabel(YCol{C*i-C+k}) if ~~strcmp(XSource{C*i-C+k},'Database') || ~~strcmp(YSource{C*i-C+k},'Database') Info.DB = Prefs.DB; % Source Database Info.Table = Prefs.Table; % Source Table else Info.DB = XSource{C*i-C+k}; % Source file/workspace Info.Table = ''; % Not from a database end if ~~strcmp(XSource{C*i-C+k},'Database') && exist(XSource{C*i-C+k},'file') ~= 2 Info.XDB = Prefs.DB; % X Source Database else Info.XDB = XSource{C*i-C+k}; % X Source end if i <= length(XCol) Info.XAxis = XCol{C*i-C+k}; % Source of X axis data else Info.XAxis = []; end if ~~strcmp(YSource{C*i-C+k},'Database') && exist(YSource{C*i-C+k},'file') ~= 2 Info.YDB = Prefs.DB; % X Source Database else Info.YDB = YSource{C*i-C+k}; % X Source end Info.Norm = YN(C*i-C+k); % Normalization factor Info.Indices = []; % Selected Indices Info.SHandle = []; % Handle of selection plot Info.Login = Prefs.Login; % Save Login Info.Pass = Prefs.Pass; % Save password Info.PastHandles = P(C*i-C+k); % Start past plot handles list set(P(C*i-C+k),'Userdata',Info) cm(fig,gca) % Set the Context Menu k = k + 1; end end end set(fig,'Closerequestfcn',{@fig_close},'WindowButtonDownFcn',{@Button_Down},'Interruptible','off'); set(fig,'WindowButtonUpFcn',{@Button_Up}); Filt = get(gui.filters_button,'UserData'); % Load filter/command information if get(gui.filter_checkbox,'Value') == 1 && ~~isfield(Filt,'Commands') active = []; for i=1:1:length(P) active = [active;{['X' num2str(i)] P(i)};{['Y' num2str(i)] P(i)}]; end active2 = analyze_exec(Filt.Commands,active,Filt.Others,Filt.Axes_List,fig,Filt); for i=1:2:size(active2,1) eval(['X = ' active2{i,1} ';clear ' active2{i,1}]) eval(['Y = ' active2{i+1,1} ';clear ' active2{i+1,1}]) P = get(active2{i,2}); % Get all plot data P.UserData.Filters.String = []; % Erase command list, they were just run P.UserData.Filters.Eval = []; if length(X) == length(Y) set(active2{i+1,2},'YData',Y,'UserData',P.UserData) else errordlg([active2{i,1} ' dimensions to not agree with ' active2{i+1,1} '. Plot not replotted.'],'Dimension Error') set(active2{i,2},'UserData',P.UserData) end end end if exist('active','var') == 1 set(cell2mat(active(:,2)),'Visible','on') else set(P,'Visible','on') end % Display Plot Errors if ~isempty(EString) errordlg(EString,'Failed Plots') end else errordlg('You must first select a database and table.','Error'); end %% Common Plot function [XData YData XCol YCol YN NPlots Prefs EString XSource YSource] = CommonPlot(gui,Prefs) % Determine Columns Info = get(gui.xcolumns_listbox,'UserData'); Cols = [Info.Col_List;Info.Data_List]; XCol = Cols(Prefs.XList); YCol = Cols(Prefs.YList); FSource = dbstack; % Function source if ~~isempty(YCol) && ~strcmp(FSource(2).name,'SaveTo') errordlg('You must first select columns to plot.','Error') XData = []; YData = []; XCol = []; YCol = []; YN = []; NPlots = []; Prefs = []; EString = []; XSource = []; YSource = []; return end % Get Conditions V = get(gui.conditions_checkbox,'Value'); if V == 1 Cond = get(gui.conditions_button,'Userdata'); if ~isempty(Cond) Conditions = Cond.SQL; else Conditions = ''; end else Conditions = ''; end % Load Data (Test of alternate method) V = unique([Prefs.XList Prefs.YList]); C = [Prefs.Col_List;Prefs.Data_List]; conn = []; XData = num2cell(ones(length(Prefs.XList),1)); YData = num2cell(ones(length(Prefs.YList),1)); XSource = repmat({'Created Index'},length(Prefs.YList),1); YSource = repmat({'Database'},length(Prefs.YList),1); if ~isempty(find([Prefs.XList Prefs.YList] <= length(Info.Col_List))) if ~isempty(Prefs.DDOY) if ~~ischar(Prefs.DDOY) SQL = ['SELECT ' SQLCol(C(V(V <= length(Prefs.Col_List)))) ' FROM `' Prefs.Table '`' Conditions ' ORDER BY `' Prefs.DDOY '`']; else SQL = ['SELECT ' SQLCol(C(V(V <= length(Prefs.Col_List)))) ' FROM `' Prefs.Table '`' Conditions]; end else SQL = ['SELECT ' SQLCol(C(V(V <= length(Prefs.Col_List)))) ' FROM `' Prefs.Table '`' Conditions]; end DBPrefs = setdbprefs('DataReturnFormat'); % Old return format setdbprefs('DataReturnFormat','cellarray') conn = connect(Prefs.DB,Prefs.Login,Prefs.Pass); % Open a database connection curs = exec(conn,SQL); % Execute SQL Query if ~~isempty(curs.Message) curs = fetch(curs); % Get the data end close(conn); % Close the connection if it was opened setdbprefs('DataReturnFormat',DBPrefs) % Restore the previous return format if ~isempty(curs.Message) EString = sprintf([curs.Message '\n\n' SQL]); XData = {}; YData = {}; NPlots = 0; YN = 1; return end testData = curs.Data; clear curs conn SQL for i=1:1:size(testData,2) if ~~isnumeric(testData{1,i}) test{i,1} = cell2mat(testData(:,i)); else test{i,1} = {testData(:,i)}; end end clear testData temp = num2cell(ones(max(V),1)); temp(V(V <= length(Prefs.Col_List))) = test; clear test XData(find(Prefs.XList <= length(Prefs.Col_List))) = temp(Prefs.XList(Prefs.XList <= length(Prefs.Col_List))); XSource(find(Prefs.XList <= length(Prefs.Col_List))) = {'Database'}; YData(find(Prefs.YList <= length(Prefs.Col_List))) = temp(Prefs.YList(Prefs.YList <= length(Prefs.Col_List))); clear temp i end if ~isempty(find([Prefs.XList Prefs.YList] > length(Info.Col_List))) WD = get(gui.help_button,'UserData'); % Load workspace data XData(find(Prefs.XList > length(Prefs.Col_List))) = WD(Prefs.XList(Prefs.XList > length(Prefs.Col_List)) - length(Prefs.Col_List),1); XSource(find(Prefs.XList > length(Prefs.Col_List))) = WD(Prefs.XList(Prefs.XList > length(Prefs.Col_List)) - length(Prefs.Col_List),2); YData(find(Prefs.YList > length(Prefs.Col_List))) = WD(Prefs.YList(Prefs.YList > length(Prefs.Col_List)) - length(Prefs.Col_List),1); YSource(find(Prefs.YList > length(Prefs.Col_List))) = WD(Prefs.YList(Prefs.YList > length(Prefs.Col_List)) - length(Prefs.Col_List),2); end clear C V WD DBPrefs conn Conditions % Test if ~~strcmp(FSource(2).name,'SaveTo') YN = []; NPlots = []; EString = []; return end % Check for Y data without X counterpart if length(YData) > length(XData) for i=length(XData)+1:1:length(YData) XData{i} = (1:1:length(YData{i}))'; % Create an index of values to substitute for lack of values end end % Dimension Check BadDim = []; for i=1:1:length(XData) if length(XData{i}) ~= length(YData{i}) BadDim = [BadDim;i]; end end BadXD = XCol(BadDim); % Bad X dimension list BadYD = YCol(BadDim); % Bad Y dimension list XCol(BadDim) = []; % Remove to maintain the same order and length as the data YCol(BadDim) = []; XData(BadDim) = []; YData(BadDim) = []; clear BadDim % Type Check BadType = []; for i=1:1:length(XData) if ~~iscell(XData{i}) if ~isnumeric(XData{i}{1}) BadType = [BadType;i]; end else if ~isnumeric(XData{i}) BadType = [BadType;i]; end end if ~~iscell(YData{i}) if ~isnumeric(YData{i}{1}) BadType = [BadType;i]; end else if ~isnumeric(YData{i}) BadType = [BadType;i]; end end end BadXT = XCol(BadType); % Bad X type list BadYT = YCol(BadType); % Bad Y type list XCol(BadType) = []; % Remove to maintain the same order and length as the data YCol(BadType) = []; XData(BadType) = []; YData(BadType) = []; % Database Cell Array Conversion for i=1:1:length(XData) if ~~iscell(XData{i}) XData{i} = cell2mat(XData{i}); end if ~~iscell(YData{i}) YData{i} = cell2mat(YData{i}); end end % Format Error String EString = []; if ~isempty(BadXD) || ~isempty(BadXT) EString = 'The following graphs were not plotted.'; end if ~isempty(BadXD) EString = [EString '\n\nNon-matching dimensions:']; for i=1:1:length(BadXD) EString = [EString '\n ' BadXD{i} ' vs ' BadYD{i}]; end end if ~isempty(BadXT) EString = [EString '\n\nNon-numeric data types.']; for i=1:1:length(BadXT) EString = [EString '\n ' BadXT{i} ' vs ' BadYT{i}]; end end if ~isempty(EString) EString = sprintf(EString); end clear BadXT BadYT BadXD BadYD BadType NPlots = length(YData); % Normalize V = get(gui.normalize_checkbox,'Value'); if V == 1 for i=1:1:length(YData) YN(i) = max(abs(YData{i})); % Normalization factor end else YN = ones(1,NPlots); end %% Conditions function Conditions(h,eventdata,gui) Prefs = get(gui.xcolumns_listbox,'Userdata'); Cond = get(gui.conditions_button,'Userdata'); % Check for Existing Conditions Window FData = get(gui.main,'UserData'); if ~isempty(FData) if ~~isstruct(FData) if ~~isfield(FData,'Windows') if ~~isfield(FData.Windows,'Conditions') if ~~ishandle(FData.Windows.Conditions) figure(FData.Windows.Conditions) return end end end end end % Check if ~~isempty(Prefs.DB) || ~~isempty(Prefs.Table) errordlg('You must first select a database and table.','Error') return end % Determine Values if ~~isempty(Cond) || ~strcmp(Prefs.DB,Cond.DB) || ~strcmp(Prefs.Table,Cond.Table) Cond.DB = Prefs.DB; Cond.Table = Prefs.Table; Cond.SQL = ''; Cond.Columns1 = 1; Cond.Columns2 = 1; Cond.Columns3 = 1; Cond.Columns4 = 1; Cond.Eq1 = 1; Cond.Eq2 = 1; Cond.Eq3 = 1; Cond.Eq4 = 1; Cond.Radio11 = 0; Cond.Radio12 = 0; Cond.Radio21 = 0; Cond.Radio22 = 0; Cond.Radio31 = 0; Cond.Radio32 = 0; Cond.Edit1 = ''; Cond.Edit2 = ''; Cond.Edit3 = ''; Cond.Edit4 = ''; end % Check if ~~isempty(Prefs) errordlg('You must first select a database and table.','Error') return end prefs('GUI') % Load Preferences sql = .4; H = 16.95+sql; % Figure height s = .212; % Spacing h = 1.538; % Height of elements b = .2; % Move everything down % Creat GUI Pos = gui_position(gui.main,63,H); fig.main = figure('HandleVisibility','off',... 'IntegerHandle','off',... 'Menubar','none',... 'NumberTitle','off',... 'Name','BDT: Conditions',... 'Tag','BDT',... 'Units','characters',... 'Userdata','BDT_Dialog',... 'Color',BGColor,... 'Position',Pos); if ~isstruct(FData) FData = []; end FData.Windows.Conditions = fig.main; set(gui.main,'UserData',FData) % Text fig.first_text = uicontrol(fig.main,'Style','text','HorizontalAlignment','left','FontSize',10,'String','Select where','Units','characters','BackgroundColor',BGColor,'Position',[2 (H-s-h-b) 16 h]); fig.second_text = uicontrol(fig.main,'Style','text','HorizontalAlignment','left','FontSize',10,'String','Select where','Units','characters','BackgroundColor',BGColor,'Position',[2 (H-3*s-3*h-b) 16 h]); fig.third_text = uicontrol(fig.main,'Style','text','HorizontalAlignment','left','FontSize',10,'String','Select where','Units','characters','BackgroundColor',BGColor,'Position',[2 (H-5*s-5*h-b) 16 h]); fig.fourth_text = uicontrol(fig.main,'Style','text','HorizontalAlignment','left','FontSize',10,'String','Select where','Units','characters','BackgroundColor',BGColor,'Position',[2 (H-7*s-7*h-b) 16 h]); % Radio Buttons fig.firstRad1 = uicontrol(fig.main,'Style','radio','HorizontalAlignment','left','String','AND','Units','characters','BackgroundColor',BGColor,'Position',[21 (H-2*s-2*h-b) 9 h],'Value',Cond.Radio11); fig.firstRad2 = uicontrol(fig.main,'Style','radio','HorizontalAlignment','left','String','OR','Units','characters','BackgroundColor',BGColor,'Position',[32 (H-2*s-2*h-b) 9 h],'Value',Cond.Radio12); fig.secondRad1 = uicontrol(fig.main,'Style','radio','HorizontalAlignment','left','String','AND','Units','characters','BackgroundColor',BGColor,'Position',[21 (H-4*s-4*h-b) 9 h],'Value',Cond.Radio21); fig.secondRad2 = uicontrol(fig.main,'Style','radio','HorizontalAlignment','left','String','OR','Units','characters','BackgroundColor',BGColor,'Position',[32 (H-4*s-4*h-b) 9 h],'Value',Cond.Radio22); fig.thirdRad1 = uicontrol(fig.main,'Style','radio','HorizontalAlignment','left','String','AND','Units','characters','BackgroundColor',BGColor,'Position',[21 (H-6*s-6*h-b) 9 h],'Value',Cond.Radio31); fig.thirdRad2 = uicontrol(fig.main,'Style','radio','HorizontalAlignment','left','String','OR','Units','characters','BackgroundColor',BGColor,'Position',[32 (H-6*s-6*h-b) 9 h],'Value',Cond.Radio32); % Edit Boxes fig.first_edit = uicontrol(fig.main,'Style','edit','HorizontalAlignment','left','String',Cond.Edit1,'Units','characters','Position',[45 (H-s-h-b) 16 h],'BackgroundColor','white'); fig.second_edit = uicontrol(fig.main,'Style','edit','HorizontalAlignment','left','String',Cond.Edit2,'Units','characters','Position',[45 (H-3*s-3*h-b) 16 h],'BackgroundColor','white'); fig.third_edit = uicontrol(fig.main,'Style','edit','HorizontalAlignment','left','String',Cond.Edit3,'Units','characters','Position',[45 (H-5*s-5*h-b) 16 h],'BackgroundColor','white'); fig.fourth_edit = uicontrol(fig.main,'Style','edit','HorizontalAlignment','left','String',Cond.Edit4,'Units','characters','Position',[45 (H-7*s-7*h-b) 16 h],'BackgroundColor','white'); fig.SQL_edit = uicontrol(fig.main,'Style','edit','HorizontalAlignment','left','String',Cond.SQL,'Units','characters','Position',[2 (H-8*s-8*h-b-sql) 59 h],'BackgroundColor','white'); % Buttons fig.ok_button = uicontrol(fig.main,'Style','push','Units','characters','BackgroundColor',BGColor,'Position',[26.5 (H-9*s-9*h-b-.5-sql) 10 1.769],'String','OK','Callback',{@Filters_List,gui,fig}); % Drop Down Menus Columns = get(gui.xcolumns_listbox,'String'); fig.firstCol_popup = uicontrol(fig.main,'Style','popup','HorizontalAlignment','left','String',Columns,'Units','characters','Position',[19 (H-s-h-b) 16 h],'BackgroundColor','white','Value',Cond.Columns1); fig.firstEq_popup = uicontrol(fig.main,'Style','popup','HorizontalAlignment','left','String',{'==','>=','<=','>','<','!='},'Units','characters','Position',[36 (H-s-h-b) 8 h],'BackgroundColor','white','Value',Cond.Eq1); fig.secondCol_popup = uicontrol(fig.main,'Style','popup','HorizontalAlignment','left','String',Columns,'Units','characters','Position',[19 (H-3*s-3*h-b) 16 h],'BackgroundColor','white','Value',Cond.Columns2); fig.secondEq_popup = uicontrol(fig.main,'Style','popup','HorizontalAlignment','left','String',{'==','>=','<=','>','<','!='},'Units','characters','Position',[36 (H-3*s-3*h-b) 8 h],'BackgroundColor','white','Value',Cond.Eq2); fig.thirdCol_popup = uicontrol(fig.main,'Style','popup','HorizontalAlignment','left','String',Columns,'Units','characters','Position',[19 (H-5*s-5*h-b) 16 h],'BackgroundColor','white','Value',Cond.Columns3); fig.thirdEq_popup = uicontrol(fig.main,'Style','popup','HorizontalAlignment','left','String',{'==','>=','<=','>','<','!='},'Units','characters','Position',[36 (H-5*s-5*h-b) 8 h],'BackgroundColor','white','Value',Cond.Eq3); fig.fourthCol_popup = uicontrol(fig.main,'Style','popup','HorizontalAlignment','left','String',Columns,'Units','characters','Position',[19 (H-7*s-7*h-b) 16 h],'BackgroundColor','white','Value',Cond.Columns4); fig.fourthEq_popup = uicontrol(fig.main,'Style','popup','HorizontalAlignment','left','String',{'==','>=','<=','>','<','!='},'Units','characters','Position',[36 (H-7*s-7*h-b) 8 h],'BackgroundColor','white','Value',Cond.Eq4); % Set all unit types to normalized H = cell2mat(struct2cell(fig)); set(H(2:end),'Units','normalized'); % Set Callbacks set(H(6:11),'Callback',{@Conditions_Radio,fig}); set(H(12:end),'Callback',{@Conditions_SQL,fig}); set(H(12:15),'KeyPressFcn',{@Conditions_SQL,fig}); set(H(17),'Callback',{@Conditions_OK,gui,fig}); %% Conditions: OK function Conditions_OK(h,eventdata,gui,fig) % Load Info Prefs = get(gui.xcolumns_listbox,'Userdata'); Cond.DB = Prefs.DB; Cond.Table = Prefs.Table; Cond.Columns1 = get(fig.firstCol_popup,'Value'); Cond.Columns2 = get(fig.secondCol_popup,'Value'); Cond.Columns3 = get(fig.thirdCol_popup,'Value'); Cond.Columns4 = get(fig.fourthCol_popup,'Value'); Cond.Eq1 = get(fig.firstEq_popup,'Value'); Cond.Eq2 = get(fig.secondEq_popup,'Value'); Cond.Eq3 = get(fig.thirdEq_popup,'Value'); Cond.Eq4 = get(fig.fourthEq_popup,'Value'); Cond.Radio11 = get(fig.firstRad1,'Value'); Cond.Radio12 = get(fig.firstRad2,'Value'); Cond.Radio21 = get(fig.secondRad1,'Value'); Cond.Radio22 = get(fig.secondRad2,'Value'); Cond.Radio31 = get(fig.thirdRad1,'Value'); Cond.Radio32 = get(fig.thirdRad2,'Value'); Cond.Edit1 = get(fig.first_edit,'String'); Cond.Edit2 = get(fig.second_edit,'String'); Cond.Edit3 = get(fig.third_edit,'String'); Cond.Edit4 = get(fig.fourth_edit,'String'); Cond.SQL = get(fig.SQL_edit,'String'); set(gui.conditions_button,'Userdata',Cond) % Save the info delete(fig.main) % Close the window %% Conditions: SQL function Conditions_SQL(h,eventdata,fig) SQL = ' WHERE '; % Initialize col = get(fig.firstCol_popup,'String'); % First Statement S = get(fig.first_edit,'String'); % String from editbox V = get(fig.firstCol_popup,'Value'); % Selected column Veq = get(fig.firstEq_popup,'Value'); % Selected equality if ~isempty(S) SQL = [SQL '`' col{V} '`' Conditions_Eq(Veq) S]; end % Second Statement S = get(fig.second_edit,'String'); % String from editbox V = get(fig.secondCol_popup,'Value'); % Selected column Veq = get(fig.secondEq_popup,'Value'); % Selected equality if ~isempty(S) && ~~max(cell2mat(get([fig.firstRad1 fig.firstRad2],'Value'))) if ~~get(fig.firstRad1,'Value') x = ' AND '; elseif ~~get(fig.firstRad2,'Value') x = ' OR '; end SQL = [SQL x '`' col{V} '`' Conditions_Eq(Veq) S]; end % Third Statement S = get(fig.third_edit,'String'); % String from editbox V = get(fig.thirdCol_popup,'Value'); % Selected column Veq = get(fig.thirdEq_popup,'Value'); % Selected equality if ~isempty(S) && ~~max(cell2mat(get([fig.secondRad1 fig.secondRad2],'Value'))) if ~~get(fig.secondRad1,'Value') x = ' AND '; elseif ~~get(fig.secondRad2,'Value') x = ' OR '; end SQL = [SQL x '`' col{V} '`' Conditions_Eq(Veq) S]; end % Fourth Statement S = get(fig.fourth_edit,'String'); % String from editbox V = get(fig.fourthCol_popup,'Value'); % Selected column Veq = get(fig.fourthEq_popup,'Value'); % Selected equality if ~isempty(S) && ~~max(cell2mat(get([fig.thirdRad1 fig.thirdRad2],'Value'))) if ~~get(fig.thirdRad1,'Value') x = ' AND '; elseif ~~get(fig.thirdRad2,'Value') x = ' OR '; end SQL = [SQL x '`' col{V} '`' Conditions_Eq(Veq) S]; end % Check if ~~strcmp(SQL(1:3),'AND') SQL = SQL(5:end); elseif ~~strcmp(SQL(1:2),'OR') SQL = SQL(4:end); elseif ~~strcmp(SQL,' WHERE ') return end set(fig.SQL_edit,'String',SQL) %% Conditions: Equality function S = Conditions_Eq(V) switch V case 1 S = '='; case 2 S = '>='; case 3 S = '<='; case 4 S = '>'; case 5 S = '<'; case 6 S = '<>'; end %% Conditions: Radio function Conditions_Radio(h,eventdata,fig) switch h case fig.firstRad1 h_other = fig.firstRad2; case fig.firstRad2 h_other = fig.firstRad1; case fig.secondRad1 h_other = fig.secondRad2; case fig.secondRad2 h_other = fig.secondRad1; case fig.thirdRad1 h_other = fig.thirdRad2; case fig.thirdRad2 h_other = fig.thirdRad1; end V = get(h,'Value'); if V == 1 set(h_other,'Value',0) end Conditions_SQL([],[],fig) %% Figure Close Function function fig_close(h,eventdata) Handles = get(h,'Userdata'); % Find Handles of Data Windows p = Plot_Handles(Ax_Handles(h)); % Get plot handles PData = get(p,'Userdata'); % Get plot data if ~iscell(PData) PData = {PData}; end for i=1:1:length(PData) if ~~isstruct(PData{i}) if ~~isfield(PData{i},'Windows') flds = fieldnames(PData{i}.Windows); % Get all subfield names for j=1:1:length(flds) if ~~isfield(PData{i}.Windows,flds{j}) if ~~ishandle(PData{i}.Windows.(flds{j})) delete(PData{i}.Windows.(flds{j})) end end end end end end delete(h) % Close all windows associated with the plot figure if ~isempty(Handles) if ~~isstruct(Handles) % Plot Info Window if ~~isfield(Handles,'Info') if ~~ishandle(Handles.Info) delete(Handles.Info) end end % Related Data Window if ~~isfield(Handles,'Related') if ~~ishandle(Handles.Related) delete(Handles.Related) end end % All other associated windows if ~~isfield(Handles,'Windows') flds = fieldnames(Handles.Windows); % Get all subfield names for i=1:1:length(flds) if ~~isfield(Handles.Windows,flds{i}) if ~~ishandle(Handles.Windows.(flds{i})) delete(Handles.Windows.(flds{i})) end end end end end end %% Post Plot function PostPlot(p,pset) % p is the handle of the main plot to be used in the callback % pset is the handle of the plot to have the context menu % p = pset for nearly all cases as the context menu is set to the plot % p != pset for selection plots since the callback has to refer to the main % plot and not the selection plot for i=1:1:length(p) context = uicontextmenu; fig = fig_handle(pset(i)); set(context,'Parent',fig) menu.delete = uimenu(context,'Label','Delete Points','Callback',{@cm_delete_points}); menu.analyze = uimenu(context,'Label','Analyze','Callback',{@analyze,fig_handle(p(i))}); menu.info = uimenu(context,'Label','Info','Callback',{@cm_PlotInfo,p(i)}); menu.plottools = uimenu(context,'Label','Plot Tools'); menu.search = uimenu(menu.plottools,'Label','Search Plot','Callback',{@search_plot,p(i)}); menu.normalize = uimenu(menu.plottools,'Label','Normalize','Callback',{@cm_normalize,p(i)}); menu.related = uimenu(menu.plottools,'Label','Related Data','Callback',{@PostPlot_Related}); menu.display = uimenu(menu.plottools,'Label','Display Data','Callback',{@PostPlot_Display,p(i)}); menu.invert = uimenu(menu.plottools,'Label','Invert Selection','Callback',{@invert,p(i)}); menu.copy = uimenu(menu.plottools,'Label','Copy Plot','Callback',{@copymove_plots}); menu.move = uimenu(menu.plottools,'Label','Move Plot','Callback',{@copymove_plots}); menu.delete = uimenu(menu.plottools,'Label','Delete Plot','Callback',{@PostPlot_Delete,p(i)}); menu.properties = uimenu(context,'Label','Properties'); menu.linestyle = uimenu(menu.properties,'Label','Line Style'); menu.doubledash = uimenu(menu.linestyle,'Label','dash','Callback',{@PostPlot_Style,p(i)},'Tag','--'); menu.dots = uimenu(menu.linestyle,'Label','dot','Callback',{@PostPlot_Style,p(i)},'Tag',':'); menu.solid = uimenu(menu.linestyle,'Label','solid','Callback',{@PostPlot_Style,p(i)},'Tag','-'); menu.none = uimenu(menu.linestyle,'Label','none','Callback',{@PostPlot_Style,p(i)},'Tag','none'); menu.linewidth = uimenu(menu.properties,'Label','Line Width'); menu.one = uimenu(menu.linewidth,'Label','1','Callback',{@PostPlot_Width,p(i)}); menu.two = uimenu(menu.linewidth,'Label','2','Callback',{@PostPlot_Width,p(i)}); menu.three = uimenu(menu.linewidth,'Label','3','Callback',{@PostPlot_Width,p(i)}); menu.four = uimenu(menu.linewidth,'Label','4','Callback',{@PostPlot_Width,p(i)}); menu.five = uimenu(menu.linewidth,'Label','5','Callback',{@PostPlot_Width,p(i)}); menu.Color = uimenu(menu.properties,'Label','Color'); menu.red = uimenu(menu.Color,'Label','Red','Tag','red','Callback',{@PostPlot_Color,p(i)}); menu.blue = uimenu(menu.Color,'Label','Blue','Tag','blue','Callback',{@PostPlot_Color,p(i)}); menu.green = uimenu(menu.Color,'Label','Green','Tag','green','Callback',{@PostPlot_Color,p(i)}); menu.yellow = uimenu(menu.Color,'Label','Yellow','Tag','yellow','Callback',{@PostPlot_Color,p(i)}); menu.magenta = uimenu(menu.Color,'Label','Magenta','Tag','m','Callback',{@PostPlot_Color,p(i)}); menu.black = uimenu(menu.Color,'Label','Black','Tag','k','Callback',{@PostPlot_Color,p(i)}); menu.cyan = uimenu(menu.Color,'Label','Cyan','Tag','cyan','Callback',{@PostPlot_Color,p(i)}); menu.marker = uimenu(menu.properties,'Label','Marker Style'); menu.plus = uimenu(menu.marker,'Label','+','Tag','+','Callback',{@PostPlot_Marker,p(i)}); menu.circle = uimenu(menu.marker,'Label','o','Tag','o','Callback',{@PostPlot_Marker,p(i)}); menu.asterisk = uimenu(menu.marker,'Label','*','Tag','*','Callback',{@PostPlot_Marker,p(i)}); menu.point = uimenu(menu.marker,'Label','.','Tag','.','Callback',{@PostPlot_Marker,p(i)}); menu.cross = uimenu(menu.marker,'Label','x','Tag','x','Callback',{@PostPlot_Marker,p(i)}); menu.square = uimenu(menu.marker,'Label','square','Tag','square','Callback',{@PostPlot_Marker,p(i)}); menu.diamond = uimenu(menu.marker,'Label','diamond','Tag','diamond','Callback',{@PostPlot_Marker,p(i)}); menu.uparrow = uimenu(menu.marker,'Label','^','Tag','^','Callback',{@PostPlot_Marker,p(i)}); menu.downarrow = uimenu(menu.marker,'Label','v','Tag','v','Callback',{@PostPlot_Marker,p(i)}); menu.greater = uimenu(menu.marker,'Label','>','Tag','>','Callback',{@PostPlot_Marker,p(i)}); menu.less = uimenu(menu.marker,'Label','<','Tag','<','Callback',{@PostPlot_Marker,p(i)}); menu.pent = uimenu(menu.marker,'Label','pentagram','Tag','pentagram','Callback',{@PostPlot_Marker,p(i)}); menu.hex = uimenu(menu.marker,'Label','hexagram','Tag','hexagram','Callback',{@PostPlot_Marker,p(i)}); menu.none = uimenu(menu.marker,'Label','none','Tag','none','Callback',{@PostPlot_Marker,p(i)}); menu.markersize = uimenu(menu.properties,'Label','Marker Size'); menu.one = uimenu(menu.markersize,'Label','1','Callback',{@PostPlot_MarkerSize,p(i)}); menu.two = uimenu(menu.markersize,'Label','2','Callback',{@PostPlot_MarkerSize,p(i)}); menu.three = uimenu(menu.markersize,'Label','3','Callback',{@PostPlot_MarkerSize,p(i)}); menu.four = uimenu(menu.markersize,'Label','4','Callback',{@PostPlot_MarkerSize,p(i)}); menu.five = uimenu(menu.markersize,'Label','5','Callback',{@PostPlot_MarkerSize,p(i)}); menu.six = uimenu(menu.markersize,'Label','6','Callback',{@PostPlot_MarkerSize,p(i)}); menu.markerfacecolor = uimenu(menu.properties,'Label','Face Color'); menu.red = uimenu(menu.markerfacecolor,'Label','Red','Tag','red','Callback',{@PostPlot_FaceColor,p(i)}); menu.blue = uimenu(menu.markerfacecolor,'Label','Blue','Tag','blue','Callback',{@PostPlot_FaceColor,p(i)}); menu.green = uimenu(menu.markerfacecolor,'Label','Green','Tag','green','Callback',{@PostPlot_FaceColor,p(i)}); menu.yellow = uimenu(menu.markerfacecolor,'Label','Yellow','Tag','yellow','Callback',{@PostPlot_FaceColor,p(i)}); menu.magenta = uimenu(menu.markerfacecolor,'Label','Magenta','Tag','m','Callback',{@PostPlot_Color,p(i)}); menu.black = uimenu(menu.markerfacecolor,'Label','Black','Tag','k','Callback',{@PostPlot_Color,p(i)}); menu.cyan = uimenu(menu.markerfacecolor,'Label','Cyan','Tag','cyan','Callback',{@PostPlot_Color,p(i)}); menu.setinfo = uimenu(menu.properties,'Label','Set Info','Callback',{@PostPlot_SetInfo,p(i)}); menu.export = uimenu(context,'Label','Export'); menu.indices = uimenu(menu.export,'Label','Indices','Callback',{@PostPlot_Indices,p(i)}); menu.xydata = uimenu(menu.export,'Label','X and Y Data','Callback',{@PostPlot_Data,p(i)}); menu.xdata = uimenu(menu.export,'Label','X Data','Callback',{@PostPlot_Data,p(i)}); menu.ydata = uimenu(menu.export,'Label','Y Data','Callback',{@PostPlot_Data,p(i)}); menu.tofile = uimenu(menu.export,'Label','To File','Callback',{@PostPlot_Data,p(i)}); set(pset(i),'UIContextMenu',context) end %% Post Plot: Set Info function PostPlot_SetInfo(h,eventdata,p) % Set the info (XSource,YSource,etc) of the selected plot % h = context menu entry handle % eventdata = unused % p = plot handle fig = fig_handle(p); % Handle of plot's parent figure PData = get(p,'UserData'); % Load plot's info % Parse Info if ~~isstruct(PData) % Check for Previous Instance if ~~isfield(PData,'Windows') if ~~isfield(PData.Windows,'SetInfo') if ~~ishandle(PData.Windows.SetInfo) figure(PData.Windows.SetInfo) return end end end if ~~isfield(PData,'DB') DB = PData.DB; db = 1; else DB = []; db = 0; end if ~~isfield(PData,'Table') Table = PData.Table; t = 1; else Table = []; t = 0; end if ~~isfield(PData,'XAxis') XSource = PData.XAxis; else XSource = []; end if ~~isfield(PData,'YAxis') YSource = PData.YAxis; e