Приложение анализа данных со многими MDF-файлами

Этот пример показывает вам, как исследовать питание от батареи автомобиля во время режима выброса через различные циклы диска. Данные для этого анализа содержатся в наборе файлов журнала автомобиля в формате MDF. В данном примере мы должны создать механизм, который может "обнаружить", когда батарея автомобиля находится в данном режиме. То, что мы действительно делаем, создает детектор, чтобы определить, когда сигнал интереса (питание от батареи в этом случае) соответствует определенным критериям. Когда критериям будут соответствовать, мы вызовем это "событие". Каждое событие будет впоследствии "квалифицировано" внушительными границами времени. То есть событие "квалифицировано", если оно сохраняется в течение по крайней мере 5 секунд (такой шаг проверки может помочь ограничить шум и удалить переходные процессы). Пороги, показанные в этом примере, иллюстративны только.

Установите местоположение источника данных

Задайте местоположение набора файла, чтобы анализировать.

dataDir = '*.dat';

Получите информацию о наборе файла

Заставьте имена всех MDF-файлов анализировать в массив отдельной ячейки.

fileList = dir(dataDir);
fileName = {fileList(:).name}';
fileDir  = {fileList(:).folder}';
fullFilePath = fullfile(fileDir, fileName)
fullFilePath = 10×1 cell array
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\ADAC.dat' }
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\ECE.dat'  }
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\FTP75.dat'}
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\HUDDS.dat'}
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\HWFET.dat'}
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\JC08.dat' }
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\LA92.dat' }
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\NEDC.dat' }
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\SC03.dat' }
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\US06.dat' }

Предварительно выделите массив ячеек выходных данных

Используйте массив ячеек, чтобы получить набор мини-таблиц, которые представляют представляющие интерес данные о событиях для каждого отдельного MDF-файла.

numFiles = size(fullFilePath, 1);
eventSet = cell(numFiles, 1)
eventSet = 10×1 cell array
    {0×0 double}
    {0×0 double}
    {0×0 double}
    {0×0 double}
    {0×0 double}
    {0×0 double}
    {0×0 double}
    {0×0 double}
    {0×0 double}
    {0×0 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 используется, чтобы отобразить первые 5 строк таблицы eventSummary.

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 = 5

Создайте объект MDF считать данные из MDF-файла.

mdfObj = mdf(fullFilePath{fileMsk})
mdfObj = 
  MDF with properties:

   File Details
                 Name: 'HWFET.dat'
                 Path: '\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\HWFET.dat'
               Author: ''
           Department: ''
              Project: ''
              Subject: ''
              Comment: ''
              Version: '3.00'
             DataSize: 3167040
     InitialTimestamp: 2017-08-09 12:20:03.000000000

   Creator Details
    ProgramIdentifier: 'MDA v7.1'
              Creator: [0×0 struct]

   File Contents
           Attachment: [0×0 struct]
         ChannelNames: {{5×1 cell}}
         ChannelGroup: [1×1 struct]

Идентифицируйте канал с channelList и считайте все данные из этого файла.

chInfo = channelList(mdfObj, chName)
chInfo=1×9 table
    ChannelName    ChannelGroupNumber    ChannelGroupNumSamples    ChannelGroupAcquisitionName    ChannelGroupComment    ChannelDisplayName    ChannelUnit    ChannelComment    ChannelDescription
    ___________    __________________    ______________________    ___________________________    ___________________    __________________    ___________    ______________    __________________

      "Power"              1                     79176                     <undefined>                cg comment                 ""            cg comment       cg comment              ""        

data = read(mdfObj, chInfo)
data = 1×1 cell array
    {79176×1 timetable}

Обратите внимание на то, что чтение с выводом channelList возвращает массив ячеек результатов.

data{1}(1:10,:)
ans=10×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

Визуализируйте Используя пользовательскую функцию построения графика

Пользовательские функции построения графика полезны для инкапсуляции и повторного использования. Визуализируйте событие в контексте целого цикла диска. Чтобы понять, как визуализация была создана, откройте и исследуйте функцию eventPlotter от этого примера.

eventPlotter(data{1}, eventOfInterest)