Page MenuHomec4science

No OneTemporary

File Metadata

Created
Sun, Jan 12, 06:51
diff --git a/@MyFit/MyFit.m b/@MyFit/MyFit.m
index 71df620..234f57d 100644
--- a/@MyFit/MyFit.m
+++ b/@MyFit/MyFit.m
@@ -1,277 +1,286 @@
classdef MyFit < handle
properties
Gui
Data;
Fit;
Parser;
fit_name='linear'
init_params=[];
scale_init=[];
lim_lower;
lim_upper;
FitStruct;
Fitdata;
coeffs;
enable_gui=1;
enable_plot;
plot_handle;
hline_init;
end
properties (Dependent=true)
fit_function;
fit_tex;
fit_params;
fit_param_names;
valid_fit_names;
n_params;
scaled_params;
init_param_fun;
end
+ events
+ PerformedFit;
+ end
+
methods
function this=MyFit(varargin)
createFitStruct(this);
createParser(this);
parse(this.Parser,varargin{:});
parseInputs(this);
if ismember('Data',this.Parser.UsingDefaults) &&...
~ismember('x',this.Parser.UsingDefaults) &&...
~ismember('y',this.Parser.UsingDefaults)
this.Data.x=this.Parser.Results.x;
this.Data.y=this.Parser.Results.y;
end
if ~isempty(this.Data.x) || ~isempty(this.Data.y)
genInitParams(this);
else
this.init_params=ones(1,this.n_params);
end
this.scale_init=ones(1,this.n_params);
if this.enable_gui
createGui(this);
end
end
%Creates the GUI of MyFit
createGui(this);
function delete(this)
if this.enable_gui
set(this.Gui.Window,'CloseRequestFcn','');
%Deletes the figure
delete(this.Gui.Window);
%Removes the figure handle to prevent memory leaks
this.Gui=[];
end
end
-
+
%Close figure callback simply calls delete function for class
function closeFigure(this,~,~)
delete(this);
end
function createParser(this)
p=inputParser;
addParameter(p,'fit_name','linear',@ischar)
addParameter(p,'Data',MyTrace());
addParameter(p,'Fit',MyTrace());
addParameter(p,'x',[]);
addParameter(p,'y',[]);
addParameter(p,'enable_gui',1);
addParameter(p,'enable_plot',0);
addParameter(p,'plot_handle',[]);
this.Parser=p;
end
%Sets the class variables to the inputs from the inputParser.
function parseInputs(this)
for i=1:length(this.Parser.Parameters)
%Takes the value from the inputParser to the appropriate
%property.
if isprop(this,this.Parser.Parameters{i})
this.(this.Parser.Parameters{i})=...
this.Parser.Results.(this.Parser.Parameters{i});
end
end
end
function fitTrace(this)
this.Fit.x=linspace(min(this.Data.x),max(this.Data.x),1e3);
switch this.fit_name
case 'linear'
this.coeffs=polyfit(this.Data.x,this.Data.y,1);
this.Fit.y=polyval(this.coeffs,this.Fit.x);
case 'quadratic'
this.coeffs=polyfit(this.Data.x,this.Data.y,2);
this.Fit.y=polyval(this.coeffs,this.Fit.x);
case {'exponential','gaussian','lorentzian'}
- this.doFit
+ doFit(this);
this.coeffs=coeffvalues(this.Fitdata);
this.Fit.y=this.Fitdata(this.Fit.x);
otherwise
- this.doFit;
+ doFit(this);
this.Fit.y=this.Fitdata(this.Fit.x);
this.coeffs=coeffvalues(this.Fitdata);
end
this.init_params=this.coeffs;
this.scale_init=ones(1,this.n_params);
+ triggerPerformedFit(this);
if this.enable_gui; updateGui(this); end
if this.enable_plot; plotFit(this); end
end
function doFit(this)
this.Fitdata=fit(this.Data.x,this.Data.y,this.fit_function,...
'Lower',this.lim_lower,'Upper',this.lim_upper,...
'StartPoint',this.init_params);
end
+ function triggerPerformedFit(this)
+ notify(this,'PerformedFit');
+ end
+
function plotFit(this)
plot(this.plot_handle,this.Fit.x,this.Fit.y);
end
function createFitStruct(this)
%Adds fits
addFit(this,'linear','a*x+b','$$ax+b$$',{'a','b'},...
{'Gradient','Offset'})
addFit(this,'quadratic','a*x^2+b*x+c','$$ax^2+bx+c$$',...
{'a','b','c'},{'Quadratic coeff.','Linear coeff.','Offset'});
addFit(this,'gaussian','a*exp(-((x-c)/b)^2/2)+d',...
'$$ae^{-\frac{(x-c)^2}{2b^2}}+d$$',{'a','b','c','d'},...
{'Amplitude','Width','Center','Offset'});
addFit(this,'lorentzian','a/(pi)*(b/2/((x-c)^2+(b/2)^2))+d',...
'$$\frac{a}{1+\frac{b/2}{(x-c)^2+(b/2)^2}}+d$$',{'a','b','c','d'},...
{'Amplitude','Width','Center','Offset'});
addFit(this,'exponential','a*exp(b*x)+c',...
'$$ae^{bx}+c$$',{'a','b','c'},...
{'Amplitude','Rate','Offset'});
end
function updateGui(this)
%Converts the scale variable to the value between 0 and 100
%necessary for the slider
slider_vals=25*log10(this.scale_init)+50;
for i=1:this.n_params
set(this.Gui.(sprintf('edit_%s',this.fit_params{i})),...
'String',sprintf('%3.3e',this.scaled_params(i)));
set(this.Gui.(sprintf('slider_%s',this.fit_params{i})),...
'Value',slider_vals(i));
end
end
%Adds a fit to the list of fits
function addFit(this,fit_name,fit_function,fit_tex,fit_params,...
fit_param_names)
this.FitStruct.(fit_name).fit_function=fit_function;
this.FitStruct.(fit_name).fit_tex=fit_tex;
this.FitStruct.(fit_name).fit_params=fit_params;
this.FitStruct.(fit_name).fit_param_names=fit_param_names;
%Generates the anonymous fit function from the above
args=['@(x,', strjoin(fit_params,','),')'];
anon_fit_fun=str2func(vectorize([args,fit_function]));
this.FitStruct.(fit_name).anon_fit_fun=anon_fit_fun;
end
function genInitParams(this)
switch this.fit_name
case 'exponential'
[this.init_params,this.lim_lower,this.lim_upper]=...
initParamExponential(this.Data.x,this.Data.y);
case 'gaussian'
[this.init_params,this.lim_lower,this.lim_upper]=...
initParamGaussian(this.Data.x,this.Data.y);
case 'lorentzian'
[this.init_params,this.lim_lower,this.lim_upper]=...
initParamLorentzian(this.Data.x,this.Data.y);
otherwise
this.init_params=ones(1,this.n_params);
end
end
function slider_Callback(this, param_ind, hObject, ~)
%Gets the value from the slider
scale=get(hObject,'Value');
%Updates the scale with a new value
this.scale_init(param_ind)=10^((scale-50)/25);
%Updates the edit box with the new value from the slider
set(this.Gui.(sprintf('edit_%s',this.fit_params{param_ind})),...
'String',sprintf('%3.3e',this.scaled_params(param_ind)));
if this.enable_plot; plotInitFun(this); end
end
function edit_Callback(this, hObject, ~)
init_param=str2double(get(hObject,'String'));
tag=get(hObject,'Tag');
%Finds the index where the fit_param name begins (convention is
%after the underscore)
fit_param=tag((strfind(tag,'_')+1):end);
param_ind=strcmp(fit_param,this.fit_params);
%Updates the slider to be such that the scaling is 1
set(this.Gui.(sprintf('slider_%s',fit_param)),...
'Value',50);
%Updates the correct initial parameter
this.init_params(param_ind)=init_param;
if this.enable_plot; plotInitFun(this); end
end
function plotInitFun(this)
%Substantially faster than any alternative - generating
%anonymous functions is very cpu intensive.
x_vec=linspace(min(this.Data.x),max(this.Data.x),1000);
input_cell=num2cell(this.scaled_params);
y_vec=feval(this.FitStruct.(this.fit_name).anon_fit_fun,x_vec,...
input_cell{:});
if isempty(this.hline_init)
this.hline_init=plot(this.plot_handle,x_vec,y_vec);
else
set(this.hline_init,'XData',x_vec,'YData',y_vec);
end
end
function set.fit_name(this,fit_name)
assert(ischar(fit_name),'The fit name must be a string');
this.fit_name=lower(fit_name);
end
function valid_fit_names=get.valid_fit_names(this)
valid_fit_names=fieldnames(this.FitStruct);
end
function fit_function=get.fit_function(this)
assert(ismember(this.fit_name,this.valid_fit_names),...
'%s is not a supported fit name',this.fit_name);
fit_function=this.FitStruct.(this.fit_name).fit_function;
end
function fit_tex=get.fit_tex(this)
assert(ismember(this.fit_name,this.valid_fit_names),...
'%s is not a supported fit name',this.fit_name);
fit_tex=this.FitStruct.(this.fit_name).fit_tex;
end
function fit_params=get.fit_params(this)
assert(ismember(this.fit_name,this.valid_fit_names),...
'%s is not a supported fit name',this.fit_name);
fit_params=this.FitStruct.(this.fit_name).fit_params;
end
function fit_param_names=get.fit_param_names(this)
assert(ismember(this.fit_name,this.valid_fit_names),...
'%s is not a supported fit name',this.fit_name);
fit_param_names=this.FitStruct.(this.fit_name).fit_param_names;
end
function scaled_params=get.scaled_params(this)
scaled_params=this.scale_init.*this.init_params;
end
function n_params=get.n_params(this)
n_params=length(this.fit_params);
end
end
end
\ No newline at end of file
diff --git a/@MyInstrument/MyInstrument.m b/@MyInstrument/MyInstrument.m
index 62009b4..956a949 100644
--- a/@MyInstrument/MyInstrument.m
+++ b/@MyInstrument/MyInstrument.m
@@ -1,242 +1,251 @@
classdef MyInstrument < handle
properties (SetAccess=protected, GetAccess=public)
name='';
interface='';
address='';
axes_handle=[];
%Logical for whether gui is enabled
enable_gui=false;
%Contains the GUI handles
Gui;
%Contains the device object
Device;
%Input parser for class constructor
Parser;
%Contains a list of the commands available for the instrument as
%well as the default values and input requirements
CommandList;
%Parses commands using an inputParser object
CommandParser;
end
properties (Dependent=true)
command_names;
command_no;
end
+ events
+ AcquiredData;
+ end
+
methods
function this=MyInstrument(name, interface, address, varargin)
createParser(this);
parse(this.Parser,name,interface,address,varargin{:});
%Loads parsed variables into class properties
this.name=this.Parser.Results.name;
this.interface=this.Parser.Results.interface;
this.address=this.Parser.Results.address;
this.enable_gui=~ismember('gui',this.Parser.UsingDefaults);
this.axes_handle=this.Parser.Results.axes_handle;
try
openDevice(this);
closeDevice(this);
catch
error(['Failed to open communications with device.',...
' Check that the address and interface is correct'])
end
%If a gui input is given, load the gui
if this.enable_gui
%Loads the gui from the input gui string
this.Gui=guihandles(eval(this.Parser.Results.gui));
%Sets figure close function such that class will know when
%figure is closed
set(this.Gui.figure1, 'CloseRequestFcn',...
@(hObject,eventdata) closeFigure(this, hObject, ...
eventdata));
end
end
+ %Triggers event for acquired data
+ function triggerAcquiredData(this)
+ notify(this,'AcquiredData')
+ end
+
function delete(this)
%Removes close function from figure, prevents infinite loop
if this.enable_gui
set(this.Gui.figure1,'CloseRequestFcn','');
%Deletes the figure
delete(this.Gui.figure1);
%Removes the figure handle to prevent memory leaks
this.Gui=[];
end
%Closes the connection to the device
closeDevice(this);
%Deletes the device object
delete(this.Device);
clear('this.Device');
end
end
methods
%Checks if the connection to the device is open
function bool=isopen(this)
bool=strcmp(this.Device.Status, 'open');
end
function createParser(this)
p=inputParser;
addRequired(p,'name',@ischar);
addRequired(p,'interface',@ischar);
addRequired(p,'address',@ischar);
addParameter(p,'gui','placeholder',@ischar);
addParameter(p,'axes_handle',[]);
this.Parser=p;
end
%Sends a read command to the device
function result=read(this,command)
result=query(this.Device, command);
end
%Writes to the device
function write(this, command)
fprintf(this.Device, command);
end
function writeProperty(this, varargin)
%Parses the inputs using the CommandParser
parse(this.CommandParser, varargin{:});
%Finds the commands that are supplied by the user
ind=~ismember(this.CommandParser.Parameters,...
this.CommandParser.UsingDefaults);
%Creates a list of commands to be executed
exec=this.CommandParser.Parameters(ind);
for i=1:length(exec)
command=sprintf(this.CommandList.(exec{i}).command,...
this.CommandParser.Results.(exec{i}));
write(this, command);
end
end
function result=readProperty(this, varargin)
result=struct();
for i=1:length(varargin)
%Finds the index of the % sign which indicates where the value
%to be written is supplied
ind=strfind(this.CommandList.(varargin{i}).command,'%');
if ~any(ind)
error('%s is not a valid tag for a command in %s',...
varargin{i},class(this));
end
%Creates the correct read command
read_command=...
[this.CommandList.(varargin{i}).command(1:(ind-2)),'?'];
%Reads the property from the device and stores it in the
%correct place
result.(varargin{i})=str2double(this.read(read_command));
end
end
%Adds a command to the CommandList
function addCommand(this, tag, command, varargin)
p=inputParser;
addRequired(p,'tag',@ischar);
addRequired(p,'command',@ischar);
addParameter(p,'default','placeholder');
addParameter(p,'attributes','placeholder',@iscell)
%If the write flag is on, it means this command can be used to
%write a parameter to the device
addParameter(p,'write_flag',false,@islogical)
parse(p,tag,command,varargin{:});
if ~isprop(this, tag) && p.Results.write_flag
error('All commands must have a tag matching the property they modify')
end
%Adds the command to be sent to the device
this.CommandList.(tag).command=command;
this.CommandList.(tag).write_flag=p.Results.write_flag;
%Adds a default value and the attributes the inputs must have
if p.Results.write_flag
%Adds the default value
this.CommandList.(tag).default=p.Results.default;
%Adds the necessary attributes for the input to the command
this.CommandList.(tag).attributes=p.Results.attributes;
end
end
%Creates inputParser using the command list
function createCommandParser(this)
%Use input parser
%Requires input of the appropriate class
p=inputParser;
p.StructExpand=0;
for i=1:this.command_no
%Adds optional inputs for each command, with the
%appropriate default value from the command list and the
%required attributes for the command input.
addParameter(p, this.command_names{i},...
this.CommandList.(this.command_names{i}).default),...
@(x) validateattributes(x,...
this.CommandList.(this.command_names{i}).attributes{1:end});
end
this.CommandParser=p;
end
%Connects to the device if it is not connected
function openDevice(this)
if ~isopen(this)
try
fopen(this.Device);
catch
try
instr_list=instrfind('RemoteHost',this.address);
fclose(instr_list);
fopen(this.Device);
warning('Multiple instrument objects of address %s exist',...
this.address);
catch
error('Could not open device')
end
end
end
end
%Closes the connection to the device
function closeDevice(this)
if isopen(this)
try
fclose(this.Device);
catch
error('Could not close device')
end
end
end
%Close figure callback simply calls delete function for class
function closeFigure(this,~,~)
delete(this);
end
function command_names=get.command_names(this)
command_names=fieldnames(this.CommandList);
end
function command_no=get.command_no(this)
command_no=length(this.command_names);
end
end
end
\ No newline at end of file
diff --git a/@MyNa/MyNa.m b/@MyNa/MyNa.m
index 1b80c26..733896a 100644
--- a/@MyNa/MyNa.m
+++ b/@MyNa/MyNa.m
@@ -1,112 +1,113 @@
classdef MyNa < MyInstrument
properties (SetAccess=protected, GetAccess=public)
ifbw;
start_freq;
stop_freq;
cent_freq;
span;
power;
Trace;
end
+
methods
function this=MyNa(name, interface, address, varargin)
this@MyInstrument(name, interface, address,varargin{:});
createCommandList(this);
createCommandParser(this);
if this.enable_gui; initGui(this); end
end
function createCommandList(this)
addCommand(this,'cent_freq','SENS:FREQ:CENT %d',...
'default',1.5e6,'attributes',{{'numeric'}},'write_flag',true);
addCommand(this,'start_freq','SENS:FREQ:START %d',...
'default',1e6,'attributes',{{'numeric'}},'write_flag',true);
addCommand(this,'stop_freq','SENS:FREQ:STOP %d',...
'default',2e6,'attributes',{{'numeric'}},'write_flag',true);
addCommand(this,'span','SENS:FREQ:SPAN %d',...
'default',1e6,'attributes',{{'numeric'}},'write_flag',true);
addCommand(this,'power','SOUR:POW:LEV:IMM:AMPL %d',...
'default',1,'attributes',{{'numeric'}},'write_flag',true);
end
function initGui(this)
set(this.Gui.reinit, 'Callback',...
@(hObject, eventdata) reinitCallback(this, hObject,...
eventdata));
set(this.Gui.start_freq, 'Callback',...
@(hObject, eventdata) start_freqCallback(this, hObject,...
eventdata));
set(this.Gui.stop_freq, 'Callback',...
@(hObject, eventdata) stop_freqCallback(this, hObject,...
eventdata));
set(this.Gui.cent_freq, 'Callback',...
@(hObject, eventdata) cent_freqCallback(this, hObject,...
eventdata));
set(this.Gui.span, 'Callback',...
@(hObject, eventdata) spanCallback(this, hObject,...
eventdata));
set(this.Gui.ifbw, 'Callback',...
@(hObject, eventdata) rbwCallback(this, hObject,...
eventdata));
set(this.Gui.fetch_single, 'Callback',...
@(hObject, eventdata) fetchCallback(this, hObject,...
eventdata));
set(this.Gui.average_no, 'Callback',...
@(hObject, eventdata) average_noCallback(this, hObject,...
eventdata));
set(this.Gui.enable_avg, 'Callback',...
@(hObject, eventdata) enable_avgCallback(this, hObject,...
eventdata));
end
function start_freqCallback(this, hObject, eventdata)
this.start_freq=str2double(get(hObject,'String'))*1e6;
openDevice(this);
writeProperty(this,'start_freq',this.start_freq);
readStatus(this);
closeDevice(this);
end
function stop_freqCallback(this, hObject, eventdata)
this.stop_freq=str2double(get(hObject,'String'))*1e6;
openDevice(this);
writeProperty(this,'stop_freq',this.stop_freq);
readStatus(this);
closeDevice(this);
end
function cent_freqCallback(this, hObject, eventdata)
this.cent_freq=str2double(get(hObject,'String'))*1e6;
openDevice(this);
writeProperty(this,'cent_freq',this.cent_freq);
readStatus(this);
closeDevice(this);
end
function spanCallback(this, hObject, eventdata)
this.span=str2double(get(hObject,'String'))*1e6;
openDevice(this);
writeProperty(this,'span',this.span);
readStatus(this)
closeDevice(this);
end
function ifbwCallback(this, hObject, eventdata)
this.ifbw=str2double(get(hObject,'String'))*1e3;
openDevice(this);
writeProperty(this,'ifbw',this.ifbw);
closeDevice(this);
end
function average_noCallback(this, hObject, eventdata)
this.average_no=str2double(get(hObject,'String'));
%Writes the average_no to the device only if averaging is
%enabled
openDevice(this);
writeProperty(this,'average_no',this.average_no);
closeDevice(this);
end
end
end
diff --git a/@MyRsa/MyRsa.m b/@MyRsa/MyRsa.m
index 80c9554..2881c96 100644
--- a/@MyRsa/MyRsa.m
+++ b/@MyRsa/MyRsa.m
@@ -1,346 +1,346 @@
classdef MyRsa < MyInstrument
properties (SetAccess=protected, GetAccess=public)
rbw;
start_freq;
stop_freq;
cent_freq;
span;
average_no;
point_no;
enable_avg;
read_cont;
Trace;
valid_points;
end
properties (Dependent=true)
freq_vec;
end
methods
function this=MyRsa(name,interface, address,varargin)
this@MyInstrument(name, interface, address,varargin{:});
- if this.enable_gui; initGui(this); end;
+ if this.enable_gui; initGui(this); end
%Valid point numbers for Tektronix 5103 and 5106.
%Depends on the RSA. Remove this in the future.
this.valid_points=[801,2401,4001,10401];
createCommandList(this);
createCommandParser(this);
switch interface
case 'TCPIP'
connectTCPIP(this);
end
%Opens communications
openDevice(this);
%Finds the current status of the device
readStatus(this);
%Initializes the device
initDevice(this);
closeDevice(this);
end
end
methods
function connectTCPIP(this)
buffer = 1000 * 1024;
visa_brand = 'ni';
visa_address_rsa = sprintf('TCPIP0::%s::inst0::INSTR',...
this.address);
this.Device=visa(visa_brand, visa_address_rsa,...
'InputBufferSize', buffer,...
'OutputBufferSize', buffer);
set(this.Device,'InputBufferSize',1e6);
set(this.Device,'Timeout',10);
end
function readStatus(this)
result=readProperty(this,'rbw','cent_freq','span','start_freq',...
'stop_freq','enable_avg');
res_names=fieldnames(result);
for i=1:length(res_names)
this.(res_names{i})=result.(res_names{i});
end
end
function initGui(this)
set(this.Gui.reinit, 'Callback',...
@(hObject, eventdata) reinitCallback(this, hObject,...
eventdata));
set(this.Gui.point_no, 'Callback',...
@(hObject, eventdata) point_noCallback(this, hObject,...
eventdata));
set(this.Gui.start_freq, 'Callback',...
@(hObject, eventdata) start_freqCallback(this, hObject,...
eventdata));
set(this.Gui.stop_freq, 'Callback',...
@(hObject, eventdata) stop_freqCallback(this, hObject,...
eventdata));
set(this.Gui.cent_freq, 'Callback',...
@(hObject, eventdata) cent_freqCallback(this, hObject,...
eventdata));
set(this.Gui.span, 'Callback',...
@(hObject, eventdata) spanCallback(this, hObject,...
eventdata));
set(this.Gui.rbw, 'Callback',...
@(hObject, eventdata) rbwCallback(this, hObject,...
eventdata));
set(this.Gui.fetch_single, 'Callback',...
@(hObject, eventdata) fetchCallback(this, hObject,...
eventdata));
set(this.Gui.average_no, 'Callback',...
@(hObject, eventdata) average_noCallback(this, hObject,...
eventdata));
set(this.Gui.enable_avg, 'Callback',...
@(hObject, eventdata) enable_avgCallback(this, hObject,...
eventdata));
end
function initDevice(this)
for i=1:this.command_no
if this.CommandList.(this.command_names{i}).write_flag
write(this, ...
sprintf(this.CommandList.(this.command_names{i}).command,...
this.CommandList.(this.command_names{i}).default));
this.(this.command_names{i})=...
this.CommandList.(this.command_names{i}).default;
end
end
end
- function reinitCallback(this, hObject, eventdata)
+ function reinitCallback(this, hObject, ~)
reinitDevice(this);
%Turns off indicator
set(hObject,'Value',0);
end
function reinitDevice(this)
openDevice(this);
readStatus(this);
initDevice(this);
writeProperty(this, 'read_cont','on')
closeDevice(this);
end
- function point_noCallback(this, hObject, eventdata)
+ function point_noCallback(this, hObject, ~)
value_list=get(hObject,'String');
this.point_no=str2double(value_list{get(hObject,'Value')});
openDevice(this);
writeProperty(this,'point_no',this.point_no);
readStatus(this);
closeDevice(this);
end
- function start_freqCallback(this, hObject, eventdata)
+ function start_freqCallback(this, hObject, ~)
this.start_freq=str2double(get(hObject,'String'))*1e6;
openDevice(this);
writeProperty(this,'start_freq',this.start_freq);
readStatus(this);
closeDevice(this);
end
- function stop_freqCallback(this, hObject, eventdata)
+ function stop_freqCallback(this, hObject, ~)
this.stop_freq=str2double(get(hObject,'String'))*1e6;
openDevice(this);
writeProperty(this,'stop_freq',this.stop_freq);
readStatus(this);
closeDevice(this);
end
- function cent_freqCallback(this, hObject, eventdata)
+ function cent_freqCallback(this, hObject, ~)
this.cent_freq=str2double(get(hObject,'String'))*1e6;
openDevice(this);
writeProperty(this,'cent_freq',this.cent_freq);
readStatus(this);
closeDevice(this);
end
- function spanCallback(this, hObject, eventdata)
+ function spanCallback(this, hObject, ~)
this.span=str2double(get(hObject,'String'))*1e6;
openDevice(this);
writeProperty(this,'span',this.span);
readStatus(this)
closeDevice(this);
end
- function rbwCallback(this, hObject, eventdata)
+ function rbwCallback(this, hObject, ~)
this.rbw=str2double(get(hObject,'String'))*1e3;
openDevice(this);
writeProperty(this,'rbw',this.rbw);
closeDevice(this);
end
- function average_noCallback(this, hObject, eventdata)
+ function average_noCallback(this, hObject, ~)
this.average_no=str2double(get(hObject,'String'));
%Writes the average_no to the device only if averaging is
%enabled
openDevice(this);
writeProperty(this,'average_no',this.average_no);
closeDevice(this);
end
function createCommandList(this)
addCommand(this,'average_no','TRAC3:DPSA:AVER:COUN %d',...
'default',1,'attributes',{{'numeric'}},'write_flag',true);
addCommand(this, 'rbw','DPSA:BAND:RES %d Hz',...
'default',1e3,'attributes',{{'numeric'}},'write_flag',true);
addCommand(this, 'span', 'DPSA:FREQ:SPAN %d Hz',...
'default',1e6,'attributes',{{'numeric'}},'write_flag',true);
addCommand(this, 'start_freq','DPSA:FREQ:STAR %d Hz',...
'default',1e6,'attributes',{{'numeric'}},'write_flag',true);
addCommand(this, 'stop_freq','DPSA:FREQ:STOP %d Hz',...
'default',2e6,'attributes',{{'numeric'}},'write_flag',true);
addCommand(this, 'cent_freq','DPSA:FREQ:CENT %d Hz',...
'default',1.5e6,'attributes',{{'numeric'}},'write_flag',true);
addCommand(this, 'point_no','DPSA:POIN:COUN P%d',...
'default',10401,'attributes',{{'numeric'}},'write_flag',true);
addCommand(this,'enable_avg','TRAC3:DPSA:COUN:ENABLE %d',...
'default',0,'attributes',{{'numeric'}},'write_flag',true);
addCommand(this,'read_cont','INIT:CONT %s','default','on',...
'attributes',{{'char'}},'write_flag',true);
end
- function fetchCallback(this, hObject, eventdata)
+ function fetchCallback(this, hObject, ~)
%Fetches the data using the settings given. This function can
%in principle be used in the future to add further fetch
%functionality.
switch get(hObject,'Tag')
case 'fetch_single'
readSingle(this)
-
end
set(this.Gui.fetch_single,'Value',0);
end
- function enable_avgCallback(this, hObject, eventdata)
+ function enable_avgCallback(this, hObject, ~)
this.enable_avg=get(hObject,'Value');
openDevice(this)
writeProperty(this,'enable_avg',this.enable_avg);
closeDevice(this);
end
function readSingle(this)
openDevice(this);
readStatus(this);
fwrite(this.Device, 'fetch:dpsa:res:trace3?');
data = binblockread(this.Device,'float');
closeDevice(this);
x=this.freq_vec/1e6;
unit_x='MHz';
name_x='Frequency';
%Calculates the power spectrum from the data, which is in dBm.
%Output is in V^2/Hz
power_spectrum = (10.^(data/10))/this.rbw*50*0.001;
-
%Trace object is created containing the data and its units
this.Trace=MyTrace('name','RsaData','x',x,'y',power_spectrum,'unit_y',...
'$\mathrm{V}^2/\mathrm{Hz}$','name_y','Power','unit_x',...
unit_x,'name_x',name_x);
+ %Trigger acquired data event (inherited from MyInstrument)
+ triggerAcquiredData(this);
%Plotting for test purposes - to be removed in the future
figure
this.Trace.plotTrace(gca);
end
end
methods
%Set function for central frequency, changes gui to show central
%frequency in MHz
function set.cent_freq(this, cent_freq)
this.cent_freq=cent_freq;
if this.enable_gui
set(this.Gui.cent_freq,'String',this.cent_freq/1e6);
end
end
%Set function for rbw, changes gui to show rbw in kHz
function set.rbw(this, rbw)
assert(isnumeric(rbw) && rbw>0,'RBW must be a positive double');
this.rbw=rbw;
if this.enable_gui
set(this.Gui.rbw,'String',this.rbw/1e3);
end
end
%Set function for enable_avg, changes gui
function set.enable_avg(this, enable_avg)
assert(isnumeric(enable_avg),...
'Flag for averaging must be a number')
assert(enable_avg==1 || enable_avg==0,...
'Flag for averaging must be 0 or 1')
this.enable_avg=enable_avg;
if this.enable_gui
set(this.Gui.enable_avg,'Value',this.enable_avg)
end
end
%Set function for span, changes gui to show span in MHz
function set.span(this, span)
assert(isnumeric(span) && span>0,...
'Span must be a positive number');
this.span=span;
if this.enable_gui
set(this.Gui.span,'String',this.span/1e6);
end
end
%Set function for start frequency, changes gui to show start
%frequency in MHz
function set.start_freq(this, start_freq)
assert(isnumeric(start_freq),'Start frequency must be a number');
this.start_freq=start_freq;
if this.enable_gui
set(this.Gui.start_freq,'String',this.start_freq/1e6);
end
end
%Set function for stop frequency, changes gui to show stop
%frequency in MHz
function set.stop_freq(this, stop_freq)
assert(isnumeric(stop_freq),...
'Stop frequency must be a number');
this.stop_freq=stop_freq;
if this.enable_gui
set(this.Gui.stop_freq,'String',this.stop_freq/1e6)
end
end
%Set function for average number, also changes GUI
function set.average_no(this, average_no)
assert(isnumeric(average_no),'Number of averages must be a number')
assert(logical(mod(average_no,1))==0 && average_no>0,...
'Number of averages must be a positive integer')
this.average_no=average_no;
if this.enable_gui
set(this.Gui.average_no,'String',this.average_no);
end
end
%Set function for point number, checks it is valid and changes GUI
function set.point_no(this, point_no)
bool=ismember(point_no,this.valid_points);
if bool
this.point_no=point_no;
if this.enable_gui
ind=strcmp(get(this.Gui.point_no,'String'),...
num2str(point_no));
set(this.Gui.point_no,'Value',find(ind));
end
else
error('Invalid number of points chosen for RSA')
end
end
end
methods
%Generates a vector of frequencies between the start and stop
%frequency of length equal to the point number
function freq_vec=get.freq_vec(this)
freq_vec=linspace(this.start_freq,this.stop_freq,...
this.point_no) ;
end
end
end
diff --git a/@MyScope/MyScope.m b/@MyScope/MyScope.m
index f5251ab..65ddca9 100644
--- a/@MyScope/MyScope.m
+++ b/@MyScope/MyScope.m
@@ -1,110 +1,117 @@
classdef MyScope <MyInstrument
properties
Trace;
channel;
end
+ events
+ AcquiredTrace;
+ end
+
methods
function this=MyScope(name, interface, address, varargin)
this@MyInstrument(name, interface, address, varargin{:});
if this.enable_gui; initGui(this); end
createCommandList(this);
createCommandParser(this);
switch interface
case 'TCPIP'
connectTCPIP(this);
case 'USB'
connectUSB(this);
end
end
function connectTCPIP(this)
this.Device= visa('ni',...
sprintf('TCPIP0::%s::inst0::INSTR',this.address));
set(this.Device,'InputBufferSize',1e6);
set(this.Device,'Timeout',2);
end
function connectUSB(this)
this.Device=visa('ni',sprintf('USB0::%s::INSTR',this.address));
set(this.Device,'InputBufferSize',1e6);
set(this.Device,'Timeout',2);
end
-
+
function initGui(this)
set(this.Gui.channel_select, 'Callback',...
@(hObject, eventdata) channel_selectCallback(this, ...
hObject,eventdata));
set(this.Gui.fetch_single, 'Callback',...
@(hObject, eventdata) fetch_singleCallback(this, ...
hObject,eventdata));
set(this.Gui.cont_read, 'Callback',...
@(hObject, eventdata) cont_readCallback(this, ...
hObject,eventdata));
end
function channel_selectCallback(this, hObject, eventdata)
this.channel=get(hObject,'Value');
end
function fetch_singleCallback(this,hObject,eventdata)
readTrace(this);
end
function cont_readCallback(this, hObject, eventdata)
while get(hObject,'Value')
readTrace(this)
end
end
function createCommandList(this)
addCommand(this,'channel','DATa:SOUrce CH%d','default',1,...
'attributes',{{'numeric'}},'write_flag',true);
end
end
methods
function set.channel(this, channel)
if any(channel==1:4)
this.channel=channel;
else
this.channel=1;
warning('Select a channel from 1 to 4')
end
%Sets the gui if the gui is enabled
if this.enable_gui
set(this.Gui.channel_select,'Value',this.channel);
end
end
function readTrace(this)
openDevice(this);
%Sets the channel to be read
writeProperty(this,'channel',this.channel);
%Sets the encoding of the data
fprintf(this.Device,'DATa:ENCdg ASCIi');
% Reading the units of x and y
unit_y = strtrim(query(this.Device,'WFMOutpre:YUNit?'));
unit_x = strtrim(query(this.Device,'WFMOutpre:XUNit?'));
% Reading the vertical spacing between points
step_y = str2num(query(this.Device,'WFMOutpre:YMUlt?'));
% Reading the y axis data
y= str2num(query(this.Device,'CURVe?'))*step_y;
n_points=length(y);
% Reading the horizontal spacing between points
x_step=str2num(query(this.Device,'WFMOutpre:XINcr?'));
%Reads where the zero of the x-axis is
x_zero=str2num(query(this.Device,'WFMOutpre:XZEro?'));
- % calculating the x axis
+ % Calculating the x axis
x=linspace(x_zero,x_zero+x_step*(n_points-1),n_points);
closeDevice(this)
this.Trace=MyTrace('name','ScopeTrace','x',x,'y',y,'unit_x',unit_x(2),...
'unit_y',unit_y(2),'name_x','Time','name_y','Voltage');
+ %Triggers the event for acquired data
+ triggerAcquiredData(this);
+
this.Trace.plotTrace(this.plot_handle);
end
end
end
\ No newline at end of file

Event Timeline