void oskar_sky_evaluate_gaussian_source_parameters(oskar_Sky* sky,
        int zero_failed_sources, double ra0, double dec0, int* num_failed,
        int* status)
{
    int i, j, num_sources;
    int type;

    /* Check if safe to proceed. */
    if (*status) return;

    /* Return if memory is not on the CPU. */
    if (oskar_sky_mem_location(sky) != OSKAR_CPU)
    {
        *status = OSKAR_ERR_BAD_LOCATION;
        return;
    }

    /* Get data type and number of sources. */
    type = oskar_sky_precision(sky);
    num_sources = oskar_sky_num_sources(sky);

    /* Switch on type. */
    if (type == OSKAR_DOUBLE)
    {
        /* Double precision. */
        const double *ra_, *dec_, *maj_, *min_, *pa_;
        double *I_, *Q_, *U_, *V_, *a_, *b_, *c_;
        double cos_pa_2, sin_pa_2, sin_2pa, inv_std_min_2, inv_std_maj_2;
        double ellipse_a, ellipse_b, maj, min, pa, cos_pa, sin_pa, t;
        double l[ELLIPSE_PTS], m[ELLIPSE_PTS];
        double work1[5 * ELLIPSE_PTS], work2[5 * ELLIPSE_PTS];
        double lon[ELLIPSE_PTS], lat[ELLIPSE_PTS];
        double x[ELLIPSE_PTS], y[ELLIPSE_PTS], z[ELLIPSE_PTS];
        ra_  = oskar_mem_double_const(oskar_sky_ra_rad_const(sky), status);
        dec_ = oskar_mem_double_const(oskar_sky_dec_rad_const(sky), status);
        maj_ = oskar_mem_double_const(oskar_sky_fwhm_major_rad_const(sky), status);
        min_ = oskar_mem_double_const(oskar_sky_fwhm_minor_rad_const(sky), status);
        pa_  = oskar_mem_double_const(oskar_sky_position_angle_rad_const(sky), status);
        I_   = oskar_mem_double(oskar_sky_I(sky), status);
        Q_   = oskar_mem_double(oskar_sky_Q(sky), status);
        U_   = oskar_mem_double(oskar_sky_U(sky), status);
        V_   = oskar_mem_double(oskar_sky_V(sky), status);
        a_   = oskar_mem_double(oskar_sky_gaussian_a(sky), status);
        b_   = oskar_mem_double(oskar_sky_gaussian_b(sky), status);
        c_   = oskar_mem_double(oskar_sky_gaussian_c(sky), status);

        for (i = 0; i < num_sources; ++i)
        {
            /* Note: could do something different from the projection below
             * in the case of a line (i.e. maj or min = 0), as in this case
             * there is no ellipse to project, only two points.
             * -- This continue could then be a if() .. else() instead.
             */
            if (maj_[i] == 0.0 && min_[i] == 0.0) continue;

            /* Evaluate shape of ellipse on the l,m plane. */
            ellipse_a = maj_[i]/2.0;
            ellipse_b = min_[i]/2.0;
            cos_pa = cos(pa_[i]);
            sin_pa = sin(pa_[i]);
            for (j = 0; j < ELLIPSE_PTS; ++j)
            {
                t = j * 60.0 * M_PI / 180.0;
                l[j] = ellipse_a*cos(t)*sin_pa + ellipse_b*sin(t)*cos_pa;
                m[j] = ellipse_a*cos(t)*cos_pa - ellipse_b*sin(t)*sin_pa;
            }
            oskar_convert_relative_directions_to_lon_lat_2d_d(ELLIPSE_PTS,
                    l, m, 0.0, 0.0, lon, lat);

            /* Rotate on the sphere. */
            oskar_convert_lon_lat_to_xyz_d(ELLIPSE_PTS, lon, lat, x, y, z);
            oskar_rotate_sph_d(ELLIPSE_PTS, x, y, z, ra_[i], dec_[i]);
            oskar_convert_xyz_to_lon_lat_d(ELLIPSE_PTS, x, y, z, lon, lat);

            oskar_convert_lon_lat_to_relative_directions_2d_d(
                    ELLIPSE_PTS, lon, lat, ra0, dec0, l, m);

            /* Get new major and minor axes and position angle. */
            oskar_fit_ellipse_d(&maj, &min, &pa, ELLIPSE_PTS, l, m, work1,
                    work2, status);

            /* Check if fitting failed. */
            if (*status == OSKAR_ERR_ELLIPSE_FIT_FAILED)
            {
                if (zero_failed_sources)
                {
                    I_[i] = 0.0;
                    Q_[i] = 0.0;
                    U_[i] = 0.0;
                    V_[i] = 0.0;
                }
                ++(*num_failed);
                *status = 0;
                continue;
            }
            else if (*status) break;

            /* Evaluate ellipse parameters. */
            inv_std_maj_2 = 0.5 * (maj * maj) * M_PI_2_2_LN_2;
            inv_std_min_2 = 0.5 * (min * min) * M_PI_2_2_LN_2;
            cos_pa_2 = cos(pa) * cos(pa);
            sin_pa_2 = sin(pa) * sin(pa);
            sin_2pa  = sin(2.0 * pa);
            a_[i] = cos_pa_2*inv_std_min_2     + sin_pa_2*inv_std_maj_2;
            b_[i] = -sin_2pa*inv_std_min_2*0.5 + sin_2pa *inv_std_maj_2*0.5;
            c_[i] = sin_pa_2*inv_std_min_2     + cos_pa_2*inv_std_maj_2;
        }
    }
    else
    {
        /* Single precision. */
        const float *ra_, *dec_, *maj_, *min_, *pa_;
        float *I_, *Q_, *U_, *V_, *a_, *b_, *c_;
        float cos_pa_2, sin_pa_2, sin_2pa, inv_std_min_2, inv_std_maj_2;
        float ellipse_a, ellipse_b, maj, min, pa, cos_pa, sin_pa, t;
        float l[ELLIPSE_PTS], m[ELLIPSE_PTS];
        float work1[5 * ELLIPSE_PTS], work2[5 * ELLIPSE_PTS];
        float lon[ELLIPSE_PTS], lat[ELLIPSE_PTS];
        float x[ELLIPSE_PTS], y[ELLIPSE_PTS], z[ELLIPSE_PTS];
        ra_  = oskar_mem_float_const(oskar_sky_ra_rad_const(sky), status);
        dec_ = oskar_mem_float_const(oskar_sky_dec_rad_const(sky), status);
        maj_ = oskar_mem_float_const(oskar_sky_fwhm_major_rad_const(sky), status);
        min_ = oskar_mem_float_const(oskar_sky_fwhm_minor_rad_const(sky), status);
        pa_  = oskar_mem_float_const(oskar_sky_position_angle_rad_const(sky), status);
        I_   = oskar_mem_float(oskar_sky_I(sky), status);
        Q_   = oskar_mem_float(oskar_sky_Q(sky), status);
        U_   = oskar_mem_float(oskar_sky_U(sky), status);
        V_   = oskar_mem_float(oskar_sky_V(sky), status);
        a_   = oskar_mem_float(oskar_sky_gaussian_a(sky), status);
        b_   = oskar_mem_float(oskar_sky_gaussian_b(sky), status);
        c_   = oskar_mem_float(oskar_sky_gaussian_c(sky), status);

        for (i = 0; i < num_sources; ++i)
        {
            /* Note: could do something different from the projection below
             * in the case of a line (i.e. maj or min = 0), as in this case
             * there is no ellipse to project, only two points.
             * -- This continue could then be a if() .. else() instead.
             */
            if (maj_[i] == 0.0 && min_[i] == 0.0) continue;

            /* Evaluate shape of ellipse on the l,m plane. */
            ellipse_a = maj_[i]/2.0;
            ellipse_b = min_[i]/2.0;
            cos_pa = cos(pa_[i]);
            sin_pa = sin(pa_[i]);
            for (j = 0; j < ELLIPSE_PTS; ++j)
            {
                t = j * 60.0 * M_PI / 180.0;
                l[j] = ellipse_a*cos(t)*sin_pa + ellipse_b*sin(t)*cos_pa;
                m[j] = ellipse_a*cos(t)*cos_pa - ellipse_b*sin(t)*sin_pa;
            }
            oskar_convert_relative_directions_to_lon_lat_2d_f(ELLIPSE_PTS,
                    l, m, 0.0, 0.0, lon, lat);

            /* Rotate on the sphere. */
            oskar_convert_lon_lat_to_xyz_f(ELLIPSE_PTS, lon, lat, x, y, z);
            oskar_rotate_sph_f(ELLIPSE_PTS, x, y, z, ra_[i], dec_[i]);
            oskar_convert_xyz_to_lon_lat_f(ELLIPSE_PTS, x, y, z, lon, lat);

            oskar_convert_lon_lat_to_relative_directions_2d_f(
                    ELLIPSE_PTS, lon, lat, (float)ra0, (float)dec0, l, m);

            /* Get new major and minor axes and position angle. */
            oskar_fit_ellipse_f(&maj, &min, &pa, ELLIPSE_PTS, l, m, work1,
                    work2, status);

            /* Check if fitting failed. */
            if (*status == OSKAR_ERR_ELLIPSE_FIT_FAILED)
            {
                if (zero_failed_sources)
                {
                    I_[i] = 0.0;
                    Q_[i] = 0.0;
                    U_[i] = 0.0;
                    V_[i] = 0.0;
                }
                ++(*num_failed);
                *status = 0;
                continue;
            }
            else if (*status) break;

            /* Evaluate ellipse parameters. */
            inv_std_maj_2 = 0.5 * (maj * maj) * M_PI_2_2_LN_2;
            inv_std_min_2 = 0.5 * (min * min) * M_PI_2_2_LN_2;
            cos_pa_2 = cos(pa) * cos(pa);
            sin_pa_2 = sin(pa) * sin(pa);
            sin_2pa  = sin(2.0 * pa);
            a_[i] = cos_pa_2*inv_std_min_2     + sin_pa_2*inv_std_maj_2;
            b_[i] = -sin_2pa*inv_std_min_2*0.5 + sin_2pa *inv_std_maj_2*0.5;
            c_[i] = sin_pa_2*inv_std_min_2     + cos_pa_2*inv_std_maj_2;
        }
    }
}
Ejemplo n.º 2
0
TEST(fit_ellipse, test1)
{
    int num_points = 7, status = 0;
    double maj_d = 0.0, min_d = 0.0, pa_d = 0.0;
    float maj_f = 0.0, min_f = 0.0, pa_f = 0.0;

    // Test double precision.
    {
        std::vector<double> x(num_points), y(num_points);
        std::vector<double> work1(5 * num_points), work2(5 * num_points);
        x[0] = -0.1686;
        x[1] = -0.0921;
        x[2] =  0.0765;
        x[3] =  0.1686;
        x[4] =  0.0921;
        x[5] = -0.0765;
        x[6] = -0.1686;

        y[0] =  0.7282;
        y[1] =  0.6994;
        y[2] =  0.6675;
        y[3] =  0.6643;
        y[4] =  0.7088;
        y[5] =  0.7407;
        y[6] =  0.7282;

        oskar_fit_ellipse_d(&maj_d, &min_d, &pa_d, num_points, &x[0], &y[0],
                &work1[0], &work2[0], &status);
        EXPECT_EQ(0, status) << oskar_get_error_string(status);
    }

    // Test single precision.
    {
        std::vector<float> x(num_points), y(num_points);
        std::vector<float> work1(5 * num_points), work2(5 * num_points);
        x[0] = -0.1686;
        x[1] = -0.0921;
        x[2] =  0.0765;
        x[3] =  0.1686;
        x[4] =  0.0921;
        x[5] = -0.0765;
        x[6] = -0.1686;

        y[0] =  0.7282;
        y[1] =  0.6994;
        y[2] =  0.6675;
        y[3] =  0.6643;
        y[4] =  0.7088;
        y[5] =  0.7407;
        y[6] =  0.7282;

        oskar_fit_ellipse_f(&maj_f, &min_f, &pa_f, num_points, &x[0], &y[0],
                &work1[0], &work2[0], &status);
        EXPECT_EQ(0, status) << oskar_get_error_string(status);
    }

    // Compare results.
    EXPECT_NEAR(maj_d, 0.3608619735, 1e-9);
    EXPECT_NEAR(min_d, 0.0494223702, 1e-9);
    EXPECT_NEAR(pa_d, -1.3865537748, 1e-9);
    EXPECT_NEAR(maj_d, maj_f, 1e-5);
    EXPECT_NEAR(min_d, min_f, 1e-5);
    EXPECT_NEAR(pa_d, pa_f, 1e-5);
}