Ejemplo n.º 1
0
            /// <summary>
            /// Find inflection point by finding the nearest maximum and fit parabola to it.
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="c"></param>
            /// <returns></returns>
            public static double ZeroCrossingLeftInflection(double[] x, double[] y, CrudeZeroCrossing c)
            {
                double[] xs = NP.Slice(x, c.FirstTrigger, c.LastTrigger);
                double[] ys = NP.Slice(y, c.FirstTrigger, c.LastTrigger);
                int argmax = NP.Argmax(ys);
                NP.PrintArray(xs);
                NP.PrintArray(ys);
                NP.ParabolicFitResult result = NP.ParabolicFit(xs, ys);

                return (-result.b / (2.0 * result.a));
            }
Ejemplo n.º 2
0
 /// <summary>
 /// Find left inflection with out fitting parabola
 /// </summary>
 /// <param name="x"></param>
 /// <param name="y"></param>
 /// <param name="c"></param>
 /// <returns></returns>
 public static double FastZeroCrossingLeftInflection(double[] x, double[] y, CrudeZeroCrossing c)
 {
     //this assumes that ys is smooth
     double[] xs = NP.Slice(x, c.FirstTrigger, c.LastTrigger);
     double[] ys = NP.Slice(y, c.FirstTrigger, c.LastTrigger);
     int argmax = NP.Argmax(ys);
     Console.WriteLine("Argmax {0}", argmax);
     return xs[argmax];
 }
Ejemplo n.º 3
0
            //public static ZeroCrossingSlopeResult CrossingSlope(double[] x, double[] y, CrudeZeroCrossing c, int width = 30)
            //{
            //    double[] xs = NP.Slice(x, c.Crossing - width, c.Crossing + width);
            //    double[] ys = NP.Slice(y, c.Crossing - width, c.Crossing + width);
            //    NP.LinearFitResult result = NP.LinearFit(xs, ys);
            //    double bw = (x[c.Crossing + width] - x[c.Crossing - width]) / (2 * width);
            //    ZeroCrossingSlopeResult ret = new ZeroCrossingSlopeResult(result.m, result.c, bw);
            //    return ret;
            //}
            /// <summary>
            /// Perform linear fit to x and y around c.Crossing+-width
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="c"></param>
            /// <param name="width"></param>
            /// <returns></returns>
            public static ZeroCrossingSlopeResult CrossingSlope(double[] x, double[] y, CrudeZeroCrossing c, int width = 10)
            {
                //we do want the right hand side to be inclusive
                double[] xs = NP.Slice(x, c.Crossing - width, c.Crossing + width + 1);
                double[] ys = NP.Slice(y, c.Crossing - width, c.Crossing + width + 1);

                NP.LinearFitResult linr = NP.LinearFit(xs, ys);
                //parabolic fit doesn't help since it's symmetric
                //NP.ParabolicFitResult parar = NP.ParabolicFit(xs, ys); //improve slope with intercept
                double cc = linr.c;
                double xintercept = -linr.c / linr.m;
                double mm = linr.m;
                double bw = (xs[xs.Length - 1] - xs[0]) / (xs.Length - 1);
                //double mm = 2 * parar.a * xintercept + parar.b; //improved slope
                ZeroCrossingSlopeResult ret = new ZeroCrossingSlopeResult(mm, cc, xintercept, bw);
                return ret;
            }
Ejemplo n.º 4
0
            /// <summary>
            /// Find all zero crossing of s with given trigger. The zero crossing is determined
            /// by detecting the plot rise above trigger and falls below zero.
            /// </summary>
            /// <param name="s"></param>
            /// <param name="trigger"></param>
            /// <returns></returns>
            public static CrudeZeroCrossing[] ZeroCrossings(double[] s, double trigger)
            {
                bool triggered = false;
                int tmpFirstTrigger = 0;
                int tmpLastTrigger = 0;
                int tmpZeroCrossing = 0;

                List<CrudeZeroCrossing> l = new List<CrudeZeroCrossing>();
                for (int i = 0; i < s.Length; i++)
                {
                    double v = s[i];

                    if (!triggered)
                    {
                        if (v > trigger)
                        {
                            triggered = true;
                            tmpFirstTrigger = i;
                            tmpLastTrigger = i;
                        }
                    }
                    else //in triggered mode
                    {
                        if (v < 0)
                        {
                            tmpZeroCrossing = i;
                            triggered = false;
                            CrudeZeroCrossing c = new CrudeZeroCrossing(i, tmpFirstTrigger, tmpLastTrigger);
                            l.Add(c);
                        }
                        else
                        {
                            if (v > trigger)
                            {
                                tmpLastTrigger = i;
                            }
                        }
                    }
                }
                return l.ToArray();
            }
Ejemplo n.º 5
0
 /// <summary>
 /// Construct Initial PeakGuess from CrudeZeroCrossing. Find mu from zero crossing position, sigma from inflection point
 /// nbkg, nsig is from zero crossing slope. The bound is mu+-n*sigma.
 /// </summary>
 /// <param name="cross"></param>
 /// <param name="x"></param>
 /// <param name="y"></param>
 /// <param name="window">smoothing parameter. indicate the size of piecewise</param>
 /// <param name="nsigma">window size</param>
 /// <param name="width">zero crossing fit width</param>
 /// <returns></returns>
 public static InitialPeakGuess OfCrudeZeroCrossing(CrudeZeroCrossing cross, double[] x, double[] y, int window = 30, double nsigma = 2.0, int width=30 )
 {
     InitialPeakGuess ret = new InitialPeakGuess();
     double[] rawg = NP.Gradient(x, y); //this is a raw gradient
     double[] g = NP.GlobalParabolicSmooth(y, window);
     return InitialPeakGuess.OfCrudeZeroCrossingAndGradient(cross, x, y, g, width, nsigma);
 }
Ejemplo n.º 6
0
            /// <summary>
            /// Construct initial peak guess from crude zerocrossing.
            /// </summary>
            /// <param name="cross"></param>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="sg">Smooth gradient</param>
            /// <param name="width"></param>
            /// <param name="nsigma"></param>
            /// <returns></returns>
            public static InitialPeakGuess OfCrudeZeroCrossingAndGradient(CrudeZeroCrossing cross, double[] x, double[] y, double[] sg, int width=10, double nsigma = 2.0)
            {
                InitialPeakGuess ret = new InitialPeakGuess();
                double[] g = sg;
                //NP.PrintArray(g);
                ZeroCrossingSlopeResult zerocrossing = PeakLocator.CrossingSlope(x, g, cross, width);
                ret.mu = zerocrossing.XIntercept;
                double inflection = PeakLocator.FastZeroCrossingLeftInflection(x, g, cross);
                Console.WriteLine("Inflection {0}", inflection);
                double sigma = ret.mu - inflection;
                ret.sigma = sigma;

                double lowerbound = Math.Max(0.0, zerocrossing.XIntercept - nsigma * sigma);
                double upperbound = Math.Min(zerocrossing.XIntercept + nsigma * sigma, x.Last());

                ret.lowerboundIndex = Math.Max(0, NP.LowerBound(x, lowerbound));
                ret.upperboundIndex = Math.Min(x.Length - 1, NP.UpperBound(x, upperbound));
                ret.lowerbound = x[ret.lowerboundIndex];
                ret.upperbound = x[ret.upperboundIndex];
                double[] xSlice = NP.Slice(x, ret.lowerboundIndex, ret.upperboundIndex + 1);//remember slice is right exclusive
                double[] ySlice = NP.Slice(y, ret.lowerboundIndex, ret.upperboundIndex + 1);
                lowerbound = ret.lowerbound;
                upperbound = ret.upperbound;

                Console.WriteLine("slope {0}, bw {1}", zerocrossing.Slope, zerocrossing.bw);
                double ntotalpeak = -zerocrossing.Slope / zerocrossing.bw * Math.Pow(sigma, 3) * Math.Sqrt(2 * Math.PI);
                double leftnsigma = (zerocrossing.XIntercept - lowerbound) / sigma;
                double rightnsigma = (upperbound - zerocrossing.XIntercept) / sigma;
                double npeakfrac = 0.5 * (SpecialFunctions.Erf(leftnsigma / Math.Sqrt(2)) + SpecialFunctions.Erf(rightnsigma / Math.Sqrt(2)));
                Console.WriteLine("npeakfrac {0}", npeakfrac);
                Console.WriteLine("ntotalpeak {0}", ntotalpeak);
                ret.nsig = ntotalpeak * npeakfrac;

                F3 gaussian = (xx, xmu, xsigma) => 1 / (xsigma * Math.Sqrt(2 * Math.PI)) * Math.Exp(-(xx - xmu) * (xx - xmu) / (2 * xsigma * xsigma));
                NP.Func1 rgauss = (xx) => ntotalpeak * zerocrossing.bw * gaussian(xx, ret.mu, ret.sigma);
                double[] peakamount = NP.Broadcast(rgauss, xSlice);
                double[] bkgamount = NP.Broadcast((xx, yy) => xx - yy, ySlice, peakamount);

                //NP.PrintArray(bkgamount);

                NP.LinearFitResult bkgshape = NP.LinearFit(xSlice, bkgamount);
                double m = bkgshape.m;
                double c = bkgshape.c;
                double bw = zerocrossing.bw;
                Console.WriteLine("bkg.m {0}, bkg.c {1}", m, c);
                double nbkg = 1 / bw * (m / 2.0 * (upperbound * upperbound - lowerbound * lowerbound) + c * (upperbound - lowerbound));

                ret.m = m;
                ret.c = c;
                ret.nbkg = nbkg;

                return ret;
            }
Ejemplo n.º 7
0
 public PeakFinder()
 {
     Crossings = new CrudeZeroCrossing[0];
     Guesses = new InitialPeakGuess[0];
     x = new double[0];
     y = new double[0];
     Edges = new double[0];
     Gradient = new double[0];
     SmoothGradient = new double[0];
     ScaledGradient = new double[0];
     TriggerValue = 0.5;
 }