From 845711104072b0e31d920e6c04cf3e8bae2d10c8 Mon Sep 17 00:00:00 2001 From: ibwharri Date: Wed, 23 Oct 2019 13:06:43 -0400 Subject: [PATCH 1/9] Initial commit of new saturation experiment --- Modules/+Experiments/@Saturation/Saturation.m | 127 ++++++------------ Modules/+Experiments/@Saturation/instance.m | 20 +++ Modules/+Experiments/@Saturation/run.m | 110 ++++++++++----- 3 files changed, 136 insertions(+), 121 deletions(-) create mode 100644 Modules/+Experiments/@Saturation/instance.m diff --git a/Modules/+Experiments/@Saturation/Saturation.m b/Modules/+Experiments/@Saturation/Saturation.m index d859fde5e..de3894ef6 100644 --- a/Modules/+Experiments/@Saturation/Saturation.m +++ b/Modules/+Experiments/@Saturation/Saturation.m @@ -1,105 +1,62 @@ classdef Saturation < Modules.Experiment - % Continuously acquires data from the APD and Thorlabs PM100 power meter and plots them. - % User should rotate the polarizer/HWP. - + % Saturation changes intensity on a sample using a HWP (motorised or manually moved) and monitors the APD to measure saturation. Optionally also monitors a power meter to calibrate measurement with power. + + properties(SetObservable,GetObservable) + angles = Prefs.String('0','help_text', 'Matlab expression evaluated to find angles at which to measure APDs','units','degree','set','setAngle','allow_empty',false); + % motor_serial_number = Prefs.MulipleChoice('help_text','Serial number of APT motor controlling the HWP','choices',@Drivers.APTMotor.getAvailMotors) + exposure = Prefs.Double(100, 'help_text', 'Exposure time to measure APD counts','units','ms','min',0,'allow_nan',false) + motor_move_time = Prefs.Double(30, 'help_text', 'Maximum time allowed for the motor to move','units','s','min',0,'allow_nan',false) + motor_home_time = Prefs.Double(120, 'help_text', 'Maximum time allowed for the motor to home','units','s','min',0,'allow_nan',false) + motor_serial_number = @Drivers.APTMotor.getAvailMotors; + APD_line = Prefs.String('APD1','help_text','NiDAQ line to apd','allow_empty',false); + APD_sync_line = Prefs.String('CounterSync','help_text','NiDAQ synchronisation line','allow_empty',false); + + end properties - pm_data; - apd_data; - linein = 'APD1'; - lineout = 'CounterSync'; - acquire = false; % this tracks when the user wants to stop acquiring data - nsamples = 1; % number of samples the APD collects - wavelength = 532; - prefs = {'linein', 'lineout', 'acquire', 'nsamples', 'wavelength'}; + prefs = {'angles','exposure','motor_move_time','motor_home_time','motor_serial_number'}; % String representation of desired prefs + %show_prefs = {}; % Use for ordering and/or selecting which prefs to show in GUI + %readonly_prefs = {}; % CC will leave these as disabled in GUI (if in prefs/show_prefs) + end + properties(SetAccess=private,Hidden) + % Internal properties that should not be accessible by command line + % Advanced users should feel free to alter these properties (keep in mind methods: abort, GetData) + data = [] % Useful for saving data from run method + meta = [] % Useful to store meta data in run method + abort_request = false; % Flag that will be set to true upon abort. Use in run method! + angle_list end - properties (SetAccess=private) - PM100; - counter; + methods(Static) + % Static instance method is how to call this experiment + % This is a separate file + obj = instance() end - methods(Access=private) function obj = Saturation() - obj.loadPrefs; - obj.PM100 = Drivers.PM100.instance(); - obj.counter = Drivers.Counter.instance(obj.linein,obj.lineout); - end - end - - methods(Static) - function obj = instance() - mlock; - persistent Object - if isempty(Object) || ~isvalid(Object) - Object = Experiments.Saturation(); - end - obj = Object; + % Constructor (should not be accessible to command line!) + obj.loadPrefs; % Load prefs specified as obj.prefs end end methods - run(obj,status,managers,ax) - - function delete(obj) - obj.PM100.delete; - end + run(obj,status,managers,ax) % Main run method in separate file function abort(obj) - obj.acquire = false; + % Callback for when user presses abort in CC + obj.abort_request = true; end function dat = GetData(obj,stageManager,imagingManager) - % Saves the in v. out power, the excitation wavelength, and the dwell time and number of samples for the APD - dat.in_power = obj.pm_data; - dat.out_power = obj.apd_data; - - dat.in_wavelength = obj.PM100.get_wavelength(); - dat.dwell_time = obj.counter.dwell; - dat.nsamples = obj.nsamples; - end - - function settings(obj,panelH,~,~) - % Creates a button for the user to stop acquiring data once it has started and a place for user to set the - % measurement wavelength of the PM - spacing = 2.25; - - uicontrol(panelH,'style','text','string','Excitation Wavelength (nm):','horizontalalignment','right',... - 'units','characters','position',[0 spacing*3 25 1.25]); - - uicontrol(panelH,'style','edit','string',obj.wavelength,... - 'units','characters','callback',@obj.set_wl,... - 'horizontalalignment','left','position',[26 spacing*3 20 1.5]); - - uicontrol(panelH,'style','text','string','APD Dwell Time:','horizontalalignment','right',... - 'units','characters','position',[0 spacing*2 25 1.25]); - - uicontrol(panelH,'style','edit','string',obj.counter.dwell,... - 'units','characters','callback',@obj.set_dwell,... - 'horizontalalignment','left','position',[26 spacing*2 20 1.5]); - - uicontrol(panelH,'style','text','string','APD Number of Samples:','horizontalalignment','right',... - 'units','characters','position',[0 spacing 25 1.25]); - - uicontrol(panelH,'style','edit','string',obj.nsamples,... - 'units','characters','callback',@obj.set_nsample,... - 'horizontalalignment','left','position',[26 spacing 20 1.5]); - end - - function stop_acquire(obj, varargin) - % Callback function for the stop acquisition button - obj.acquire = false; - end - - function set_wl(obj, src, varargin) - obj.wavelength = str2num(get(src, 'string')); - end - - function set_dwell(obj, src, varargin) - obj.counter.dwell = str2num(get(src, 'string')); + % Callback for saving methods + meta = stageManager.position; + dat.data = obj.data; + dat.meta = obj.meta; end - function set_nsample(obj, src, varargin) - obj.nsamples = str2num(get(src, 'string')); + % Set methods allow validating property/pref set values + function setAngle(obj,val,pref) + angle_list = str2num(val); + obj.angles = val end end -end \ No newline at end of file +end diff --git a/Modules/+Experiments/@Saturation/instance.m b/Modules/+Experiments/@Saturation/instance.m new file mode 100644 index 000000000..c83e1d7a8 --- /dev/null +++ b/Modules/+Experiments/@Saturation/instance.m @@ -0,0 +1,20 @@ +function obj = instance(varargin) + % This file is what locks the instance in memory such that singleton + % can perform properly. + % For the most part, varargin will be empty, but if you know what you + % are doing, you can modify/use the input (just be aware of singleton_id) + mlock; + persistent Objects + if isempty(Objects) + Objects = Experiments.Saturation.empty(1,0); + end + for i = 1:length(Objects) + if isvalid(Objects(i)) && isequal(varargin,Objects(i).singleton_id) + obj = Objects(i); + return + end + end + obj = Experiments.Saturation(varargin{:}); + obj.singleton_id = varargin; + Objects(end+1) = obj; +end \ No newline at end of file diff --git a/Modules/+Experiments/@Saturation/run.m b/Modules/+Experiments/@Saturation/run.m index f4247b509..17eadf39e 100644 --- a/Modules/+Experiments/@Saturation/run.m +++ b/Modules/+Experiments/@Saturation/run.m @@ -1,39 +1,77 @@ -function run(obj,statusH,managers,ax) -statusWin = statusH.Parent.Parent; -button = findall(statusWin,'tag','AbortButton'); -newButton = add_button(button,'Stop Acquire'); -newButton.Callback = @obj.stop_acquire; -set(statusH,'string','Starting data acquisition...'); -drawnow; - -panel = ax.Parent; -delete(ax) -ax(1) = subplot(1,2,1,'parent',panel); -ax(2) = subplot(1,2,2,'parent',panel); - -% Flip the acquire boolean to true, set PM wavelength, and initialize data structures -obj.acquire = true; -obj.PM100.set_wavelength(obj.wavelength); -obj.pm_data = []; -obj.apd_data = []; - -% Continually collect and plot PM and APD data until the user hits "Stop acquisition", which flips -% obj.acquire to false -while obj.acquire - obj.pm_data = [obj.pm_data, obj.PM100.get_power('MW')]; - obj.apd_data = [obj.apd_data, obj.counter.singleShot(obj.counter.dwell, obj.nsamples)]; - [~, sort_index] = sort(obj.pm_data); - plot(ax(1),obj.pm_data(sort_index),obj.apd_data(sort_index)) - xlabel(ax(1),'Input Power (mW)') - ylabel(ax(1), 'Output Counts') - plot(ax(2),obj.pm_data) - ylabel(ax(2),'Input Power (mW)') - xlabel(ax(2), 'Collection Bins') +function run( obj,status,managers,ax ) + % Main run method (callback for CC run button) + obj.abort_request = false; + status.String = 'Experiment started'; + ctr = Drivers.Counter.instance(obj.APD_line, obj.APD_Sync_line); % Instantiate APD counter + drawnow; + + % Edit this to include meta data for this experimental run (saved in obj.GetData) + obj.meta.prefs = obj.prefs2struct; + obj.meta.position = managers.Stages.position; % Save current stage position (x,y,z); + obj.meta.angles = obj.angle_list; %Angles corresponding to each spectrum + + % Check that rot is not empty and valid + assert(~isempty(obj.rot) && isvalid(obj.rot),'Motor SN must be a valid number; motor handle may have been deleted. Check motor serial number/APT Config') + + % Setup graphics + y = NaN(1,n); + hold(ax,'on'); + plotH(1) = plot(obj.angle_list, y,'color', 'k','parent',ax); + current_freqH = plot(ax,NaN,NaN,'--r'); + ylabel(ax,'Counts (cps)'); + xlabel(ax,'Angle (\deg)'); + yyaxis(ax, 'left'); + + try + % Home rotation mount + if ~obj.rot.Homed + status.String = 'Homing motor'; drawnow; + + obj.rot.home(); + pause4Move(obj, obj.motor_home_time); + end + + % Sweep through polarisation and get spectra + Nangles = length(obj.angle_list); + obj.data.intensity = nan(1,Nangles) + for i = 1:Nangles + theta = obj.angle_list(i); + status.String = sprintf( 'Navigating to %g (%i/%i)', theta, ... + i, Nangles); drawnow; + obj.rot.move(theta); + pause4Move(obj, obj.motor_move_time); + status.String = sprintf( 'Measuring at %g (%i/%i)', theta, ... + i, Nangles); drawnow; + + % Measure count rate + obj.data.intensity(i) = ctr.singleShot(obj.exposure, 1) + + plotH(1).YData = obj.data.intensity; + drawnow; assert(~obj.abort_request,'User aborted'); + end + + %Get meta data from spectrum experiment + obj.meta.spec_meta = tempDat_nonvolatile; + obj.meta.diamondbase = tempDat.diamondbase; + + + + catch err + end + % CLEAN UP CODE % + if exist('err','var') + % HANDLE ERROR CODE % + rethrow(err) + end end -set(statusH, 'string', 'Acquisition complete!'); -% Set "abort" status if the data structures are empty -if isempty(obj.pm_data) && isempty(obj.apd_data) - set(statusH,'string','Aborted!'); +% Wait until motor stops moving, or timeout +function pause4Move(obj,maxTime) + t = tic; + while (obj.rot.Moving || ~obj.rot.Homed) && (toc(t) < maxTime) + drawnow + if toc(t) > maxTime + error('Motor timed out while moving') + end + end end -end \ No newline at end of file From 00eca7f9ae12cce29e09e8dd60cb02d5e18757c1 Mon Sep 17 00:00:00 2001 From: Isaac Harris Date: Wed, 23 Oct 2019 23:38:33 -0400 Subject: [PATCH 2/9] small bug fixes --- Modules/+Experiments/@Saturation/Saturation.m | 30 ++++++++++++++--- Modules/+Experiments/@Saturation/run.m | 32 +++++++++---------- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/Modules/+Experiments/@Saturation/Saturation.m b/Modules/+Experiments/@Saturation/Saturation.m index de3894ef6..80b8deab1 100644 --- a/Modules/+Experiments/@Saturation/Saturation.m +++ b/Modules/+Experiments/@Saturation/Saturation.m @@ -8,6 +8,7 @@ motor_move_time = Prefs.Double(30, 'help_text', 'Maximum time allowed for the motor to move','units','s','min',0,'allow_nan',false) motor_home_time = Prefs.Double(120, 'help_text', 'Maximum time allowed for the motor to home','units','s','min',0,'allow_nan',false) motor_serial_number = @Drivers.APTMotor.getAvailMotors; + %motor_serial_number = {27251915} APD_line = Prefs.String('APD1','help_text','NiDAQ line to apd','allow_empty',false); APD_sync_line = Prefs.String('CounterSync','help_text','NiDAQ synchronisation line','allow_empty',false); @@ -24,6 +25,7 @@ meta = [] % Useful to store meta data in run method abort_request = false; % Flag that will be set to true upon abort. Use in run method! angle_list + rot %Handle for rotation mount driver end methods(Static) @@ -48,15 +50,35 @@ function abort(obj) function dat = GetData(obj,stageManager,imagingManager) % Callback for saving methods - meta = stageManager.position; dat.data = obj.data; dat.meta = obj.meta; end % Set methods allow validating property/pref set values - function setAngle(obj,val,pref) - angle_list = str2num(val); - obj.angles = val + function newVal = setAngle(obj,val,pref) + obj.angle_list = str2num(val); + newVal = val; + end + + function set.motor_serial_number(obj,val) + val_as_double = str2double(val); % must be double to instantiate motor + + %assert(~isnan(val_as_double),'Motor SN must be a valid number.') + if isnan(val_as_double) + return + end + % Handle proper deleting of smotor driver object + delete(obj.rot); % Either motor obj or empty + obj.rot = []; + + obj.motor_serial_number = val; + if val_as_double == 0 + %Leave obj.rot empty if no serial number selected + return % Short circuit + end + + % Add new motor + obj.rot = Drivers.APTMotor.instance(val_as_double, [0 360]); end end end diff --git a/Modules/+Experiments/@Saturation/run.m b/Modules/+Experiments/@Saturation/run.m index 17eadf39e..350279fd0 100644 --- a/Modules/+Experiments/@Saturation/run.m +++ b/Modules/+Experiments/@Saturation/run.m @@ -2,7 +2,7 @@ function run( obj,status,managers,ax ) % Main run method (callback for CC run button) obj.abort_request = false; status.String = 'Experiment started'; - ctr = Drivers.Counter.instance(obj.APD_line, obj.APD_Sync_line); % Instantiate APD counter + ctr = Drivers.Counter.instance(obj.APD_line, obj.APD_sync_line); % Instantiate APD counter drawnow; % Edit this to include meta data for this experimental run (saved in obj.GetData) @@ -13,17 +13,21 @@ function run( obj,status,managers,ax ) % Check that rot is not empty and valid assert(~isempty(obj.rot) && isvalid(obj.rot),'Motor SN must be a valid number; motor handle may have been deleted. Check motor serial number/APT Config') + % Instantiate data object + Nangles = length(obj.angle_list); + obj.data.intensity = nan(1,Nangles); + % Setup graphics - y = NaN(1,n); + y = NaN(1,Nangles); hold(ax,'on'); plotH(1) = plot(obj.angle_list, y,'color', 'k','parent',ax); - current_freqH = plot(ax,NaN,NaN,'--r'); ylabel(ax,'Counts (cps)'); - xlabel(ax,'Angle (\deg)'); + xlabel(ax,['Angle (' char(176) ')']); yyaxis(ax, 'left'); try % Home rotation mount + if ~obj.rot.Homed status.String = 'Homing motor'; drawnow; @@ -32,30 +36,26 @@ function run( obj,status,managers,ax ) end % Sweep through polarisation and get spectra - Nangles = length(obj.angle_list); - obj.data.intensity = nan(1,Nangles) for i = 1:Nangles theta = obj.angle_list(i); - status.String = sprintf( 'Navigating to %g (%i/%i)', theta, ... - i, Nangles); drawnow; - obj.rot.move(theta); + if ~isempty(obj.rot) + status.String = sprintf( 'Navigating to %g (%i/%i)', theta, ... + i, Nangles); drawnow; + obj.rot.move(theta); + else + pause(5) + end pause4Move(obj, obj.motor_move_time); status.String = sprintf( 'Measuring at %g (%i/%i)', theta, ... i, Nangles); drawnow; % Measure count rate - obj.data.intensity(i) = ctr.singleShot(obj.exposure, 1) + obj.data.intensity(i) = ctr.singleShot(obj.exposure, 1); plotH(1).YData = obj.data.intensity; drawnow; assert(~obj.abort_request,'User aborted'); end - %Get meta data from spectrum experiment - obj.meta.spec_meta = tempDat_nonvolatile; - obj.meta.diamondbase = tempDat.diamondbase; - - - catch err end % CLEAN UP CODE % From dff6c427e73ac92ee496b7e9410d401975b4b3f7 Mon Sep 17 00:00:00 2001 From: ibwharri Date: Mon, 28 Oct 2019 11:09:26 -0400 Subject: [PATCH 3/9] Updated motor serial number to Pref.MultipleChoice --- Modules/+Experiments/@Saturation/Saturation.m | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/Modules/+Experiments/@Saturation/Saturation.m b/Modules/+Experiments/@Saturation/Saturation.m index 80b8deab1..ee0678c13 100644 --- a/Modules/+Experiments/@Saturation/Saturation.m +++ b/Modules/+Experiments/@Saturation/Saturation.m @@ -3,18 +3,17 @@ properties(SetObservable,GetObservable) angles = Prefs.String('0','help_text', 'Matlab expression evaluated to find angles at which to measure APDs','units','degree','set','setAngle','allow_empty',false); - % motor_serial_number = Prefs.MulipleChoice('help_text','Serial number of APT motor controlling the HWP','choices',@Drivers.APTMotor.getAvailMotors) exposure = Prefs.Double(100, 'help_text', 'Exposure time to measure APD counts','units','ms','min',0,'allow_nan',false) motor_move_time = Prefs.Double(30, 'help_text', 'Maximum time allowed for the motor to move','units','s','min',0,'allow_nan',false) motor_home_time = Prefs.Double(120, 'help_text', 'Maximum time allowed for the motor to home','units','s','min',0,'allow_nan',false) - motor_serial_number = @Drivers.APTMotor.getAvailMotors; - %motor_serial_number = {27251915} + motor_serial_number = Prefs.MultipleChoice('help_text','Serial number of APT motor controlling the HWP','choices',{'0'},'allow_empty',true) + reload = Prefs.Boolean(false,'set','reload_toggle','help_text','Toggle this to reload list of available motors') APD_line = Prefs.String('APD1','help_text','NiDAQ line to apd','allow_empty',false); APD_sync_line = Prefs.String('CounterSync','help_text','NiDAQ synchronisation line','allow_empty',false); end properties - prefs = {'angles','exposure','motor_move_time','motor_home_time','motor_serial_number'}; % String representation of desired prefs + prefs = {'angles','exposure','motor_move_time','motor_home_time','motor_serial_number','reload'}; % String representation of desired prefs %show_prefs = {}; % Use for ordering and/or selecting which prefs to show in GUI %readonly_prefs = {}; % CC will leave these as disabled in GUI (if in prefs/show_prefs) end @@ -37,6 +36,7 @@ function obj = Saturation() % Constructor (should not be accessible to command line!) obj.loadPrefs; % Load prefs specified as obj.prefs + obj.reload_toggle() end end @@ -60,10 +60,26 @@ function abort(obj) newVal = val; end - function set.motor_serial_number(obj,val) + function val = reload_toggle(obj,~,~) + % TODO: replace with a Prefs.Button + % Pretends to be a button from a boolean pref + val = false; % Swap back to false + mp = obj.get_meta_pref('motor_serial_number'); + mp.choices = Drivers.APTMotor.getAvailMotors(); % set new choices + obj.set_meta_pref('motor_serial_number', mp); + end + + function val = set_motor_serial_number(obj,val) + if isempty(val) + % If '', delete handle and short-circuit + delete(obj.rot); % Either motor obj or empty + obj.rot = []; + return + end + val_as_double = str2double(val); % must be double to instantiate motor - %assert(~isnan(val_as_double),'Motor SN must be a valid number.') + assert(~isnan(val_as_double),'Motor SN must be a valid number.') if isnan(val_as_double) return end @@ -80,5 +96,6 @@ function abort(obj) % Add new motor obj.rot = Drivers.APTMotor.instance(val_as_double, [0 360]); end + end end From f09902dfc6e9d93eb0dc56d32226b21862c2ca4b Mon Sep 17 00:00:00 2001 From: Isaac Harris Date: Mon, 28 Oct 2019 13:24:55 -0400 Subject: [PATCH 4/9] fixed small bugs in experiment --- Modules/+Experiments/@Saturation/Saturation.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/+Experiments/@Saturation/Saturation.m b/Modules/+Experiments/@Saturation/Saturation.m index ee0678c13..68b99d1a3 100644 --- a/Modules/+Experiments/@Saturation/Saturation.m +++ b/Modules/+Experiments/@Saturation/Saturation.m @@ -6,7 +6,7 @@ exposure = Prefs.Double(100, 'help_text', 'Exposure time to measure APD counts','units','ms','min',0,'allow_nan',false) motor_move_time = Prefs.Double(30, 'help_text', 'Maximum time allowed for the motor to move','units','s','min',0,'allow_nan',false) motor_home_time = Prefs.Double(120, 'help_text', 'Maximum time allowed for the motor to home','units','s','min',0,'allow_nan',false) - motor_serial_number = Prefs.MultipleChoice('help_text','Serial number of APT motor controlling the HWP','choices',{'0'},'allow_empty',true) + motor_serial_number = Prefs.MultipleChoice('help_text','Serial number of APT motor controlling the HWP','set','set_motor_serial_number','allow_empty',true) reload = Prefs.Boolean(false,'set','reload_toggle','help_text','Toggle this to reload list of available motors') APD_line = Prefs.String('APD1','help_text','NiDAQ line to apd','allow_empty',false); APD_sync_line = Prefs.String('CounterSync','help_text','NiDAQ synchronisation line','allow_empty',false); @@ -69,7 +69,7 @@ function abort(obj) obj.set_meta_pref('motor_serial_number', mp); end - function val = set_motor_serial_number(obj,val) + function val = set_motor_serial_number(obj,val,~) if isempty(val) % If '', delete handle and short-circuit delete(obj.rot); % Either motor obj or empty From 070568b7240927691648cfd4eba4d8a335e0060a Mon Sep 17 00:00:00 2001 From: ibwharri Date: Wed, 30 Oct 2019 10:50:00 -0400 Subject: [PATCH 5/9] adjusted prefs so that 'reload' is not saved, removed redundant line in motor serial number set function --- Modules/+Experiments/@Saturation/Saturation.m | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Modules/+Experiments/@Saturation/Saturation.m b/Modules/+Experiments/@Saturation/Saturation.m index ee0678c13..53f14cf2b 100644 --- a/Modules/+Experiments/@Saturation/Saturation.m +++ b/Modules/+Experiments/@Saturation/Saturation.m @@ -13,8 +13,8 @@ end properties - prefs = {'angles','exposure','motor_move_time','motor_home_time','motor_serial_number','reload'}; % String representation of desired prefs - %show_prefs = {}; % Use for ordering and/or selecting which prefs to show in GUI + prefs = {'angles','exposure','motor_move_time','motor_home_time','motor_serial_number'}; % String representation of desired prefs + show_prefs = {'angles','exposure','motor_move_time','motor_home_time','motor_serial_number','reload'}; % Use for ordering and/or selecting which prefs to show in GUI %readonly_prefs = {}; % CC will leave these as disabled in GUI (if in prefs/show_prefs) end properties(SetAccess=private,Hidden) @@ -87,7 +87,6 @@ function abort(obj) delete(obj.rot); % Either motor obj or empty obj.rot = []; - obj.motor_serial_number = val; if val_as_double == 0 %Leave obj.rot empty if no serial number selected return % Short circuit From 4b84c9aaf4d93ec045f840ff40e916911921d26c Mon Sep 17 00:00:00 2001 From: Isaac Harris Date: Wed, 30 Oct 2019 12:14:26 -0400 Subject: [PATCH 6/9] removed reload toggle; functionality to reload to be added at higher level (see set_metapref branch) --- Modules/+Experiments/@Saturation/Saturation.m | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/Modules/+Experiments/@Saturation/Saturation.m b/Modules/+Experiments/@Saturation/Saturation.m index ffbb52393..501874a0f 100644 --- a/Modules/+Experiments/@Saturation/Saturation.m +++ b/Modules/+Experiments/@Saturation/Saturation.m @@ -7,14 +7,13 @@ motor_move_time = Prefs.Double(30, 'help_text', 'Maximum time allowed for the motor to move','units','s','min',0,'allow_nan',false) motor_home_time = Prefs.Double(120, 'help_text', 'Maximum time allowed for the motor to home','units','s','min',0,'allow_nan',false) motor_serial_number = Prefs.MultipleChoice('help_text','Serial number of APT motor controlling the HWP','set','set_motor_serial_number','allow_empty',true) - reload = Prefs.Boolean(false,'set','reload_toggle','help_text','Toggle this to reload list of available motors') APD_line = Prefs.String('APD1','help_text','NiDAQ line to apd','allow_empty',false); APD_sync_line = Prefs.String('CounterSync','help_text','NiDAQ synchronisation line','allow_empty',false); end properties prefs = {'angles','exposure','motor_move_time','motor_home_time','motor_serial_number'}; % String representation of desired prefs - show_prefs = {'angles','exposure','motor_move_time','motor_home_time','motor_serial_number','reload'}; % Use for ordering and/or selecting which prefs to show in GUI + % show_prefs = {}; % Use for ordering and/or selecting which prefs to show in GUI %readonly_prefs = {}; % CC will leave these as disabled in GUI (if in prefs/show_prefs) end properties(SetAccess=private,Hidden) @@ -36,7 +35,11 @@ function obj = Saturation() % Constructor (should not be accessible to command line!) obj.loadPrefs; % Load prefs specified as obj.prefs - obj.reload_toggle() + + % Find available motor serial numbers + mp = obj.get_meta_pref('motor_serial_number'); + mp.choices = Drivers.APTMotor.getAvailMotors(); % set new choices + obj.set_meta_pref('motor_serial_number', mp); end end @@ -59,15 +62,6 @@ function abort(obj) obj.angle_list = str2num(val); newVal = val; end - - function val = reload_toggle(obj,~,~) - % TODO: replace with a Prefs.Button - % Pretends to be a button from a boolean pref - val = false; % Swap back to false - mp = obj.get_meta_pref('motor_serial_number'); - mp.choices = Drivers.APTMotor.getAvailMotors(); % set new choices - obj.set_meta_pref('motor_serial_number', mp); - end function val = set_motor_serial_number(obj,val,~) if isempty(val) From e5d6be6165ed949d5d6fefc23e785850e9e4a560 Mon Sep 17 00:00:00 2001 From: ibwharri Date: Mon, 4 Nov 2019 11:16:55 -0500 Subject: [PATCH 7/9] Updated getAvailMotors to remove '0' choice; updated prefs that used it to class-based prefs --- Modules/+Drivers/APTMotor.m | 3 ++- .../@PolarisationSpectrum/PolarisationSpectrum.m | 7 ++++++- Modules/+Stages/MAX302motors.m | 13 ++++++++++--- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Modules/+Drivers/APTMotor.m b/Modules/+Drivers/APTMotor.m index 8709e19a5..65a942cce 100644 --- a/Modules/+Drivers/APTMotor.m +++ b/Modules/+Drivers/APTMotor.m @@ -31,7 +31,8 @@ APTSystem = Drivers.APTSystem.instance; devices = APTSystem.getDevices; devices = num2cell(double(devices.USB_STEPPER_DRIVE)); - devices = [{'0'},cellfun(@num2str,devices,'uniformoutput',false)]; + devices = cellfun(@num2str,devices,'uniformoutput',false); + delete(APTSystem) % Needs to be deleted to delete(f); end % Use this to create/retrieve instance associated with serialNum diff --git a/Modules/+Experiments/@PolarisationSpectrum/PolarisationSpectrum.m b/Modules/+Experiments/@PolarisationSpectrum/PolarisationSpectrum.m index d3e2b3398..5b2f9de75 100644 --- a/Modules/+Experiments/@PolarisationSpectrum/PolarisationSpectrum.m +++ b/Modules/+Experiments/@PolarisationSpectrum/PolarisationSpectrum.m @@ -16,7 +16,7 @@ properties(SetObservable,AbortSet) angles = '0:10:180'; % string of rotations (in degrees) at which spectra will be measured. Can specify a list or MATLAB range - motor_serial_number = @Drivers.APTMotor.getAvailMotors; % Serial number for the rotation mount, to be used to create a driver for the rotation mount. Must be connected through APT Config first. + motor_serial_number = Prefs.MultipleChoice('help_text','Serial number of APT motor controlling the HWP','set','set_motor_serial_number','allow_empty',true) spec_experiment = Experiments.Spectrum.instance % Handle for spectrum experiment to be run. Settings for the experiment accessed from GUI motor_move_time = 30; % Maximum time allowed for motor to move between positions motor_home_time = 120; % Maximum time allowed for the motor to home itself @@ -47,6 +47,11 @@ % Constructor (should not be accessible to command line!) obj.spec_experiment = Experiments.Spectrum.instance; obj.loadPrefs; % Load prefs specified as obj.prefs + + % Find available motor serial numbers + mp = obj.get_meta_pref('motor_serial_number'); + mp.choices = Drivers.APTMotor.getAvailMotors(); % set new choices + obj.set_meta_pref('motor_serial_number', mp); end end diff --git a/Modules/+Stages/MAX302motors.m b/Modules/+Stages/MAX302motors.m index 8f67226a5..cf9d47781 100644 --- a/Modules/+Stages/MAX302motors.m +++ b/Modules/+Stages/MAX302motors.m @@ -11,9 +11,9 @@ prefs = {'X_Motor','Y_Motor','Z_Motor','direction'}; end properties(SetObservable,AbortSet) - X_Motor = @Drivers.APTMotor.getAvailMotors; % Motor serial number - Y_Motor = @Drivers.APTMotor.getAvailMotors; % Motor serial number - Z_Motor = @Drivers.APTMotor.getAvailMotors; % Motor serial number + X_Motor = Prefs.MultipleChoice('help_text','Serial number of APT motor controlling the X axis','set','set_motor_serial_number','allow_empty',true) + Y_Motor = Prefs.MultipleChoice('help_text','Serial number of APT motor controlling the Y axis','set','set_motor_serial_number','allow_empty',true) + Z_Motor = Prefs.MultipleChoice('help_text','Serial number of APT motor controlling the Z axis','set','set_motor_serial_number','allow_empty',true) direction = [1 1 1]; end properties(SetAccess=private,SetObservable,AbortSet) @@ -45,6 +45,13 @@ methods(Access=private) function obj = MAX302motors() obj.loadPrefs; + + % Find available motor serial numbers + for motor = ["X_Motor","Y_Motor","Z_Motor"] + mp = obj.get_meta_pref(motor); + mp.choices = Drivers.APTMotor.getAvailMotors(); % set new choices + obj.set_meta_pref(motor, mp); + end end end % Callback functions for APTMotor From af182bda158cd9f6bb32a41c6a6717d067c9baf3 Mon Sep 17 00:00:00 2001 From: Isaac Harris Date: Mon, 4 Nov 2019 11:51:37 -0500 Subject: [PATCH 8/9] added comment --- Modules/+Drivers/APTMotor.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/+Drivers/APTMotor.m b/Modules/+Drivers/APTMotor.m index 65a942cce..f8602e806 100644 --- a/Modules/+Drivers/APTMotor.m +++ b/Modules/+Drivers/APTMotor.m @@ -32,7 +32,7 @@ devices = APTSystem.getDevices; devices = num2cell(double(devices.USB_STEPPER_DRIVE)); devices = cellfun(@num2str,devices,'uniformoutput',false); - delete(APTSystem) % Needs to be deleted to + delete(APTSystem) % Needs to be deleted to update properly delete(f); end % Use this to create/retrieve instance associated with serialNum From fa24f3a77a9868ac3d70a7b4a9b5763feebf001f Mon Sep 17 00:00:00 2001 From: ibwharri Date: Tue, 25 Feb 2020 17:56:18 -0500 Subject: [PATCH 9/9] Fixed bug in PolarisationSpectrum --- .../+Experiments/@PolarisationSpectrum/PolarisationSpectrum.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/+Experiments/@PolarisationSpectrum/PolarisationSpectrum.m b/Modules/+Experiments/@PolarisationSpectrum/PolarisationSpectrum.m index 5b2f9de75..8ee157b4c 100644 --- a/Modules/+Experiments/@PolarisationSpectrum/PolarisationSpectrum.m +++ b/Modules/+Experiments/@PolarisationSpectrum/PolarisationSpectrum.m @@ -14,7 +14,7 @@ % diamondbase - diamondbase data - properties(SetObservable,AbortSet) + properties(SetObservable,GetObservable,AbortSet) angles = '0:10:180'; % string of rotations (in degrees) at which spectra will be measured. Can specify a list or MATLAB range motor_serial_number = Prefs.MultipleChoice('help_text','Serial number of APT motor controlling the HWP','set','set_motor_serial_number','allow_empty',true) spec_experiment = Experiments.Spectrum.instance % Handle for spectrum experiment to be run. Settings for the experiment accessed from GUI @@ -72,7 +72,7 @@ function abort(obj) dat.meta = obj.meta; end - function set.motor_serial_number(obj,val) + function val = set_motor_serial_number(obj,val,~) val_as_double = str2double(val); % must be double to instantiate motor assert(~isnan(val_as_double),'Motor SN must be a valid number.')