From d610f241e1334e508b965d689362cf8a5aa418f6 Mon Sep 17 00:00:00 2001
From: Edward Brash <brash@jlab.org>
Date: Mon, 15 Jun 2015 11:47:30 -0400
Subject: [PATCH] Initial commit for THcScalerEventHandler plugin for Hall C
 scalers

---
 SConscript.py               |   2 +-
 src/HallC_LinkDef.h         |   1 +
 src/SConscript.py           |   1 +
 src/THcScalerEvtHandler.cxx | 426 ++++++++++++++++++++++++++++++++++++
 src/THcScalerEvtHandler.h   |  63 ++++++
 5 files changed, 492 insertions(+), 1 deletion(-)
 create mode 100644 src/THcScalerEvtHandler.cxx
 create mode 100644 src/THcScalerEvtHandler.h

diff --git a/SConscript.py b/SConscript.py
index 3d54796..e653977 100644
--- a/SConscript.py
+++ b/SConscript.py
@@ -19,7 +19,7 @@ hcheaders = Split("""
 	src/THcDCLookupTTDConv.h src/THcDCTimeToDistConv.h src/THcShower.h src/THcShowerPlane.h 
 	src/THcRawShowerHit.h src/THcAerogel.h src/THcAerogelHit.h src/THcCherenkov.h src/THcCherenkovHit.h
         src/THcGlobals.h src/THcDCTrack.h src/THcFormula.h
-        src/THcRaster.h src/THcRasteredBeam.h src/THcRasterRawHit.h
+        src/THcRaster.h src/THcRasteredBeam.h src/THcRasterRawHit.h src/THcScalerEvtHandler.h
 	src/HallC_LinkDef.h
 	""")
 pbaseenv.RootCint(roothcdict,hcheaders)
diff --git a/src/HallC_LinkDef.h b/src/HallC_LinkDef.h
index d421883..3997487 100644
--- a/src/HallC_LinkDef.h
+++ b/src/HallC_LinkDef.h
@@ -52,5 +52,6 @@
 #pragma link C++ class THcRaster+;
 #pragma link C++ class THcRasteredBeam+;
 #pragma link C++ class THcRasterRawHit+;
+#pragma link C++ class THcScalerEvtHandler+;
 
 #endif
diff --git a/src/SConscript.py b/src/SConscript.py
index 6f2abbe..eecec46 100644
--- a/src/SConscript.py
+++ b/src/SConscript.py
@@ -26,6 +26,7 @@ THcAerogel.cxx THcAerogelHit.cxx \
 THcCherenkov.cxx THcCherenkovHit.cxx \
 THcFormula.cxx \
 THcRaster.cxx THcRasteredBeam.cxx THcRasterRawHit.cxx
+THcScalerEvtHandler.cxx
 """)
 
 pbaseenv.Object('main.C')
diff --git a/src/THcScalerEvtHandler.cxx b/src/THcScalerEvtHandler.cxx
new file mode 100644
index 0000000..208b474
--- /dev/null
+++ b/src/THcScalerEvtHandler.cxx
@@ -0,0 +1,426 @@
+////////////////////////////////////////////////////////////////////
+//
+//   THcScalerEvtHandler
+//
+//   Event handler for Hall C scalers
+//   E. Brash, June, 2015
+//   based on THaScalerEvtHandler 
+//   R. Michaels,  Sept, 2014
+//
+//   This class does the following
+//      For a particular set of event types (here, event type 0)
+//      decode the scalers and put some variables into global variables.
+//      The global variables can then appear in the Podd output tree T.
+//      In addition, a tree "TS" is created by this class; it contains
+//      just the scaler data by itself.  Note, the "fName" is concatenated
+//      with "TS" to ensure the tree is unqiue; further, "fName" is
+//      concatenated with the name of the global variables, for uniqueness.
+//      The list of global variables and how they are tied to the
+//      scaler module and channels is defined here; eventually this
+//      will be modified to use a scaler.map file
+//      NOTE: if you don't have the scaler map file (e.g. Leftscalevt.map)
+//      there will be no variable output to the Trees.
+//
+//   To use in the analyzer, your setup script needs something like this
+//       gHaEvtHandlers->Add (new THcScalerEvtHandler("HMS","HC scaler event type 0"));
+//
+//   To enable debugging you may try this in the setup script
+// 
+//     THcScalerEvtHandler *hscaler = new THcScalerEvtHandler("HS","HC scaler event type 0");
+//     hscaler->SetDebugFile("HScaler.txt");
+//     gHaEvtHandlers->Add (hscaler);
+//
+/////////////////////////////////////////////////////////////////////
+
+#include "THaEvtTypeHandler.h"
+#include "THcScalerEvtHandler.h"
+#include "GenScaler.h"
+#include "Scaler3800.h"
+#include "Scaler3801.h"
+#include "Scaler1151.h"
+#include "Scaler560.h"
+#include "THaCodaData.h"
+#include "THaEvData.h"
+#include "TNamed.h"
+#include "TMath.h"
+#include "TString.h"
+#include <cstring>
+#include <cstdio>
+#include <cstdlib>
+#include <iostream>
+#include <sstream>
+#include "THaVarList.h"
+#include "VarDef.h"
+
+using namespace std;
+using namespace Decoder;
+
+static const UInt_t ICOUNT    = 1;
+static const UInt_t IRATE     = 2;
+static const UInt_t MAXCHAN   = 32;
+static const UInt_t MAXTEVT   = 5000;
+static const UInt_t defaultDT = 4;
+
+THcScalerEvtHandler::THcScalerEvtHandler(const char *name, const char* description)
+  : THaEvtTypeHandler(name,description), evcount(0), ifound(0), fNormIdx(-1),
+    dvars(0), fScalerTree(0)
+{
+  rdata = new UInt_t[MAXTEVT];
+}
+
+THcScalerEvtHandler::~THcScalerEvtHandler()
+{
+  delete [] rdata;
+  if (fScalerTree) {
+    delete fScalerTree;
+  }
+}
+
+Int_t THcScalerEvtHandler::End( THaRunBase* r)
+{
+  if (fScalerTree) fScalerTree->Write();
+  return 0;
+}
+
+Int_t THcScalerEvtHandler::Analyze(THaEvData *evdata)
+{
+  Int_t lfirst=1;
+
+  if ( !IsMyEvent(evdata->GetEvType()) ) return -1;
+
+  if (fDebugFile) {
+    *fDebugFile << endl << "---------------------------------- "<<endl<<endl;
+    *fDebugFile << "\nEnter THcScalerEvtHandler  for fName = "<<fName<<endl;
+    EvDump(evdata);
+  }
+
+  if (lfirst && !fScalerTree) {
+
+    lfirst = 0; // Can't do this in Init for some reason
+
+    TString sname1 = "TS";
+    TString sname2 = sname1 + fName;
+    TString sname3 = fName + "  Scaler Data";
+
+    if (fDebugFile) {
+      *fDebugFile << "\nAnalyze 1st time for fName = "<<fName<<endl;
+      *fDebugFile << sname2 << "      " <<sname3<<endl;
+    }
+
+    fScalerTree = new TTree(sname2.Data(),sname3.Data());
+    fScalerTree->SetAutoSave(200000000);
+
+    TString name, tinfo;
+
+    name = "evcount";
+    tinfo = name + "/D";
+    fScalerTree->Branch(name.Data(), &evcount, tinfo.Data(), 4000);
+
+    for (UInt_t i = 0; i < scalerloc.size(); i++) {
+      name = scalerloc[i]->name;
+      tinfo = name + "/D";
+      fScalerTree->Branch(name.Data(), &dvars[i], tinfo.Data(), 4000);
+    }
+
+  }  // if (lfirst && !fScalerTree)
+
+
+  // Parse the data, load local data arrays.
+
+  Int_t ndata = evdata->GetEvLength();
+  if (ndata >= static_cast<Int_t>(MAXTEVT)) {
+    cout << "THcScalerEvtHandler:: ERROR: Event length crazy "<<endl;
+    ndata = MAXTEVT-1;
+  }
+
+  if (fDebugFile) *fDebugFile<<"\n\nTHcScalerEvtHandler :: Debugging event type "<<dec<<evdata->GetEvType()<<endl<<endl;
+
+  // local copy of data
+
+  for (Int_t i=0; i<ndata; i++) rdata[i] = evdata->GetRawData(i);
+
+  Int_t nskip=0;
+  UInt_t *p = rdata;
+  UInt_t *pstop = rdata+ndata;
+  int j=0;
+
+  ifound = 0;
+
+  while (p < pstop && j < ndata) {
+    if (fDebugFile) {
+      *fDebugFile << "p  and  pstop  "<<j++<<"   "<<p<<"   "<<pstop<<"   "<<hex<<*p<<"   "<<dec<<endl;
+    }
+    nskip = 1;
+    for (UInt_t j=0; j<scalers.size(); j++) {
+      nskip = scalers[j]->Decode(p);
+      if (fDebugFile && nskip > 1) {
+	*fDebugFile << "\n===== Scaler # "<<j<<"     fName = "<<fName<<"   nskip = "<<nskip<<endl;
+	scalers[j]->DebugPrint(fDebugFile);
+      }
+      if (nskip > 1) {
+	ifound = 1;
+	break;
+      }
+    }
+    p = p + nskip;
+  }
+
+  if (fDebugFile) {
+    *fDebugFile << "Finished with decoding.  "<<endl;
+    *fDebugFile << "   Found flag   =  "<<ifound<<endl;
+  }
+
+  // FIXME: What are the HMS and SOS headers?  Are there header words?
+  //
+  // L-HRS has headers which are different from R-HRS, but both are
+  // event type 140 and come here.  If you found no headers, it was
+  // the other arms event type.  (The arm is fName).
+
+  if (!ifound) return 0;
+
+  // The correspondance between dvars and the scaler and the channel
+  // will be driven by a scaler.map file  -- later
+
+  for (UInt_t i = 0; i < scalerloc.size(); i++) {
+    UInt_t ivar = scalerloc[i]->ivar;
+    UInt_t isca = scalerloc[i]->iscaler;
+    UInt_t ichan = scalerloc[i]->ichan;
+    if (fDebugFile) *fDebugFile << "Debug dvars "<<i<<"   "<<ivar<<"  "<<isca<<"  "<<ichan<<endl;
+    if ((ivar >= 0 && ivar < scalerloc.size()) &&
+	(isca >= 0 && isca < scalers.size()) &&
+	(ichan >= 0 && ichan < MAXCHAN)) {
+      if (scalerloc[ivar]->ikind == ICOUNT) dvars[ivar] = scalers[isca]->GetData(ichan);
+      if (scalerloc[ivar]->ikind == IRATE)  dvars[ivar] = scalers[isca]->GetRate(ichan);
+      if (fDebugFile) *fDebugFile << "   dvars  "<<scalerloc[ivar]->ikind<<"  "<<dvars[ivar]<<endl;
+    } else {
+      cout << "THcScalerEvtHandler:: ERROR:: incorrect index "<<ivar<<"  "<<isca<<"  "<<ichan<<endl;
+    }
+  }
+
+  evcount = evcount + 1.0;
+
+  for (UInt_t j=0; j<scalers.size(); j++) scalers[j]->Clear("");
+
+  if (fDebugFile) *fDebugFile << "scaler tree ptr  "<<fScalerTree<<endl;
+
+  if (fScalerTree) fScalerTree->Fill();
+
+  return 1;
+}
+
+THaAnalysisObject::EStatus THcScalerEvtHandler::Init(const TDatime& date)
+{
+  const int LEN = 200;
+  char cbuf[LEN];
+
+  fStatus = kOK;
+  fNormIdx = -1;
+
+  cout << "Howdy !  We are initializing THcScalerEvtHandler !!   name =   "
+        << fName << endl;
+
+  eventtypes.push_back(0);  // what events to look for
+
+  TString dfile;
+  dfile = fName + "scaler.txt";
+
+// Parse the map file which defines what scalers exist and the global variables.
+
+  TString sname0 = "Scalevt";
+  TString sname;
+  sname = fName+sname0;
+
+  FILE *fi = OpenFile(sname.Data(), date);
+  if ( !fi ) {
+    cout << "Cannot find db file for "<<fName<<" scaler event handler"<<endl;
+    return kFileError;
+  }
+
+  size_t minus1 = -1;
+  size_t pos1;
+  string scomment = "#";
+  string svariable = "variable";
+  string smap = "map";
+  vector<string> dbline;
+
+  while( fgets(cbuf, LEN, fi) != NULL) {
+    std::string sinput(cbuf);
+    if (fDebugFile) *fDebugFile << "string input "<<sinput<<endl;
+    dbline = vsplit(sinput);
+    if (dbline.size() > 0) {
+      pos1 = FindNoCase(dbline[0],scomment);
+      if (pos1 != minus1) continue;
+      pos1 = FindNoCase(dbline[0],svariable);
+      if (pos1 != minus1 && dbline.size()>4) {
+	string sdesc = "";
+	for (UInt_t j=5; j<dbline.size(); j++) sdesc = sdesc+" "+dbline[j];
+	Int_t isca = atoi(dbline[1].c_str());
+	Int_t ichan = atoi(dbline[2].c_str());
+	Int_t ikind = atoi(dbline[3].c_str());
+	if (fDebugFile)
+	  *fDebugFile << "add var "<<dbline[1]<<"   desc = "<<sdesc<<"    isca= "<<isca<<"  "<<ichan<<"  "<<ikind<<endl;
+	TString tsname(dbline[4].c_str());
+	TString tsdesc(sdesc.c_str());
+	AddVars(tsname,tsdesc,isca,ichan,ikind);
+      }
+      pos1 = FindNoCase(dbline[0],smap);
+      if (fDebugFile) *fDebugFile << "map ? "<<dbline[0]<<"  "<<smap<<"   "<<pos1<<"   "<<dbline.size()<<endl;
+      if (pos1 != minus1 && dbline.size()>6) {
+	Int_t imodel, icrate, islot, inorm;
+	UInt_t header, mask;
+	char cdum[20];
+	sscanf(sinput.c_str(),"%s %d %d %d %x %x %d \n",cdum,&imodel,&icrate,&islot, &header, &mask, &inorm);
+	if ((fNormIdx >= 0) && (fNormIdx != inorm)) cout << "THcScalerEvtHandler::WARN:  contradictory norm index  "<<fNormIdx<<"   "<<inorm<<endl;
+	Int_t clkchan = -1;
+	Double_t clkfreq = 1;
+	if (dbline.size()>8) {
+	  clkchan = atoi(dbline[7].c_str());
+	  clkfreq = 1.0*atoi(dbline[8].c_str());
+	}
+	if (fDebugFile) {
+	  *fDebugFile << "map line "<<dec<<imodel<<"  "<<icrate<<"  "<<islot<<endl;
+	  *fDebugFile <<"   header  0x"<<hex<<header<<"  0x"<<mask<<dec<<"  "<<inorm<<"  "<<clkchan<<"  "<<clkfreq<<endl;
+	}
+	switch (imodel) {
+	case 560:
+	  scalers.push_back(new Scaler560(icrate, islot));
+	  break;
+	case 1151:
+	  scalers.push_back(new Scaler1151(icrate, islot));
+	  break;
+	case 3800:
+	  scalers.push_back(new Scaler3800(icrate, islot));
+	  break;
+	case 3801:
+	  scalers.push_back(new Scaler3801(icrate, islot));
+	  break;
+	}
+	if (scalers.size() > 0) {
+	  UInt_t idx = scalers.size()-1;
+	  scalers[idx]->SetHeader(header, mask);
+	  if (clkchan >= 0) scalers[idx]->SetClock(defaultDT, clkchan, clkfreq);
+	}
+      }
+    }
+  }
+  // can't compare UInt_t to Int_t (compiler warning), so do this
+  nscalers=0;
+  for (UInt_t i=0; i<scalers.size(); i++) nscalers++;
+  // need to do LoadNormScaler after scalers created and if fNormIdx found.
+  if ((fNormIdx >= 0) && fNormIdx < nscalers) {
+    for (Int_t i = 0; i < nscalers; i++) {
+      if (i==fNormIdx) continue;
+      scalers[i]->LoadNormScaler(scalers[fNormIdx]);
+    }
+  }
+
+#ifdef HARDCODED
+  // This code is superseded by the parsing of a map file above.  It's another way ...
+  if (fName == "Left") {
+    AddVars("TSbcmu1", "BCM x1 counts", 1, 4, ICOUNT);
+    AddVars("TSbcmu1r","BCM x1 rate",  1, 4, IRATE);
+    AddVars("TSbcmu3", "BCM u3 counts", 1, 5, ICOUNT);
+    AddVars("TSbcmu3r", "BCM u3 rate",  1, 5, IRATE);
+  } else {
+    AddVars("TSbcmu1", "BCM x1 counts", 0, 4, ICOUNT);
+    AddVars("TSbcmu1r","BCM x1 rate",  0, 4, IRATE);
+    AddVars("TSbcmu3", "BCM u3 counts", 0, 5, ICOUNT);
+    AddVars("TSbcmu3r", "BCM u3 rate",  0, 5, IRATE);
+  }
+#endif
+
+
+  DefVars();
+
+#ifdef HARDCODED
+  // This code is superseded by the parsing of a map file above.  It's another way ...
+  if (fName == "Left") {
+    scalers.push_back(new Scaler1151(1,0));
+    scalers.push_back(new Scaler3800(1,1));
+    scalers.push_back(new Scaler3800(1,2));
+    scalers.push_back(new Scaler3800(1,3));
+    scalers[0]->SetHeader(0xabc00000, 0xffff0000);
+    scalers[1]->SetHeader(0xabc10000, 0xffff0000);
+    scalers[2]->SetHeader(0xabc20000, 0xffff0000);
+    scalers[3]->SetHeader(0xabc30000, 0xffff0000);
+    scalers[0]->LoadNormScaler(scalers[1]);
+    scalers[1]->SetClock(4, 7, 1024);
+    scalers[2]->LoadNormScaler(scalers[1]);
+    scalers[3]->LoadNormScaler(scalers[1]);
+  } else {
+    scalers.push_back(new Scaler3800(2,0));
+    scalers.push_back(new Scaler3800(2,0));
+    scalers.push_back(new Scaler1151(2,1));
+    scalers.push_back(new Scaler1151(2,2));
+    scalers[0]->SetHeader(0xceb00000, 0xffff0000);
+    scalers[1]->SetHeader(0xceb10000, 0xffff0000);
+    scalers[2]->SetHeader(0xceb20000, 0xffff0000);
+    scalers[3]->SetHeader(0xceb30000, 0xffff0000);
+    scalers[0]->SetClock(4, 7, 1024);
+    scalers[1]->LoadNormScaler(scalers[0]);
+    scalers[2]->LoadNormScaler(scalers[0]);
+    scalers[3]->LoadNormScaler(scalers[0]);
+  }
+#endif
+
+  if(fDebugFile) *fDebugFile << "THcScalerEvtHandler:: Name of scaler bank "<<fName<<endl;
+  for (UInt_t i=0; i<scalers.size(); i++) {
+    if(fDebugFile) {
+      *fDebugFile << "Scaler  #  "<<i<<endl;
+      scalers[i]->SetDebugFile(fDebugFile);
+      scalers[i]->DebugPrint(fDebugFile);
+    }
+  }
+  return kOK;
+}
+
+void THcScalerEvtHandler::AddVars(TString name, TString desc, Int_t iscal,
+				  Int_t ichan, Int_t ikind)
+{
+  // need to add fName here to make it a unique variable.  (Left vs Right HRS, for example)
+  TString name1 = fName + name;
+  TString desc1 = fName + desc;
+  ScalerLoc *loc = new ScalerLoc(name1, desc1, iscal, ichan, ikind);
+  loc->ivar = scalerloc.size();  // ivar will be the pointer to the dvars array.
+  scalerloc.push_back(loc);
+}
+
+void THcScalerEvtHandler::DefVars()
+{
+  // called after AddVars has finished being called.
+  Nvars = scalerloc.size();
+  if (Nvars == 0) return;
+  dvars = new Double_t[Nvars];  // dvars is a member of this class
+  memset(dvars, 0, Nvars*sizeof(Double_t));
+  if (gHaVars) {
+    if(fDebugFile) *fDebugFile << "THcScalerEVtHandler:: Have gHaVars "<<gHaVars<<endl;
+  } else {
+    cout << "No gHaVars ?!  Well, that's a problem !!"<<endl;
+    return;
+  }
+  if(fDebugFile) *fDebugFile << "THcScalerEvtHandler:: scalerloc size "<<scalerloc.size()<<endl;
+  const Int_t* count = 0;
+  for (UInt_t i = 0; i < scalerloc.size(); i++) {
+    gHaVars->DefineByType(scalerloc[i]->name.Data(), scalerloc[i]->description.Data(),
+			  &dvars[i], kDouble, count);
+  }
+}
+
+size_t THcScalerEvtHandler::FindNoCase(const string& sdata, const string& skey)
+{
+  // Find iterator of word "sdata" where "skey" starts.  Case insensitive.
+  string sdatalc, skeylc;
+  sdatalc = "";  skeylc = "";
+  for (string::const_iterator p =
+	 sdata.begin(); p != sdata.end(); ++p) {
+    sdatalc += tolower(*p);
+  }
+  for (string::const_iterator p =
+	 skey.begin(); p != skey.end(); ++p) {
+    skeylc += tolower(*p);
+  }
+  if (sdatalc.find(skeylc,0) == string::npos) return -1;
+  return sdatalc.find(skeylc,0);
+};
+
+ClassImp(THcScalerEvtHandler)
diff --git a/src/THcScalerEvtHandler.h b/src/THcScalerEvtHandler.h
new file mode 100644
index 0000000..edc6807
--- /dev/null
+++ b/src/THcScalerEvtHandler.h
@@ -0,0 +1,63 @@
+#ifndef THcScalerEvtHandler_
+#define THcScalerEvtHandler_
+
+/////////////////////////////////////////////////////////////////////
+//
+//   THcScalerEvtHandler
+//   Class to handle Hall C scaler events (type 0)
+//   author  Edward Brash (brash@jlab.org)
+//   based on THaScalerEvtHandler by Robert Michaels (rom@jlab.org)
+//
+/////////////////////////////////////////////////////////////////////
+
+#include "THaEvtTypeHandler.h"
+#include "Decoder.h"
+#include <string>
+#include <vector>
+#include "TTree.h"
+#include "TString.h"  
+
+class ScalerLoc { // Utility class used by THaScalerEvtHandler
+ public:
+ ScalerLoc(TString nm, TString desc, Int_t isc, Int_t ich, Int_t iki) :
+   name(nm), description(desc), iscaler(isc), ichan(ich), ikind(iki) { };
+  ~ScalerLoc();
+  TString name, description;
+  UInt_t iscaler, ichan, ivar, ikind;
+};
+
+class THcScalerEvtHandler : public THaEvtTypeHandler {
+
+public:
+
+   THcScalerEvtHandler(const char*, const char*);
+   virtual ~THcScalerEvtHandler();
+
+   Int_t Analyze(THaEvData *evdata);
+   virtual EStatus Init( const TDatime& run_time);
+   virtual Int_t End( THaRunBase* r=0 );
+
+
+private:
+
+   void AddVars(TString name, TString desc, Int_t iscal, Int_t ichan, Int_t ikind);
+   void DefVars();
+   static size_t FindNoCase(const std::string& sdata, const std::string& skey);
+
+   std::vector<Decoder::GenScaler*> scalers;
+   std::vector<ScalerLoc*> scalerloc;
+   Double_t evcount;
+   UInt_t *rdata;
+   std::vector<Int_t> index;
+   Int_t Nvars, ifound, fNormIdx, nscalers;
+   Double_t *dvars;
+   TTree *fScalerTree;
+
+   THcScalerEvtHandler(const THcScalerEvtHandler& fh);
+   THcScalerEvtHandler& operator=(const THcScalerEvtHandler& fh);
+
+   ClassDef(THcScalerEvtHandler,0)  // Scaler Event handler
+
+};
+
+#endif
-- 
GitLab