/*
 * SUMMARY:      ReadWeights.c - Calculate interpolation weights
 * USAGE:        Part of DHSVM
 *
 * AUTHOR:       Mark Wigmosta
 * ORG:          
 * E-MAIL:       
 * ORIG-DATE:    
 * Last Change: Mon Apr  9 15:01:03 2001 by Scott Waichler <waichler@tuff.pnl.gov>
 * DESCRIPTION:  calculate the interpolation weights for the meteorological
 *               inputs for each point in the modeling area.  The number of 
 *               stations is variable. 
 * DESCRIP-END.
 * FUNCTIONS:    CalcWeights()
 * COMMENTS:     
 */

#ifndef lint
static char vcid[] = "$Id: ReadWeights.c,v 1.3 2001/04/11 23:45:37 waichler Exp $";
#endif /* lint */

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include "settings.h"
#include "data.h"
#include "DHSVMerror.h"
#include "functions.h"
#include "fileio.h"
#include "getinit.h"
#include "round.h"
#include "readweights.h"

enum KEY {info_file, weight_path};


/*****************************************************************************
  Function name: InitReadWeights()

  Purpose      : Reads weight information and allocates array for weights.

  Required     :
    METLOCATION *Station - Location of meteorological stations
    int NStats           - Number of meteorological stations
    int NX               - Number of pixels in East - West direction
    int NY               - Number of pixels in North - South direction
    uchar ** BasinMask   - BasinMask
    uchar ***WeightArray - 3D array with interpolation weights
  
  Returns      :  void

  Modifies     :  WeightInfo


  Comments     :
*****************************************************************************/
void InitReadWeights(LISTPTR Input, int NX, int NY, unsigned char **BasinMask, 
                     unshort ****WeightArray, WEIGHT_INFO ***WeightInfo, 
                     WEIGHT_FILES *WeightFiles, int NStats)
{
  FILE *InfoFile;
  int y;			/* Counter for rows */
  int x;			/* Counter for columns */
  int i;			/* Counter for stations */
  int NumStations = 0, temp = 0;

  const char *Routine = "InitElevBand()";

  STRINIENTRY StrEnv[] = {
    {"OPTIONS", "MET WEIGHTS INFO FILE"    , ""  , NULL},
    {"OPTIONS", "MET WEIGHTS FILE PATH", ""  , NULL},
    {NULL     , NULL                  , ""  , NULL}
  };

  printf("Initializing read met weights\n");

  /* allocate memory for weight Info Struct */
  if (!(*WeightInfo = (WEIGHT_INFO **) calloc(NY, sizeof(WEIGHT_INFO *))))
    ReportError("ReadWeights()", 1);;
  for (y = 0; y < NY; y++) {
    if (!((*WeightInfo)[y] = (WEIGHT_INFO *) calloc(NX, sizeof(WEIGHT_INFO))))
    ReportError("ReadWeights()", 1);;
  }
  
  /* Read the key-entry pairs from the [WEIGHTS] section of the input file */
  for (i = 0; StrEnv[i].SectionName; i++) {
    GetInitString(StrEnv[i].SectionName, StrEnv[i].KeyName, StrEnv[i].Default,
                  StrEnv[i].VarStr, (unsigned long) BUFSIZE, Input);
    if (!StrEnv[i].VarStr)
      ReportError(StrEnv[i].KeyName, 51);
  } 

  /* open met weight info file and read data   */
  OpenFile(&InfoFile, StrEnv[info_file].VarStr, "r", FALSE);

  for (y = 0; y < NY; y++) {
    for (x = 0; x < NX; x++) {
      if (InBasin(BasinMask[y][x])) { /*we are inside the basin mask*/

        /* number of stations for interpolation */
        fscanf(InfoFile, "%d ", &NumStations );
        (*WeightInfo)[y][x].NumStats = (unsigned) NumStations;
                
        /* allocate memory for station numbers */
        if (!((*WeightInfo)[y][x].StationNum 
          = (unsigned char *) calloc(NumStations, sizeof(unsigned char))))
          ReportError("ReadWeights()", 1);

        /* read station numbers */
        for( i = 0; i < NumStations; i++ ) {
          fscanf( InfoFile, "%d ", &temp );
          (*WeightInfo)[y][x].StationNum[i] = (unsigned char) temp;
        }

        fscanf( InfoFile, " \n" ); /* next line */

      }
    }
  }

  fclose( InfoFile );


  /* Allocate memory for a 3 dimensional array */
  if (!((*WeightArray) = (unshort ***) calloc(NY, sizeof(unshort **))))
    ReportError("CalcWeights()", 1);

  for (y = 0; y < NY; y++) 
    if (!((*WeightArray)[y] = (unshort **) calloc(NX, sizeof(unshort *))))
      ReportError("CalcWeights()", 1);
    
  for (y = 0; y < NY; y++)
    for (x = 0; x < NX; x++)
      if (InBasin(BasinMask[y][x])) { /*we are inside the basin mask*/
        if (!((*WeightArray)[y][x] = 
	      (unshort *) calloc((*WeightInfo)[y][x].NumStats, sizeof(unshort))))
	      ReportError("CalcWeights()", 1);
      }
      else {
        (*WeightArray)[y][x] = NULL;  /* out of basin */
      }

  /* assign path name for weight files */
  strcpy( WeightFiles->Path, StrEnv[weight_path].VarStr);

  /* allocate memory for expanded vector of station weights */
    if (!(WeightFiles->WeightVector =  
	   (unshort *) calloc(NStats, sizeof(unshort))))
	   ReportError("CalcWeights()", 1);
  

}

/*****************************************************************************
  Function name: ReadWeights()

  Purpose      : Read interpolation weights to interpolate the
                 meteorological data from the various stations for every
                 individual pixel

  Required     :
    METLOCATION *Station - Location of meteorological stations
    int NStats           - Number of meteorological stations
    int NX               - Number of pixels in East - West direction
    int NY               - Number of pixels in North - South direction
    uchar ** BasinMask   - BasinMask
    uchar ***WeightArray - 3D array with interpolation weights
  
  Returns      :  void

  Modifies     :
    The values stored at the addresses pointed to by WeightArray (i.e. it
    calculates the weights and stores them)


  Comments     :
*****************************************************************************/
void ReadWeights(int NX, int NY, unsigned char **BasinMask, unshort ****WeightArray, 
                 WEIGHT_INFO **WeightInfo, int Month, char *Path)
{
  FILE *WeightFile;
  int y;			/* Counter for rows */
  int x;			/* Counter for columns */
  int i;			/* Counter for stations */
  float temp;
  char FileName[MAXSTRING+1];
  char str[MAXSTRING+1];

  /* open file for current month */
  sprintf(str, ".%02d", Month);
  sprintf(FileName, "%s%s%s", Path, str,".dat");
  OpenFile(&WeightFile, FileName, "r", FALSE);

  for (y = 0; y < NY; y++){
    for (x = 0; x < NX; x++){
      if (InBasin(BasinMask[y][x])) {
        for( i = 0; i < (int)WeightInfo[y][x].NumStats;  i++ ) {
          fscanf( WeightFile, " %f", &temp );
          (*WeightArray)[y][x][i] = (unshort)(temp * PRISM_SCALE_FACTOR);
        }
        fscanf( WeightFile, " \n");
      }
    }
  }

  fclose( WeightFile );

}

/********************************************************************************/
void TempFullWeightArray( WEIGHT_FILES *WeightFiles, WEIGHT_INFO WeightInfo, 
                          unshort *CompressedArray, int NStats ) 
{
  
  int i;
  
  /* first set to zero */
  for( i = 0; i < NStats; i++ ) (*WeightFiles).WeightVector[i] = 0;

  /* set non-zero valuse */
  for( i = 0; i < (int)WeightInfo.NumStats; i++ ) 
    (*WeightFiles).WeightVector[ WeightInfo.StationNum[i] ] = CompressedArray[i];
  
}
