public ParamSearch(double PV_Target, double CVMinLimit, double CVMaxLimit, double CVStepSize, int CVNumSamplesPerStep, ParamSearchMode Mode, bool Enabled) { this.PV_Target = PV_Target; this.CVMinLimit = CVMinLimit; this.CVMaxLimit = CVMaxLimit; this.CVStepSize = CVStepSize; this.CVNumSamplesPerStep = CVNumSamplesPerStep; this.Mode = Mode; this.Enabled = Enabled; listSamplesCV = new List <double>(); listSamplesPV = new List <double>(); numSamples = (int)((CVMaxLimit - this.CVMinLimit) / this.CVStepSize); //initialize search status information SearchCompleted = false; CV_Found = Double.MinValue; PV_Found = Double.MinValue; //initialize internal variables CV = CVMinLimit; CVNumSamplesCtr = 0; }
/// <summary> /// Once curve data contains all points required /// scan the curve for optimal CV range that gives stable desired PV. /// If such ideal range can't be located, find range that gives closest PV /// to the desired one. (may need params for HIGHER/LOWER) /// bool closestHigher = if PV range not found - will return closest value. THis parameter allows to specify /// whether closest higher or lower is preferred. /// </summary> private (double cvFound, double pvFound) FindOptimalCV(List <double> lstCV, List <double> lstPV, double pvTarget, ParamSearchMode mode) { //keep track of ranges found List <int> listExactRangeStart = new List <int>(); //Exact is preferred. Keep track of exact ranges regardless of mode List <int> listExactRangeLength = new List <int>(); List <int> listClosestRangeStart = new List <int>(); //If exact not found. Keep track of closest ranges according to mode. List <int> listClosestRangeLength = new List <int>(); int sampleIdx = 0; //index to sample being processed bool rngProcessing = false; //true if currently processing a range int rngIdxExact = -1; //index of found exact range being processed int rngIdxClosest = -1; //index of found closest range being processed (acc to mode) int longestRngStartExact = 0; //index of longest found Exact range int longestRngLengthExact = 0; //length of longest found Ecxact range int longestRngStartClosest = 0; //index of longest found Closest range int longestRngLengthClosest = 0; //length of longest found Closest range //FIND RANGES EQUAL TO PV TARGET foreach (double pv in lstPV) { bool sampleInRange = false; //determine if sample is within search parameters and //a candidate to store for analysis if (mode == ParamSearchMode.Exact && pv == pvTarget) { sampleInRange = true; } if (mode == ParamSearchMode.Higher && pv >= pvTarget) { sampleInRange = true; } if (mode == ParamSearchMode.Lower && pv <= pvTarget) { sampleInRange = true; } //start of range found if (sampleInRange && rngProcessing == false) { rngProcessing = true; if (mode == ParamSearchMode.Exact) { rngIdxExact++; listExactRangeStart.Add(sampleIdx); listExactRangeLength.Add(0); } if (mode == ParamSearchMode.Higher || mode == ParamSearchMode.Lower) { rngIdxClosest++; listClosestRangeStart.Add(sampleIdx); listClosestRangeLength.Add(0); } } //track end of range index if (sampleInRange && rngProcessing == true) { if (mode == ParamSearchMode.Exact) { listExactRangeLength[rngIdxExact] = sampleIdx - listExactRangeStart[rngIdxExact] + 1; } if (mode == ParamSearchMode.Higher || mode == ParamSearchMode.Lower) { listClosestRangeLength[rngIdxClosest] = sampleIdx - listClosestRangeStart[rngIdxClosest] + 1; } } //mark of range if (!sampleInRange) { rngProcessing = false; } sampleIdx++; } //FIND LONGEST EXACT RANGE for (int idx = 0; idx < listExactRangeStart.Count; idx++) { if (listExactRangeLength[idx] > longestRngLengthExact) { longestRngStartExact = listExactRangeStart[idx]; longestRngLengthExact = listExactRangeLength[idx]; } } //FIND LONGEST CLOSEST RANGE for (int idx = 0; idx < listClosestRangeStart.Count; idx++) { if (listClosestRangeLength[idx] > longestRngLengthClosest) { longestRngStartClosest = listClosestRangeStart[idx]; longestRngLengthClosest = listClosestRangeLength[idx]; } } //RETURN LONGEST EXACT RANGE IF FOUND (REGARDLESS OF MODE) if (longestRngLengthExact > 0) { int rangeMiddle = longestRngStartExact + (longestRngLengthExact / 2); double optimalCV = lstCV[rangeMiddle]; return(optimalCV, lstPV[rangeMiddle]);