Main Content

本页翻译不是最新的。点击此处可查看最新英文版本。

将通道组数据从现有 MDF 文件写入新 MDF 文件

此示例说明如何处理在 MDF 文件的通道组中记录的数据,并将更新后的数据写入新文件。此示例 VehicleData.mf4 中使用的 MDF 文件包含从两个通道组中的两个仿真记录的数据,但该示例仅处理通道组 2 中的数据。

首先需要将通道组 2 中的数据读入一个时间表,然后对数据副本执行后处理。最后,您需要创建一个与 VehicleData.mf4 具有相同文件元数据的新 MDF 文件,并将更新后的数据作为新通道组写入新 MDF 文件。

打开 MDF 文件

使用 mdf 函数来开启对 MDF 文件的访问。

mdfObj = mdf("VehicleData.mf4")
mdfObj = 
  MDF with properties:

   File Details
                 Name: 'VehicleData.mf4'
                 Path: '/tmp/Bdoc22a_1880208_151076/tp5e0c0350/vnt-ex28629694/VehicleData.mf4'
               Author: ''
           Department: ''
              Project: ''
              Subject: ''
              Comment: 'Example file demonstrating workflows of writing to MDF files.'
              Version: '4.10'
             DataSize: 2252350
     InitialTimestamp: 2022-01-20 01:22:34.000000000

   Creator Details
    ProgramIdentifier: 'MATLAB'
              Creator: [1x1 struct]

   File Contents
           Attachment: [1x1 struct]
         ChannelNames: {2x1 cell}
         ChannelGroup: [1x2 struct]

   Options
           Conversion: Numeric

检查有关两个通道组的详细信息。

mdfObj.ChannelGroup
ans=1×2 struct array with fields:
    AcquisitionName
    Comment
    NumSamples
    DataSize
    Sorted
    SourceInfo
    Channel

读取包含元数据的通道组数据

使用可选参数 IncludeMetadata 设置为 trueread 函数从通道组 2 读取数据。输出时间表 chanGrp2TT 是通道组 2 中所有通道的数据的副本。

chanGrp2TT = read(mdfObj, 2, IncludeMetadata=true)
chanGrp2TT=92033×3 timetable
         Time         AirFlow    FuelRate       time   
    ______________    _______    ________    __________

    0 sec             17.294       1.209              0
    0.00056199 sec    17.263       1.209     0.00056199
    0.0033719 sec     17.112       1.209      0.0033719
    0.01 sec          16.776      1.1729           0.01
    0.02 sec          16.316      1.1409           0.02
    0.03 sec          15.907      1.1124           0.03
    0.04 sec          15.546      1.0873           0.04
    0.05 sec          15.228      1.0652           0.05
    0.055328 sec      15.075      1.0652       0.055328
    0.055328 sec      15.075      1.0652       0.055328
    0.055328 sec      15.075      1.0652       0.055328
    0.06 sec          14.949      1.0458           0.06
    0.064672 sec      14.832      1.0458       0.064672
    0.07 sec          14.707      1.0289           0.07
    0.08 sec          14.497      1.0143           0.08
    0.09 sec          14.317      1.0019           0.09
      ⋮

通道组 2 及其通道的元数据作为自定义属性显示在时间表中。一个通道组的元数据存储为整个表的时间表自定义属性,属性名称以“ChannelGroup”为前缀。各个通道的元数据存储为各变量的时间表自定义属性,属性名称以“Channel”为前缀。

查看通道组 2 和此组中所有通道的元数据。

chanGrp2TT.Properties.CustomProperties
ans = 
CustomProperties with properties:

    ChannelGroupAcquisitionName: ""
            ChannelGroupComment: "Simulation of engine gas dynamics."
         ChannelGroupSourceInfo: [1x1 struct]
             ChannelDisplayName: [""    ""    ""]
                 ChannelComment: [""    ""    ""]
                    ChannelUnit: ["g/s"    "g/s"    "s"]
                    ChannelType: [FixedLength    FixedLength    Master]
                ChannelDataType: [RealLittleEndian    ...    ]
                 ChannelNumBits: [64 64 64]
           ChannelComponentType: [None    None    None]
         ChannelCompositionType: [None    None    None]
              ChannelSourceInfo: [1x3 struct]
              ChannelReadOption: [Numeric    Numeric    Numeric]

请注意,在调用 read 函数时,默认情况下,IncludeMetadata 设置为 false。因此,如果您读取通道组数据的最终目标是写入新通道组,并保留通道组和通道元数据,则 IncludeMetadata 必须设置为 true

减少数据副本中的采样数

使用 stackedplot 创建一个堆叠图,以可视化通道 AirFlowFuelRate 中的数据。

stackedplot(chanGrp2TT, ["AirFlow", "FuelRate"])

Figure contains an object of type stackedplot.

从该堆叠图中可以观察到,从大约 182.17 秒处到 900 秒处的记录结束位置,FuelRate 的值保持在 0,这表明在测量期间可能有故障。对于此特定应用,当 FuelRate 的值无效时,AirFlow 的记录值是无用的。因此,您决定丢弃 FuelRate 为零的无效数据采样。

查找 FuelRate 的最后一个“良好”值(即不为零)的行索引。

lastNonZeroIdx = find(chanGrp2TT.FuelRate ~= 0, 1, "last")
lastNonZeroIdx = 18634

减少通道组 2 中的数据采样数,以仅保留从行索引 1 到 lastNonZeroIdx 的有效值。

chanGrp2TT = chanGrp2TT(1:lastNonZeroIdx, :)
chanGrp2TT=18634×3 timetable
         Time         AirFlow    FuelRate       time   
    ______________    _______    ________    __________

    0 sec             17.294       1.209              0
    0.00056199 sec    17.263       1.209     0.00056199
    0.0033719 sec     17.112       1.209      0.0033719
    0.01 sec          16.776      1.1729           0.01
    0.02 sec          16.316      1.1409           0.02
    0.03 sec          15.907      1.1124           0.03
    0.04 sec          15.546      1.0873           0.04
    0.05 sec          15.228      1.0652           0.05
    0.055328 sec      15.075      1.0652       0.055328
    0.055328 sec      15.075      1.0652       0.055328
    0.055328 sec      15.075      1.0652       0.055328
    0.06 sec          14.949      1.0458           0.06
    0.064672 sec      14.832      1.0458       0.064672
    0.07 sec          14.707      1.0289           0.07
    0.08 sec          14.497      1.0143           0.08
    0.09 sec          14.317      1.0019           0.09
      ⋮

在数据副本中添加通道

将气流量除以喷油量得到空燃比,并将计算出的值赋给一个名为 AirFuelRatio 的新时间表变量。

chanGrp2TT.AirFuelRatio = chanGrp2TT.AirFlow./chanGrp2TT.FuelRate
chanGrp2TT=18634×4 timetable
         Time         AirFlow    FuelRate       time       AirFuelRatio
    ______________    _______    ________    __________    ____________

    0 sec             17.294       1.209              0       14.304   
    0.00056199 sec    17.263       1.209     0.00056199       14.278   
    0.0033719 sec     17.112       1.209      0.0033719       14.154   
    0.01 sec          16.776      1.1729           0.01       14.303   
    0.02 sec          16.316      1.1409           0.02       14.301   
    0.03 sec          15.907      1.1124           0.03         14.3   
    0.04 sec          15.546      1.0873           0.04       14.298   
    0.05 sec          15.228      1.0652           0.05       14.296   
    0.055328 sec      15.075      1.0652       0.055328       14.152   
    0.055328 sec      15.075      1.0652       0.055328       14.152   
    0.055328 sec      15.075      1.0652       0.055328       14.152   
    0.06 sec          14.949      1.0458           0.06       14.294   
    0.064672 sec      14.832      1.0458       0.064672       14.182   
    0.07 sec          14.707      1.0289           0.07       14.293   
    0.08 sec          14.497      1.0143           0.08       14.292   
    0.09 sec          14.317      1.0019           0.09        14.29   
      ⋮

检查更新后的通道元数据,并注意新添加的通道的 missing 值。

chanGrp2TT.Properties.CustomProperties
ans = 
CustomProperties with properties:

    ChannelGroupAcquisitionName: ""
            ChannelGroupComment: "Simulation of engine gas dynamics."
         ChannelGroupSourceInfo: [1x1 struct]
             ChannelDisplayName: [""    ""    ""    <missing>]
                 ChannelComment: [""    ""    ""    <missing>]
                    ChannelUnit: ["g/s"    "g/s"    "s"    <missing>]
                    ChannelType: [FixedLength    FixedLength    ...    ]
                ChannelDataType: [RealLittleEndian    ...    ]
                 ChannelNumBits: [64 64 64 NaN]
           ChannelComponentType: [None    None    None    Missing]
         ChannelCompositionType: [None    None    None    Missing]
              ChannelSourceInfo: [1x4 struct]
              ChannelReadOption: [Numeric    Numeric    Numeric    Missing]

自定义设置通道组和通道元数据

更新通道组注释,以提供有关对数据所做处理的信息。

chanGrpComment = chanGrp2TT.Properties.CustomProperties.ChannelGroupComment
chanGrpComment = 
"Simulation of engine gas dynamics."
chanGrp2TT.Properties.CustomProperties.ChannelGroupComment = chanGrpComment + " Update: Removed invalid samples and added new channel ""AirFuelRatio"".";

更新 AirFlowFuelRate 的通道注释,以提供有关通道的详细信息。您可以使用变量索引或变量名称对 ChannelComment 元数据进行索引。

chanGrp2TT.Properties.CustomProperties.ChannelComment(1) = "Air flow logged from simulation.";
chanGrp2TT.Properties.CustomProperties.ChannelComment("FuelRate") = "Fuel rate logged from simulation.";

AirFuelRatio 添加一个通道注释。

chanGrp2TT.Properties.CustomProperties.ChannelComment(4) = "Air fuel ratio calculated by dividing air flow by fuel rate.";

检查通道元数据,并注意 ChannelGroupCommentChannelComment 中更新后的值。如果不需要对该特定元数据进行自定义设置,可以保留 missing 值。稍后,当写入 MDF 文件时,将相应地应用默认值或派生的值。

chanGrp2TT.Properties.CustomProperties
ans = 
CustomProperties with properties:

    ChannelGroupAcquisitionName: ""
            ChannelGroupComment: "Simulation of engine gas dynamics. Update: Removed invalid samples and added new channel "AirFuelRatio"."
         ChannelGroupSourceInfo: [1x1 struct]
             ChannelDisplayName: [""    ""    ""    <missing>]
                 ChannelComment: [1x4 string]
                    ChannelUnit: ["g/s"    "g/s"    "s"    <missing>]
                    ChannelType: [FixedLength    FixedLength    ...    ]
                ChannelDataType: [RealLittleEndian    ...    ]
                 ChannelNumBits: [64 64 64 NaN]
           ChannelComponentType: [None    None    None    Missing]
         ChannelCompositionType: [None    None    None    Missing]
              ChannelSourceInfo: [1x4 struct]
              ChannelReadOption: [Numeric    Numeric    Numeric    Missing]

创建新 MDF 文件

在此步骤中,您将创建一个名为 VehicleDataNew.mf4 的新 MDF 文件,该文件与原始文件 VehicleData.mf4 具有相同的文件元数据。

使用函数 mdfInfo 获取一个结构体,其中包含原始 MDF 文件 VehicleData.mf4 的文件元数据。

info = mdfInfo("VehicleData.mf4")
info = struct with fields:
                 Name: 'VehicleData.mf4'
                 Path: '/tmp/Bdoc22a_1880208_151076/tp5e0c0350/vnt-ex28629694/VehicleData.mf4'
               Author: ''
           Department: ''
              Project: ''
              Subject: ''
              Comment: 'Example file demonstrating workflows of writing to MDF files.'
              Version: '4.10'
    ProgramIdentifier: 'MATLAB'
     InitialTimestamp: 2022-01-20 01:22:34.000000000
              Creator: [1x1 struct]
           Attachment: [1x1 struct]

info.Creator
ans = struct with fields:
     VendorName: 'The MathWorks, Inc.'
       ToolName: 'MATLAB'
    ToolVersion: '9.12.0.1846952 (R2022a) Prerelease Update 1'
       UserName: ''
        Comment: ''

调用函数 mdfCreate,将可选参数 FileInfo 设置为刚刚获得的结构体。这将在磁盘上创建一个新框架 MDF 文件 VehicleDataNew.mf4,其文件元数据与 VehicleData.mf4 的元数据相同。

mdfCreate("VehicleDataNew.mf4", FileInfo=info)
ans = 
"/tmp/Bdoc22a_1880208_151076/tp5e0c0350/vnt-ex28629694/VehicleDataNew.mf4"

FileInfo 是可选的名称-值对组。如果未指定,mdfCreate 将使用默认文件元数据创建一个新的框架 MDF 文件。

请注意,mdfCreate 只会将适用的元数据应用到新创建的文件中。例如,NamePath 等字段是特定于每个文件的,因此它们会被函数忽略。

检查文件元数据

要确认 mdfCreate 调用创建了已正确应用文件元数据的 MDF 文件,请再次调用 mdfInfo 来检查 VehicleDataNew.mf4 的文件元数据。

infoNew = mdfInfo("VehicleDataNew.mf4")
infoNew = struct with fields:
                 Name: 'VehicleDataNew.mf4'
                 Path: '/tmp/Bdoc22a_1880208_151076/tp5e0c0350/vnt-ex28629694/VehicleDataNew.mf4'
               Author: ''
           Department: ''
              Project: ''
              Subject: ''
              Comment: 'Example file demonstrating workflows of writing to MDF files.'
              Version: '4.10'
    ProgramIdentifier: 'MATLAB'
     InitialTimestamp: 2022-01-20 01:22:34.000000000
              Creator: [1x1 struct]
           Attachment: [0x1 struct]

infoNew.Creator
ans = struct with fields:
     VendorName: 'The MathWorks, Inc.'
       ToolName: 'MATLAB'
    ToolVersion: '9.12.0.1873999 (R2022a)'
       UserName: ''
        Comment: ''

将更新后的数据写入新 MDF 文件中的新通道组

在未指定属性 GroupNumber 的情况下调用函数 mdfWrite。以此种方式使用时,mdfWrite 函数会将输入时间表作为新通道组追加到目标文件的末尾。由于此时 VehicleDataNew.mf4 是没有通道组的框架文件,此操作会将 chanGrp2TT 写入通道组 1。

mdfWrite("VehicleDataNew.mf4", chanGrp2TT)
Warning: Timetable has variable "time" with ChannelType "Master" in addition to the row times. Only one master channel synchronizing by time is allowed per channel group. Row times used for write operation and data in this variable disregarded.

您会看到关于 time 变量的警告,因为时间数据已作为行时间和变量 time 读入时间表。当除了行时间之外还存在包含时间数据的变量时,该变量将被忽略。

检查数据

要确认 mdfWrite 调用按预期更新了 MDF 文件,请开启对 VehicleDataNew.mf4 的访问以读取包含元数据的数据进行验证。

mdfObjNew = mdf("VehicleDataNew.mf4");

从包含元数据的新 MDF 文件中读取通道组 1 的数据。请注意采样数的减少和新通道 AirFuelRatio

chanGrp1TTNew = read(mdfObjNew, 1, IncludeMetadata=true)
chanGrp1TTNew=18634×4 timetable
         Time         AirFlow    FuelRate    AirFuelRatio       time   
    ______________    _______    ________    ____________    __________

    0 sec             17.294       1.209        14.304                0
    0.00056199 sec    17.263       1.209        14.278       0.00056199
    0.0033719 sec     17.112       1.209        14.154        0.0033719
    0.01 sec          16.776      1.1729        14.303             0.01
    0.02 sec          16.316      1.1409        14.301             0.02
    0.03 sec          15.907      1.1124          14.3             0.03
    0.04 sec          15.546      1.0873        14.298             0.04
    0.05 sec          15.228      1.0652        14.296             0.05
    0.055328 sec      15.075      1.0652        14.152         0.055328
    0.055328 sec      15.075      1.0652        14.152         0.055328
    0.055328 sec      15.075      1.0652        14.152         0.055328
    0.06 sec          14.949      1.0458        14.294             0.06
    0.064672 sec      14.832      1.0458        14.182         0.064672
    0.07 sec          14.707      1.0289        14.293             0.07
    0.08 sec          14.497      1.0143        14.292             0.08
    0.09 sec          14.317      1.0019         14.29             0.09
      ⋮

检查通道组和通道元数据

通过访问时间表自定义属性,检查新 MDF 文件中通道组 1 和此组中通道的元数据。

chanGrp1TTNew.Properties.CustomProperties
ans = 
CustomProperties with properties:

    ChannelGroupAcquisitionName: ""
            ChannelGroupComment: "Simulation of engine gas dynamics. Update: Removed invalid samples and added new channel "AirFuelRatio"."
         ChannelGroupSourceInfo: [1x1 struct]
             ChannelDisplayName: [""    ""    ""    ""]
                 ChannelComment: [1x4 string]
                    ChannelUnit: ["g/s"    "g/s"    ""    "s"]
                    ChannelType: [FixedLength    FixedLength    ...    ]
                ChannelDataType: [RealLittleEndian    ...    ]
                 ChannelNumBits: [64 64 64 64]
           ChannelComponentType: [None    None    None    None]
         ChannelCompositionType: [None    None    None    None]
              ChannelSourceInfo: [1x4 struct]
              ChannelReadOption: [Numeric    Numeric    Numeric    Numeric]

关闭 MDF 文件

通过从工作区中清除 MDF 文件的变量,关闭对 MDF 文件的访问。

clear mdfObj mdfObjNew