对多个 MDF 文件进行数据分析
以下示例说明如何研究多个驾驶周期间放电模式下的车辆电池电量。用于此分析的数据包含在一组 MDF 格式的车辆日志文件中。对于此示例,我们需要建立一种机制,用于“检测”车辆电池何时处于给定模式。我们真正要做的是建立一个探测器,以确定何时关注的信号(在本例中为电池电量)满足特定条件。当条件得到满足时,我们称之为一个“事件”。每个事件都需要满足一定的时间限制才算是“合格”事件。也就是说,事件至少要持续 5 秒,才算是一个“合格的”事件。这种鉴定步骤有助于限制噪声和消除瞬变。此示例中显示的阈值仅用于举例说明。
设置数据源位置
定义要分析的文件集的位置。
dataDir = '*.dat';
获取文件集信息
将要分析的所有 MDF 文件的名称放入一个元胞数组中。
fileList = dir(dataDir); fileName = {fileList(:).name}'; fileDir = {fileList(:).folder}'; fullFilePath = fullfile(fileDir, fileName)
fullFilePath = 5x1 cell
{'/tmp/Bdoc24a_2511836_3070643/tp8879c7f7/vnt-ex86857001/ADAC.dat' }
{'/tmp/Bdoc24a_2511836_3070643/tp8879c7f7/vnt-ex86857001/ECE.dat' }
{'/tmp/Bdoc24a_2511836_3070643/tp8879c7f7/vnt-ex86857001/HWFET.dat'}
{'/tmp/Bdoc24a_2511836_3070643/tp8879c7f7/vnt-ex86857001/SC03.dat' }
{'/tmp/Bdoc24a_2511836_3070643/tp8879c7f7/vnt-ex86857001/US06.dat' }
预分配输出数据元胞数组
使用一个元胞数组来捕获一组迷你表,这些表用来表示每个 MDF 文件所关注的事件数据。
numFiles = size(fullFilePath, 1); eventSet = cell(numFiles, 1)
eventSet=5×1 cell array
{0x0 double}
{0x0 double}
{0x0 double}
{0x0 double}
{0x0 double}
定义事件检测和通道信息条件
chName = 'Power'; % Name of the signal of interest in the MDF files thdValue = [5, 55]; % Threshold in KW thdDuration = seconds(5); % Threshold for event qualification
循环遍历每个 MDF 文件并应用事件检测器函数
eventSet
是一个元胞数组,其中包含已分析的每个文件的摘要表。您可以将这个由表组成的元胞数组视为一组迷你表,所有这些迷你表都具有相同的格式,但每个迷你表的内容分别对应于不同的 MDF 文件。
在此示例中,事件检测器不仅报告事件的开始和结束时间,还报告有关事件本身的一些描述性统计量。这种聚合和报告可用于发现活动和对活动进行故障排除。要更详细地了解 MDF 文件对接和数据处理,请打开并探查此示例中的 processMDF
函数。
请注意本例的数据处理方式,它以原子方式解析每个 MDF 文件,并将解析结果返回到结果元胞数组中对应的索引位置。这允许处理函数通过 parfor
利用并行计算功能。parfor
和标准 for
在输出方面可以互换,但两者在完成分析所需的处理时间上有所不同。要试验并行计算,只需将下面的 for
调用更改为 parfor
并运行示例即可。
for i = 1:numFiles eventSet{i} = processMDF(fullFilePath{i}, chName, thdValue, thdDuration); end eventSet{1}
ans=20×8 table
FileName EventNumber EventDuration EventStart EventStop MeanPower_KW MaxPower_KW MinPower_KW
________ ___________ _____________ __________ __________ ____________ ___________ ___________
ADAC.dat 2 00:01:22 19.345 sec 101.79 sec 28.456 53.5 5
ADAC.dat 3 00:00:08 107.82 sec 116.36 sec 21.295 53.5 5.09
ADAC.dat 5 00:00:55 123.8 sec 179.67 sec 28.642 37.2 5.01
ADAC.dat 6 00:00:10 189.83 sec 200.36 sec 11.192 54.4 5.1
ADAC.dat 8 00:00:40 212.4 sec 252.79 sec 28.539 37.4 5.01
ADAC.dat 9 00:00:08 258.76 sec 267.37 sec 21.289 53.7 5.02
ADAC.dat 11 00:00:44 274.81 sec 319.79 sec 28.554 37.2 5.08
ADAC.dat 12 00:00:08 325.75 sec 334.37 sec 21.279 53.7 5.05
ADAC.dat 14 00:00:44 341.81 sec 386.79 sec 28.554 37.2 5.08
ADAC.dat 15 00:00:08 392.75 sec 401.37 sec 21.278 53.7 5.04
ADAC.dat 17 00:00:44 408.81 sec 453.67 sec 28.579 37.2 5.08
ADAC.dat 18 00:00:07 463.77 sec 471.37 sec 11.895 54.676 5.04
ADAC.dat 20 00:00:40 483.44 sec 523.79 sec 28.544 37.363 5.0682
ADAC.dat 21 00:00:08 529.75 sec 538.37 sec 21.279 53.7 5.05
ADAC.dat 23 00:00:44 545.81 sec 590.79 sec 28.553 37.2 5.08
ADAC.dat 24 00:00:08 596.75 sec 605.37 sec 21.279 53.7 5.05
⋮
串联结果
将元胞数组 eventSet
的内容合并到一个表中。我们现在可以使用表 eventSummary
进行后续分析。head
函数用于显示表 eventSummary
的前 5 行。
eventSummary = vertcat(eventSet{:}); disp(head(eventSummary, 5))
FileName EventNumber EventDuration EventStart EventStop MeanPower_KW MaxPower_KW MinPower_KW ________ ___________ _____________ __________ __________ ____________ ___________ ___________ ADAC.dat 2 00:01:22 19.345 sec 101.79 sec 28.456 53.5 5 ADAC.dat 3 00:00:08 107.82 sec 116.36 sec 21.295 53.5 5.09 ADAC.dat 5 00:00:55 123.8 sec 179.67 sec 28.642 37.2 5.01 ADAC.dat 6 00:00:10 189.83 sec 200.36 sec 11.192 54.4 5.1 ADAC.dat 8 00:00:40 212.4 sec 252.79 sec 28.539 37.4 5.01
可视化摘要结果以确定后续步骤
查看事件持续时间的概览。
histogram(eventSummary.EventDuration) grid on title 'Distribution of Event Duration' xlabel 'Event Duration (minutes)' ylabel 'Frequency'
现在看看均值电量与事件持续时间。
scatter(eventSummary.MeanPower_KW, minutes(eventSummary.EventDuration)) grid on xlabel 'MeanPower(KW)' ylabel 'Event Duration (minutes)' title 'Mean Power vs. Event Duration'
深入分析关注的事件
检查持续时间超过 4 分钟的事件。首先,创建一个封装来查找关注的情形。msk
是逻辑索引,用于显示表 eventSummary
的哪些行满足指定的条件。
msk = eventSummary.EventDuration > minutes(4);
提取表 eventSummary
中满足指定条件的行并显示结果。
eventOfInterest = eventSummary(msk, :); disp(eventOfInterest)
FileName EventNumber EventDuration EventStart EventStop MeanPower_KW MaxPower_KW MinPower_KW _________ ___________ _____________ __________ __________ ____________ ___________ ___________ HWFET.dat 18 00:04:43 297.22 sec 580.37 sec 12.275 30.2 5.0024
在整个驾驶周期背景中可视化此事件
我们需要完整的文件路径和文件名来从 MDF 文件中读取数据。表 eventOfInterest
具有文件名,因为我们对其进行了跟踪。它没有该文件的完整文件路径。为了获得这些信息,我们会对原始文件名和路径列表进行一些集合处理。首先,找到关注的文件的完整文件路径。
fileMsk = find(ismember(fileName, eventOfInterest.FileName))
fileMsk = 3
使用 mdfRead
从 MDF 文件中读取感兴趣的通道数据。
data = mdfRead(fullFilePath{fileMsk}, Channel=chName)
data = 1x1 cell array
{79176x1 timetable}
data{1}
ans=79176×1 timetable
time Power
_____________ _________
0.0048987 sec 0
0.0088729 sec 0
0.01 sec 0
0.013223 sec 0
0.016446 sec 0
0.019668 sec 0
0.02 sec 0
0.021658 sec -2.4e-28
0.023878 sec -3.42e-15
0.026098 sec -1.04e-14
0.027766 sec -1.9e-14
0.029433 sec -3.14e-14
0.03 sec -3.66e-14
0.031341 sec -5.14e-14
0.032681 sec -6.92e-13
0.034022 sec -1.56e-12
⋮
使用自定义绘图函数进行可视化
自定义绘图函数可用于封装和重用。在整个驾驶周期背景中可视化事件。要了解可视化的创建方式,请打开并探查此示例中的 eventPlotter
函数。
eventPlotter(data{1}, eventOfInterest)