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.

Open MDF-File

Open access to the MDF-file using the mdf function.

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

   File Details
                 Name: 'VehicleData.mf4'
                 Path: '/tmp/Bdoc22b_2054784_2458883/tp193364be/vnt-ex75859393/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

Inspect details about the two channel groups.

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

Read Channel Group Data with Metadata Included

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

chanGrp1TT = read(mdfObj, 1, IncludeMetadata=true)
chanGrp1TT=751×9 timetable
      Time      EngineRPM    Brake    Throttle    Gear    ImpellerTorque    OutputTorque    TransmissionRPM    VehicleSpeed    time
    ________    _________    _____    ________    ____    ______________    ____________    _______________    ____________    ____

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

Because IncludeMetadata was set to true during the read 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."
         ChannelGroupSourceInfo: [1x1 struct]
             ChannelDisplayName: [""    ""    ""    ""    ""    ""    ...    ]
                 ChannelComment: [""    ""    ""    ""    ""    ""    ...    ]
                    ChannelUnit: ["rpm"    "ft*lbf"    "%"    ""    ...    ]
                    ChannelType: [FixedLength    FixedLength    ...    ]
                ChannelDataType: [RealLittleEndian    ...    ]
                 ChannelNumBits: [64 8 64 8 64 64 64 64 64]
           ChannelComponentType: [None    None    None    None    ...    ]
         ChannelCompositionType: [None    None    None    None    ...    ]
              ChannelSourceInfo: [1x9 struct]
              ChannelReadOption: [Numeric    Numeric    Numeric    ...    ]

Note that when calling the read function, IncludeMetadata is set to false by default. Therefore, 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"])

Figure contains an object of type stackedplot.

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

zeroIdx = find(chanGrp1TT.Gear == 0)
zeroIdx = 5×1

    46
   107
   196
   378
   513

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

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

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

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×7 timetable
      Time      EngineRPM    Throttle    Gear    ImpellerTorque    OutputTorque    TransmissionRPM    time
    ________    _________    ________    ____    ______________    ____________    _______________    ____

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

Write Updated Data Back to the Same Channel Group

As VehicleData.mf4 is still open in MATLAB at this point, the MDF-file needs to be closed first. First, clear the MDF object mdfObj from workspace.

clear mdfObj

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

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. In such cases, data of the removed channels are erased, but the channels still exist in the channel group.

You also see a warning about the time variable because the time data has been read into the timetable both as the row times and as a variable time. When a variable that contains time data is present in addition to the row times, the variable is disregarded.

Examine the Data

Open access to VehicleData.mf4 to read data back into MATLAB for verification.

mdfObj = mdf("VehicleData.mf4");

Because metadata for channel group 1 and its channels was unchanged, read only the data from channel group 1 without metadata. 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.

chanGrp1TTNew = read(mdfObj, 1)
chanGrp1TTNew=751×9 timetable
      Time      EngineRPM    Brake    Throttle    Gear    ImpellerTorque    OutputTorque    TransmissionRPM    VehicleSpeed    time
    ________    _________    _____    ________    ____    ______________    ____________    _______________    ____________    ____

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

Close MDF-File

Close access to the MDF-file by clearing its variable from the workspace.

clear mdfObj