/// <summary> /// Set the structure bounds around the brightest structure in the image. /// The 1D projected image of the green channel is used. /// Boundaries are placed where intensity drops to half the distance between the peak and the noise floor. /// Noise floor is defined as the 20-percentile of the 1D projected image. /// </summary> public void AutoStructure() { // determine the brightest column double[] columnIntensities = ImageDataTools.GetAverageLeftright(imgG); double brightestValue = 0; int brightestIndex = 0; for (int i = 0; i < columnIntensities.Length; i++) { if (columnIntensities[i] > brightestValue) { brightestValue = columnIntensities[i]; brightestIndex = i; } } Log($"Brightest structure (G): {brightestValue} AFU at {brightestIndex}px"); // determine the 20-percentile brightness (background fluorescence) double[] sortedIntensities = new double[columnIntensities.Length]; Array.Copy(columnIntensities, sortedIntensities, columnIntensities.Length); Array.Sort(sortedIntensities); double noiseFloor = sortedIntensities[(int)(sortedIntensities.Length * .2)]; Log($"Noise floor (G): {noiseFloor} AFU"); // intensity cut-off is half-way to the noise floor double peakAboveNoise = brightestValue - noiseFloor; double cutOff = (peakAboveNoise * .5) + noiseFloor; Log($"Cut-off (G): {cutOff} AFU"); // start both structures at the brighest point, then walk away structure1 = brightestIndex; structure2 = brightestIndex; while (columnIntensities[structure1] > cutOff && structure1 > 0) { structure1--; } while (columnIntensities[structure2] > cutOff && structure2 < columnIntensities.Length - 1) { structure2++; } Log($"Automatic structure: {structure1}px - {structure2}px"); }
public void UpdateGraphs(bool skipUpdatesIfBusy = true) { // use pretty colors Color blue = System.Drawing.ColorTranslator.FromHtml("#1f77b4"); Color lightBlue = System.Drawing.ColorTranslator.FromHtml("#a2d1f2"); Color red = System.Drawing.ColorTranslator.FromHtml("#d62728"); Color lightRed = System.Drawing.ColorTranslator.FromHtml("#e63738"); Color green = System.Drawing.ColorTranslator.FromHtml("#2ca02c"); Color lightGreen = System.Drawing.ColorTranslator.FromHtml("#98df8a"); Color colorBaselineMarks = System.Drawing.ColorTranslator.FromHtml("#666666"); Color colorPeak = System.Drawing.ColorTranslator.FromHtml("#d62728"); Color colorZero = System.Drawing.ColorTranslator.FromHtml("#000000"); if (!lsFolder.isValid) { return; } if (skipUpdatesIfBusy && busyUpdating) { return; } else { busyUpdating = true; } // do the analysis lsFolder.GenerateAnalysisCurves(); // update the structure profile plot double[] columnPixelIndices = new double[lsFolder.imgG.width]; for (int i = 0; i < columnPixelIndices.Length; i++) { columnPixelIndices[i] = i; } formsPlot2.plt.Clear(); if ((cbR.Enabled && cbR.Checked)) { double[] columnBrightnessR = ImageDataTools.GetAverageLeftright(lsFolder.imgR); formsPlot2.plt.PlotScatter(columnPixelIndices, columnBrightnessR, markerSize: 0, color: red); } if ((cbG.Enabled && cbG.Checked)) { double[] columnBrightnessG = ImageDataTools.GetAverageLeftright(lsFolder.imgG); formsPlot2.plt.PlotScatter(columnPixelIndices, columnBrightnessG, markerSize: 0, color: green); } formsPlot2.plt.AxisAuto(0, .1); formsPlot2.plt.PlotVLine(lsFolder.structure1, color: Color.Black); formsPlot2.plt.PlotVLine(lsFolder.structure2, color: Color.Black); // update styling before the render formsPlot2.plt.YLabel("Intensity"); formsPlot2.plt.XLabel("Position (pixel number)"); formsPlot2.Render(); // update the time series plot curveToCopy = null; formsPlot1.plt.Clear(); if (cbRatio.Checked && cbRatio.Enabled) { if (cbDelta.Enabled && cbDelta.Checked) { curveToCopy = lsFolder.GetFilteredYs(lsFolder.curveDeltaGoR); formsPlot1.plt.PlotScatter(lsFolder.timesMsec, lsFolder.curveDeltaGoR, color: lightBlue, lineWidth: 0, markerSize: 2); formsPlot1.plt.PlotScatter(lsFolder.GetFilteredXs(), curveToCopy, markerSize: 0, color: blue, lineWidth: 2); formsPlot1.plt.PlotVLine(lsFolder.baseline1 * lsFolder.scanLinePeriod, color: colorBaselineMarks, lineWidth: 2); formsPlot1.plt.PlotVLine(lsFolder.baseline2 * lsFolder.scanLinePeriod, color: colorBaselineMarks, lineWidth: 2); formsPlot1.plt.PlotHLine(0, color: colorZero, lineWidth: 2); formsPlot1.plt.PlotHLine(curveToCopy.Max(), color: colorPeak, lineWidth: 2); formsPlot1.plt.YLabel("Delta G/R (%)"); } else { curveToCopy = lsFolder.GetFilteredYs(lsFolder.curveGoR); formsPlot1.plt.PlotScatter(lsFolder.timesMsec, lsFolder.curveGoR, color: lightBlue, lineWidth: 0, markerSize: 2); formsPlot1.plt.PlotScatter(lsFolder.GetFilteredXs(), curveToCopy, markerSize: 0, color: blue, lineWidth: 2); formsPlot1.plt.YLabel("G/R (%)"); formsPlot1.plt.PlotHLine(curveToCopy.Max(), color: colorPeak, lineWidth: 2); } } else if ((cbR.Checked && cbR.Enabled) && (cbG.Checked && cbG.Enabled)) { formsPlot1.plt.PlotScatter(lsFolder.timesMsec, lsFolder.curveG, markerSize: 0, color: green); formsPlot1.plt.PlotScatter(lsFolder.timesMsec, lsFolder.curveR, markerSize: 0, color: red); formsPlot1.plt.YLabel("G and R (AFU)"); } else if (cbR.Checked && cbR.Enabled) { formsPlot1.plt.PlotScatter(lsFolder.timesMsec, lsFolder.curveR, markerSize: 0, color: red); formsPlot1.plt.YLabel("R (AFU)"); } else if (cbG.Checked && cbG.Enabled) { if (cbDelta.Enabled && cbDelta.Checked) { curveToCopy = lsFolder.GetFilteredYs(lsFolder.curveDeltaG); formsPlot1.plt.PlotScatter(lsFolder.timesMsec, lsFolder.curveDeltaG, lineWidth: 0, color: lightGreen, markerSize: 2); formsPlot1.plt.PlotScatter(lsFolder.GetFilteredXs(), curveToCopy, markerSize: 0, color: green, lineWidth: 2); formsPlot1.plt.PlotVLine(lsFolder.baseline1 * lsFolder.scanLinePeriod, color: colorBaselineMarks, lineWidth: 2); formsPlot1.plt.PlotVLine(lsFolder.baseline2 * lsFolder.scanLinePeriod, color: colorBaselineMarks, lineWidth: 2); formsPlot1.plt.PlotHLine(0, color: colorZero, lineWidth: 2); formsPlot1.plt.PlotHLine(curveToCopy.Max(), color: colorPeak, lineWidth: 2); formsPlot1.plt.YLabel("Delta G (%)"); } else { curveToCopy = lsFolder.GetFilteredYs(lsFolder.curveG); formsPlot1.plt.PlotScatter(lsFolder.timesMsec, lsFolder.curveG, lineWidth: 0, color: lightGreen, markerSize: 2); formsPlot1.plt.PlotScatter(lsFolder.GetFilteredXs(), curveToCopy, markerSize: 0, color: green, lineWidth: 2); formsPlot1.plt.PlotHLine(curveToCopy.Max(), color: colorPeak, lineWidth: 2); formsPlot1.plt.YLabel("G (AFU)"); } } formsPlot1.plt.AxisAuto(.05, .1); // make ticks smaller than typical var tickFont = new Font(FontFamily.GenericMonospace, (float)10.0); //formsPlot1.plt.Ticks(font: tickFont); //formsPlot2.plt.Ticks(font: tickFont); // update styling before the render formsPlot1.plt.XLabel("Time (milliseconds)"); formsPlot1.Render(); // update peak label if (curveToCopy == null) { lblPeak.Text = $""; } else { lblPeak.Text = $"{Math.Round(curveToCopy.Max(), 2)}%"; } Application.DoEvents(); busyUpdating = false; }