Main Content

Visualize and Preprocess OPC UA Data

This example shows you how to work with OPC UA Data objects.

You create OPC UA Data objects when you read historical data from an OPC UA server. OPC UA Data objects allow you to store, visualize and manipulate historical data before converting that data to builtin data types for further processing in MATLAB.

For more information on generating OPC UA Data objects, see the example Read Historical OPC UA Server Data.

Load Sample OPC UA Data Set

Load the sample data into the workspace.

load demoUA_SampleData

Display OPC UA Data objects

Examine the workspace to see what variables have been loaded.

whos
  Name            Size            Bytes  Class          Attributes

  dataSample      1x3              4931  opc.ua.Data              

Display a summary of the sample data.

summary(dataSample)
1-by-3 OPC UA Data object:

     Name        Value            Start Timestamp           End Timestamp            Quality      
    ------  ----------------  -----------------------  -----------------------  ------------------
    Double  9 double values   2015-04-22 09:00:10.000  2015-04-22 09:01:30.000  3 unique qualities
    Float   12 single values  2015-04-22 09:00:02.000  2015-04-22 09:01:30.000  3 unique qualities
    Int32   12 int32 values   2015-04-22 09:00:02.000  2015-04-22 09:01:30.000  3 unique qualities

The data object contains three data sets. The first element Double contains 9 values, the second and third have 12 values each.

See whether the Float and Int32 data sets have the same timestamp.

arrayHasSameTimestamp(dataSample(2:3))
ans =

  logical

   1

Display the Float and Int32 data sets together. Because all the elements have the same timestamp, a table of values can be displayed

dataSample(2:3)
ans = 

1-by-2 OPC UA Data object array:

           Timestamp                      Float                            Int32                
    -----------------------  -------------------------------  --------------------------------  
    2015-04-22 09:00:02.000       10.000000 [Good (Raw)]                    10 [Good (Raw)]       
    2015-04-22 09:00:25.000       20.000000 [Good (Raw)]                    20 [Good (Raw)]       
    2015-04-22 09:00:28.000       25.000000 [Good (Raw)]                    25 [Good (Raw)]       
    2015-04-22 09:00:40.000       30.000000 [Good (Raw)]                    30 [Good (Raw)]       
    2015-04-22 09:00:42.000        0.000000 [Bad (Raw)]                      0 [Bad (Raw)]        
    2015-04-22 09:00:48.000        4.000000 [Good (Raw)]                    40 [Good (Raw)]       
    2015-04-22 09:00:52.000       50.000000 [Good (Raw)]                    50 [Good (Raw)]       
    2015-04-22 09:01:12.000       60.000000 [Good (Raw)]                    60 [Good (Raw)]       
    2015-04-22 09:01:17.000       70.000000 [Uncertain (Raw)]               70 [Uncertain (Raw)]  
    2015-04-22 09:01:23.000       70.000000 [Good (Raw)]                    70 [Good (Raw)]       
    2015-04-22 09:01:26.000       80.000000 [Good (Raw)]                    80 [Good (Raw)]       
    2015-04-22 09:01:30.000       90.000000 [Good (Raw)]                    90 [Good (Raw)]       

Change the Date Display Format

Get the current date display format using opc.getDateDisplayFormat.

origFormat = opc.getDateDisplayFormat;

Change the display format to standard US date format and display the value again.

opc.setDateDisplayFormat('mm/dd/yyyy HH:MM AM');
dataSample(2:3)
ans = 

1-by-2 OPC UA Data object array:

         Timestamp                    Float                            Int32                
    -------------------  -------------------------------  --------------------------------  
    04/22/2015  9:00 AM       10.000000 [Good (Raw)]                    10 [Good (Raw)]       
    04/22/2015  9:00 AM       20.000000 [Good (Raw)]                    20 [Good (Raw)]       
    04/22/2015  9:00 AM       25.000000 [Good (Raw)]                    25 [Good (Raw)]       
    04/22/2015  9:00 AM       30.000000 [Good (Raw)]                    30 [Good (Raw)]       
    04/22/2015  9:00 AM        0.000000 [Bad (Raw)]                      0 [Bad (Raw)]        
    04/22/2015  9:00 AM        4.000000 [Good (Raw)]                    40 [Good (Raw)]       
    04/22/2015  9:00 AM       50.000000 [Good (Raw)]                    50 [Good (Raw)]       
    04/22/2015  9:01 AM       60.000000 [Good (Raw)]                    60 [Good (Raw)]       
    04/22/2015  9:01 AM       70.000000 [Uncertain (Raw)]               70 [Uncertain (Raw)]  
    04/22/2015  9:01 AM       70.000000 [Good (Raw)]                    70 [Good (Raw)]       
    04/22/2015  9:01 AM       80.000000 [Good (Raw)]                    80 [Good (Raw)]       
    04/22/2015  9:01 AM       90.000000 [Good (Raw)]                    90 [Good (Raw)]       

Reset the display format to the default.

opc.setDateDisplayFormat('default')
ans =

    'yyyy-mm-dd HH:MM:SS.FFF'

Reset the display format to the original value.

opc.setDateDisplayFormat(origFormat);

Visualize OPC UA Data

Visualize OPC UA Data using the plot and stairs function on the data object.

figure;
axH1 = subplot(2,1,1);
plot(dataSample);
title('Plot of sample data');
axH2 = subplot(2,1,2);
stairs(dataSample);
title('Stairstep plot of sample data');
legend('Location', 'NorthWest')

Resample OPC UA Data

The data in the dataSample set has different timestamps.

arrayHasSameTimestamp(dataSample)
ans =

  logical

   0

Attempt to convert the data to a double array. The conversion will fail.

try
    vals = double(dataSample);
catch exc
    disp(exc.message)
end
Conversion to double failed. All elements of the OPC Data object must have the same time stamp.
Consider using 'TSUNION', 'TSINTERSECT' or 'RESAMPLE' on the Data object.

The intersection of the data timestamps results in a smaller data set containing the common timestamps from all elements.

dataIntersect = tsintersect(dataSample)
dataIntersect = 

1-by-3 OPC UA Data object array:

           Timestamp                   Double                      Float                        Int32             
    -----------------------  --------------------------  --------------------------  ---------------------------  
    2015-04-22 09:00:40.000       40.000000 [Bad (Raw)]        30.000000 [Good (Raw)]               30 [Good (Raw)]  
    2015-04-22 09:01:30.000       90.000000 [Good (Raw)]       90.000000 [Good (Raw)]               90 [Good (Raw)]  

Convert the data object into a double array.

vals = double(dataIntersect)
vals =

    40    30    30
    90    90    90

Use tsunion to return the union of time series in a Data object. New values are interpolated using the method supplied (or linear interpolation if no method is supplied). The quality is set to "Interpolated" for those new values.

dataUnion = tsunion(dataSample)
dataUnion = 

1-by-3 OPC UA Data object array:

           Timestamp                               Double                                       Float                                Int32                  
    -----------------------  --------------------------------------------------  -----------------------------------  ------------------------------------  
    2015-04-22 12:30:02.000        2.000000 [Uncertain:Subnormal (Interpolated)]       10.000000 [Good (Raw)]                        10 [Good (Raw)]           
    2015-04-22 12:30:10.000       10.000000 [Good (Raw)]                               13.478261 [Good (Interpolated)]               13 [Good (Interpolated)]  
    2015-04-22 12:30:20.000       20.000000 [Good (Raw)]                               17.826086 [Good (Interpolated)]               18 [Good (Interpolated)]  
    2015-04-22 12:30:25.000       25.000000 [Good (Interpolated)]                      20.000000 [Good (Raw)]                        20 [Good (Raw)]           
    2015-04-22 12:30:28.000       28.000000 [Good (Interpolated)]                      25.000000 [Good (Raw)]                        25 [Good (Raw)]           
    2015-04-22 12:30:30.000       30.000000 [Good (Raw)]                               25.833334 [Good (Interpolated)]               26 [Good (Interpolated)]  
    2015-04-22 12:30:40.000       40.000000 [Bad (Raw)]                                30.000000 [Good (Raw)]                        30 [Good (Raw)]           
    2015-04-22 12:30:42.000       42.000000 [Good (Interpolated)]                       0.000000 [Bad (Raw)]                          0 [Bad (Raw)]            
    2015-04-22 12:30:48.000       48.000000 [Good (Interpolated)]                       4.000000 [Good (Raw)]                        40 [Good (Raw)]           
    2015-04-22 12:30:50.000       50.000000 [Good (Raw)]                               27.000000 [Good (Interpolated)]               45 [Good (Interpolated)]  
    2015-04-22 12:30:52.000       52.000000 [Good (Interpolated)]                      50.000000 [Good (Raw)]                        50 [Good (Raw)]           
    2015-04-22 12:31:00.000       60.000000 [Good (Raw)]                               54.000000 [Good (Interpolated)]               54 [Good (Interpolated)]  
    2015-04-22 12:31:10.000       70.000000 [Uncertain (Raw)]                          59.000000 [Good (Interpolated)]               59 [Good (Interpolated)]  
    2015-04-22 12:31:12.000       72.000000 [Good (Interpolated)]                      60.000000 [Good (Raw)]                        60 [Good (Raw)]           
    2015-04-22 12:31:17.000       77.000000 [Good (Interpolated)]                      70.000000 [Uncertain (Raw)]                   70 [Uncertain (Raw)]      
    2015-04-22 12:31:20.000       80.000000 [Good (Raw)]                               70.000000 [Good (Interpolated)]               70 [Good (Interpolated)]  
    2015-04-22 12:31:23.000       83.000000 [Good (Interpolated)]                      70.000000 [Good (Raw)]                        70 [Good (Raw)]           
    2015-04-22 12:31:26.000       86.000000 [Good (Interpolated)]                      80.000000 [Good (Raw)]                        80 [Good (Raw)]           
    2015-04-22 12:31:30.000       90.000000 [Good (Raw)]                               90.000000 [Good (Raw)]                        90 [Good (Raw)]           

Plot the data with markers to show how the methods work.

figure;
subplot(2,1,1);
plot(dataSample, 'Marker','.');
hold all
plot(dataIntersect, 'Marker','o', 'LineStyle','none');
title('Intersection of time series in Data object');
subplot(2,1,2);
plot(dataSample, 'Marker','.');
hold all
plot(dataUnion, 'Marker','o', 'LineStyle','--');
title('Union of time series in Data object');

Resample the small data set at specified time steps.

newTS = dataSample(1).Timestamp(1):seconds(5):dataSample(1).Timestamp(end);
dataResampled = resample(dataSample,newTS)
figure;
plot(dataSample);
hold all
plot(dataResampled, 'Marker','x', 'Linestyle','none');
dataResampled = 

1-by-3 OPC UA Data object array:

           Timestamp                       Double                                Float                                Int32                  
    -----------------------  -----------------------------------  -----------------------------------  ------------------------------------  
    2015-04-22 12:30:10.000       10.000000 [Good (Raw)]                13.478261 [Good (Interpolated)]               13 [Good (Interpolated)]  
    2015-04-22 12:30:15.000       15.000000 [Good (Interpolated)]       15.652174 [Good (Interpolated)]               16 [Good (Interpolated)]  
    2015-04-22 12:30:20.000       20.000000 [Good (Raw)]                17.826086 [Good (Interpolated)]               18 [Good (Interpolated)]  
    2015-04-22 12:30:25.000       25.000000 [Good (Interpolated)]       20.000000 [Good (Raw)]                        20 [Good (Raw)]           
    2015-04-22 12:30:30.000       30.000000 [Good (Raw)]                25.833334 [Good (Interpolated)]               26 [Good (Interpolated)]  
    2015-04-22 12:30:35.000       35.000000 [Good (Interpolated)]       27.916666 [Good (Interpolated)]               28 [Good (Interpolated)]  
    2015-04-22 12:30:40.000       40.000000 [Bad (Raw)]                 30.000000 [Good (Raw)]                        30 [Good (Raw)]           
    2015-04-22 12:30:45.000       45.000000 [Good (Interpolated)]        2.000000 [Good (Interpolated)]               20 [Good (Interpolated)]  
    2015-04-22 12:30:50.000       50.000000 [Good (Raw)]                27.000000 [Good (Interpolated)]               45 [Good (Interpolated)]  
    2015-04-22 12:30:55.000       55.000000 [Good (Interpolated)]       51.500000 [Good (Interpolated)]               52 [Good (Interpolated)]  
    2015-04-22 12:31:00.000       60.000000 [Good (Raw)]                54.000000 [Good (Interpolated)]               54 [Good (Interpolated)]  
    2015-04-22 12:31:05.000       65.000000 [Good (Interpolated)]       56.500000 [Good (Interpolated)]               57 [Good (Interpolated)]  
    2015-04-22 12:31:10.000       70.000000 [Uncertain (Raw)]           59.000000 [Good (Interpolated)]               59 [Good (Interpolated)]  
    2015-04-22 12:31:15.000       75.000000 [Good (Interpolated)]       66.000000 [Good (Interpolated)]               66 [Good (Interpolated)]  
    2015-04-22 12:31:20.000       80.000000 [Good (Raw)]                70.000000 [Good (Interpolated)]               70 [Good (Interpolated)]  
    2015-04-22 12:31:25.000       85.000000 [Good (Interpolated)]       76.666664 [Good (Interpolated)]               77 [Good (Interpolated)]  
    2015-04-22 12:31:30.000       90.000000 [Good (Raw)]                90.000000 [Good (Raw)]                        90 [Good (Raw)]           

Filter Data by Quality

Find only the Good data from the second element of resampled data set

resampledGood = filterByQuality(dataResampled(2), 'good')
resampledGood = 

1-by-1 OPC UA Data object array:

           Timestamp                        Float                 
    -----------------------  -----------------------------------  
    2015-04-22 12:30:10.000       13.478261 [Good (Interpolated)]  
    2015-04-22 12:30:15.000       15.652174 [Good (Interpolated)]  
    2015-04-22 12:30:20.000       17.826086 [Good (Interpolated)]  
    2015-04-22 12:30:25.000       20.000000 [Good (Raw)]           
    2015-04-22 12:30:30.000       25.833334 [Good (Interpolated)]  
    2015-04-22 12:30:35.000       27.916666 [Good (Interpolated)]  
    2015-04-22 12:30:40.000       30.000000 [Good (Raw)]           
    2015-04-22 12:30:45.000        2.000000 [Good (Interpolated)]  
    2015-04-22 12:30:50.000       27.000000 [Good (Interpolated)]  
    2015-04-22 12:30:55.000       51.500000 [Good (Interpolated)]  
    2015-04-22 12:31:00.000       54.000000 [Good (Interpolated)]  
    2015-04-22 12:31:05.000       56.500000 [Good (Interpolated)]  
    2015-04-22 12:31:10.000       59.000000 [Good (Interpolated)]  
    2015-04-22 12:31:15.000       66.000000 [Good (Interpolated)]  
    2015-04-22 12:31:20.000       70.000000 [Good (Interpolated)]  
    2015-04-22 12:31:25.000       76.666664 [Good (Interpolated)]  
    2015-04-22 12:31:30.000       90.000000 [Good (Raw)]           

Filter the second element of the resampled data to return only the Interpolated data. Visualize the filtered data with the original.

resampledInterpolated = filterByQuality(dataResampled(2), 'Origin','interpolated')

figure;
plot(dataResampled(2))
hold on
plot(resampledGood, 'Marker', '+', 'Linestyle','none', 'DisplayName', 'Good');
plot(resampledInterpolated, 'Marker','x', 'Linestyle','none', 'DisplayName', 'Interpolated');
legend('Location', 'NorthWest')
resampledInterpolated = 

1-by-1 OPC UA Data object array:

           Timestamp                        Float                 
    -----------------------  -----------------------------------  
    2015-04-22 12:30:10.000       13.478261 [Good (Interpolated)]  
    2015-04-22 12:30:15.000       15.652174 [Good (Interpolated)]  
    2015-04-22 12:30:20.000       17.826086 [Good (Interpolated)]  
    2015-04-22 12:30:30.000       25.833334 [Good (Interpolated)]  
    2015-04-22 12:30:35.000       27.916666 [Good (Interpolated)]  
    2015-04-22 12:30:45.000        2.000000 [Good (Interpolated)]  
    2015-04-22 12:30:50.000       27.000000 [Good (Interpolated)]  
    2015-04-22 12:30:55.000       51.500000 [Good (Interpolated)]  
    2015-04-22 12:31:00.000       54.000000 [Good (Interpolated)]  
    2015-04-22 12:31:05.000       56.500000 [Good (Interpolated)]  
    2015-04-22 12:31:10.000       59.000000 [Good (Interpolated)]  
    2015-04-22 12:31:15.000       66.000000 [Good (Interpolated)]  
    2015-04-22 12:31:20.000       70.000000 [Good (Interpolated)]  
    2015-04-22 12:31:25.000       76.666664 [Good (Interpolated)]