void Ltas_fitTiltLine (Ltas me, double fmin, double fmax, bool lnf, int method, double *a, double *b) {
	try {
		if (fmax <= fmin) {
			fmin = my xmin; fmax = my xmax;
		}
		long ifmin, ifmax, numberOfSamples = Sampled_getWindowSamples (me, fmin, fmax, &ifmin, &ifmax);
		if (numberOfSamples < 2) {
			Melder_throw ("There must be at least two data points to fit a line.");
		}
		autoNUMvector<double> x (1, numberOfSamples);
		autoNUMvector<double> y (1, numberOfSamples);
		for (long i = ifmin; i <= ifmax; i++) {
			long ixy = i - ifmin + 1;
			x[ixy] = my x1 + (i - 1) * my dx;
			if (lnf) {
				// For Ltas always x1 > 0
				x[ixy] = log10 (x[ixy]);
			}
			y[ixy] = my z[1][i];
		}
		NUMlineFit (x.peek(), y.peek(), numberOfSamples, a, b, method);
	} catch (MelderError) {
		Melder_throw ("Tilt line not determined.");
	}
}
Exemple #2
0
/* Fit line y = ax+b (lineType ==1) or y = a log(x) + b (lineType == 2) on interval [qmin,qmax]
 * method == 1 : Least squares fit
 * method == 2 : Theil's partial robust fit
 */
void PowerCepstrum_fitTiltLine (PowerCepstrum me, double qmin, double qmax, double *p_a, double *p_intercept, int lineType, int method) {
	try {
		double a, intercept;
		if (qmax <= qmin) {
			qmin = my xmin; qmax = my xmax;
		}

		long imin, imax;
		if (! Matrix_getWindowSamplesX (me, qmin, qmax, & imin, & imax)) {
			return;
		}
		imin = (lineType == 2 && imin == 1) ? 2 : imin; // log(0) is undefined!
		long numberOfPoints = imax - imin + 1;
		if (numberOfPoints < 2) {
			Melder_throw (U"Not enough points for fit.");
		}
		autoNUMvector<double> y (1, numberOfPoints);
		autoNUMvector<double> x (1, numberOfPoints);
		for (long i = 1; i <= numberOfPoints; i++) {
			long isamp = imin + i - 1;
			x[i] = my x1 + (isamp - 1) * my dx;
			if (lineType == 2) {
				x[i] = log (x[i]);
			}
			y[i] = my v_getValueAtSample (isamp, 1, 0);
		}
		if (method == 3) { // try local maxima first
			autoNUMvector<double> ym (1, numberOfPoints / 2 + 1);
			autoNUMvector<double> xm (1, numberOfPoints / 2 + 1);
			long numberOfLocalPeaks = 0;
			// forget y[1] if y[2]<y[1] and y[n] if y[n-1]<y[n] !
			for (long i = 2; i <= numberOfPoints; i++) {
				if (y[i - 1] <= y[i] && y[i] > y[i + 1]) {
					ym[++numberOfLocalPeaks] = y[i];
					xm[numberOfLocalPeaks] = x[i];
				}
			}
			if (numberOfLocalPeaks > numberOfPoints / 10) {
				for (long i = 1; i <= numberOfLocalPeaks; i++) {
					x[i] = xm[i]; y[i] = ym[i];
				}
				numberOfPoints = numberOfLocalPeaks;
			}
			method = 2; // robust fit of peaks
		}
		// fit a straight line through (x,y)'s
		NUMlineFit (x.peek(), y.peek(), numberOfPoints, & a, & intercept, method);
		if (p_intercept) { *p_intercept = intercept; }
		if (p_a) { *p_a = a; }
	} catch (MelderError) {
		Melder_throw (me, U": couldn't fit a line.");
	}
}