function varargout = optostim(varargin) % OPTOSTIM Application M-file for optostim.fig % FIG = OPTOSTIM launch optostim GUI. % OPTOSTIM('callback_name', ...) invoke the named callback. % Last Modified by GUIDE v2.0 15-Jun-2005 15:05:46 if nargin == 0 % LAUNCH GUI fig = openfig(mfilename,'reuse'); % Use system color scheme for figure: set(fig,'Color',get(0,'defaultUicontrolBackgroundColor')); % Generate a structure of handles to pass to callbacks, and store it. handles = guihandles(fig); % voltages used to put the beam out of sight handles.beam_off = [-0.5 -0.5] ; % valid range of voltages handles.voltage_range = [0.0 9.9]; handles.center = [ 0 0 ]; handles.image = 'none'; handles.camera_name = 'none'; handles.blank = imread('optostim_wait.tif'); guidata(fig, handles); if nargout > 0 varargout{1} = fig; end elseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACK try if (nargout) [varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard else feval(varargin{:}); % FEVAL switchyard end catch disp(lasterr); end end % ----------------------------------------------------------- function changed_handles = selectCamera(handles, camera_name) groupEnable(handles, 'off'); handles.camera_name = camera_name; handles.sizes = load(['optostim_' camera_name '.ddt']); % figure out the convertion from camera pixels to physical size handles.limits = [handles.sizes(1,1)*handles.sizes(1,3) handles.sizes(1,2)*handles.sizes(1,4) ]; handles.x_scale = (1:handles.sizes(1,1))*handles.sizes(1,3); handles.y_scale = (1:handles.sizes(1,2))*handles.sizes(1,4); handles.area = [0 0 handles.limits]; updateImage(handles,0); groupEnable(handles, 'on'); changed_handles = handles; %-------------------------------------------------------------------- function groupEnable(handles, mode) if strcmp(mode, 'off') == 0 set(handles.pushbuttonReset, 'Enable', 'off'); else set(handles.pushbuttonReset, 'Enable', 'on'); end set(handles.pushbuttonExecute, 'Enable', mode); set(handles.togglebuttonMoveToClick, 'Enable', mode); set(handles.pushbuttonRefreshImage, 'Enable', mode); set(handles.pushbuttonScan, 'Enable', mode); set(handles.togglebuttonSetLocations, 'Enable', mode); set(handles.togglebuttonPulseOnClick, 'Enable', mode); set(handles.editLength, 'Enable', mode); set(handles.editTail, 'Enable', mode); set(handles.editNumber, 'Enable', mode); set(handles.editSpacing, 'Enable', mode); set(handles.editLabel, 'Enable', mode); set(handles.checkboxSave0, 'Enable', mode); set(handles.checkboxSave1, 'Enable', mode); set(handles.radiobuttonPlot0, 'Enable', mode); set(handles.radiobuttonPlot1, 'Enable', mode); set(handles.editFrequency, 'Enable', mode); set(handles.pushbuttonCalibrateX, 'Enable', mode); set(handles.pushbuttonCalibrateY, 'Enable', mode); set(handles.togglebuttonCenter, 'Enable', mode); set(handles.togglebuttonArea, 'Enable', mode); set(handles.editFront, 'Enable', mode); set(handles.pushbuttonRollback, 'Enable', mode); set(handles.pushbuttonCompare, 'Enable', mode); set(handles.pushbuttonRandom, 'Enable', mode); set(handles.editRandom, 'Enable', mode); set(handles.editCounter, 'Enable', mode); set(handles.editResolution, 'Enable', mode); set(handles.editThreshold, 'Enable', mode); set(handles.editRepeat, 'Enable', mode); set(handles.editDelay, 'Enable', mode); set(handles.editCycles, 'Enable', mode); set(handles.editTWait, 'Enable', mode); set(handles.editWindow, 'Enable', mode); set(handles.pushbuttonRepeat, 'Enable', mode); set(handles.pushbuttonScale, 'Enable', mode); set(handles.editRate, 'Enable', mode); set(handles.checkboxDelay, 'Enable', mode); set(handles.checkboxBackground, 'Enable', mode); set(handles.checkboxMeanPulse, 'Enable', mode); set(handles.checkboxMaxPulse, 'Enable', mode); set(handles.checkboxMinPulse, 'Enable', mode); set(handles.checkboxMaxTail, 'Enable', mode); set(handles.checkboxMeanTail, 'Enable', mode); set(handles.checkboxMinTail, 'Enable', mode); set(handles.editTLength, 'Enable', mode); set(handles.editRatio, 'Enable', mode); function voltages = coords_to_voltages(handles, coords) k = handles.sizes ; if coords(1) == -1 & coords(2) == -1 voltages = handles.beam_off; else % voltages = y_0 + k_y * tan ( (x-x_0)/k_x ) ch_1 = k(3,4) * tan((coords(2)-k(3,1))/k(3,2)) + k(3,3) ; ch_2 = k(2,4) * tan((coords(1)-k(2,1))/k(2,2)) + k(2,3) ; if ch_1 < handles.voltage_range(1) | ch_1 > handles.voltage_range(2) | ch_2 < handles.voltage_range(1) | ch_2 > handles.voltage_range(2) disp(sprintf('warning: voltage out of range for position (%f,%f)', coords(1), coords(2))); voltages = handles.beam_off; else voltages = [ch_1 ch_2]; end end %| ABOUT CALLBACKS: %| GUIDE automatically appends subfunction prototypes to this file, and %| sets objects' callback properties to call them through the FEVAL %| switchyard above. This comment describes that mechanism. %| %| Each callback subfunction declaration has the following form: %| (H, EVENTDATA, HANDLES, VARARGIN) %| %| The subfunction name is composed using the object's Tag and the %| callback type separated by '_', e.g. 'slider2_Callback', %| 'figure1_CloseRequestFcn', 'axis1_ButtondownFcn'. %| %| H is the callback object's handle (obtained using GCBO). %| %| EVENTDATA is empty, but reserved for future use. %| %| HANDLES is a structure containing handles of components in GUI using %| tags as fieldnames, e.g. handles.figure1, handles.slider2. This %| structure is created at GUI startup using GUIHANDLES and stored in %| the figure's application data using GUIDATA. A copy of the structure %| is passed to each callback. You can store additional information in %| this structure at GUI startup, and you can change the structure %| during callbacks. Call guidata(h, handles) after changing your %| copy to replace the stored original so that subsequent callbacks see %| the updates. Type "help guihandles" and "help guidata" for more %| information. %| %| VARARGIN contains any extra arguments you have passed to the %| callback. Specify the extra arguments by editing the callback %| property in the inspector. By default, GUIDE sets the property to: %| ('', gcbo, [], guidata(gcbo)) %| Add any extra arguments after the last argument, before the final %| closing parenthesis. % ------------------------------------------------------------------------- function result = updateImage(handles, option) axes(handles.axesView) ; if strcmp(handles.camera_name, 'scion') == 1 if option ~= 2 imagesc(handles.blank); drawnow; end image_data = scion_read'; elseif strcmp(handles.camera_name,'sensicam') == 1 if option ~= 2 imagesc(handles.blank); drawnow; end image_data = senQE(30)'; else disp(sprintf('ERROR: updateImage(): invalid camera name: %s', handles.camera_name)); beep; result = -1; return end pause(0.1); if option == -1 % scale calibration, use pix for axes: imagesc(image_data); colormap jet; result = size(image_data); else imagesc(handles.x_scale, handles.y_scale, image_data); colormap gray; if option == 1 % newCenter, image to be saved, return filename filename = [date '_' get(handles.editCounter,'String') '_image']; x_scale = handles.x_scale; y_scale = handles.y_scale; save(filename, 'image_data', 'x_scale', 'y_scale'); result = filename; else result = 0; end end % -------------------------------------------------------------------- function varargout = pushbuttonRefreshImage_Callback(h, eventdata, handles, varargin) groupEnable(handles, 'off'); if strcmp(handles.image,'none') beep; disp('Image data missing. Acquiring new image ..'); updateImage(handles,0); else image = load(handles.image); axes(handles.axesView) ; imagesc(image.x_scale, image.y_scale, image.image_data); end groupEnable(handles, 'on'); % -------------------------------------------------------------------- function varargout = editLength_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = editSpacing_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = editNumber_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = editMeasure_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = togglebuttonSetLocations_Callback(h, eventdata, handles, varargin) groupEnable(handles, 'off'); number_of_places = str2num(get(handles.editNumber, 'String')); axes(handles.axesView) ; window = str2num(get(handles.editWindow, 'String')); content_string = 'locations [ '; for index = 1:number_of_places disp(sprintf('Waiting for location %d ..',index)); if window > 0 figure(window) end location = ginput(1); if location(1) >= 0 & location(1) <= handles.limits(1) & location(2) >= 0 & location(2) <= handles.limits(2) % add to matrix: location = round(location); places(index,:) = location ; % add to plots: axes(handles.axesView) ; hold on plot(places(:,1), places(:,2), 'mo','MarkerSize',10, 'LineWidth',2) hold off if window > 0 figure(window) hold on plot(places(:,1), places(:,2), 'mo','MarkerSize',10, 'LineWidth',2) hold off end % add to log: content_string = sprintf('%s %d %d ;', content_string, location(1), location(2)); else disp(sprintf('warning: click %d out of range',index)) end end content_string = sprintf('%s ]', content_string); % remember 'places' in 'handles': handles.places = places; guidata(gcbo, handles); % save places for reference: filename = [date '_' get(handles.editCounter,'String') '_locations.dat']; save(filename, 'places', '-ascii'); writeLog(handles, content_string); % done: groupEnable(handles, 'on'); set(handles.togglebuttonSetLocations, 'Value', 0); % -------------------------------------------------------------------- function varargout = editFrequency_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = togglebuttonMoveToClick_Callback(h, eventdata, handles, varargin) groupEnable(handles, 'off'); if updateImage(handles,0) == -1 return end disp('Make sure ND filter is in!'); disp('Mouse-click the location ..'); frequency = str2num(get(handles.editFrequency, 'String')); while get(handles.togglebuttonMoveToClick, 'Value') == 1 location = ginput(1); if location(1) >= 0 & location(1) <= handles.limits(1) & location(2) >= 0 & location(2) <= handles.limits(2) voltages = coords_to_voltages(handles,location); inputs = aoi(repmat(voltages,10,1), [1], frequency); if updateImage(handles,2) == -1 return end else disp('Check-beam mode stopped') inputs = aoi(repmat(handles.beam_off,10,1), [1], frequency); break end end updateImage(handles,2); groupEnable(handles, 'on'); set(handles.togglebuttonMoveToClick, 'Value', 0); % -------------------------------------------------------------------- function varargout = togglebuttonPulseOnClick_Callback(h, eventdata, handles, varargin) groupEnable(handles, 'off'); frequency = str2num(get(handles.editFrequency, 'String')); pulse_length = str2num(get(handles.editLength, 'String')); background_length = str2num(get(handles.editFront, 'String')); tail_length = str2num(get(handles.editTail,'String')); pulse_samples = round(pulse_length * frequency / 1000) ; background_samples = round(background_length * frequency / 1000) ; capture_samples = round(tail_length * frequency / 1000) ; total_samples = background_samples+pulse_samples+capture_samples; time_values = ((1:total_samples)* 1000 / frequency)' ; threshold = str2num(get(handles.editThreshold, 'String'))/1000; super_thr = zeros(0,2); sub_thr = zeros(0,2); which = get(handles.radiobuttonPlot1,'Value') + 1 ; % which input channel to check for threshold hot_map = hot(64); delay_range = str2num(get(handles.editTail,'String')) * frequency / 1000 / 2 ; % scale delays colormap for half the tail disp('Mouse-click the target for the illumination pulse..') while 1 == 1 axes(handles.axesView) ; hold on location = ginput(1); if location(1) >= 0 & location(1) <= handles.limits(1) & location(2) >= 0 & location(2) <= handles.limits(2) % do pulse: voltages = coords_to_voltages(handles,location); outputs = [ repmat(handles.beam_off,background_samples,1) ; repmat(voltages,pulse_samples,1) ; repmat(handles.beam_off,capture_samples,1)]; inputs = aoi(outputs, [ 0 1 ], frequency); % try to report action spikes: facecolor = [0 0.5 0.5]; [max_value, max_sample] = max(inputs(:,which)); if max_value - mean(inputs(1:background_samples,which)) > threshold & max_sample > background_samples+pulse_samples beep super_thr = [ super_thr ; location ]; heat = round((background_samples+pulse_samples+delay_range - max_sample)*64/delay_range); if heat > 0 facecolor = hot_map(heat,:); end else sub_thr = [ sub_thr ; location ]; end plot(location(:,1), location(:,2), 'ro', 'MarkerFaceColor',facecolor,'MarkerSize',10) hold off coords_abs = round(location); details_string = sprintf('pulse\t[%3d %3d]',coords_abs(1), coords_abs(2)); handles = guidata(gcbo); % needs the updated values of the counter process_inputs(handles, inputs, time_values, details_string); else disp('Test-pulse mode stopped') % save overall results if required: save0 = get(handles.checkboxSave0,'Value'); save1 = get(handles.checkboxSave1,'Value'); if ( save0 == 1 | save1 == 1 ) & size(sub_thr,1) > 3 & size(super_thr,1) > 3 filename = [date '_' get(handles.editCounter,'String') '_super.dat']; save(filename, 'super_thr', '-ascii'); filename = [date '_' get(handles.editCounter,'String') '_sub.dat']; save(filename, 'sub_thr', '-ascii'); writeLog(handles, ['locations saved: ' num2str(size(super_thr,1)) ':' num2str(size(sub_thr,1))]); end break end end hold off groupEnable(handles, 'on'); set(handles.togglebuttonPulseOnClick, 'Value', 0); % -------------------------------------------------------------------- function increment_counter(handles) counter = str2num(get(handles.editCounter,'String')) + 1; new_counter_string = num2str(counter); if (counter < 10) new_counter_string = ['00' new_counter_string]; elseif (counter < 100) new_counter_string = ['0' new_counter_string]; end set(handles.editCounter, 'String', new_counter_string); % -------------------------------------------------------------------- function writeLog(handles, content) filename = [date '_optostim.log']; fid = fopen(filename,'a'); timestamp = round(clock); time = sprintf('%02d:%02d:%02d',timestamp(4),timestamp(5),timestamp(6)); string_to_write = sprintf('%s\t%s\t%s', time, get(handles.editCounter,'String'), content); fprintf(fid,'%s\n', string_to_write); fclose(fid); disp(string_to_write) increment_counter(handles); % -------------------------------------------------------------------- function varargout = pushbuttonExecute_Callback(h, eventdata, handles, varargin) % get user values: places = handles.places ; number_of_pulses = size(places,1); front_ms = str2num(get(handles.editFront,'String')); pulse_ms = str2num(get(handles.editLength,'String')); period_ms = str2num(get(handles.editSpacing,'String')); spacing_ms = period_ms - pulse_ms; if spacing_ms < 0 beep; disp('error: requested pulse is longer than the period'); return end total_length_ms = str2num(get(handles.editTLength,'String')); tail_ms = total_length_ms - front_ms - (pulse_ms+spacing_ms) * number_of_pulses; if tail_ms < 0 beep; disp(sprintf('error: %.1fms missing in total allowed length',-tail_ms)); return end frequency = str2num(get(handles.editFrequency,'String')); % compile trajectory one movement per row: for index = 1:number_of_pulses trajectory(index*2-1,:) = [ places(index,:) pulse_ms]; trajectory(index*2,:) = [ -1 -1 spacing_ms ]; end trajectory = [ -1 -1 front_ms ; trajectory ; -1 -1 tail_ms ]; samples_per_ms = round(frequency/1000); outputs = zeros(0,2); for index = 1:size(trajectory,1) outputs = [outputs ; repmat(coords_to_voltages(handles, trajectory(index,1:2)),round(trajectory(index,3)*samples_per_ms),1)]; end inputs = aoi(outputs, [0 1], frequency); time_values = ((1:size(outputs,1))*1000/frequency)'; details_string = ['sequence of ' num2str(number_of_pulses)]; process_inputs(handles, inputs, time_values, details_string); % ------------------------------------------------------------------------------ function process_inputs(handles, inputs, time_values, details_string) which = get(handles.radiobuttonPlot1,'Value'); axes(handles.axesPlot) if which == 0 plot(time_values, inputs(:,1),'b'); else plot(time_values, inputs(:,2),'r'); end %set(trace_plot, 'ydata', input_data); grid on save0 = get(handles.checkboxSave0,'Value'); save1 = get(handles.checkboxSave1,'Value'); if save0 == 1 | save1 == 1 filename = [date '_' get(handles.editCounter,'String') '_trace']; save(filename, 'time_values'); saved = 0; if save0 == 1 ch0 = inputs(:,1); save(filename, 'ch0', '-append'); saved = 'CH.0'; end if save1 == 1 ch1 = inputs(:,2); save(filename, 'ch1', '-append'); if (ischar(saved)) saved = 'both'; else saved = 'CH.1'; end end writeLog(handles, sprintf('%s\t%s\t%s', saved, details_string, get(handles.editLabel,'String'))); end % -------------------------------------------------------------------- function varargout = editTarget0_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = editTarget1_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = checkboxSave0_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = checkboxSave1_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = editLabel0_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = editLabel1_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = pushbuttonCalibrateX_Callback(h, eventdata, handles, varargin) groupEnable(handles, 'off'); % get the data to fit axes(handles.axesView) ; frequency = str2num(get(handles.editFrequency, 'String')); index = 0 ; start = 100; if strcmp(handles.camera_name, 'sensicam') == 1 start = 400; end disp('Mouse-click the illuminated spot ..'); for x = start:100:handles.limits(1) voltages = coords_to_voltages(handles, [ x handles.limits(2)/2 ]); inputs = aoi(repmat(voltages,10,1), [1], frequency); if updateImage(handles,2) == -1 return end location = ginput(1); index = index + 1 ; data(index,:) = [ location(1) voltages(2) ] ; end old_params_main = handles.sizes(2,:); new_params_main = optostim_calibrate(data, old_params_main); handles.sizes(2,:) = new_params_main; guidata(gcbo, handles); saveCalibration(handles); groupEnable(handles, 'on'); % -------------------------------------------------------------------- function saveCalibration(handles) filename = ['optostim_' handles.camera_name '.ddt']; data_to_save = handles.sizes; save(filename, 'data_to_save', '-ascii'); % -------------------------------------------------------------------- function varargout = pushbuttonCalibrateY_Callback(h, eventdata, handles, varargin) groupEnable(handles, 'off'); % get the data to fit axes(handles.axesView) ; frequency = str2num(get(handles.editFrequency, 'String')); index = 0 ; disp('Mouse-click the illuminated spot ..'); for y = 100:100:handles.limits(2) voltages = coords_to_voltages(handles, [ handles.limits(1)/2 y ]); inputs = aoi(repmat(voltages,10,1), [1], frequency); if updateImage(handles,2) == -1 return end location = ginput(1); index = index + 1 ; data(index,:) = [ location(2) voltages(1) ] ; end old_params_main = handles.sizes(3,:); new_params_main = optostim_calibrate(data, old_params_main); handles.sizes(3,:) = new_params_main; guidata(gcbo, handles); saveCalibration(handles); groupEnable(handles, 'on'); % -------------------------------------------------------------------- function varargout = editFront_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = togglebuttonCenter_Callback(h, eventdata, handles, varargin) groupEnable(handles, 'off'); result = updateImage(handles,1); if ischar(result) == 0 | result == -1 return end handles.image = result; % get new center disp('Mouse-click the new ref point ..'); pointed = round(ginput(1)); content = sprintf('reference\t[%3d %3d]\t%s\n', pointed(1), pointed(2), get(handles.editLabel,'String')); writeLog(handles, content); handles.center = pointed; guidata(gcbo, handles); groupEnable(handles, 'on'); set(handles.togglebuttonCenter, 'Value', 0); % -------------------------------------------------------------------- function varargout = pushbuttonScan_Callback(h, eventdata, handles, varargin) pulse_ms = str2num(get(handles.editLength,'String')); front_ms = str2num(get(handles.editFront,'String')); tail_ms = str2num(get(handles.editTail,'String')); delay_ms = str2num(get(handles.editDelay, 'String')); threshold_V = str2num(get(handles.editThreshold, 'String'))/1000; delay_range_ms = str2num(get(handles.editTail,'String'))/2; %scale delays colormap to half the tail % make timing: frequency = str2num(get(handles.editFrequency,'String')); samples_per_ms = round(frequency/1000); samples_before = front_ms * samples_per_ms ; samples_pulse = pulse_ms * samples_per_ms ; samples_after = tail_ms * samples_per_ms ; total_samples = samples_before + samples_pulse + samples_after; time_values = (1:total_samples)/samples_per_ms ; % omit front to exclude edge effects: skip_background = round(samples_before/4); skip_pulse = round(samples_pulse/10); % define grid: resolution = str2num(get(handles.editResolution, 'String')); area = round(handles.area); x_ticks = area(1):resolution:(area(1)+area(3)); y_ticks = area(2):resolution:(area(2)+area(4)); % prepare to plot traces without rescaling: axes(handles.axesPlot) ylimits = get(gca,'ylim'); trace_plot = plot(time_values, repmat(threshold_V,total_samples,1)); set(gca,'ylim',ylimits); set(gcf,'DoubleBuffer','on') % prepare empty matrices: if (get(handles.checkboxMaxTail, 'Value') == 1) max_tail = 1; max_tail_values = zeros(size(y_ticks,2), size(x_ticks,2)); else max_tail = 0; end if (get(handles.checkboxMaxPulse, 'Value') == 1) max_pulse = 1; max_pulse_values = zeros(size(y_ticks,2), size(x_ticks,2)); else max_pulse = 0; end if (get(handles.checkboxMinTail, 'Value') == 1) min_tail = 1; min_tail_values = zeros(size(y_ticks,2), size(x_ticks,2)); else min_tail = 0; end if (get(handles.checkboxMinPulse, 'Value') == 1) min_pulse = 1; min_pulse_values = zeros(size(y_ticks,2), size(x_ticks,2)); else min_pulse = 0; end if (get(handles.checkboxMeanTail, 'Value') == 1) mean_tail = 1; mean_tail_values = zeros(size(y_ticks,2), size(x_ticks,2)); else mean_tail = 0; end if (get(handles.checkboxMeanPulse, 'Value') == 1) mean_pulse = 1; mean_pulse_values = zeros(size(y_ticks,2), size(x_ticks,2)); else mean_pulse = 0; end if (get(handles.checkboxBackground, 'Value') == 1) background = 1; background_values = zeros(size(y_ticks,2), size(x_ticks,2)); else background = 0; end if (get(handles.checkboxDelay, 'Value') == 1) delay = 1; delay_values = - ones(size(y_ticks,2), size(x_ticks,2)) * tail_ms ; else delay = 0; end if max_tail + mean_tail + min_tail + delay + background + min_pulse + max_pulse + mean_pulse == 0 beep disp('ERROR: scan data to be saved not specified') return end groupEnable(handles, 'off'); disp('scanning the area, please wait ..'); which = get(handles.checkboxSave1,'Value'); % analize CH0 input by default but CH1 when checked x_index = 0; super_thr = zeros(0,2); delay_range = delay_range_ms * frequency / 1000 ; for x = x_ticks x_index = x_index + 1; y_index = 0; for y = y_ticks y_index = y_index + 1; voltages = coords_to_voltages(handles,[x y]); outputs = [ repmat(handles.beam_off,samples_before,1) ; repmat(voltages,samples_pulse,1) ; repmat(handles.beam_off,samples_after,1)]; input_data = aoi(outputs, [which], frequency); set(trace_plot, 'ydata', input_data); if which == 0 set(trace_plot,'color','b'); else set(trace_plot,'color','r'); end grid on facecolor = [0 0 0]; background_level = mean(input_data(skip_background:samples_before)) ; if background == 1 background_values(y_index,x_index) = background_level; end if max_tail == 1 | min_tail == 1 | mean_tail == 1 | delay == 1 [ max_tail_value, max_index] = max(input_data(samples_before+samples_pulse:total_samples)); if max_tail_value - background_level > threshold_V % adjust marker color: brightness = 1-max_index/delay_range; if brightness > 0 facecolor = repmat(brightness,1,3); end super_thr = [ super_thr ; x y ]; % audiosignal beep; if delay == 1 delay_values(y_index,x_index) = - max_index / samples_per_ms ; end end if max_tail == 1 max_tail_values(y_index,x_index) = max_tail_value; end if min_tail == 1 min_tail_values(y_index,x_index) = min(input_data(samples_before+samples_pulse+skip_pulse:total_samples)); end if mean_tail == 1 mean_tail_values(y_index,x_index) = mean(input_data(samples_before+samples_pulse+skip_pulse:total_samples)) ; end end if mean_pulse == 1 mean_pulse_values(y_index,x_index) = mean(input_data(samples_before+skip_pulse:samples_before+samples_pulse)) ; end if max_pulse == 1 max_pulse_values(y_index,x_index) = max(input_data(samples_before+skip_pulse:samples_before+samples_pulse)) ; end if min_pulse == 1 min_pulse_values(y_index,x_index) = min(input_data(samples_before+skip_pulse:samples_before+samples_pulse)) ; end axes(handles.axesView) hold on plot(x, y, 'go', 'MarkerFaceColor',facecolor) hold off % allow user to stop the scan: if (exist('stop') == 2) unix('rm stop'); disp('stopped by user'); groupEnable(handles, 'on'); return end pause(delay_ms/1000); end % end of column end % end of scan % save results according to checkboxes filename = [date '_' get(handles.editCounter,'String') '_scan']; save(filename, 'x_ticks', 'y_ticks'); if max_tail == 1 save(filename , 'max_tail_values', '-append'); figure(11) imagesc(x_ticks', y_ticks', max_tail_values); colormap hot; title('Max after pulse') % also save spike locations: save(filename, 'super_thr', '-append'); end if min_tail == 1 save( filename, 'min_tail_values', '-append'); figure(12) imagesc(x_ticks', y_ticks', min_tail_values); colormap hot; title('Min after pulse') end if mean_tail == 1 save( filename, 'mean_tail_values', '-append'); figure(13) imagesc(x_ticks', y_ticks', mean_tail_values); colormap hot; title('Mean after pulse') end if background == 1 save(filename, 'background_values', '-append'); figure(14) imagesc(x_ticks', y_ticks', background_values); colormap hot; title('Background before pulse') end if delay == 1 save(filename , 'delay_values', '-append'); figure(15) imagesc(x_ticks', y_ticks', delay_values, [-delay_range_ms 0]); colormap hot; title(sprintf('Delays <%dms after pulse',delay_range_ms)) end if max_pulse == 1 save(filename, 'max_pulse_values', '-append'); figure(16) imagesc(x_ticks', y_ticks', max_pulse_values); colormap gray; title('Max during pulse') end if min_pulse == 1 save(filename, 'min_pulse_values', '-append'); figure(17) imagesc(x_ticks', y_ticks', min_pulse_values); colormap gray; title('Min during pulse') end if mean_pulse == 1 save(filename, 'mean_pulse_values', '-append'); figure(18) imagesc(x_ticks', y_ticks', mean_pulse_values); colormap gray; title('Mean during pulse') end scan_info = sprintf('scan\t[%d %d]:%d:[%d %d]\t%s', area(1), area(2), resolution, area(1)+area(3), area(2)+area(4), get(handles.editLabel, 'String')); writeLog(handles, scan_info); groupEnable(handles, 'on'); % -------------------------------------------------------------------- function varargout = editResolution_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = editCounter_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = pushbuttonRollback_Callback(h, eventdata, handles, varargin) counter = str2num(get(handles.editCounter,'String')) - 1; new_counter_string = num2str(counter); if (counter < 10) new_counter_string = ['00' new_counter_string]; elseif (counter < 100) new_counter_string = ['0' new_counter_string]; end set(handles.editCounter, 'String', new_counter_string); % -------------------------------------------------------------------- function varargout = radiobuttonPlot0_Callback(h, eventdata, handles, varargin) if (get(handles.radiobuttonPlot0, 'Value') == 1) set(handles.radiobuttonPlot1, 'Value', 0); end % -------------------------------------------------------------------- function varargout = radiobuttonPlot1_Callback(h, eventdata, handles, varargin) if (get(handles.radiobuttonPlot1, 'Value') == 1) set(handles.radiobuttonPlot0, 'Value', 0); end % -------------------------------------------------------------------- function varargout = edit14_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = togglebuttonArea_Callback(h, eventdata, handles, varargin) groupEnable(handles, 'off'); handles.area = getrect(handles.axesView); guidata(gcbo, handles); groupEnable(handles, 'on'); set(handles.togglebuttonArea, 'Value', 0); % -------------------------------------------------------------------- function varargout = editThreshold_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = pushbuttonReset_Callback(h, eventdata, handles, varargin) groupEnable(handles, 'on'); set(handles.togglebuttonMoveToClick, 'Value', 0); set(handles.togglebuttonPulseOnClick, 'Value', 0); set(handles.togglebuttonCenter, 'Value', 0); set(handles.togglebuttonArea, 'Value', 0); % -------------------------------------------------------------------- function varargout = editRepeat_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = pushbuttonRepeat_Callback(h, eventdata, handles, varargin) % get user values: places = handles.places; length = str2num(get(handles.editLength,'String')); period = str2num(get(handles.editSpacing,'String')); spacing = period - length; if spacing < 0 beep; disp('error: requested pulse is longer than the period'); return end total_pulses = size(places,1); total_duration_ms = (length + spacing) * total_pulses ; send_delay_ms = 100; % we assume extra time is spent to send the data back and forth save_delay_ms = 0; % saving data will make more delay: save0 = get(handles.checkboxSave0,'Value'); save1 = get(handles.checkboxSave1,'Value'); if save0 == 1 | save1 == 1 save_delay_ms = 100; end rate_sec = str2num(get(handles.editRate,'String')); pause_sec = rate_sec - (total_duration_ms + send_delay_ms + save_delay_ms) / 1000 ; if (pause_sec <= 0) beep disp(sprintf('Can not do the sequence at this rate:\n\tyour sequence length is %.1f seconds\n\tprocessing delay is %.f seconds', ... total_duration_ms/1000, (send_delay_ms + save_delay_ms)/1000)); return end samp_frequency = str2num(get(handles.editFrequency,'String')); total_executions = str2num(get(handles.editRepeat, 'String')); groupEnable(handles, 'off'); % compile trajectory one movement per row: for index = 1:total_pulses trajectory(index*2-1,:) = [ places(index,:) length]; trajectory(index*2,:) = [ -1 -1 spacing ]; end front_ms = str2num(get(handles.editFront,'String')); total_length_ms = str2num(get(handles.editTLength,'String')); tail_ms = total_length_ms - front_ms - (length+spacing) * total_pulses; if tail_ms < 0 beep; disp(sprintf('error: %.1fms missing in total allowed length',-tail_ms)); return end trajectory = [ -1 -1 front_ms ; trajectory ; -1 -1 tail_ms ]; samples_per_ms = round(samp_frequency/1000); % make output outputs = zeros(0,2); for index = 1:size(trajectory,1) outputs = [outputs ; repmat(coords_to_voltages(handles, trajectory(index,1:2)),trajectory(index,3)*samples_per_ms,1)]; end time_values = ((1:size(outputs,1))*1000/samp_frequency)'; % ready to execute tic % start stopwatch for repeat = 1:total_executions inputs = aoi(outputs, [0 1], samp_frequency); details_string = ['repeat ' num2str(repeat)]; process_inputs(handles, inputs, time_values, details_string); if repeat ~= total_executions pause(pause_sec); end %allow user to stop the execution: if (exist('stop') == 2) unix('rm stop'); disp('stopped by user'); groupEnable(handles, 'on'); hold off return end end time = toc; disp(sprintf('%d rounds done in %.1f seconds', ... total_executions, time)); groupEnable(handles, 'on'); % -------------------------------------------------------------------- function varargout = editDelay_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = editRate_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = checkboxMaxPulse_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = checkboxMaxTail_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = checkboxMinTail_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = checkboxMinPulse_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = checkboxMeanTail_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = checkboxMeanPulse_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = checkboxDelay_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = checkboxBackground_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = editTail_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = pushbuttonCompare_Callback(h, eventdata, handles, varargin) waiting_s = str2num(get(handles.editTWait, 'String')); cycles = str2num(get(handles.editCycles, 'String')); places = handles.places; frequency = str2num(get(handles.editFrequency, 'String')); pulse_length = str2num(get(handles.editLength, 'String')); background_length = str2num(get(handles.editFront, 'String')); tail_length = str2num(get(handles.editTail,'String')); total_time_ms = pulse_length + background_length + tail_length; % ms send_delay_ms = 100 ; % spent to send data save_delay_ms = 0 ; % spent to save data: save0 = get(handles.checkboxSave0,'Value'); save1 = get(handles.checkboxSave1,'Value'); if save0 == 1 | save1 == 1 save_delay_ms = 100; end waiting_sec = waiting_s - (total_time_ms + send_delay_ms + save_delay_ms) / 1000 ; if waiting_sec < 0 beep; disp(sprintf('error: wait: %.1fsec missing', -waiting_sec)); return end groupEnable(handles, 'off'); pulse_samples = round(pulse_length * frequency / 1000) ; background_samples = round(background_length * frequency / 1000) ; capture_samples = round(tail_length * frequency / 1000) ; time_values = ((1:(background_samples+pulse_samples+capture_samples))* 1000 / frequency)' ; threshold = str2num(get(handles.editThreshold, 'String'))/1000; which = get(handles.radiobuttonPlot1,'Value') + 1 ; % which input channel for cycle = 1:cycles for index = 1:size(places,1) voltages = coords_to_voltages(handles, places(index,:)); outputs = [ repmat(handles.beam_off,background_samples,1) ; repmat(voltages,pulse_samples,1) ; repmat(handles.beam_off,capture_samples,1)]; inputs = aoi(outputs, [0 1], frequency); if max(inputs(:,which)) - mean(inputs(1:background_samples,which)) > threshold beep end details_string = sprintf('compare %d:%d', cycle, index); handles = guidata(gcbo); % needs the updated values of the counter process_inputs(handles, inputs, time_values, details_string); pause(waiting_sec) % allow user to stop: if (exist('stop') == 2) unix('rm stop'); disp('stopped by user'); groupEnable(handles, 'on'); return end end end groupEnable(handles, 'on'); % -------------------------------------------------------------------- function varargout = editCycles_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = editTWait_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = editWindow_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = pushbuttonScale_Callback(h, eventdata, handles, varargin) groupEnable(handles, 'off'); pixels = updateImage(handles, -1); if pixels(1) == -1 return end disp('Select a 1mm x 1mm rectangle ..') one_mm = getrect(handles.axesView); scaling = [1000/one_mm(3) 1000/one_mm(4)]; handles.sizes(1,1:2) = [pixels(2) pixels(1)]; handles.limits = [handles.sizes(1,1)*scaling(1) handles.sizes(1,2)*scaling(2)]; handles.area = [0 0 handles.limits]; handles.x_scale = (1:handles.sizes(1,1))*scaling(1); handles.y_scale = (1:handles.sizes(1,2))*scaling(2); % also need to correct coord-to-voltage conversion params: handles.sizes(2,1:2) = handles.sizes(2,1:2)*scaling(1)/handles.sizes(1,3); handles.sizes(3,1:2) = handles.sizes(3,1:2)*scaling(2)/handles.sizes(1,4); handles.sizes(1,3:4) = [scaling(1) scaling(2)]; guidata(gcbo, handles); saveCalibration(handles); % plot again with corrected scale updateImage(handles,0); groupEnable(handles, 'on'); % -------------------------------------------------------------------- function varargout = radiobuttonScion_Callback(h, eventdata, handles, varargin) set(handles.radiobuttonScion, 'Value', 1); set(handles.radiobuttonSensicam, 'Value', 0); handles = selectCamera(handles,'scion'); writeLog(handles, sprintf('camera\t%s', 'scion')); groupEnable(handles, 'on'); set(handles.radiobuttonScion, 'Enable', 'of'); set(handles.radiobuttonSensicam, 'Enable', 'of'); guidata(gcbo, handles); % -------------------------------------------------------------------- function varargout = radiobuttonSensicam_Callback(h, eventdata, handles, varargin) set(handles.radiobuttonSensicam, 'Value', 1); set(handles.radiobuttonScion, 'Value', 0); handles = selectCamera(handles, 'sensicam'); writeLog(handles, sprintf('camera\t%s', 'sensicam')); groupEnable(handles, 'on'); set(handles.radiobuttonScion, 'Enable', 'of'); set(handles.radiobuttonSensicam, 'Enable', 'of'); guidata(gcbo, handles); % -------------------------------------------------------------------- function varargout = editTLength_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- % in case nearest history influences the result, randomize sequence and locations tests function varargout = pushbuttonRandom_Callback(h, eventdata, handles, varargin) places = handles.places ; % these are our locations of interest total_locations = size(places,1); front_ms = str2num(get(handles.editFront,'String')); pulse_ms = str2num(get(handles.editLength,'String')); % spacing_ms is the interfal between fronts of consecutive pulses period_ms = str2num(get(handles.editSpacing,'String')); spacing_ms = period_ms - pulse_ms; if spacing_ms < 1 beep; disp('error: requested period is too short'); return end % tail_ms is how much data to capture following the sequence % total_length_ms should at least fit the whole sequence total_length_ms = str2num(get(handles.editTLength,'String')); tail_ms = total_length_ms - front_ms - (pulse_ms+spacing_ms) * total_locations; if tail_ms < 0 beep; disp(sprintf('error: %.1fms missing in total allowed length',-tail_ms)); return end send_delay_ms = 100; % we assume extra time is spent to send the data back and forth save_delay_ms = 0; % saving data will make more delay: save0 = get(handles.checkboxSave0,'Value'); save1 = get(handles.checkboxSave1,'Value'); if save0 == 1 | save1 == 1 save_delay_ms = 100; else beep disp('channel to save not specified. exit.'); return end rate_sec = str2num(get(handles.editRate,'String')); pause_sec = rate_sec - (total_length_ms + send_delay_ms + save_delay_ms) / 1000 ; if (pause_sec <= 0) beep disp(sprintf('Can not do the sequence at this rate:\n\tyour sequence length is %.1f seconds\n\tprocessing delay is %.f seconds', ... total_length_ms/1000, (send_delay_ms + save_delay_ms)/1000)); return end groupEnable(handles, 'off'); frequency = str2num(get(handles.editFrequency,'String')); % put together a sequence for index = 1:total_locations trajectory(index*2-1,:) = [ places(index,:) pulse_ms]; trajectory(index*2,:) = [ -1 -1 spacing_ms ]; end trajectory = [ -1 -1 front_ms ; trajectory ; -1 -1 tail_ms ]; samples_per_ms = round(frequency/1000); sequence = zeros(0,2); for index = 1:size(trajectory,1) sequence = [sequence ; repmat(coords_to_voltages(handles, trajectory(index,1:2)),round(trajectory(index,3)*samples_per_ms),1)]; end time_values = ((1:size(sequence,1))*1000/frequency)'; locations = zeros(size(time_values,1),0); % put together all the locations: tail_ms = total_length_ms - front_ms - pulse_ms; for location_index = 1:total_locations trajectory = [ -1 -1 front_ms ; places(location_index,:) pulse_ms ; -1 -1 tail_ms ]; location = zeros(0,2); for index = 1:size(trajectory,1) location = [location ; repmat(coords_to_voltages(handles, trajectory(index,1:2)),round(trajectory(index,3)*samples_per_ms),1)]; end locations(:,location_index*2-1:location_index*2) = location; end % randomize tests: total_rounds = str2num(get(handles.editRandom,'String')); ratio = str2num(get(handles.editRatio, 'String')); disp(sprintf('doing %d random rounds',total_rounds)); for round = 1:total_rounds total_cases = total_locations+ratio; tests = (randperm(total_cases))'; filename = [date '_' get(handles.editCounter,'String') '_random.dat']; save(filename, 'tests', '-ascii'); for index = 1:total_cases current_location = tests(index); if current_location > total_locations inputs = aoi(sequence, [0 1], frequency); process_inputs(handles, inputs, time_values, sprintf('%d:all',round)); else inputs = aoi(locations(:,current_location*2-1:current_location*2)); process_inputs(handles, inputs, time_values, sprintf('%d:%d',round,current_location)); end pause(pause_sec); %allow user to stop the execution: if (exist('stop') == 2) unix('rm stop'); disp('stopped by user'); groupEnable(handles, 'on'); hold off return end end end groupEnable(handles, 'on'); % -------------------------------------------------------------------- function varargout = editRandom_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = editRatio_Callback(h, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = pushbuttonLog_Callback(h, eventdata, handles, varargin) writeLog(handles, get(handles.editLabel,'String'));