Example #1
0
        private void ProcessChannel_Worker(object sender, DoWorkEventArgs e)
        {
            List<eventTime> eventList = new List<eventTime>(); //holds list of potential new Events for this channel
            workerArguments args = (workerArguments)e.Argument;
            double[] d = args.data; //channel data to be analyzed
            int N = d.Length;
            int degree = args.trendDegree;
            if (degree >= 0) //then perform polynomial detrending
            {
                bw.ReportProgress(0, "detrending with " + degree.ToString("0") + " degree polynomial");
                removeTrend(d, degree);
            }

            double maxD = d[0];
            double minD = maxD;
            foreach (double v in d)
                if (v > maxD) maxD = v;
                else if (v < minD) minD = v;

            int filterN = args.filterLength;
            double[] V = new double[filterN];
            double c1 = 12D / (double)(filterN * (filterN - 1) * (filterN + 1));
            double offset = ((double)filterN - 1D) / 2D;
            for (int i = 0; i < filterN; i++) V[i] = c1 * ((double)i - offset);
            List<double> filtered = new List<double>(64);
            bool inEvent = false;
            int eventLength = 0;
            double sign = 1D;
            double threshold = args.threshold;
            int minimumLength = args.minLength;

            bw.ReportProgress(0, "detecting with " + filterN.ToString("0") + "pt filter;  th = " +
                threshold.ToString("0.00") + "; minLen = " + minimumLength.ToString("0"));

            int eventCount = 0;
            for (int i = 0; i < N; i++)
            {
                if (bw.CancellationPending) { e.Cancel = true; return; }
                double s = 0;
                for (int j = 0; j < filterN; j++)
                {
                    int index = i + j - filterN / 2;
                    if (index < 0) //handle start-up
                        s += V[j] * d[0]; //repeat first value to its left
                    else if (index >= N) //handle end
                        s += V[j] * d[N - 1]; //repeat last value to its right
                    else //usual case
                        s += V[j] * d[index];
                }
                if (Math.Abs(s) > threshold) //above threshold?
                {
                    if (!inEvent) //found beginning of new event
                    {
                        sign = s > 0D ? 1D : -1D;
                        eventLength = 0;
                        inEvent = true;
                    }
                    filtered.Add(s - sign * threshold);
                    eventLength++;
                }
                else //below threshold
                    if (inEvent) //are we just exiting an event?
                    {
                        if (eventLength > minimumLength) //event counts only if longer than minimum length
                        {
                            eventTime ev = new eventTime(); //create eventTime for each detected signal
                            ev.channelItem = args.channelItem;
                            ev.serialNumber = ++eventCount;
                            ev.channelNumber = args.channelNumber;
                            ev.startTime = i - eventLength; //starting index in data
                            ev.length = eventLength;
                            ev.sign = sign;
                            ev.filterSignal = filtered;
                            ev.trendDegree = args.trendDegree;
                            ev.filterLength = args.filterLength;
                            ev.threshold = args.threshold;
                            ev.minimumLength = args.minLength;
                            filtered = new List<double>(64); //need new filtered array for signal
                            eventList.Add(ev);
                            lf.registerPKEvent();
                        }
                        else
                            filtered.Clear();
                        inEvent = false;
                    }
            }

            //now we do a fit on each of the detected signals
            double samplingRate = args.samplingRate;
            double t0 = (double)filterN / (2D * samplingRate); //fixed initial estimate of t0
            int nEvents = eventList.Count;
            if (nEvents != 0)
                if (nEvents == 1)
                    eventList[0].foundFit = fitSignal(d, 0, eventList[0], d.Length, samplingRate, minD, maxD);
                else
                {
                    eventList[0].foundFit = fitSignal(d, 0, eventList[0], eventList[1].startTime, samplingRate, minD, maxD);
                    for (int i = 1; i < eventList.Count - 1; i++)
                    {
                        if (bw.CancellationPending) { e.Cancel = true; return; } //look for cancellation
                        bw.ReportProgress((int)((100D * i) / eventList.Count), "");
                        eventList[i].foundFit = fitSignal(d, eventList[i - 1].endTime, eventList[i], eventList[i + 1].startTime, samplingRate, minD, maxD);
                    }
                    eventList[eventList.Count - 1].foundFit = fitSignal(d, eventList[eventList.Count - 2].endTime, eventList[eventList.Count - 1], d.Length, samplingRate, minD, maxD);
                }

            e.Result = eventList;
        }
Example #2
0
        static void Main(string[] args)
        {
            List<eventTime> eventList = new List<eventTime>();
            Console.Write("Degree of fit desired: ");
            int degree = Convert.ToInt32(Console.ReadLine());

            BDFEDFFileReader bdf = new BDFEDFFileReader(new FileStream(@"C:\\Users\Jim\Desktop\PK detector data\S9998-AP-20150210-1205_PKcubes.bdf", FileMode.Open, FileAccess.Read));
            Console.WriteLine("Opened BDF file");
            double[] d = bdf.readAllChannelData(5);
            int N = d.Length;
            double n = (double)N;

            Console.WriteLine(d[0].ToString() + " " + d[1].ToString() + " " + d[100].ToString());

            removeTrend(d, degree);
            Console.WriteLine(d[0].ToString() + " " + d[1].ToString() + " " + d[100].ToString());

            double[] V = new double[filterN];
            double c1 = 12D / (double)(filterN * (filterN - 1) * (filterN + 1));
            double offset = ((double)filterN - 1D) / 2D;
            for (int i = 0; i < filterN; i++) V[i] = c1 * ((double)i - offset);
            List<double> filtered = new List<double>(64);
            byte[] marker = new byte[N];
            bool inEvent = false;
            int eventLength = 0;
            double sign = 1D;
            for (int i = 0; i < N; i++)
            {
                double s = 0;
                for (int j = 0; j < filterN; j++)
                {
                    int index = i + j - filterN / 2;
                    if (index < 0) //handle start-up
                        s += V[j] * d[0]; //repeat first value to its left
                    else if (index >= N) //handle end
                        s += V[j] * d[N - 1]; //repeat last value to its right
                    else //usual case
                        s += V[j] * d[index];
                }
                if (Math.Abs(s) > threshold) //above threshold?
                {
                    if (!inEvent) //found beginning of new event
                    {
                        sign = s > 0D ? 1D : -1D;
                        eventLength = 0;
                        inEvent = true;
                    }
                    filtered.Add(s - sign * threshold);
                    eventLength++;
                }
                else //below threshold
                    if (inEvent) //are we just exiting an event?
                    {
                        if (eventLength > minimumLength) //event counts only if longer than minimum length
                        {
                            eventTime e = new eventTime();
                            e.time = i - eventLength;
                            e.length = eventLength;
                            e.sign = sign;
                            e.filteredSignal = filtered;
                            filtered = new List<double>(64); //need new filtered array
                            eventList.Add(e);
                        }
                        else
                            filtered.Clear();
                        inEvent = false;
                    }
            }
            int dataLength;
            double t;
            eventTime et0;
            eventTime et1;
            double t0 = (double)filterN / (2D * SR);
            for (int i = 0; i < eventList.Count - 1; i++)
            {
                et0 = eventList[i];
                et1 = eventList[i + 1];
                dataLength = Math.Min(et1.time - et0.time, 16000);
                double max = double.MinValue;
                for (int p = et0.time; p < et0.time + et0.length; p++) max = Math.Max(max, Math.Abs(d[p]));
                et0.A = et0.sign * max; //correct sign of displacement; could be max sign*Abs(displacement)
                et0.C = d[et0.time]; //estimate of initial offset
                et0.B = et0.C; //current actual "baseline"
                et0.a = 4D; //typical alpha
                et0.b = 0.04; //typical beta
                t = t0; //half filterN / SR
                if (et0.foundFit = fitSignal(d, et0.time, dataLength, ref et0.A, ref et0.B, ref et0.C, ref et0.a, ref et0.b, ref t))
                    et0.time += (int)(t * SR);
                Console.WriteLine();
                Console.WriteLine(et0.time.ToString("0") + " (" + LM.Result.ToString() + ", " + LM.Iterations.ToString("0") +
                    ", " + LM.ChiSquare.ToString("0.0") + ", " + LM.normalizedStandardErrorOfFit.ToString("0.00") + "): ");
                Console.WriteLine(et0.A.ToString("0.0") + " " + et0.B.ToString("0.0") + " " + et0.C.ToString("0.0") +
                    " " + et0.a.ToString("0.000") + " " + et0.b.ToString("0.00000") + " " + t.ToString("0.000") + " ");
                NVector Sp = LM.parameterStandardError;
                Console.WriteLine(Sp[0].ToString("0.00") + " " + Sp[1].ToString("0.00") + " " + Sp[2].ToString("0.00") +
                    " " + Sp[3].ToString("0.0000") + " " + Sp[4].ToString("0.000000") + " " + Sp[5].ToString("0.0000") + " ");
            }
            et0 = eventList[eventList.Count - 1];
            dataLength = Math.Min(N - et0.time, 16000);
            et0.A = et0.sign * 5000D; //correct sign of displacement; could be max sign*Abs(displacement)
            et0.C = d[et0.time]; //estimate of initial offset
            et0.B = et0.C;
            et0.a = 4D;
            et0.b = 0.05;
            t = 0.25;
            if (et0.foundFit = fitSignal(d, et0.time, dataLength, ref et0.A, ref et0.B, ref et0.C, ref et0.a, ref et0.b, ref t))
                et0.time += (int)(t * SR);
            Console.WriteLine(et0.time.ToString("0") + " (" + LM.Result.ToString() + ", " + LM.Iterations.ToString("0") +
                ", " + LM.ChiSquare.ToString("0.0") + "): " + et0.A.ToString("0.0") + " " + et0.B.ToString("0.0") + " " + et0.C.ToString("0.0") +
                " " + et0.a.ToString("0.000") + " " + et0.b.ToString("0.00000") + " " + t.ToString("0.000") + " ");

            Console.WriteLine("Total events found = " + eventList.Count.ToString("0"));
            ConsoleKeyInfo cki = Console.ReadKey();
        }
Example #3
0
        private static bool fitSignal(double[] d, int beforeTime, eventTime current, int afterTime,
            double samplingRate, double minD, double maxD)
        {
            LevenbergMarquardt LM = new LevenbergMarquardt(func, Jfunc,
                new NVector(new double[] { minD - maxD, 2 * minD, 2 * minD, 0.25, 0.005, -0.25 }),
                new NVector(new double[] { maxD - minD, 2 * maxD, 2 * maxD, 40, 0.1, 0.5 }), null,
                new double[] { 0.0001, 0.00001, 0.00001, 0.01 },
                LevenbergMarquardt.UpdateType.Marquardt); //set up LM processor, parameters and limits

            //determine subset of data around the detection signal
            int start = Math.Max(0, Math.Min(current.startTime - (beforeTime + (int)(deadtimeSecsAfter * samplingRate)), (int)(maxSecsBefore * samplingRate))); //up to 5 seconds before
            double newTOffset = (double)start / samplingRate;
            int dataLength = start + Math.Max(current.filterLength, Math.Min(afterTime - current.filterLength - current.startTime, (int)(maxSecsAfter * samplingRate))); //up to 40 seconds after
            start = current.startTime - start;
            dataLength = Math.Min(dataLength, d.Length - start); //watch for overrun past end of data array

            double max = double.MinValue;
            for (int v = current.startTime; v < current.startTime + current.length; v++) max = Math.Max(max, Math.Abs(d[v])); //Get signal max for initial estimate of A

            NVector t = new NVector(dataLength);
            for (int ti = 0; ti < dataLength; ti++) t[ti] = (double)ti / samplingRate - newTOffset; //create independent variable array
            NVector y = new NVector(dataLength);
            for (int i = 0; i < dataLength; i++) y[i] = d[start + i]; //create dependent variable array

            NVector p =
                LM.Calculate(
                new NVector(new double[] { current.sign * max, /* A */
                    d[current.startTime], /* B */
                    d[current.startTime], /* C */
                    4D, /* alpha */
                    0.04, /* beta */
                    0D }), /* t0 */
                t, y); //fit signal using Levenberg-Marquardt algorithm

            current.A = p[0]; //parse estimated parameters out
            current.B = p[1];
            current.C = p[2];
            current.a = p[3];
            current.b = p[4];
            if (LM.Result > 0)
                current.t0 += (int)(p[5] * samplingRate); //offset starting time by new t0, only if fit found
            current.chiSquare = LM.ChiSquare; //remember Chi square
            return LM.Result > 0;
        }