Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}