Exemplo n.º 1
0
/* eval_kdensity is a modification of eval_bezier */
static double
eval_kdensity ( 
    struct curve_points *cp,
    int first_point,	/* where to start in plot->points (to find x-range) */
    int num_points,	/* to determine end in plot->points */
    double x		/* x value at which to calculate y */
    ) {

    unsigned int i;
    struct coordinate GPHUGE *this_points = (cp->points) + first_point;
  
    double y, Z, ytmp;
    double avg, sigma;
    double bandwidth, default_bandwidth;

    avg = 0.0;
    sigma = 0.0;
    for (i = 0; i < num_points; i++) {
	avg   += this_points[i].x;
	sigma += this_points[i].x * this_points[i].x;
    }
    avg /= (double)num_points;
    sigma = sqrt( sigma/(double)num_points - avg*avg ); /* Standard Deviation */
    
    /* This is the optimal bandwidth if the point distribution is Gaussian.
       (Applied Smoothing Techniques for Data Analysis
       by Adrian W, Bowman & Adelchi Azzalini (1997)) */
    /* If the supplied bandwidth is zero of less, the default bandwidth is used. */
    default_bandwidth = pow( 4.0/(3.0*num_points), 1.0/5.0 )*sigma;
    if (cp->smooth_parameter <= 0) {
	bandwidth = default_bandwidth;
	cp->smooth_parameter = -default_bandwidth;
    } else
	bandwidth = cp->smooth_parameter;

    y = 0;
    for (i = 0; i < num_points; i++) {
	Z = ( x - this_points[i].x )/bandwidth;
	ytmp = this_points[i].y;
	y += AXIS_DE_LOG_VALUE(cp->y_axis,ytmp) * exp( -0.5*Z*Z ) / bandwidth;
    }
    y /= sqrt(2.0*M_PI);

    return y;
}
Exemplo n.º 2
0
static void
do_cubic(
    struct curve_points *plot,	/* still containes old plot->points */
    spline_coeff *sc,		/* generated by cp_tridiag */
    int first_point,		/* where to start in plot->points */
    int num_points,		/* to determine end in plot->points */
    struct coordinate *dest)	/* where to put the interpolated data */
{
    double xdiff, temp, x, y;
    double xstart, xend;	/* Endpoints of the sampled x range */
    int i, l;
    struct coordinate GPHUGE *this_points;

    /* min and max in internal (eg logged) co-ordinates. We update
     * these, then update the external extrema in user co-ordinates
     * at the end.
     */
    double ixmin, ixmax, iymin, iymax;
    double sxmin, sxmax, symin, symax;	/* starting values of above */

    x_axis = plot->x_axis;
    y_axis = plot->y_axis;

    ixmin = sxmin = AXIS_LOG_VALUE(x_axis, X_AXIS.min);
    ixmax = sxmax = AXIS_LOG_VALUE(x_axis, X_AXIS.max);
    iymin = symin = AXIS_LOG_VALUE(y_axis, Y_AXIS.min);
    iymax = symax = AXIS_LOG_VALUE(y_axis, Y_AXIS.max);

    this_points = (plot->points) + first_point;

    l = 0;

    /* HBB 20010727: Sample only across the actual x range, not the
     * full range of input data */
#if SAMPLE_CSPLINES_TO_FULL_RANGE
    xstart = this_points[0].x;
    xend = this_points[num_points - 1].x;
#else
    xstart = GPMAX(this_points[0].x, sxmin);
    xend = GPMIN(this_points[num_points - 1].x, sxmax);

    if (xstart >= xend)
	int_error(plot->token,
		  "Cannot smooth: no data within fixed xrange!");
#endif
    xdiff = (xend - xstart) / (samples_1 - 1);

    for (i = 0; i < samples_1; i++) {
	x = xstart + i * xdiff;

	/* Move forward to the spline interval this point is in */
	while ((x >= this_points[l + 1].x) && (l < num_points - 2))
	    l++;

	/* KB 981107: With logarithmic x axis the values were
         * converted back to linear scale before calculating the
         * coefficients. Use exponential for log x values. */
	temp = AXIS_DE_LOG_VALUE(x_axis, x)
	    - AXIS_DE_LOG_VALUE(x_axis, this_points[l].x);

	/* Evaluate cubic spline polynomial */
	y = ((sc[l][3] * temp + sc[l][2]) * temp + sc[l][1]) * temp + sc[l][0];

	/* With logarithmic y axis, we need to convert from linear to
         * log scale now. */
	if (Y_AXIS.log) {
	    if (y > 0.)
		y = AXIS_DO_LOG(y_axis, y);
	    else
		y = symin - (symax - symin);
	}

	dest[i].type = INRANGE;
	STORE_AND_FIXUP_RANGE(dest[i].x, x, dest[i].type, ixmin, ixmax, X_AXIS.autoscale, NOOP, continue);
	STORE_AND_FIXUP_RANGE(dest[i].y, y, dest[i].type, iymin, iymax, Y_AXIS.autoscale, NOOP, NOOP);

	dest[i].xlow = dest[i].xhigh = dest[i].x;
	dest[i].ylow = dest[i].yhigh = dest[i].y;

	dest[i].z = -1;

    }

    UPDATE_RANGE(ixmax > sxmax, X_AXIS.max, ixmax, x_axis);
    UPDATE_RANGE(ixmin < sxmin, X_AXIS.min, ixmin, x_axis);
    UPDATE_RANGE(iymax > symax, Y_AXIS.max, iymax, y_axis);
    UPDATE_RANGE(iymin < symin, Y_AXIS.min, iymin, y_axis);

}
Exemplo n.º 3
0
/*
 * Calculation of cubic splines
 *
 * This can be treated as a special case of approximation cubic splines, with
 * all weights -> infinity.
 *
 * Returns matrix of spline coefficients
 */
static spline_coeff *
cp_tridiag(struct curve_points *plot, int first_point, int num_points)
{
    spline_coeff *sc;
    tri_diag *m;
    double *r, *x, *h, *xp, *yp;
    struct coordinate GPHUGE *this_points;
    int i;

    x_axis = plot->x_axis;
    y_axis = plot->y_axis;
    if (num_points < 3)
	int_error(plot->token, "Can't calculate splines, need at least 3 points");

    this_points = (plot->points) + first_point;

    sc = gp_alloc((num_points) * sizeof(spline_coeff), "spline matrix");
    m = gp_alloc((num_points - 2) * sizeof(tri_diag), "spline help matrix");

    r = gp_alloc((num_points - 2) * sizeof(double), "spline right side");
    x = gp_alloc((num_points - 2) * sizeof(double), "spline solution vector");
    h = gp_alloc((num_points - 1) * sizeof(double), "spline help vector");

    xp = gp_alloc((num_points) * sizeof(double), "x pos");
    yp = gp_alloc((num_points) * sizeof(double), "y pos");

    /* KB 981107: With logarithmic axis first convert back to linear scale */

    xp[0] = AXIS_DE_LOG_VALUE(x_axis,this_points[0].x);
    yp[0] = AXIS_DE_LOG_VALUE(y_axis,this_points[0].y);
    for (i = 1; i < num_points; i++) {
	xp[i] = AXIS_DE_LOG_VALUE(x_axis,this_points[i].x);
	yp[i] = AXIS_DE_LOG_VALUE(y_axis,this_points[i].y);
	h[i - 1] = xp[i] - xp[i - 1];
    }

    /* set up the matrix and the vector */

    for (i = 0; i <= num_points - 3; i++) {
	r[i] = 3 * ((yp[i + 2] - yp[i + 1]) / h[i + 1]
		    - (yp[i + 1] - yp[i]) / h[i]);

	if (i < 1)
	    m[i][0] = 0;
	else
	    m[i][0] = h[i];

	m[i][1] = 2 * (h[i] + h[i + 1]);

	if (i > num_points - 4)
	    m[i][2] = 0;
	else
	    m[i][2] = h[i + 1];
    }

    /* solve the matrix */
    if (!solve_tri_diag(m, r, x, num_points - 2)) {
	free(h);
	free(x);
	free(r);
	free(m);
	free(xp);
	free(yp);
	int_error(plot->token, "Can't calculate cubic splines");
    }
    sc[0][2] = 0;
    for (i = 1; i <= num_points - 2; i++)
	sc[i][2] = x[i - 1];
    sc[num_points - 1][2] = 0;

    for (i = 0; i <= num_points - 1; i++)
	sc[i][0] = yp[i];

    for (i = 0; i <= num_points - 2; i++) {
	sc[i][1] = (sc[i + 1][0] - sc[i][0]) / h[i]
	    - h[i] / 3 * (sc[i + 1][2] + 2 * sc[i][2]);
	sc[i][3] = (sc[i + 1][2] - sc[i][2]) / 3 / h[i];
    }

    free(h);
    free(x);
    free(r);
    free(m);
    free(xp);
    free(yp);

    return (sc);
}
Exemplo n.º 4
0
/*
 * Calculation of approximation cubic splines
 * Input:  x[i], y[i], weights z[i]
 *
 * Returns matrix of spline coefficients
 */
static spline_coeff *
cp_approx_spline(
    struct curve_points *plot,
    int first_point,		/* where to start in plot->points */
    int num_points)		/* to determine end in plot->points */
{
    spline_coeff *sc;
    five_diag *m;
    double *r, *x, *h, *xp, *yp;
    struct coordinate GPHUGE *this_points;
    int i;

    x_axis = plot->x_axis;
    y_axis = plot->y_axis;

    sc = gp_alloc((num_points) * sizeof(spline_coeff),
				   "spline matrix");

    if (num_points < 4)
	int_error(plot->token, "Can't calculate approximation splines, need at least 4 points");

    this_points = (plot->points) + first_point;

    for (i = 0; i < num_points; i++)
	if (this_points[i].z <= 0)
	    int_error(plot->token, "Can't calculate approximation splines, all weights have to be > 0");

    m = gp_alloc((num_points - 2) * sizeof(five_diag), "spline help matrix");

    r = gp_alloc((num_points - 2) * sizeof(double), "spline right side");
    x = gp_alloc((num_points - 2) * sizeof(double), "spline solution vector");
    h = gp_alloc((num_points - 1) * sizeof(double), "spline help vector");

    xp = gp_alloc((num_points) * sizeof(double), "x pos");
    yp = gp_alloc((num_points) * sizeof(double), "y pos");

    /* KB 981107: With logarithmic axis first convert back to linear scale */

    xp[0] = AXIS_DE_LOG_VALUE(x_axis, this_points[0].x);
    yp[0] = AXIS_DE_LOG_VALUE(y_axis, this_points[0].y);
    for (i = 1; i < num_points; i++) {
	xp[i] = AXIS_DE_LOG_VALUE(x_axis, this_points[i].x);
	yp[i] = AXIS_DE_LOG_VALUE(y_axis, this_points[i].y);
	h[i - 1] = xp[i] - xp[i - 1];
    }

    /* set up the matrix and the vector */

    for (i = 0; i <= num_points - 3; i++) {
	r[i] = 3 * ((yp[i + 2] - yp[i + 1]) / h[i + 1]
		    - (yp[i + 1] - yp[i]) / h[i]);

	if (i < 2)
	    m[i][0] = 0;
	else
	    m[i][0] = 6 / this_points[i].z / h[i - 1] / h[i];

	if (i < 1)
	    m[i][1] = 0;
	else
	    m[i][1] = h[i] - 6 / this_points[i].z / h[i] * (1 / h[i - 1] + 1 / h[i])
		- 6 / this_points[i + 1].z / h[i] * (1 / h[i] + 1 / h[i + 1]);

	m[i][2] = 2 * (h[i] + h[i + 1])
	    + 6 / this_points[i].z / h[i] / h[i]
	    + 6 / this_points[i + 1].z * (1 / h[i] + 1 / h[i + 1]) * (1 / h[i] + 1 / h[i + 1])
	    + 6 / this_points[i + 2].z / h[i + 1] / h[i + 1];

	if (i > num_points - 4)
	    m[i][3] = 0;
	else
	    m[i][3] = h[i + 1] - 6 / this_points[i + 1].z / h[i + 1] * (1 / h[i] + 1 / h[i + 1])
		- 6 / this_points[i + 2].z / h[i + 1] * (1 / h[i + 1] + 1 / h[i + 2]);

	if (i > num_points - 5)
	    m[i][4] = 0;
	else
	    m[i][4] = 6 / this_points[i + 2].z / h[i + 1] / h[i + 2];
    }

    /* solve the matrix */
    if (!solve_five_diag(m, r, x, num_points - 2)) {
	free(h);
	free(x);
	free(r);
	free(m);
	free(xp);
	free(yp);
	int_error(plot->token, "Can't calculate approximation splines");
    }
    sc[0][2] = 0;
    for (i = 1; i <= num_points - 2; i++)
	sc[i][2] = x[i - 1];
    sc[num_points - 1][2] = 0;

    sc[0][0] = yp[0] + 2 / this_points[0].z / h[0] * (sc[0][2] - sc[1][2]);
    for (i = 1; i <= num_points - 2; i++)
	sc[i][0] = yp[i] - 2 / this_points[i].z *
	    (sc[i - 1][2] / h[i - 1]
	     - sc[i][2] * (1 / h[i - 1] + 1 / h[i])
	     + sc[i + 1][2] / h[i]);
    sc[num_points - 1][0] = yp[num_points - 1]
	- 2 / this_points[num_points - 1].z / h[num_points - 2]
	* (sc[num_points - 2][2] - sc[num_points - 1][2]);

    for (i = 0; i <= num_points - 2; i++) {
	sc[i][1] = (sc[i + 1][0] - sc[i][0]) / h[i]
	    - h[i] / 3 * (sc[i + 1][2] + 2 * sc[i][2]);
	sc[i][3] = (sc[i + 1][2] - sc[i][2]) / 3 / h[i];
    }

    free(h);
    free(x);
    free(r);
    free(m);
    free(xp);
    free(yp);

    return (sc);
}