Main Content

Process PI Data Using Common MATLAB Operations

R2026b

This 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")

Three subplot time series of Voltage AB (red), Voltage AC (green), and Voltage BC (blue) ranging from 3.28 to 3.32 over November to December 2021

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;

See Also

Functions

Topics