////////////////////////////////////////////////////////////////////////
//
// ScoreMatrix.h - a collection of classes for scoreMatrices
//
// $Id: ScoreMatrix.C,v 1.4 2002/01/20 10:51:37 goetz Exp $
//
////////////////////////////////////////////////////////////////////////

#include "ScoreMatrix.h"

int EditDistMatrix::sc(const Alchar &a1, const Alchar &a2) const
{
  if (a1.isGap() && a2.isGap() )
    return 0;
  else if (a1.isGap() || a2.isGap()) 
    return -2; // gap penalty
  else if (a1.c == a2.c)
    return 1;  // match
  else 
    return -1; // mismatch
}

int PredefScore::sc(const Alchar &a1, const Alchar &a2) const
{
  const char firstchar('A'); // first capital letter in alphabet 
  
  // first, hande gaps separately:
  if (a1.isGap() && a2.isGap())
    return 0;
  else if (a1.isGap() || a2.isGap())
    return gap;
  else { // no gaps involved
    // tmp vars: chars converted to upper chars and then indices of matrix
    char c1(toupper(a1.c)-firstchar), c2(toupper(a2.c)-firstchar);
    // report characters out of range:
    assert( (c1 >= 0) && (c1 <= 26) && (c2 >= 0) && (c2 <= 26) );
    // now access to scorematrix is safe:
    return scores[c1][c2];    
  }
}

PredefScore::PredefScore( const short *matr, int gap, const string &name )
  : ScoreMatrix("PredefScore "+name), gap(gap)
{
  init(matr);
}

PredefScore::PredefScore( const short *matr, const string &name )
  : ScoreMatrix("PredefScore "+name)
{
  init(matr);
  gap= gapEst;
}

void PredefScore::init( const short *matr )
{
  const char firstchar('A'); // first capital letter in alphabet 
  // order is used for conversion: i-th amino acid -> letter for it
  const char *order= "ABCDEFGHIKLMNPQRSTVWXYZ";
  // conversion of coordinates in triangle matrix
  int row(0);
  // for estimating the gap penalty
  int summism(0);

  // first initialize to avoid nasty effects ...
  for (int i=0; i < 26; i++)
    for (int j=0; j < 26; j++)
      scores[i][j]= 0;
  
  // convert lower triangle matrix into full matrix
  for (int i=0; i < 23; i++) {
    row= i*(i+1)/2; // determine row in triangle matrix = 1+...+i,
    // since matrix "matr" is one dimensional array containing the
    // whole lower triangle matrix:
    //    00
    //    10 11
    //    20 21 22
    //    30 31 32 33
    //    40 41 ...   -> { 00, 10, 11, 20, 21, 22, 30, 31, 32, 33, ... }

    // symmetric entry on main diagonal first
    scores[ order[i]-firstchar ][ order[i]-firstchar ]= matr[ row + i ];
    // now copy all entries in both upper and lower triangle matrices 
    // of matrix scores simultanously:
    for (int j=0; j < i; j++) {
      // -firstchar is done to map 'A'..'Z' to 0..25
      scores[ order[i]-firstchar ][ order[j]-firstchar ] = 
	scores[ order[j]-firstchar ][ order[i]-firstchar ] = matr[ row + j ];
      // add mismatches to sum
      summism += matr[ row + j ];
    }
  }
  gapEst= summism/253; // 253=(22*23)/2
}
