// $Id: EEmcDb.cxx,v 1.21 2004/05/15 16:27:01 jwebb Exp $

#include <iostream>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

//#include <TH1.h>
//#include <TFile.h>
//#include <TDirectory.h>
//#include <TClonesArray.h>


#define  __STDB_STANDALONE__

#include "EEmcDb.h"
#include "StEEmcUtil/EEfeeRaw/EEdims.h"

#include "StEEmcDbMaker/EEmcDbItem.h"
#include "StEEmcUtil/EEfeeRaw/EEname2Index.h"

#ifndef IN_PANITKIN

#include "StDbLib/StDbManager.hh"
#include "StDbLib/StDbConfigNode.hh"

#include "StEEmcDbMaker/cstructs/eemcDbADCconf.hh"
#include "StEEmcDbMaker/cstructs/eemcDbPMTcal.hh"
#include "StEEmcDbMaker/cstructs/eemcDbPIXcal.hh"
#include "StEEmcDbMaker/cstructs/eemcDbPMTname.hh"
#include "StEEmcDbMaker/cstructs/eemcDbPMTped.hh"
#include "StEEmcDbMaker/cstructs/eemcDbPMTstat.hh"

ClassImp(EEmcDb)
#endif

#include "StEEmcUtil/EEfeeRaw/EEname2Index.cxx"  
//--------------------------------------------------
//--------------------------------------------------
 EEmcDb::EEmcDb()
{
  // Constructor

  // printf("CCC EEmcDbn");
  mfirstSecID=mlastSecID=mNSector=0;
  timeStamp=0;
  setThreshold(1.0);  // defines threshold for ADCs
  
  //................ allocate memory for lookup tables
  byIndex=new  EEmcDbItem[EEindexMax];

  mxAdcCrate=MaxAnyCrate;
  mxAdcChan=MaxAnyCh;
  byCrate=new  EEmcDbItem ** [mxAdcCrate];

  int i;
  for(i=0;i<mxAdcCrate;i++){
    byCrate[i]=NULL;
    if(i==0 || (i>MaxTwCrateID && i<MinMapmtCrateID) ) continue; // to save memory for nonexisting crates
    byCrate[i]=new EEmcDbItem * [mxAdcChan];
    memset(byCrate[i],0,sizeof(EEmcDbItem *)*mxAdcChan);// clear all pointers
  }


} 

//--------------------------------------------------
//--------------------------------------------------
 void EEmcDb::readAsciiDataBase(char *fname,int sec1, int sec2) 
{
  // Reads database from an ascii file produced by EEmcDb::exportAscii(). 

  printf("readAsciiDataBase('%s', sec1=%d sec2=%d)n",fname,sec1,sec2);


  timeStamp=11;// sth dumm
 
  nFound=0;
  mfirstSecID=sec1;
  mlastSecID=sec2;
  mNSector=mlastSecID - mfirstSecID+1;
  if(sec1>sec2) {
    mNSector+=12;
    printf("EEmcDb::readAsciiDataBase()  will pass 12 o'clock, mNSector=%dn",mNSector);
  }
  assert(mNSector>0);

  clearItemArray();
  
  FILE *fd=fopen(fname,"r");
  EEmcDbItem item;
  int nd=0;
  if(fd==0) goto crashIt;
  
  while (1  ) {
    int ret=item.importAscii(fd);
    if(ret==0) break;
    if(ret==1) continue;
    if(ret<0) goto crashIt;

    int key=EEname2Index(item.name);


    if(key!=item.key) {
      printf("WARN: name='%s' key=%d!=inpKey=%d, inpKey ignoredn",item.name,key,item.key);
      item.key=key;
    }

    assert(key>=0 && key<EEindexMax);

    int isec=item.sec-sec1;
    if (sec1>sec2 ) isec+=12;
    
    if( isec<0) continue;
    if( isec>=  mNSector) continue;
    nd++;

    EEmcDbItem *x=&byIndex[key];
    if(!x->isEmpty()) goto crashIt;
    *x=item; // copy this DB record
    //    x->print();

    assert(byCrate[x->crate]);// ERROR: unsupported crate ID
    if(byCrate[x->crate][x->chan]) {
      printf("Fatal Error of eemc DB records: the same crate=%d / channel=%d entered twice for :n",x->crate,x->chan);
      byCrate[x->crate][x->chan]->print(); // first time
      x->print(); // second time
      assert(1==2);
    }
    byCrate[x->crate][x->chan]=x;
    // assert(2==311);
  }
  
  printf("readAsciiDataBase() done, found %d valid recordsn",nd);
  return;

 crashIt:// any failure of reading of the data
  clearItemArray();
  //  assert(2==3);
  printf("EEmcDb - no/corrupted input file, all cleared, continuen");

}

//--------------------------------------------------
//--------------------------------------------------
 const  EEmcDbItem* EEmcDb::getByIndex(int i)
{
  // Gets database entry by absolute index

  assert(i>=0);
  assert(i<EEindexMax);
  const  EEmcDbItem *x=byIndex+i;
  if(x->isEmpty()) return 0;
  return x;
}

//--------------------------------------------------
//--------------------------------------------------
 const  EEmcDbItem* EEmcDb::getByCrate(int crateID, int channel) 
{
  // Retrieves database entry by referencing the corresponding
  // crate ID (numbered from 1) and channel number (indexed from 0).

  // crateID counts from 1, channel from 0 
  int type=0;
  int max=0;
  // printf("cr=%d ch=%dn",crateID, channel);
  if(crateID>=MinTwCrateID && crateID<=MaxTwCrateID) {
    // Towers
    type =1;
    max=MaxTwCrateCh; 
    if(channel>=max) return 0; // not all data blocks are used 

  } else if (crateID>=MinMapmtCrateID && crateID<=MaxMapmtCrateID ){
    //MAPMT
    type =2;
    max=MaxMapmtCrateCh;
  } else if (crateID>=17 && crateID<=46 ){
    return 0;  //BTOW
  }
  
  // printf("id=%d  type=%d ch=%dn",crateID,type,channel);
  //printf(" p=%p n",byCrate[crateID]);

  assert(type);
  assert( byCrate[crateID]);
  assert(channel>=0);
  assert(channel<max);
  return byCrate[crateID][channel]; 
}
//__________________________________________________
//__________________________________________________
//__________________________________________________

const EEmcDbItem*
 EEmcDb::getTile(int sec, char sub, int eta, char type)
{
  // Get the database entry for the specified "tile" readout.
  // type = T,P,Q,R for tower, pre1, pre2 and post.
  char name[20];
  sprintf(name,"%2.2d%c%c%2.2d",sec,type,sub,eta);
  int key=EEname2Index(name);
  return byIndex+key;  
}

const EEmcDbItem*
 EEmcDb::getByStrip0( Int_t isec, Int_t iuv, Int_t istrip )
{
  // Get the database entry for the specified strip, counted
  // from 0.  Unlike the version in StEEmcDbMaker, this routine
  // uses the slow "EEname2Index" method to retrieve, rather
  // than a lookup table.
  char name[20];
  char uv[]={'U','V'};
  sprintf(name,"%2.2d%c%3.3d",isec+1,uv[iuv],istrip+1);
  return byIndex+EEname2Index(name);
}

//--------------------------------------------------
//--------------------------------------------------
 void EEmcDb::setThreshold(float x)
{
  // Sets the minimum adc threshold as a multiple of the pedestal width.

  KsigOverPed=x;
  printf("setThres() KsigOverPed=%f, threshold=ped+sig*KsigOverPedn",KsigOverPed);
} 


//--------------------------------------------------
//--------------------------------------------------
 void EEmcDb::exportAscii(char *fname) const
{
  // Export the database to an ascii file.  readAsciiDatabase() can be used
  // to read the database values from the file.

  printf("EEmcDb::exportAscii('%s') ...n",fname);
  
  FILE * fd=fopen(fname,"w");
  assert(fd);
  // fd=stdout;
 
  int nTot=0;

  fprintf(fd,"# EEmcDb::exportAscii()ttime stamp   : %d / %s",(int)timeStamp,
	  ctime((const time_t *)&timeStamp));
  fprintf(fd,"# see StRoot/StEEmcDbMaker/EEmcDbItem::exportAscii()  for definitionn");
  
  int j;
  for(j=0;j<EEindexMax; j++) { // loop over channels
    const  EEmcDbItem *x=byIndex+j;
    if(x->isEmpty())continue;
    x->exportAscii(fd);
    nTot++;
  }
  printf("        nTot=%d, donen",nTot);
  fclose(fd);
}   

//--------------------------------------------------
//--------------------------------------------------
 void EEmcDb::clearItemArray()
{
  printf("clearItemArray()n");
  nFound=0;
  
  int i;
  
  for(i=0; i<EEindexMax; i++)
    byIndex[i].clear();
  
  int j;
  for(i=0;i<mxAdcCrate;i++) {
    if(byCrate[i]==NULL) continue;
    for(j=0;j<mxAdcChan;j++)
      byCrate[i][j]=0;
  }
}  


#ifndef IN_PANITKIN 

//--------------------------------------------------
// pixel has to have a form
// 05S3-12:11
//--------------------------------------------------
 int EEmcDb::scaleGain(const char *pixel, float factor) 
{ 
  int   pixNameLen = strlen(pixel);
  int   charOffset = 0;
  int   secID      = atoi(pixel);


  if(secID<1 || MaxSectors<secID) { 
     if(dbg)   printf("n Invalid sector %d n",secID);
     return (-1);
  }
  if(secID<10 && pixel[0]!='0') charOffset = 1;


  int i1=0,i2=0;
  EEindexRange(secID,i1,i2);
  EEmcDbItem *item = byIndex+i1;

  for(int i=i1;i<i2; i++, item++) { 
    if(item->isEmpty())                      continue;
    if(strncmp(item->tube+charOffset,pixel,pixNameLen-charOffset)) continue;      
    item->gain *= factor;
    if(dbg)printf("%s scaled by %.2f (%s)n",item->tube,factor,pixel);
  }
  return 0;
}

//--------------------------------------------------
//--------------------------------------------------
 void EEmcDb::requestDataBase(unsigned int tt, int sec1, int sec2, char *dbName, char *dbVer) {

  mgr = StDbManager::Instance();
  printf("STARdb:: connect to dbName='%s, ver='%sn",dbName, dbVer);
  nodeHead= mgr->initConfig(dbName, dbVer);
  assert(nodeHead);
  setDbg(0);

  
  timeStamp=tt;
  printf("requestDataBase(),  timeStamp=%d=%sn" ,timeStamp,ctime((const time_t *)&timeStamp));
  assert(timeStamp>0);
  
  nFound=0;
  mfirstSecID=sec1;
  mlastSecID=sec2;
  mNSector=mlastSecID - mfirstSecID+1;
  if(sec1>sec2) {
    mNSector+=12;
    printf("EEmcDb::requestDataBase(sec1=%d, sec2=%d)  Will pass 12 o'clock, mNSector=%dn",sec1,sec2,mNSector);
    
  }
  assert(mNSector>0);

  printf("reloadDbn");
  clearItemArray();
  assert(mNSector) ;  
  assert(timeStamp>0);
  

  //............  reload all lookup tables ...............
  int is;
  for(is=0; is< mNSector; is++) {
    int secID=is+mfirstSecID;
    if(secID>12) secID-=12;
    reloadDbConfig(secID);
    reloadDbOthers(secID);
  }
  
}



//--------------------------------------------------
//--------------------------------------------------
 void EEmcDb::setPreferredFlavor(char *flavor, char *nameMask)
{
  // Flavors allow multiple versions of gains, pedestals, etc... while
  // performing calibrations and other analysis tasks.

  strncpy(dbFlavor.flavor,flavor,DbFlavor::mx);
  strncpy(dbFlavor.nameMask,nameMask,DbFlavor::mx);
  printf("set  fetchDbTable(flavor='%s' mask='%s')n",dbFlavor.flavor,dbFlavor.nameMask);
}



//--------------------------------------------------
//--------------------------------------------------
 void EEmcDb::reloadDbConfig(int secID){
  
  if(dbg) printf("  conf ADC for sector=%dn",secID);
  
  printf("n ------------ query DB for sector %d ------n",secID);
  eemcDbADCconf *t=( eemcDbADCconf*) getDbTable(secID,"eemcADCconf");
  if(t==0) return;
  printf("  comment=%sn",t->comment);
  
  int j;
  for(j=0;j<EEMCDbMaxAdc; j++) { // loop over channels
    char *name=t->name+j*EEMCDbMaxName;
    
    if(*name==EEMCDbStringDelim) continue;
    
    //printf("%d '%s'  %d %dn",j,name,t->crate[j],t->channel[j]);
    // printf("%d   %d %dn",j,t->crate[j],t->channel[j]);

    int key=EEname2Index(name);
    assert(key>=0 && key<EEindexMax);
    EEmcDbItem *x=&byIndex[key];
    if(!x->isEmpty()) {
      x->print();
      assert(x->isEmpty());
    }
    x->crate=t->crate[j];
    x->chan=t->channel[j];
    x->setName(name);
    x->key=key;
    x->setDefaultTube(MinMapmtCrateID);
    // x->print();

    assert(x->crate>=0 && x->crate<mxAdcCrate);
    assert(x->chan>=0 && x->chan<mxAdcChan);
    assert(byCrate[x->crate]);// ERROR: duplicated crate ID from DB
    if(byCrate[x->crate][x->chan]) {
      printf("Fatal Error of eemc DB records: the same crate=%d / channel=%d entered twice for :n",x->crate,x->chan);
      byCrate[x->crate][x->chan]->print(); // first time
      x->print(); // second time
      assert(1==2);
    }
    byCrate[x->crate][x->chan]=x;
  }
}


//--------------------------------------------------
//--------------------------------------------------
 void EEmcDb::reloadDbOthers(int secID){
  
  if(dbg) printf("  secondary DB info for sector=%dn",secID);
  
  eemcDbPIXcal  *calM= ( eemcDbPIXcal*)  getDbTable(secID,"eemcPIXcal");
  if(calM) printf("  calMAPMT-comment=%sn",calM->comment);

  eemcDbPMTcal  *calT= ( eemcDbPMTcal*)  getDbTable(secID,"eemcPMTcal");
  if(calT) printf("  calTw-comment=%sn",calT->comment);

  eemcDbPMTname *tubeTw=( eemcDbPMTname*) getDbTable(secID,"eemcPMTname");
  if(tubeTw) printf("  tube-comment=%sn",tubeTw->comment);

  eemcDbPMTped  *ped= ( eemcDbPMTped*)  getDbTable(secID,"eemcPMTped");
  if(ped) printf("  ped-comment=%sn",ped->comment);

  eemcDbPMTstat *stat=( eemcDbPMTstat*) getDbTable(secID,"eemcPMTstat");
  if(stat) printf("  stat-comment=%sn",stat->comment);
  
  int ix1,ix2;
  EEindexRange(secID,ix1,ix2);
  if(dbg)printf("EEindexRange(%d,%d,%d)n",secID,ix1,ix2);

  //  if(dbg)printf(" Size: ped=%d cal=%d name=%d stat=%d n",sizeof(ped->name)/EEMCDbMaxName,sizeof(cal->name)/EEMCDbMaxName,sizeof(tubeTw->name)/EEMCDbMaxName,sizeof(stat->name)/EEMCDbMaxName);
  
  int key; 
  for(key=ix1;key<ix2; key++) { // loop  in this sector
    EEmcDbItem *x=byIndex+key;
    if(x->isEmpty()) continue;
    char *name=x->name;
    
    if(ped) { // pedestals 
      int j;
      int mx=sizeof(ped->name)/EEMCDbMaxName;
      for(j=0;j<mx; j++) {
	char *name1=ped->name+j*EEMCDbMaxName;
	if(strncmp(name,name1,strlen(name))) continue;
	x->ped=ped->ped[j];
	x->thr=ped->ped[j]+KsigOverPed*ped->sig[j];
	//printf("%d found %s %d %dn",j,name,strlen(name),strncmp(name,name1,strlen(name)));
	//x->print();
	break;
      }
    } // end of pedestals

    
    if(calT&& name[2]=='T') { // calibration for towers only
      int j;
      int mx=sizeof(calT->name)/EEMCDbMaxName;
      for(j=0;j<mx; j++) {
	char *name1=calT->name+j*EEMCDbMaxName;
	if(strncmp(name,name1,strlen(name))) continue;
	x->gain=calT->gain[j];
	break;
      }
    } // end of Tower gains

    if(calM && name[2]!='T') { // calibration for MAPMT
      int j;
      int mx=sizeof(calM->name)/EEMCDbMaxName;

      for(j=0;j<mx; j++) {
	char *name1=calM->name+j*EEMCDbMaxName;
	if(strncmp(name,name1,strlen(name))) continue;
	x->gain=calM->gain[j];
	break;
      }
    } // end of gains

    if(tubeTw && name[2]=='T') { // change tube for towers only
      int j;
      int mx=sizeof(tubeTw->name)/EEMCDbMaxName;
      for(j=0;j<mx; j++) {
	char *name1=tubeTw->name+j*EEMCDbMaxName;
	if(strncmp(name,name1,strlen(name))) continue;
	x->setTube(tubeTw->tubeName+j*EEMCDbMaxName);
	//x->print();
	break;
      }
    } // end of tube
    
    
    if(stat) { // status
      int j;
      int mx=sizeof(stat->name)/EEMCDbMaxName;
      for(j=0;j<mx; j++) {
	char *name1=stat->name+j*EEMCDbMaxName;
	if(strncmp(name,name1,strlen(name))) continue;
	x->stat=stat->stat[j];
	x->fail=stat->fail[j];
	//x->print();
	break;
      }
    } // end of status
    
  }// end of pixels in this sector
  
}



//--------------------------------------------------
//--------------------------------------------------
 void * EEmcDb::getDbTable(int secID, char *nameT){
  char nameSec[100];
  char nameFull[100];
  sprintf(nameSec,"sector%2.2d",secID); //.................

  sprintf(nameFull,"%s/%s",nameSec,nameT);
  printf("request='%s'  -->n",nameFull);
  StDbConfigNode* node =0;
  
  node=nodeHead->findConfigNode(nameSec);
  
  assert(node);
  if(dbg) printf("node '%s' found (JB)n",nameSec);
  
  StDbTable * tab=node->findTable(nameT);
  
  //  printf(" tab=%pn",tab);

  assert(tab);

  int nrows;
  int* elist;
  if(tab->GetNRows()<=0) {
    printf("nJB: FAILED : tab->GetNRows()=%dn",tab->GetNRows());
    exit(1);
  }
  elist = tab->getElementID(nrows);
  if(dbg)  printf("   nrows=%d, elis=%dn",nrows,*elist);

  mgr->setRequestTime(timeStamp);
  
  int ret=0;
  if(dbFlavor.flavor[0] && strstr(nameFull,dbFlavor.nameMask)) {
    //printf("nDO fetchDbTable(tab) for flavor='%s' mask='%s' n",dbFlavor.flavor,dbFlavor.nameMask);
    printf("  try flavor='%s' mask='%s' n",dbFlavor.flavor,dbFlavor.nameMask);
    tab->setFlavor(dbFlavor.flavor); // make it sensitive to null entries
    ret= mgr->fetchDbTable(tab);
  }

  if(!ret) { // try default 
    if(dbg) printf("ntry default: fetchDbTable(tab) for 'ofl'n");
    tab->setFlavor("ofl+null"); // make it sensitive to null entries
    ret= mgr->fetchDbTable(tab);
  }


  //  printf("      BeginDate     =%s, ",tab->getBeginDateTime());
  // printf("        EndDate     =%sn",tab->getEndDateTime());

  //  printf(" BeginTime     =%dn",tab->getBeginTime());
  //printf("   EndTime     =%dn\n",tab->getEndTime());

  if(!ret) {
    printf("n problem with fetch(t=%s)n",ctime((const time_t *)&timeStamp));
    return 0;
  }
  if(dbg)   printf("n requested DBtable found n");
  void * t= tab->GetTable();
  assert(t);
  return t;
}

#endif // IN_PANIKIN

// $Log: EEmcDb.cxx,v $
// Revision 1.21  2004/05/15 16:27:01  jwebb
// Added getByStrip, getByStrip0 and getTile methods.
//
// Revision 1.20  2004/03/23 20:02:31  jwebb
// EEmcDb now inherits from TObject (had ClassDef and ClassImp declared
// already).  Added comments for documentation generator.  Added
// "friend" class EEsmdCalibration.
//
// Revision 1.19  2004/03/05 19:25:43  balewski
// ignore key in readAscii
//
// Revision 1.18  2004/02/29 04:04:48  balewski
// to match Panitkin
//
// Revision 1.17  2004/02/26 04:21:43  balewski
// reading ASCII dump
//
// Revision 1.16  2004/02/17 03:32:22  balewski
// tower gains fixed
//
// Revision 1.15  2004/02/17 03:09:02  balewski
// *** empty log message ***
//
// Revision 1.14  2004/02/12 15:53:41  balewski
//  EEmcDb::requestDataBase(time,sec1=8,sec2=4) works
//
// Revision 1.13  2004/02/06 05:09:10  balewski
// *** empty log message ***
//
// Revision 1.12  2004/02/05 15:56:53  balewski
// drop use PIXname, use PMTname again
//
// Revision 1.11  2004/01/27 15:15:51  balewski
// *** empty log message ***
//
// Revision 1.10  2004/01/20 05:52:23  balewski
// cleanup
//
// Revision 1.9  2003/12/10 04:42:33  balewski
// *** empty log message ***
//
// Revision 1.8  2003/12/09 17:09:07  zolnie
// *** empty log message ***
//
// Revision 1.7  2003/12/08 22:19:20  zolnie
// allowed for gain
//
// Revision 1.6  2003/12/01 05:01:27  balewski
// DB & SMD
//
// Revision 1.5  2003/11/27 06:30:43  balewski
// added raw/pedSub
//
// Revision 1.4  2003/11/24 05:40:37  balewski
// new stuff for miniDaq
//
// Revision 1.3  2003/11/22 05:35:16  balewski
// *** empty log message ***
//
// Revision 1.2  2003/11/20 22:59:36  balewski
// cleanup
//
// Revision 1.1  2003/11/20 16:08:53  balewski
// start
//


ROOT page - Class index - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.