static void menu_cb_removePoints (RealTierEditor me, EDITOR_ARGS_DIRECT) { Editor_save (me, U"Remove point(s)"); RealTier tier = (RealTier) my data; if (my d_startSelection == my d_endSelection) AnyTier_removePointNear (tier->asAnyTier(), my d_startSelection); else AnyTier_removePointsBetween (tier->asAnyTier(), my d_startSelection, my d_endSelection); RealTierEditor_updateScaling (me); FunctionEditor_redraw (me); Editor_broadcastDataChanged (me); }
double RealTier_getStandardDeviation_curve (RealTier me, double tmin, double tmax) { long n = my points.size, imin, imax; double mean, integral = 0.0; if (tmax <= tmin) { tmin = my xmin; tmax = my xmax; } // autowindow if (n == 0) return NUMundefined; if (n == 1) return 0.0; imin = AnyTier_timeToLowIndex (me->asAnyTier(), tmin); if (imin == n) return 0.0; imax = AnyTier_timeToHighIndex (me->asAnyTier(), tmax); if (imax == 1) return 0.0; Melder_assert (imin < n); Melder_assert (imax > 1); /* * Add the areas between the points. * This works even if imin is 0 (offleft) and/or imax is n + 1 (offright). */ mean = RealTier_getMean_curve (me, tmin, tmax); for (long i = imin; i < imax; i ++) { double tleft, fleft, tright, fright, sum, diff; if (i == imin) { tleft = tmin; fleft = RealTier_getValueAtTime (me, tmin); } else { tleft = my points.at [i] -> number; fleft = my points.at [i] -> value - mean; } if (i + 1 == imax) { tright = tmax; fright = RealTier_getValueAtTime (me, tmax); } else { tright = my points.at [i + 1] -> number; fright = my points.at [i + 1] -> value - mean; } /* * The area is integral dt f^2 * = integral dt [f1 + (f2-f1)/(t2-t1) (t-t1)]^2 * = int dt f1^2 + int dt 2 f1 (f2-f1)/(t2-t1) (t-t1) + int dt [(f2-f1)/(t2-t1)]^2 (t-t1)^2 * = f1^2 (t2-t1) + f1 (f2-f1)/(t2-t1) (t2-t1)^2 + 1/3 [(f2-f1)/(t2-t1)]^2 (t2-t1)^3 * = (t2-t1) [f1 f2 + 1/3 (f2-f1)^2] * = (t2-t1) (f1^2 + f2^2 + 1/3 f1 f2) * = (t2-t1) [1/4 (f1+f2)^2 + 1/12 (f1-f2)^2] * In the last expression, we have a sum of squares, which is computationally best. */ sum = fleft + fright; diff = fleft - fright; integral += (sum * sum + (1.0/3.0) * diff * diff) * (tright - tleft); } return sqrt (0.25 * integral / (tmax - tmin)); }
void RealTier_removePointsBelow (RealTier me, double level) { for (long ipoint = my points.size; ipoint > 0; ipoint --) { RealPoint point = my points.at [ipoint]; if (point -> value < level) { AnyTier_removePoint (me->asAnyTier(), ipoint); } } }
void RealTier_draw (RealTier me, Graphics g, double tmin, double tmax, double fmin, double fmax, int garnish, const char32 *method, const char32 *quantity) { bool drawLines = str32str (method, U"lines") || str32str (method, U"Lines"); bool drawSpeckles = str32str (method, U"speckles") || str32str (method, U"Speckles"); long n = my points.size, imin, imax, i; if (tmax <= tmin) { tmin = my xmin; tmax = my xmax; } Graphics_setWindow (g, tmin, tmax, fmin, fmax); Graphics_setInner (g); imin = AnyTier_timeToHighIndex (me->asAnyTier(), tmin); imax = AnyTier_timeToLowIndex (me->asAnyTier(), tmax); if (n == 0) { } else if (imax < imin) { double fleft = RealTier_getValueAtTime (me, tmin); double fright = RealTier_getValueAtTime (me, tmax); if (drawLines) Graphics_line (g, tmin, fleft, tmax, fright); } else for (i = imin; i <= imax; i ++) { RealPoint point = my points.at [i]; double t = point -> number, f = point -> value; if (drawSpeckles) Graphics_speckle (g, t, f); if (drawLines) { if (i == 1) Graphics_line (g, tmin, f, t, f); else if (i == imin) Graphics_line (g, t, f, tmin, RealTier_getValueAtTime (me, tmin)); if (i == n) Graphics_line (g, t, f, tmax, f); else if (i == imax) Graphics_line (g, t, f, tmax, RealTier_getValueAtTime (me, tmax)); else { RealPoint pointRight = my points.at [i + 1]; Graphics_line (g, t, f, pointRight -> number, pointRight -> value); } } } Graphics_unsetInner (g); if (garnish) { Graphics_drawInnerBox (g); Graphics_textBottom (g, true, my v_getUnitText (0, 0, 0)); Graphics_marksBottom (g, 2, true, true, false); Graphics_marksLeft (g, 2, true, true, false); if (quantity) Graphics_textLeft (g, true, quantity); } }
double RealTier_getMean_points (RealTier me, double tmin, double tmax) { long n = my points.size, imin, imax; double sum = 0.0; if (tmax <= tmin) { tmin = my xmin; tmax = my xmax; } // autowindow n = AnyTier_getWindowPoints (me->asAnyTier(), tmin, tmax, & imin, & imax); if (n == 0) return NUMundefined; for (long i = imin; i <= imax; i ++) sum += my points.at [i] -> value; return sum / n; }
double RealTier_getStandardDeviation_points (RealTier me, double tmin, double tmax) { long n = my points.size, imin, imax; double mean, sum = 0.0; if (tmax <= tmin) { tmin = my xmin; tmax = my xmax; } // autowindow n = AnyTier_getWindowPoints (me->asAnyTier(), tmin, tmax, & imin, & imax); if (n < 2) return NUMundefined; mean = RealTier_getMean_points (me, tmin, tmax); for (long i = imin; i <= imax; i ++) { double diff = my points.at [i] -> value - mean; sum += diff * diff; } return sqrt (sum / (n - 1)); }
double RealTier_getArea (RealTier me, double tmin, double tmax) { long n = my points.size, imin, imax; //RealPoint *points = & my points [0]; if (n == 0) return NUMundefined; if (n == 1) return (tmax - tmin) * my points.at [1] -> value; imin = AnyTier_timeToLowIndex (me->asAnyTier(), tmin); if (imin == n) return (tmax - tmin) * my points.at [n] -> value; imax = AnyTier_timeToHighIndex (me->asAnyTier(), tmax); if (imax == 1) return (tmax - tmin) * my points.at [1] -> value; Melder_assert (imin < n); Melder_assert (imax > 1); /* * Sum the areas between the points. * This works even if imin is 0 (offleft) and/or imax is n + 1 (offright). */ double area = 0.0; for (long i = imin; i < imax; i ++) { double tleft, fleft, tright, fright; if (i == imin) { tleft = tmin; fleft = RealTier_getValueAtTime (me, tmin); } else { tleft = my points.at [i] -> number; fleft = my points.at [i] -> value; } if (i + 1 == imax) { tright = tmax; fright = RealTier_getValueAtTime (me, tmax); } else { tright = my points.at [i + 1] -> number; fright = my points.at [i + 1] -> value; } area += 0.5 * (fleft + fright) * (tright - tleft); } return area; }
double RealTier_getValueAtTime (RealTier me, double t) { long n = my points.size; if (n == 0) return NUMundefined; RealPoint pointRight = my points.at [1]; if (t <= pointRight -> number) return pointRight -> value; // constant extrapolation RealPoint pointLeft = my points.at [n]; if (t >= pointLeft -> number) return pointLeft -> value; // constant extrapolation Melder_assert (n >= 2); long ileft = AnyTier_timeToLowIndex (me->asAnyTier(), t), iright = ileft + 1; Melder_assert (ileft >= 1 && iright <= n); pointLeft = my points.at [ileft]; pointRight = my points.at [iright]; double tleft = pointLeft -> number, fleft = pointLeft -> value; double tright = pointRight -> number, fright = pointRight -> value; return t == tright ? fright // be very accurate : tleft == tright ? 0.5 * (fleft + fright) // unusual, but possible; no preference : fleft + (t - tleft) * (fright - fleft) / (tright - tleft); // linear interpolation }