Skip navigation
All Places > PI Developers Club > Blog > 2013 > May

Accessing AF via Matlab

Posted by mhalhead Champion May 18, 2013

 My first blog post; finally, only took me 2 months to write this!


Numerous method of accessing PI data from Matlab have been published so a thought I throw another one into the mix. The issue with most of these methods is that support for AF is limited, particularly if you want to write back. The good news is that it turns out that Matlab is very capable of calling the AF SDK (or any .NET assembly for that matter). This means that you can use the very rich AF SDK to interact with AF from Matlab. AF 2.5 also gives you access to all the PI data. So I thought that I would show the basics, the code is not "production" ready seeing that I have not included minor things like exception handling.


Why would you want to do this:


Matlab is an excellent tool for number crunching. Building model and generally manipulating large data sets is really easy in Matlab.  I'm guessing you all know what the PI Systems is (otherwise you probably wouldn't be here). Using the AF SDK has numerous advantageous over other method:

  • I've found the performance to be superior to OLE DB
  • No limitation: you can read/write/... Anything that the AF SDK supports is available to you.

Useful link:

The real stuff

The first step is to create an instance of the AF SDK and import the relevant namespaces (note the .* at the end of the namespaces). Yes you do need the AF SDK on the Matlab computer.  

afSDK = NET.addAssembly('OSIsoft.AFSDK');
import OSIsoft.AF.*
import OSIsoft.AF.Asset.*

 Now connect to an AF server and database:

piSystems = OSIsoft.AF.PISystems;
PIsystem = piSystems.Item('MyAFServer');
AFdatabase = PIsystem.Databases.Item('MyAFDatabase');



 That is it. You now have a fully functional connection to AF via the SDK within Matlab. This means that you can do anything with this connection that the AF SDK allows.


Couple of examples working with the AF:

Find an Element: 

afElements = AFElement.FindElements(AFdatabase, [], 'Amplats', AFSearchField.Name, true, AFSortField.Name,  AFSortOrder.Ascending,intmax('int32'));

You hopefully noticed the one trick, nulls are passed as []. Otherwise it is pretty much the same as working with the AF SDK in C#. Below is a simply example of access the returned elements collection



Get some values: 

powerTransmitters = AFElement.FindElements(AFdatabase, [], '138JI006', AFSearchField.Name, true, AFSortField.Name,  AFSortOrder.Ascending,intmax('int32'));
attrib = powerTransmitters.Item(0).Attributes;
PV = attrib.Item('PV');

myTime = OSIsoft.AF.Time.AFTime.Now;
myValues = PV.Data.RecordedValue(myTime, Data.AFRetrievalMode.AtOrBefore, PV.DefaultUOM);



The more astute reader will have noticed that I went and got another element; I need one that had actual values. You will also notice that I constructed an AFTime object; you must pass a time object to the RecordValue method and a Matlab type doesn't cut it.


I think I've demonstrate just how easy it is to work with the AF SDK directly within Matlab. It very powerful option for access AF (and now PI data thanks to RDA) from Matlab.


All the code was tested on Matlab 2013a. You will need to check the MathWorks documentation if you are using an older version.


So that all folks





PI Web Services 2012 added support for searching through PI AF for Elements, Attributes and Event Frames. These features are added in the IPISoap interface that is added only in this release. One parameter that is required in most of these new search methods in IPISoap is RootPath. This essential is used to identify which AF Server and Database you are searching in. If you want to be searching for a subtree instead of the whole database, then you can also use this to specify that. The problem is you might start specifying this path parameter like you would in any other PI System products, like \\myafserver\myafdatabase. But this would not be recognized as a valid path with PI Web Services.


The format for this RootPath parameter is somewhat similar to how you would specify a path to the AF Attribute for reading values in the previous releases.


Referencing our usual NuGreen demo AF Database as an example:




Where the AF Server is piafserver and database name is afdb.


If you want to specify the AF Server and Database to search in, for finding Elements (IPISoap's FindElements method), it is:
af:\\<af server>\<af database>




If you want to specify to search within a specific subtree or element, it is:
af:\\<af server>\<af database>\<path to af element>


For example, I only want the elements that fulfill the name criteria in the subtree under Houston, my path should be:


You can use this simple code snippet for a console application to test this:

private void FindElement()
    PISoapServiceClient sClient = new PISoapServiceClient();
    ElementSearchConstraints constraints = new ElementSearchConstraints();
    constraints.AllowMatchOnDerivedTemplates = true;
    constraints.NameMask = "B-*";
    constraints.RootPath = @"af:\\piafserver\afdb";
    //constraints.RootPath = @"af:\\piafserver\afdb\NuGreen\Houston";

    ElementSearchManner manner = new ElementSearchManner();
    manner.FlatHierarchy = true;

    Element[] elements = sClient.FindElements(constraints, manner);

    foreach (Element e in elements)

For finding path of attributes through PI Web Services, you have to provide a Root Path as well. The difference that I've found out is that you cannot specify a path to just the database. Meaning you have to provide a path to a specific element or a subtree that you want to search:
af:\\<af server>\<af database>\<path to af element>


af:\\piarserver\afdb\NuGreen\Houston\Cracking Process\Equipment\B-210 


Here's a sample code snippet:

private static void FindAttribute()
    PISoapServiceClient sClient = new PISoapServiceClient();

    AttributeSearchConstraints constraints = new AttributeSearchConstraints();
    constraints.NameMask = "Process Feedrate";
    constraints.RootPath = @"af:\\piafserver\afdb\NuGreen";
    //constraints.RootPath = @"af:\\piafserver\afdb\NuGreen\Houston\Cracking Process\Equipment\B-210";

    AttributeSearchManner manner = new AttributeSearchManner();

    string[] attributepaths = sClient.FindAttributePaths(constraints, manner);

    foreach (string path in attributepaths)

If you are searching for Event Frames instead, replace "af:" with "ef:", like:
ef:\\<af server>\<af database>


The reason for using the "ef:" prefix is because for searching Event Frames, PI Web Services is expecting a path to an event frame instead of a element or attribute for the RootPath parameter. This is because you can have setup hierarchy for your events like batch, unit-batch and sub-batch. The RootPath parameter is for you to specify which event frame is the root event that the search runs through. To do that the path format should be:
ef:\\<af server>\<af database>\EventFrames[<name of event>] or
ef:\\<af server>\<af database>\EventFrames[{<GUID of event>}] 


As an example, here's some sample event frames created for this:




Note: If your AF server has Event Frame feature enabled, you can manually create event frames to test this.


If I want to find all event frames in the AF database, I can simply use the path:


But if what I want is limited to just the child event frame of Process Downtime 20130506 I can set the RootPath as:
ef:\\piafserver\afdb\EventFrames[Process Downtime 20130506]


Again a simple code snippet:

private static void FindEventFrames()
    PISoapServiceClient sClient = new PISoapServiceClient();

    EventFrameSearchConstraints constraints = new EventFrameSearchConstraints();
    constraints.NameMask = "*";
    constraints.RootPath = @"ef:\\piafserver\afdb";
    //constraints.RootPath = @"ef:\\piafserver\afdb\EventFrames[Process Downtime 20130506]";
    constraints.RefElementNameMask = "*";
    constraints.SearchRootLevelOnly = false;
    constraints.Start = "*-30d";
    constraints.Template = null;

    EventFrameSearchManner manner = new EventFrameSearchManner();
    manner.UseName = true;

    EventFrame[] efs = sClient.FindEventFrames(constraints, manner);

    foreach(EventFrame ef in efs)

Hopefully this quick introduction of the path format expected in PI Web Services will be helpful for you in using these new search methods introduced in PI Web Services 2012.

Hello to the OSIsoft vCampus community!  My name is Dan Noonen and I'm sending this email to introduce myself to all of you. I am the new PM for PI System Access.  I come to OSIsoft after a long stint with Rockwell Automation.  At Rockwell I held various firmware and software development positions throughout the years culminating with a role as a Software Development Manager.  Most of my development experience has been in the infrastructure that moves data between the User Interface layer and the Control System.  I'm very excited to join all of you and look forward to collaborating on the various PI System Access methods.  My main initial focus will be on the emerging REST/OData access method and I'd be very interested to hear your related thoughts and needs.  


I'm still getting oriented into all the logistics associated with vCampus.  If you are trying to reach out to me on vCampus and I'm not replying back, it isn't because I'm ignoring you :-).    You can always reach me at


Dan Noonen





Filter Blog

By date: By tag: