Esempio n. 1
0
        /**********************************************************************
         * trinomial_mult - multiplies a series of trinomials together and returns
         * the coefficients of the resulting polynomial.
         *
         * The multiplication has the following form:
         *
         * (x^2 + b[0]x + c[0])*(x^2 + b[1]x + c[1])*...*(x^2 + b[n-1]x + c[n-1])
         *
         * The b[i] and c[i] coefficients are assumed to be complex and are passed
         * to the function as a pointers to arrays of doubles of length 2n. The real
         * part of the coefficients are stored in the even numbered elements of the
         * array and the imaginary parts are stored in the odd numbered elements.
         *
         * The resulting polynomial has the following form:
         *
         * x^2n + a[0]*x^2n-1 + a[1]*x^2n-2 + ... +a[2n-2]*x + a[2n-1]
         *
         * The a[i] coefficients can in general be complex but should in most cases
         * turn out to be real. The a[i] coefficients are returned by the function as
         * a pointer to an array of doubles of length 4n. The real and imaginary
         * parts are stored, respectively, in the even and odd elements of the array.
         * Storage for the array is allocated by the function and should be freed by
         * the calling program when no longer needed.
         *
         * Function arguments:
         *
         * n  -  The number of trinomials to multiply
         * b  -  Pointer to an array of doubles of length 2n.
         * c  -  Pointer to an array of doubles of length 2n.
         */

        private static rawType[] trinomial_mult(int n, rawType[] b, rawType[] c)
        {
            int i, j;

            rawType[] a = new rawType[4 * n];

            a[2] = c[0];
            a[3] = c[1];
            a[0] = b[0];
            a[1] = b[1];

            for (i = 1; i < n; ++i)
            {
                a[2 * (2 * i + 1)]     += c[2 * i] * a[2 * (2 * i - 1)] - c[2 * i + 1] * a[2 * (2 * i - 1) + 1];
                a[2 * (2 * i + 1) + 1] += c[2 * i] * a[2 * (2 * i - 1) + 1] + c[2 * i + 1] * a[2 * (2 * i - 1)];

                for (j = 2 * i; j > 1; --j)
                {
                    a[2 * j] += b[2 * i] * a[2 * (j - 1)] - b[2 * i + 1] * a[2 * (j - 1) + 1] +
                                c[2 * i] * a[2 * (j - 2)] - c[2 * i + 1] * a[2 * (j - 2) + 1];
                    a[2 * j + 1] += b[2 * i] * a[2 * (j - 1) + 1] + b[2 * i + 1] * a[2 * (j - 1)] +
                                    c[2 * i] * a[2 * (j - 2) + 1] + c[2 * i + 1] * a[2 * (j - 2)];
                }

                a[2] += b[2 * i] * a[0] - b[2 * i + 1] * a[1] + c[2 * i];
                a[3] += b[2 * i] * a[1] + b[2 * i + 1] * a[0] + c[2 * i + 1];
                a[0] += b[2 * i];
                a[1] += b[2 * i + 1];
            }
            return(a);
        }
Esempio n. 2
0
        /**********************************************************************
         * sf_bwbp - calculates the scaling factor for a butterworth bandpass filter.
         * The scaling factor is what the c coefficients must be multiplied by so
         * that the filter response has a maximum value of 1.
         */

        private static rawType sf_bwbp(int n, rawType f1f, rawType f2f)
        {
            int     k;        // loop variables
            rawType ctt;      // cotangent of theta
            rawType sfr, sfi; // real and imaginary parts of the scaling factor
            rawType parg;     // pole angle
            rawType sparg;    // sine of pole angle
            rawType cparg;    // cosine of pole angle
            rawType a, b, c;  // workspace variables

            ctt = (rawType)(1.0 / Math.Tan(Math.PI * (f2f - f1f) / 2.0));
            sfr = (rawType)1.0;
            sfi = (rawType)0.0;

            for (k = 0; k < n; ++k)
            {
                parg  = (rawType)(Math.PI * (rawType)(2 * k + 1) / (rawType)(2 * n));
                sparg = (rawType)(ctt + Math.Sin(parg));
                cparg = (rawType)(Math.Cos(parg));
                a     = (sfr + sfi) * (sparg - cparg);
                b     = sfr * sparg;
                c     = -sfi * cparg;
                sfr   = b - c;
                sfi   = a - b - c;
            }

            return((rawType)(1.0 / sfr));
        }
Esempio n. 3
0
        //note that this only needs to filter the channels on this particular device


        public SALPA3(int length_sams, int asym_sams, int blank_sams, int ahead_sams, int forcepeg_sams, rawType railLow, rawType railHigh, int numElectrodes, int bufferLength, rawType[] thresh)
        {
            //MB defaults:
            this.length_sams = length_sams; // 75;
            this.asym_sams   = asym_sams;   // 10;
            this.blank_sams  = blank_sams;  // 75;//HACK try 20
            this.ahead_sams  = ahead_sams;  // 5;
            //this.period_sams = period_sams;// 0;
            //this.delay_sams = 0;
            this.forcepeg_sams = forcepeg_sams;//10;


            this.thresh        = thresh;
            this.numElectrodes = numElectrodes;
            this.railHigh      = railHigh;
            this.railLow       = railLow;
            this.numSamples    = bufferLength;

            this.PRE  = 2 * length_sams;
            this.POST = 2 * length_sams + 1 + ahead_sams;
            fitters   = new LocalFit[numElectrodes];
            for (int i = 0; i < numElectrodes; i++)
            {
                fitters[i] = new LocalFit(thresh[i], length_sams, blank_sams, ahead_sams, asym_sams, railHigh, railLow, bufferLength, forcepeg_sams);
            }
        }
Esempio n. 4
0
 private void calc_X3()
 {
     X3 = 0;
     for (int t = -tau; t <= tau; t++)
     {
         int     t3 = t * t * t;
         rawType y  = source[t0 + t];
         X3 += ((double)t3 * y);
     }
 }
Esempio n. 5
0
        private bool ispegged(rawType r)
        {
            bool tmp = (r < railLow) || (r > railHigh);

            if (tmp)
            {
                tmp = true;
            }
            return(tmp);
        }
Esempio n. 6
0
        protected override void updateThreshold(rawType[] data, int channel)
        {
            /*  After band pass filtering as for BandFlt, LimAda splits the data stream into 10 ms windows,
             *  and determines the 2nd and 30th percentiles of the distribution of voltages found in each
             *  such window. Call these voltages V.02 and V.30. (Note that both are usually negative because
             *  of the filtering, which sets V.50 ~ <V> ~ 0.) It then performs two tests:
             *  • Is the ratio of V.02 over V.30 less than 5?
             *  • Is the absolute value of V.30 (significantly) non-zero?
             *  The first test makes sure that there was no actual spike in the window; the second test
             *  makes sure that the data in the window was not blanked out (e.g. by Rawsrv or Salpa).
             *  If both tests are passed, the windows is considered ‘clean’, and V.02 is used to update the
             *  current noise threshold estimate. Spikes are detected whenever the absolute value of the
             *  voltage exceeds the current threshold, which is the output of passing the absolute values of
             *  V.02 from all ‘clean’ windows through a low-pass filter with a time constant of 100 windows
             *  (1 second if all are clean). This algorithm adapts rapidly to changing noise situations, while
             *  not desensitizing during bursts.
             */
            for (int j = 0; j < numChunks; ++j)
            {
                //Copy chunk into tempData, sort
                for (int k = 0; k < chunkSize; ++k)
                {
                    tempData[k] = data[j * chunkSize + k];
                }
                Array.Sort(tempData);
                VLo = tempData[VLoIdx];
                VHi = tempData[VHiIdx];
                if (VLo / VHi < 5.0 && VHi != 0.0)
                {
                    //Low pass filter threshold
                    if (VLo < 0)
                    {
                        tempThreshold = -alpha * VLo + (1 - alpha) * limAdaPrevious[channel];
                    }
                    else
                    {
                        //tempThreshold = alpha * VLo + (1 - alpha) * limAdaPrevious[channel];
                        tempThreshold = limAdaPrevious[channel] + alpha * (VLo - limAdaPrevious[channel]);
                    }
                }
                else
                {
                    tempThreshold = limAdaPrevious[channel];
                }
                finalThreshold = tempThreshold * thresholdMultiplier * 0.494F; //The 0.494 is to make it commensurate with RMS noise

                //Copy threshold to thrAda
                for (int k = 0; k < chunkSize; ++k)
                {
                    threshold[channel, j *chunkSize + k] = finalThreshold;
                }
                limAdaPrevious[channel] = tempThreshold;
            }
        }
Esempio n. 7
0
 //functions to actually calculate the curve
 #region X0-3 functions
 private void calc_X012()
 {
     X0 = X1 = X2 = 0;
     for (int t = -tau; t <= tau; t++)
     {
         int     t2 = t * t;
         rawType y  = source[t0 + t];
         X0 += y;
         X1 += ((double)t * y);
         X2 += ((double)t2 * y);
     }
 }
Esempio n. 8
0
 public RMSThresholdFixed(int spikeBufferLengthIn, int numChannelsIn, int downsampleIn, int spikeWaveformLength,
                          int numPostIn, int numPreIn, rawType threshMult, int detectionDeadTime, int minSpikeWidth, int maxSpikeWidth
                          , double maxSpikeAmp, double minSpikeSlope, int spikeIntegrationTime, double deviceRefresh, int threshPolarity) :
     base(spikeBufferLengthIn, numChannelsIn, downsampleIn, spikeWaveformLength, numPostIn, numPreIn, threshMult, detectionDeadTime,
          minSpikeWidth, maxSpikeWidth, maxSpikeAmp, minSpikeSlope, threshPolarity)
 {
     numUpdatesForTrain = (int)Math.Round(10 / deviceRefresh); // ten seconds worth of data used in training
     threshold          = new rawType[1, numChannels];
     numUpdates         = new int[numChannels];
     RMSList            = new double[numChannels, numUpdatesForTrain];
     ChanThresh         = new double[numUpdatesForTrain];
     ThreshSorted       = new double[(int)Math.Floor((double)(numUpdatesForTrain - 9 * numUpdatesForTrain / 10))];
 }
Esempio n. 9
0
        /**********************************************************************
         * dcof_bwbp - calculates the d coefficients for a butterworth bandpass
         * filter. The coefficients are returned as an array of doubles.
         */

        public static rawType[] dcof_bwbp(int n, rawType f1f, rawType f2f)
        {
            int     k;        // loop variables
            rawType theta;    // M_PI * (f2f - f1f) / 2.0
            rawType cp;       // cosine of phi
            rawType st;       // sine of theta
            rawType ct;       // cosine of theta
            rawType s2t;      // sine of 2*theta
            rawType c2t;      // cosine 0f 2*theta

            rawType[] rcof;   // z^-2 coefficients
            rawType[] tcof;   // z^-1 coefficients
            rawType[] dcof;   // dk coefficients
            rawType   parg;   // pole angle
            rawType   sparg;  // sine of pole angle
            rawType   cparg;  // cosine of pole angle
            rawType   a;      // workspace variables

            cp    = (rawType)(Math.Cos(Math.PI * (f2f + f1f) / 2.0));
            theta = (rawType)(Math.PI * (f2f - f1f) / 2.0);
            st    = (rawType)(Math.Sin(theta));
            ct    = (rawType)(Math.Cos(theta));
            s2t   = (rawType)(2.0 * st * ct);       // sine of 2*theta
            c2t   = (rawType)(2.0 * ct * ct - 1.0); // cosine of 2*theta

            rcof = new rawType[2 * n];
            tcof = new rawType[2 * n];

            for (k = 0; k < n; ++k)
            {
                parg            = (rawType)(Math.PI * (rawType)(2 * k + 1) / (rawType)(2 * n));
                sparg           = (rawType)(Math.Sin(parg));
                cparg           = (rawType)(Math.Cos(parg));
                a               = (rawType)(1.0 + s2t * sparg);
                rcof[2 * k]     = c2t / a;
                rcof[2 * k + 1] = s2t * cparg / a;
                tcof[2 * k]     = (rawType)(-2.0 * cp * (ct + st * sparg) / a);
                tcof[2 * k + 1] = (rawType)(-2.0 * cp * st * cparg / a);
            }

            dcof = trinomial_mult(n, tcof, rcof);

            dcof[1] = dcof[0];
            dcof[0] = (rawType)1.0;
            for (k = 3; k <= 2 * n; ++k)
            {
                dcof[k] = dcof[2 * k - 2];
            }
            return(dcof);
        }
Esempio n. 10
0
        public void mein(string[] args)//filter data
        {
            if (args.Length < 2)
            {
                System.Console.Out.WriteLine("Not enough input arguments.");
                return;
            }
            StreamReader sr      = new StreamReader(args[0]);
            StreamWriter sw      = new StreamWriter(args[1]);
            string       in_line = sr.ReadLine();
            string       out_line;

            rawType[] data;
            //Continue to read until you reach end of file

            //filter data from ascii file one line at a time
            while (in_line != null)
            {
                //convert string to raw
                //System.Console.Out.WriteLine(in_line);

                string[] words = in_line.Split(' ');
                //System.Console.Out.WriteLine("here?");
                data = new rawType[words.Length - 1];
                //System.Console.Out.WriteLine("here?");
                for (int i = 0; i < words.Length - 1; i++)//-1 for the last one
                {
                    //System.Console.Out.WriteLine(":"+ words[i]);
                    data[i] = (rawType)Convert.ToDouble(words[i]);
                }

                //filter data
                filterData(data);

                //convert raw to string
                out_line = "";
                for (int i = 0; i < data.Length; i++)
                {
                    out_line += Convert.ToString(data[i]) + " ";
                }

                //output processed data in string form to output file.
                sw.WriteLine(out_line);
                in_line = sr.ReadLine();
            }
            //close file streams
            sw.Close();
            sr.Close();
        }
Esempio n. 11
0
        public void Reset(int order, rawType samplingRate, rawType lowCut, rawType highCut, int bufferSize)
        {
            lock (this)
            {
                dcof = ButterworthFilter.dcof_bwbp(order, (rawType)(lowCut / (samplingRate * 0.5)), (rawType)(highCut / (samplingRate * 0.5)));
                ccof = ButterworthFilter.ccof_bwbp(order, (rawType)(lowCut / (samplingRate * 0.5)), (rawType)(highCut / (samplingRate * 0.5)));
                //for (int i = 0; i < dcof.Length; ++i)
                //    dcof[i] = -dcof[i]; //Since you always subtract dcof
                lastInput = new rawType[ccof.Length - 1];
                lastInput.Initialize();
                lastOutput = new rawType[ccof.Length - 1];
                lastOutput.Initialize();

                oldData = new rawType[bufferSize];
            }
        }
Esempio n. 12
0
        internal void calcThreshForOneBlock(rawType[] data, int channel, int idx)
        {
            rawType tempData = 0;

            for (int j = 0; j < spikeBufferLength / downsample; ++j)
            {
                double dd = data[j * downsample] * data[j * downsample];
                if (dd > 0)         // Don't include blanked samples
                {
                    tempData += dd; //Square data
                }
            }
            tempData /= (spikeBufferLength / downsample);
            rawType thresholdTemp = (rawType)(Math.Sqrt(tempData) * _thresholdMultiplier);

            RMSList[channel, idx] = thresholdTemp;
            threshold[0, channel] = (threshold[0, channel] * (numUpdates[channel])) / (numUpdates[channel] + 1) + (thresholdTemp / (numUpdates[channel] + 1));// Recursive RMS estimate
        }
Esempio n. 13
0
 public AdaptiveRMSThreshold(int spikeBufferLengthIn, int numChannelsIn, int downsampleIn, int spikeWaveformLength,
                             int numPostIn, int numPreIn, rawType threshMult, int detectionDeadTime, int minSpikeWidth, int maxSpikeWidth
                             , double maxSpikeAmp, double minSpikeSlope, int spikeIntegrationTime, double deviceRefresh, int threshPolarity) :
     base(spikeBufferLengthIn, numChannelsIn, downsampleIn, spikeWaveformLength, numPostIn, numPreIn, threshMult, detectionDeadTime,
          minSpikeWidth, maxSpikeWidth, maxSpikeAmp, minSpikeSlope, threshPolarity)
 {
     numUpdatesForTrain = (int)Math.Round(updateBlockLengthSec / deviceRefresh); // 1 second worth of data used for estimating each RMS point to be feed into the exp filter
     filterHalfLife     = filterHalfLifeSec / updateBlockLengthSec;              // seconds
     threshold          = new rawType[1, numChannels];
     numUpdates         = new int[numChannels];
     RMSList            = new double[numChannels, numUpdatesForTrain];
     ChanThresh         = new double[numUpdatesForTrain];
     ThreshSorted       = new double[(int)Math.Floor((double)(numUpdatesForTrain - 9 * numUpdatesForTrain / 10))];
     alpha           = 2 / (2.8854 * filterHalfLife + 1);
     chanStarted     = new bool[numChannels];
     warmupThreshold = threshold;
     warmedUp        = new bool[numChannels];
     countWarmup     = new int[numChannels];
 }
Esempio n. 14
0
        public LocalFit(rawType y_threshold, int N, int t_blankdepeg, int t_ahead, int t_chi2, rawType railHigh, rawType railLow, int bufferlength, int forcepegsamples)
        {
            elecState            = state.PEGGED;
            this.N               = N;
            this.tau             = N;
            this.y_threshold     = y_threshold;
            this.t_blankdepeg    = t_blankdepeg;
            this.t_ahead         = t_ahead;
            this.t_chi2          = t_chi2;
            this.railHigh        = railHigh;
            this.railLow         = railLow;
            this.forcepegsamples = forcepegsamples;
            //this code in the init_t section of DAW's MB
            my_thresh = 3.92 * t_chi2 * y_threshold;

            //a bunch of terms that get used repeatedly:
            tau_plus_1         = tau + 1;
            tau_plus_1_squared = tau_plus_1 * tau_plus_1;
            tau_plus_1_cubed   = tau_plus_1_squared * tau_plus_1;
            minus_tau          = -tau;
            minus_tau_squared  = minus_tau * minus_tau;
            minus_tau_cubed    = minus_tau_squared * minus_tau;

            T0 = T2 = T4 = T6 = 0;
            for (int t = -tau; t <= tau; t++)
            {
                int t2 = t * t;
                int t4 = t2 * t2;
                int t6 = t4 * t2;
                T0 += 1;
                T2 += t2;
                T4 += t4;
                T6 += t6;
            }
            this.bufferlength = bufferlength;
            PRE          = 2 * N;
            POST         = 2 * N + 1 + t_ahead;
            source       = new rawType[PRE + POST + bufferlength];
            previousData = new rawType[PRE + POST];
        }
Esempio n. 15
0
        public LimAda(int spikeBufferLengthIn, int numChannelsIn, int downsampleIn, int spikeWaveformLength, int numPostIn,
                      int numPreIn, rawType threshMult, int detectionDeadTime, int minSpikeWidth, int maxSpikeWidth, double maxSpikeAmp
                      , double minSpikeSlope, int spikeIntegrationTime, int spikeSamplingRateIn, int threshPolarity) :
            base(spikeBufferLengthIn, numChannelsIn, downsampleIn, spikeWaveformLength, numPostIn, numPreIn, threshMult, detectionDeadTime,
                 minSpikeWidth, maxSpikeWidth, maxSpikeAmp, minSpikeSlope, threshPolarity)
        {
            chunkSize = (int)(0.01 * (rawType)spikeSamplingRateIn); //Big enough for 10ms of data
            numChunks = spikeBufferLength / chunkSize;
            VLoIdx    = (int)(0.02 * chunkSize);
            VHiIdx    = (int)(0.3 * chunkSize);
            tempData  = new rawType[chunkSize]; //To hold 10ms window

            threshold      = new rawType[numChannels, spikeBufferLength];
            limAdaPrevious = new rawType[numChannels];
            for (int i = 0; i < numChannels; ++i)
            {
                limAdaPrevious[i] = 0.0001;
            }

            thresholdCarryOverBuffer = new double[numChannels, carryOverLength];
            firstPass = new bool[numChannels];
        }
Esempio n. 16
0
        /**********************************************************************
         * ccof_bwbp - calculates the c coefficients for a butterworth bandpass
         * filter. The coefficients are returned as an array of integers.
         */
        public static rawType[] ccof_bwbp(int n, rawType lowCut, rawType highCut)
        {
            int[]     tcof;
            int[]     ccofTemp = new int[2 * n + 1];
            rawType[] ccof     = new rawType[2 * n + 1];

            tcof = ccof_bwhp(n);

            for (int i = 0; i < n; ++i)
            {
                ccofTemp[2 * i]     = tcof[i];
                ccofTemp[2 * i + 1] = 0;
            }
            ccofTemp[2 * n] = tcof[n];

            rawType scalingFactor = sf_bwbp(n, lowCut, highCut);

            for (int i = 0; i < ccof.Length; ++i)
            {
                ccof[i] = ccofTemp[i] * scalingFactor;
            }

            return(ccof);
        }
Esempio n. 17
0
        unsafe public void filterData(rawType[] data)
        {
            lock (this)
            {
                rawType temp = 0;
                //for (int i = 0; i < data.Length; ++i)
                //{
                //    temp = data[i];

                //    data[i] *= ccof[0];
                //    for (int j = 1; j < ccof.Length; ++j)
                //        data[i] += ccof[j] * lastInput[j - 1] - dcof[j] * lastOutput[j - 1];

                //    //Update lastInput and lastOutput
                //    for (int j = lastInput.Length - 1; j > 0; --j)
                //    {
                //        lastInput[j] = lastInput[j - 1];
                //        lastOutput[j] = lastOutput[j - 1];
                //    }
                //    lastInput[0] = temp;
                //    lastOutput[0] = data[i];
                //}
                fixed(double *pData = data)
                {
                    fixed(double *pOldData = oldData)
                    {
                        //for (int i = 0; i < data.Length; ++i)
                        //    oldData[i] = data[i];
                        for (int i = 0; i < data.Length; ++i)
                        {
                            pOldData[i] = pData[i];
                        }
                    }

                    for (int i = 0; i < ccof.Length; ++i)
                    {
                        temp = pData[i];

                        pData[i] *= ccof[0];
                        for (int j = 1; j < ccof.Length; ++j)
                        {
                            pData[i] += ccof[j] * lastInput[j - 1] - dcof[j] * lastOutput[j - 1];
                        }

                        //Update lastInput and lastOutput
                        for (int j = lastInput.Length - 1; j > 0; --j)
                        {
                            lastInput[j]  = lastInput[j - 1];
                            lastOutput[j] = lastOutput[j - 1];
                        }
                        lastInput[0]  = temp;
                        lastOutput[0] = pData[i];
                    }

                    for (int i = ccof.Length; i < data.Length; ++i)
                    {
                        pData[i] *= ccof[0];
                        for (int j = 1; j < ccof.Length; ++j)
                        {
                            pData[i] += ccof[j] * oldData[i - j] - dcof[j] * pData[i - j];
                        }
                    }

                    for (int i = 0; i < lastOutput.Length; ++i)
                    {
                        lastOutput[i] = pData[data.Length - 1 - i];
                        lastInput[i]  = oldData[oldData.Length - 1 - i];
                    }
                }
            }
        }
Esempio n. 18
0
 public ButterworthFilter(int order, rawType samplingRate, rawType lowCutF, rawType highCutF, int bufferSize)
 {
     Reset(order, samplingRate, lowCutF, highCutF, bufferSize);
 }