// =====================================================================
//  $Id: rs01OFFvsecview3x3.cc,v 1.2 2003/10/06 16:28:15 goiwai Exp $
//  $Name: CLDAQ-1-14-03 $
//  $Log: rs01OFFvsecview3x3.cc,v $
//  Revision 1.2  2003/10/06 16:28:15  goiwai
//  *** empty log message ***
//
//  Revision 1.1  2003/09/17 09:53:14  goiwai
//  時間積分(読み出し電圧×直前の読み出しからの経過時間)をチャンネル16(中
//  心)とその周囲8チャンネルのみプロットします.
//  横軸は時刻(H:M:S)です.
//
//  これまた変な仕様ですが,引数は5つ必要です.
//    1. ランID
//    2. 初期ペデスタル定義ファイルへのパス(1行32列のデータ)
//    3. ビームOFF後のペデスタル定義ファイルへのパス(1行32列のデータ)
//    4. ペデスタルが増えはじめるイベントID
//    4. ペデスタルの増加が止まるイベントID
//
//  % rs01OFFvsecview 123 ped0.dat ped1.dat 45 678
//  とすれば, run000123.drec について実行します.
//  Event ID:0からID:44までは "ped0.dat"がペデスタルとして使用されます.
//  Event ID:679以降のイベントには "ped1.dat" が使用されます.
//  Event ID:45からEvent ID:678まではイベント数に比例して増えます.
//
//  もし,ひとつの同じペデスタルを使いたかったら
//  % rs01OFFvsecview 123 ped0.dat ped0.dat(読めるファイル) 10000(でかい数) 678(適当)
//  これでランを通してずっと同じペデスタルを使います.
//
// =====================================================================
#include "TDataRecord.hh"
#include "TDataSection.hh"
#include "TDataSegment.hh"
#include "TDataElement.hh"
#include "TEnvironmentVariableTable.hh"
#include "TInputObjectFile.hh"
#include "Trootinit.h"

static const Tstring rcpath = "rs01setup";
static const Tint npin = 32;
// static Tint pinpos[ npin ] = {
//            3,  4, 5,   6,  7,
//       10, 11, 12, 13, 14, 15, 16,
//   17, 18, 19, 20, 21, 22, 23, 24,
//       26, 27, 28, 29, 30, 31, 32,
//            35, 36, 37, 38, 39
// };

TInputObjectFile* ifile = 0;
TEnvironmentVariableTable* envtable = 0;
TDataRecord record;
Tdouble vdc[ npin ];
Tint elapsed[ npin ];
Tdouble integrated[ npin ];
Tdouble ped0[ npin ];
Tdouble ped1[ npin ];

TApplication* theApplication = 0;
TCanvas* CVvsec = 0;
static const Tint nx = 3;
static const Tint ny = 3;
static const Tint npadvsec = nx * ny;
TH1D** H1Dvsec;
Tstring htvsec[ npin ];
Tstring hnamevsec[ npin ];

static Tstring fpath, macrof, giff, psf, rootf, dataf, ped0path, ped1path;
static Tint modperiod, pedbegin, pedend, runid;
static Tstring pedbeginclock, pedendclock, runbeginclock, runendclock;

static Tvoid initialize( Tint argc, Tchar** argv );
static Tvoid event();
static Tvoid runbegin();
static Tvoid runend();
static Tdouble getpedestal( Tint ch, Tint eventid );

int main( int argc, char** argv, char** envv )
{
  initialize( argc, argv );

  while ( ifile -> Read( record ) ) {
    Tstring recid = record.GetID();
    if ( recid == "RUN BEGIN" ) {
      runbegin();
      continue;
    } else if ( recid == "EVENT" ) {
      event();
    } else if ( recid == "RUN END" ) {
      runend();
      break;
    } else {
      Tcerr << "unknown tag: " << recid << Tendl;
      break;
    }
    gSystem -> ProcessEvents();
  }

  theApplication -> Terminate();
  return 0;
}

Tvoid initialize( Tint argc, Tchar** argv )
{
  if ( argc != 6 ) {
    Tcerr << "usage: " << argv[ 0 ] << " <run#> <path0> <path1> <begin> <end>" << Tendl;
    Tcout << "ex) " << argv[ 0 ] << " 123 ped0.dat ped1.dat 45 678" << Tendl;
    Tcout << "Run123電圧×時間の積分量をプロットします." << Tendl;
    Tcout << "ペデスタルには1行32列のデータファイル\"ped0.dat\"と\"ped1.dat\"を読みこんで使用します." << Tendl;
    Tcout << "Event ID:0からEvent ID:44までは\"ped0.dat\"がペデスタルとして使用されます." << Tendl;
    Tcout << "Event ID:679以降のイベントには\"ped1.dat\"がペデスタルとして使用されます." << Tendl;
    Tcout << "Event ID:45からEvent ID:678まではイベント数に比例してペデスタルが増えます." << Tendl;
    Tcout << Tendl;
    Tcout << "ひとつの同じペデスタルを使いたかったら" << Tendl;
    Tcout << "ex) " << argv[ 0 ] << " 123 ped0.dat ped0.dat(読めるファイル) 10000(でかい数) 678(適当)" << Tendl;
    Tcout << "これでランを通してずっと同じペデスタルを使います." << Tendl;
    exit( -1 );
  }

  runid = (Tint)strtol( argv[1], 0, 0 );
  Tstring runidstr = itostr( runid );

  ped0path = argv[2];
  ped1path = argv[3];
  pedbegin = (Tint)strtol(argv[4],0,0);
  pedend = (Tint)strtol(argv[5],0,0);



  Tstring htped = "Beam Profile Monitor, Run ID: " + runidstr;
  Tstring htint = "Beam Profile Monitor(Integrated), Run ID: " + runidstr;

  envtable = new TEnvironmentVariableTable ( rcpath );
  Tstring rechead = envtable -> GetEnvironmentValue( "RS01_RECORD_HEAD" );
  Tstring recpath = envtable -> GetEnvironmentValue( "RS01_RECORD_DIR" );
  fpath = recpath + Tslash + rechead + runidstr + ".drec";
  ifile = new TInputObjectFile( fpath );


  rootf = rechead + runidstr + "vsec3x3.root";
  macrof = rechead + runidstr + "vsec3x3.C";
  giff = rechead + runidstr + "vsec3x3.gif";
  psf = rechead + runidstr + "vsec3x3.ps";
  dataf = rechead + runidstr + "vsec3x3.dat";

  modperiod = envtable -> GetIntegerValue( "RS01_UPDATE_PERIOD" );


  // pedestal
  Tifstream ifs;
  ifs.open(ped0path.c_str());
  for ( Tint i = 0; i < npin; i ++ ) {
    ifs >> ped0[i];
  }
  ifs.close();

  ifs.open(ped1path.c_str());
  for ( Tint i = 0; i < npin; i ++ ) {
    ifs >> ped1[i];
  }
  ifs.close();


  theApplication = rootinit();
  TGaxis::SetMaxDigits( 2 );


  CVvsec = new TCanvas( "CVvsec", "Integrated Voltage VS Time", 960, 720 );
  CVvsec -> ToggleEventStatus();
  CVvsec -> Divide( nx, ny );


  H1Dvsec = new TH1D*[npin];
  for ( Tint ch = 0; ch < npin; ch ++ ) {
    htvsec[ ch ] = "Channel: " + itostr( ch, 2 ) + ", Run ID: " + runidstr;
    hnamevsec[ ch ] = "H1Dvsec" + itostr( ch, 2 );

    H1Dvsec[ ch ] = 
      new TH1D( hnamevsec[ ch ].c_str(), htvsec[ ch ].c_str(), 10, 0.0, 10.0 );

    H1Dvsec[ ch ] -> SetStats( 0 );
    H1Dvsec[ ch ] -> GetXaxis() -> SetTimeDisplay( 1 );
    H1Dvsec[ ch ] -> SetMarkerStyle( 1 );
    H1Dvsec[ ch ] -> SetLineColor( 10 );
    H1Dvsec[ ch ] -> SetLineStyle( 0 );
    H1Dvsec[ ch ] -> SetLineWidth( 0 );

    H1Dvsec[ ch ] -> GetXaxis() -> SetNdivisions( 504 );
    H1Dvsec[ ch ] -> GetXaxis() -> SetTimeFormat( "%H:%M:%S" );
    H1Dvsec[ ch ] -> GetXaxis() -> SetTitle( "Time (H:M:S)" );
    H1Dvsec[ ch ] -> GetXaxis() -> CenterTitle();
    H1Dvsec[ ch ] -> GetYaxis() -> SetTitle( "Integrated Voltage (Vsec)" );
    H1Dvsec[ ch ] -> GetYaxis() -> CenterTitle();
    H1Dvsec[ ch ] -> GetYaxis() -> SetNoExponent();

  }

  //表示するのは 7,8,9 15,16,17 22,23,24
  CVvsec -> cd( 1 );
  H1Dvsec[ 7 ] -> Draw("pe");
  CVvsec -> cd( 2 );
  H1Dvsec[ 8 ] -> Draw("pe");
  CVvsec -> cd( 3 );
  H1Dvsec[ 9 ] -> Draw("pe");
  CVvsec -> cd( 4 );
  H1Dvsec[ 15 ] -> Draw("pe");
  CVvsec -> cd( 5 );
  H1Dvsec[ 16 ] -> Draw("pe");
  CVvsec -> cd( 6 );
  H1Dvsec[ 17 ] -> Draw("pe");
  CVvsec -> cd( 7 );
  H1Dvsec[ 22 ] -> Draw("pe");
  CVvsec -> cd( 8 );
  H1Dvsec[ 23 ] -> Draw("pe");
  CVvsec -> cd( 9 );
  H1Dvsec[ 24 ] -> Draw("pe");

  return;
}

Tvoid event()
{
  Tint eventid;
  record[ 0 ][ 0 ][ 0 ].StorePrimitive( eventid );
  if ( eventid == pedbegin ) {
    record[1][0][1].StorePrimitive(pedbeginclock);
  }
  if ( eventid == pedend ) {
    record[1][0][1].StorePrimitive(pedendclock);
  }

  for ( Tint ch = 0; ch < npin; ch ++ ) {
    // VDCのスナップショット
    record[ 1 ][ ch ][ 0 ].StorePrimitive( vdc[ ch ] );

    // 前の読みだしからの経過秒数(msec)
    Tdouble secbuf;
    record[ 1 ][ ch ][ 4 ].StorePrimitive(secbuf);

    // msec -> sec
    secbuf /= 1000.0;

    // ペデスタルを引いたものを使う
    Tdouble pedbuf = getpedestal( ch, eventid );
    integrated[ ch ] += ( vdc[ch] - pedbuf ) * secbuf;

    // ラン開始からの経過秒数(sec)
    record[ 1 ][ ch ][ 3 ].StorePrimitive( elapsed[ ch ] );

    // 積分電圧 VS 時間
    H1Dvsec[ ch ] -> SetBinContent( elapsed[ ch ], integrated[ ch ] );

    H1Dvsec[ ch ] -> GetXaxis() -> SetNdivisions( 504 );
    H1Dvsec[ ch ] -> GetXaxis() -> SetTimeFormat( "%H:%M:%S" );
    H1Dvsec[ ch ] -> GetXaxis() -> SetTitle( "Time (H:M:S)" );
    H1Dvsec[ ch ] -> GetXaxis() -> CenterTitle();
    H1Dvsec[ ch ] -> GetYaxis() -> SetTitle( "Integrated Voltage (Vsec)" );
    H1Dvsec[ ch ] -> GetYaxis() -> CenterTitle();
    H1Dvsec[ ch ] -> GetYaxis() -> SetNoExponent();

    H1Dvsec[ ch ] -> SetDrawOption( "pe" );
  }


  // update
  if ( eventid % modperiod == 0 ) {
    for ( Tint i = 0; i < npadvsec; i ++ ) {
      CVvsec -> GetPad(i+1)->Modified();
      CVvsec -> GetPad(i+1)->Update();
    }
  }

  return;
}

Tvoid runbegin()
{
  Tint secbuf;
  record[ 0 ][ 1 ][ 1 ].StorePrimitive( secbuf );
  gStyle -> SetTimeOffset( secbuf );

  for ( Tint ch = 0; ch < npin; ch ++ ) {
    vdc[ch] = 0.0;
    elapsed[ch] = 0;
    integrated[ch] = 0.0;
  }

  pedbeginclock = "----/--/-- --:--:--(undefine)";
  pedendclock = "----/--/-- --:--:--(undefine)";
  record[0][1][0].StorePrimitive(runbeginclock);
  runendclock = "----/--/-- --:--:--(undefine)";
  return;
}

Tvoid runend()
{
  record[0][1][0].StorePrimitive(runendclock);

  Tofstream ofs(dataf.c_str());
  ofs << "// RUN ID: " << runid << Tendl;
  ofs << "// RUN BEGIN: " << runbeginclock << Tendl;
  ofs << "// RUN END: " << runendclock << Tendl;
  ofs << "// PEDESTAL BEGIN: " << ped0path << Ttab << pedbegin << Ttab << pedbeginclock << Tendl;
  ofs << "// PEDESTAL END: " << ped1path << Ttab << pedend << Ttab << pedendclock << Tendl;
  for ( Tint ch = 0; ch < npin; ch ++ ) {
    ofs << ch << Ttab << H1Dvsec[ch] -> GetMaximum() << Tendl;
  }
  ofs.close();


  // update
  for ( Tint i = 0; i < npadvsec; i ++ ) {
    CVvsec -> GetPad(i+1)->Modified();
    CVvsec -> GetPad(i+1)->Update();
  }


  // printout
  CVvsec -> cd();
  TFile* file = new TFile( rootf.c_str(), "RECREATE", "INTEGRATED VOLTAGE VIEW OFFLINE" );
  for ( Tint ch = 0; ch < npin; ch ++ ) {
    H1Dvsec[ ch ] -> Write();
  }
  CVvsec -> Write();
  file -> Close();

  CVvsec -> Print( giff.c_str() );
  CVvsec -> Print( psf.c_str() );

  return;
}

Tdouble getpedestal( Tint ch, Tint eventid )
{
  if ( eventid >= 0 && eventid < pedbegin ) {
    return ped0[ch];
  } else if ( eventid > pedend ) {
    return ped1[ch];
  } else if ( eventid >= pedbegin && eventid <= pedend ) {
    Tdouble a = (ped1[ch]-ped0[ch])/(Tdouble)(pedend-pedbegin);
    Tdouble b = ped0[ch] - a*(Tdouble)pedbegin;
    //どっちでも同じ結果になることは確認済
    //Tdouble b = ped1[ch] - a*(Tdouble)pedend;
    return (a*(Tdouble)eventid) + b;
  } else {
    Tcerr << "EVENT: " << eventid << Ttab;
    Tcerr << "BEGIN: " << pedbegin << Ttab;
    Tcerr << "END: " << pedbegin << Tendl;
    exit( -1 );
  }
}
