/// <summary> /// Default constructor /// </summary> /// <param name="startTime"></param> public PatternsEngineWrapper(DateTime startTime, string name) { this.Name = name; this.StartTime = startTime; this.CurrentTime = startTime; this.EngineWorkerHandle = new SafeNativeMethods.EngineCriticalHandle((IntPtr)0); // Trace and counters PatternsProcessorWrapper.Source.TraceEvent(TraceEventType.Verbose, 1200, "{0} instanciation at {1:s}", this, startTime); // Initialize performance counters PerformanceCounterHelper.InitializePerformanceCounters(); }
/// <summary> /// Add the given FHR & UP signal to the engine and detect the events & contractions /// </summary> /// <param name="hrs">FHR1 signal in 4Hz</param> /// <param name="ups">UP signal in 1Hz</param> /// <param name="startIndex">Index to start processing as per the 1Hz signal</param> /// <param name="length">Number of seconds of the buffer to process as per the 1Hz signal</param> /// <returns></returns> public IEnumerable <DetectedObject> Process(byte[] hrs, byte[] ups, int startIndex, int length) { try { var results = new List <DetectedObject>(); if (length <= 0) { return(results); } // Some validation if (hrs == null) { throw new ArgumentNullException("hrs"); } if (ups == null) { throw new ArgumentNullException("ups"); } // We want UP in 1Hz and HR in 4Hz and an equal number of seconds of UP and HR! if (hrs.GetLength(0) != 4 * ups.GetLength(0)) { throw new InvalidOperationException("Mismatch between FHR and UP signal lengths"); } if ((startIndex < 0) || (ups.GetLength(0) < startIndex + length)) { throw new InvalidOperationException("Out of bound parameters"); } lock (this.LockObject) { // Start the engine if necessary if (!this.IsEngineInitialized) { this.EngineWorkerHandle = SafeNativeMethods.EngineInitialize(); } // Make sure the engine was successfully started if (!this.IsEngineInitialized) { throw new InvalidOperationException("Unable to initialize the calculation engine"); } // Process the data AS IS int buffer_size = 0; // Simulate a limited seconds feed of 1 day of tracing at once maximum int time_frame = 86400; int position = startIndex; int end = startIndex + length; while (position < end) { int block_size = Math.Min(time_frame, end - position); buffer_size = SafeNativeMethods.EngineProcessUP(this.EngineWorkerHandle, ups, position, block_size); buffer_size = SafeNativeMethods.EngineProcessHR(this.EngineWorkerHandle, hrs, 4 * position, 4 * block_size); position += time_frame; } // Read the results if (buffer_size > 0) { var data = new StringBuilder(buffer_size); bool moreData = SafeNativeMethods.EngineReadResults(this.EngineWorkerHandle, data, buffer_size); Debug.Assert(!moreData); string[] lines = data.ToString().Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); foreach (string line in lines) { PatternsProcessorWrapper.Source.TraceEvent(TraceEventType.Error, 1299, "PAW debug: PatternsEngineWrapper::Process {0}", line); var artifact = line.ToDetectionArtifact(this.StartTime); if (artifact != null) { results.Add(artifact); } } } // Count Artifacts PerformanceCounterHelper.AddArtifactsFound(results.Count); // Count Seconds PerformanceCounterHelper.AddSecondsOfTracingProcessed(length); // Remember current time possition this.CurrentTime = this.CurrentTime.AddSeconds(length); return(results); } } catch (Exception ex) { PatternsProcessorWrapper.Source.TraceEvent(TraceEventType.Error, 1299, "{0} [Process Method]\n:{0}", ex); throw; } }