Skip navigation
All Places > PI Developers Club > PI Visualization Development > Blog > Author: Kenji Hashimoto

Sometimes we want to show compass gauge for showing the wind direction by PI Vision.

I found "Canvas Gauge" library, so tried it on PI Vision.

GitHub - Mikhus/canvas-gauges: HTML5 Canvas Gauge (Canvas Gauges library)

(Wind Turbine picture is coming from symbol library. My custom symbol shows only compass gauge)


My PI Vision custom symbol code is on this link.

GitHub - kenji0711/CompassGaugeCustomSymbol: PI Vision 2017 custom symbol. It can show compass. the value should be from…

The tag should have 0-360 values and it shows direction.

Please try it and put the comments. Now we don't need to use PI ProcessBook to show the compass gauge.


How to use it:

Copy the following files to %PIHOME64%\PIVision\Scripts\app\editor\symbols\ext




Copy the following files to ext\libraries



Copy the file to ext\Icons


There are a lot of users who want a SQC symbol in PI Vision, similarly to what exists in PI ProcessBook.

On the customer feedback site for PI Vision, there is currently 87 votes for such a feature.

If you also want this feature, please vote!

Until it gets implemented, I tried my best to mimic the PI ProcessBook's SQC symbol.

In particular, PI ProcessBook's SQC symbol displays histogram along with a trend overlay.

I tried to mimic this in PI Vision. (PI Coresight 2016 R2)

First, for displaying the histogram, I used this sample.


It can show histogram like following.

The limits (HiHi, LoLo, etc.) are computed using the following analyses and are stored as child attributes.


In PI Vision, I created the following display.

The trend contains the source attribute (in blue) and the limits are the dotted lines.

The red dots showing the exceptions that are created by the analysis too. (2017/05/15 Edited as Jerome's comments)


If the histogram does not appear, open the debug console and see if you get the following error:

“Too many points in dataset. Number of points is 401 and current limit is 400.“

You will need to either view the data over a smaller timerange or edit the custom symbol's source code.

In the PI Vision's "ext" folder open the sym-amcharts-histogram.js and add in the "Intervals" property as below.

Intervals represents the number of values the symbol will retrieve. Setting intervals to a large number can impact performance.


I am by no means an expert in SQC and in the statistics method involved.

If you have suggestions, please add them in the comments below.


I worked with Daniel Cho and Jerome Lefebvre  for creating this display.

I created write value custom symbol by PI Coresight 2016.

The specified item was not found.

Since PI Coresight 2016 R2 and this old custom symbol does not work anymore, I created new one. (Edit 2017/05/30 : Changed the code to PI Vision 2017)

Also for writing value, we have a good example on

Thank you Anna Perry. It works by PI Vision 2017 too.


This example calls PI Web API to write value. So you can create custom symbol with PI Web API from now on.

You can download the code from GitHub. (Changed the code to PI Vision 2017)

GitHub - kenji0711/PICoresight2016R2-CustomSymbol-PutValue


(In this display I put "250" value to cdt158 tag.) It is possible to write value to AF attribute too if the attribute is from PI tags!

Put the new value to the box and click "Put New Value" text. It uploads the new value to PI data Archive or AF with current timestamp by PI Web API.

It can be hided by right click > Format Symbol

The point is that this code uses PI Web API Batch request.

Copy following 3 files to %PIHOME64%\PIVision\Scripts\app\editor\symbols\ext folder.

Also copy the image (attaced pen.svg) to Scripts\app\editor\symbols\ext\Icons folder.

sym-putvalue.js (Please change var piwebapiaddress = "MachineName"; to your PI Web API machine name. PI Coresight machine contains PI Web API. So it should be PI Vision machine name)

Also a lot of people interested in to register the custom symbol to the specific user.

So I tried the code to check browser user name. if the user is 'KHASHIMOTO' then this custom symbol appears however, the other users open it, it does not shows up if you put the following code on the sym-putvalue.js file.

if (userNamewithoutDomain == 'KHASHIMOTO')



(function (PV) {  
    var userName = PV.IdentityContext.FriendlyUserName.toUpperCase();  
    var index = userName.indexOf("\\",0);  
    var userNamewithoutDomain = userName.substr(index + 1);  
    function symbolVis() { }  
    symbolVis.prototype.init = function (scope) {  
     this.onDataUpdate = dataUpdate; 
     //default value for timestamp
     scope.config.TimeBox = '*';
     function dataUpdate(data) {  
    if(data) {  
        scope.value = data.Value;  
        scope.time = data.Time;  
         scope.path = data.Path;  
        if(data.Label) {  
            scope.label = data.Label;  

     scope.putvalue = function() {    
            var piwebapiaddress = "khashimotoe6440";    
            //scope.path contains pi:\\servername\tagname or af:\\servername\databasename\element...|attribute    
            var ini = scope.path.substr(0,3);    
            var orgpath = scope.path.substr(3,10000);    
            //To double the backslash -  \\\\servername\\tagname    
            var path = orgpath.replace(/\\|\\/g,"\\\\");    
                var urladdress = "\"https://" + piwebapiaddress + "/piwebapi/points?path="+path+"\"";    
            else if(ini=="af:"){    
                var urladdress = "\"https://" + piwebapiaddress + "/piwebapi/attributes?path="+path+"\"";    
            //Get text box value    
            var valueboxval = new String(scope.config.ValueBox, { "type" : "text/plain" });
            var timeboxval = new String(scope.config.TimeBox, { "type" : "text/plain" });    
            //Create value contents as json    
            var jsonval = '"{Timestamp : \'' + timeboxval + '\', Value:\'' + valueboxval + '\'}"';
            //var jsonval = '"{Value:' + valueboxval + '}"';    
            // Create contents of PI Web API batch request
            var contents = '{"GetWebID":{"Method": "GET","Resource": '+ urladdress + '},"WriteValuetoPI":{"Method":"POST","Resource": "{0}","Content":' + jsonval + ',"Parameters": ["$.GetWebID.Content.Links.Value"],"ParentIds": ["GetWebID"]}}';    
            //PI Web API Request    
            var batchurl = "https://" + piwebapiaddress + "/piwebapi/batch";
            var xhr= new XMLHttpRequest();    
            //true = Async call    
            //Set credential for Kerberos    
            xhr.withCredentials = true;    
            //Send request    
    var definition = {  
        typeName: 'putvalue',  
        datasourceBehavior: PV.Extensibility.Enums.DatasourceBehaviors.Single,  
        visObjectType: symbolVis,  
        getDefaultConfig: function() {  
            return {  
                DataShape: 'Value',  
                Height: 170,  
                Width: 180,  
            TextColor: 'rgb(255,255,255)',  
         ShowLabel: true,  
         ShowTime: true,  
         ShowPutValue: true  
    configTitle: 'Format Symbol',  
    StateVariables: [ 'MultistateColor' ]  



<div class="c-side-pane t-toolbar">
    <span style="color:#fff; margin-left:15px">Text Color</span>
<div class="config-option-format"><cs-color-picker id="textcolor" ng-model="config.TextColor"></cs-color-picker></div>
<div class="c-side-pane t-toolbar">
    <span style="color:#fff; margin-left:15px">Background Color</span>
<div class="config-option-format"><cs-color-picker id="backgroundcolor" ng-model="config.BackgroundColor"></cs-color-picker></div>
<div class="c-side-pane t-toolbar">
    <span style="color:#fff; margin-left:15px">Show Options</span>
<div class="c-config-content">Show Label:
    <input type="checkbox" ng-model="config.ShowLabel">
<div class="c-config-content">Show Time:
    <input type="checkbox" ng-model="config.ShowTime">
<div class="c-config-content">Show PutValue:  
    <input type="checkbox" ng-model="config.ShowPutValue">  



<div ng-style="{background: config.BackgroundColor, color: MultistateColor || config.TextColor}">  
    <div ng-show="config.ShowLabel">{{label}}</div>  
    <div ng-show="config.ShowTime">{{time}}</div>  
    <div id='putvalue' ng-show="config.ShowPutValue">  
        Enter Timestamp :<br>
        <input type="text" style="margin-left:5px; width:120px;" name="timebox" ng-model="config.TimeBox" /><br>  
        Enter new Value :<br>
        <input type="text" style="margin-left:5px; width:120px;" name="valuebox" ng-model="config.ValueBox" /><br>  
        <a name='putvalue' type="button" ng-click="putvalue()">Put New Value</a><br>  

For using PI Web API from custom symbols, I needed to change CoresMethods = *, CorsHeaders = *, CorsOrigins = * and CorsSupportsCredentials = True in the AF configuration database. (I use Kerberos as Authentication Methods)

Enjoy the write value to PI from PI Vision!

Some customers want to achieve PI WebParts (PI TreeView + PI Graphic) behavior by PI Coresight 2016 R2.


For showing Tree, we can use PI Web API to achieve it. Help file contains it.

Please check following part.


A Simple Application

In this section, we'll develop a JavaScript application for exploring the AF hierarchy of your PI System. A basic knowledge of JavaScript, HTML, and CSS is assumed. The following is the complete code.


It can shows like PI Tree View.

For showing PI ProcessBook Display by PI Coresight, we can use HTML's Frame.

I created two files. (Please change F2's src= part as your PBDisplay)

1 index.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "">
<html xmlns="" xml:lang="ja" lang="ja">
    <frameset cols='20%,80%' id="main">
        <frame name="F1" src=".\AFTree.html" />
        <frame name="F2" src="https://CoresightServerName/Coresight/PB/#/PBDisplays/40102?HideToolBar">
                <p>The browser does not support frames</p>


2 AFTree.html  (I changed it from PI WebAPI's help file. It contains URL hyper link to "F2" frame. Please change RootElement and DisplayPath)

<!DOCTYPE html>
    <title>AF Hierarchy Viewer</title>
    <script src=""></script>
    <script type="text/javascript">
        //Please enter tree's root element's WebID address.
        var RootElement = 'https://PIWebAPIServerName/piwebapi/assetdatabases/D0c_UDU9Pb-k6nVsZu0iuPpgKZD5gy4Ww0WeCfOWEZoj_wS0hBU0hJTU9UT0U2NDQwXFBJIEJJRyBUSVJFUyBDTw/elements';
        //Display path and CurrentElement
        var DisplayPath = 'https://CoresightServerName/Coresight/PB/#/PBDisplays/40102?HideToolBar&CurrentElement=';
        var childrenMap = {
          Elements: ['Elements']
        function node(name, type, links, parentDiv, path) {
          this.type = type;
          this.links = links;
          this.flipper = $('<span class="flipper">+</span>').click(flip.bind(this, this));
          parentDiv.append(this.flipper).append('<span class=" + type + "><a href="'+DisplayPath + path  + '" target="F2">' + name + '</a></span><br />');
          this.div = $('<div></div>').hide().appendTo(parentDiv);
        function loadChildren(n) {
          n.loaded = true;
          childrenMap[n.type].forEach(function(childCollection) {
            $.get(n.links[childCollection], function(collection) {
              n[childCollection] = (item) {
                return new node(item.Name, childCollection, item.Links, n.div, item.Path);
        function flip(n) {
          if (!n.loaded) { loadChildren(n); }
          n.flipper.html(n.flipper.html() == '+' ? '-' : '+');
        $(function() {
          root = new node('Elements', 'Elements',
            { Elements: RootElement }, $("#root"));
    <style type="text/css">
        div {
          left: 10px;
          position: relative;
        .flipper {
          cursor: pointer;
  <div id="root"></div>


For showing PI Coresight in Frame, it needs web.config change.


<add name="X-Frame-Options" value="Allow"/>


You can run it from local but we can use IIS to host these files.

Create new IIS site and put these 2 files (index.html, AFTree.html) to the website's folder. (Click Explorer)

Put 2 files.


Now we can see element relative ProcessBook display + Tree.


If I click Philly > PHI.Press03, it shows PHI.Press03 display.

IIS's windows authentication is required. Sometimes, IIS gets an error for connecting PI Web API. Annonymous works but if you want to use Kerberos, you need to cover security issues includes SPN etc...

(PI Web API's Kerberos authentication is required for running PI Web API Crawler correctly. This is a tricky part. If PI Web API Crawler does not work, PI Coresight could not show search results.)


For showing PI Coresight native display + Tree, we have Asset parameter.

PI Coresight 2016 R2 works fine by asset parameter. So you can use Native PI Coresight display + Tree by PI Coresight 2016 R2. (PI Coresight 2016 had an issue for asset parameter)


I have created Japanese version too.(日本語はこちら)

PI WebParts (PI TreeView + PI Graphic) の挙動をPI Coresight 2016 R2で再現させる方法

This post has been edited to be in compliance with OSIsoft Legal Policies. For questions on this, please send an email to


If you want to change the Help,


If you comment out following, it delete PI Live Library in Help.

{ id: 'HelpMenu', title: CS.Messages.HelpMenu, url: '' + lang + '/coresight-v7/GUID-7EF650C5-1235-4F8A-AC61-2EB1D2A3A5BF ' },


Or I recommend to delete this question itself if you don't need it.


Do you want that users are not possible to create a new display?

Delete div class="c-new-display" in %PIHOME64%\Coresight\Scripts\app\editor\layout\coresight.cs-header-directive.js

You can delete all of the followings.

<div class="c-new-display t-display-content-font">
            <div class="c-icon-display" ng-click="navCtrl.newDisplay()" title="{{::newDisplayTooltip}}">
                <div class="c-new-display-rollover">
                        <svg id="new-display-icon" class="t-icon-fill" version="1.1" x="0px" y="0px"
                             width="25px" height="25px" viewBox="0 -4 25 25" enable-background="new 0 0 25 25" xml:space="preserve">
                        <path d="M9.677,0.823c-5.12,0-9.271,4.188-9.271,9.354c0,5.169,4.151,9.356,9.271,9.356
                                    c5.119,0,9.271-4.188,9.271-9.356C18.948,5.012,14.796,0.823,9.677,0.823" />
                        <polygon fill="#091d3a" points="15.553,8.831 10.982,8.831 10.982,4.114 8.37,4.114 8.37,8.831 3.8,8.831 3.8,11.527 8.37,11.527
                                    8.37,16.243 10.982,16.243 10.982,11.527 15.553,11.527" />
                    <div class="t-font-color-white" style="text-decoration: none">{{::newDisplayLinkText}}</div>

Then all users could not see/press "New Display" link anymore.

However, you also could not press New Display button anymore.

In this case, luckily we can create new display by this URL.



Do you want to force "?mode=kiosk" to all users/all displays?

You can do it by comment out if sentence as following.


// if (parms.mode === 'kiosk')

If you do this, all users/ all displays can be seen as Kiosk mode.

We could not choose which users can see display without kiosk. So if you want to create/edit display, you need to change comments out again. (Found with Jerome Lefebvre)


PI Coresight 2016 Value object shows tool tip. I don't want to show it.


//valueLabel.path = data.Path;

If you comment out this, it doesn't show tool tip anymore.

By default, Value object's Multi-State changes background color.

I want to change font color. (Not background color)

In this case, change sym-value-template.html's "Fill ||" place.


<div  title="{{runtimeData.valueLabel.path.indexOf(':') === -1 ? runtimeData.valueLabel.path : runtimeData.valueLabel.path.split(':')[1]}}" style="white-space:nowrap;text-align:left;overflow:visible;" ng-style="{background: (config.Fill), 'font-size': fontSize}" ng-class="{'blink': Blink}">
    <div class="text-symbol-sizing-line" style="display:table" ng-show="config.ShowLabel">
        <span style="margin-right:2px" ng-style="{color:Fill ||config.Stroke}" ng-bind="runtimeData.valueLabel.displayName"></span>
    <div class="text-symbol-sizing-line" style="display:table">
        <span ng-style="{color:Fill ||config.ValueStroke}" ng-bind="value"></span>
        <span style="font-size:smaller;margin-left:1px;" ng-style="{color:Fill ||config.Stroke}" ng-bind="units" ng-show="config.ShowUOM"></span>
    <div class="text-symbol-sizing-line" style="display:table" ng-show="config.ShowTime">
        <span ng-style="{color:Fill ||config.Stroke}" ng-bind="time"></span>

So I could change font color instead of background color by Multi States.

For changing display's background color, I have checked the display object name by Chrome + F12.

t-display-container is the name of the class.


contains the t-display-container.

.t-display-container {
  background-color: white; }

I could see white background color.

PI Coresight 2016 can use custom symbols which is great feature.

GitHub - osisoft/PI-Coresight-Custom-Symbols: Learn how to add a custom symbol, created with JavaScript and HTML, to PI …

by default, it shows icon.

For this, you can take a screenshot of the objects and save it as png/jpg. (Need to change background color though. You can set "#48586b" color as back group color and take screenshot)

Put the image to %PIHOME64%\Coresight\Images folder.

Open the js fiile and put the IconURL.

var defintion = {
typeName: 'liquidgauge',
iconUrl: 'Images/liquid.png',

It shows the icon.

If you click the item, then you can realize that the image contains the background color.

Of cause it is good to create image without background color. Though in this way, it is easy to create the image by ms-paint.

Third party applications are also good options. For example:


I have not checked all items. But it seems like HTML5 works fine for changing a lot of things.

Please remember that those changes are not supported officially.


Worked with Jerome Lefebvre