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

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

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

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

dataDir = '*.dat';

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

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

fileList = dir(dataDir);
fileName = {fileList(:).name}';
fileDir  = {fileList(:).folder}';
fullFilePath = fullfile(fileDir, fileName)
fullFilePath = 5x1 cell
    {'/tmp/BR2021bd_1751886_255755/mlx_to_docbook1/tp43650a5e/vnt-ex86857001/ADAC.dat' }
    {'/tmp/BR2021bd_1751886_255755/mlx_to_docbook1/tp43650a5e/vnt-ex86857001/ECE.dat'  }
    {'/tmp/BR2021bd_1751886_255755/mlx_to_docbook1/tp43650a5e/vnt-ex86857001/HWFET.dat'}
    {'/tmp/BR2021bd_1751886_255755/mlx_to_docbook1/tp43650a5e/vnt-ex86857001/SC03.dat' }
    {'/tmp/BR2021bd_1751886_255755/mlx_to_docbook1/tp43650a5e/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-файл анализируется атомарно и возвращается в его собственный индекс получившегося массива ячеек. Это позволяет функции обработки усиливать возможность параллельных вычислений с parforparfor и стандартный 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'

Figure contains an axes object. The axes object with title Distribution of Event Duration contains an object of type histogram.

Теперь посмотрите на Среднюю Степень по сравнению с Продолжительностью события.

scatter(eventSummary.MeanPower_KW, minutes(eventSummary.EventDuration))
grid on
xlabel 'MeanPower(KW)'
ylabel 'Event Duration (minutes)'
title 'Mean Power vs. Event Duration'

Figure contains an axes object. The axes object with title Mean Power vs. Event Duration contains an object of type scatter.

Глубокое погружение мероприятие

Смотрите событие, которое длилось больше 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

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

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

   File Details
                 Name: 'HWFET.dat'
                 Path: '/tmp/BR2021bd_1751886_255755/mlx_to_docbook1/tp43650a5e/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: [1x1 struct]

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

   Options
           Conversion: Numeric

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

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

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

data = read(mdfObj, chInfo)
data = 1x1 cell array
    {79176x1 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)

Figure contains an axes object. The axes object with title HWFET.dat contains 2 objects of type line. These objects represent Raw Signal, Event.

Закройте файл

Закройте доступ к MDF-файлу путем очищения его переменной из рабочей области.

clear mdfObj
Для просмотра документации необходимо авторизоваться на сайте