📄 xferplot.m
字号:
params1 = rmfield(params1,nop);
params2 = rmfield(params2,nop);
y = ~isequal(params1,params2);
% ---------------------------------------------------------------
function DialogApply(params,block_name)
% Called from MaskInitialization command via:
% sdspfscope2([],[],[],'DialogApply',params);
% Updates block_data
% In case of call from an internal method (not a callback)
% For example, SetAndApply calls us directly, and gcb might
% not be correct...
if nargin<2,
block_name = gcb;
end
block_data = get_param(block_name, 'UserData');
if isempty(block_data),
return; % System has not run yet
end
% Check dialog parameters:
% ------------------------
msg = CheckParams(block_name, params);
if ~isempty(msg),
% Invalid parameters
errordlg(msg,'Frame Scope Dialog Error','modal');
RevertDialogParams(block_name);
return
end
% On start-up, no params field exists
% Set params, and skip any further processing
if ~isfield(block_data,'params'),
block_data.params = params;
set_param(block_name, 'UserData', block_data);
return;
end
% Check for a run-time change in the scaling or units:
if relevant_params_changed(params, block_data.params),
if isempty(block_data.hfig),
% Scope window is not open
% Just record new param info:
block_data.params = params;
set_param(block_name, 'UserData', block_data);
return;
end
% Scope window is open and a change has been made
% Update menu checks:
SetMenuChecks(block_name);
% Handle figure position changes here:
% Only update if the current block dialog FigPos differs from
% the cached block_data FigPos. The figure itself might be at
% a different position, which we should not change UNLESS the
% user actually made an explicit change in the mask (or, hit
% the RecordFigPos menu item, which simply changes the mask).
if ~isequal(block_data.params.FigPos, params.FigPos),
set(block_data.hfig,'Position',params.FigPos);
end
% Could check for a change in YUnits (Amplitude <-> dB)
% Start autoscale if changed
% start_autoscale = ~isequal(block_data.params.YUnits, params.YUnits);
% OBJECTIVES:
%
% 1 - formulate a "u" vector that emulates that which Simulink
% would have passed in on a standard "mdlUpdate" call.
% 2 - update the display if the number of horiz frames has changed
% 3 - call setup_axes
% Get currently displayed line data, before any
% new dialog param changes are instated.
%
% xdata = get(block_data.hline(1),'xdata');
u_disp = get(block_data.hline, 'ydata');
if iscell(u_disp),
% If we have a cell, then length(block_data.hline) > 1
% This was caused by a multi-channel display
%
ndepc = length(u_disp{1}); % (# display elements per chan) = (samples/frame)*(nframes)
nchans = length(u_disp); % number of channels
u_disp = [u_disp{:}]; % make it one long vector
u_disp = reshape(u_disp,ndepc,nchans);
else
% Reshape in case of multiple channels (matrix input)
% Also, corrects for HG giving us a 1xN when it should be Nx1 per channel
nchans = 1;
if (block_data.NChans ~= nchans),
error('Number of channels is incorrect.');
end
ndepc = length(u_disp(:));
u_disp = reshape(u_disp, ndepc, block_data.NChans);
end
% Determine samples per frame
% NOTE: could be multiple channels of data,
% and multiple horizontal frames per channel.
% Disregard param if freq domain
orig_horizspan = block_data.params.HorizSpan;
orig_samples_per_frame = block_data.samples_per_frame;
% Formulate "emulated input, u" from u_disp
%
if (orig_horizspan == 1),
% Only one frame in display span
% The input, u, to mdlUpdate is u_disp itself
u = u_disp;
else
% More than one frame in horiz span
% The input, u, from Simulink is only one frame
% Hence, we must keep only one frame from u_disp
% We choose to keep the most recent:
u = u_disp(end - orig_samples_per_frame+1:end, :);
end
% Update displayed data
%
% xxx must also update stem lines
%
if params.HorizSpan ~= orig_horizspan,
% Number of displayed frames has changed
if params.HorizSpan > orig_horizspan,
% new horiz span exceeds span in current display
% we need to "manufacture" additional input data
ydata = u_disp;
padframes = params.HorizSpan - orig_horizspan;
prepad = NaN * ones(padframes*orig_samples_per_frame, nchans);
ydata = [prepad; ydata];
else % if params.HorizSpan < orig_horizspan,
% new horiz span is less than span in current display
%
% retain only the most recent frames for the display
f1 = orig_horizspan - (params.HorizSpan-1); % first frame
f2 = orig_horizspan; % last frame
s1 = (f1-1)*orig_samples_per_frame+1; % 1st sample in 1st frame
s2 = f2*orig_samples_per_frame; % last sample of last frame
ydata = u_disp(s1:s2,:);
end
% We can make up any xdata, as long as it has the right length,
% since setup_axes will correct the values:
xdata = (1:size(ydata,1))';
for i=1:nchans,
set(block_data.hline(i),'xdata',xdata, 'ydata',ydata(:,i));
end
end
% Must "undo" any preprocessing performed on data
% to emulate Simulink's input data to block
%
% Use "old" params to determine how to undo processing.
if (block_data.params.Domain==2),
% Convert from dB back to linear, if required:
if block_data.params.YUnits == 2,
u = dB2lin(u);
end
% Unrotate data if display range is [-Fn, Fn]:
if block_data.params.XRange == 2,
% unrotate each channel of data:
p = orig_samples_per_frame/2; % all FFT's are a power of 2 here
u = u([p+1:orig_samples_per_frame 1:p],:);
end
end
% Record new param info:
block_data.params = params;
% Cache the appropriate line-update function
%
% If HorizSpan, NChans, or Domain changed, this will need updating:
block_data.UpdateLinesFcn = select_UpdateLinesFcn(block_data);
set_param(block_name, 'UserData', block_data);
% Adjust the GUI axes, line styles, etc,
setup_axes(block_name);
end
% ---------------------------------------------------------------
function setup_axes(block_name)
% Setup scope x- and y-axes
% Does not alter block_data
% u = input data, one frame of data
block_data = get_param(block_name,'UserData');
hfig = block_data.hfig;
hax = block_data.haxis;
hline = block_data.hline;
hstem = block_data.hstem;
nframes = block_data.params.HorizSpan;
nchans = block_data.NChans;
samples_per_channel = block_data.samples_per_frame;
% [samples_per_channel, nchans] = size(u);
% Clear memory (persistence):
% ---------------------------
FigRefresh([],[],block_data.hfig);
% Assign line colors and styles:
% ------------------------------
stem_rgb = 'k'; % in case no lines use stem plots
for i=1:length(hline),
rgb = getDialogLineColor(block_name, i);
style = getDialogLineStyle(block_name, i);
marker = getDialogLineMarker(block_name, i);
disable = getDialogLineDisable(block_name, i);
markerface = 'auto'; % rgb;
% There is only one set of stem lines, so we need to deduce
% which line color/style to set it to. We could use multiple
% stem lines, but that seems like it would use significantly
% more time/memory without much improvement.
if strcmp(marker,'stem'),
% Set stem line style
% If style is 'none', use solid:
if strcmp(lower(style),'none'),
style='-';
end
set(hstem,'linestyle',style);
stem_rgb = rgb; % use the "last" stem color
% Reset some properties for stem markers:
style='none';
marker='o';
end
set(hline(i), ...
'Color', rgb, ...
'LineStyle', style, ...
'Visible', disable, ...
'Marker', marker, ...
'MarkerFaceColor',markerface);
end
% Setup vertical stem lines:
if anyStemMarkers(block_name),
stemVis='on';
else
stemVis='off';
end
set(hstem, ...
'color', stem_rgb, ...
'visible', stemVis, ...
'marker', 'none');
% Determine x-axis limits:
% ------------------------
switch block_data.params.Domain
case 1
% Time-domain:
if block_data.Ts<0,
% Triggered:
ts = 1;
xLabel = 'Trigger events (samples)';
else
ts = block_data.Ts;
xLabel = 'Time (s)';
end
xData = (0:samples_per_channel*nframes-1)' * ts;
if (samples_per_channel==1) & (nframes==1),
xLimits = [-ts ts]; % prevent problems
else
xLimits = [-ts xData(end)+ts];
end
case 2
% Frequency domain:
% Disregard # horiz frames (nframes) for freq domain
% sample time can be inherited, but is usually overridden by user
if isOn(block_data.params.InheritXIncr),
% Inherited sample rate:
if block_data.Ts==-1,
Fs = samples_per_channel; % unusual, but we'll allow it
else
% This is either the Spectrum Scope, or the Vector Scope
% set to the Freq domain.
%
% We may have a buffer of data here, due to:
% - an inherited frame, or
% - explicit buffering parameters
%
% NOTE: .Ts is the per-frame time, not per-sample time
% Determine if explicit buffered is being used:
% - this must be a spectrum scope block, and
% - the buffered checkbox (UseBuffer) is set
if strcmp(get_param(block_name,'MaskType'), 'Spectrum Scope'),
isExplicitBuffer = isOn(block_data.params.UseBuffer);
else
isExplicitBuffer=0;
end
if isExplicitBuffer,
buffer_size = block_data.params.BufferSize;
buffer_overlap = block_data.params.Overlap;
else
buffer_size = samples_per_channel; % assume frame input
buffer_overlap = 0; % assume no overlap
end
Fs = 1 ./ block_data.Ts; % sample rate
end
else
% User-defined sample time for frequency domain:
Fs = 1 ./ block_data.params.XIncr; % sample rate
end
Fn = Fs/2; % Nyquist rate
xData = (0 : samples_per_channel-1)' .* Fs ./ samples_per_channel;
switch block_data.params.XRange
case 1,
xLimits = [0 Fn];
case 2,
xLimits = [-Fn Fn];
xData = (0:samples_per_channel-1)' .* Fs ./ samples_per_channel - Fn;
otherwise,
xLimits = [0 Fs];
end
if block_data.params.XUnits == 1,
xLabel = 'Frequency (Hz)';
else
xLabel = 'Frequency (rad/s)';
xLimits = 2*pi * xLimits;
xData = 2*pi * xData;
end
otherwise
% User-defined
% Determine sample increment if inherited:
if isOn(block_data.params.InheritXIncr),
if block_data.Ts==-1, % triggered system?
incr = 1; % unusual, but we'll allow it
else
incr = block_data.Ts;
end
else
incr = block_data.params.XIncr;
end
xLabel = block_data.params.XLabel;
if ~isstr(xLabel), xLabel = 'X-Axis'; end
xData = (0:samples_per_channel*nframes-1)' * incr;
if (samples_per_channel==1) & (nframes==1),
xLimits = [-incr incr]; % prevent problems
else
xLimits = [-incr xData(end)+incr];
end
end
% Adjust x-axes for engineering units:
% ------------------------------------
% Allow scalar
if xLimits(2)==0,
xLimits=[0 1];
elseif (xLimits(1) > xLimits(2)),
warning(sprintf(['Reversing the order of X-axis limits entered in scope block: %s\n', ...
'Limits must appear in ascending order.'], block_name));
xLimits(1:2)=xLimits([2 1]);
end
set(hax,'xLim',xLimits); % preliminary gridding of limits
% Don't adjust the user-defined domain:
if (block_data.params.Domain ~= 3),
xlim = get(hax,'xlim');
if block_data.params.Domain==1,
% engunits will use us/ms, and s/mins/hrs where applicable
[xunits_val,xunits_exp,xunits_prefix] = engunits(max(abs(xlim)),'latex','time');
else
[xunits_val,xunits_exp,xunits_prefix] = engunits(max(abs(xlim)),'latex','freq');
end
xData = xData .* xunits_exp;
set(hax, 'xlim', xlim .* xunits_exp);
end
% Setup X-axis label:
% -------------------
% Don't modify user-defined domain:
if block_data.params.Domain == 2,
% Freq - insert units only 'Freq (Hz)' => 'Freq (kHz)'
i = find(xLabel=='(');
s = [xLabel(1:i) xunits_prefix xLabel(i+1:end)];
xLabel = s;
elseif block_data.params.Domain==1,
% Time - remove everything between parens 'Horiz (s)' => 'Horiz (days)'
i = find(xLabel=='('); j = find(xLabel==')');
s = [xLabel(1:i) xunits_prefix xLabel(j:end)];
xLabel = s;
end
hxLabel = get(hax, 'XLabel');
set(hxLabel, 'String', xLabel);
% Setup Y-axis label and limits:
% ------------------------------
yLabel = block_data.params.YLabel;
if ~isstr(yLabel), yLabel='Y-Axis'; end
hyLabel = get(hax,'YLabel');
set(hyLabel, 'String', yLabel);
set(hax, 'ylimmode','manual', ...
'ylim',[block_data.params.YMin block_data.params.YMax]);
% Setup line data:
% ----------------
% Don't draw anything, so use NaN's for Y-data.
% Can use vectorized set since all x/y data are identical.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -