// =====================================================================
//  $Id: St00CtiSolution.cc,v 1.3 2003/10/06 16:28:17 goiwai Exp $
//  $Name: CLDAQ-1-14-06 $
//  $Log: St00CtiSolution.cc,v $
//  Revision 1.3  2003/10/06 16:28:17  goiwai
//  *** empty log message ***
//
//  Revision 1.2  2003/07/30 16:15:51  goiwai
//  ファイルにコミットログをつけることにしました.
//
// =====================================================================
#include "TDataMultiplicity.hh"
#include "St00CtiSolution.hh"
#include "St00SinglePixel.hh"

static const Tint _nrow = 3;
static const Tint _ncol = 3;

St00CtiSolution::St00CtiSolution( const St00SinglePixelList& list )
  : theSinglePixelList( list ),
    theHorizontalCTI( 0.0 ), theVerticalCTI( 0.0 ), theInitialValue( 0.0 ),
    theErrorOfHorizontalCTI( 0.0 ), 
    theErrorOfVerticalCTI( 0.0 ), 
    theErrorOfInitialValue( 0.0 )
{
  resolve();
  resolveError();
}

St00CtiSolution::~St00CtiSolution()
{;}

Tvoid St00CtiSolution::resolve()
{
  Tint ndata = (Tint)theSinglePixelList.size();

  TDataMultiplicity left( _nrow, _ncol, 0 );
  TDataMultiplicity right( _nrow, 1, 0 );

  for ( Tint i = 0; i < ndata; i ++ ) {
    Tdouble x = 0.0;
    Tdouble y = 0.0;
    Tdouble z = 0.0;

    x = (Tdouble)theSinglePixelList[ i ].GetHorizontalID();
    y = (Tdouble)theSinglePixelList[ i ].GetVerticalID();
    z = log( (Tdouble)theSinglePixelList[ i ].GetSignal() );

    left[ 0 ][ 0 ] += x * x;
    left[ 1 ][ 0 ] += x * y;
    left[ 2 ][ 0 ] += x;

    left[ 0 ][ 1 ] += x * y;
    left[ 1 ][ 1 ] += y * y;
    left[ 2 ][ 1 ] += y;

    left[ 0 ][ 2 ] += x;
    left[ 1 ][ 2 ] += y;
    left[ 2 ][ 2 ] += 1;

    right[ 0 ][ 0 ] += x * z;
    right[ 1 ][ 0 ] += y * z;
    right[ 2 ][ 0 ] += z;
  }

  Tint ierr;
  left.invert( ierr );

  if ( ierr != 0 ) {
    Tcerr << "St00CtiSolution::resolve(): " << ierr << Tendl;
    Tcout << left << Tendl;
    Tcout << right << Tendl;
    return;
  }

  TDataMultiplicity m = left * right;

  Tdouble a = m[ 0 ][ 0 ];
  Tdouble b = m[ 1 ][ 0 ];
  Tdouble c = m[ 2 ][ 0 ];

  theHorizontalCTI = 1.0 - exp( a );
  theVerticalCTI = 1.0 - exp( b );
  theInitialValue = exp( c );

  return;
}

Tvoid St00CtiSolution::resolveError()
{
  Tint ndata = (Tint)theSinglePixelList.size();
  Tdouble ave = 0.0;
  for ( Tint i = 0; i < ndata; i ++ ) {
    ave += theSinglePixelList[ i ].GetSignal();
  }
  ave /= (Tdouble)ndata;

  static const Tdouble k = ave / 1630;

  
  TDataMultiplicity error( _nrow, _ncol, 0 );

  for ( Tint i = 0; i < ndata; i ++ ) {
    Tdouble x = 0.0;
    Tdouble y = 0.0;
    Tdouble delta = 0.0;
    Tdouble delta2 = 0.0;

    x = (Tdouble)theSinglePixelList[ i ].GetHorizontalID();
    y = (Tdouble)theSinglePixelList[ i ].GetVerticalID();
    delta = theSinglePixelList[ i ].GetSignal();
    delta += theSinglePixelList[ i ].GetDark();
    delta = sqrt( delta * k );
    delta2 = delta * delta;

    error[ 0 ][ 0 ] += x * x / delta2;
    error[ 1 ][ 0 ] += x * y / delta2;
    error[ 2 ][ 0 ] += x / delta2;

    error[ 0 ][ 1 ] += x * y / delta2;
    error[ 1 ][ 1 ] += y * y / delta2;
    error[ 2 ][ 1 ] += y / delta2;

    error[ 0 ][ 2 ] += x / delta2;
    error[ 1 ][ 2 ] += y / delta2;
    error[ 2 ][ 2 ] += 1 / delta2;

  }

  Tint ierr;
  error.invert( ierr );

  if ( ierr != 0 ) {
    Tcerr << "St00CtiSolution::resolveError(): " << ierr << Tendl;
    Tcout << error << Tendl;
    return;
  }

  Tdouble Eaa = error[ 0 ][ 0 ];
  Tdouble Ebb = error[ 1 ][ 1 ];
  Tdouble Ecc = error[ 2 ][ 2 ];


  Tdouble delta_a = sqrt( Eaa );
  Tdouble delta_b = sqrt( Ebb );
  Tdouble delta_c = sqrt( Ecc );

  theErrorOfHorizontalCTI = fabs( 1.0 - exp( delta_a ) );
  theErrorOfVerticalCTI = fabs( 1.0 - exp( delta_b ) );
  theErrorOfInitialValue = exp( delta_c );

  return;
}
