////////// ///////// ///////// //////// ///////// ///////// ///////// 72
////////////////////////////////////////////////////////////////////////
// Program name: CDAnaModule.cxx
//
// Package: CalDetTracker
//
// Purpose: 
//
// Contact: Jeff Hartnell
////////////////////////////////////////////////////////////////////////

#include "TObject.h"
#include "TH1F.h"
#include "TFile.h"
#include "TProfile.h"
#include "TGraph.h"

#include "MessageService/MsgService.h"
#include "MinosObjectMap/MomNavigator.h"
#include "JobControl/JobCModuleRegistry.h"

#include "RawData/RawRecord.h"
#include "RawData/RawDaqSnarlHeader.h"
#include "RawData/RawDigitDataBlock.h"
#include "RawData/RawDeadChipBlock.h"
#include "RawData/RawDigit.h"
#include "Validity/VldContext.h"

#include "CalDetTracker/CDAnaModule.h"

CVSID("$Id: CDAnaModule.cxx,v 1.5 2005/08/28 01:41:37 rhatcher Exp $");

JOBMODULE(CDAnaModule,"CDAnaModule","Bla");

//......................................................................

CDAnaModule::CDAnaModule()
{
  fSnarl=-1;
  fRun=-1;
  fSubrun=-1;
  fSec=-1;
  fDetector=Detector::kUnknown;
  
  fPrevEvT=-2;
  fPrevEvT1=-2;
  fPrevEvT2=-2;
  fNextEvT=-1;
  fNextEvT1=-1;
  fNextEvT2=-1;
  fT=-1;
  fT1=-1;
  fT2=-1;

  smallestT1=1e10;
  largestT2=0;

  string sFileName="cdTiming.root";
  fOutFile=new TFile(sFileName.c_str(),"RECREATE");

  htEarliest=new TH1F("htEarliest","htEarliest",4000,0,1e9);
  htEarliest->GetXaxis()->SetTitle("Time in second");
  htEarliest->GetXaxis()->CenterTitle();
  htEarliest->GetYaxis()->SetTitle("");
  htEarliest->GetYaxis()->CenterTitle();
  htEarliest->SetFillColor(0);
  //htEarliest->SetBit(TH1::kCanRebin);

  htEarliestScint=new TH1F("htEarliestScint","htEarliestScint",
				 4000,0,1e9);
  htEarliestScint->GetXaxis()->SetTitle("Time in second (VA scint)");
  htEarliestScint->GetXaxis()->CenterTitle();
  htEarliestScint->GetYaxis()->SetTitle("");
  htEarliestScint->GetYaxis()->CenterTitle();
  htEarliestScint->SetFillColor(0);
  //htEarliestScint->SetBit(TH1::kCanRebin);

  htLatest=new TH1F("htLatest","htLatest",4000,0,1e9);
  htLatest->GetXaxis()->SetTitle("Time in second");
  htLatest->GetXaxis()->CenterTitle();
  htLatest->GetYaxis()->SetTitle("");
  htLatest->GetYaxis()->CenterTitle();
  htLatest->SetFillColor(0);
  //htLatest->SetBit(TH1::kCanRebin);

  htLatestScint=new TH1F("htLatestScint","htLatestScint",
			       4000,0,1e9);
  htLatestScint->GetXaxis()->SetTitle("Time in second (VA scint)");
  htLatestScint->GetXaxis()->CenterTitle();
  htLatestScint->GetYaxis()->SetTitle("");
  htLatestScint->GetYaxis()->CenterTitle();
  htLatestScint->SetFillColor(0);
  //htLatestScint->SetBit(TH1::kCanRebin);

  hdt=new TH1F("hdt","hdt",1000,0,1e9);
  hdt->GetXaxis()->SetTitle("dt (ns)");
  hdt->GetXaxis()->CenterTitle();
  hdt->GetYaxis()->SetTitle("");
  hdt->GetYaxis()->CenterTitle();
  hdt->SetFillColor(0);
  //hdt->SetBit(TH1::kCanRebin);

  hdtZoom=new TH1F("hdtZoom","hdtZoom",200,0,200000);
  hdtZoom->GetXaxis()->SetTitle("dt (ns)");
  hdtZoom->GetXaxis()->CenterTitle();
  hdtZoom->GetYaxis()->SetTitle("");
  hdtZoom->GetYaxis()->CenterTitle();
  hdtZoom->SetFillColor(0);
  //hdtZoom->SetBit(TH1::kCanRebin);

  hdtDeadChips=new TH1F("hdtDeadChips","hdtDeadChips",
			      200,0,200000);
  hdtDeadChips->GetXaxis()->SetTitle("dt (ns)");
  hdtDeadChips->GetXaxis()->CenterTitle();
  hdtDeadChips->GetYaxis()->SetTitle("");
  hdtDeadChips->GetYaxis()->CenterTitle();
  hdtDeadChips->SetFillColor(0);
  hdtDeadChips->SetLineColor(2);

  pTimeVsdt=new TProfile("pTimeVsdt","pTimeVsdt",
				   20000,0,800000);
  pTimeVsdt->GetXaxis()->SetTitle("dt (ns)");
  pTimeVsdt->GetXaxis()->CenterTitle();
  pTimeVsdt->GetYaxis()->SetTitle("Time in second");
  pTimeVsdt->GetYaxis()->CenterTitle();
  //hdtDeadChips->SetFillColor(0);
  //hdtDeadChips->SetLineColor(2);
  //hdtDeadChips->SetBit(TH1::kCanRebin);

  gTimeVsdt=new TGraph(200);
  gTimeVsdt->SetName("gTimeVsdt");
  gTimeVsdt->SetTitle("Time in second vs delta T (all in ns)");
  //gTimeVsdt->GetXaxis()->SetTitle("dt (ns)");
  //gTimeVsdt->GetXaxis()->CenterTitle();
  //gTimeVsdt->GetYaxis()->SetTitle("Time in second");
  //gTimeVsdt->GetYaxis()->CenterTitle();
  //hdtDeadChips->SetFillColor(0);
  gTimeVsdt->SetMarkerColor(2);
  gTimeVsdt->SetMarkerStyle(8);

  gAdcVsTime=new TGraph(200);
  gAdcVsTime->SetName("gAdcVsTime");
  gAdcVsTime->SetTitle("ADC vs Time");
  //gAdcVsTime->GetXaxis()->SetTitle("dt (ns)");
  //gAdcVsTime->GetXaxis()->CenterTitle();
  //gAdcVsTime->GetYaxis()->SetTitle("Time in second");
  //gAdcVsTime->GetYaxis()->CenterTitle();
  //hdtDeadChips->SetFillColor(0);
  gAdcVsTime->SetMarkerColor(2);
  gAdcVsTime->SetMarkerStyle(8);

  gAdcVsTimeZoom=new TGraph(10);
  gAdcVsTimeZoom->SetName("gAdcVsTimeZoom");
  gAdcVsTimeZoom->SetTitle("ADC vs Time (zoom)");
  //gAdcVsTimeZoom->GetXaxis()->SetTitle("dt (ns)");
  //gAdcVsTimeZoom->GetXaxis()->CenterTitle();
  //gAdcVsTimeZoom->GetYaxis()->SetTitle("Time in second");
  //gAdcVsTimeZoom->GetYaxis()->CenterTitle();
  //hdtDeadChips->SetFillColor(0);
  gAdcVsTimeZoom->SetMarkerColor(2);
  gAdcVsTimeZoom->SetMarkerStyle(8);

  gTtagTime=new TGraph(1);
  gTtagTime->SetName("gTtagTime");
  gTtagTime->SetTitle("TTag time(s)");
  //gTtagTime->GetXaxis()->SetTitle("dt (ns)");
  //gTtagTime->GetXaxis()->CenterTitle();
  //gTtagTime->GetYaxis()->SetTitle("Time in second");
  //gTtagTime->GetYaxis()->CenterTitle();
  //hdtDeadChips->SetFillColor(0);
  gTtagTime->SetMarkerColor(4);
  gTtagTime->SetMarkerStyle(8);

  gTtagTimeZoom=new TGraph(1);
  gTtagTimeZoom->SetName("gTtagTimeZoom");
  gTtagTimeZoom->SetTitle("TTag time(s)");
  //gTtagTimeZoom->GetXaxis()->SetTitle("dt (ns)");
  //gTtagTimeZoom->GetXaxis()->CenterTitle();
  //gTtagTimeZoom->GetYaxis()->SetTitle("Time in second");
  //gTtagTimeZoom->GetYaxis()->CenterTitle();
  //hdtDeadChips->SetFillColor(0);
  gTtagTimeZoom->SetMarkerColor(4);
  gTtagTimeZoom->SetMarkerStyle(8);
}

//......................................................................

CDAnaModule::~CDAnaModule()
{
  if (fOutFile){
    gTimeVsdt->Write();
    gAdcVsTime->Write();
    gAdcVsTimeZoom->Write();
    gTtagTime->Write();
    gTtagTimeZoom->Write();
    fOutFile->cd();
    fOutFile->Write();
    fOutFile->Close();
  }
}

//......................................................................

JobCResult CDAnaModule::Ana(const MomNavigator *mom) 
{
  JobCResult result(JobCResult::kPassed);

  RawRecord *rr=dynamic_cast<RawRecord *>
    (mom->GetFragment("RawRecord"));
  if (rr==0) {
    MSG("CDTrackerModule", Msg::kWarning) 
      <<"No RawRecord in MOM." << endl;
    result.SetFailed();
    return result;
  }
  
  const RawDaqSnarlHeader* snarlHdr =
    dynamic_cast<const RawDaqSnarlHeader*>(rr->GetRawHeader());
  if(snarlHdr){
    fSnarl=snarlHdr->GetSnarl();
    fRun=snarlHdr->GetRun();
    fSubrun=snarlHdr->GetSubRun();
    fSec=snarlHdr->GetVldContext().GetTimeStamp().GetSec();
    fDetector=snarlHdr->GetVldContext().GetDetector();
  }
  else{
    MSG("CDTrackerModule", Msg::kWarning) 
      <<"No RawDaqSnarlHeader in MOM."<<endl;
    result.SetFailed();
    return result;
  }

  const RawDeadChipBlock* deadblock=
    dynamic_cast<const RawDeadChipBlock*>
    (rr->FindRawBlock("RawDeadChipBlock"));
  Int_t numDeadChips=-1;
  if(deadblock) {
    numDeadChips=deadblock->GetNumberOfEntries();
  }

  const RawDigitDataBlock *rddb=dynamic_cast<const RawDigitDataBlock *>
    (rr->FindRawBlock("RawDigitDataBlock"));

  Double_t earliestT=1e10;
  Double_t latestT=0;
  Double_t earliestScintT=1e10;
  Double_t latestScintT=0;

  //times taken from Calibrator::GetTDCConvert
  Double_t secsPerVaTick=25/16.;//(640MHz)
  Double_t secsPerQieTick=1000./53.1;// clock is 53.1MHz

  //CalDet has yet a different clock frequency
  if (fDetector==Detector::kCalDet){
    secsPerQieTick=1.5625*16.0*58.0/77.0;
  }

  MAXMSG("CDTrackerModule", Msg::kVerbose,1000) 
    <<"secsPerVaTick="<<secsPerVaTick<<endl;

  /*

Large dt: snarl=1784, sec=1033300996, numDeadChips=1
Previous time=(813178545.3 -> 813178825.0)
                     dt=1335.373 us
This one time=(814514198.4 -> 814514475.0)
                     dt=13596.958 us
Next     time=(828111432.8 -> 828111700.0)

  */

  
  Int_t second=1063522292;//1033300999;//1033301498;//1033300996;//1033302919;//1033300999//1033301517
  //second=2000000000;
  Bool_t skipSeconds=false;
  if (skipSeconds){
    if (fSec<second){
      MAXMSG("CDTrackerModule",Msg::kInfo,1)
	<<endl<<"Skipping seconds to get to second="<<second
	<<"..."<<endl;
      return result;    
    }
    if (fSec>second) {
      MAXMSG("CDTrackerModule",Msg::kInfo,1)
	<<endl<<"Not looking at any more seconds beyond second="<<second
	<<"..."<<endl;
      return result;
    }
  }

  Int_t lemoCounter=0;
  vector<Double_t> lemoTimes(6,-1);
  Double_t ttagTime=-1;
  Int_t ttagAdc=-1;
  Double_t dtLemoTtag=-1;
  Double_t dtLemoTtagMin=1e9;
  static Bool_t foundQie=false;

  //looping to find particular channel
  if (rddb) {
    TIter it=rddb->GetDatumIter();
    while (TObject *obj=it.Next()) {
      RawDigit* rvd=dynamic_cast<RawDigit*>(obj);
      if (rvd) {

	//take out the timing fid from each snarl...
	RawChannelId timingFid(Detector::kCalDet,ElecType::kVA,
			       0,2,5,1,2,16);
	if (timingFid.IsSameChannel(rvd->GetChannel())) continue;
	
	//use va first then check if qie
	Double_t time=(rvd->GetTDC())*secsPerVaTick;
	if (rvd->GetChannel().GetElecType()==ElecType::kQIE){
	  foundQie=true;
	  time=(rvd->GetTDC())*secsPerQieTick;
	  string sTime=Form("%.1f",time);
	  MAXMSG("CDTrackerModule", Msg::kInfo,100)
	    <<"TDC="<<rvd->GetTDC()
	    <<", time="<<sTime
	    <<", ADC="<<rvd->GetADC()
	    <<", chan="<<rvd->GetChannel().GetVaChannel()
	    <<endl;
	}
	
	Int_t adc=rvd->GetADC();
	if (rvd->GetChannel().GetVmm()==6){
	  Int_t lemoVarc=rvd->GetChannel().GetVarcId();
	  Int_t lemoCrate=rvd->GetChannel().GetCrate();
	  Int_t lemoIndex=lemoCrate*3+lemoVarc;
	  string sTime=Form("%.1f",time);
	  MAXMSG("CDTrackerModule", Msg::kInfo,100)
	    <<"TDC="<<rvd->GetTDC()
	    <<", time="<<sTime
	    <<", ADC="<<rvd->GetADC()
	    <<", chan="<<rvd->GetChannel().GetVaChannel()
	    <<", crate="<<lemoCrate
	    <<", varc="<<lemoVarc
	    <<", index="<<lemoIndex
	    <<endl;
	  lemoCounter++;
	  
	  //find the largest lemo ttag time diff
	  Double_t dt=time-ttagTime;
	  if (dt>dtLemoTtag) dtLemoTtag=dt;
	  if (dt<dtLemoTtagMin) dtLemoTtagMin=dt;
	  
	  if (lemoIndex<6){
	    lemoTimes[lemoIndex]=time;
	  }
	  else cout<<"ahhhhh strange lemo..."<<endl;
	}
	else if (rvd->GetChannel().GetVmm()==5){
	  RawChannelId ttag(Detector::kCalDet,ElecType::kVA,
			    0,2,5,1,1,16);
	  if (ttag.IsSameChannel(rvd->GetChannel())){
	    ttagTime=time;
	    ttagAdc=adc;
	    string sTime=Form("%.1f",time);
	    MAXMSG("CDTrackerModule", Msg::kInfo,20) 
	      <<"Found ttag, time="<<sTime<<", adc="<<ttagAdc<<endl;
	    static Int_t tti=0;
	    gTtagTime->SetPoint(tti,time,adc);
	    tti++;
	  }
	}

	//calc times
	if (time>latestT) latestT=time;
	if (time<earliestT) earliestT=time;
	if (rvd->GetChannel().GetVmm()<5){
	  if (time>latestScintT) latestScintT=time;
	  if (time<earliestScintT) earliestScintT=time;
	}

	//store all the hits in a particular second
	if (fSec==second){
	  static Int_t i=0;
	  gAdcVsTime->SetPoint(i,time,rvd->GetADC());
	  i++;
	  
	  //now look at the zoom
	  Double_t timeInSec=78137900;//330610000;//467440000;//467649000;//331466423.4;//828111432.8;//385630640.6;//4.67649e8;
	  Double_t gate=70e3;//ns so 200 us
	  //Double_t gate=20000e6;
	  if (time>timeInSec-gate && time<timeInSec+gate){
	    static Int_t i2=0;
	    gAdcVsTimeZoom->SetPoint(i2,time,rvd->GetADC());
	    i2++;
	    string sTime=Form("%.1f",time);
	    MAXMSG("CDTrackerModule", Msg::kInfo,1000) 
	      <<"Sec="<<fSec<<", TDC="<<rvd->GetTDC()
	      <<", time="<<sTime
	      <<", ADC="<<rvd->GetADC()
	      <<", vmm="<<rvd->GetChannel().GetVmm()
	      <<","<<rvd->GetChannel().GetVaAdcSel()
	      <<","<<rvd->GetChannel().GetVaChip()
	      <<","<<rvd->GetChannel().GetVaChannel()
	      <<endl;

	    //fill graph for ttag
	    if (rvd->GetChannel().GetVmm()==5){
	      RawChannelId ttag(Detector::kCalDet,ElecType::kVA,
				0,2,5,1,1,16);
	      if (ttag.IsSameChannel(rvd->GetChannel())){
		static Int_t tti=0;
		gTtagTimeZoom->SetPoint(tti,time,adc);
		tti++;
	      }
	    }
	  }
	  else{
	    MAXMSG("CDTrackerModule", Msg::kVerbose,1000) 
	      <<"Not in gate: sec="<<fSec<<", TDC="<<rvd->GetTDC()
	      <<", time="<<time
	      <<", ADC="<<rvd->GetADC()<<endl;
	  }
	}
	else if (fSnarl==18926){
	  string sTime=Form("%.1f",time);
	  MAXMSG("CDTrackerModule", Msg::kInfo,1000) 
	    <<"snl="<<fSnarl<<", Sec="<<fSec<<", TDC="<<rvd->GetTDC()
	    <<", time="<<sTime
	    <<", ADC="<<rvd->GetADC()<<endl;
	}
      }
    }
  }
  else{
    MSG("CDTrackerModule", Msg::kWarning) 
      <<"No RawDigitDataBlock"<<endl;
    result.SetFailed();
    return result;
  }

  if ((lemoCounter!=6 && !foundQie) || (lemoCounter!=3 && foundQie)){
    string sTimeEarliest=Form("%.1f",earliestT);
    string sTimeLatest=Form("%.1f",latestT);
    MAXMSG("CDTrackerModule", Msg::kInfo,1000) 
      <<"snarl="<<fSnarl<<", sec="<<fSec
      <<", lemoCount="<<lemoCounter
      <<", rddbNum="<<rddb->GetNumberOfDigits()
      <<", time=("<<sTimeEarliest<<" -> "<<sTimeLatest<<")"<<endl;
  }

  MAXMSG("CDTrackerModule", Msg::kInfo,10) 
    <<"snarl="<<fSnarl<<", sec="<<fSec<<" Lemodt="<<dtLemoTtag
    <<", lemo="<<lemoCounter
    <<", #rddb="<<rddb->GetNumberOfDigits()
    <<", t=("<<earliestT<<" -> "<<latestT<<")"<<endl;

  if ((dtLemoTtag>150 || dtLemoTtagMin<5) && ttagTime>0){
    string sTimeEarliest=Form("%.1f",earliestT);
    string sTimeLatest=Form("%.1f",latestT);
    string sTimeTtag=Form("%.1f",ttagTime);
    string sdtLemoTtag=Form("%.1f",dtLemoTtag);
    string sdtLemoTtagMin=Form("%.1f",dtLemoTtagMin);
    
      MAXMSG("CDTrackerModule", Msg::kInfo,100) 
      <<"** snl="<<fSnarl//<<", sec="<<fSec
      <<" Ldt="<<sdtLemoTtag
      <<"->"<<sdtLemoTtagMin
      <<", #L="<<lemoCounter
      <<", #d="<<rddb->GetNumberOfDigits()<<endl
      <<"    ttagTime="<<sTimeTtag
      <<", t=("<<sTimeEarliest<<" -> "<<sTimeLatest<<")"<<endl;
  }

  //set them to something named appropriately
  fNextEvT1=earliestT;
  fNextEvT2=latestT;
  fNextEvT=fSec;

  string sPrevEvT1=Form("%.1f",fPrevEvT1);
  string sPrevEvT2=Form("%.1f",fPrevEvT2);
  string sT1=Form("%.1f",fT1);
  string sT2=Form("%.1f",fT2);
  string sNextEvT1=Form("%.1f",fNextEvT1);
  string sNextEvT2=Form("%.1f",fNextEvT2);

  //calculate the delta Ts and check that same second
  Double_t pre_dt=fT1-fPrevEvT2;
  Double_t post_dt=fNextEvT1-fT2;
  string sPre_dt=Form("%.3f",(pre_dt/1000.));
  if (fT!=fPrevEvT) {
    pre_dt=1e9;//no good
    sPre_dt="wrap around";
  }
  string sPost_dt=Form("%.3f",(post_dt/1000));
  if (fT!=fNextEvT) {
    post_dt=1e9;//no good
    sPost_dt="wrap around";
  }

  //fill the histos
  htEarliest->Fill(earliestT);
  htLatest->Fill(latestT);
  htEarliestScint->Fill(earliestScintT);
  htLatestScint->Fill(latestScintT);
  hdt->Fill(post_dt);
  hdtZoom->Fill(post_dt);

  if (numDeadChips>0){
    hdtDeadChips->Fill(post_dt);
    pTimeVsdt->Fill(post_dt,earliestT);
    if (gTimeVsdt){
      static Int_t i=1;
      gTimeVsdt->SetPoint(i,post_dt,earliestT);
      i++;
    }
    else cout<<"ahhhh"<<endl;

    if (post_dt>10e6 && post_dt<1e9){// ms!
      MAXMSG("CDTrackerModule", Msg::kInfo,100) 
	<<endl
	<<"Large dt: snarl="<<fSnarl-1<<", sec="<<fSec
	<<", numDeadChips="<<numDeadChips<<endl
	<<"Previous time=("<<sPrevEvT1<<" -> "<<sPrevEvT2<<")"<<endl
	<<"                     dt="<<sPre_dt<<" us"<<endl
	<<"This one time=("<<sT1<<" -> "<<sT2<<")"<<endl
	<<"                     dt="<<sPost_dt<<" us"<<endl
	<<"Next     time=("<<sNextEvT1<<" -> "<<sNextEvT2<<")"<<endl
	<<endl;
    }
  }

  if (post_dt<49000){
    MAXMSG("CDTrackerModule", Msg::kInfo,100) 
      <<endl
      <<"Snarl="<<fSnarl-1<<", sec="<<fSec
      <<", numDeadChips="<<numDeadChips<<endl
      <<"Previous time=("<<sPrevEvT1<<" -> "<<sPrevEvT2<<")"<<endl
      <<"                     dt="<<sPre_dt<<" us"<<endl
      <<"This one time=("<<sT1<<" -> "<<sT2<<")"<<endl
      <<"                     dt="<<sPost_dt<<" us"<<endl
      <<"Next     time=("<<sNextEvT1<<" -> "<<sNextEvT2<<")"<<endl
      <<endl;
  }

  //cascade the values down
  fPrevEvT1=fT1;
  fPrevEvT2=fT2;
  fPrevEvT=fT;
  fT1=earliestT;
  fT2=latestT;
  fT=fSec;

  //work out the times nearest the boundaries
  if (earliestT<smallestT1) smallestT1=earliestT;
  if (latestT>largestT2) largestT2=latestT;

  //return the final result
  return result;
}

//......................................................................

void CDAnaModule::EndJob() 
{
  string sLower_dt=Form("%.3f",(smallestT1/1000.));//us
  string sUpper_dt=Form("%.3f",((1e9-largestT2)/1000.));//us

  MSG("CDTrackerModule", Msg::kInfo) 
    <<"Times closest to timeframe boundaries in run "<<fRun<<endl
    <<"  Lower time: "<<smallestT1<<" (dt="<<sLower_dt<<" us)"<<endl
    <<"  Upper time: "<<largestT2<<" (dt="<<sUpper_dt<<" us)"
    <<endl;
}

//......................................................................
