/********************************************************************************************************
 * QRNA - Comparative analysis of biological sequences 
 *         with pair hidden Markov models, pair stochastic context-free
 *        grammars, and probabilistic evolutionary  models.
 *       
 * Version 2.0.3 (MAY 2004)
 *
 * Copyright (C) 2000-2004 Howard Hughes Medical Institute/Washington University School of Medicine
 * All Rights Reserved
 * 
 *     This source code is distributed under the terms of the
 *     GNU General Public License. See the files COPYING and LICENSE
 *     for details.
 ***********************************************************************************************************/

/* evolnullmodel.c
 * 
 *
 * ER, Mon May 17 10:10:29 CDT 2004 [STL, at work with Coro]
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <time.h>

#include "funcs.h"
#include "evolfuncs.h"
#include "globals.h"
#include "squid.h"
#include "structs.h"

/* Function: EvolConstructNullModel()
 * Date:     ER, Mon May 17 10:14:16 CDT 2004 [St. Louis, at work with Coro]
 *
 * Purpose:  Constructs a nullmodel_s
 *
 *           eta = eta_infty + (eta_zero-eta_infty) * exp [- t * log [ (eta-eta_infty)/(eta_zero-eta_infty) ]
 *
 *
 * Args:     otherparam - the list of parameters that define a othermodel           
 *
 * Returns:  (void)
 *           fills all prob's for nullmodel, log2 form 
 *           (allc'ed here, freed by caller)
 */
void
EvolConstructNullModel(struct psubs_s *mutpxy_star, struct nullmodel_s *null, 
		       struct nullparam_s param, struct nullparam_s param_zero, struct nullparam_s param_infty, 
		       double tfactor, double *targetfreq, int changefreq, int verbose)
{
  struct psubs_s *mutpxy_null;
  double          eta_infty;
  double          eta_zero;
  double          eta;

  eta       = param.eta;
  eta_infty = param_infty.eta;
  eta_zero  = param_zero.eta;

  if      (eta_infty <= eta && eta <= eta_zero);
  else if (eta_infty >= eta && eta >= eta_zero);
  else Die ("check your parameters for the Null model. Time zero (%f), star (%f) and infty (%f) \n", eta_zero, eta, eta_infty);
  /*
   * Also check that if eta_zero and eta are equal, then eta_infty is also the same
   */
  if ( eta_zero  - eta < 1-accuracy1 && eta_zero  - eta > -(1-accuracy1) &&
       (eta_infty - eta > 1-accuracy1 || eta_infty - eta < -(1-accuracy1))  )
    Die ("check your parameters for the Null model. Time zero (%f), star (%f) and infty (%f) \n", eta_zero, eta, eta_infty);
  
  
  if (eta_zero - eta_infty > MARGIN || eta_zero - eta_infty < -MARGIN) 
    null->eta  =  eta_infty + (eta_zero-eta_infty) *  EXP2(tfactor*(LOG2((eta-eta_infty)/(eta_zero-eta_infty))));
  else 
    null->eta = eta;
  
  null->meta = 1. - null->eta;
  
  if (null->eta < 0.0 || null->eta > 1.0 )
    Die ("Wrong trnasition probabilities  for the Null model (eta = %f)", null->eta);
  
  /* Calculate emission prob's: null.xem[], null.yem[]
   */
  EvolMutProbs(mutpxy_star, tfactor, &mutpxy_null, targetfreq, changefreq, FALSE, FALSE);
  ConstructXemNullProb(mutpxy_null->P, null->xem);
  ConstructYemNullProb(mutpxy_null->P, null->yem);
  
  if (verbose) 
    PrintMutProbs (mutpxy_null->P, null->xem);

  /* check prob's add up to one
   */
  CheckNullProbs(null);

  /* convert to LOG2 form
   */
  NullToLog2(null);

  /* free memory */
  FreeSubsProbs(mutpxy_null);

}
