public virtual IBFSample[] ApplyMontage(IBFSample[] samples, SignalFilter filter, int boardId, int numberOfChannels, int sampleRate) { var montagedSignal = new List <IBFSample>(); foreach (var nextSample in samples) { var newSample = new BFSampleImplementation(nextSample, NumberOfDerivations, 0, 0, 0); for (int i = 0; i < Derivations.Count; i++) { var result = 0.0; foreach (var nextChannel in Derivations[i].Channels) { result += nextSample.GetExgDataForChannel(nextChannel.RawChannelNumber) * nextChannel.Factor; } newSample.SetExgDataForChannel(i, result); } montagedSignal.Add(newSample); } samples = montagedSignal.ToArray(); if (filter != null) { samples = FilterBrainflowSample.FilterChunk(filter, samples, boardId, numberOfChannels, sampleRate); } return(samples); }
public void BlinkDetectorRisingAndFalling() { LeftCount = 0; RightCount = 0; BlinkDetector detector = new BlinkDetector(); detector.DetectedBlink += Detector_DetectedBlink; BFSampleImplementation data = new BFSampleImplementation(0) { TimeStamp = 1.00100, }; // this looks like rising edge detector.DetectBlinks(data, 31.0, 10.0, 31.0, 10.0); // no blinks on rising edge alone Assert.AreEqual(0, LeftCount); Assert.AreEqual(0, RightCount); data = new BFSampleImplementation(0) { TimeStamp = 1.25, }; // this looks like falling edge detector.DetectBlinks(data, 11.0, 10.0, 11.0, 10.0); // should be one blink Assert.AreEqual(1, LeftCount); Assert.AreEqual(1, RightCount); }
/// <summary> /// Process chunk read /// </summary> void ProcessChunk(double[,] buffer, int num) { for (int s = 0; s < num; s++) { IBFSample nextSample = new BFSampleImplementation(BoardId); nextSample.InitializeFromSample(buffer.GetRow(s)); RawDataReceived?.Invoke(this, new BFSampleEventArgs(nextSample)); LogRawDataProcessingPerformance(nextSample); } }
/// <summary> /// Calculate the median for each Exg channel using specified seconds worth of data /// </summary> IBFSample GenerateMedianReport(double seconds) { var medianReport = new BFSampleImplementation(BoardId); var data = GetUnfilteredData(seconds); for (int i = 0; i < NumberOfChannels; i++) { medianReport.SetExgDataForChannel(i, data.GetExgDataForChannel(i).Median()); } return(medianReport); }
// Public Methods #region PublicMethods /// <summary> /// Setup the band powers range lists /// </summary> public void InitializeMonitorForBandPowerRangeList() { BandPowers = new IBFSample[BandPowerCalc.NumberOfBands]; // create a dictionary for the results of the band power calculation // must match the number of frequency ranges list above BandPowersCollection = new ConcurrentDictionary <string, IBFSample>(); for (int j = 0; j < BandPowerCalc.NumberOfBands; j++) { BandPowers[j] = new BFSampleImplementation(BoardId); var key = (BandPowerCalc.BandPowerCalcRangeList[j].Item1 + (BandPowerCalc.BandPowerCalcRangeList[j].Item2 - BandPowerCalc.BandPowerCalcRangeList[j].Item1) / 2).BandPowerKey(); BandPowersCollection.TryAdd(key, BandPowers[j]); } }
/// <summary> /// Create samples from a single data record (chunk of signals per sample) /// </summary> void CreateSamples(double[,] chunk) { double dataRecordTime = StartTime.Value + (ReadDataRecordsCount * DataRecordDuration); for (int i = 0; i < chunk.GetRow(0).Length; i++) { IBFSample newSample = null; newSample = new BFSampleImplementation(BoardId); if (newSample != null) { newSample.InitializeFromSample(chunk.GetColumn(i)); newSample.TimeStamp = StartTime.Value + newSample.TimeStamp; _Samples.Add(newSample); } } }
/// <summary> /// Calculate band powers for the range list /// </summary> public IBFSample[] CalculateBandPowers(IEnumerable <IBFSample> samples) { var bandPowers = new IBFSample[BandPowerCalcRangeList.Count]; for (int i = 0; i < BandPowerCalcRangeList.Count; i++) { bandPowers[i] = new BFSampleImplementation(BoardId); } for (int i = 0; i < NumberOfChannels; i++) { var bandPower = CalculateBandPower(samples, SampleRate, i, BandPowerCalcRangeList); int j = 0; foreach (var nextBandPower in bandPower) { bandPowers[j++].SetExgDataForChannel(i, nextBandPower); } } return(bandPowers); }
/// <summary> /// Create a sample from a single line of ascii text /// </summary> IBFSample CreateSample(string nextLine) { IBFSample newSample = null; newSample = new BFSampleImplementation(BoardId); newSample.InitializeFromText(nextLine); // check the timestamp for valid data, this indicates we read a partial line for example the file is actively being written if (Math.Abs(newSample.TimeStamp - 0) < 0.0000001) { return(null); } // cache the start time of the first record if (!StartTime.HasValue) { StartTime = newSample.TimeStamp; } // cahce the end time EndTime = newSample.TimeStamp; return(newSample); }
/// <summary> /// Read data from the board, and return collection of data /// </summary> private List <IBFSample> ReadDataFromBoard() { var data = new List <IBFSample>(); try { Stopwatch sw = new Stopwatch(); sw.Start(); var rawData = TheBoard.get_board_data(); sw.Stop(); var timeReadData = sw.Elapsed.TotalSeconds; sw.Restart(); if (rawData.GetLength(1) == 0) { InvalidReadCounter++; } else { InvalidReadCounter = 0; if (rawData.GetLength(1) > 255) { return(data); // this is the first connection surge, flush these readings } //Log?.Invoke(this, new LogEventArgs(this, "ReadDataFromBoard", $"Read {rawData.Columns()}.", LogLevel.VERBOSE)); double oldestReadingTime, period; CalculateReadingPeriod(rawData, out oldestReadingTime, out period); for (int i = 0; i < rawData.GetLength(1); i++) { IBFSample nextSample = new BFSampleImplementation(BoardId); nextSample.InitializeFromSample(rawData.GetColumn(i)); nextSample.TimeStamp = oldestReadingTime + ((i + 1) * period); data.Add(nextSample); InspectSampleIndex(nextSample); } sw.Stop(); var timeParseData = sw.Elapsed.TotalSeconds; ReadCounter += data.Count; var since = (DateTimeOffset.UtcNow - LastReportTime); if (since.TotalMilliseconds > 5000) { Log?.Invoke(this, new LogEventArgs(this, "ReadDataFromBoard", $"Read {ReadCounter - ReadCounterLastReport} in {since.TotalSeconds.ToString("F3")} s. { (int)(((ReadCounter - ReadCounterLastReport) / since.TotalSeconds) + 0.5)} SPS. Read time {timeReadData.ToString("F4")} Parse Time {timeParseData.ToString("F4")}.", LogLevel.TRACE)); LastReportTime = DateTimeOffset.UtcNow; ReadCounterLastReport = ReadCounter; if (CountMissingIndex > 1) { Log?.Invoke(this, new LogEventArgs(this, "ReadDataFromBoard", $"Missed {CountMissingIndex} samples in the past {since.TotalSeconds.ToString("F3")} seconds.", LogLevel.WARN)); } CountMissingIndex = 0; } } } catch (Exception e) { Log?.Invoke(this, new LogEventArgs(this, "ReadDataFromBoard", e, LogLevel.ERROR)); } return(data); }