/*-----------------
* Copyright (C) 2001-2003, CompHEP Collaboration
*------------------------------------------------------
* $Id: mk_tab.c,v 1.8 2003/08/25 09:33:18 sherstnv Exp $
*
* $Log: mk_tab.c,v $
* Revision 1.8  2003/08/25 09:33:18  sherstnv
* type midstr - middlestr is changed
*
* Revision 1.7  2003/06/25 18:46:42  kryukov
* *** empty log message ***
*
* Revision 1.6  2003/06/17 11:13:59  sherstnv
* mk_tab now is re-linked by user in $WDIR/usr
* It is necessary for replace U-variables if user develops own ones.
*
* Revision 1.5  2003/05/01 12:19:29  sherstnv
* Pri ne otsutstvii file s imenem zadannom v kom.stroke
* vivoditsya kratkiy help.
*
* Revision 1.4  2003/04/22 09:01:22  kryukov
* Apply indent to improve readability of files
*
* Revision 1.3  2003/04/20 17:55:03  kryukov
* Clean up warnings during make
*
*/
#include <stdio.h>
#include "num/include/tag_reader.h"
#include "num/include/tag_parser.h"
#include "num/include/event_reader.h"
#include "num/include/4_vector.h"
#include "num/include/phys_val.h"
#include "service2/include/paragraphs.h"
#include "e_tools.h"

#define const
#include "out_ext.h"
#undef const

static void
wrongParam (int N)
{
  if (N)
    fprintf (stderr, "Wrong parameter %d\n", N);
  else
    fprintf (stderr, "Wrong number of parameters \n");
  fprintf (stderr, "Parameters:\n"
	   " 1- file name,\n"
	   " 2- name of variable,\n"
	   " 3- minimum limit,\n"
	   " 4- maximum limit,\n"
	   " 5- number of bins(<=300).\n");
}


int
main (int argc, char **argv)
{
  int i, j, k, n;
  int nbin;
  int Nproc;
  int format;
  int npr;
  int max_format = 0;
  long Npoints;
  int *Nevents;
  int *Npartons;
  int **pnum;

  char key;
  char plist[MAXNP];
  middlestr name_proc;

  double minX, maxX;
  double weight, coef;
  double *CSec;
  double *hist;
  double *dhist;
  double **mass;

  string_comnd com;
  tags *head;

  FILE *f = fopen (argv[1], "r");
  if (!f)
    {
      fprintf (stderr, "***Error! File not found: %s\n", argv[1]);
      return 2;
    }

  head = init_cap (1);
  cup_reader (f, head);
  Nproc = number_proc (head);

  Npartons = malloc (Nproc * sizeof (int));
  Nevents = malloc (Nproc * sizeof (int));
  pnum = malloc (Nproc * sizeof (int *));
  CSec = malloc (Nproc * sizeof (double));
  mass = malloc (Nproc * sizeof (double *));

  for (i = 0; i < Nproc; i++)
    {
      pnum[i] = malloc (100 * sizeof (int));
      sprintf (com.value, "%i", i + 1);

/*---  Get number of partons, cross section and parton's names from process tag  */
      strcpy (com.name, "ID");
      n = get_tag_with_exactcom (0, head, "process", &com);
      if (n != -1)
	{
	  Npartons[i] = get_ival (0, "Nparton", head->tag[n]);
	  CSec[i] = get_fval (0, "CrosSec", head->tag[n]);
	  strcpy (name_proc, get_cval (0, "name", head->tag[n]));
	  getNames (name_proc);
	}
      else
	{
	  wrongParam (0);
	  fprintf (stderr, "***Error! The process tag for the %i-th subprocess has been lost.\n", i + 1);
	  exit (1);
	}

/*---  Get number of events from the n_event tag  */
      strcpy (com.name, "IDprocess");
      n = get_tag_with_exactcom (0, head, "n_event", &com);
      if (n != -1)
	{
	  Nevents[i] = get_ival (0, "N", head->tag[n]);
	}
      else
	{
	  fprintf (stderr, "***Error! The n_event tag for the %i-th subprocess has been lost.\n", i + 1);
	  exit (1);
	}

/*---  Set format numbers for i-th subprocess  */
      sprintf (com.value, "%i", i + 1);
      format = get_tag_with_exactcom (0, head, "format", &com);
      if (format != -1)
	{
	  if (head->tag[format]->tagsize > max_format)
	    max_format = head->tag[format]->tagsize;

	  strcpy (com.name, "p1.3");
	  n = tag_contain_com (&com, head->tag[format]);
	  if (n > 0)
	    pnum[i][3] = n - 2;
	  else
	    {
	      fprintf (stderr, "***Error in format tag for the %i-th subprocess.\n", i + 1);
	      exit (1);
	    }
	  strcpy (com.name, "p2.3");
	  n = tag_contain_com (&com, head->tag[format]);
	  if (n > 0)
	    pnum[i][7] = n - 2;
	  else
	    {
	      fprintf (stderr, "***Error in format tag for the %i-th subprocess.\n", i + 1);
	      exit (1);
	    }

	  for (k = 2; k < Npartons[i]; k++)
	    {
	      for (j = 0; j < 3; j++)
		{
		  sprintf (com.name, "p%i.%i", k + 1, j + 1);
		  n = tag_contain_com (&com, head->tag[format]);
		  if (n > 1)
		    pnum[i][4 * k + j + 1] = n - 2;
		  else
		    pnum[i][4 * k + j + 1] = 0;
		}
	    }
	}
      else
	{
	  fprintf (stderr, "***Error! The format tag for the %i-th subprocess has been lost.\n", i + 1);
	  exit (1);
	}

/*---  Get partons masses from partons tags  */
      strcpy (com.name, "IDprocess");
      sprintf (com.value, "%i", i + 1);
      n = -1;
      mass[i] = malloc (Npartons[i] * sizeof (double));
      for (j = 0; j < Npartons[i]; j++)
	{
	  n = get_tag_with_exactcom (n + 1, head, "parton", &com);
	  if (n != -1)
	    {
	      int in = get_ival (0, "in", head->tag[n]);
	      int out = get_ival (0, "out", head->tag[n]);
	      if (in)
		mass[i][in - 1] = get_fval (0, "mass", head->tag[n]);
	      if (out)
		mass[i][out - 1] = get_fval (0, "mass", head->tag[n]);
	    }
	  else
	    {
	      fprintf (stderr, "***Error! The number of parton tags are not equaled to the number\n"
		       "          of parton in process tag for the %i-th subprocess.\n", i + 1);
	      exit (1);
	    }
	}
    }

  if (argc != 6)
    {
      wrongParam (0);
      return 1;
    }
  if (!checkPhysVal (argv[2], &key, plist))
    {
      wrongParam (1);
      return 1;
    }
  if (sscanf (argv[3], "%lf", &minX) != 1)
    {
      wrongParam (2);
      return 1;
    }
  if (sscanf (argv[4], "%lf", &maxX) != 1 || minX >= maxX)
    {
      wrongParam (3);
      return 1;
    }
  if (sscanf (argv[5], "%d", &nbin) != 1 || nbin <= 0)
    {
      wrongParam (4);
      return 1;
    }

  hist = malloc (nbin * sizeof (double));
  dhist = malloc (nbin * sizeof (double));

  for (i = 0; i < nbin; i++)
    {
      hist[i] = 0;
      dhist[i] = 0;
    }

  Npoints = 0;
  {
    char **eventword = malloc (max_format * sizeof (char *));
    char buf[STRSIZE];
    char buff[STRSIZE];
    int debug = 0, err;
    pvect[1] = 0;
    pvect[2] = 0;
    pvect[5] = 0;
    pvect[6] = 0;

    fgets (buf, 1000, f);
    while (fgets (buf, 1000, f))
      {
	sscanf (buf, "%i:%[^\n]", &npr, buff);
	npr--;
	err = event_parser (buff, eventword);
	if (err)
	  {
	    fprintf (stderr, "Error in event %i\n. Exit!", debug);
	    exit (1);
	  }
	pvect[3] = atof (eventword[pnum[npr][3]]);
	pvect[7] = atof (eventword[pnum[npr][7]]);
	for (i = 2; i < Npartons[npr]; i++)
	  for (j = 0; j < 3; j++)
	    pvect[4 * i + j + 1] = atof (eventword[pnum[npr][4 * i + j + 1]]);
	for (i = 0; i < nin_ + nout_; i++)
	  pvect[4 * i] = ENERGY (mass[npr][i], pvect + 4 * i + 1);

	weight = CSec[npr] / Nevents[npr];
	i = nbin * (calcPhysVal (key, plist) - minX) / (maxX - minX);
	if (i >= 0 && i < nbin)
	  {
	    hist[i] += weight;
	    dhist[i] += weight * weight;
	    Npoints++;
	  }
	debug++;
      }
    free (eventword);
  }
  free (Npartons);
  free (Nevents);
  free (pnum);
  free (CSec);
  free (mass);
  coef = nbin / (maxX - minX);

  for (i = 0; i < nbin; i++)
    {
      dhist[i] = coef * sqrt (dhist[i] - hist[i] * hist[i] / Npoints);
      hist[i] *= coef;
    }

  {
    char xname[200], yname[200], xunits[100];

    for (i = 0; i < nin_ + nout_; i++)
      {
	if (i == nin_)
	  fprintf (stdout, " ->");
	else if (i)
	  fprintf (stdout, ",");
	pinf_ (1, i + 1, xname, NULL);
	fprintf (stdout, " %s", xname);
      }
    if (nin_ == 2)
      sprintf (yname, "Diff. cross section [pb");
    else
      sprintf (yname, "Diff. width [GeV");
    fprintf (stdout, "\n");

    xName (key, plist, xname, xunits);
    fprintf (stdout, "x-axis: \"%s\"  from %f to %f N_bins= %d\n", xname, minX, maxX, nbin);
    fprintf (stdout, "%s", yname);
    if (xunits[0])
      fprintf (stdout, "/%s", xunits);
    fprintf (stdout, "]");
  }

  for (i = 0; i < nbin; i++)
    fprintf (stdout, "\n%-12E +/-  %-12E", hist[i], dhist[i]);

  fprintf (stdout, "\n");
  fclose (f);
  free (hist);
  free (dhist);
  return 0;
}
