Пример #1
0
void scantwo_1chr_em(int n_ind, int n_pos, int n_gen, 
		     double *****Pairprob, double **Addcov, int n_addcov, 
		     double **Intcov, int n_intcov, double *pheno, 
		     double *weights,
		     double **Result, int maxit, double tol, int verbose,
		     int n_col2drop, int *col2drop)
{
  int error_flag, i, i1, i2, k1, k2, j, m, n_col[2], n_col_rev[2], nit[2], r, flag=0;
  double *param, *oldparam, ***Wts12, **Wts1, **Wts2;
  double *wts, *work1, *work2, temp, ***Probs, oldllik=0.0, llik[2], sw;
  int *allcol2drop;

  n_col[0] = (2*n_gen-1) + n_addcov + 2*(n_gen-1)*n_intcov;
  n_col[1] = n_gen*n_gen + n_addcov + (n_gen*n_gen-1)*n_intcov;

  /* expand col2drop */
  if(n_col2drop) {
    allocate_int(n_col[1], &allcol2drop);
    expand_col2drop(n_gen, n_addcov, n_intcov, 
		    col2drop, allcol2drop);
  }

  /* revised numbers of parameters */
  if(n_col2drop) {
    n_col_rev[0] = 0;
    for(i=0; i<n_col[0]; i++) 
      if(!allcol2drop[i]) n_col_rev[0]++;
    n_col_rev[1] = n_col_rev[0];
    for(i=n_col[0]; i<n_col[1]; i++)
      if(!allcol2drop[i]) n_col_rev[1]++;
  }
  else {
    n_col_rev[0] = n_col[0];
    n_col_rev[1] = n_col[1];
  }

  /* allocate workspaces */
  wts = (double *)R_alloc(2*n_gen*(n_gen+1)*n_ind, sizeof(double));
  reorg_errlod(n_ind, n_gen, wts, &Wts1);
  reorg_errlod(n_ind, n_gen, wts+n_gen*n_ind, &Wts2);
  reorg_genoprob(n_ind, n_gen, n_gen, wts+2*n_gen*n_ind, &Wts12);
  reorg_genoprob(n_ind, n_gen, n_gen, wts+n_gen*(n_gen+2)*n_ind, &Probs);
  work1 = (double *)R_alloc(n_col[1]*n_col[1], sizeof(double));
  work2 = (double *)R_alloc(n_col[1], sizeof(double));
  param = (double *)R_alloc(n_col[1]+1, sizeof(double));
  oldparam = (double *)R_alloc(n_col[1]+1, sizeof(double));
  
  /* recenter phenotype to have mean 0, for 
     possibly increased numerical stability */
  for(j=0, temp=0.0; j<n_ind; j++) temp += pheno[j];
  temp /= (double)n_ind;
  for(j=0; j<n_ind; j++) pheno[j] -= temp;

  /* adjust phenotypes and covariates with weights */
  /* Note: weights are actually sqrt(weights) */
  sw = 0.0;
  for(i=0; i<n_ind; i++) {
    pheno[i] *= weights[i];
    for(j=0; j<n_addcov; j++) Addcov[j][i] *= weights[i];
    for(j=0; j<n_intcov; j++) Intcov[j][i] *= weights[i];
    sw += log(weights[i]);   /* sum of log weights */
  }
  sw /= log(10.0); /* make log 10 */

  /* begin loop over pairs of positions */
  for(i1=0; i1<n_pos-1; i1++) {
    for(i2=i1+1; i2<n_pos; i2++) { /* loop over positions */
      nit[0] = nit[1] = 0;
      llik[0] = llik[1] = NA_REAL;

      /* copy the parts from Pairprob into Probs */
      for(j=0; j<n_ind; j++) 
	for(k1=0; k1<n_gen; k1++)
	  for(k2=0; k2<n_gen; k2++)
	    Probs[k1][k2][j] = Pairprob[k1][k2][i1][i2][j];

      for(m=0; m<2; m++) { /* loop over add've model and full model */
	/* initial estimates */
	for(j=0; j<n_ind; j++) {
	  for(k1=0; k1<n_gen; k1++) {
	    Wts1[k1][j] = Wts2[k1][j] = 0.0;
	    for(k2=0; k2<n_gen; k2++) {
	      Wts1[k1][j] += Probs[k1][k2][j];
	      Wts2[k1][j] += Probs[k2][k1][j];
	    }
	  }
	}
	scantwo_em_mstep(n_ind, n_gen, n_gen, Addcov, n_addcov, 
			 Intcov, n_intcov, pheno, weights, Probs, Wts1, Wts2,
			 oldparam, m, work1, work2, &error_flag,
			 n_col2drop, allcol2drop, verbose);

	if(error_flag) {
	  if(verbose>1) 
	    Rprintf("   [%3d %3d] %1d: Initial model had error.\n",
		    i1+1, i2+1, m+1);
	}
	else { /* only proceed if there's no error */
	  oldllik = scantwo_em_loglik(n_ind, n_gen, n_gen, Probs, Wts12, 
				      Wts1, Wts2, Addcov, n_addcov, Intcov, 
				      n_intcov, pheno, weights, oldparam, m,
				      n_col2drop, allcol2drop);

	  if(verbose>2) 
	    Rprintf("   [%3d %3d] %1d %9.3lf\n", 
		    i1+1, i2+1, m+1, oldllik);
	
	  for(r=0; r<maxit; r++) { /* loop over iterations */
	    R_CheckUserInterrupt(); /* check for ^C */

	    scantwo_em_estep(n_ind, n_gen, n_gen, Probs, Wts12, 
			     Wts1, Wts2, Addcov, n_addcov, Intcov, 
			     n_intcov, pheno, weights, oldparam, m, 1,
			     n_col2drop, allcol2drop);

	    scantwo_em_mstep(n_ind, n_gen, n_gen, Addcov, n_addcov, 
			     Intcov, n_intcov, pheno, weights, Wts12, Wts1, 
			     Wts2, param, m, work1, work2, &error_flag,
			     n_col2drop, allcol2drop, verbose);
	    if(error_flag) {
	      flag=0;
	      if(verbose>1)
		Rprintf("   [%3d %3d] %1d %4d: Error in mstep\n",
			i1+1, i2+1, m+1, r+1);
	      break;
	    }

	    llik[m] = scantwo_em_loglik(n_ind, n_gen, n_gen, Probs, Wts12, 
					Wts1, Wts2, Addcov, n_addcov, Intcov, 
					n_intcov, pheno, weights, param, m,
					n_col2drop, allcol2drop);

	    if(verbose>1) { /* print log likelihood */
	      if(verbose>2) 
		Rprintf("   [%3d %3d] %1d %4d %9.6lf\n", 
			i1+1, i2+1, m+1, r+1, (llik[m]-oldllik));
	      if(llik[m] < oldllik-tol) 
		Rprintf("** [%3d %3d] %1d %4d %9.6lf **\n",
			i1+1, i2+1, m+1, r+1, (llik[m]-oldllik));

	      if(verbose>3) { /* print parameters */
		for(j=0; j<n_col_rev[m]; j++) 
		  Rprintf(" %7.3lf", param[j]);
		Rprintf("\n");
	      }
	    }
	    
	    flag = 1;
	    /* use log likelihood only to check for convergence */
	    if(llik[m]-oldllik < tol) { 
	      flag = 0; 
	      break; 
	    }

	    oldllik = llik[m];
	    for(j=0; j<n_col[m]+1; j++) oldparam[j] = param[j];

	  } /* loop over EM iterations */
	  nit[m] = r+1;
	  if(flag) {
	    if(verbose>1)
	      Rprintf("** [%3d %3d] %1d Didn't converge! **\n",
		      i1+1, i2+1, m+1);
	    warning("Didn't converge!\n");
	  }

	} /* no error in getting initial estimates */
      } /* loop over model */ 


      if(verbose>1) { /* print likelihoods */
	Rprintf("   [%3d %3d]   %4d %4d    %9.6lf", 
		i1+1, i2+1, nit[0], nit[1], llik[1]-llik[0]);
	if(llik[1] < llik[0]) Rprintf(" ****");
	Rprintf("\n");
      }

      Result[i2][i1] = -(llik[0]+sw);
      Result[i1][i2] = -(llik[1]+sw); /* sw = sum[log10(weights)] */

    } /* position 2 */
  } /* position 1 */
}
Пример #2
0
void scantwo_imp(int n_ind, int same_chr, int n_pos1, int n_pos2, 
		 int n_gen1, int n_gen2, int n_draws, int ***Draws1, 
		 int ***Draws2, double **Addcov, int n_addcov, 
		 double **Intcov, int n_intcov, double *pheno, int nphe,
		 double *weights, double *result, int n_col2drop,
		 int *col2drop)
{

  /* create local variables */
  int i, i1, i2, j, k; /* loop variants */
  double **lrss0, **lrss1, **LODfull, **LODadd,*lod_tmp;
  double *dwork_null, *dwork_add, *dwork_full, *tmppheno, dtmp;
  int nrss, n_col_null, n_col_a, n_col_f, n_gen_sq, idx;
  int lwork, nlod_per_draw, multivar=0;
  int *allcol2drop;

  /* if number of pheno is 1 or do multivariate model, 
  we have only one rss at each position. Otherwise, 
  we have one rss for each phenotype */
  if( (nphe==1) || (multivar==1) )
    nrss = 1;
  else
    nrss = nphe;

  /* constants */
  n_gen_sq = n_gen1*n_gen2;
  /* number of columns of X for null model */
  n_col_null = 1 + n_addcov;
  /* number of columns of X for additive model */
  n_col_a = (n_gen1+n_gen2-1) + n_addcov + n_intcov*(n_gen1+n_gen2-2);
  /* number of columns of X for full model */
  n_col_f = n_gen_sq + n_addcov + n_intcov*(n_gen_sq-1);

  /* expand col2drop */
  if(n_col2drop) {
    allocate_int(n_col_f, &allcol2drop);
    expand_col2drop(n_gen1, n_addcov, n_intcov, 
		    col2drop, allcol2drop);
  }

  /*********************
   * allocate memory
   *********************/
  tmppheno = (double *)R_alloc(n_ind*nphe, sizeof(double));
  /* for rss' and lod scores - we might not need all of this memory */
  lrss0 = (double **)R_alloc(n_draws, sizeof(double*));
  lrss1 = (double **)R_alloc(n_draws, sizeof(double*));
  LODadd = (double **)R_alloc(n_draws, sizeof(double*));
  LODfull = (double **)R_alloc(n_draws, sizeof(double*));
  for(i=0; i<n_draws; i++) {
    lrss0[i] = (double *)R_alloc(nrss, sizeof(double));
    lrss1[i] = (double *)R_alloc(2*nrss, sizeof(double));
    LODadd[i] = (double *)R_alloc(nrss, sizeof(double));
    LODfull[i] = (double *)R_alloc(nrss, sizeof(double));
  }

  /* the working arrays for the calling of dgelss */
  /* allocate memory */
  /* for null model */
  lod_tmp = (double *)R_alloc(n_draws, sizeof(double));
  lwork = 3*n_col_null + MAX(n_ind, nphe);
  if(multivar == 1) /* request to do multivariate normal model */
    dwork_null = (double *)R_alloc(n_col_null+lwork+2*n_ind*n_col_null+n_ind*nphe+
				   nphe*nphe+n_col_null*nphe,
      sizeof(double));
  else
    dwork_null = (double *)R_alloc(n_col_null+lwork+2*n_ind*n_col_null+n_ind*nphe+n_col_null*nphe,
      sizeof(double));
  /* for additive model */
  lwork = 3*n_col_a + MAX(n_ind, nphe);;
  if(multivar == 1) /* request to do multivariate normal model */
    dwork_add = (double *)R_alloc(n_col_a+lwork+2*n_ind*n_col_a+n_ind*nphe+nphe*nphe+n_col_a*nphe,
      sizeof(double));
  else
    dwork_add = (double *)R_alloc(n_col_a+lwork+2*n_ind*n_col_a+n_ind*nphe+n_col_a*nphe,
      sizeof(double));
  /* for full model */
  lwork = 3*n_col_f + MAX(n_ind, nphe);;
  if(multivar == 1) /* request to do multivariate normal model */
    dwork_full = (double *)R_alloc(n_col_f+lwork+2*n_ind*n_col_f+n_ind*nphe+nphe*nphe+n_col_f*nphe,
      sizeof(double));
  else
    dwork_full = (double *)R_alloc(n_col_f+lwork+2*n_ind*n_col_f+n_ind*nphe+n_col_f*nphe,
      sizeof(double));
  /***************************
   * finish memory allocation
   ***************************/

  /* adjust phenotypes and covariates using weights */
  /* Note: these are actually square-root of weights */
  for(i=0; i<n_ind; i++) {
    for(j=0; j<nphe; j++)     pheno[i+j*n_ind] *= weights[i];
    for(j=0; j<n_addcov; j++) Addcov[j][i] *= weights[i];
    for(j=0; j<n_intcov; j++) Intcov[j][i] *= weights[i];
  }

  /* Note that lrss0 is the log10(RSS) for model E(Yi) = b0;
     lrss_add is the log10(RSS) for model 
                 E(Yi) = b0 + b1*q1 + b2*q2;
     lrss_full is the log10(RSS) for model 
                 E(Yi) = b0 + b1*q1 + b2*q2 + b3*(q1*q2); 
     Additive and interactive covariates are included (if any) */

  dtmp = (double)n_ind/2.0; /* this will be used in calculating LOD score */

  /* Call nullRss to calculate the RSS for the null model */
  for (i=0; i<n_draws; i++) {
    /* make a copy of phenotypes. I'm doing this because 
       dgelss will destroy the input rhs array */
    memcpy(tmppheno, pheno, n_ind*nphe*sizeof(double));
    nullRss(tmppheno, pheno, nphe, n_ind, Addcov, n_addcov,
      dwork_null, multivar, lrss0[i], weights);
  }

  /* calculate the LOD score for each pair of markers */
  if(same_chr) { /* if the pair is on the same chromesome */
    /* number of lod scores per draw */
    nlod_per_draw = n_pos1 * n_pos1;
    for(i1=0; i1<n_pos1-1; i1++) {
      for (i2=i1+1; i2<n_pos1; i2++) {
	for(j=0; j<n_draws; j++) { /* loop over imputations */
	  R_CheckUserInterrupt(); /* check for ^C */

          /* calculate rss */
          memcpy(tmppheno, pheno, n_ind*nphe*sizeof(double));
          altRss2(tmppheno, pheno, nphe, n_ind, n_gen1, n_gen1, Draws1[j][i1],
		  Draws1[j][i2], Addcov, n_addcov, Intcov, n_intcov,
		  lrss1[j], dwork_add, dwork_full, multivar, weights,
		  n_col2drop, allcol2drop);

	  /* calculate 2 different LOD scores */
          for(k=0; k<nrss; k++) {
            LODadd[j][k] = dtmp*(lrss0[j][k]-lrss1[j][k]);
            LODfull[j][k] = dtmp*(lrss0[j][k]-lrss1[j][k+nrss]);
          }
	}
        /* calculate the weight average on the two LOD score vector
        and fill the result matrix */
        if(n_draws > 1) {
          for(k=0; k<nrss; k++) { /* loop for phenotypes */
            /* for full model LOD */                                            
            for(j=0; j<n_draws; j++)
              lod_tmp[j] = LODfull[j][k];                                       
            result[k*nlod_per_draw+i1*n_pos2+i2] = wtaverage(lod_tmp, n_draws); 
            /* for epistasis LOD */
            for(j=0; j<n_draws; j++)  
              lod_tmp[j] = LODadd[j][k];
            result[k*nlod_per_draw+i2*n_pos1+i1] = wtaverage(lod_tmp, n_draws);
          }
        }
        else { /* only one draw */
          for(k=0;k<nrss; k++) {
	    result[k*nlod_per_draw+i1*n_pos2+i2] = LODfull[0][k];
            result[k*nlod_per_draw+i2*n_pos1+i1] = LODadd[0][k];
          }
        }

      } /* end loop over position 1 */
    } /* end loop over position 2 */
  }

  else { /* the pair is for different chromesome */
    nlod_per_draw = n_pos1*n_pos2;
    idx = n_pos1*n_pos2;
    for(i1=0; i1<n_pos1; i1++) { /* loop over markers on chr 1 */
      for(i2=0; i2<n_pos2; i2++) { /* loop over markers on chr 2 */
	for(j=0; j<n_draws; j++) { /* loop over imputations */
	  R_CheckUserInterrupt(); /* check for ^C */

	  /* rss for alternative model */
          altRss2(tmppheno, pheno, nphe, n_ind, n_gen1, n_gen2, Draws1[j][i1],
		  Draws2[j][i2], Addcov, n_addcov, Intcov, n_intcov,
		  lrss1[j], dwork_add, dwork_full,multivar, weights,
		  n_col2drop, allcol2drop);
          /* calculate 2 different LOD scores */
          for(k=0; k<nrss; k++) {
            LODadd[j][k] = dtmp*(lrss0[j][k]-lrss1[j][k]);
            LODfull[j][k] = dtmp*(lrss0[j][k]-lrss1[j][k+nrss]);
          }
	}
        /* calculate the weight average on the two LOD score vector
	   and fill the result matrix */
        if(n_draws > 1) {
          for(k=0; k<nrss; k++) {
            /* for full model LOD */ 
            for(j=0; j<n_draws; j++) 
              lod_tmp[j] = LODfull[j][k];
            result[(k+nrss)*nlod_per_draw+i1*n_pos2+i2] = wtaverage(lod_tmp, n_draws);
            /* for epistasis LOD */
            for(j=0; j<n_draws; j++)  
              lod_tmp[j] = LODadd[j][k];
            result[k*nlod_per_draw+i2*n_pos1+i1] = wtaverage(lod_tmp, n_draws);
          }
        }
        else { /* only one draw */
          for(k=0;k<nrss; k++) {
	    result[(k+nrss)*nlod_per_draw+i1*n_pos2+i2] = LODfull[0][k]; 
            result[k*nlod_per_draw+i2*n_pos1+i1] = LODadd[0][k];
          }
        }
      } /* end loop over chromesome 2 */
    } /* end loop over chromesome 1 */
  } 
  /* end of scantwo_imp() */
}
Пример #3
0
void scantwo_1chr_hk(int n_ind, int n_pos, int n_gen, double ***Genoprob,
                     double *****Pairprob, double **Addcov, int n_addcov,
                     double **Intcov, int n_intcov, double *pheno, int nphe,
                     double *weights, double ***Result, int n_col2drop,
                     int *col2drop)
{
    int n_col_a, n_col_f, n_gen_sq, multivar=0, rank=0, n_col_a_temp, n_col_f_temp;
    int itmp, i, i2, j, k, k2, k3, s, nrss, lwork, info, ind_idx;
    /* additive model working arrays */
    /*  double *dwork_add, *x_add, *x_bk_add, *singular_add, *work_add,
     *yfit_add, *coef_add; */
    /* full model working arrays */
    /*  double *dwork_full, *x_full, *x_bk_full, *singular_full, *work_full,
     *yfit_full, *coef_full;*/
    double *dwork, *x, *x_bk, *singular, *work, *yfit, *coef, *tmppheno;
    double tol=TOL, dtmp=0;
    int *allcol2drop;

    /* number of rss */
    if( (nphe==1) || (multivar==1) )
        nrss = 1;
    else
        nrss = nphe;

    /* tolerance for linear regression */
    tol = TOL;

    n_gen_sq = n_gen*n_gen;
    /* no. param in additive QTL model */
    n_col_a = (n_gen*2-1)+n_addcov+n_intcov*(n_gen-1)*2;
    /* no. param full model */
    n_col_f = n_gen_sq+n_addcov+n_intcov*(n_gen_sq-1);

    /* expand col2drop */
    if(n_col2drop) {
        allocate_int(n_col_f, &allcol2drop);
        expand_col2drop(n_gen, n_addcov, n_intcov,
                        col2drop, allcol2drop);
    }

    /* allocate space and set things up - I will leave multivariate model at this time */
    tmppheno = (double *)R_alloc(n_ind*nphe, sizeof(double));

    /* for full model */
    lwork = 3*n_col_f + MAX(n_ind, nphe);;
    if(multivar == 1) /* request to do multivariate normal model */
        dwork = (double *)R_alloc(n_col_f+lwork+2*n_ind*n_col_f+n_ind*nphe+nphe*nphe+n_col_f*nphe,
                                  sizeof(double));
    else
        dwork = (double *)R_alloc(n_col_f + lwork + 2*n_ind*n_col_f + n_ind*nphe + n_col_f*nphe,
                                  sizeof(double));
    /* split memory block */
    lwork = 3*n_col_f + MAX(n_ind, nphe);
    singular = dwork;
    work = singular + n_col_f;
    x = work + lwork;
    x_bk = x + n_ind*n_col_f;
    yfit = x_bk + n_ind*n_col_f;
    coef =  yfit + n_ind*nphe;

    /***************************
     * finish memory allocation
     ***************************/

    /* modify pheno, Addcov and Intcov with weights */
    for(i=0; i<n_ind; i++) {
        for(j=0; j<nphe; j++) pheno[i+j*n_ind] *= weights[i];
        for(j=0; j<n_addcov; j++) Addcov[j][i] *= weights[i];
        for(j=0; j<n_intcov; j++) Intcov[j][i] *= weights[i];
    }

    for(i=0; i<n_pos-1; i++) {
        for(i2=i+1; i2<n_pos; i2++) { /* loop over pairs of positions */

            R_CheckUserInterrupt(); /* check for ^C */

            /* ADDITIVE MODEL */
            rank = n_col_a;
            /* fill up X matrix */
            for(j=0; j<n_ind; j++) {
                for(k=0, s=0; k<n_gen; k++, s++) /* QTL 1 */
                    x[j+s*n_ind] = Genoprob[k][i][j]*weights[j];  /* s keeps track of column */
                for(k=0; k<n_gen-1; k++,s++) /* QTL 2 */
                    x[j+s*n_ind] = Genoprob[k][i2][j]*weights[j];
                for(k=0; k<n_addcov; k++, s++) /* additive covariates */
                    x[j+s*n_ind] = Addcov[k][j];
                for(k2=0; k2<n_intcov; k2++) {
                    for(k=0; k<n_gen-1; k++, s++) /* interactive x QTL 1 */
                        x[j+s*n_ind] = Genoprob[k][i][j]*Intcov[k2][j];
                    for(k=0; k<n_gen-1; k++, s++) /* interactive x QTL 2 */
                        x[j+s*n_ind] = Genoprob[k][i2][j]*Intcov[k2][j];
                }
            }

            /* drop cols */
            n_col_a_temp = n_col_a;
            if(n_col2drop)
                dropcol_x(&n_col_a_temp, n_ind, allcol2drop, x);
            rank = n_col_a_temp;

            /* linear regression of phenotype on QTL genotype probabilities */
            /* make a copy of x matrix, we may need it */
            memcpy(x_bk, x, n_ind*n_col_a_temp*sizeof(double));

            /* copy pheno to tmppheno, because dgelss will destroy
               the input pheno array */
            memcpy(tmppheno, pheno, n_ind*nphe*sizeof(double));
            /* Call LAPACK engine DGELSS to do linear regression.
               Note that DGELSS doesn't have the assumption that X is full rank. */
            /* Pass all arguments to Fortran by reference */
            mydgelss (&n_ind, &n_col_a_temp, &nphe, x, x_bk, pheno, tmppheno,
                      singular, &tol, &rank, work, &lwork, &info);

            /*
              F77_CALL(dqrls)(x, &n_ind, &n_col_a, pheno, &ny, &tol, coef, resid,
              qty, &k, jpvt, qraux, work);*/
            /* RSS */
            /* calculate residual sum of squares */
            if(nphe == 1) { /*only one phenotype */
                /* if the design matrix is full rank */
                if(rank == n_col_a_temp) {
                    for (itmp=rank, dtmp=0.0; itmp<n_ind; itmp++)
                        dtmp += tmppheno[itmp]*tmppheno[itmp];
                }
                else {
                    /* the design matrix is not full rank, this is trouble */
                    /* calculate the fitted value */
                    matmult(yfit, x_bk, n_ind, n_col_a_temp, tmppheno, 1);
                    /* calculate rss */
                    for (itmp=0, dtmp=0.0; itmp<n_ind; itmp++)
                        dtmp += (pheno[itmp]-yfit[itmp]) * (pheno[itmp]-yfit[itmp]);
                }
                Result[0][i2][i] = log10(dtmp);
            }
            else { /* multiple phenotypes */
                if(multivar == 1) { /* multivariate model, I will leave it now */
                }
                else{
                    if(rank == n_col_a_temp) { /* design matrix is of full rank, this is easier */
                        for(itmp=0, ind_idx=0; itmp<nrss; itmp++, ind_idx+=n_ind) { /* loop thru phenotypes */
                            for(j=rank, dtmp=0.0; j<n_ind; j++)
                                dtmp += tmppheno[ind_idx+j] * tmppheno[ind_idx+j];
                            Result[itmp][i2][i] = log10(dtmp);
                        }
                    }
                    else { /* design matrix is singular, this is troubler */
                        /* note that the result tmppheno has dimension n_ind x nphe,
                           the first ncolx rows contains the estimates. */
                        for (itmp=0; itmp<nphe; itmp++)
                            memcpy(coef+itmp*n_col_a_temp, tmppheno+itmp*n_ind, n_col_a_temp*sizeof(double));
                        /* calculate yfit */
                        matmult(yfit, x_bk, n_ind, n_col_a_temp, coef, nphe);
                        /* calculate residual, put the result in tmppheno */
                        for (itmp=0; itmp<n_ind*nphe; itmp++)
                            tmppheno[itmp] = pheno[itmp] - yfit[itmp];
                        for(itmp=0; itmp<nrss; itmp++) { /* loop thru phenotypes */
                            ind_idx = itmp*n_ind;
                            for(j=0, dtmp=0.0; j<n_ind; j++)
                                dtmp += tmppheno[ind_idx+j] * tmppheno[ind_idx+j];
                            Result[itmp][i2][i] = log10(dtmp);
                        }
                    }
                }
            }

            /* INTERACTIVE MODEL */
            rank = n_col_f;
            /* fill up X matrix */
            for(j=0; j<n_ind; j++) {
                for(k=0, s=0; k<n_gen; k++, s++) /* QTL 1 */
                    x[j+s*n_ind] = Genoprob[k][i][j]*weights[j];  /* s keeps track of column */

                for(k=0; k<n_gen-1; k++,s++) /* QTL 2 */
                    x[j+s*n_ind] = Genoprob[k][i2][j]*weights[j];

                for(k=0; k<n_addcov; k++, s++) /* additive covariates */
                    x[j+s*n_ind] = Addcov[k][j];

                for(k2=0; k2<n_intcov; k2++) {
                    for(k=0; k<n_gen-1; k++,s++) /* interactive x QTL 1 */
                        x[j+s*n_ind] = Genoprob[k][i][j]*Intcov[k2][j];

                    for(k=0; k<n_gen-1; k++,s++) /* interactive x QTL 2 */
                        x[j+s*n_ind] = Genoprob[k][i2][j]*Intcov[k2][j];
                }

                for(k=0; k<n_gen-1; k++)
                    for(k2=0; k2<n_gen-1; k2++,s++) /* QTL 1 x QTL 2 */
                        x[j+s*n_ind] = Pairprob[k][k2][i][i2][j]*weights[j];

                for(k3=0; k3<n_intcov; k3++)
                    for(k=0; k<n_gen-1; k++) /* interactive x QTL 1 x QTL 2 */
                        for(k2=0; k2<n_gen-1; k2++,s++)
                            x[j+s*n_ind] = Pairprob[k][k2][i][i2][j]*Intcov[k3][j];
            }

            /* drop x's */
            n_col_f_temp = n_col_f;
            if(n_col2drop)
                dropcol_x(&n_col_f_temp, n_ind, allcol2drop, x);
            rank = n_col_f_temp;

            /* linear regression of phenotype on QTL genotype probabilities */
            /* make a copy of x matrix, we may need it */
            memcpy(x_bk, x, n_ind*n_col_f_temp*sizeof(double));

            /* copy pheno to tmppheno, because dgelss will destroy
               the input pheno array */
            memcpy(tmppheno, pheno, n_ind*nphe*sizeof(double));

            /* Call LAPACK engine DGELSS to do linear regression.
               Note that DGELSS doesn't have the assumption that X is full rank. */
            /* Pass all arguments to Fortran by reference */
            mydgelss (&n_ind, &n_col_f_temp, &nphe, x, x_bk, pheno, tmppheno,
                      singular, &tol, &rank, work, &lwork, &info);

            /* calculate residual sum of squares */
            if(nphe == 1) { /*only one phenotype */
                /* if the design matrix is full rank */
                if(rank == n_col_f_temp) {
                    for (itmp=rank, dtmp=0.0; itmp<n_ind; itmp++)
                        dtmp += tmppheno[itmp]*tmppheno[itmp];
                }
                else {
                    /* the design matrix is not full rank, this is trouble */
                    /* calculate the fitted value */

                    /*          matmult(yfit, x_bk, n_ind, n_col_f_temp, tmppheno, 1); */
                    matmult(yfit, x_bk, n_ind, n_col_f_temp, tmppheno, 1);

                    /* calculate rss */
                    for (itmp=0, dtmp=0.0; itmp<n_ind; itmp++)
                        dtmp += (pheno[itmp]-yfit[itmp]) * (pheno[itmp]-yfit[itmp]);
                }
                Result[0][i][i2] = log10(dtmp);
            }
            else { /* multiple phenotypes */
                if(multivar == 1) { /* multivariate model */
                }
                else{
                    if(rank == n_col_f_temp) { /* design matrix is of full rank, this is easier */
                        for(itmp=0; itmp<nrss; itmp++) { /* loop thru phenotypes */
                            ind_idx = itmp*n_ind;
                            for(j=rank, dtmp=0.0; j<n_ind; j++)
                                dtmp += tmppheno[ind_idx+j] * tmppheno[ind_idx+j];
                            Result[itmp][i][i2] = log10(dtmp);
                        }
                    }
                    else { /* design matrix is singular, this is troubler */
                        /* note that the result tmppheno has dimension n_ind x nphe,
                           the first ncolx rows contains the estimates. */
                        for (itmp=0; itmp<nphe; itmp++)
                            memcpy(coef+itmp*n_col_f_temp, tmppheno+itmp*n_ind, n_col_f_temp*sizeof(double));
                        /* calculate yfit */
                        matmult(yfit, x_bk, n_ind, n_col_f_temp, coef, nphe);
                        /* calculate residual, put the result in tmppheno */
                        for (itmp=0; itmp<n_ind*nphe; itmp++)
                            tmppheno[itmp] = pheno[itmp] - yfit[itmp];
                        for(itmp=0; itmp<nrss; itmp++) { /* loop thru phenotypes */
                            ind_idx = itmp*n_ind;
                            for(j=0, dtmp=0.0; j<n_ind; j++)
                                dtmp += tmppheno[ind_idx+j] * tmppheno[ind_idx+j];
                            Result[itmp][i][i2] = log10(dtmp);
                        }
                    }
                }
            }

            /* convert to LODs */
            for(itmp=0; itmp < nphe; itmp++) {
                Result[itmp][i2][i] = (double)n_ind/2.0*Result[itmp][i2][i];
                Result[itmp][i][i2] = (double)n_ind/2.0*
                    Result[itmp][i][i2];
            }

        } /* end loop over positions */
    }
}