/// <summary>
        /// Run calculations for specific time stamps.
        /// </summary>
        /// inspired from:
        /// <see cref="https://pisquare.osisoft.com/message/28537#28537"/>
        /// <param name="analysis">Analysis that needs to be evaluated</param>
        /// <param name="times">List of times</param>
        /// <param name="evaluationTime">output, contains the time taken to execute all the calculations</param>
        /// <param name="evaluationsErrorsCount">output, contains the number of evaluations in error.</param>
        /// <returns></returns>
        public List <AFValue> Run(AFAnalysis analysis, IEnumerable <AFTime> times, out TimeSpan evaluationTime, out int evaluationsErrorsCount)
        {
            evaluationsErrorsCount = 0;
            var results   = new List <AFValue>();
            var stopwatch = Stopwatch.StartNew();


            var analysisConfiguration = analysis.AnalysisRule.GetConfiguration();
            var state = new AFAnalysisRuleState(analysisConfiguration);

            foreach (var time in times)
            {
                //  Console.WriteLine("Evaluating for {0}", time);
                state.Reset();
                state.SetExecutionTimeAndPopulateInputs(time);
                analysis.AnalysisRule.Run(state);

                if (state.EvaluationError != null)
                {
                    if (_debug)
                    {
                        _logger.ErrorFormat("Analyse in error at time: {3:s}  - {0} - at {1}, Error: {2}", analysis.Name, analysis.GetPath(), state.EvaluationError, time);
                    }

                    evaluationsErrorsCount += 1;
                }


                // this merges the state (results) with the configuration so its easier to loop with both...
                var resultSet = analysisConfiguration.ResolvedOutputs.Zip(state.Outputs, Tuple.Create);

                foreach (var result in resultSet)
                {
                    // for more clarty, we take out our data into clearer variables
                    AFAnalysisRuleResolvedOutput analysisRow = result.Item1;
                    var calcRes = (AFValue)result.Item2;

                    // we filter to get only the results that have an output attribute ( an AFValue )
                    if (analysisRow.Attribute != null)
                    {
                        // add new AF Value into the results table
                        results.Add(new AFValue((AFAttribute)analysisRow.Attribute, calcRes.Value,
                                                calcRes.Timestamp));
                    }
                }
            }

            stopwatch.Stop();
            evaluationTime = stopwatch.Elapsed;
            return(results);
        }
Esempio n. 2
0
        /// <summary>
        /// Adapted from Mike's example
        /// Mike also talks about errors and warnings in his post, you should check it.
        /// </summary>
        /// <see cref="https://pisquare.osisoft.com/message/28537#28537"/>
        /// <param name="analysis"></param>
        /// <param name="times"></param>
        /// <returns></returns>
        private static List <AFValue> Calculate(AFAnalysis analysis, IEnumerable <AFTime> times)
        {
            var results = new List <AFValue>();
            var analysisConfiguration = analysis.AnalysisRule.GetConfiguration();
            var state = new AFAnalysisRuleState(analysisConfiguration);

            foreach (var time in times)
            {
                //Console.WriteLine("Evaluating for {0}", time);
                state.Reset();
                state.SetExecutionTimeAndPopulateInputs(time);
                analysis.AnalysisRule.Run(state);
                if (state.EvaluationError == null)
                {
                    // this merges the state (results) with the configuration so its easier to loop with both...
                    var resultSet = analysisConfiguration.ResolvedOutputs.Zip(state.Outputs, Tuple.Create);


                    foreach (var result in resultSet)
                    {
                        // for more clarty, we take out our data into clearer variables
                        AFAnalysisRuleResolvedOutput analysisRow = result.Item1;
                        var calcRes = (AFValue)result.Item2;


                        // we filter to get only the results that have an output attribute ( an AFValue )
                        if (analysisRow.Attribute != null)
                        {
                            // add new AF Value into the results table
                            results.Add(new AFValue((AFAttribute)analysisRow.Attribute, calcRes.Value, calcRes.Timestamp));
                        }
                    }
                }
                else
                {
                    // errors occur quite frequently, for example, TagTot('attr1', 't', '*') will fail if computed at '*' = 't'
                    // but this does not occur when the analysis is running on event base.
                    //Console.WriteLine("An error occurred: {0}", state.EvaluationError.Message);
                }
            }

            return(results);
        }