// =====================================================================
//  $Id: rs01view.cc,v 1.14 2003/10/17 04:44:40 goiwai Exp $
//  $Name: CLDAQ-1-14-03 $
//  $Log: rs01view.cc,v $
//  Revision 1.14  2003/10/17 04:44:40  goiwai
//  プロファイルモニターの左上の図をペデスタルを引いた電圧のプロットにしま
//  した.これまではペデスタルを考慮しないプロットでした.
//
//  Revision 1.13  2003/10/16 12:54:57  goiwai
//  特別なチャンネルには色をつけて表示するようにしました
//
//  Revision 1.12  2003/10/16 07:56:43  goiwai
//  若干の修正をしました
//
//  Revision 1.11  2003/10/14 22:44:42  goiwai
//  別々のアップデートサイクルにしました.
//  これで両方起動してもよさげです.
//
//  Revision 1.10  2003/10/12 22:52:22  goiwai
//  秋のビームテストにむけての若干の修正.
//  パラメーターやROOTオブジェクトの出力.
//  WEB閲覧用に毎イベントGIFの出力.
//  オンラインストリームの採用.
//
//  Revision 1.9  2003/10/06 16:28:15  goiwai
//  *** empty log message ***
//
//  Revision 1.8  2003/07/30 16:14:41  goiwai
//  ファイルにコミットログをつけることにしました.
//
// =====================================================================
#include "TDataRecord.hh"
#include "TDataSection.hh"
#include "TDataSegment.hh"
#include "TDataElement.hh"
#include "TEnvironmentVariableTable.hh"
#include "TInputObjectFileOnline.hh"
#include "TSystemClock.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;
TDataElement element;
Tdouble vdc[ npin ];
Tint elapsed[ npin ];
Tdouble integrated[ npin ];
Tdouble pedestal[ npin ];

Tstring lastupdate[ npin ];
//
TApplication* theApplication = 0;
TCanvas* CVpro = 0;
TCanvas* CVvdc = 0;
static const Tint nx = 8;
static const Tint ny = 5;

TH2D* H2Dpro = 0;
TH2D* H2Dint = 0;
TPaveText* PTinfo;

Tofstream runlog;
Tstring fpath, macrof, giff, psf, rootf, webdir;
static Tbool autoprint, enableoverwrite;
static Tint modperiod;

static Tvoid initialize( Tint argc, Tchar** argv );
static Tvoid event();
static Tvoid runbegin();
static Tvoid runend();
static Tbool iscenter( Tint ch );
static Tbool isaround( Tint ch );

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 -> Run();
  return 0;
}

Tvoid initialize( Tint argc, Tchar** argv )
{
  if ( argc != 2 ) {
    Tcerr << "usage: " << argv[ 0 ] << " <run#>" << Tendl;
    exit( -1 );
  }

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

  Tstring htpro = "Beam Profile Monitor(Snapshot), 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";
  Tstring logpath = envtable -> GetEnvironmentValue( "RS01_LOG_DIR" );
  logpath = logpath + Tslash + rechead + runidstr + ".log";
  ifile = new TInputObjectFileOnline( fpath );
  runlog.open( logpath.c_str() );


  Tstring rootdir = envtable -> GetEnvironmentValue( "RS01_ROOTFILE_DIR" );
  rootf = rootdir + Tslash + rechead + runidstr + "bpm.root";
  Tstring macrodir = envtable -> GetEnvironmentValue( "RS01_ROOTFILE_DIR" );
  macrof = macrodir + Tslash + rechead + runidstr + "bpm.C";
  Tstring gifdir = envtable -> GetEnvironmentValue( "RS01_FIGURE_DIR" );
  giff = gifdir + Tslash + rechead + runidstr + "bpm.gif";
  Tstring psdir = envtable -> GetEnvironmentValue( "RS01_FIGURE_DIR" );
  psf = psdir + Tslash + rechead + runidstr + "bpm.ps";
  webdir = envtable -> GetEnvironmentValue( "RS01_WEB_DIR" );


  modperiod = envtable -> GetIntegerValue( "RS01_UPDATE_PERIOD_BPM" );
  enableoverwrite = (Tbool)envtable -> GetIntegerValue( "RS01_OVERWRITE_ENABLE" );
  autoprint = (Tbool)envtable -> GetIntegerValue( "RS01_AUTO_PRINT" );


  // ペデスタル
  for ( Tint i = 0; i < npin; i ++ ) {
    Tstring item = "RS01_PEDESTAL_" + itostr( i, 2 );
    pedestal[ i ] = envtable -> GetDoubleValue( item );
  }


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

  // ヒットの2D キャンバス
  CVpro = new TCanvas( "CVpro", "Distribution", 960, 720 );
  CVpro -> ToggleEventStatus();
  CVpro -> Divide( 2, 1 );
  CVpro -> GetPad( 1 ) -> Divide( 1, 2 );

  // ヒット分布の初期設定
  H2Dpro = new TH2D( "H2Dpro", htpro.c_str(), 8, 0.0, 8.0, 5, 0.0, 5.0 );
  H2Dpro -> SetStats(0);
  H2Dpro -> GetXaxis() -> SetTitle( "Horizontal Position" );
  H2Dpro -> GetXaxis() -> SetNoExponent();
  H2Dpro -> GetXaxis() -> CenterTitle();
  H2Dpro -> GetXaxis() -> SetNdivisions( 8 );
  H2Dpro -> GetXaxis() -> CenterLabels();

  H2Dpro -> GetYaxis() -> SetTitle( "Vertical Position" );
  H2Dpro -> GetYaxis() -> SetNoExponent();
  H2Dpro -> GetYaxis() -> CenterTitle();
  H2Dpro -> GetYaxis() -> SetNdivisions( 5 );
  H2Dpro -> GetYaxis() -> CenterLabels();

  H2Dpro -> GetZaxis() -> SetTitle( "DC Voltage (V)");
  H2Dpro -> GetZaxis() -> CenterTitle();
  H2Dpro -> GetZaxis() -> SetNoExponent();
  CVpro -> GetPad( 1 ) -> cd( 1 );
  gPad -> SetLeftMargin( 0.16 );
  gPad -> SetRightMargin( 0.16 );
  gPad -> SetTopMargin( 0.18 );
  gPad -> SetBottomMargin( 0.2 );
  gPad -> SetGrid();
  gStyle -> SetGridStyle(1);
  H2Dpro -> Draw( "colz" );

  //
  H2Dint = new TH2D( "H2Dint", htint.c_str(), 8, 0.0, 8.0, 5, 0.0, 5.0 );
  H2Dint -> SetStats(0);
  H2Dint -> GetXaxis() -> SetTitle( "Horizontal Position" );
  H2Dint -> GetXaxis() -> SetNoExponent();
  H2Dint -> GetXaxis() -> CenterTitle();
  H2Dint -> GetXaxis() -> SetNdivisions( 8 );
  H2Dint -> GetXaxis() -> CenterLabels();

  H2Dint -> GetYaxis() -> SetTitle( "Vertical Position" );
  H2Dint -> GetYaxis() -> SetNoExponent();
  H2Dint -> GetYaxis() -> CenterTitle();
  H2Dint -> GetYaxis() -> SetNdivisions( 5 );
  H2Dint -> GetYaxis() -> CenterLabels();

  H2Dint -> GetZaxis() -> SetTitle( "Integrated Voltage (Vsec)");
  H2Dint -> GetZaxis() -> CenterTitle();
  H2Dint -> GetZaxis() -> SetNoExponent();
  CVpro -> GetPad( 1 ) -> cd( 2 );
  gPad -> SetLeftMargin( 0.16 );
  gPad -> SetRightMargin( 0.16 );
  gPad -> SetTopMargin( 0.18 );
  gPad -> SetBottomMargin( 0.2 );
  gPad -> SetGrid();
  gStyle -> SetGridStyle(1);
  H2Dint -> Draw( "colz" );



  // テキスト情報の初期設定
  PTinfo = new TPaveText( 0.02, 0.02, 0.98, 0.98 );
  PTinfo -> SetName( "PTinfo" );
  PTinfo -> SetFillColor( 10 );
  PTinfo -> SetFillStyle( 0 );
  PTinfo -> SetBorderSize( 0 );
  PTinfo -> SetTextAlign( 12 );
  CVpro -> cd( 2 );
  PTinfo -> Draw();

  return;
}

Tvoid event()
{
  H2Dpro -> Reset();
  H2Dint -> Reset();
  PTinfo -> Clear();
  element = record[ 0 ][ 0 ][ 0 ];
  Tint eventid;
  element.StorePrimitives( &eventid );
  for ( Tint ch = 0; ch < npin; ch ++ ) {
    // VDCのスナップショット
    element = record[ 1 ][ ch ][ 0 ];
    element.StorePrimitives( &vdc[ ch ] );

    // その時刻
    element = record[ 1 ][ ch ][ 1 ];
    element.StorePrimitives( &lastupdate[ ch ] );

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

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

    // VDC * sec (ペデスタルを引いたものを使う)
    // ペデスタルは Run ID 101 の とりあえずイベントID0 のもの
    // run#113以降はrun112のものを使う
    Tdouble vdcsubped = vdc[ ch ] - pedestal[ ch ];
    integrated[ ch ] += vdcsubped * secbuf;
    // ペデスタルは引かない
    //integrated[ ch ] += vdc[ ch ] * secbuf;


    // ヒット分布へのフィル
    Tint x = ( pinpos[ ch ] - 1 ) % nx;
    Tint y = ny - ( ( pinpos[ ch ] - 1 ) / nx ) - 1;
    //H2Dpro -> Fill( (Tdouble)x, (Tdouble)y, vdc[ ch ] );
    H2Dpro -> Fill( (Tdouble)x, (Tdouble)y, vdcsubped );
    H2Dint -> Fill( (Tdouble)x, (Tdouble)y, integrated[ ch ] );

    // テキストサマリ
    Tstring sbuf;
    sbuf = "CH" + itostr( ch, 2 ) + ": " + dtostr( vdc[ ch ] ) + "VDC, ";
    sbuf += itostr( elapsed[ ch ], 0 ) + "sec, ";
    sbuf += dtostr( integrated[ ch ] ) + "Vsec, ";
    sbuf += lastupdate[ ch ];
    TText* text = PTinfo -> AddText( sbuf.c_str() );
    if ( iscenter( ch ) ) {
      text -> SetTextColor( 2 );
    } else if ( isaround( ch ) ) {
      text -> SetTextColor( 4 );
    }

    // ログ出力
    runlog << ch << Ttab;
    runlog << vdc[ ch ] << Ttab;
    runlog << elapsed[ ch ] << Ttab;
    runlog << integrated[ ch ] << Ttab;
    runlog << lastupdate[ ch ] << Tendl;
  }


  // update
  if ( eventid % modperiod == 0 ) {
    CVpro -> GetPad(1)->GetPad(1)->Modified();
    CVpro -> GetPad(1)->GetPad(1)->Update();
    CVpro -> GetPad(1)->GetPad(2)->Modified();
    CVpro -> GetPad(1)->GetPad(2)->Update();
    CVpro -> GetPad(2)->Modified();
    CVpro -> GetPad(2)->Update();


    // Print as Gif Format
    TSystemClock clk;
    Tstring fn = webdir + Tslash + itostr( clk.GetTime() ) + ".gif";
    CVpro -> Print(fn.c_str());
  }



  return;
}

Tvoid runbegin()
{
  element = record[ 0 ][ 1 ][ 1 ];
  Tint secbuf;
  element.StorePrimitives( &secbuf );
  gStyle -> SetTimeOffset( secbuf );
  return;
}

Tvoid runend()
{
  // update
  CVpro -> GetPad(1)->GetPad(1)->Modified();
  CVpro -> GetPad(1)->GetPad(1)->Update();
  CVpro -> GetPad(1)->GetPad(2)->Modified();
  CVpro -> GetPad(1)->GetPad(2)->Update();
  CVpro -> GetPad(2)->Modified();
  CVpro -> GetPad(2)->Update();

  // printout
  CVpro -> cd();
  if ( !isexist( rootf ) || enableoverwrite ) {
    TFile* file = new TFile( rootf.c_str(), "RECREATE", "VIEW ONLINE" );
    H2Dpro -> Write();
    H2Dint -> Write();
    PTinfo -> Write();
    CVpro -> Write();
    file -> Close();
  }


  if ( !isexist( giff ) || enableoverwrite ) {
    CVpro -> Print( giff.c_str() );
  }
  if ( !isexist( psf ) || enableoverwrite ) {
    CVpro -> Print( psf.c_str() );
    if ( autoprint ) {
      Tstring exec = "lpr " + psf;
      system( exec.c_str() );
    }
  }

  runlog.close();
  return;
}

Tbool iscenter( Tint ch )
{
  return ( ch == 16 );
}

Tbool isaround( Tint ch )
{
  return ( ch == 7 || ch == 8 || ch == 9 || ch == 15 || ch == 17 || ch == 22 || ch == 23 || ch == 24 );
}
