Skip navigation
All Places > All Things PI - Ask, Discuss, Connect > PI Square中文论坛 > Blog > 2016 > September
2016

接上一篇有关AF analytics的最佳实践 - Part1

 

如何实现含有过滤条件的平均值(Average)、总值(Total)和汇总(Rollup)计算

关于这个内容有一篇KB文章 KB01120

下面这个例子中我们想要计算流量大于0(FlowRate > 0)时的流量的平均值(事件加权以及事件加权),仅靠TagAvg()和TagMean()函数不能实现这个功能。

m1.jpg

m2.jpgm3.jpg

要获得正确的时间加权平均,我们需要创建另外一个属性,比如叫做Filtered Flowrate,然后使用Formula 数据引用类型如下图所示:

m4.jpg

时间加权平均值的计算:使用TimeGT()函数来计算Flowrate属性在过去一天中大于0的时间。这个结果的单位是秒(s),因此我们还需要把它转化成为天(d),即PumpRunningInDays变量,接着TagTot()函数来计算Filtered Flowrate属性过去一天的总值。将两者得到的结果相除就得到Filtered Time weighted Average了。

m5.jpg

m6.jpg

事件加权平均值的计算:我们需要创建一个新的属性,在FlowRate > 0时,显示原来的值,当flowRate = 0时,显示NoOutput()

m7.jpg

接着对FilteredFlow这个属性使用TagMean()函数即可计算经过过滤以后的事件平均

m9.jpg

 

汇总计算:

同理,通过创建Filtered Production这样的属性可以对production属性的值进行过滤,并将这个值用在Rollup的计算中,即可得到过滤后的rollup的值

n1.jpg

n2.jpg

n3.jpg

n4.jpg

 

高级回填选项:

写入PI的时间戳可以是触发事件的未来时间

o1.jpg

 

如何在表达式中使用时间

这个例子中我们想要计算Volume1中的变化率,以及变化的持续时间

p1.jpg

其中st和et记录了Volume1属性的开始时间和结束时间,DateTime变量是两者之间的时间差,格式是dd:hh:mm:ss。这个结果用在ROC的计算中,并得到一个结果。DateTime变量已经被转换为秒(s),这样ROC的单位是(bbl/sec)。但当您想把这个结果映射到属性是会有下面这个错误

p2.jpg

但是,Raw Delta Time的数据类型是DateTime,没办法定义UOMs。

这里的trick是可以使用Float()函数,使用Float()可以将Delta Time变量改为double。接着可以使用Convert()函数给DeltaTimeInHours变量添加单位,然后进行rate of change(ROC)的计算。

p3.jpg

 

根据需求计算(结果不写入PI点)

AF Client (AFSDK)2.7开始,AF中多了一种新的数据引用类型,Analysis,该引用会记录表达式,但只有在客户端query的时候才会计算结果

q1.jpg

对于这种数据引用类型有如下一些内容需要考虑:

  • 计算是在AF客户端进行的
  • 计算频率是不是过于频繁?
  • 这个按需求计算是不是依赖于别的其他的按需求计算?
  • 在一个数据请求中有多少这样的计算?
  • 数据请求的间隔是多少?

以上这些因素都是影响性能的,所以这种数据引用类型应该被谨慎地使用

 

被限制使用的函数——这些函数可以被使用,但不支持summary data calls:

  • EventCount()
  • PctGood()
  • Range()
  • StDev()
  • TagAvg()
  • TagMax()
  • TagMean()
  • TagMin()
  • TagTot()

在下面这个例子中,我们计算Flow属性的5分钟平均值,并将结果映射到属性average flow。这个结果没有被映射到一个PI点,但我们仍然可以在一段时间内计算他们的值。请见下图:

 

 

q2.jpg

q3.jpg

q4.jpg

但如果您想将这个属性用于另外一个表达式的时候会得到下面这个报错,因为这个结果不能再被用于新的summary call函数中

q5.jpg

如果我们创建一个变量AvgFlowHist将计算结果映射到一个PI点中,AvgFlowHist可以被用于计算tagtot

q8.jpg

 

下列函数是不能在按需求计算中使用的,因为这些函数计算时比较消耗资源:

  • DeltaValue()
  • FindEq()
  • FindGE()
  • FindGT()
  • FindLE()
  • FindLT()
  • FindNE()
  • HasValueChanged()
  • NumOfChanges()
  • TimeEq()
  • TimeGE()
  • TimeGT()
  • TimeLE()
  • TimeLT()
  • TimeNE()
  • NoOutput()

q9.jpg

最近在pisquare上有同事发了有关AF Analytics的最佳实践的系列文章,以及一个文档(请见附件),全文比较长,下面挑选几个我认为比较重要或者新的内容介绍一下。

原文连接:

Tips and Tricks for Asset Based Analytics

Creating Analytics in Element Templates

Using Categories in Analytics

Make AF Analytics more readable - Break up your calculations

AF Analytics - Preview Results

AF Analytics - Bad and/or Stale Value Filters

AF Analytics - Pass parameters using Attributes

AF Analytics - NoOutput() Function

AF Analytics - Triggers for Event Frames and Notifications

AF Analytics - Units Of Measure (UOMs) in Equations

AF Analytics - Commenting your work

AF Analytics - Filtered calculations

AF Analytics - Advanced write back

AF Analytics - Working with date-time arithmetic

AF Analytics - On Demand calculations

AF Analytics - How to use Attributes from other Elements

 

如何避免个别Analysis在用模板创建的过程中自动启动

在AF 2.8之前,当我们check in对Analysis的修改之后,分析都会自动启动,而有时我们并不想这么做(可能只是想保存所做的修改)。

在AF 2.8或今后版本中,我们加入了一个新的功能,使得这个问题变得简单。您可以选择反选Start analyses when created from a template。这样,Analyses在被手动启动之前不会被启动。

A6.jpg

对于2.8或之前版本有一个tricky的方法,可以参考原文链接Creating Analytics in Element Templates

 

使用分组(Category)功能

将分析分组之后可以更方便的在Analyses plugin中进行管理,而且一个分析可以归属于多个组(category)。比如,下面这个例子中,我们有一个PI AF database,叫做Refinery,有许多Analyses,当我们用模板(Template)来分组时:

B1.jpg

但,如果我们想要backfill所有的Simulation的analyses,靠Analysis Template和Status(运行状态)来筛选就没有办法做到。如果有了合适的分组,就可以通过Category过滤来很方便的找到所有想要启动的分析

B2.jpg

 

让你的计算更有可读性和更容易理解 - 拆分您的计算:

1. 将您的计算分到多个变量中:

下面这个表达式就很长,很不易读

C1.jpg

可以把表达式分拆成多个变量,如下:

C2.jpg

2. 将您的表达式分到多个行中:

C3.jpg

可以通过Shift-Enter来把上面的表达式分行,使之更加可读

C5.jpg

C4.jpg

3. 使用变量来创建您的计算

C5.jpg

上面这个表达式有很多地方使用了重复的表达式(如下面P、T、Dens这三个变量),如果把这些表达式定义为变量,那会使得整个表达式更加可读

C6.jpg

 

预览结果

在启动、回填分析之前,最好都能够预览一下您的结果。只需要选择分析,并右键点击,选择Preview results即可。(注意:分析表达式必须没有syntax error,如果您是用模板创建分析,您需要选择一个样板元素-Example Element)

D1.jpgD2.jpg

在预览中,您将会看到触发的时间戳,所有变量的值(包括所有中间变量,这个例子中,PumpOn、PumpOff、Flowing、Status,而不仅仅是输出最终结果的Staus变量)。

D3.jpg

另外,和常识不同,预览并不需要签入(check in)分析,事实上,在创建分析的过程中频繁签入并不是十分高效的做法,而且每次签入之后,所有在运行的analyses将会重新启动。当看到预览结果之后,您还可以将结果导出到excel中,选择Export Results即可。

D4.jpg

 

坏的以及停滞不变的值

坏的值(Bad Value)和停滞的值可能导致计算失败,或者很多无意义的结果。在写表达式的时候可以通过一些方式来规避他们的影响。

E1.jpg

坏值:通过BadVal来过滤No Data,当BadGasFlow为真的时候,没有结果被写入FixedFlow属性(NoOutput())。

E2.jpg

停滞不变的值:

可以使用HasChanged()函数,使用这个函数的时候需要注意,否则会出现不正确的结果,下面这个例子中,属性Trigger在PI Archive中的值如下图所示,注意到它上一个归档值和前一个值相同,并且已经是在10分钟以前了

E4.jpg

我们现在用HasChanged()来写表达式,并预览,我们可注意到显然最后一个值(在8月3日12点57分53秒的值)显然应该为False

E5.jpg

这是因为这个属性Trigger是被用作触发的,每当这个表达式被出发,有一个新的值会在PI Archive中,所以这个表达式会返回True,尽管实际上这个值并没有改变。

E6.jpg

如果我们修改一下表达式,新加入一个属性,比如Pressure,我们可以用这个属性来触发。这时我们可以得到我们想要的结果。

E7.jpgE8.jpgE9.jpg

什么时候不要使用HasChanged()函数:如果想要用Trigger属性的变化来触发计算,HasChanged()不应该被使用。可以使用prevVal来替代。(尽管不是十分精确)

E11.jpg

 

让您的计算更具适用性,尽量使用属性来传递值,避免写死的数字。

传递时间参数:

F1.jpg

下面两个表达式,分别使用EndTime/OffSet和EndTime/StartTime来计算体积的平均值(您需要使用parseTime()函数,来将string型的原数据转换为时间的格式)

F2.jpg

写死的表达式不需要使用ParseTime()函数,但是灵活性不强。如下:

F3.jpg

传递控制限参数:

子属性最合适用在,关联的PI tag名字、控制限、说明等与父元素相关的地方。这里我们添加了最大值、最小值的子属性,并在计算中引用了这两个属性(Mass|Maximum, Mass|Minimum)。

F4a.jpgF5a.jpg

您也可以在右边Attributes导航栏中找到相应的元素,选择插入相对路径(Relative)

F6.png

 

NoOutput()函数的使用

有的时候NoOutput()可能不会给出期待的结果,参见 KB01127不过这个情况是有意为之的),但大多数时候,使用NoOutput()可以节省资源,如下面这个例子

 

 

G1.jpg

使用NoOutput()函数之后,大大减少了输出的结果,如果这个输出结果要用于新的分析的trigger condition并使用natural trigger,那使用NoOutput()函数之后可以大大减少检查触发条件的次数。

G2.jpg

 

给事件框架和报警创建相同的触发条件

从今年第四季度将会发布的PI AF 2.8.5开始,Notification将会成为Event frame的扩展,采用下面的方法可能就不是必须了。

下面的例子中,我们将在Pump开(On)、关(Off)时触发事件和报警。首先分别创建事件框架和报警的模板

 

H1.jpg

H2.jpg

H3.jpg

 

H4.jpg

创建Pump Status分析来记录Pump的on或者off状态发生切换时的值

H5.jpg

接下来创建事件框架分析来生成相应的事件。

H6.jpg

H7.jpg

 

在计算中指定单位(UOM)以保证获得正确的结果:

比如我们用体积(Vol)和密度(Den)计算质量,现在所有的单位都是匹配的,最终可以得到以磅(lb)为单位的质量

k1.jpg

k2.jpg

但如果我不小心将Mass属性的单位从磅(lb)改为了千克(kg),则我们会得到错误的结果

k3.jpg

但如果我们添加如下新的变量在表达式当中,并将这个新的结果map到Mass属性,则最终得到的结果会是正确的。

k5.jpg

关于UOM的行为, KB01366有更详细的说明

 

给分析添加注释

使用“//”来添加注释

l2.jpg

如果要添加多行注释,可以使用Shift-Enter换行,或者使用“/*”和“*/”

l3.jpg

l4.jpg

余下内容在Part2中继续