Home > chronux_2_00 > spikesort > ssg > ssg_featureselect.m

ssg_featureselect

PURPOSE ^

SSG_FEATURESELECT M-file for ssg_featureselect.fig

SYNOPSIS ^

function varargout = ssg_featureselect(varargin)

DESCRIPTION ^

 SSG_FEATURESELECT M-file for ssg_featureselect.fig
      SSG_FEATURESELECT(axes_handle) creates a new SSG_FEATURESELECT.  Not
      a user GUI; intended for internal use by SS GUI applications.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function varargout = ssg_featureselect(varargin)
0002 % SSG_FEATURESELECT M-file for ssg_featureselect.fig
0003 %      SSG_FEATURESELECT(axes_handle) creates a new SSG_FEATURESELECT.  Not
0004 %      a user GUI; intended for internal use by SS GUI applications.
0005 
0006 % Begin initialization code - DO NOT EDIT
0007 gui_Singleton = 0;
0008 gui_State = struct('gui_Name',       mfilename, ...
0009                    'gui_Singleton',  gui_Singleton, ...
0010                    'gui_OpeningFcn', @ssg_featureselect_OpeningFcn, ...
0011                    'gui_OutputFcn',  @ssg_featureselect_OutputFcn, ...
0012                    'gui_LayoutFcn',  [] , ...
0013                    'gui_Callback',   []);
0014 if nargin && ischar(varargin{1})
0015     gui_State.gui_Callback = str2func(varargin{1});
0016 end
0017 
0018 if nargout
0019     [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
0020 else
0021     gui_mainfcn(gui_State, varargin{:});
0022 end
0023 % End initialization code - DO NOT EDIT
0024 
0025 
0026 % --- Executes just before ssg_featureselect is made visible.
0027 function ssg_featureselect_OpeningFcn(hObject, eventdata, handles, varargin)
0028 handles.output = hObject;
0029 
0030 
0031 % Argument error checking
0032 if (length(varargin) < 2)
0033     error('SSG:invalid_init_arg', 'Incorrect initalization syntax.');
0034 end
0035 handles.axes_handle = varargin{1};
0036 handles.switchaxis = varargin{2};
0037 
0038 if (~ishandle(handles.axes_handle) || ~strcmp(get(handles.axes_handle, 'Type'), 'axes') || ...
0039     isempty(guidata(handles.axes_handle)))
0040     error('SSG:invalid_init_arg', 'First initialization argument must be an axis handle created by an SSG function.');
0041 end
0042 if (~ischar(handles.switchaxis) || ~any(strcmpi({'x', 'y', 'z'}, handles.switchaxis)))
0043     error('SSG:invalid_init_arg', 'Second initialization argument must be one of ''x'', ''y'', or ''z''.');
0044 end
0045 ssg = guidata(handles.axes_handle);
0046 
0047 choices = get(handles.popup_datatype, 'String');
0048 value = find(strcmpi(choices, ssg.([handles.switchaxis 'choice'])));
0049 if (isempty(value))
0050     error('SSG:invalid_default_choice', ['Invalid entry in initial ' handles.switchaxis 'choice.']);
0051 end
0052 
0053 % Fill in controls to reflect exisiting data choice.
0054 set(handles.popup_datatype, 'Value', value);
0055 set(handles.edit_param1, 'String', ssg.([handles.switchaxis 'param1']));
0056 handles.oldparam = ssg.([handles.switchaxis 'param1']);
0057 handles.maxparam = size(ssg.ss_object.waveforms, 2);
0058 set(handles.figure_ssg_featureselect, 'Name', [upper(handles.switchaxis) '-Axis Selection']);
0059 
0060 % Move this window to the current location of the corresponding label for convenience.
0061 set(handles.figure_ssg_featureselect, 'Units', 'Pixel');
0062 newpos = labelposition_screen_coords(handles);
0063 currpos = get(handles.figure_ssg_featureselect, 'Position');
0064 set(handles.figure_ssg_featureselect, 'Position', [(newpos-currpos(3:4)*0.75) currpos(3:4)]);
0065 set(handles.figure_ssg_featureselect, 'Color', get(handles.axes_handle, [handles.switchaxis 'Color']));
0066 
0067 % Update guidata structures
0068 ssg.([handles.switchaxis 'control']) = handles.figure_ssg_featureselect;
0069 guidata(handles.axes_handle, ssg);
0070 guidata(hObject, handles);
0071 
0072 
0073 % Outputs from this function are returned to the command line.
0074 function varargout = ssg_featureselect_OutputFcn(hObject, eventdata, handles)
0075 varargout{1} = handles.output;
0076 
0077 
0078 %%%%%%%%%%%%%%%%%%%%%%%  GUI INITIALIZATION %%%%%%%%%%%%%%%%%%%%%%%%%%
0079 % Executes during object creation, after setting all properties.
0080 %  Most of this is just for visual consistency.
0081 
0082 function edit_param1_CreateFcn(hObject, eventdata, handles)
0083 if ispc,  set(hObject,'BackgroundColor','white');
0084 else      set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
0085 end
0086 
0087 function popup_datatype_CreateFcn(hObject, eventdata, handles)
0088 if ispc,  set(hObject,'BackgroundColor','white');
0089 else      set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
0090 end
0091 
0092 function slider_aspect_CreateFcn(hObject, eventdata, handles)
0093 set(hObject,'BackgroundColor', [.9 .9 .9]);
0094 
0095 
0096 %%%%%%%%%%%%%%%%%%%%%%%%%%%% CALLBACKS  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0097 
0098 function popup_datatype_Callback(hObject, eventdata, handles)
0099 % Make GUI state consistent before calling for data update.
0100 choices = get(hObject, 'String');
0101 choice = choices{get(hObject, 'Value')};
0102 paramhandles = [handles.edit_param1, handles.button_next, handles.button_last];
0103 switch (choice),
0104     case {'Signal', 'PC'}
0105         set(paramhandles, 'Enable', 'on');
0106     case {'Event Time', 'Height', 'Width', 'ISI Preceding', 'Total Energy', 'Cluster #'}
0107         set(paramhandles, 'Enable', 'off');
0108 end
0109 alter_data(handles);
0110 
0111 
0112 function edit_param1_Callback(hObject, eventdata, handles)
0113 % Bounds checking on the parameter edit box.
0114 param1 = str2double(get(handles.edit_param1, 'String'));
0115 if (isnan(param1) || (param1 ~= round(param1)))
0116     set(handles.edit_param1, 'String', handles.oldparam);
0117     beep;
0118 else
0119     handles = param1_bounds_check(handles, param1);
0120     alter_data(handles);
0121 end
0122 
0123 
0124 % These next two functions just advance or review the param1 value
0125 % in integer steps; just finger-candy to make it easier to step
0126 % through a range of values.
0127 function button_next_Callback(hObject, eventdata, handles)
0128 param1 = str2double(get(handles.edit_param1, 'String'));
0129 handles = param1_bounds_check(handles, param1 + 1);
0130 alter_data(handles);
0131 
0132 function button_last_Callback(hObject, eventdata, handles)
0133 param1 = str2double(get(handles.edit_param1, 'String'));
0134 handles = param1_bounds_check(handles, param1 - 1);
0135 alter_data(handles);
0136 
0137 
0138 function figure_delete_Callback(hObject, eventdata, handles)
0139 % We need to let the parent axis know when this GUI is deleted.
0140 ssg = guidata(handles.axes_handle);
0141 ssg.([handles.switchaxis 'control']) = [];
0142 guidata(handles.axes_handle, ssg);
0143 
0144 %%%%%%%%%%%%%%%%%%%%%%%%% HELPER FUNCTIONS  %%%%%%%%%%%%%%%%%%%%%%%%%%%%
0145 
0146 function pos = labelposition_screen_coords(handles)
0147 % Returns [left, lower] pixel coordinates where the GUI can be placed
0148 % (in screen coordinates) so that it appears somewhere in the vicinity
0149 % of the axes (i tried to have them pop up on top of the axis labels, but
0150 % there's something wrong with the units of the label's 'Extent' property
0151 % in MatlabR13).
0152 axeshndl = handles.axes_handle;
0153 figurehndl = get(axeshndl, 'Parent');
0154 
0155 oldunits = get([figurehndl, axeshndl], 'Units');
0156 set([figurehndl, axeshndl], 'Units', 'Pixel');
0157 
0158 axes_relative = get(axeshndl, 'Position');
0159 figure_pos = get(figurehndl, 'Position');
0160 
0161 set(figurehndl, 'Units', oldunits{1});
0162 set(axeshndl, 'Units', oldunits{2});
0163 
0164 % Offsets to get near default axis orientation.  Won't do the right thing if the
0165 % axes have been rotated . . . its an imperfect world.
0166 offset = axes_relative(3:4);
0167 switch(handles.switchaxis),  
0168     case 'x',
0169         offset = offset .* [0.75 0];
0170     case 'y',
0171         offset = offset .* [-0.10 0.10];
0172     case 'z',
0173         offset = offset .* [0 0.75];
0174 end
0175 pos = figure_pos + axes_relative;
0176 pos = pos(1:2) + offset;
0177 
0178 
0179 function handles = param1_bounds_check(handles, param1)
0180 % Checks bounds on 'param1', clipping to [1,maxparam] if necessary, then
0181 % sets the param1 edit box to reflect the clipped value.
0182 % Note that this function also sets the 'handles.oldparam' to the newly
0183 % validated string but does NOT save the modified 'handles'.  Make sure to
0184 % accept 'handles' as an output and to save if you want to remember the
0185 % old value (useful for recovering from user typos).
0186 if (param1 < 1)
0187     param1 = '1';
0188 elseif (param1 > handles.maxparam)
0189     param1 = num2str(handles.maxparam);
0190 else
0191     param1 = num2str(param1);
0192 end
0193 set(handles.edit_param1, 'String', param1);
0194 handles.oldparam = param1;
0195 
0196     
0197 function alter_data(handles)
0198 %%% NEEDS COMMENTS!
0199 choices = get(handles.popup_datatype, 'String');
0200 choice = choices{get(handles.popup_datatype, 'Value')};
0201 param1 = str2double(get(handles.edit_param1, 'String'));
0202 ssg = guidata(handles.axes_handle);
0203 axname = handles.switchaxis;  % shorthand
0204 
0205 % First get the relevant data values ...
0206 switch (choice), 
0207     case 'Signal', 
0208         vector = ssg.ss_object.waveforms(:,param1);
0209       
0210     case 'PC', % (for principal components, we might need to compute the first time)
0211         if (~isfield(ssg.ss_object, 'pca'))
0212             parentfig = get(handles.axes_handle, 'Parent');  oldptr = get(parentfig, 'Pointer');
0213             set([handles.figure_ssg_featureselect, parentfig], 'Pointer', 'watch');
0214 
0215             [pca.scores,pca.u,pca.s,pca.v] = pcasvd(ssg.ss_object.waveforms);
0216             ssg.ss_object.pca = pca;
0217             
0218             set(handles.figure_ssg_featureselect, 'Pointer', 'arrow');
0219             set(parentfig, 'Pointer', oldptr);
0220         end
0221         vector = ssg.ss_object.pca.scores(:,param1);
0222         
0223     case 'Cluster #',
0224         vector = ssg.ss_assigns;
0225         
0226     case 'Event Time',
0227         vector = ssg.ss_object.spiketimes;
0228         
0229     case 'ISI Preceding',
0230         vector = [NaN; diff(ssg.ss_object.spiketimes)];
0231         
0232     case 'Total Energy',
0233         vector = sum(ssg.ss_object.waveforms.^2, 2);
0234         
0235     case {'Height', 'Width'},  % again, we might need to compute these the first time they're used
0236         if (~isfield(ssg.ss_object, 'heightwidth'))
0237             [hw.height, hw.width] = thresholded_peaks(ssg.ss_object);
0238             ssg.ss_object.heightwidth = hw;
0239         end
0240         vector = ssg.ss_object.heightwidth.(lower(choice));
0241         
0242 end 
0243 ssg.([axname 'choice']) = choice;
0244 ssg.([axname 'param1']) = num2str(param1);
0245 
0246 % ... then feed them to the appropriate group of data.
0247 for gp = 1:length(ssg.group_handles)
0248     set(ssg.group_handles(gp), [axname 'Data'], vector(ssg.group_indices{gp}));
0249 end
0250 
0251 % Reset the camera in case the axis scales have changed dramatically.
0252 haxes = handles.axes_handle;
0253 axis(haxes, 'tight');
0254 if ~isempty(get(ssg.group_handles(1), 'ZData'))
0255     campos(haxes,'auto'); camtarget(haxes,'auto');  view(haxes,3);
0256     camva(haxes,'auto');  camup(haxes,'auto');      camva(haxes,camva(haxes)); 
0257 end
0258 daspect(haxes,'auto');   daspect(haxes,daspect(haxes));
0259 
0260 % Change the axis labels to reflect the new reality.
0261 label = ssg.([axname 'choice']);
0262 if (strcmp(get(handles.edit_param1, 'Enable'), 'on'))
0263     label = [label ssg.([axname 'param1'])];
0264 end
0265 set(get(haxes, [axname 'Label']), 'String', label);
0266 
0267 % Store guidata's and raise this axis control to the top.
0268 guidata(handles.axes_handle, ssg);
0269 guidata(handles.figure_ssg_featureselect, handles);
0270 figure(handles.figure_ssg_featureselect);

Generated on Fri 15-Aug-2008 11:35:42 by m2html © 2003