我正在尝试构建一个应用程序,该应用程序收集连续数据并校准,然后在应用程序轴上显示该数据并将数据写入基础工作区,以便可以进一步操作。我希望能够打开和关闭通道,并且能够“打开”或“关闭”每个单独通道的校准。目前,我正在努力让每个通道能够打开和关闭其校准。
我使用以下函数来制作并允许我的 UI 表格可编辑。
function UpdateUITable(app, subsystem)
% Return the initial logical values for checkboxes
app.IndvCal = false(size(subsystem.ChannelNames));
%Channels = cellstr(string(subsystem.ChannelNames));
app.Channels = string(subsystem.ChannelNames);
% Create a cell array with channel names and logical values for the checkboxes
UIData = [app.Channels, app.IndvCal];
% Set the CellEditCallback for the UITable
app.UITable.Data = UIData;
end
function UITableCellEdit(app, event)
indices = event.Indices;
newData = event.NewData;
% Update the logical array based on checkbox changes
app.IndvCal(indices(1)) = newData;
% Update the selected channels variables
app.SelectedCal = app.Channels(app.IndvCal);
app.SelectedChannels = app.Channels(indices(1));
% Call the function that uses the selected channels (e.g., data calibration)
updateChannelMeasurementComponents(app)
end
我使用这些值来确定我拥有的哪些数据将使用以下函数进行校准。我收到此逻辑字符串错误,但我不确定原因。我希望所选的通道显示在我的图表中
function updateLivePlot(app)
% Update the live plot
if isempty(app.DataFIFOBufferch1) || isempty(app.SelectedChannels)
return
end
% Disable interactivity
disableDefaultInteractivity(app.LiveAxes);
% Keep the colors the same after each new data point
app.LiveAxes.ColorOrderIndex = 1;
if isempty(app.LivePlotLine)
% First-Time Setup
app.LivePlotLine = plot(app.LiveAxes, app.TimestampsFIFOBuffer, app.DataFIFOBufferch1(:, app.SelectedChannels));
else
% Update existing plot
for j = 1:numel(app.SelectedChannels)
% Check if the line needs to be extended
if numel(app.LivePlotLine) < j || isempty(app.LivePlotLine(j))
% Use existing axes to plot
app.LivePlotLine(j) = plot(app.LiveAxes, app.TimestampsFIFOBuffer, app.DataFIFOBufferch1(:, app.SelectedChannels(j,1)));
else
% Update existing line
set(app.LivePlotLine(j), 'XData', app.TimestampsFIFOBuffer, 'YData', app.DataFIFOBufferch1(:, app.SelectedChannels(j,1)));
end
end
end
if numel(app.TimestampsFIFOBuffer) > 1
xlim(app.LiveAxes, [app.TimestampsFIFOBuffer(1), app.TimestampsFIFOBuffer(end)]);
end
end
并且该图根据以下函数绘制了校准数据和原始数据。数据连续输入所有功能,并且当在 UI 表中选择通道时(理论上)会改变图表上显示的内容。我想知道是否应该在 UI 表中添加另一列,该列可以是另一个逻辑,可以跟踪通道是否关闭并保持校准逻辑?
unction calibratedData = calibrateData(app,data, slopes, intercepts)
% Calibrate the data using slopes and intercepts
calibratedData = data;
for j = 1:numel(app.SelectedChannels)
if app.SelectedChannels(j,1) == true
calibratedData(:,j) = calibratedData(:,j) * slopes(:,j) + intercepts(:,j);
elseif app.SelectedChannels(j,1) == false
calibratedData = app.data;
app.TimewindowEditField.Value = 10;
else
calibratedData = app.data;
end
end
end
我的startupFCn中也有以下内容
app.UITable.ColumnFormat = {'char', 'logical'};
app.UITable.ColumnEditable = [true, true];
谢谢
对于处理实时数据收集、校准和可视化的动态应用程序来说,您的方法似乎结构良好。包括打开或关闭单个通道校准的功能是一项细致入微的功能,可增强用户对所呈现数据的控制。为了解决您在打开和关闭每个通道校准时遇到的困难,让我们通过一些建议来完善您的策略:
除了跟踪校准之外,在 UI 表中添加另一列来跟踪通道是打开还是关闭是一个好主意。这将使用户能够清晰地控制每个通道的可见性和校准状态。您的表格将包含三列:
UpdateUITable
功能修改您的
UpdateUITable
函数以初始化并填充这个新的可见性列。
function UpdateUITable(app, subsystem)
% Initialize visibility and calibration logical arrays
app.IndvCal = false(size(subsystem.ChannelNames));
app.ChannelVisibility = true(size(subsystem.ChannelNames)); % Assuming you want all channels visible by default
app.Channels = string(subsystem.ChannelNames);
% Create a cell array with channel names, calibration, and visibility values
UIData = [app.Channels, app.IndvCal, app.ChannelVisibility];
% Update the UITable data
app.UITable.Data = UIData;
end
您的
UITableCellEdit
函数需要区分对校准列和可见性列所做的编辑。使用 indices
参数确定编辑了哪一列。
updateLivePlot
功能在绘图函数中,您应该考虑每个通道的校准状态和可见性状态。仅绘制标记为可见的通道的数据。绘图时,检查每个通道的校准状态并根据需要进行校准。
在您的
calibrateData
函数中,您尝试基于布尔标志应用校准,但逻辑似乎略有偏差。您应该迭代每个通道,检查是否选择它进行校准,然后应用相应的斜率和截距(如果是)。
这是您可以如何处理它的简化版本:
function calibratedData = calibrateData(app, data, slopes, intercepts)
% Initialize calibrated data array
calibratedData = data;
for j = 1:numel(app.SelectedChannels)
if app.IndvCal(j) % Check if calibration is enabled for this channel
% Apply calibration
calibratedData(:,j) = data(:,j) * slopes(j) + intercepts(j);
end
% Note: No need for an 'else' block if we're not changing data for non-calibrated channels
end
end
如果
slopes
和 intercepts
是数组,请确保它们的索引正确。
对于处理连续数据更新的应用程序,请确保您的数据结构(如 FIFO 缓冲区)和绘图更新机制针对性能进行了优化。这包括最大限度地减少复制或移动的数据,并有效地更新绘图数据点,而不是重新绘制整个绘图。
调整您的应用程序以区分通道可见性和校准状态将显着提高其灵活性。始终牢记用户体验,确保 UI 直观且响应灵敏。彻底测试您的应用程序,尤其是实时数据处理和 UI 交互部分,以微调性能和可用性。