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/Bdoc24b_2725827_3770987/tpf6b9d6b0/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 Event: [0x8 eventtable]
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: Validity: [92033x2 timetable] 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: Validity: [92033x2 timetable] 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: Validity: [92033x2 timetable] 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/Bdoc24b_2725827_3770987/tpf6b9d6b0/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 Event: [0x8 eventtable]
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/Bdoc24b_2725827_3770987/tpf6b9d6b0/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/Bdoc24b_2725827_3770987/tpf6b9d6b0/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.2.0.2712019 (R2024b)" CreatorUserName: "" CreatorComment: "" File Contents Attachment: [0x7 table] ChannelGroupCount: 0 Event: [0x8 eventtable]
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/Bdoc24b_2725827_3770987/tpf6b9d6b0/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.2.0.2712019 (R2024b)" CreatorUserName: "" CreatorComment: "" File Contents Attachment: [0x7 table] ChannelGroupCount: 1 Event: [0x8 eventtable]
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: Validity: [18634x3 timetable] 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]