Main Content

Overwrite Channel Group Data in an MDF File

This example shows how to process data logged in a channel group of an MDF file and write the updated data back to the same channel group. 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 1.

You will first read data from channel group 1 into a timetable, then perform correction and reduction on the data copy, and lastly overwrite the same channel group with updated data.

View File and Channel Group Details

View metadata of the MDF file using mdfInfo by specifying the file name.

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

   File Details
                  Name: "VehicleData.mf4"
                  Path: "/tmp/Bdoc24a_2528353_1100067/tp38a48925/vnt-ex75859393/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 1 using the mdfRead function with optional argument IncludeMetadata set to true. The output timetable chanGrp1TT is a copy of data for all channels in channel group 1.

chanGrp1Data = mdfRead("VehicleData.mf4", GroupNumber=1, IncludeMetadata=true)
chanGrp1Data = 1x1 cell array
    {751x8 timetable}

chanGrp1TT = chanGrp1Data{1}
chanGrp1TT=751×8 timetable
      time      EngineRPM    Brake    Throttle    Gear    ImpellerTorque    OutputTorque    TransmissionRPM    VehicleSpeed
    ________    _________    _____    ________    ____    ______________    ____________    _______________    ____________

    0 sec          1000        0           60      1          52.919           282.65                0              0      
    0.04 sec     1383.3        0       59.946      1           101.4           532.63           13.593              0      
    0.08 sec     1685.4        0       59.893      1          150.76           776.41           35.847              0      
    0.12 sec     1907.2        0       59.839      1          193.42           973.15           65.768              0      
    0.16 sec       2062        0       59.785      1          227.02           1117.6           101.53              0      
    0.2 sec      2161.2        0       59.732      1          251.11           1212.8           141.45              0      
    0.24 sec     2221.4        0       59.678      1          267.24           1264.3           183.86              0      
    0.28 sec     2257.2        0       59.624      1          276.35           1271.2           227.25              0      
    0.32 sec     2278.7        0        59.57      1          281.99           1259.5           270.52              0      
    0.36 sec     2292.4        0       59.517      1          283.39             1229           313.08              0      
    0.4 sec      2305.1        0       59.463      1          283.29           1193.4           354.43              0      
    0.44 sec     2317.4        0       59.409      1          282.91           1156.6           394.58              0      
    0.48 sec     2330.5        0       59.356      1          281.84           1112.8           433.27              0      
    0.52 sec     2344.5        0       59.302      1          281.19           1073.1           470.53              0      
    0.56 sec     2359.1        0       59.248      1          279.77           1032.9           506.43              0      
    0.6 sec      2376.4        0       59.195      1          277.89           993.97           540.92              0      
      ⋮

Because IncludeMetadata was set to true during the mdfRead function call, the output timetable also contains metadata for channel group 1 and all channels in this group. 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 1 and all channels in this group.

chanGrp1TT.Properties.CustomProperties
ans = 
CustomProperties with properties:

           ChannelGroupAcquisitionName: ""
                   ChannelGroupComment: "Simulation of an automatic transmission controller during passing maneuver."
                ChannelGroupSourceName: ""
                ChannelGroupSourcePath: ""
             ChannelGroupSourceComment: ""
                ChannelGroupSourceType: Unspecified
             ChannelGroupSourceBusType: Unspecified
    ChannelGroupSourceBusChannelNumber: 0
                    ChannelDisplayName: [""    ""    ""    ""    ""    ""    ""    ""]
                        ChannelComment: [""    ""    ""    ""    ""    ""    ""    ""]
                           ChannelUnit: ["rpm"    "ft*lbf"    "%"    ""    "ft*lbf"    "ft*lbf"    "rpm"    "mph"]
                           ChannelType: [FixedLength    FixedLength    FixedLength    FixedLength    FixedLength    FixedLength    FixedLength    FixedLength]
                       ChannelDataType: [RealLittleEndian    IntegerUnsignedLittleEndian    RealLittleEndian    IntegerUnsignedLittleEndian    RealLittleEndian    RealLittleEndian    RealLittleEndian    RealLittleEndian]
                        ChannelNumBits: [64 8 64 8 64 64 64 64]
                  ChannelComponentType: [None    None    None    None    None    None    None    None]
                ChannelCompositionType: [None    None    None    None    None    None    None    None]
                     ChannelSourceName: [""    ""    ""    ""    ""    ""    ""    ""]
                     ChannelSourcePath: [""    ""    ""    ""    ""    ""    ""    ""]
                  ChannelSourceComment: [""    ""    ""    ""    ""    ""    ""    ""]
                     ChannelSourceType: [Unspecified    Unspecified    Unspecified    Unspecified    Unspecified    Unspecified    Unspecified    Unspecified]
                  ChannelSourceBusType: [Unspecified    Unspecified    Unspecified    Unspecified    Unspecified    Unspecified    Unspecified    Unspecified]
         ChannelSourceBusChannelNumber: [0 0 0 0 0 0 0 0]
                     ChannelReadOption: [All    All    All    All    All    All    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 overwrite the same channel group from which data is read.

Correct Selected Samples in the Data Copy

For this particular application, there are only 4 gears, so a valid value of Gear should be an integer in the range of [1,4]. However, the value of Gear appears to have been reset to zero due to a possible fault whenever a gear shift takes place.

Create a stacked plot using stackedplot to see how the abrupt drops to zero in Gear coincide with the abrupt value changes in ImpellerTorque and OutputTorque.

stackedplot(chanGrp1TT, ["ImpellerTorque", "OutputTorque", "Gear"])

Find row indices where value of Gear is equal to zero.

zeroIdx = find(chanGrp1TT.Gear == 0)
zeroIdx =

  0x1 empty double column vector

Correct samples at the found indices to take the values immediately following the zeros.

chanGrp1TT.Gear(zeroIdx) = chanGrp1TT.Gear(zeroIdx + 1)
chanGrp1TT=751×8 timetable
      time      EngineRPM    Brake    Throttle    Gear    ImpellerTorque    OutputTorque    TransmissionRPM    VehicleSpeed
    ________    _________    _____    ________    ____    ______________    ____________    _______________    ____________

    0 sec          1000        0           60      1          52.919           282.65                0              0      
    0.04 sec     1383.3        0       59.946      1           101.4           532.63           13.593              0      
    0.08 sec     1685.4        0       59.893      1          150.76           776.41           35.847              0      
    0.12 sec     1907.2        0       59.839      1          193.42           973.15           65.768              0      
    0.16 sec       2062        0       59.785      1          227.02           1117.6           101.53              0      
    0.2 sec      2161.2        0       59.732      1          251.11           1212.8           141.45              0      
    0.24 sec     2221.4        0       59.678      1          267.24           1264.3           183.86              0      
    0.28 sec     2257.2        0       59.624      1          276.35           1271.2           227.25              0      
    0.32 sec     2278.7        0        59.57      1          281.99           1259.5           270.52              0      
    0.36 sec     2292.4        0       59.517      1          283.39             1229           313.08              0      
    0.4 sec      2305.1        0       59.463      1          283.29           1193.4           354.43              0      
    0.44 sec     2317.4        0       59.409      1          282.91           1156.6           394.58              0      
    0.48 sec     2330.5        0       59.356      1          281.84           1112.8           433.27              0      
    0.52 sec     2344.5        0       59.302      1          281.19           1073.1           470.53              0      
    0.56 sec     2359.1        0       59.248      1          279.77           1032.9           506.43              0      
    0.6 sec      2376.4        0       59.195      1          277.89           993.97           540.92              0      
      ⋮

Remove Channels from the Data Copy

For this particular application, assume Brake and VehicleSpeed are no longer required for analysis. Remove these two variables from the timetable using removevars.

chanGrp1TT = removevars(chanGrp1TT, ["Brake", "VehicleSpeed"])
chanGrp1TT=751×6 timetable
      time      EngineRPM    Throttle    Gear    ImpellerTorque    OutputTorque    TransmissionRPM
    ________    _________    ________    ____    ______________    ____________    _______________

    0 sec          1000           60      1          52.919           282.65                0     
    0.04 sec     1383.3       59.946      1           101.4           532.63           13.593     
    0.08 sec     1685.4       59.893      1          150.76           776.41           35.847     
    0.12 sec     1907.2       59.839      1          193.42           973.15           65.768     
    0.16 sec       2062       59.785      1          227.02           1117.6           101.53     
    0.2 sec      2161.2       59.732      1          251.11           1212.8           141.45     
    0.24 sec     2221.4       59.678      1          267.24           1264.3           183.86     
    0.28 sec     2257.2       59.624      1          276.35           1271.2           227.25     
    0.32 sec     2278.7        59.57      1          281.99           1259.5           270.52     
    0.36 sec     2292.4       59.517      1          283.39             1229           313.08     
    0.4 sec      2305.1       59.463      1          283.29           1193.4           354.43     
    0.44 sec     2317.4       59.409      1          282.91           1156.6           394.58     
    0.48 sec     2330.5       59.356      1          281.84           1112.8           433.27     
    0.52 sec     2344.5       59.302      1          281.19           1073.1           470.53     
    0.56 sec     2359.1       59.248      1          279.77           1032.9           506.43     
    0.6 sec      2376.4       59.195      1          277.89           993.97           540.92     
      ⋮

Write Updated Data Back to the Same Channel Group

You will write updated data into channel group 1 of VehicleData.mf4, which requires permission to modify the MDF file. Check if you have write access to the MDF file. If not, make the MDF file writable.

[~, values] = fileattrib("VehicleData.mf4");
if ~values.UserWrite
    fileattrib("VehicleData.mf4", "+w")
end

Call function mdfWrite with optional argument GroupNumber set to 1 to overwrite channel group 1 with the updated data in chanGrp1TT.

mdfWrite("VehicleData.mf4", chanGrp1TT, GroupNumber=1)
Warning: Channel "Brake" removed while overwriting an existing channel group. Data of the corresponding channel will be erased but the channel will still exist.
Warning: Channel "VehicleSpeed" removed while overwriting an existing channel group. Data of the corresponding channel will be erased but the channel will still exist.

Two variables Brake and VehicleSpeed were removed from the timetable chanGrp1TT in the previous step. However, because MDF is a binary file format, altering the channel group structure can lead to file corruption. Therefore, it is not possible to truly remove channels from an existing channel group. Data of the removed channels are erased, but the channels still exist in the channel group.

Examine the Data

To verify that data was successfully written to file, read only the data from channel group 1 without metadata using mdfRead. Inspect the updated values in variable Gear. Also note that values have been erased and reset to zeros for the removed variables Brake and VehicleSpeed.

chanGrp1DataNew = mdfRead("VehicleData.mf4", GroupNumber=1)
chanGrp1DataNew = 1x1 cell array
    {751x8 timetable}

chanGrp1TTNew = chanGrp1DataNew{1}
chanGrp1TTNew=751×8 timetable
      time      EngineRPM    Brake    Throttle    Gear    ImpellerTorque    OutputTorque    TransmissionRPM    VehicleSpeed
    ________    _________    _____    ________    ____    ______________    ____________    _______________    ____________

    0 sec          1000        0           60      1          52.919           282.65                0              0      
    0.04 sec     1383.3        0       59.946      1           101.4           532.63           13.593              0      
    0.08 sec     1685.4        0       59.893      1          150.76           776.41           35.847              0      
    0.12 sec     1907.2        0       59.839      1          193.42           973.15           65.768              0      
    0.16 sec       2062        0       59.785      1          227.02           1117.6           101.53              0      
    0.2 sec      2161.2        0       59.732      1          251.11           1212.8           141.45              0      
    0.24 sec     2221.4        0       59.678      1          267.24           1264.3           183.86              0      
    0.28 sec     2257.2        0       59.624      1          276.35           1271.2           227.25              0      
    0.32 sec     2278.7        0        59.57      1          281.99           1259.5           270.52              0      
    0.36 sec     2292.4        0       59.517      1          283.39             1229           313.08              0      
    0.4 sec      2305.1        0       59.463      1          283.29           1193.4           354.43              0      
    0.44 sec     2317.4        0       59.409      1          282.91           1156.6           394.58              0      
    0.48 sec     2330.5        0       59.356      1          281.84           1112.8           433.27              0      
    0.52 sec     2344.5        0       59.302      1          281.19           1073.1           470.53              0      
    0.56 sec     2359.1        0       59.248      1          279.77           1032.9           506.43              0      
    0.6 sec      2376.4        0       59.195      1          277.89           993.97           540.92              0      
      ⋮