Main Content

Write Channel Group Data from an Existing MDF File to a New MDF File

This example shows how to process data logged in a channel group of an MDF file and write the updated data to a new file. The MDF file used in this example VehicleData.mf4 contains data logged from two simulations in two channel groups, but the example only works with data in channel group 2.

You will first read data from channel group 2 into a timetable, and then perform post-processing on the data copy. Lastly, you will create a new MDF file that has the same file metadata as VehicleData.mf4, and write the updated data into the new MDF file as a new channel group.

View Details about the MDF File and Its Channel Groups

View metadata of file VehicleData.mf4 using mdfInfo by specifying the file name.

mdfInfo("VehicleData.mf4")
ans = 
  MDFInfo with properties:

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

   Creator Details
     ProgramIdentifier: "MATLAB"
     CreatorVendorName: "The MathWorks, Inc."
       CreatorToolName: "MATLAB"
    CreatorToolVersion: "9.12.0.1846952 (R2022a) Prerelease Update 1"
       CreatorUserName: ""
        CreatorComment: ""

   File Contents
            Attachment: [1x7 table]
     ChannelGroupCount: 2

Inspect details about the two channel groups using mdfChannelGroupInfo.

mdfChannelGroupInfo("VehicleData.mf4")
ans=2×13 table
    GroupNumber    AcquisitionName                                      Comment                                      NumSamples    DataSize    Sorted    SourceName     SourcePath     SourceComment    SourceType     SourceBusType    SourceBusChannelNumber    SourceSimulated
    ___________    _______________    ___________________________________________________________________________    __________    ________    ______    ___________    ___________    _____________    ___________    _____________    ______________________    _______________

         1           <undefined>      Simulation of an automatic transmission controller during passing maneuver.        751         43558     true      <undefined>    <undefined>     <undefined>     Unspecified     Unspecified               0                    false     
         2           <undefined>      Simulation of engine gas dynamics.                                               92033       2208792     true      <undefined>    <undefined>     <undefined>     Unspecified     Unspecified               0                    false     

Read Channel Group Data with Metadata Included

Read data from channel group 2 using the mdfRead function with optional argument IncludeMetadata set to true. The output timetable chanGrp2TT is a copy of data for all channels in channel group 2.

chanGrp2Data = mdfRead("VehicleData.mf4", GroupNumber=2, IncludeMetadata=true)
chanGrp2Data = 1x1 cell array
    {92033x2 timetable}

chanGrp2TT = chanGrp2Data{1}
chanGrp2TT=92033×2 timetable
         time         AirFlow    FuelRate
    ______________    _______    ________

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

Metadata for channel group 2 and its channels are available in the timetable as custom properties. Metadata for a channel group are stored as the timetable's custom properties for the entire table, and the property names are prefixed with "ChannelGroup". Metadata for individual channels are stored as the timetable's custom properties for the variables, and the property names are prefixed with "Channel".

View metadata for channel group 2 and all channels in this group.

chanGrp2TT.Properties.CustomProperties
ans = 
CustomProperties with properties:

           ChannelGroupAcquisitionName: ""
                   ChannelGroupComment: "Simulation of engine gas dynamics."
                ChannelGroupSourceName: ""
                ChannelGroupSourcePath: ""
             ChannelGroupSourceComment: ""
                ChannelGroupSourceType: Unspecified
             ChannelGroupSourceBusType: Unspecified
    ChannelGroupSourceBusChannelNumber: 0
                    ChannelDisplayName: [""    ""]
                        ChannelComment: [""    ""]
                           ChannelUnit: ["g/s"    "g/s"]
                           ChannelType: [FixedLength    FixedLength]
                       ChannelDataType: [RealLittleEndian    RealLittleEndian]
                        ChannelNumBits: [64 64]
                  ChannelComponentType: [None    None]
                ChannelCompositionType: [None    None]
                     ChannelSourceName: [""    ""]
                     ChannelSourcePath: [""    ""]
                  ChannelSourceComment: [""    ""]
                     ChannelSourceType: [Unspecified    Unspecified]
                  ChannelSourceBusType: [Unspecified    Unspecified]
         ChannelSourceBusChannelNumber: [0 0]
                     ChannelReadOption: [All    All]

Note that when calling the mdfRead function, IncludeMetadata is set to false by default. IncludeMetadata must be set to true if your ultimate goal for reading channel group data is to write to a new channel group with channel group and channel metadata carried over.

Reduce Number of Samples in the Data Copy

Create a stacked plot using stackedplot to visualize data in channels AirFlow and FuelRate.

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

It can be observed from the stacked plot that the value of FuelRate stays at 0 from around 182.17 sec until the end of the recording at 900 sec, indicating a possible fault during measurement. For this particular application, the recorded values of AirFlow are useless where the values of FuelRate are invalid. Therefore, you decide to discard the invalid data samples where FuelRate is zero.

Reduce the data samples in channel group 2 to only keep the valid non-zero values.

chanGrp2TT = chanGrp2TT(chanGrp2TT.FuelRate ~= 0, :)
chanGrp2TT=18634×2 timetable
         time         AirFlow    FuelRate
    ______________    _______    ________

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

Add Channels in the Data Copy

Divide the air flow by fuel rate to get the air fuel ratio, and assign the calculated values to a new timetable variable named AirFuelRatio.

chanGrp2TT.AirFuelRatio = chanGrp2TT.AirFlow./chanGrp2TT.FuelRate
chanGrp2TT=18634×3 timetable
         time         AirFlow    FuelRate    AirFuelRatio
    ______________    _______    ________    ____________

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

Inspect the updated channel metadata and note the missing values for the newly added channel.

chanGrp2TT.Properties.CustomProperties
ans = 
CustomProperties with properties:

           ChannelGroupAcquisitionName: ""
                   ChannelGroupComment: "Simulation of engine gas dynamics."
                ChannelGroupSourceName: ""
                ChannelGroupSourcePath: ""
             ChannelGroupSourceComment: ""
                ChannelGroupSourceType: Unspecified
             ChannelGroupSourceBusType: Unspecified
    ChannelGroupSourceBusChannelNumber: 0
                    ChannelDisplayName: [""    ""    <missing>]
                        ChannelComment: [""    ""    <missing>]
                           ChannelUnit: ["g/s"    "g/s"    <missing>]
                           ChannelType: [FixedLength    FixedLength    Missing]
                       ChannelDataType: [RealLittleEndian    RealLittleEndian    Missing]
                        ChannelNumBits: [64 64 NaN]
                  ChannelComponentType: [None    None    Missing]
                ChannelCompositionType: [None    None    Missing]
                     ChannelSourceName: [""    ""    <missing>]
                     ChannelSourcePath: [""    ""    <missing>]
                  ChannelSourceComment: [""    ""    <missing>]
                     ChannelSourceType: [Unspecified    Unspecified    Missing]
                  ChannelSourceBusType: [Unspecified    Unspecified    Missing]
         ChannelSourceBusChannelNumber: [0 0 0]
                     ChannelReadOption: [All    All    Missing]

Customize Channel Group Metadata and Channel Metadata

Update the channel group comment to provide information about the processing done on data.

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"".";

Update the channel comment for AirFlow and FuelRate to provide more information about the channels. You can use either the variable index or the variable name to index into the ChannelComment metadata.

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

Add a channel comment for AirFuelRatio.

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

Inspect the channel metadata and note the updated values in ChannelGroupComment and ChannelComment. It is okay to leave the missing values if you do not need to customize that specific metadata. Later, when writing to an MDF file, the default or derived values will be applied accordingly.

chanGrp2TT.Properties.CustomProperties
ans = 
CustomProperties with properties:

           ChannelGroupAcquisitionName: ""
                   ChannelGroupComment: "Simulation of engine gas dynamics. Update: Removed invalid samples and added new channel "AirFuelRatio"."
                ChannelGroupSourceName: ""
                ChannelGroupSourcePath: ""
             ChannelGroupSourceComment: ""
                ChannelGroupSourceType: Unspecified
             ChannelGroupSourceBusType: Unspecified
    ChannelGroupSourceBusChannelNumber: 0
                    ChannelDisplayName: [""    ""    <missing>]
                        ChannelComment: ["Air flow logged from simulation."    "Fuel rate logged from simulation."    "Air fuel ratio calculated by dividing air flow by fuel rate."]
                           ChannelUnit: ["g/s"    "g/s"    <missing>]
                           ChannelType: [FixedLength    FixedLength    Missing]
                       ChannelDataType: [RealLittleEndian    RealLittleEndian    Missing]
                        ChannelNumBits: [64 64 NaN]
                  ChannelComponentType: [None    None    Missing]
                ChannelCompositionType: [None    None    Missing]
                     ChannelSourceName: [""    ""    <missing>]
                     ChannelSourcePath: [""    ""    <missing>]
                  ChannelSourceComment: [""    ""    <missing>]
                     ChannelSourceType: [Unspecified    Unspecified    Missing]
                  ChannelSourceBusType: [Unspecified    Unspecified    Missing]
         ChannelSourceBusChannelNumber: [0 0 0]
                     ChannelReadOption: [All    All    Missing]

Create a New MDF File

In this step, you create a new MDF file named VehicleDataNew.mf4 that has the same file metadata as the original file VehicleData.mf4.

Obtain an MDFInfo object that contains file metadata for the original MDF file VehicleData.mf4 using function mdfInfo.

info = mdfInfo("VehicleData.mf4")
info = 
  MDFInfo with properties:

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

   Creator Details
     ProgramIdentifier: "MATLAB"
     CreatorVendorName: "The MathWorks, Inc."
       CreatorToolName: "MATLAB"
    CreatorToolVersion: "9.12.0.1846952 (R2022a) Prerelease Update 1"
       CreatorUserName: ""
        CreatorComment: ""

   File Contents
            Attachment: [1x7 table]
     ChannelGroupCount: 2

Call function mdfCreate with optional argument FileInfo set to the MDFInfo object just obtained. This creates a new skeleton MDF file VehicleDataNew.mf4 on disk with the same file metadata as VehicleData.mf4.

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

FileInfo is an optional name-value pair. If unspecified, mdfCreate creates a new skeleton MDF file using default file metadata.

Note that mdfCreate only sets the applicable metadata to the newly created file. For example, properties like Name and Path are specific to each file, so they are ignored.

Examine the File Metadata

To confirm that mdfCreate created the MDF file with file metadata correctly applied, use mdfInfo to examine the file metadata for VehicleDataNew.mf4. Note that ChannelGroupCount is 0 as the file has no channel group yet.

mdfInfo("VehicleDataNew.mf4")
ans = 
  MDFInfo with properties:

   File Details
                  Name: "VehicleDataNew.mf4"
                  Path: "/tmp/Bdoc24a_2528353_1101874/tp8faccd1d/vnt-ex28629694/VehicleDataNew.mf4"
                Author: ""
            Department: ""
               Project: ""
               Subject: ""
               Comment: "Example file demonstrating workflows of writing to MDF files."
               Version: "4.10"
      InitialTimestamp: 2022-01-20 01:22:34.000000000

   Creator Details
     ProgramIdentifier: "MATLAB"
     CreatorVendorName: "The MathWorks, Inc."
       CreatorToolName: "MATLAB"
    CreatorToolVersion: "24.1.0.2508561 (R2024a)"
       CreatorUserName: ""
        CreatorComment: ""

   File Contents
            Attachment: [0x7 table]
     ChannelGroupCount: 0

Write Updated Data to a New Channel Group in the New MDF File

Call function mdfWrite with optional argument GroupNumber unspecified. When used as such, the function appends the input timetable to the end of the target file as a new channel group. Because VehicleDataNew.mf4 at this point is a skeleton file with no channel group, this operation writes chanGrp2TT into channel group 1.

mdfWrite("VehicleDataNew.mf4", chanGrp2TT)

Examine the Data

To confirm that mdfWrite updated the MDF file as expected, view file details of VehicleDataNew.mf4 again. Note that ChannelGroupCount is 1 now.

mdfInfo("VehicleDataNew.mf4")
ans = 
  MDFInfo with properties:

   File Details
                  Name: "VehicleDataNew.mf4"
                  Path: "/tmp/Bdoc24a_2528353_1101874/tp8faccd1d/vnt-ex28629694/VehicleDataNew.mf4"
                Author: ""
            Department: ""
               Project: ""
               Subject: ""
               Comment: "Example file demonstrating workflows of writing to MDF files."
               Version: "4.10"
      InitialTimestamp: 2022-01-20 01:22:34.000000000

   Creator Details
     ProgramIdentifier: "MATLAB"
     CreatorVendorName: "The MathWorks, Inc."
       CreatorToolName: "MATLAB"
    CreatorToolVersion: "24.1.0.2508561 (R2024a)"
       CreatorUserName: ""
        CreatorComment: ""

   File Contents
            Attachment: [0x7 table]
     ChannelGroupCount: 1

Read data from channel group 1 of the new MDF file with metadata included. Note the reduced number of samples and the new channel AirFuelRatio.

chanGrp1DataNew = mdfRead("VehicleDataNew.mf4", GroupNumber=1, IncludeMetadata=true)
chanGrp1DataNew = 1x1 cell array
    {18634x3 timetable}

chanGrp1TTNew = chanGrp1DataNew{1}
chanGrp1TTNew=18634×3 timetable
         time         AirFlow    FuelRate    AirFuelRatio
    ______________    _______    ________    ____________

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

Examine the Channel Group Metadata and Channel Metadata

Examine the metadata for channel group 1 and channels in this group by accessing the timetable custom properties.

chanGrp1TTNew.Properties.CustomProperties
ans = 
CustomProperties with properties:

           ChannelGroupAcquisitionName: ""
                   ChannelGroupComment: "Simulation of engine gas dynamics. Update: Removed invalid samples and added new channel "AirFuelRatio"."
                ChannelGroupSourceName: ""
                ChannelGroupSourcePath: ""
             ChannelGroupSourceComment: ""
                ChannelGroupSourceType: Unspecified
             ChannelGroupSourceBusType: Unspecified
    ChannelGroupSourceBusChannelNumber: 0
                    ChannelDisplayName: [""    ""    ""]
                        ChannelComment: ["Air flow logged from simulation."    "Fuel rate logged from simulation."    "Air fuel ratio calculated by dividing air flow by fuel rate."]
                           ChannelUnit: ["g/s"    "g/s"    ""]
                           ChannelType: [FixedLength    FixedLength    FixedLength]
                       ChannelDataType: [RealLittleEndian    RealLittleEndian    RealLittleEndian]
                        ChannelNumBits: [64 64 64]
                  ChannelComponentType: [None    None    None]
                ChannelCompositionType: [None    None    None]
                     ChannelSourceName: [""    ""    ""]
                     ChannelSourcePath: [""    ""    ""]
                  ChannelSourceComment: [""    ""    ""]
                     ChannelSourceType: [Unspecified    Unspecified    Unspecified]
                  ChannelSourceBusType: [Unspecified    Unspecified    Unspecified]
         ChannelSourceBusChannelNumber: [0 0 0]
                     ChannelReadOption: [All    All    All]