/// <summary> /// Adds the specified SimpleCurve to the SimpleMeasurement. /// </summary> /// <param name="simpleCurve">The SimpleCurve.</param> /// <param name="silent">if set to <c>true</c> [silent] the SimpleCurveAdded event is not raised.</param> /// <exception cref="System.ArgumentNullException">The specified SimpleCurve is null.</exception> /// <exception cref="System.ArgumentException">This measurement allready contains the specified SimpleCurve.</exception> public void AddSimpleCurve(SimpleCurve simpleCurve, bool silent = false) { if (simpleCurve == null) { throw new ArgumentNullException("The specified SimpleCurve is null."); } if (ContainsSimpleCurve(simpleCurve)) { throw new ArgumentException("This SimpleMeasurement allready contains the specified SimpleCurve."); } SimpleCurveCollection.Add(simpleCurve); //Add the SimpleCurve to this SimpleMeasurement. if (!Measurement.ContainsCurve(simpleCurve.Curve)) { if (!silent) { Measurement.AddCurve(simpleCurve.Curve); //Add the original Curve to the orginal Measurement. } else { Measurement.AddCurveSilent(simpleCurve.Curve); //Add the original Curve to the orginal Measurement without raising the curve added event. } } if (!silent) { OnSimpleCurveAdded(simpleCurve); } }
/// <summary> /// Multiplies the specified SimpleCurve with this SimpleCurve. /// </summary> /// <param name="multiply">The SimpleCurve to multiply by.</param> /// <returns> /// A new SimpleCurve with the result /// </returns> /// <exception cref="System.Exception"> /// Wait untill SimpleCurves are finished before multiplying /// or /// SimpleCurves must have the same number of data points /// </exception> public SimpleCurve Multiply(SimpleCurve multiply) { if (!IsFinished && !multiply.IsFinished) { throw new Exception("Wait untill SimpleCurves are finished before multiplying"); } if (NDataPoints != multiply.NDataPoints) { throw new Exception("SimpleCurves must have the same number of data points"); } return(Multiply(multiply, 0, NDataPoints)); }
/// <summary> /// Subtracts the specified SimpleCurve to this SimpleCurve. /// </summary> /// <param name="subtract">The SimpleCurve to subtract.</param> /// <returns> /// A new SimpleCurve with the result /// </returns> /// <exception cref="System.Exception"> /// Wait untill SimpleCurves are finished before subtracting /// or /// SimpleCurves must have the same number of data points /// </exception> public SimpleCurve Subtract(SimpleCurve subtract) { if (!IsFinished && !subtract.IsFinished) { throw new Exception("Wait untill SimpleCurves are finished before subtracting"); } if (NDataPoints != subtract.NDataPoints) { throw new Exception("SimpleCurves must have the same number of data points"); } return(Subtract(subtract, 0, NDataPoints)); }
/// <summary> /// Adds the specified SimpleCurve to this SimpleCurve. /// </summary> /// <param name="add">The SimpleCurve to add.</param> /// <returns>A new SimpleCurve with the result</returns> /// <exception cref="System.Exception"> /// Wait untill SimpleCurves are finished before adding /// or /// SimpleCurves must have the same number of data points /// </exception> public SimpleCurve Add(SimpleCurve add) { if (!IsFinished && !add.IsFinished) { throw new Exception("Wait untill SimpleCurves are finished before adding"); } if (NDataPoints != add.NDataPoints) { throw new Exception("SimpleCurves must have the same number of data points"); } return(Add(add, 0, NDataPoints)); }
/// <summary> /// Multiplies the specified SimpleCurve with this SimpleCurve starting from a specified index. /// </summary> /// <param name="multiply">The multiply.</param> /// <param name="from">The index to start multiplying by.</param> /// <returns> /// A new SimpleCurve with the result /// </returns> /// <exception cref="System.Exception"> /// Wait untill SimpleCurves are finished before multiplying /// or /// The index to start adding from exceeds the bounds of the SimpleCurves /// </exception> public SimpleCurve Multiply(SimpleCurve multiply, int from) { if (!IsFinished && !multiply.IsFinished) { throw new Exception("Wait untill SimpleCurves are finished before multiplying"); } if ((from > NDataPoints || from > multiply.NDataPoints) && from >= 0) { throw new Exception("The index to start adding from exceeds the bounds of the SimpleCurves"); } int count = (NDataPoints > multiply.NDataPoints) ? multiply.NDataPoints - from : NDataPoints - from; return(Multiply(multiply, from, count)); }
/// <summary> /// Subtracts the specified SimpleCurve from this SimpleCurve starting from a specified index. /// </summary> /// <param name="subtract">The SimpleCurve to subtract.</param> /// <param name="from">The index to start subtracting from.</param> /// <returns> /// A new SimpleCurve with the result /// </returns> /// <exception cref="System.Exception"> /// Wait untill SimpleCurves are finished before subtracting /// or /// The index to start adding from exceeds the bounds of the SimpleCurves /// </exception> public SimpleCurve Subtract(SimpleCurve subtract, int from) { if (!IsFinished && !subtract.IsFinished) { throw new Exception("Wait untill SimpleCurves are finished before subtracting"); } if ((from > NDataPoints || from > subtract.NDataPoints) && from > 0) { throw new Exception("The index to start adding from exceeds the bounds of the SimpleCurves"); } int count = (NDataPoints > subtract.NDataPoints) ? subtract.NDataPoints - from : NDataPoints - from; return(Subtract(subtract, from, count)); }
/// <summary> /// Adds the specified SimpleCurve to this SimpleCurve starting from a specified index. /// </summary> /// <param name="add">The SimpleCurve to add.</param> /// <param name="from">The index to start adding from.</param> /// <returns>A new SimpleCurve with the result</returns> /// <exception cref="System.Exception"> /// Wait untill SimpleCurves are finished before adding /// or /// The index to start adding from exceeds the bounds of the SimpleCurves /// </exception> public SimpleCurve Add(SimpleCurve add, int from) { if (!IsFinished && !add.IsFinished) { throw new Exception("Wait untill SimpleCurves are finished before adding"); } if ((from > NDataPoints || from > add.NDataPoints) && from >= 0) { throw new Exception("The index to start adding from exceeds the bounds of the SimpleCurves"); } int count = (NDataPoints > add.NDataPoints) ? add.NDataPoints - from : NDataPoints - from; return(Add(add, from, count)); }
/// <summary> /// Adds the active curve and its respective to the collection and subscribes to its events. /// </summary> /// <param name="activeCurve">The active curve.</param> private void OnSimpleCurveStartReceivingData(Curve activeCurve) { if (activeCurve == null) { return; } SimpleCurve activeSimpleCurve = _activeSimpleMeasurement.SimpleCurveCollection.Where(sc => sc.Curve == activeCurve).FirstOrDefault(); if (activeSimpleCurve == null) { activeSimpleCurve = new SimpleCurve(activeCurve, _activeSimpleMeasurement); _activeSimpleMeasurement.AddSimpleCurve(activeSimpleCurve); } SimpleCurveStartReceivingData?.Invoke(this, activeSimpleCurve); }
/// <summary> /// Removes the specified SimpleCurves from the SimpleMeasurement. /// </summary> /// <param name="simpleCurve">The simple curve.</param> /// <param name="silent">if set to <c>true</c> [silent] the SimpleCurveRemoved even is not raised.</param> /// <exception cref="System.ArgumentNullException">The specified SimpleCurve is null.</exception> /// <exception cref="System.ArgumentException">This SimpleMeasurement does not contain the specified SimpleCurve</exception> public void RemoveSimpleCurve(SimpleCurve simpleCurve, bool silent = false) { if (simpleCurve == null) { throw new ArgumentNullException("The specified SimpleCurve is null."); } if (!ContainsSimpleCurve(simpleCurve)) { throw new ArgumentException("This SimpleMeasurement does not contain the specified SimpleCurve"); } Measurement.RemoveCurve(simpleCurve.Curve); //Removes the original curve from the original measurement SimpleCurveCollection.Remove(simpleCurve); //Removes the SimpleCurve from the SimpleMeasurement if (!silent) { OnSimpleCurveRemoved(simpleCurve); } }
/// <summary> /// Multiplies the specified SimpleCurve with this SimpleCurve over a specified range. /// </summary> /// <param name="multiply">The multiply.</param> /// <param name="from">The index to start multiplying by.</param> /// <returns> /// <param name="count">The number of datapoints in the range.</param> /// <returns> /// A new SimpleCurve with the result /// </returns> /// <exception cref="System.Exception"> /// Wait untill SimpleCurves are finished before multiplying /// or /// The range to add exceeds the bounds of the SimpleCurves /// </exception> public SimpleCurve Multiply(SimpleCurve multiply, int from, int count) { if (!IsFinished && !multiply.IsFinished) { throw new Exception("Wait untill SimpleCurves are finished before multiplying"); } if ((from + count > NDataPoints || from + count > multiply.NDataPoints) && from >= 0) { throw new Exception("The range to add exceeds the bounds of the SimpleCurves"); } //Create a copy of the Y Axis data to prevent the raw measurement data from being overwritten DataArray newArray = Curve.YAxisDataArray.Clone(true); for (int i = from; i < from + count; i++) { newArray[i].Value *= multiply.Curve.YAxisDataArray[i].Value; } Curve newCurve = new Curve(Curve.XAxisDataArray, newArray, $"{Title}, * {multiply.Title}"); newCurve.Finish(); return(new SimpleCurve(newCurve, _simpleMeasurement)); }
//Simple connection to the palmsens, currently the only one used public async void SimpleConnect(int fileNum, bool RunningPC, bool RunningNC, bool RunningReal, bool RunningDPV) { bool RunningBL = true; string testRun = "5"; //Below sets which option the code will execute SimpleMeasurement baseline; AssetManager assetManager = Application.Context.Assets; using (StreamReader sr = new StreamReader(assetManager.Open(testRun + "_2525AfterMch" + fileNum + ".pssession"))) //Loads a blank baseline curve to subtract from the scanned/loaded curve baseline = SimpleLoadSaveFunctions.LoadMeasurements(sr)[0]; baselineCurves = baseline.SimpleCurveCollection; //Runs a real scan depending on whatever parameters the person has set if (RunningReal) { Context context = Application.Context; //Loads the current android context IAttributeSet attributeSet = null; psCommSimpleAndroid = new PSCommSimpleAndroid(context, attributeSet); //Uses a simple comm with the palmsens Device[] devices = await psCommSimpleAndroid.GetConnectedDevices(); try { await psCommSimpleAndroid.Connect(devices[0]); //Connect to the first palmsens found } catch (Exception ex) { Crashes.TrackError(ex); } psCommSimpleAndroid.MeasurementStarted += PsCommSimpleAndroid_MeasurementStarted; //Loads the necessary flags psCommSimpleAndroid.MeasurementEnded += PsCommSimpleAndroid_MeasurementEnded; psCommSimpleAndroid.SimpleCurveStartReceivingData += PsCommSimpleAndroid_SimpleCurveStartReceivingData; Method runScan = await RunScan(); //Sets the scan parameters activeSimpleMeasurement = await psCommSimpleAndroid.Measure(runScan); //Runs the scan on the potentiostat psCommSimpleAndroid.Wait(11000); psCommSimpleAndroid.Dispose(); List <ScanDatabase> allDb = await App.Database.GetScanDatabasesAsync(); //Loads the current database //Add in processing stuff here SimpleLoadSaveFunctions.SaveMeasurement(activeSimpleMeasurement, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "dpv" + allDb.Count + ".pssession")); //FileHack instance = new FileHack(); //activeSimpleMeasurement = instance.HackDPV(activeSimpleMeasurement); List <SimpleCurve> simpleCurves = activeSimpleMeasurement.NewSimpleCurve(DataArrayType.Current, DataArrayType.Potential); SimpleCurve subtractedCurve = simpleCurves[0].Subtract(baselineCurves[0]); //Note, replace simpleCurves[1] w/ the standard blank curve SimpleCurve movingAverageBaseline = subtractedCurve.MovingAverageBaseline(); //Subtracts the baseline from the subtracted curve SimpleCurve baselineCurve = subtractedCurve.Subtract(movingAverageBaseline); subtractedCurve.Dispose(); //Disposes of the subtracted curve SimpleCurve smoothedCurve = baselineCurve.Smooth(SmoothLevel.VeryHigh); smoothedCurve.DetectPeaks(0.1, 0, true, false, false); double peakLocation = smoothedCurve.Peaks[smoothedCurve.Peaks.nPeaks - 1].PeakX; double peakHeight = smoothedCurve.Peaks[smoothedCurve.Peaks.nPeaks - 1].PeakValue; ScanDatabase _database = await App.Database.GetScanAsync(allDb.Count); if (peakLocation <= -0.3 && peakLocation >= -0.4) //If the peak is between a certain range, the sample is infected, add in a minimum value once one is determined { _database.IsInfected = true; } else { _database.IsInfected = false; } _database.PeakVoltage = peakHeight; await App.Database.SaveScanAsync(_database); //Saves the current database subtractedCurve.Dispose(); baselineCurve.Dispose(); //Disposes of the baseline curve smoothedCurve.Dispose(); } //Runs a differential pulse voltammetric scan for testing else if (RunningDPV) { using (StreamReader sr = new StreamReader(assetManager.Open("blank.pssession"))) //Loads a blank curve as a baseline to be subtracted baseline = SimpleLoadSaveFunctions.LoadMeasurements(sr)[0]; Context context = Application.Context; //Loads the current android context IAttributeSet attributeSet = null; psCommSimpleAndroid = new PSCommSimpleAndroid(context, attributeSet); //Initializes the palmsens comm Device[] devices = await psCommSimpleAndroid.GetConnectedDevices(); try { await psCommSimpleAndroid.Connect(devices[0]); //Connects to the first palmsens found } catch (Exception ex) { psCommSimpleAndroid.Dispose(); Crashes.TrackError(ex); return; } psCommSimpleAndroid.MeasurementStarted += PsCommSimpleAndroid_MeasurementStarted; //Loads the necessary flags psCommSimpleAndroid.MeasurementEnded += PsCommSimpleAndroid_MeasurementEnded; psCommSimpleAndroid.SimpleCurveStartReceivingData += PsCommSimpleAndroid_SimpleCurveStartReceivingData; Method runScan = await RunScan(); //Sets the scan parameters activeSimpleMeasurement = await psCommSimpleAndroid.Measure(runScan); //Runs the scan on the potentiostat Thread.Sleep(50000); psCommSimpleAndroid.Dispose(); //Disposes of the comm when it is done being used List <ScanDatabase> allDb = await App.Database.GetScanDatabasesAsync(); //Loads the current database //Add in processing stuff here SimpleLoadSaveFunctions.SaveMeasurement(activeSimpleMeasurement, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "dpv" + allDb.Count + ".pssession")); //FileHack instance = new FileHack(); //activeSimpleMeasurement = instance.HackDPV(activeSimpleMeasurement); List <SimpleCurve> simpleCurves = activeSimpleMeasurement.NewSimpleCurve(DataArrayType.Current, DataArrayType.Potential); //SimpleCurve subtractedCurve = simpleCurves[0].Subtract(baselineCurves[0]); //Note, replace simpleCurves[1] w/ the standard blank curve SimpleCurve movingAverageBaseline = simpleCurves[0].MovingAverageBaseline(); //Subtracts the baseline from the subtracted curve SimpleCurve baselineCurve = simpleCurves[0].Subtract(movingAverageBaseline); //subtractedCurve.Dispose(); //Disposes of the subtracted curve SimpleCurve smoothedCurve = baselineCurve.Smooth(SmoothLevel.VeryHigh); smoothedCurve.DetectPeaks(0.1, 0, true, false, false); PeakList peakList = smoothedCurve.Peaks; //Detects the peaks on the subtracted curve baselineCurve.Dispose(); //Disposes of the baseline curve smoothedCurve.Dispose(); Peak mainPeak = peakList[peakList.nPeaks - 1]; //Note, the proper peak is the last peak, not the first peak double peakLocation = mainPeak.PeakX; double peakHeight = mainPeak.PeakValue; ScanDatabase _database = await App.Database.GetScanAsync(allDb.Count); if (peakLocation <= -0.3 && peakLocation >= -0.4) //If the peak is between a certain range, the sample is infected, add in a minimum value once one is determined { _database.IsInfected = true; } else { _database.IsInfected = false; } _database.PeakVoltage = peakHeight; await App.Database.SaveScanAsync(_database); //Saves the current database } else if (RunningNC || RunningPC || RunningBL) //If a test scan is being run { if (RunningBL) //If a simple baseline test is run with no subtraction or curve manipulation { SimpleMeasurement baselineMeasurement; using (StreamReader sr = new StreamReader(assetManager.Open(testRun + "_baselineOnly" + fileNum + ".pssession"))) baselineMeasurement = SimpleLoadSaveFunctions.LoadMeasurements(sr)[0]; List <SimpleCurve> avgBaselineCurves = baselineMeasurement.SimpleCurveCollection; SimpleCurve avgBaselineCurve = avgBaselineCurves[0]; avgBaselineCurve.DetectPeaks(0.05, 0, true, false); //Detect peaks only if they are wider than 0.05 V PeakList avgBaselinePeakList = avgBaselineCurve.Peaks; if (avgBaselinePeakList.nPeaks != 0) //If it detects a peak run below code { Peak avgBaselinePeak = avgBaselinePeakList[avgBaselinePeakList.nPeaks - 1]; //Use the last peak detected which should be the wanted peak double avgBaselinePeakLocation = avgBaselinePeak.PeakX; double avgBaselinePeakValue = avgBaselinePeak.PeakValue; List <ScanDatabase> allDb = await App.Database.GetScanDatabasesAsync(); ScanDatabase _database = await App.Database.GetScanAsync(allDb.Count); if (avgBaselinePeakLocation <= -0.3 && avgBaselinePeakLocation >= -0.4) //If a peak is between a certain range, the sample is infected, add in a minimal value once determined { _database.IsInfected = true; } else { _database.IsInfected = false; } _database.PeakVoltage = avgBaselinePeakValue; await App.Database.SaveScanAsync(_database); } else //If no peak is detected { List <ScanDatabase> allDb = await App.Database.GetScanDatabasesAsync(); ScanDatabase _database = await App.Database.GetScanAsync(allDb.Count); _database.IsInfected = false; _database.PeakVoltage = 0.0; _database.VoltamType = "Failed PC"; await App.Database.SaveScanAsync(_database); } } else if (RunningPC) //If a postitive control test is being run with known values { SimpleMeasurement positiveControl; using (StreamReader sr = new StreamReader(assetManager.Open(testRun + "_2525AfterTarget" + fileNum + ".pssession"))) positiveControl = SimpleLoadSaveFunctions.LoadMeasurements(sr)[0]; List <SimpleCurve> positiveCurves = positiveControl.SimpleCurveCollection; SimpleCurve baselineCurve; SimpleCurve subtractedCurve = positiveCurves[0].Subtract(baselineCurves[0]); baselineCurve = subtractedCurve.MovingAverageBaseline(); subtractedCurve.Dispose(); baselineCurve.DetectPeaks(0.05, 0, true, false); //Detect all peaks with width greater than 0.05 V PeakList positivePeakList = baselineCurve.Peaks; baselineCurve.Dispose(); if (positivePeakList.nPeaks != 0) //If a peak is detected, execute the code below { Peak positivePeak = positivePeakList[positivePeakList.nPeaks - 1]; double positivePeakLocation = positivePeak.PeakX; double positivePeakValue = positivePeak.PeakValue; List <ScanDatabase> allDb = await App.Database.GetScanDatabasesAsync(); ScanDatabase _database = await App.Database.GetScanAsync(allDb.Count); if (positivePeakLocation <= -0.3 && positivePeakLocation >= -0.4) //If a peak is between a certain range, the sample is infected, add in minimum value once determined { _database.IsInfected = true; } else { _database.IsInfected = false; } _database.PeakVoltage = positivePeakValue; await App.Database.SaveScanAsync(_database); } else //If no peak is detected, execute the code below { List <ScanDatabase> allDb = await App.Database.GetScanDatabasesAsync(); ScanDatabase _database = await App.Database.GetScanAsync(allDb.Count); _database.IsInfected = false; _database.PeakVoltage = 0.0; _database.VoltamType = "Failed PC"; await App.Database.SaveScanAsync(_database); } } else if (RunningNC) //If a negative control test is being run { SimpleMeasurement negativeControl; using (StreamReader sr = new StreamReader(assetManager.Open(testRun + "_2525AfterMch" + fileNum + ".pssession"))) negativeControl = SimpleLoadSaveFunctions.LoadMeasurements(sr)[0]; List <SimpleCurve> negativeCurves = negativeControl.SimpleCurveCollection; SimpleCurve baselineCurve; SimpleCurve subtractedCurve = negativeCurves[0].Subtract(baselineCurves[0]); baselineCurve = subtractedCurve.MovingAverageBaseline(); subtractedCurve.Dispose(); baselineCurve.DetectPeaks(0.05, 0, true, false); //Detect all peaks with a width greater than 0.05 V PeakList negativePeakList = baselineCurve.Peaks; baselineCurve.Dispose(); if (negativePeakList.nPeaks != 0) //If a peak is detected, execute the code below { Peak negativePeak = negativePeakList[negativePeakList.nPeaks - 1]; double negativePeakLocation = negativePeak.PeakX; double negativePeakValue = negativePeak.PeakValue; List <ScanDatabase> allDb = await App.Database.GetScanDatabasesAsync(); ScanDatabase _database = await App.Database.GetScanAsync(allDb.Count); if (negativePeakLocation <= -0.3 && negativePeakLocation >= -0.4) //If a peak is in a certain range, the sample is infected, add a minimum value once determined { _database.IsInfected = true; } else { _database.IsInfected = false; } _database.PeakVoltage = negativePeakValue; await App.Database.SaveScanAsync(_database); } else //If a peak is not detected { List <ScanDatabase> allDb = await App.Database.GetScanDatabasesAsync(); ScanDatabase _database = await App.Database.GetScanAsync(allDb.Count); _database.IsInfected = false; _database.PeakVoltage = 0.0; _database.VoltamType = "Failed NC"; await App.Database.SaveScanAsync(_database); } } } }
//Notifies when a curve starts to receive data protected virtual void PsCommSimpleAndroid_SimpleCurveStartReceivingData(object sender, SimpleCurve activeSimpleCurve) { _activeSimpleCurve = activeSimpleCurve; _activeSimpleCurve.NewDataAdded += _activeSimpleCurve_NewDataAdded; _activeSimpleCurve.CurveFinished += _activeSimpleCurve_CurveFinished; }
/// <summary> /// Called when a [SimpleCurve] has been removed. /// </summary> /// <param name="simpleCurve">The simple curve.</param> private void OnSimpleCurveRemoved(SimpleCurve simpleCurve) { SimpleCurveRemoved?.Invoke(this, simpleCurve); }
/// <summary> /// Determines whether this SimpleMeasurement contains [the specified simple curve]. /// </summary> /// <param name="simpleCurve">The simple curve.</param> /// <returns> /// <c>true</c> if the measurement contains [the specified simple curve]; otherwise, <c>false</c>. /// </returns> public bool ContainsSimpleCurve(SimpleCurve simpleCurve) { return(SimpleCurveCollection.Contains(simpleCurve)); }