DataInterval* DataInterval :: Split (DataInterval*& secondInterval) const { if (mNumberOfMinima == 0) { secondInterval = NULL; return NULL; } int ctr = (Left + mLocalMinimum) / 2; DataInterval* rtnValue = new DataInterval (Left, ctr, mLocalMinimum); rtnValue->SetNumberOfMinima (0); rtnValue->SetFixedRightTrue (); if (FixedLeft) rtnValue->SetFixedLeftTrue (); secondInterval = new DataInterval (mLocalMinimum, ctr, Right); secondInterval->SetNumberOfMinima (0); secondInterval->SetFixedLeftTrue (); if (FixedRight) secondInterval->SetFixedRightTrue (); // Set modes and value at modes for both and then return if (Mode < mLocalMinimum) { rtnValue->SetMode (Mode); rtnValue->SetMaxAtMode (MaxAtMode); secondInterval->SetMode (mSecondaryMode); secondInterval->SetMaxAtMode (mMaxAtSecondaryMode); } else { rtnValue->SetMode (mSecondaryMode); rtnValue->SetMaxAtMode (mMaxAtSecondaryMode); secondInterval->SetMode (Mode); secondInterval->SetMaxAtMode (MaxAtMode); } return rtnValue; }
DataInterval* STRTracePrequalification :: GetNextDataIntervalWithPrecomputedConvolution (NoiseInterval*& CurrentNoiseInterval, RGTextOutput& text, double minRFU, DataInterval* prevInterval, Boolean print) { // Perform convolution with square wave of width WindowWidth until hit peak (and // beyond), to capture whole data interval. Return DataInterval with center at // convolution peak and left and right end points determined by WindowWidth. Norm // of convolution is value of convolution at local peak. Convolution is performed // right to left. double PeakHeight; double PeakMass; int PeakRight; int PeakLeft; int PeakCenter; DataInterval* dataInterval; Endl endLine; int currentMode; double currentMaxAtMode = -DOUBLEMAX; double peakValueLeft; double peakValueRight; int nMinima; int localMin; double localMinValue; int secondaryStart; int secondaryEnd; double secondaryMax; double temp; int currentSecondaryMode; // int halfWindow = WindowWidth / 2; // int localMinSamplesForRegression = TracePrequalification::GetMinSamplesForSlopeRegression (); // if (halfWindow < localMinSamplesForRegression) // halfWindow = localMinSamplesForRegression; if (CurrentIndex <= 0) { CurrentNoiseInterval = NULL; return NULL; } PeakRight = CurrentIndex; peakValueRight = Data->Value (PeakRight); int SearchMode = LookingForMax; // if ((CurrentIndex >= 1) && (Data->Value (CurrentIndex - 1) < Data->Value (CurrentIndex))) // SearchMode = LookingForMin; // if (mConvolution [CurrentIndex] <= mConvolution [CurrentIndex + 1]) // SearchMode = LookingForMin; int LocationOfLastMin; int LocationOfLastMax = -1; int LocationOfBeginConstant = -1; // int CurrentEndNoise = CurrentIndex; CurrentNoiseInterval = new NoiseInterval (Data->Value (CurrentIndex), CurrentIndex); CurrentNoiseInterval->SetModeAscending (); // double newL; // double newR; double newCenter; double minRFUApproximate = 0.90 * minRFU; double localLowHeightThreshold = TracePrequalification::GetLowHeightThreshold (); double localLowSlopeThreshold = TracePrequalification::GetLowSlopeThreshold (); double maxSlope = 0.0; double currentSlope; double absCurrentSlope; // const double* dataArray = Data->GetData (); double delt = Data->GetSampleSpacing (); // int halfHalfWindow = halfWindow / 2; // int halfWindow1 = halfWindow - 1; bool slopeExceededThresholdOnDescent = false; bool slopeBelowThresholdOnFinalDescent = false; bool convolutionReversal = false; bool peakValueNegative = false; bool peakValueBelowThreshold = false; bool slopeReversal = false; double slopeThreshold; bool foundLocalMin; int prevPeakLeft; double rightLocalMin; double temp1; // double temp2; double slope1; // double slope2; int nPoints = 0; if (localLowHeightThreshold < 0.0) localLowHeightThreshold = 0.0; if (localLowSlopeThreshold < 0.0) localLowSlopeThreshold = 0.0; // // Add code here to mark possible right end of peak (it will move as we move) // LocationOfLastMin = CurrentIndex; while (CurrentIndex > 0) { // newL = Data->Value (WindowLeft); // newR = Data->Value (WindowRight); PeakLeft = CurrentIndex; newCenter = peakValueLeft = Data->Value (CurrentIndex); // NewConvolution = CurrentConvolution + 0.5 * (OldLeft + newL - OldRight - newR); NewConvolution = mConvolution [CurrentIndex]; CurrentConvolution = mConvolution [CurrentIndex + 1]; // CumulativeNorm += newCenter * newCenter; if (newCenter > currentMaxAtMode) { currentMaxAtMode = newCenter; currentMode = CurrentIndex; } // currentSlope = LinearSlopeRegression (dataArray + CurrentIndex - halfHalfWindow, delt, halfWindow1); currentSlope = mSlopeFits [CurrentIndex]; absCurrentSlope = fabs (currentSlope); if (absCurrentSlope > maxSlope) maxSlope = absCurrentSlope; // // Now test for maximum at CurrentConvolution; if not perform another iteration; if // so, start looking for relative minimum to bracket peak unless too low, in which case // add to noise and continue; in any case, bump WindowLeft, etc and Convolution values // to get ready for next try. // switch (SearchMode) { case LookingForMax: // It may be noise...add to CurrentNoiseInterval and we'll judge later CurrentNoiseInterval->AddPoint (newCenter, CurrentIndex); // Test for new value < 0 and if so, reset NewConvolution to zero (?) and break if ((NewConvolution < CurrentConvolution) && (nPoints >= 2)) { // // Found one! Test to see if it's above NoiseThreshold. If not, add to noise // and continue. If so, start to look for next minimum to add to DataInterval // if ((CurrentConvolution < NoiseThreshold) && (currentMaxAtMode < minRFUApproximate)) { // The max is noise; reset CurrentNoiseInterval to descending mode CurrentNoiseInterval->SetModeDescending (); LocationOfLastMax = CurrentIndex; LocationOfBeginConstant = -1; SearchMode = LookingForMin; } else { // It's a real maximum. This is it, boys! We've found another peak! PeakRight = LocationOfLastMin; peakValueRight = Data->Value (PeakRight); // Since we have found a real max, no point in collecting more noise data CurrentNoiseInterval->EndNoiseInterval (); if (LocationOfBeginConstant > 0) PeakCenter = (LocationOfBeginConstant + CurrentIndex) / 2; else PeakCenter = CurrentIndex; PeakHeight = Data->Value (PeakCenter); PeakMass = CurrentConvolution; LocationOfLastMax = PeakCenter; LocationOfBeginConstant = -1; // Now set up to look for next local minimum SearchMode = LookingForFinalMin; slopeExceededThresholdOnDescent = false; } } else if (NewConvolution == CurrentConvolution) { if (LocationOfBeginConstant < 0) LocationOfBeginConstant = CurrentIndex; } else { // Not at a maximum yet...keep looking LocationOfBeginConstant = -1; } CurrentIndex--; break; case LookingForMin: CurrentNoiseInterval->AddPoint (newCenter, CurrentIndex); // Test if new value < 0 and if so, reset NewConvolution to 0 (?) and break...or maybe no change...? if (NewConvolution > CurrentConvolution) { // // Found one! It must be below NoiseThreshold, or previous maximum would have been // above, too. In that case we would have been LookingForFinalMin! // // The min is noise; reset CurrentNoiseInterval to ascending mode CurrentNoiseInterval->SetModeAscending (); LocationOfLastMin = CurrentIndex; LocationOfBeginConstant = -1; SearchMode = LookingForMax; currentMaxAtMode = newCenter; } else if (NewConvolution == CurrentConvolution) { if (LocationOfBeginConstant < 0) LocationOfBeginConstant = CurrentIndex; } else { // Not at a minimum yet...keep looking LocationOfBeginConstant = -1; } CurrentIndex--; break; case LookingForFinalMin: // Test if new value < 0 and if so, declare Final Min found! peakValueLeft = Data->Value (CurrentIndex); // currentSlope = LinearSlopeRegression (dataArray + CurrentIndex - halfHalfWindow, delt, halfWindow1); // Use PeakLeft??? // absCurrentSlope = abs (currentSlope); // if ((currentSlope > 0.0) && (currentSlope > maxSlope)) // maxSlope = currentSlope; if (!slopeExceededThresholdOnDescent) { if ((currentSlope > 0.0) && (absCurrentSlope >= 3.0 * localLowSlopeThreshold * maxSlope)) { slopeExceededThresholdOnDescent = true; slopeBelowThresholdOnFinalDescent = false; } } else if (absCurrentSlope <= localLowSlopeThreshold * maxSlope) slopeBelowThresholdOnFinalDescent = true; else slopeBelowThresholdOnFinalDescent = false; convolutionReversal = (NewConvolution > CurrentConvolution); peakValueNegative = (peakValueLeft < 0.0); peakValueBelowThreshold = (peakValueLeft <= localLowHeightThreshold * currentMaxAtMode); slopeReversal = (currentSlope <= 0.0); if (CurrentIndex >= 1) foundLocalMin = (peakValueLeft <= Data->Value (CurrentIndex - 1)); else foundLocalMin = false; foundLocalMin = false; // *****!!!! This is a test!!!! ***** slopeReversal = false; // *****!!!! This is a test!!!! ***** if (convolutionReversal || peakValueNegative || slopeBelowThresholdOnFinalDescent || peakValueBelowThreshold || slopeReversal || foundLocalMin) { // // Found it! It could be above or below NoiseThreshold. If above, the very // next peak will be a data peak. Either way, don't add to CurrentNoiseInterval. // If it's below, it will be added next time. If above, there will be an // "empty" NoiseInterval, which will tell that there is a problem between these 2 // peaks, this and the next one. // LocationOfLastMin = CurrentIndex; double maxThreshold = localLowHeightThreshold * currentMaxAtMode; int lastIndex = PeakRight; int ii; // if (peakValueNegative || slopeReversal) // PeakLeft = CurrentIndex + 1; // else PeakLeft = CurrentIndex; peakValueLeft = Data->Value (PeakLeft); /*nMinima = FindInteriorLocalMinimum (PeakLeft, PeakRight, localMin, localMinValue); if (currentMode < localMin) { currentSecondaryMode = secondaryStart = localMin; secondaryEnd = PeakRight; } else { currentSecondaryMode = secondaryStart = PeakLeft; secondaryEnd = localMin; } secondaryMax = -DOUBLEMAX; for (int ii=secondaryStart; ii<=secondaryEnd; ii++) { temp = Data->Value (ii); if (temp > secondaryMax) { secondaryMax = temp; currentSecondaryMode = ii; } }*/ lastIndex = PeakLeft; slopeThreshold = localLowSlopeThreshold * maxSlope; for (ii=PeakLeft; ii < currentMode; ii++) { temp = Data->Value (ii); temp1 = Data->Value (ii - 1); // temp2 = Data->Value (ii - 2); slope1 = (temp - temp1) / delt; // slope2 = 0.5 * (temp - temp2) / delt; if (slope1 <= 0.0) lastIndex = ii + 1; else if (fabs (slope1) <= slopeThreshold) lastIndex = ii; // else if ((slope2 <= 0.0) || (abs (slope2) <= slopeThreshold)) // lastIndex = ii + 1; else break; } PeakLeft = lastIndex; peakValueLeft = Data->Value (PeakLeft); lastIndex = PeakRight; /*if ((nMinima > 0) && (currentMode < localMin)) { maxThreshold = localLowHeightThreshold * secondaryMax; }*/ if (prevInterval != NULL) { rightLocalMin = currentMaxAtMode; prevPeakLeft = prevInterval->GetLeft (); for (ii=PeakRight; ii<prevPeakLeft; ii++) { temp = Data->Value (ii); if (temp < rightLocalMin) { rightLocalMin = temp; lastIndex = ii; } else break; } PeakRight = lastIndex; peakValueRight = Data->Value (PeakRight); } for (int i=PeakRight; i>currentMode; i--) { temp = Data->Value (i); temp1 = Data->Value (i + 1); slope1 = (temp1 - temp) / delt; if (temp < maxThreshold) lastIndex = i; else if ((slope1 >= 0.0) || (fabs (slope1) <= slopeThreshold)) lastIndex = i; else break; } PeakRight = lastIndex; peakValueRight = Data->Value (PeakRight); /*slopeExceededThresholdOnDescent = false; for (int i=currentMode+1; i<=PeakRight; i++) { temp = Data->Value (i); currentSlope = mSlopeFits [i + 1]; absCurrentSlope = abs (currentSlope); temp1 = Data->Value (i + 1); slope1 = (temp1 - temp) / delt; if (temp < maxThreshold) { lastIndex = i; break; } if (!slopeExceededThresholdOnDescent) { if ((currentSlope <= 0.0) && (absCurrentSlope >= 3.0 * slopeThreshold)) slopeExceededThresholdOnDescent = true; } else if ((currentSlope >= 0.0) || (absCurrentSlope <= slopeThreshold)) { lastIndex = i; break; } else if ((slope1 >= 0.0) || (abs (slope1) <= slopeThreshold)) { lastIndex = i; break; } } PeakRight = lastIndex;*/ nMinima = FindInteriorLocalMinimum (PeakLeft, PeakRight, localMin, localMinValue); if (currentMode < localMin) { currentSecondaryMode = secondaryStart = localMin; secondaryEnd = PeakRight; } else { currentSecondaryMode = secondaryStart = PeakLeft; secondaryEnd = localMin; } secondaryMax = -DOUBLEMAX; for (ii=secondaryStart; ii<=secondaryEnd; ii++) { temp = Data->Value (ii); if (temp > secondaryMax) { secondaryMax = temp; currentSecondaryMode = ii; } } dataInterval = new DataInterval (PeakLeft, currentMode, PeakRight); dataInterval->SetHeight (PeakHeight); dataInterval->SetMass (PeakMass); dataInterval->SetLeftMinimum (Data->Value (PeakLeft)); dataInterval->SetRightMinimum (Data->Value (PeakRight)); dataInterval->SetMode (currentMode); dataInterval->SetMaxAtMode (currentMaxAtMode); dataInterval->SetNumberOfMinima (nMinima); dataInterval->SetLocalMinimum (localMin); dataInterval->SetLocalMinValue (localMinValue); dataInterval->SetSecondaryMode (currentSecondaryMode); dataInterval->SetMaxAtSecondaryMode (secondaryMax); // if ((currentMode == PeakLeft) || (currentMode == PeakRight)) { // Invent a test for a pure minimum: maybe this is enough of a test, but, for now // we'll just omit it until and if we need it. // } // PreviousConvolution = CurrentConvolution; // CurrentConvolution = NewConvolution; // CurrentIndex--; // ?????????????????? // OldLeft = newL; // OldRight = newR; // WindowLeft--; // WindowRight--; LocationOfBeginConstant = -1; if (print) { text << "Found data interval with left = " << PeakLeft << ", right = " << PeakRight << " and center = " << PeakCenter << endLine; text << " Value at center = " << Data->Value (PeakCenter) << endLine; text << " Convolution = " << PeakMass << endLine; } if (foundLocalMin) { dataInterval->SetFixedLeftTrue (); return dataInterval; } if ((slopeReversal) || (PeakLeft > CurrentIndex) || convolutionReversal) { dataInterval->SetFixedLeftTrue (); /*lastIndex = CurrentIndex; for (ii=CurrentIndex; ii<=PeakLeft; ii++) { if (Data->Value (ii) >= Data->Value (ii + 1)) lastIndex = ii; else break; } CurrentIndex = lastIndex;*/ CurrentIndex--; return dataInterval; } // if (convolutionReversal) // return dataInterval; SearchMode = UnravelingFinalCurve; CurrentIndex--; break; } else if (NewConvolution == CurrentConvolution) { if (LocationOfBeginConstant < 0) LocationOfBeginConstant = CurrentIndex; CurrentIndex--; } else { // Not at a minimum yet...keep looking LocationOfBeginConstant = -1; CurrentIndex--; } break; case UnravelingFinalCurve: peakValueLeft = Data->Value (CurrentIndex); convolutionReversal = (NewConvolution > CurrentConvolution); slopeReversal = (currentSlope <= 0.0); peakValueNegative = (peakValueLeft < 0.0); if (CurrentIndex >= 1) foundLocalMin = (peakValueLeft <= Data->Value (CurrentIndex - 1)); else foundLocalMin = false; if (slopeReversal || foundLocalMin || peakValueNegative) { LocationOfBeginConstant = -1; if (peakValueNegative) CurrentIndex--; return dataInterval; } if (convolutionReversal) { CurrentIndex++; return dataInterval; } CurrentIndex--; break; } /*PreviousConvolution = CurrentConvolution; CurrentConvolution = NewConvolution;*/ // CurrentIndex--; //??????????????????????? /*OldLeft = newL; OldRight = newR; WindowLeft--; WindowRight--;*/ nPoints++; } if ((SearchMode == LookingForFinalMin) || (SearchMode == UnravelingFinalCurve)) { LocationOfLastMin = CurrentIndex; PeakLeft = CurrentIndex; peakValueLeft = Data->Value (PeakLeft); dataInterval = new DataInterval (PeakLeft, PeakCenter, PeakRight); dataInterval->SetHeight (PeakHeight); dataInterval->SetMass (PeakMass); dataInterval->SetNumberOfMinima (0); dataInterval->SetMode (currentMode); dataInterval->SetMaxAtMode (currentMaxAtMode); dataInterval->SetLeftMinimum (peakValueLeft); dataInterval->SetRightMinimum (Data->Value (PeakRight)); /*PreviousConvolution = CurrentConvolution; CurrentConvolution = NewConvolution;*/ CurrentIndex--; /*OldLeft = newL; OldRight = newR; WindowLeft--; WindowRight--;*/ LocationOfBeginConstant = -1; if (print) { text << "Found data interval with left = " << PeakLeft << ", right = " << PeakRight << " and center = " << PeakCenter << endLine; text << " Value at center = " << Data->Value (PeakCenter) << endLine; text << " Convolution = " << PeakMass << endLine; } return dataInterval; } return NULL; }