/*__*
 *__*
 *__* WEIGHBOR 1.0.1
 *__*
 *__* Copyright (c) 1997-2000 
 *__*    Los Alamos National Laboratories
 *__*    The Rockefeller University
 *__*
 *__* This file is part of the WEIGHBOR program that can be used free of
 *__* charge in academic research and teaching. Any commercial use of
 *__* this software requires prior permission and possibly a license. For
 *__* commercial use contact: W. Bruno at billb@t10.lanl.gov Los Alamos
 *__* National Laboratories makes no representations about the
 *__* suitability of this software for any purpose. It is provided 
 *__* "as is" without express or implied warranty
 *__*	
 *__* For those using this program for research please use the following 
 *__* citation for this program:
 *__*
 *__*    Bruno, W. J., Socci, N. D. and Halpern, A. L., ``Weighted 
 *__*        Neighbor Joining: A Fast Approximation to Maximum-Likelihood
 *__*        Phylogeny Reconstruction,'' Molecular Biology and Evolution, 
 *__*        17(1): 189-197, (2000).
 *__*
 *__* 
 *__*/
/*
  
  \input cnoweb

  Program: weighbor                             \hfill\break
  File: io.c                                    \hfill\break
  Author: N. D. Socci                           \hfill\break
  Created: 6-Feb-97                             \hfill\break
  
  \title{io.c}
  \job{Weighbor}
  
  \synopsis{File I/O Routines}
  

  */

static char version[] = "$Id: io.c,v 1.10 2000/01/12 00:49:33 nds Exp $";


/*

  \section{Introduction}

  These routines handle the basic file i/o for the weighbor
  program. The the expection of the tree printing routines which are
  in the \|tree| module.


  */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "matrix.h"

/*

  \subsection{File opening}
  
  Open a file for reading or writing and do a fp pointer
  check. 

  */

FILE *
openRead(char *filename)
{

  FILE *fp;

  fp = fopen(filename, "r");
  if(!fp)
    {
      fprintf(stderr, "%s could not be open for reading\n", filename);
      perror("weighbor::io::openRead");
      exit(1);
    }

  return(fp);

}

FILE *
openWrite(char *filename)
{

  FILE *fp;

  fp = fopen(filename, "w");
  if(!fp)
    {
      fprintf(stderr, "%s could not be open for writing\n", filename);
      perror("weighbor::io::openWrite");
      exit(1);
    }

  return(fp);

}

/*

  \subsection{Read Data File}

  Read in a Phylip data file. 

  The matrix D is reassigned by this routine so it should not be
  pointing to any allocated memory otherwise that memory will be
  lost.
  
  If there is an error in the file the function prints and error and
  exits the program

  \item\ fp - is a filepointer to the file to read from. Had better not
  be null

  \item\ N - Number of taxz (note this is a pointer to an int)

  \item\ D - The distance matrix $N\times N$; it is automatically
  symmetrized by this routine (again a pointer since we change it in
  this function)

  \item\ names - An array of strings holding the taxa
  names. Memory dynamically allocated be the routine

  */


/*
  print an error and die
  */

void
printError(char *s)
{
  perror("weigbor::io");
  fprintf(stderr, "%s\n", s);
  exit(1);
}


int
readPhylipFile(FILE *fp, int *N, MatrixT *D, char **names[])
{
  
  int i, j;
  double tmp;
  char namebuf[81];
  BooleanT lowerTriag = False;

  if(fscanf(fp, "%d", N)!=1) /* N already a pointer */
    {
      return(0);
    }

  *D = matrix(*N);

  /* allocate N string pointers, note we index from $0\ldots N-1$ */

  *names = (char **)malloc((*N)*sizeof(char *));
  if(!(*names)) printError("File format error-Out of memory");

  for(i=0;i<(*N);++i) {
	int limit = lowerTriag?i+1:(*N);
	
    /* read the taxon name */

    if(fscanf(fp, "%s", namebuf)!=1) printError("File format error-1");

    /* allocate enough memory and move string from tmp buf to name
       array */

    (*names)[i] = (char *)malloc((strlen(namebuf)+1)*sizeof(char));
    if(!((*names)[i])) printError("File format error-Out of memory");
    strcpy((*names)[i], namebuf);
    
    /* read in the $i^{\rm th}$ row */

    for(j=0;j<limit;++j)
      {
		if(fscanf(fp, "%lf", &tmp)!=1) {
		  if(j!=i && j!=i+1) {
			printError("File format error-2");
		  } else {
			lowerTriag = True;
			break;
		  }
		} else 
		  (*D)[i][j] = tmp;
      }

  }

  /* Symmetrize Matrix */
  
  if(lowerTriag = False) {
	for(i=0;i<(*N);++i) 
	  for(j=0;j<(*N);++j)
		if(i!=j) (*D)[i][j] = (*D)[j][i] = .5*((*D)[i][j] + (*D)[j][i]);
  } else {
	for(i=0;i<(*N)-1;++i) 
	  for(j=i+1;j<(*N);++j)
		(*D)[i][j] = (*D)[j][i];
  }

  return(1);
  
}



      
/* \endc */ 




