예제 #1
0
        //--------------------------------------------------------------------

        private void TemperatureCorrection(Assay recalc)
        {
            // get last valid temp in temperature table (table must be monotonic)
            int indexLast = 0;

            while ((indexLast < recalc.cal.TempTable.Length - 1) &&
                   (recalc.cal.TempTable[indexLast + 1].temp > recalc.cal.TempTable[indexLast].temp))
            {
                indexLast++;
            }

            // walk thru table to get line segment endpoints
            int index = 1;

            while ((recalc.TempAvg > recalc.cal.TempTable[index].temp) && index < indexLast)
            {
                index++;
            }

            float tempLow    = recalc.cal.TempTable[index - 1].temp;
            float tempHigh   = recalc.cal.TempTable[index].temp;
            float factorLow  = recalc.cal.TempTable[index - 1].factor;
            float factorHigh = recalc.cal.TempTable[index].factor;

            float correctionFactor = (factorHigh - factorLow) / (tempHigh - tempLow);

            correctionFactor = correctionFactor * (recalc.TempAvg - tempLow) + factorLow;

            float result = recalc.SWCValue * (correctionFactor / 1000.0f);

            recalc.TempCorrected = (uint)(result + 0.5f);
        }
예제 #2
0
        //--------------------------------------------------------------------

        private bool BaselineCorrection(Assay recalc)
        {
            int left  = IndexOfMinimum(recalc.CorrectedTable, recalc.cal.Min1, recalc.cal.Min2);
            int right = IndexOfMinimum(recalc.CorrectedTable, recalc.cal.Min3, recalc.cal.Min4);

            float rise  = recalc.CorrectedTable[right] - recalc.CorrectedTable[left];
            float run   = right - left;
            float slope = rise / run;

            recalc.LowerMinimum = (ushort)left;
            recalc.UpperMinimum = (ushort)right;
            recalc.Slope        = (short)(slope * 100.0f);

            if ((recalc.CorrectedTable[right] == 0) && (recalc.CorrectedTable[left] == 0))
            {
                return(false);
            }

            float adjuster       = -slope * left;
            short baseline       = recalc.CorrectedTable[left];
            int   correctedIndex = 0;

            for (int i = 0; i < recalc.StepCount; i++)
            {
                float temp = recalc.CorrectedTable[i];
                temp = temp - adjuster;
                temp = temp - baseline;

                temp = temp + 0.5f;
                recalc.CorrectedTable[correctedIndex++] = (short)temp;
                adjuster = adjuster + slope;
            }
            return(true);
        }
예제 #3
0
        /// <summary>
        /// get difference between forward and reverse curves and
        /// set recal assay error if ADC overflow in resulting table
        /// </summary>
        /// <param name="rawDiffTable">must be same size as Forward & Reverse tables</param>
        private void GetDifferenceCurve(Assay recalc, short[] rawDiffTable)
        {
            for (int i = 0; i < StepCount; i++)
            {
                int adjustedForward = recalc.ForwardTable[i] - recalc.ForwardTable[recalc.cal.Min1];
                int adjustedReverse = recalc.ReverseTable[i] - recalc.ReverseTable[recalc.cal.Min1];
                int difference      = adjustedForward - adjustedReverse;

                if (difference > short.MaxValue)
                {
                    difference = short.MaxValue;
                    if (i >= recalc.cal.Min1 && i <= recalc.cal.Min4)
                    {
                        recalc.Error = 17;
                    }
                }
                if (difference < short.MinValue)
                {
                    difference = short.MinValue;
                    if (i >= recalc.cal.Min1 && i <= recalc.cal.Min4)
                    {
                        recalc.Error = 17;
                    }
                }

                rawDiffTable[i] = (short)difference;
            }
        }
예제 #4
0
        //--------------------------------------------------------------------

        private void TranslateBLL(Assay recalc)
        {
            if (recalc.TempCorrected > recalc.cal.MaxADCcount)
            {
                recalc.BLLCorrected = Assay.HighLead;
                return;
            }

            ushort scaledSWC = (ushort)((65535.0f * recalc.TempCorrected / recalc.cal.MaxADCcount) + 0.5f);

            recalc.SWCscaled = scaledSWC;

            int indexLast = LastSwcIndex(recalc.cal);

            // if value ouside table bounds then set result and exit
            if (scaledSWC < recalc.cal.SwcTable[0].swc)
            {
                recalc.BLLCorrected = Assay.LowLead;
                return;
            }
            else if (scaledSWC >= recalc.cal.SwcTable[indexLast].swc)
            {
                recalc.BLLCorrected = Assay.HighLead;
                return;
            }

            // walk thru table and get line segment endpoints
            int index = 1;

            while (scaledSWC > recalc.cal.SwcTable[index].swc)
            {
                index++;
            }

            float swcLow  = recalc.cal.SwcTable[index - 1].swc;
            float bllLow  = recalc.cal.SwcTable[index - 1].bll;
            float swcHigh = recalc.cal.SwcTable[index].swc;
            float bllHigh = recalc.cal.SwcTable[index].bll;

            // interpolate to obtained corrected BLL
            float bllResult = (bllHigh - bllLow) / (swcHigh - swcLow);

            bllResult = (scaledSWC - swcLow) * bllResult + bllLow;

            // round and convert
            recalc.BLLCorrected = (uint)(bllResult + 0.5);
        }
예제 #5
0
        //--------------------------------------------------------------------

        private void TestAgainstCurrentLimit(Assay recalc, short[] forward, short[] reverse)
        {
            short ADClimit  = 26344;
            bool  currentOK = true;

            for (int i = recalc.cal.Min1; i <= recalc.cal.Min4; i++)
            {
                if (Math.Abs(forward[i]) > ADClimit)
                {
                    currentOK = false;
                }
                if (Math.Abs(reverse[i]) > ADClimit)
                {
                    currentOK = false;
                }
            }

            // 17 is the high current error number
            if (!currentOK)
            {
                recalc.Error = 17;
            }
        }
예제 #6
0
        //--------------------------------------------------------------------

        public Assay ReCalcResults()
        {
            Calibration newCal = this.cal.Clone() as Calibration;

            // no need to recal LC3 results, since they were done on PC in first place
            if (Source == Analyzer.LeadCare3)
            {
                return((Assay)this.Clone());
            }

            // create new assay, set calibration,zero result
            Assay recalc = (Assay)this.Clone();

            recalc.cal      = newCal.Clone() as Calibration;
            recalc.Result   = 0;
            recalc.SWCValue = 0;

            // only recalc if we have raw data
            if (recalc.ForwardADC == null || recalc.ReverseADC == null || recalc.StepCount == 0)
            {
                return(recalc);
            }

            // intermediate data tables for filtering
            short[] avgForwardTable = new short[recalc.StepCount];
            short[] avgReverseTable = new short[recalc.StepCount];
            short[] rawDiffTable    = new short[recalc.StepCount];

            // first fill with raw ADC reads
            for (int step = 0; step < recalc.StepCount; step++)
            {
                if (Source == Analyzer.LeadCare3)
                {
                    avgForwardTable[step] = ConvertLc3AdcReading(ForwardADC[step]);
                    avgReverseTable[step] = ConvertLc3AdcReading(ReverseADC[step]);
                }
                else
                {
                    avgForwardTable[step] = ForwardADC[step];
                    avgReverseTable[step] = ReverseADC[step];
                }
            }

            TestAgainstCurrentLimit(recalc, avgForwardTable, avgReverseTable);

            // apply boxcar filter to averaged reads to get final forward & reverse tables
            Filter(recalc.ForwardTable, avgForwardTable, BoxcarFilter);
            Filter(recalc.ReverseTable, avgReverseTable, BoxcarFilter);

            // get difference table with ADC overflow flagging and then filter with FFT
            GetDifferenceCurve(recalc, rawDiffTable);
            Filter(recalc.DifferenceTable, rawDiffTable, FFTfilter);

            // fill raw corrected table and apply baseline correction
            for (int i = 0; i < recalc.StepCount; i++)
            {
                recalc.CorrectedTable[i] = recalc.DifferenceTable[i];
            }
            recalc.BCiterations = 0;
            for (int i = 0; i < 3; i++)
            {
                if (BaselineCorrection(recalc))
                {
                    ++recalc.BCiterations;
                }
            }

            // integrate to get square wave capacitance
            recalc.SWCValue = 0;
            for (int i = recalc.LowerMinimum; i <= recalc.UpperMinimum; i++)
            {
                if (recalc.CorrectedTable[i] > 0)
                {
                    recalc.SWCValue += (uint)recalc.CorrectedTable[i];
                }
            }

            // final correction and conversion
            TemperatureCorrection(recalc);
            TranslateBLL(recalc);
            if (recalc.Error == 0)
            {
                recalc.Result = recalc.BLLCorrected;
            }

            // debug test for calculation
            bool recalcOK = true;

            try {
                for (int step = 0; step < recalc.StepCount; step++)
                {
                    if (recalc.ForwardTable[step] != this.ForwardTable[step])
                    {
                        recalcOK = false;
                    }
                    if (recalc.ReverseTable[step] != this.ReverseTable[step])
                    {
                        recalcOK = false;
                    }
                    if (recalc.DifferenceTable[step] != this.DifferenceTable[step])
                    {
                        recalcOK = false;
                    }
                    if (recalc.CorrectedTable[step] != this.CorrectedTable[step])
                    {
                        recalcOK = false;
                    }
                }
                if (recalc.SWCValue != this.SWCValue)
                {
                    recalcOK = false;
                }
                if (recalc.TempCorrected != this.TempCorrected)
                {
                    recalcOK = false;
                }
                if (recalc.SWCscaled != this.SWCscaled)
                {
                    recalcOK = false;
                }
                if (recalc.BLLCorrected != this.BLLCorrected)
                {
                    recalcOK = false;
                }
            }
            catch (Exception) {
                recalcOK = false;
            }

            if (recalcOK)
            {
            }

            return(recalc);
        }