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/Bdoc22a_1891349_156950/tp07074cff/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"])
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