Skip to content

Commit

Permalink
Re-organize to blocks and cumulocity-blocks, add a DiscreateStatistic…
Browse files Browse the repository at this point in the history
…s sample + test
  • Loading branch information
Reed committed Jan 9, 2020
1 parent 70f355d commit 931c596
Show file tree
Hide file tree
Showing 5 changed files with 236 additions and 1 deletion.
126 changes: 126 additions & 0 deletions blocks/DiscreteStatistics.mon
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* $Copyright (c) 2020 Software AG, Darmstadt, Germany and/or Software AG USA Inc., Reston, VA, USA, and/or its subsidiaries and/or its affiliates and/or their licensors.$
* Use, reproduction, transfer, publication or disclosure is prohibited except as specifically provided for in your License Agreement with Software AG
*/

package apamax.analyticsbuilder.blocks;

using apama.analyticsbuilder.BlockBase;
using apama.analyticsbuilder.Activation;
using apama.analyticsbuilder.Value;
using apama.analyticsbuilder.TimerParams;
using com.apama.exceptions.Exception;
using apama.analyticsbuilder.L10N;
using apama.analyticsbuilder.Promise;


event DiscreteStatistics_$State {
float sum;
float sum_squared;
integer count;
float min;
float max;


action reset() {
sum := 0.0;
sum_squared := 0.0;
count := 0;
min := float.INFINITY;
max := -float.INFINITY;
}

action update(float value) {
sum := sum + value;
sum_squared := sum_squared + value * value;
count := count + 1;
min := float.min(min, value);
max := float.max(max, value);
}
}
/**
* Discrete Statistics
*
* Statistics for discrete measurements.
*
* Generates statistics - minimum, maximum, sum, count, mean and standard deviation for discrete time inputs.
*
* If the sample input is not connected, every re-evaluation will count, including when reset. If connected, block will
* only update when a signal on the sample input is received. A sample and reset can co-incide, in which case the block
* resets its state and then updates for the given value.
*
* @$blockCategory Aggregates
*/
event DiscreteStatistics {

BlockBase $base;



/**
* Calculates statistics.
* @param $activation The current activation.
* @param $input_value The input value.
* @param $input_sample A new sample is provided.
* @param $input_reset Reset the state of the block.
*/
action $process(Activation $activation, float $input_value, boolean $input_reset, boolean $input_sample, DiscreteStatistics_$State $blockState) {
if $blockState.count = 0 or $input_reset {
$blockState.reset();
}
if $base.getInputCount("sample") = 0 or $input_sample {
$blockState.update($input_value);
}
$setOutput_sum($activation, $blockState.sum);
$setOutput_count($activation, $blockState.count.toFloat());
$setOutput_min($activation, $blockState.min);
$setOutput_max($activation, $blockState.max);
float mean := $blockState.sum / $blockState.count.toFloat();
$setOutput_mean($activation, mean);
$setOutput_standardDeviation($activation, (($blockState.sum_squared / $blockState.count.toFloat()) - (mean * mean)).sqrt());
}

/**
* Sum
*
* Sum of the received input values.
*/
action<Activation,float> $setOutput_sum;
/**
* Count
*
* Count of the received input values.
*/
action<Activation,float> $setOutput_count;
/**
* Mean
*
* Mean of the received input values.
*/
action<Activation,float> $setOutput_mean;
/**
* Standard deviation
*
* Standard deviation of the received input values.
*/
action<Activation,float> $setOutput_standardDeviation;
/**
* Minimum
*
* Minimum of the received input values.
*/
action<Activation,float> $setOutput_min;
/**
* Maximum
*
* Maximum of the received input values.
*/
action<Activation,float> $setOutput_max;

/**Defines type for input reset.*/
constant string $INPUT_TYPE_reset := "pulse";

/**Defines type for input sample.*/
constant string $INPUT_TYPE_sample := "pulse";

}
2 changes: 1 addition & 1 deletion TimeTicker.mon → cumulocity-blocks/TimeTicker.mon
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Use, reproduction, transfer, publication or disclosure is prohibited except as specifically provided for in your License Agreement with Software AG
*/

package apama.analyticskit.blocks.cumulocity;
package apamax.analyticsbuilder.blocks;

using apama.analyticsbuilder.BlockBase;
using apama.analyticsbuilder.Activation;
Expand Down
33 changes: 33 additions & 0 deletions pysysproject.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<pysysproject>
<requires-pysys>1.3.0</requires-pysys>
<requires-python>3</requires-python>


<property name="ANALYTICS_BUILDER_SDK" value="${env.ANALYTICS_BUILDER_SDK}"/>


<property name="SOURCE" value="${root}"/>
<property root="testRootDir"/>
<property environment="env"/>
<property osfamily="osfamily"/>

<property name="APAMA_HOME" value="${env.APAMA_HOME}"/>
<property name="APAMA_WORK" value="${env.APAMA_WORK}"/>

<property name="defaultAbortOnError" value="true"/>
<property name="defaultIgnoreExitStatus" value="false"/>
<property name="defaultEnvironsTempDir" value="self.output"/>
<property name="redirectPrintToLogger" value="false"/>
<property name="verboseWaitForSignal" value="true"/>

<property name="shutdownApamaComponentsAfterTest" value="true"/>



<runner classname="ApamaRunner" module="apama.runner"/>

<path value="${ANALYTICS_BUILDER_SDK}/testframework"/>


</pysysproject>
27 changes: 27 additions & 0 deletions tests/DiscreteStatistics/pysystest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" standalone="yes"?>
<pysystest type="auto" state="runnable">

<description>
<title>Discrete stats: To check the basic working of the block</title>
<purpose><![CDATA[
To check discrete statistics.
]]>
</purpose>
</description>

<classification>
<groups>
<group></group>
</groups>
</classification>

<data>
<class name="PySysTest" module="run"/>
</data>

<traceability>
<requirements>
<requirement id=""/>
</requirements>
</traceability>
</pysystest>
49 changes: 49 additions & 0 deletions tests/DiscreteStatistics/run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#
# $Copyright (c) 2019 Software AG, Darmstadt, Germany and/or Software AG USA Inc., Reston, VA, USA, and/or its subsidiaries and/or its affiliates and/or their licensors.$
# This file is licensed under the Apache 2.0 license - see https://www.apache.org/licenses/LICENSE-2.0
#

from pysys.constants import *
from apamax.analyticsbuilder.basetest import AnalyticsBuilderBaseTest


class PySysTest(AnalyticsBuilderBaseTest):
def execute(self):
correlator = self.startAnalyticsBuilderCorrelator(
blockSourceDir=f'{self.project.SOURCE}/blocks/')
modelId = self.createTestModel('apamax.analyticsbuilder.blocks.DiscreteStatistics', inputs={'value':'float', 'sample':'pulse', 'reset':'pulse'})
self.sendEventStrings(correlator,
self.timestamp(.9),
self.inputEvent('value', 100, id=modelId),
self.inputEvent('sample', 'true', id=modelId, eplType = 'boolean'),
self.timestamp(1.9),
self.inputEvent('value', 110, id=modelId),
self.inputEvent('sample', 'true', id=modelId, eplType = 'boolean'),
self.timestamp(2.9),
self.inputEvent('value', 120, id=modelId),
self.inputEvent('sample', 'true', id=modelId, eplType = 'boolean'),
self.timestamp(3.9),
self.inputEvent('value', 30, id=modelId),
self.inputEvent('sample', 'true', id=modelId, eplType = 'boolean'),
self.inputEvent('reset', 'true', id=modelId, eplType = 'boolean'), # reset and sample at same time : sum = mean = value
self.timestamp(4.9),
self.inputEvent('reset', 'true', id=modelId, eplType = 'boolean'), # reset on its own : sum = count = 0 (mean and std dev are NaN!)
self.timestamp(6),
)

def validate(self):
self.assertGrep('output.evt', expr=self.outputExpr('sum', 100, time=1))
self.assertGrep('output.evt', expr=self.outputExpr('count', 1, time=1))
self.assertGrep('output.evt', expr=self.outputExpr('sum', 100, time=1))
self.assertGrep('output.evt', expr=self.outputExpr('sum', 210, time=2))
self.assertGrep('output.evt', expr=self.outputExpr('sum', 330, time=3))
self.assertGrep('output.evt', expr=self.outputExpr('min', 100, time=3))
self.assertGrep('output.evt', expr=self.outputExpr('max', time=3))
self.assertGrep('output.evt', expr=self.outputExpr('mean', 110, time=3))
self.assertGrep('output.evt', expr=self.outputExpr('standardDeviation', 8.164965809277223, time=3))
self.assertGrep('output.evt', expr=self.outputExpr('sum', 30, time=4))
self.assertGrep('output.evt', expr=self.outputExpr('count', 1, time=4))
self.assertGrep('output.evt', expr=self.outputExpr('mean', 30, time=4))
self.assertGrep('output.evt', expr=self.outputExpr('standardDeviation', 0, time=4))

self.assertGrep('output.evt', expr=self.outputExpr('sum', 0, time=5))

0 comments on commit 931c596

Please sign in to comment.