📄 xferplot.m
字号:
% 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 datablock_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 plotsfor 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';endset(hstem, ... 'color', stem_rgb, ... 'visible', stemVis, ... 'marker', 'none');% Determine x-axis limits:% ------------------------switch block_data.params.Domaincase 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 scalarif 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]);endset(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;endhxLabel = get(hax, 'XLabel');set(hxLabel, 'String', xLabel);% Setup Y-axis label and limits:% ------------------------------yLabel = block_data.params.YLabel;if ~isstr(yLabel), yLabel='Y-Axis'; endhyLabel = 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.%% NOTE: update_lines() does NOT alter/update the x-data,% so it needs to be set up once here, correctly.% The y-data is not significant ... just needs to be% sized appropriately:xLen=length(xData);uNaN = NaN;for i=1:length(hline), yData = get(hline(i),'YData')'; % Manufacture the right yData if default is present: if length(yData) ~= xLen, yData = uNaN(ones(xLen,1)); end set(hline(i),'XData',xData, 'YData',yData);end% Setup "stem" line data:% -----------------------% Stems are implemented as a SECOND line% The usual data plotting occurs, but with a circle ('o')% substituted for the marker.% In addition, a second line is set up for the vertical% stems themselves.%% We only need to set up ONE stem line.% The vertical extent will reach to the "highest" point% at each sample time, effectively providing a stem for% *all* data channels at one time.%% Vertical stem data:%% [x1 x1 x1 x2 x2 x2 x3 x3 x3 ....]% [0 y1 NaN 0 y2 NaN 0 y3 NaN ...]xstem = [xData';xData';xData'];xstem = xstem(:)'; % triplicate each valueymin = 0; % stems originate from y=0, not block_data.params.YMinystem = [ymin;0;NaN]; % assume y values are 0 for nowystem = ystem(:,ones(size(xData)));ystem = ystem(:)';set(hstem, 'xdata', xstem, 'ydata', ystem);% Perform AxisZoom:% -----------------%% Put axis into correct zoom state:fig_data = get(hfig,'UserData');if strcmp(block_data.params.AxisZoom,'off'), % Turn off AxisZoom: % - turn on menus set(fig_data.menu.top,'vis','on'); % - reset axis position set(hax, fig_data.main.axiszoom.off{:});
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -