Process PI Data Using Common MATLAB Operations
R2026bThis example shows you how to process PI data using common MATLAB® timetable operations.
The PI Data Archive is capable of storing decades of real-time data from hundreds of assets. Running this example assumes a PI Data Archive available for connection. The demo tags used in this example were provided by AVEVA and can be downloaded from AVEVA sharefile.
Create Client/Server Connection and Retrieve Required Tags
Connect to the PI Data Archive using the piclient function. In this example the Windows computer name is used as the PI Data Archive name. Your situation might vary depending on the PI System configuration.
host = getenv("COMPUTERNAME");
client = piclient(host);Request a list of tags related to the asset of interest. For more detailed information see Get Started Accessing a PI Data Archive.
tagsGenerator = tags(client, Name = "OSIDemo_GU1 Generator*")tagsGenerator = 28×1 table
"OSIDemo_GU1 Generator.Active Power.4db83f0a-ff87-5c67-385a-83cfe3ac560d"
"OSIDemo_GU1 Generator.Axial Vibration.373a6144-442d-5e69-1079-5986bf866fa1"
"OSIDemo_GU1 Generator.Bearing Temperature.3cfb845c-000c-5cf2-2ca0-b47dfdcfb4d7"
"OSIDemo_GU1 Generator.Bearing Vibration.ac4f121c-0633-5a0d-3e26-e8d6a6249515"
"OSIDemo_GU1 Generator.Cooling Water Intake Temperature.2b0243be-4a97-5a48-1337-0e0b242c4795"
"OSIDemo_GU1 Generator.Cooling Water Output Temperature.7d1a79de-1957-5efc-1d55-aa5fcfccf36a"
"OSIDemo_GU1 Generator.Cooling Water Pressure.0c723cab-80c6-5630-13bf-38fdd7092768"
"OSIDemo_GU1 Generator.Core Temperature.79a1a7b5-5425-51ba-0bd6-ea1d6fbc4b86"
"OSIDemo_GU1 Generator.Current Phase A.07815f38-c5b4-5abc-3d7c-2b0d4cd303ac"
"OSIDemo_GU1 Generator.Current Phase B.7e11e986-d6e3-5f51-241a-23cc597bde31"
"OSIDemo_GU1 Generator.Current Phase C.02c2ac50-14f7-5a5a-2e97-8b7d24851468"
"OSIDemo_GU1 Generator.Frequency.8886141f-470a-514e-22d9-ef9e6aceaf95"
"OSIDemo_GU1 Generator.Hours Since Last Maintenance.cb867a54-053b-5616-1a4a-dfa68f6b454c"
"OSIDemo_GU1 Generator.Line Voltage AB.373eb947-c651-5aef-1948-a312f1aa02e9"
⋮
Find All Tags from List Related to Voltage
Refine the list of tags using the contains function. This groups together all tags related to line voltages for use later in the example.
tagsVoltage = tagsGenerator(contains(tagsGenerator.Tags,"Voltage"),:)tagsVoltage = 3×1 table
"OSIDemo_GU1 Generator.Line Voltage AB.373eb947-c651-5aef-1948-a312f1aa02e9"
"OSIDemo_GU1 Generator.Line Voltage AC.a809d1f1-c08f-54f9-0915-2a1f0096c464"
"OSIDemo_GU1 Generator.Line Voltage BC.90cc345e-520f-5284-187b-d2c1f98bf536"
Read Latest Value of Multiple Tags
Read the latest value multiple tags using the read function, and specifying a range of tags.
voltageLatestTT = read(client, tagsVoltage.Tags(1:3))
voltageLatestTT = 3×3 timetable
21-December-2021 15:45:00 "OSIDemo_GU1 Generator.Line Voltage AB.373eb947-c651-5aef-1948-a312f1aa02e9" 3.3100 Good
21-December-2021 15:45:00 "OSIDemo_GU1 Generator.Line Voltage AC.a809d1f1-c08f-54f9-0915-2a1f0096c464" 3.3200 Good
21-December-2021 15:45:00 "OSIDemo_GU1 Generator.Line Voltage BC.90cc345e-520f-5284-187b-d2c1f98bf536" 3.2900 Good
Read All Recorded Values of Multiple Tags
To read all recorded values of a tag, it is useful to know when data recording began. You can use the Earliest name-value argument to determine this. Notice that all three of the tags from tagsVoltage are passed to the read function.
voltageEarliestTT = read(client, tagsVoltage.Tags(1:3), Earliest=true)
voltageEarliestTT = 3×3 timetable
04-November-2021 20:25:12 "OSIDemo_GU1 Generator.Line Voltage AB.373eb947-c651-5aef-1948-a312f1aa02e9" NaN Bad
04-November-2021 20:25:12 "OSIDemo_GU1 Generator.Line Voltage AC.a809d1f1-c08f-54f9-0915-2a1f0096c464" NaN Bad
04-November-2021 20:25:12 "OSIDemo_GU1 Generator.Line Voltage BC.90cc345e-520f-5284-187b-d2c1f98bf536" NaN Bad
Notice the value of this tag at the earliest recorded time is a NaN. This is often the case for the first data point in a series as the PI Data Archive indicates a status of Bad for this data point upon creation. You can exclude this from your data set if desired.
This earliest data point identifies the time of the first recorded value. You can now use this information to establish a starting datetime for your request.
startDate = datetime(voltageEarliestTT.Time(1)); endDate = datetime("now", TimeZone="local");
Depending on your system, this query might return a large amount of data. If you have an extensive history of data that makes this too slow or impractical, you can skip this step.
voltageAllTT = read(client, tagsVoltage.Tags(1:3), DateRange=[startDate,endDate])
voltageAllTT = 29815×3 timetable
04-November-2021 20:25:12 "OSIDemo_GU1 Generator.Line Voltage AB.373eb947-c651-5aef-1948-a312f1aa02e9" NaN Bad
04-November-2021 20:25:12 "OSIDemo_GU1 Generator.Line Voltage AC.a809d1f1-c08f-54f9-0915-2a1f0096c464" NaN Bad
04-November-2021 20:25:12 "OSIDemo_GU1 Generator.Line Voltage BC.90cc345e-520f-5284-187b-d2c1f98bf536" NaN Bad
04-November-2021 20:30:00 "OSIDemo_GU1 Generator.Line Voltage AB.373eb947-c651-5aef-1948-a312f1aa02e9" 3.2800 Good
04-November-2021 20:30:00 "OSIDemo_GU1 Generator.Line Voltage AC.a809d1f1-c08f-54f9-0915-2a1f0096c464" 3.3200 Good
04-November-2021 20:30:00 "OSIDemo_GU1 Generator.Line Voltage BC.90cc345e-520f-5284-187b-d2c1f98bf536" 3.3200 Good
04-November-2021 20:35:00 "OSIDemo_GU1 Generator.Line Voltage AC.a809d1f1-c08f-54f9-0915-2a1f0096c464" 3.3000 Good
04-November-2021 20:40:00 "OSIDemo_GU1 Generator.Line Voltage AB.373eb947-c651-5aef-1948-a312f1aa02e9" 3.3100 Good
04-November-2021 20:40:00 "OSIDemo_GU1 Generator.Line Voltage AC.a809d1f1-c08f-54f9-0915-2a1f0096c464" 3.3000 Good
04-November-2021 20:45:00 "OSIDemo_GU1 Generator.Line Voltage AB.373eb947-c651-5aef-1948-a312f1aa02e9" 3.3100 Good
04-November-2021 20:45:00 "OSIDemo_GU1 Generator.Line Voltage AC.a809d1f1-c08f-54f9-0915-2a1f0096c464" 3.2800 Good
04-November-2021 20:50:00 "OSIDemo_GU1 Generator.Line Voltage AB.373eb947-c651-5aef-1948-a312f1aa02e9" 3.2900 Good
04-November-2021 20:50:00 "OSIDemo_GU1 Generator.Line Voltage AC.a809d1f1-c08f-54f9-0915-2a1f0096c464" 3.2800 Good
04-November-2021 20:50:00 "OSIDemo_GU1 Generator.Line Voltage BC.90cc345e-520f-5284-187b-d2c1f98bf536" 3.3200 Good
⋮
Reduce Data Set Using Linear Interpolation Provided by PI Server
Notice the large number of data points in the result of the previous step. You can reduce the data set by using the Interval name-value argument. For example the following read requests data with an interval of 4 hours. The Interval name-value argument requests the PI Server to perform linear interpolation on recorded values and provide results at the specified interval.
voltageInterpolatedTT = read(client, tagsVoltage.Tags(1:3), DateRange=[startDate,endDate], Interval=hours(4))
voltageInterpolatedTT = 843×3 timetable
04-November-2021 20:25:12 "OSIDemo_GU1 Generator.Line Voltage AB.373eb947-c651-5aef-1948-a312f1aa02e9" NaN Bad
04-November-2021 20:25:12 "OSIDemo_GU1 Generator.Line Voltage AC.a809d1f1-c08f-54f9-0915-2a1f0096c464" NaN Bad
04-November-2021 20:25:12 "OSIDemo_GU1 Generator.Line Voltage BC.90cc345e-520f-5284-187b-d2c1f98bf536" NaN Bad
05-November-2021 00:25:12 "OSIDemo_GU1 Generator.Line Voltage AB.373eb947-c651-5aef-1948-a312f1aa02e9" 3.2908 Good
05-November-2021 00:25:12 "OSIDemo_GU1 Generator.Line Voltage AC.a809d1f1-c08f-54f9-0915-2a1f0096c464" 3.3053 Good
05-November-2021 00:25:12 "OSIDemo_GU1 Generator.Line Voltage BC.90cc345e-520f-5284-187b-d2c1f98bf536" 3.3200 Good
05-November-2021 04:25:12 "OSIDemo_GU1 Generator.Line Voltage AB.373eb947-c651-5aef-1948-a312f1aa02e9" 3.2805 Good
05-November-2021 04:25:12 "OSIDemo_GU1 Generator.Line Voltage AC.a809d1f1-c08f-54f9-0915-2a1f0096c464" 3.2808 Good
05-November-2021 04:25:12 "OSIDemo_GU1 Generator.Line Voltage BC.90cc345e-520f-5284-187b-d2c1f98bf536" 3.3200 Good
05-November-2021 08:25:12 "OSIDemo_GU1 Generator.Line Voltage AB.373eb947-c651-5aef-1948-a312f1aa02e9" 3.3102 Good
05-November-2021 08:25:12 "OSIDemo_GU1 Generator.Line Voltage AC.a809d1f1-c08f-54f9-0915-2a1f0096c464" 3.3194 Good
05-November-2021 08:25:12 "OSIDemo_GU1 Generator.Line Voltage BC.90cc345e-520f-5284-187b-d2c1f98bf536" 3.2912 Good
05-November-2021 12:25:12 "OSIDemo_GU1 Generator.Line Voltage AB.373eb947-c651-5aef-1948-a312f1aa02e9" 3.3047 Good
05-November-2021 12:25:12 "OSIDemo_GU1 Generator.Line Voltage AC.a809d1f1-c08f-54f9-0915-2a1f0096c464" 3.3092 Good
⋮
Unstack Values from One Timetable Variable to Multiple Variables
Unstack the timetable to distribute each line voltage as a timetable variable.
uVoltageTT = unstack(voltageInterpolatedTT,"Value","Tag",... "AggregationFunction",@(x)x(~isempty(x)),"VariableNamingRule","preserve")
uVoltageTT = 281×3 timetable
04-November-2021 20:25:12 NaN NaN NaN
05-November-2021 00:25:12 3.2908 3.3053 3.3200
05-November-2021 04:25:12 3.2805 3.2808 3.3200
05-November-2021 08:25:12 3.3102 3.3194 3.2912
05-November-2021 12:25:12 3.3047 3.3092 3.3196
05-November-2021 16:25:12 3.2832 3.3094 3.2992
05-November-2021 20:25:12 3.2806 3.3188 3.3096
06-November-2021 00:25:12 3.3188 3.3200 3.3184
06-November-2021 04:25:12 3.2808 3.2812 3.3088
06-November-2021 08:25:12 3.2896 3.2906 3.3198
06-November-2021 12:25:12 3.3088 3.3192 3.3200
06-November-2021 16:25:12 3.3184 3.2806 3.3184
06-November-2021 20:25:12 3.3000 3.3188 3.3004
07-November-2021 00:25:12 3.3008 3.2992 3.3097
⋮
Fill Missing Values
Notice the timetable in the previous step contains some NaN values. This happens when data points of a timetable are not all sampled at the same interval. Use the fillmissing function to correct this by linear interpolation.
[cVoltageTT,~] = fillmissing(uVoltageTT,"linear")cVoltageTT = 281×3 timetable
04-November-2021 20:25:12 3.3011 3.3298 3.3200
05-November-2021 00:25:12 3.2908 3.3053 3.3200
05-November-2021 04:25:12 3.2805 3.2808 3.3200
05-November-2021 08:25:12 3.3102 3.3194 3.2912
05-November-2021 12:25:12 3.3047 3.3092 3.3196
05-November-2021 16:25:12 3.2832 3.3094 3.2992
05-November-2021 20:25:12 3.2806 3.3188 3.3096
06-November-2021 00:25:12 3.3188 3.3200 3.3184
06-November-2021 04:25:12 3.2808 3.2812 3.3088
06-November-2021 08:25:12 3.2896 3.2906 3.3198
06-November-2021 12:25:12 3.3088 3.3192 3.3200
06-November-2021 16:25:12 3.3184 3.2806 3.3184
06-November-2021 20:25:12 3.3000 3.3188 3.3004
07-November-2021 00:25:12 3.3008 3.2992 3.3097
⋮
View Each Voltage in a Separate Timetable
View voltage AB in its own timetable.
lineVoltageAB = cVoltageTT.Properties.VariableNames{1};
vabTT = timetable(cVoltageTT.(lineVoltageAB)(:), 'RowTimes', cVoltageTT.Time(:), 'VariableNames', {char(lineVoltageAB)})vabTT = 281×1 timetable
04-November-2021 20:25:12 3.3011
05-November-2021 00:25:12 3.2908
05-November-2021 04:25:12 3.2805
05-November-2021 08:25:12 3.3102
05-November-2021 12:25:12 3.3047
05-November-2021 16:25:12 3.2832
05-November-2021 20:25:12 3.2806
06-November-2021 00:25:12 3.3188
06-November-2021 04:25:12 3.2808
06-November-2021 08:25:12 3.2896
06-November-2021 12:25:12 3.3088
06-November-2021 16:25:12 3.3184
06-November-2021 20:25:12 3.3000
07-November-2021 00:25:12 3.3008
⋮
View voltage AC in its own timetable.
lineVoltageAC = cVoltageTT.Properties.VariableNames{2};
vacTT = timetable(cVoltageTT.(lineVoltageAC)(:), 'RowTimes', cVoltageTT.Time(:), 'VariableNames', {char(lineVoltageAC)})vacTT = 281×1 timetable
04-November-2021 20:25:12 3.3298
05-November-2021 00:25:12 3.3053
05-November-2021 04:25:12 3.2808
05-November-2021 08:25:12 3.3194
05-November-2021 12:25:12 3.3092
05-November-2021 16:25:12 3.3094
05-November-2021 20:25:12 3.3188
06-November-2021 00:25:12 3.3200
06-November-2021 04:25:12 3.2812
06-November-2021 08:25:12 3.2906
06-November-2021 12:25:12 3.3192
06-November-2021 16:25:12 3.2806
06-November-2021 20:25:12 3.3188
07-November-2021 00:25:12 3.2992
⋮
View voltage BC in its own timetable.
lineVoltageBC = cVoltageTT.Properties.VariableNames{3};
vbcTT = timetable(cVoltageTT.(lineVoltageBC)(:), 'RowTimes', cVoltageTT.Time(:), 'VariableNames', {char(lineVoltageBC)})vbcTT = 281×1 timetable
04-November-2021 20:25:12 3.3200
05-November-2021 00:25:12 3.3200
05-November-2021 04:25:12 3.3200
05-November-2021 08:25:12 3.2912
05-November-2021 12:25:12 3.3196
05-November-2021 16:25:12 3.2992
05-November-2021 20:25:12 3.3096
06-November-2021 00:25:12 3.3184
06-November-2021 04:25:12 3.3088
06-November-2021 08:25:12 3.3198
06-November-2021 12:25:12 3.3200
06-November-2021 16:25:12 3.3184
06-November-2021 20:25:12 3.3004
07-November-2021 00:25:12 3.3097
⋮
Visualize Tag Values of Voltages
To visualize values of interest, you can plot voltages from the timetables over time for further analysis.
subplot(3, 1, 1) plot(vabTT.Time, vabTT.("OSIDemo_GU1 Generator.Line Voltage AB.373eb947-c651-5aef-1948-a"), "r") title("{\itVoltage AB}", "FontWeight", "bold") xlabel("Timestamp") ylabel("Voltage") subplot(3, 1, 2) plot(vacTT.Time, vacTT.("OSIDemo_GU1 Generator.Line Voltage AC.a809d1f1-c08f-54f9-0915-2"), "g") title("{\itVoltage AC}", "FontWeight", "bold") xlabel("Timestamp") ylabel("Voltage") subplot(3, 1, 3) plot(vbcTT.Time, vbcTT.("OSIDemo_GU1 Generator.Line Voltage BC.90cc345e-520f-5284-187b-d"), "b") title("{\itVoltage BC}", "FontWeight", "bold") xlabel("Timestamp") ylabel("Voltage")

Cleanup
When you are finished working with the PI Data Archive, disconnect and remove the client by clearing its variable from the workspace.
clear client;