EMAN2
Defines | Functions | Variables
varimax.cpp File Reference
#include <math.h>
#include "varimax.h"
Include dependency graph for varimax.cpp:

Go to the source code of this file.

Defines

#define ROTMAXITER   100
#define ROTEPSILON   1e-5

Functions

float compcrit (float *loadings, int nv, int nf, float lambda)
int varmx (float *aload, int nv, int nf, int method, float *params, float *fnorm, int itmax, float eps, int)
int doRotation (int method, float *aload, int nv, int nf, float *params, float *fnorm, float *knorm, int itmax, float eps, int verbose)

Variables

methodName Methods [NMETHODS]

Define Documentation

#define ROTEPSILON   1e-5

Definition at line 37 of file varimax.cpp.

#define ROTMAXITER   100

Definition at line 33 of file varimax.cpp.


Function Documentation

float compcrit ( float *  loadings,
int  nv,
int  nf,
float  lambda 
)

Definition at line 89 of file varimax.cpp.

Referenced by varmx().

{
        float       crit = 0.0, *loadingj = loadings;
        float       fnv = (float) nv;
        int         i, j;
        
        for (j = 0; j < nf ;j++)
        {
                float       s2 = 0.0;

                for (i = 0;i < nv ;i++)
                {
                        float        sq = loadingj[i]*loadingj[i];

                        s2 += sq;
                        crit += sq*sq;
                }
                crit -= lambda*s2*s2/fnv;
                loadingj += nv;
        } /*for (j = 0;j < nf ;j++)*/

        return (crit);
        
} /*compcrit()*/
int doRotation ( int  method,
float *  aload,
int  nv,
int  nf,
float *  params,
float *  fnorm,
float *  knorm,
int  itmax,
float  eps,
int  verbose 
)

Definition at line 265 of file varimax.cpp.

References IORTHOMAX, IQUARTIMAX, IVARIMAX, sqrt(), and varmx().

{
        int        reply = -1;

        if (method <= IORTHOMAX)
        {
                if (method < IORTHOMAX)
                {
                        if (method == IVARIMAX)
                        {
                                params[0] = 1.0;
                        }
                        else if (method == IQUARTIMAX)
                        {
                                params[0] = 0.0;
                        }
                        else
                        {
                                /* equimax */
                                params[0] = .5f*(float) nf;
                        }
                }
                if (knorm != (float *) 0)
                {
                        int         i, j, k;
                        float       s;

                        for (i = 0; i < nv; i++)
                        {
                                k = i;
                                s = 0.0;
                                for (j = 0; j < nf; j++, k += nv)
                                {
                                        s += aload[k]*aload[k];
                                }
                                knorm[i] = s = (s > 0) ? sqrt(s) : 1.0f;

                                k = i;
                                for (j = 0; j < nf; j++, k += nv)
                                {
                                        aload[k] /= s;
                                }
                        }
                } /*if (fcopy != (float *) 0)*/
                
                reply = varmx(aload, nv, nf, method, params, fnorm, itmax,
                                          eps, verbose);
                if (knorm != (float *) 0)
                {
                        int      i, j, k = 0;
                        
                        for (j = 0; j < nf; j++)
                        {
                                for (i = 0; i < nv; i++, k++)
                                {
                                        aload[k] *= knorm[i];
                                }
                        }
                }
        } /*if (method <= IORTHOMAX)*/
        return (reply);
} /*doRotation()*/
int varmx ( float *  aload,
int  nv,
int  nf,
int  method,
float *  params,
float *  fnorm,
int  itmax,
float  eps,
int   
)

Definition at line 120 of file varimax.cpp.

References b, compcrit(), IORTHOMAX, and t.

Referenced by EMAN::varimax::analyze(), and doRotation().

{
        float         crit, startCrit, fnv = (float) nv;
        float        *aloadj, *aloadk;
        float         denominator, numerator, angl, trot;
        float         eps1 = eps, eps2 = eps;
        float         lambda = 0.0;     //avoid use lambda uninitialized
        int           inoim = 0, ict = 0, irot = 0;
        int           i, j, k, iflip, nf1 = nf - 1;

        if (method <= IORTHOMAX)
        {
                lambda = params[0];
        }

        startCrit = crit = compcrit(aload, nv, nf, lambda);

        do /*while (inoim < 2 && ict < itmax && iflip);*/
        {
                float      oldCrit = crit;

                iflip = 0;
                aloadj = aload;

                for (j = 0;j < nf1 ;j++)
                {
                        aloadk = aloadj + nv;
                        for (k = j + 1;k < nf ;k++)
                        {
                                float      a = 0.0, b = 0.0, c = 0.0, d = 0.0, s = 0.0;
                                
                                for (i = 0;i < nv ;i++)
                                {
                                        float    c2 = aloadj[i]*aloadj[i] - aloadk[i]*aloadk[i];
                                        float    s2 = 2.0f*aloadj[i]*aloadk[i];

                                        a += c2;
                                        b += s2;
                                        c += c2*c2 - s2*s2;
                                        d += c2*s2;
                                } /*for (i = 0;i < nv ;i++)*/

                                denominator = fnv*c + lambda*(b*b - a*a);
                                numerator = 2.0f*(fnv*d - lambda*a*b);

                                if (fabs(numerator) > eps1*fabs(denominator))
                                {
                                        iflip = 1;
                                        irot++;
                                        angl = 0.25f*atan2(numerator,denominator);
                                        
                                        c = cos(angl);
                                        s = sin(angl);
                                        for (i = 0;i < nv ;i++)
                                        {
                                                float   t = c*aloadj[i] + s*aloadk[i];

                                                aloadk[i] = -s*aloadj[i] + c*aloadk[i];
                                                aloadj[i] = t;
                                        } /*for (i = 0;i < nv ;i++)*/
                                } /*if (fabs(numerator) >= eps1*fabs(denominator))*/
                                aloadk += nv;
                        } /*for (k = j + 1;k < nf ;k++)*/
                        aloadj += nv;
                } /*for (j = 0;j < nf1 ;j++)*/
                ict++;

                crit = compcrit(aload, nv, nf, lambda);
                trot = (crit > 0.0f) ? (crit - oldCrit)/crit : 0.0f;
                inoim++;
                if (trot > eps2)
                {
                        inoim = 0;
                }
        } while (inoim < 2 && ict < itmax && iflip);

        if (fnorm != (float *) 0)
        {
                aloadj = aload;
                for (j = 0;j < nf ;j++)
                {
                        float     ssj = 0, sj = 0;
                        
                        for (i = 0;i < nv ;i++)
                        {
                                sj += aloadj[i];
                                ssj += aloadj[i]*aloadj[i];
                        } /*for (i = 0;i < nv ;i++)*/
                        fnorm[j] = ssj;
                        if (sj <= 0.0)
                        {
                                for (i = 0;i < nv ;i++)
                                {
                                        aloadj[i] = -aloadj[i];
                                }
                        } /*if (sj <= 0.0)*/

                        aloadk = aload;
                        for (k = 0;k < j ;k++)
                        {
                                if (fnorm[k] < fnorm[j])
                                {
                                        float       t = fnorm[k];

                                        fnorm[k] = fnorm[j];
                                        fnorm[j] = t;
                                        for (i = 0;i < nv ;i++)
                                        {
                                                t = aloadj[i];
                                                aloadj[i] = aloadk[i];
                                                aloadk[i] = t;
                                        } /*for (i = 0;i < nv ;i++)*/
                                } /*if (fnorm[k] < fnorm[j])*/
                                aloadk += nv;
                        } /*for (k = 0;k < j ;k++)*/
                        aloadj += nv;
                } /*for (j = 0;j < nf ;j++)*/
        } /*if (fnorm != (float *) 0)*/

        /*
        if (verbose)
        {
                char   *outstr = OUTSTR;
                
                outstr += formatChar(outstr, Methods[method].name, CHARASIS);
                outstr += formatChar(outstr, " starting criterion = ", CHARASIS);
                outstr += formatDouble(outstr, startCrit, DODEFAULT | TRIMLEFT);
                outstr += formatChar(outstr, ", final criterion = ", CHARASIS);
                outstr += formatDouble(outstr, crit, DODEFAULT | TRIMLEFT);
                putOUTSTR();
                sprintf(OUTSTR, "%ld iterations and %ld rotations", ict, irot);
                putOUTSTR();
        } if (verbose)*/

        return (ict < itmax);
} /*varmx()*/

Variable Documentation

methodName Methods[NMETHODS]
Initial value:
{
        {"Varimax",    3},
        {"Quartimax",  5},
        {"Equimax",    4},
        {"Orthomax",   5},
        {"Oblimin",    7}
}

Definition at line 44 of file varimax.cpp.