exponenta event banner

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

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

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

Определите расположение анализируемого набора файлов.

dataDir = '*.dat';

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

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

fileList = dir(dataDir);
fileName = {fileList(:).name}';
fileDir  = {fileList(:).folder}';
fullFilePath = fullfile(fileDir, fileName)
fullFilePath = 5x1 cell
    {'/tmp/BR2021ad_1655202_62692/mlx_to_docbook1/tp4da62608/vnt-ex86857001/ADAC.dat' }
    {'/tmp/BR2021ad_1655202_62692/mlx_to_docbook1/tp4da62608/vnt-ex86857001/ECE.dat'  }
    {'/tmp/BR2021ad_1655202_62692/mlx_to_docbook1/tp4da62608/vnt-ex86857001/HWFET.dat'}
    {'/tmp/BR2021ad_1655202_62692/mlx_to_docbook1/tp4da62608/vnt-ex86857001/SC03.dat' }
    {'/tmp/BR2021ad_1655202_62692/mlx_to_docbook1/tp4da62608/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 используется для отображения первых 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. The axes with title Distribution of Event Duration contains an object of type histogram.

Теперь посмотрите на Mean Power vs. Продолжительность события.

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. The axes 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/BR2021ad_1655202_62692/mlx_to_docbook1/tp4da62608/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. The axes with title HWFET.dat contains 2 objects of type line. These objects represent Raw Signal, Event.

Закрыть файл

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

clear mdfObj