// =====================================================================
//  $Id: OFFmanualcutsp-5divide-highrad.cc,v 1.3 2003/10/06 16:28:17 goiwai Exp $
//  $Name: CLDAQ-1-14-03 $
//  $Log: OFFmanualcutsp-5divide-highrad.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 <TROOT.h>
#include <TSystem.h>
#include <TApplication.h> 
#include <TStyle.h>
#include <TGraph.h>
#include <TGraphErrors.h>
#include <TH1.h>
#include <TH2.h>
#include <TCanvas.h>
#include <TNtuple.h>
#include <TFile.h>
#include <TPad.h>
#include <TFrame.h>
#include <TF1.h>
#include <TPaveText.h>
#include <TLegend.h>

#include "TEnvironmentVariableTable.hh"
#include "St00SinglePixelInterface.hh"
#include "St00CtiSolution.hh"

int main( int argc, char** argv, char** envv )
{
  enum { INPUT_DATARECORD, INPUT_ASCII_DATASET, INPUT_UNKNOWN = -1 };
  Tint inmode = INPUT_UNKNOWN;

  if ( argc != 2 && argc != 3 ) {
    Tcerr << "usage: " << argv[ 0 ] << Tspace << "<dataset>" << Tendl;
    Tcerr << "usage: " << argv[ 0 ] << Tspace << "<dark> <source>" << Tendl;
    return -1;
  } else if ( argc == 2 ) {
    inmode = INPUT_ASCII_DATASET;
  } else if ( argc == 3 ) {
    inmode = INPUT_DATARECORD;
  }

  TApplication* theApplication = new TApplication( "root-analyser", 0, 0 );
  gROOT -> Reset( 0 );
  gStyle -> SetStatColor( 42 );
  gStyle -> SetTitleColor( 42 );
  gStyle -> SetFrameFillColor( 21 );
  gStyle -> SetFrameFillStyle( 1 );
  gStyle -> SetMarkerStyle( 7 );
  gStyle -> SetFuncColor( 4 );
  gStyle -> SetOptStat( 1111110 );
  gStyle -> SetOptFit( 1111 );
  gStyle -> SetPadGridX( kTRUE );
  gStyle -> SetPadGridY( kTRUE );

  // canvas
  TCanvas CV2x2( "CV2x2", "Single Pixel View", 600, 400 );
  CV2x2.Divide( 2, 2 );
  TH1D signal( "signal", "Single", 50, 0.0, 500.0 );
  TH1D dark( "dark", "Dark", 50, 0.0, 500.0 );
  signal.SetFillColor( 45 );
  dark.SetFillColor( 45 );


  St00SinglePixelInterface* spif = 0;
  if ( inmode == INPUT_DATARECORD ) {
    spif = new St00SinglePixelInterface( argv[ 1 ], argv[ 2 ] );
  } else if ( inmode == INPUT_ASCII_DATASET ) {
    spif = new St00SinglePixelInterface( argv[ 1 ] );
  }
  St00SinglePixelList spl = spif -> GetSinglePixelList();
  delete spif;


  for ( Tsize_t i = 0; i < spl.size(); i ++ ) {
    signal.Fill( spl[ i ].GetSignal() );
    dark.Fill( spl[ i ].GetDark() );
  }


  CV2x2.cd( 1 );
  signal.Draw();

  CV2x2.cd( 2 );
  dark.Draw();
  CV2x2.cd( 1 );


  Tcout << "********************************************" << Tendl;
  Tcout << "********************************************" << Tendl;
  Tcout << "********************************************" << Tendl;
  Tcout << "shakehand mode begin!" << Tendl;
  Tstring answer;
  Tdouble mean;
  Tdouble sigma;
  Tdouble xmin;
  Tdouble xmax;
  do {
    gSystem -> ProcessEvents();
    Tcout << "set Xmin --> ";
    Tcin >> xmin;
    Tcout << "set Xmax --> ";
    Tcin >> xmax;
    TF1 gaussignal( "gaussignal", "gaus", xmin, xmax );
    CV2x2.cd( 1 );
    signal.Fit( "gaussignal", "qr", "same" );
    CV2x2.Update();

    mean = gaussignal.GetParameter( "Mean" );
    sigma = gaussignal.GetParameter( "Sigma" );

    Tcout << Tendl << Tendl;
    Tcout << "** Mean: " << mean << Tendl;
    Tcout << "** Sigma: " << sigma << Tendl;
    Tcout << Tendl << Tendl;

    Tcout << "OK?[n/y] --> ";
    Tcin >> answer;
  } while ( answer != "y" );
  Tcout << "********************************************" << Tendl;
  Tcout << "********************************************" << Tendl;
  Tcout << "********************************************" << Tendl;

  TEnvironmentVariableTable envtable( "setenvrc" );
  Tdouble factor = envtable.GetDoubleValue( "ST00_MANUALCUT_SIGMA" );
  const Tdouble cutlow = mean;
  const Tdouble cutupp = mean + ( factor * sigma );

  // cut 中心から右側だけ使う
  St00SinglePixelList newsplist;
  for ( Tsize_t i = 0; i < spl.size(); i ++ ) {
    Tdouble signal = spl[ i ].GetSignal();
    if ( signal > cutlow && signal < cutupp ) {
      newsplist.push_back( spl[ i ] );
    }
  }
  St00CtiSolution analyser( newsplist );


  TH1D cutoffsignal( "cutoffsignal", "Single Pixel Distribution", 50, 0.0, 500.0 );
  TH1D signalln( "signalln", "Single Pixel Distribution", 50, 0.0, 10.0 );
  cutoffsignal.SetFillColor( 45 );
  signalln.SetFillColor( 45 );
  for ( Tsize_t i = 0; i < newsplist.size(); i ++ ) {
    Tdouble signal = newsplist[ i ].GetSignal();
    cutoffsignal.Fill( signal );
    signalln.Fill( log( signal ) );
  }
  CV2x2.cd( 3 );
  cutoffsignal.Fit( "gaus", "q" );
  CV2x2.cd( 4 );
  signalln.Fit( "gaus", "q" );

  Tdouble err = signalln.GetFunction( "gaus" )->GetParameter( "Sigma" );

  // ================================================================
  // グラフを作る
  const Tint ngraph = 10;
  TGraphErrors graph[ ngraph ];
  Tstring grname[ ngraph ] = {
    "h013-062", "h063-112", "h113-162", "h163-212", "h213-262",
    "v014-063", "v064-113", "v114-163", "v164-213", "v214-263"
  };
  Tint cnt[ ngraph ];
  for ( Tint i = 0; i < ngraph; i ++ ) {
    graph[ i ].SetName( grname[ i ].c_str() );
    cnt[ i ] = 0;
  }
  for ( Tsize_t i = 0; i < newsplist.size(); i ++ ) {
    Tint h = newsplist[ i ].GetHorizontalID() ;
    Tint v = newsplist[ i ].GetVerticalID();
    Tdouble diff = newsplist[ i ].GetSignal();

    if ( h >= 13 && h <= 62 ) {
      graph[ 0 ].SetPoint( cnt[ 0 ], (Tdouble)v, log( diff ) );
      graph[ 0 ].SetPointError( cnt[ 0 ], 0.0, err );
      cnt[ 0 ] ++;
    }
    if ( h >= 63 && h <= 112 ) {
      graph[ 1 ].SetPoint( cnt[ 1 ], (Tdouble)v, log( diff ) );
      graph[ 1 ].SetPointError( cnt[ 1 ], 0.0, err );
      cnt[ 1 ] ++;
    }
    if ( h >= 113 && h <= 162 ) {
      graph[ 2 ].SetPoint( cnt[ 2 ], (Tdouble)v, log( diff ) );
      graph[ 2 ].SetPointError( cnt[ 2 ], 0.0, err );
      cnt[ 2 ] ++;
      ;
    }
    if ( h >= 163 && h <= 212 ) {
      graph[ 3 ].SetPoint( cnt[ 3 ], (Tdouble)v, log( diff ) );
      graph[ 3 ].SetPointError( cnt[ 3 ], 0.0, err );
      cnt[ 3 ] ++;
    }
    if ( h >= 213 && h <= 262 ) {
      graph[ 4 ].SetPoint( cnt[ 4 ], (Tdouble)v, log( diff ) );
      graph[ 4 ].SetPointError( cnt[ 4 ], 0.0, err );
      cnt[ 4 ] ++;
    }

    if ( v >= 14 && v <= 63 ) {
      graph[ 5 ].SetPoint( cnt[ 5 ], (Tdouble)h, log( diff ) );
      graph[ 5 ].SetPointError( cnt[ 5 ], 0.0, err );
      cnt[ 5 ] ++;
    }
    if ( v >= 64 && v <= 113 ) {
      graph[ 6 ].SetPoint( cnt[ 6 ], (Tdouble)h, log( diff ) );
      graph[ 6 ].SetPointError( cnt[ 6 ], 0.0, err );
      cnt[ 6 ] ++;
    }
    if ( v >= 114 && v <= 163 ) {
      graph[ 7 ].SetPoint( cnt[ 7 ], (Tdouble)h, log( diff ) );
      graph[ 7 ].SetPointError( cnt[ 7 ], 0.0, err );
      cnt[ 7 ] ++;
    }
    if ( v >= 164 && v <= 213 ) {
      graph[ 8 ].SetPoint( cnt[ 8 ], (Tdouble)h, log( diff ) );
      graph[ 8 ].SetPointError( cnt[ 8 ], 0.0, err );
      cnt[ 8 ] ++;
    }
    if ( v >= 214 && v <= 263 ) {
      graph[ 9 ].SetPoint( cnt[ 9 ], (Tdouble)h, log( diff ) );
      graph[ 9 ].SetPointError( cnt[ 9 ], 0.0, err );
      cnt[ 9 ] ++;
    }
  }

  Tdouble q0[ ngraph ];
  Tdouble q0_e[ ngraph ];
  Tdouble cti[ ngraph ];
  Tdouble cti_e[ ngraph ];
  for ( Tint i = 0; i < ngraph; i ++ ) {
    graph[ i ].Fit( "pol1", "q0" );
    TF1* f = graph[ i ].GetFunction( "pol1" );
    Tdouble p0 = f -> GetParameter( 0 );
    Tdouble p1 = f -> GetParameter( 1 );
    Tdouble p0_e = f -> GetParError( 0 );
    Tdouble p1_e = f -> GetParError( 1 );

    q0[ i ] = exp( p0 );
    q0_e[ i ] = exp( p0 ) * p0_e;
    cti[ i ] = 1.0 - exp( p1 );
    cti_e[ i ] = exp( p1 ) * p1_e;
  }

  Tstring line0[ ngraph ] = {
    "13 #leq H #leq 62",
    "63 #leq H #leq 112",
    "113 #leq H #leq 162",
    "163 #leq H #leq 212",
    "213 #leq H #leq 262",
    "14 #leq V #leq 063",
    "064 #leq V #leq 113",
    "114 #leq V #leq 163",
    "164 #leq V #leq 213",
    "214 #leq V #leq 263"
  };
  Tstring line1[ ngraph ];
  for ( Tint i = 0; i < ngraph; i ++ ) {
    line1[ i ] = "Nsamples: " + dtostr( cnt[ i ] ) + " #/ ";
    line1[ i ] += " Q_{0}: " + dtostr( q0[ i ] ) + " #pm " + dtostr( q0_e[ i ] ) + " #/ ";
    if ( i < 5 ) {
      line1[ i ] += " CTI_{V}: ";
    } else {
      line1[ i ] += " CTI_{H}: ";
    }
    line1[ i ] += dtostr( cti[ i ] ) + " #pm " + dtostr( cti_e[ i ] );
  }


  //define dirname, filename
  //Tstring dir( input );
  //dir.erase( dir.begin(), dir.begin() + dir.find( "/" ) + 1 );
  //dir.erase( dir.begin() + dir.find( "/" ), dir.end() );
  //Tstring file( input );
  //file.erase( file.begin(), file.begin() + file.rfind( "/" ) + 1 );
  Tstring dir = argv[ 1 ];
  Tstring file = argv[ 1 ];


  TCanvas CVsummary( "CVsummary", "Summary", 600, 800 );
  CVsummary.cd();
  TPaveText summary( 0.01, 0.01, 0.99, 0.99 );
  summary.SetFillColor( 44 );
  summary.SetTextAlign( 12 );
  summary.SetTextSize( 0.024 );


  Tstring head1 = "DIR: " + dir;
  Tstring head2 = "FILE: " + file;
  summary.AddText( head1.c_str() );
  summary.AddText( head2.c_str() );
  for ( Tint i = 0; i < ngraph; i ++ ) {
    summary.AddText( "" );
    summary.AddText( line0[ i ].c_str() );
    summary.AddText( line1[ i ].c_str() );
  }

  summary.Draw();
  

  // <CTI>の計算
  //cti[i] cti_e[i]
  Tdouble a = 0.0;
  Tdouble b = 0.0;
  for ( Tint i = 0; i < 5; i ++ ) {
    a += cti[ i ] / pow( cti_e[ i ], 2.0 );
    b += 1.0 / pow( cti_e[ i ], 2.0 );
  }
  Tdouble vcti = a / b;
  Tdouble vcti_e = 1.0 / sqrt( b );
  
  Tdouble c = 0.0;
  Tdouble d = 0.0;
  for ( Tint i = 5; i < ngraph; i ++ ) {
    c += cti[ i ] / pow( cti_e[ i ], 2.0 );
    d += 1.0 / pow( cti_e[ i ], 2.0 );
  }
  Tdouble hcti = c / d;
  Tdouble hcti_e = 1.0 / sqrt( d );

  
  Tcout << "HCTI: " << hcti << " " << hcti_e << Tendl;
  Tcout << "VCTI: " << vcti << " " << vcti_e << Tendl;


  theApplication -> Run();

  return 0;
}
