]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - STEER/AliLHCData.cxx
Quick fix for bug 71658
[u/mrichter/AliRoot.git] / STEER / AliLHCData.cxx
index f7db5d1e849a63bc579def9176ef0ebbe2ef9344..03d28ebf86e2db48f608ff3dff48e4c84d22afa3 100755 (executable)
-/**************************************************************************
- * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
- *                                                                        *
- * Author: The ALICE Off-line Project.                                    *
- * Contributors are mentioned in the code where appropriate.              *
- *                                                                        *
- * Permission to use, copy, modify and distribute this software and its   *
- * documentation strictly for non-commercial purposes is hereby granted   *
- * without fee, provided that the above copyright notice appears in all   *
- * copies and that both the copyright notice and this permission notice   *
- * appear in the supporting documentation. The authors make no claims     *
- * about the suitability of this software for any purpose. It is          *
- * provided "as is" without express or implied warranty.                  *
- *                                                                        *
- **************************************************************************/
-
-
-#include "AliLHCData.h"
-#include "TMap.h"
-
-
-ClassImp(AliLHCData)
-
-const Char_t* AliLHCData::fgkDCSNames[] = {
-  "dip/acc/LHC/Beam/Intensity/Beam%d.totalIntensity",
-  "dip/acc/LHC/Beam/IntensityPerBunchBeam%d.averageBunchIntensity",
-  "dip/acc/LHC/Beam/LuminosityAverage/BRANB.4%c2.meanLuminosity",
-  "dip/acc/LHC/Beam/LuminosityPerBunch/BRANB_4%c2.bunchByBunchLuminosity",
-  "dip/acc/LHC/Beam/LuminosityAverage/BRANB.4%c2.meanCrossingAngle",
-  "dip/acc/LHC/RunControl/CirculatingBunchConfig/Beam%d.value",
-  "dip/acc/LHC/RunControl/FillNumber.payload",
-  //
-  "dip/acc/LHC/Beam/Size/Beam%d.planeSet%d",
-  "dip/acc/LHC/Beam/Size/Beam%d.amplitudeSet%d",
-  "dip/acc/LHC/Beam/Size/Beam%d.positionSet%d",
-  "dip/acc/LHC/Beam/Size/Beam%d.sigmaSet%d"};
-
-const Char_t* AliLHCData::fgkDCSColNames[] = {
-  "dip/acc/LHC/Machine/CollimatorPositions/TCTVB.4L2.%s",
-  "dip/acc/LHC/Machine/CollimatorPositions/TCTVB.4R2.%s",
-  "dip/acc/LHC/Machine/CollimatorPositions/TCLIA.4R2.%s"};
-
-const Char_t* AliLHCData::fgkDCSColJaws[] = {
-  "lvdt_gap_downstream","lvdt_gap_upstream","lvdt_left_downstream",
-  "lvdt_left_upstream","lvdt_right_downstream","lvdt_right_upstream"};
-
-//___________________________________________________________________
-AliLHCData::AliLHCData(const TMap* dcsMap, double tmin, double tmax, int avPeriod)
-  : fPeriod(avPeriod),fTMin(tmin),fTMax(tmax)  
-{
-  FillData(dcsMap,tmin,tmax);
-}
-
-//___________________________________________________________________
-Bool_t AliLHCData::FillData(const TMap* dcsMap, double tmin, double tmax)
-{
-  // process DCS map and fill all fields. 
-  // Accept only entries with timestamp between tmin and tmax
-  const double ktReal = 1200000000.;
-  const double kCollTolerance = 100e-4; // tolerance on collimator move (cm)
-  char buff[100];
-  TObjArray* arr;
-  AliDCSArray* dcsVal;
-  Double_t tPeriodEnd=0;
-  Int_t dcsSize,nEntries,iEntry;
-  //
-  SetTMin(tmin);
-  SetTMax(tmax);
-  //
-  // -------------------------- extract Fill Number
-  arr = GetDCSEntry(dcsMap,fgkDCSNames[kRecFillNum],iEntry,tmin,tmax);
-  if (arr && iEntry>=0) SetFillNumber( ((AliDCSArray*)arr->At(iEntry))->GetInt(0) );
-  //
-  // -------------------------- extract total intensities for beam 1 and 2
-  for (int ibm=0;ibm<2;ibm++) {
-    //
-    sprintf(buff,fgkDCSNames[kRecTotInt],ibm+1);  
-    if ( !(arr=GetDCSEntry(dcsMap,buff,iEntry,tmin,tmax)) || iEntry<0 ) continue;
-    AliLHCDipValD* curVal;
-    tPeriodEnd = 0;
-    //
-    nEntries = arr->GetEntriesFast();
-    while (iEntry<nEntries) {
-      dcsVal = (AliDCSArray*) arr->At(iEntry++);
-      double tstamp = dcsVal->GetTimeStamp();
-      if (tstamp>tmax) break;
-      if (tstamp>tPeriodEnd) {
-       curVal = new AliLHCDipValD(1,0.,0);  // start new period
-       fIntTot[ibm].Add(curVal);
-       // if tmin is provided, count periods from it, otherwise from the 1st timestamp
-       if (tPeriodEnd<1) tPeriodEnd = ((tmin>ktReal) ? tmin : tstamp);
-       tPeriodEnd += fPeriod;
-      }
-      *curVal += *dcsVal;
-    }
-    for (int i=fIntTot[ibm].GetEntries();i--;) ((AliLHCDipValD*)(fIntTot[ibm])[i])->Average();
-  }
-  //  
-  // -------------------------- extract total luminosities according L and R detectors
-  for (int ilr=0;ilr<2;ilr++) {
-    //
-    sprintf(buff,fgkDCSNames[kRecTotLum],ilr ? 'L':'R');  
-    if ( !(arr=GetDCSEntry(dcsMap,buff,iEntry,tmin,tmax)) || iEntry<0 ) continue;
-    AliLHCDipValD* curVal = 0;
-    tPeriodEnd = 0;
-    //
-    nEntries = arr->GetEntriesFast();
-    while (iEntry<nEntries) {
-      dcsVal = (AliDCSArray*) arr->At(iEntry++);
-      double tstamp = dcsVal->GetTimeStamp();
-      if (tstamp>tmax) break;
-      if (tstamp>tPeriodEnd) {
-       curVal = new AliLHCDipValD(1,0.,0);  // start new period
-       fLuminTot[ilr].Add(curVal);
-       // if tmin is provided, count periods from it, otherwise from the 1st timestamp
-       if (tPeriodEnd<1) tPeriodEnd = ((tmin>ktReal) ? tmin : tstamp);
-       tPeriodEnd += fPeriod;
-      }
-      *curVal += *dcsVal;
-    }
-    for (int i=fLuminTot[ilr].GetEntries();i--;) ((AliLHCDipValD*)(fLuminTot[ilr])[i])->Average();
-  }
-  //
-  // -------------------------- extract mean crossing angles according to L and R detectors
-  for (int ilr=0;ilr<2;ilr++) {
-    //
-    sprintf(buff,fgkDCSNames[kRecCrossAngle],ilr ? 'L':'R');  
-    if ( !(arr=GetDCSEntry(dcsMap,buff,iEntry,tmin,tmax)) || iEntry<0 ) continue;
-    AliLHCDipValD* curVal=0;
-    tPeriodEnd = 0;
-    //
-    nEntries = arr->GetEntriesFast();
-    while (iEntry<nEntries) {
-      dcsVal = (AliDCSArray*) arr->At(iEntry++);
-      double tstamp = dcsVal->GetTimeStamp();
-      if (tstamp>tmax) break;
-      if (tstamp>tPeriodEnd) {
-       curVal = new AliLHCDipValD(1,0.,0);  // start new period
-       fCrossAngle[ilr].Add(curVal);
-       // if tmin is provided, count periods from it, otherwise from the 1st timestamp
-       if (tPeriodEnd<1) tPeriodEnd = ((tmin>ktReal) ? tmin : tstamp);
-       tPeriodEnd += fPeriod;
-      }
-      *curVal += *dcsVal;
-    }
-    for (int i=fCrossAngle[ilr].GetEntries();i--;) ((AliLHCDipValD*)(fCrossAngle[ilr])[i])->Average();
-  }
-  //
-  // -------------------------- extract intensities per bunch for beam 1 and 2
-  for (int ibm=0;ibm<2;ibm++) {
-    //
-    sprintf(buff,fgkDCSNames[kRecBunchInt],ibm+1);  
-    if ( !(arr=GetDCSEntry(dcsMap,buff,iEntry,tmin,tmax)) || iEntry<0 ) continue;
-    AliLHCDipValD* curVal=0;
-    tPeriodEnd = 0;
-    //
-    dcsVal = (AliDCSArray*)arr->At(iEntry);
-    nEntries = dcsVal->GetNEntries();     // count number of actual bunches
-    dcsSize = 0;
-    while(dcsSize<nEntries && dcsVal->GetDouble(dcsSize)>0) dcsSize++;
-    if (!dcsSize) {
-      AliWarning(Form("Beam1 bunch intensities record is present but empty",ibm));
-      continue;
-    }
-    //
-    nEntries = arr->GetEntriesFast();
-    while (iEntry<nEntries) {
-      dcsVal = (AliDCSArray*) arr->At(iEntry++);
-      double tstamp = dcsVal->GetTimeStamp();
-      if (tstamp>tmax) break;
-      if (tstamp>tPeriodEnd) {
-       curVal = new AliLHCDipValD(dcsSize,0.,0);  // start new period
-       fIntBunch[ibm].Add(curVal);
-       // if tmin is provided, count periods from it, otherwise from the 1st timestamp
-       if (tPeriodEnd<1) tPeriodEnd = ((tmin>ktReal) ? tmin : tstamp);
-       tPeriodEnd += fPeriod;
-      }
-      *curVal += *dcsVal;
-    }
-    for (int i=fIntBunch[ibm].GetEntries();i--;) ((AliLHCDipValD*)(fIntBunch[ibm])[i])->Average();
-  }
-  //
-  // -------------------------- extract per bunch luminosities according L and R detectors
-  for (int ilr=0;ilr<2;ilr++) {
-    //
-    sprintf(buff,fgkDCSNames[kRecBunchLum],ilr ? 'L':'R');  
-    if ( !(arr=GetDCSEntry(dcsMap,buff,iEntry,tmin,tmax)) || iEntry<0 ) continue;
-    AliLHCDipValD* curVal=0;
-    tPeriodEnd = 0;
-    //
-    dcsVal = (AliDCSArray*) arr->At(iEntry);
-    nEntries = dcsVal->GetNEntries();     // count number of actual bunches
-    dcsSize = 0;
-    while(dcsSize<nEntries && dcsVal->GetDouble(dcsSize)>0) dcsSize++;
-    if (!dcsSize) {
-      AliWarning(Form("Probe%c bunch luminosities record is present but empty",ilr ? 'R':'L'));
-      continue;
-    }
-    //
-    nEntries = arr->GetEntriesFast();
-    while (iEntry<nEntries) {
-      dcsVal = (AliDCSArray*) arr->At(iEntry++);
-      double tstamp = dcsVal->GetTimeStamp();
-      if (tstamp>tmax) break;
-      if (tstamp>tPeriodEnd) {
-       curVal = new AliLHCDipValD(dcsSize,0.,0);  // start new period
-       fLuminBunch[ilr].Add(curVal);
-       // if tmin is provided, count periods from it, otherwise from the 1st timestamp
-       if (tPeriodEnd<1) tPeriodEnd = ((tmin>ktReal) ? tmin : tstamp);
-       tPeriodEnd += fPeriod;
-      }
-      *curVal += *dcsVal;
-    }
-    for (int i=fLuminBunch[ilr].GetEntries();i--;) ((AliLHCDipValD*)(fLuminBunch[ilr])[i])->Average();
-  }
-  //
-  // ------------------------- extract bunch configuration for beam 1 and 2
-  for (int ibm=0;ibm<2;ibm++) {
-    //
-    sprintf(buff,fgkDCSNames[kRecBunchConf],ibm+1);  
-    if ( !(arr=GetDCSEntry(dcsMap,buff,iEntry,tmin,tmax)) || iEntry<0 ) continue;
-    dcsVal = (AliDCSArray*) arr->At(iEntry);
-    nEntries = dcsVal->GetNEntries();     // count number of actual bunches
-    dcsSize = 0;
-    while(dcsSize<nEntries && dcsVal->GetInt(dcsSize)) dcsSize++;
-    if (!dcsSize) {
-      AliWarning("Bunches configuration record is present but empty");
-      continue;
-    }
-    fBunchConfig[ibm].SetSize(dcsSize);
-    fBunchConfig[ibm] += *dcsVal;
-  }
-  //
-  // ------------------------- extract gaussian fit params for beam 1 and 2 profiles
-  for (int ibm=0;ibm<2;ibm++) {
-    for (int ixy=0;ixy<2;ixy++) {
-      // determine which projection corresponds actually to given ixy
-      sprintf(buff,fgkDCSNames[kRecPrfPrID],ibm+1,ixy+1); 
-      if ( !(arr=GetDCSEntry(dcsMap,buff,iEntry,0/*tmin*/,tmax)) || iEntry<0 ) continue;
-      dcsVal = (AliDCSArray*) arr->At(iEntry);
-      int proj = dcsVal->GetInt(0)-1;          // beam projection
-      //
-      if (proj!=kX && proj!=kY) {
-       AliError(Form("Unknown beam projection %d for %s",proj,buff));
-       continue;
-      }
-      // Amp,Pos,Sig - each one have separate entry and time stamp (though come from the single fit)
-      int entPar[3];
-      TObjArray *arrPar[3];
-      AliDCSArray *dcsPar[3];
-      AliLHCDipValD* curVal=0;
-      double tstamp = 0;
-      int npars = 0;
-      for (int ipar=0;ipar<3;ipar++) {
-       sprintf(buff,fgkDCSNames[ipar+kRecPrfAmp],ibm+1,ixy+1);
-       if ( !(arrPar[ipar]=GetDCSEntry(dcsMap,buff,entPar[ipar],tmin,tmax)) || entPar[ipar]<0 ) break;
-       dcsPar[ipar] = (AliDCSArray*) arrPar[ipar]->At(entPar[ipar]);   
-       if (dcsPar[ipar]->GetTimeStamp()>tstamp) tstamp = dcsPar[ipar]->GetTimeStamp(); // max time among 1st entries
-       npars++;
-      }
-      if (npars<3) continue; // ignore incomplete data
-      //
-      tPeriodEnd = 0;
-      // start recording from max timeStamp: 
-      // the entries for different params must correspond to same timestamp
-      while(1) { 
-       //
-       // read next timestamp for which all 3 params are present
-       npars = 0; // align the first entries to read to same timestamp
-       for (int ipar=0;ipar<3;ipar++) {
-         while(entPar[ipar]<arrPar[ipar]->GetEntriesFast()) {
-           dcsPar[ipar] = (AliDCSArray*) arrPar[ipar]->At(entPar[ipar]);
-           double df = dcsPar[ipar]->GetTimeStamp() - tstamp;
-           if (TMath::Abs(df)<0.5) { // same time stamp, ok
-             npars++; 
-             break;
-           }
-           if (df<0) entPar[ipar]++;  // check next entry
-           else {
-             tstamp = dcsPar[ipar]->GetTimeStamp();
-             ipar = -1; // reference tstamp was changed, check all arrays again
-             npars = 0;
-             break;
-           }
-         }
-       } // 
-       if (npars<3) break; // no more data
-       for (int ipar=0;ipar<3;ipar++) entPar[ipar]++;
-       //
-       if (tstamp>tmax) break;
-       if (tstamp>tPeriodEnd) {
-         curVal = new AliLHCDipValD(3,0.,0);  // start new period
-         fBeamPos[ibm][proj].Add(curVal);
-         // if tmin is provided, count periods from it, otherwise from the 1st timestamp
-         if (tPeriodEnd<1) tPeriodEnd = ((tmin>ktReal) ? tmin : tstamp);
-         tPeriodEnd += fPeriod;
-       }
-       int nsamp = curVal->GetNSamplesUsed()+1;
-       curVal->SetTimeStamp( (tstamp + curVal->GetNSamplesUsed()*curVal->GetTimeStamp())/nsamp);
-       curVal->SetNSamplesUsed(nsamp);
-       for (int ipar=3;ipar--;) (*curVal)[ipar] += dcsPar[ipar]->GetDouble(0);
-       //
-      }
-      //
-      for (int i=fBeamPos[ibm][proj].GetEntriesFast();i--;) ((AliLHCDipValD*)(fBeamPos[ibm][proj])[i])->Average();
-      //
-    } // projection
-  } // beam
-  //
-  // ------------------------- extract collimators data
-  for (int icl=0;icl<kNCollimators;icl++) {
-    for (int jaw=0;jaw<kNJaws;jaw++) {
-      sprintf(buff,fgkDCSColNames[icl],fgkDCSColJaws[jaw]);        
-      if ( !(arr=GetDCSEntry(dcsMap,buff,iEntry,tmin,tmax)) || iEntry<0 ) continue;
-      dcsVal = (AliDCSArray*) arr->At(iEntry);       
-      AliLHCDipValD* curVal = new AliLHCDipValD(1,dcsVal->GetTimeStamp(),1);
-      (*curVal)[0] = dcsVal->GetDouble(0)/10;  // gap in cm
-      fCollimators[icl][jaw].Add(curVal);
-      //
-      // now track the changes above the threshold (100 um?)
-      nEntries = arr->GetEntriesFast();
-      while(++iEntry<nEntries) {
-       dcsVal = (AliDCSArray*) arr->At(iEntry);
-       if (dcsVal->GetTimeStamp() > tmax) break;  // out of time
-       double val = dcsVal->GetDouble(0)/10;
-       if ( TMath::Abs(val-curVal->GetValue(0))<kCollTolerance ) continue;  // no significant change
-       // need to create a new entry
-       curVal = new AliLHCDipValD(1,dcsVal->GetTimeStamp(),1);
-       (*curVal)[0] = val;  // gap in cm
-       fCollimators[icl][jaw].Add(curVal);     
-      }
-    } // jaws
-  } // collimators
-  //
-  return kTRUE;
-}
-
-//___________________________________________________________________
-TObjArray* AliLHCData::GetDCSEntry(const TMap* dcsMap,const char* key,int &entry,double tmin,double tmax) const
-{
-  // extract array from the DCS map and find the first entry within the time limits
-  TObjArray* arr = (TObjArray*)dcsMap->GetValue(key);
-  if (!arr || !arr->GetEntriesFast()) { 
-    AliWarning(Form("No data for %s",key)); 
-    return 0;
-  }
-  int ntot = arr->GetEntriesFast();
-  for (entry=0;entry<ntot;entry++) {
-    AliDCSArray* ent = (AliDCSArray*)arr->At(entry);
-    if (ent->GetTimeStamp()>=tmin && ent->GetTimeStamp()<=tmax) break;
-  }
-  if (entry==ntot) {
-    entry = -1;
-    TString str;
-    str += AliLHCDipValD::TimeAsString(tmin);
-    str += " : ";
-    str += AliLHCDipValD::TimeAsString(tmax);
-    AliWarning(Form("All entries for %s are outside the requested range:\n%s",key,str.Data()));
-  }
-  return arr;
-}
-
-//___________________________________________________________________
-void AliLHCData::Print(const Option_t* opt) const
-{
-  // print everything
-  printf("LHC DIP Data | Fill Number#%d (Averaging time: %d sec.)",GetFillNumber(),fPeriod);
-  printf("Validity period: %s : %s",
-        fTMin<1.23e9 ? "N/A": AliLHCDipValD::TimeAsString(fTMin),
-        fTMax>7.00e9 ? "N/A": AliLHCDipValD::TimeAsString(fTMax) );
-  //
-  int n=0;
-  for (int ibm=0;ibm<2;ibm++) {
-    printf("*** Bunch Configuration for Beam%d: %s\n",ibm,(n=fBunchConfig[ibm].GetSize()) ? "":"N/A");
-    if (n) fBunchConfig[ibm].Print(opt);
-  }
-  printf("\n");
-  //
-  for (int ibm=0;ibm<2;ibm++) {
-    printf("*** Total intensity for Beam%d: %s\n",ibm,(n=fIntTot[ibm].GetEntriesFast()) ? "":"N/A");
-    for (int i=0;i<n;i++) (fIntTot[ibm])[i]->Print(opt);
-  }
-  printf("\n");
-  //
-  for (int ibm=0;ibm<2;ibm++) {
-    printf("*** Bunch intensities for Beam%d: %s\n",ibm,(n=fIntBunch[ibm].GetEntriesFast()) ? "":"N/A");
-    for (int i=0;i<n;i++) (fIntBunch[ibm])[i]->Print(opt);
-  }
-  printf("\n");
-  //
-  for (int ibm=0;ibm<2;ibm++) {
-    printf("*** Total luminosity for probe%c: %s\n",ibm ? 'R':'L',(n=fLuminTot[ibm].GetEntriesFast()) ? "":"N/A");
-    for (int i=0;i<n;i++) (fLuminTot[ibm])[i]->Print(opt);
-  }
-  printf("\n");
-  //
-  for (int ibm=0;ibm<2;ibm++) {
-    printf("*** Bunch luminosities for probe%c: %s\n",ibm ? 'R':'L',(n=fLuminBunch[ibm].GetEntriesFast()) ? "":"N/A");
-    for (int i=0;i<n;i++) (fLuminBunch[ibm])[i]->Print(opt);
-  }
-  printf("\n");
-  //
-  for (int ibm=0;ibm<2;ibm++) {
-    printf("*** Crossing angle for probe%c: %s\n",ibm ? 'L':'R',(n=fCrossAngle[ibm].GetEntriesFast()) ? "":"N/A");
-    for (int i=0;i<n;i++) (fCrossAngle[ibm])[i]->Print(opt);
-  }
-  printf("\n");
-  //
-  for (int ibm=0;ibm<2;ibm++) {
-    for (int ixy=0;ixy<2;ixy++) {
-      printf("*** Gaussian fit for Beam%d %c profile: %s\n",ibm,ixy ? 'Y':'X',(n=fBeamPos[ibm][ixy].GetEntriesFast()) ? "":"N/A");
-      for (int i=0;i<n;i++) (fBeamPos[ibm][ixy])[i]->Print(opt);
-    }
-  }
-  //
-  for (int icl=0;icl<kNCollimators;icl++) {
-    printf("\n");
-    for (int ij=0;ij<kNJaws;ij++) {
-      printf(fgkDCSColNames[icl],fgkDCSColJaws[ij]);
-      printf(": %s\n",(n=fCollimators[icl][ij].GetEntriesFast()) ? "":"N/A");
-      for (int i=0;i<n;i++) (fCollimators[icl][ij])[i]->Print(opt);
-    }
-  }
-  //
-}
+/**************************************************************************\r
+ * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *\r
+ *                                                                        *\r
+ * Author: The ALICE Off-line Project.                                    *\r
+ * Contributors are mentioned in the code where appropriate.              *\r
+ *                                                                        *\r
+ * Permission to use, copy, modify and distribute this software and its   *\r
+ * documentation strictly for non-commercial purposes is hereby granted   *\r
+ * without fee, provided that the above copyright notice appears in all   *\r
+ * copies and that both the copyright notice and this permission notice   *\r
+ * appear in the supporting documentation. The authors make no claims     *\r
+ * about the suitability of this software for any purpose. It is          *\r
+ * provided "as is" without express or implied warranty.                  *\r
+ *                                                                        *\r
+ **************************************************************************/\r
+\r
+/********************************************************************************\r
+*                                                                               *\r
+*   AliLHCData: summary of the LHC related information from LHC DIP.            *\r
+*   Created from the TMap provided by the AliLHCReader with optional beginning  *\r
+*                                                                               *\r
+*   The data are (wrapped in the AliLHCDipValT):                                *\r
+*   made of TimeStamp (double) and array of values                              *\r
+*                                                                               *\r
+*   Multiple entries for each type of data are possible. To obtaine number of   *\r
+*   records (with distinct timestamp) for give type od records use:             *\r
+*   int GetNBunchConfigMeasured(int beam) (with beam=0,1) etc.                  *\r
+*                                                                               *\r
+*   To get i-th entry, use brec= AliLHCDipValI* GetBunchConfigMeasured(bm,i);   *\r
+*   Note: exact type of templated AliLHCDipValT pointer depends on the record   *\r
+*   type, concult getters to know it.                                           *\r
+*                                                                               *\r
+*   Then, once the pointer is obtained, details can be accessed:                *\r
+*   int nBunches = brec->GetSize();                                             *\r
+*   for (int i=0;i<nBunches;i++) printf("Bunch#%d: %d\n",i,(*brec)[i]);         *\r
+*                                                                               *\r
+*                                                                               *\r
+*   Author: ruben.shahoyan@cern.ch                                              *\r
+*                                                                               *\r
+********************************************************************************/\r
+\r
+#include "AliLHCData.h"\r
+#include "TMap.h"\r
+#include "AliDCSArray.h"\r
+#include "AliLHCReader.h"\r
+#include <TString.h>\r
+#include <TObjArray.h>\r
+\r
+ClassImp(AliLHCData)\r
+\r
+const Char_t* AliLHCData::fgkDCSNames[] = {\r
+  "LHC_IntensityBeam%d_totalIntensity",\r
+  "LHC_BeamIntensityPerBunchBeam%d_averageBeamIntensity",\r
+  "LHC_BeamIntensityPerBunchBeam%d_Average_BunchIntensities",\r
+  //\r
+  "LHC_LumAverageBRANB_4%c2_acqMode",\r
+  "LHC_LumAverageBRANB_4%c2_meanLuminosity",\r
+  "LHC_LumAverageBRANB_4%c2_meanLuminosityError",\r
+  "LHC_BeamLuminosityPerBunchBRANB_4%c2_Average_BunchLuminosity",\r
+  "LHC_BeamLuminosityPerBunchBRANB_4%c2_BunchLuminosityError",\r
+  "LHC_LumAverageBRANB_4%c2_meanCrossingAngle",\r
+  "LHC_LumAverageBRANB_4%c2_meanCrossingAngleError",\r
+  "LHC_CirculatingBunchConfig_Beam%d",\r
+  "LHC_FillNumber",\r
+  //\r
+  "LHC_BunchLengthBeam%d_nBunches",\r
+  "LHC_BunchLengthBeam%d_bunchesLenghts",\r
+  "LHC_BunchLengthBeam%d_filledBuckets",\r
+  //\r
+  "LHC_RunControl_ActiveInjectionScheme",\r
+  "LHC_RunControl_BetaStar",\r
+  "LHC_RunControl_IP2_Xing_Murad",\r
+  "LHC_RunControl_IP2_ALICE_Murad",\r
+\r
+  "LHC_BeamSizeBeam%d_acqMode",\r
+  "LHC_BeamSizeBeam%d_sigmaH",\r
+  "LHC_BeamSizeBeam%d_sigmaV",\r
+  "LHC_BeamSizeBeam%d_emittanceH",\r
+  "LHC_BeamSizeBeam%d_emittanceV",\r
+  "LHC_BeamSizeBeam%d_errorSigmaH",\r
+  "LHC_BeamSizeBeam%d_errorSigmaV",\r
+  //\r
+  "LHC_CollimatorPos_%s_lvdt_%s"\r
+};\r
+\r
+const Char_t* AliLHCData::fgkDCSColNames[] = {\r
+  "TCTVB_4L2",\r
+  "TCTVB_4R2",\r
+  "TCLIA_4R2"\r
+};\r
+\r
+const Char_t* AliLHCData::fgkDCSColJaws[] = {\r
+  "gap_downstream","gap_upstream","left_downstream",\r
+  "left_upstream","right_downstream","right_upstream"};\r
+\r
+//___________________________________________________________________\r
+AliLHCData::AliLHCData(const TMap* dcsMap, double tmin, double tmax)\r
+  : fTMin(0),fTMax(0),fFillNumber(0),fData(0),fFile2Process(0),fMap2Process(0)\r
+{\r
+  FillData(dcsMap,tmin,tmax);\r
+}\r
+\r
+//___________________________________________________________________\r
+AliLHCData::AliLHCData(const Char_t* dcsFile, double tmin, double tmax)\r
+  : fTMin(0),fTMax(0),fFillNumber(0),fData(0),fFile2Process(dcsFile),fMap2Process(0)\r
+{\r
+  FillData(dcsFile,tmin,tmax);\r
+}\r
+\r
+//___________________________________________________________________\r
+Bool_t AliLHCData::FillData(const TMap*   dcsMap,double tmin, double tmax)\r
+{\r
+  // process DCS map and fill all fields. \r
+  Clear();\r
+  fMap2Process = dcsMap;\r
+  FillData(tmin,tmax);\r
+  return kTRUE;\r
+}\r
+\r
+//___________________________________________________________________\r
+Bool_t AliLHCData::FillData(const Char_t* dcsFile,double tmin, double tmax)\r
+{\r
+  // process DCS file and fill all fields. \r
+  Clear();\r
+  fFile2Process = dcsFile;\r
+  FillData(tmin,tmax);\r
+  return kTRUE;\r
+}\r
+\r
+//___________________________________________________________________\r
+Bool_t AliLHCData::FillData(double tmin, double tmax)\r
+{\r
+  // process DCS map and fill all fields. \r
+  // Accept only entries with timestamp between tmin and tmax\r
+  //\r
+  char buff[100],buff1[100];\r
+  //\r
+  SetTMin(tmin);\r
+  SetTMax(tmax);\r
+  //\r
+  // -------------------------- extract Fill Number\r
+  int iFirst=0,iLast=0;\r
+  TObjArray* arr = GetDCSEntry(fgkDCSNames[kFillNum],iFirst,iLast,fTMin,fTMax);\r
+  if (arr) SetFillNumber( ExtractInt( (AliDCSArray*)arr->At(iFirst), 0) );\r
+  if (fFile2Process) delete arr; // array was created on demand\r
+  //\r
+  for (int ibm=0;ibm<2;ibm++) {\r
+    //\r
+    sprintf(buff,fgkDCSNames[kBunchConf],ibm+1);         // ----- declared bunch configuration\r
+    FillBunchConfig(fBunchConfDecl[ibm], buff);\r
+    //\r
+    sprintf(buff,fgkDCSNames[kBunchLgtFillB],ibm+1);     // ----- measured bunch configuration\r
+    FillBunchConfig(fBunchConfMeas[ibm], buff);\r
+    //\r
+    sprintf(buff,fgkDCSNames[kBunchLgt],ibm+1);          // ----- measured bunch lenghts\r
+    FillBunchInfo(fBunchLengths[ibm],buff,ibm,kFALSE);  \r
+    //\r
+    sprintf(buff,fgkDCSNames[kIntBunchAv],ibm+1);        // ----- B-by-B intensities\r
+    FillBunchInfo(fIntensPerBunch[ibm],buff,ibm,kTRUE);\r
+    //\r
+    //\r
+    sprintf(buff,fgkDCSNames[kIntTot],ibm+1);            // ----- total intensities for beam 1 and 2\r
+    FillScalarRecord(fIntensTotal[ibm], buff);\r
+    //\r
+    sprintf(buff,fgkDCSNames[kIntTotAv],ibm+1);          // ----- total intensities for beam 1 and 2 from B-by-B average\r
+    FillScalarRecord(fIntensTotalAv[ibm], buff);\r
+    //\r
+    sprintf(buff,fgkDCSNames[kBeamSzEmittH],ibm+1);      // ----- H emittance for beam 1 and 2 \r
+    FillScalarRecord(fEmittanceH[ibm], buff);\r
+    //\r
+    sprintf(buff,fgkDCSNames[kBeamSzEmittV],ibm+1);      // ----- V emittance for beam 1 and 2 \r
+    FillScalarRecord(fEmittanceV[ibm], buff);\r
+    //\r
+    sprintf(buff ,fgkDCSNames[kBeamSzSigH],   ibm+1);    // ----- H sigmas and errors for beam 1 and 2 \r
+    sprintf(buff1,fgkDCSNames[kBeamSzSigHErr],ibm+1);\r
+    FillScalarRecord(fBeamSigmaH[ibm], buff, buff1);\r
+    //\r
+    sprintf(buff ,fgkDCSNames[kBeamSzSigV],   ibm+1);    // ----- V sigmas and errors for beam 1 and 2 \r
+    sprintf(buff1,fgkDCSNames[kBeamSzSigVErr],ibm+1);\r
+    FillScalarRecord(fBeamSigmaV[ibm], buff, buff1);\r
+    //\r
+  }\r
+  //\r
+  FlagInteractingBunches(fBunchConfMeas[0],fBunchConfMeas[1]);\r
+  FlagInteractingBunches(fBunchConfDecl[0],fBunchConfDecl[1]);\r
+  //\r
+  for (int ilr=0;ilr<2;ilr++) {\r
+    //\r
+    sprintf(buff ,fgkDCSNames[kLumBunch], ilr ? 'R':'L');       // ---- BC-by-BC luminosity at IP2 and its error\r
+    sprintf(buff1,fgkDCSNames[kLumBunchErr], ilr ? 'R':'L');\r
+    FillBCLuminosities(fLuminPerBC[ilr], buff, buff1, 0); // BRAN L uses beam2 as a reference, BRAN R - beam1\r
+    //\r
+    sprintf(buff ,fgkDCSNames[kLumTot]   , ilr ? 'R':'L');       // ---- total luminosity at IP2 and its error\r
+    sprintf(buff1,fgkDCSNames[kLumTotErr], ilr ? 'R':'L');\r
+    FillScalarRecord(fLuminTotal[ilr], buff, buff1);\r
+    //\r
+    sprintf(buff ,fgkDCSNames[kLumAcqMode], ilr ? 'R':'L');      // ---- luminosity acquisition mode\r
+    FillAcqMode(fLuminAcqMode[ilr], buff);\r
+    //\r
+    sprintf(buff, fgkDCSNames[kLumCrossAng]   , ilr ? 'R':'L');  //----- crossing angle at IP2 and its error\r
+    sprintf(buff1,fgkDCSNames[kLumCrossAngErr], ilr ? 'R':'L');\r
+    FillScalarRecord(fCrossAngle[ilr], buff, buff1);\r
+    //    \r
+  }\r
+  //\r
+  for (int icl=0;icl<kNCollimators;icl++) {             // ----- collimators positions\r
+    for (int jaw=0;jaw<kNJaws;jaw++) {\r
+      sprintf(buff,fgkDCSNames[kCollPos], fgkDCSColNames[icl],fgkDCSColJaws[jaw]);        \r
+      FillScalarRecord(fCollimators[icl][jaw], buff);\r
+    } // jaws\r
+  } // collimators\r
+  //\r
+  //\r
+  // RunControl info\r
+  FillStringRecord(fRCInjScheme, fgkDCSNames[kRCInjSch]);   // ---- active injection scheme\r
+  FillScalarRecord(fRCBeta, fgkDCSNames[kRCBeta]);          // ---- target beta \r
+  FillScalarRecord(fRCAngH, fgkDCSNames[kRCCrossAng]);      // ---- horisontal angle\r
+  FillScalarRecord(fRCAngV,fgkDCSNames[kRCVang] );          // ---- vertical angle\r
+  //\r
+  return kTRUE;\r
+}\r
+\r
+//___________________________________________________________________\r
+TObjArray* AliLHCData::GetDCSEntry(const char* key,int &entry,int &last,double tmin,double tmax) const\r
+{\r
+  // extract array from the DCS map or file and find the first entry within the time limits\r
+  entry = -1;\r
+  last = -2;\r
+  TObjArray* arr;\r
+  if (fMap2Process) arr = (TObjArray*)fMap2Process->GetValue(key);\r
+  else if (fFile2Process) {\r
+    AliLHCReader rd;\r
+    arr = rd.ReadSingleLHCDP(fFile2Process,key);\r
+  }\r
+  else {\r
+    AliError("Neither DCS map nor DCS filename are set");\r
+    return 0;  \r
+  }\r
+  //\r
+  if (!arr || !arr->GetEntriesFast()) { \r
+    AliWarning(Form("No data for %s",key)); \r
+    if (fMap2Process) delete arr; // created on demand\r
+    return 0;\r
+  }\r
+  int ntot = arr->GetEntriesFast();\r
+  //\r
+  // search 1st entry before or at tmin\r
+  AliDCSArray* ent = 0;\r
+  Bool_t found = kFALSE;\r
+  for (entry=0;entry<ntot;entry++) {\r
+    ent = (AliDCSArray*)arr->At(entry);\r
+    if (ent->GetTimeStamp()>=tmin-kMarginSOR && ent->GetTimeStamp()<=tmax+kMarginEOR) {\r
+      found = kTRUE;\r
+      if (ent->GetTimeStamp()>tmin) break;\r
+    }\r
+  }\r
+  if (!found) {\r
+    entry = -1;\r
+    TString str;\r
+    str += AliLHCDipValD::TimeAsString(tmin);\r
+    str += " : ";\r
+    str += AliLHCDipValD::TimeAsString(tmax);\r
+    AliWarning(Form("All entries for %s are outside the requested range:\n%s",key,str.Data()));\r
+    if (fMap2Process) delete arr; // created on demand\r
+    return 0;\r
+  }\r
+  if (entry>0) entry--;\r
+  //\r
+  // search last entry at or after tmin\r
+  ent = 0;\r
+  for (last=entry;last<ntot;last++) {\r
+    ent = (AliDCSArray*)arr->At(last);\r
+    if (ent->GetTimeStamp()>tmax) break;\r
+  }\r
+  if (last == ntot) last--;\r
+  else if (ent->GetTimeStamp()>tmax+kMarginEOR) last--;\r
+  //\r
+  return arr;\r
+}\r
+\r
+//___________________________________________________________________\r
+Int_t AliLHCData::TimeDifference(double v1,double v2,double tol) const\r
+{\r
+  // return 0 if the times are the same within the tolerance\r
+  //        1 if v1>v2\r
+  //       -1 if v1<v2\r
+  v1-=v2;\r
+  if (v1>tol)  return  1;\r
+  if (v1<-tol) return -1;\r
+  return 0;\r
+}\r
+\r
+//___________________________________________________________________\r
+Bool_t AliLHCData::GoodPairID(int beam) const\r
+{\r
+  // check for correct beam identifier \r
+  if (beam>kBeam2||beam<0) {AliError(Form("BeamID can be 0 or 1, %d requested",beam)); return kFALSE;}\r
+  return kTRUE;\r
+}\r
+\r
+//___________________________________________________________________\r
+AliLHCDipValI* AliLHCData::GetBunchConfigMeasured(int beam,double tstamp) const\r
+{\r
+  // find measured bunch configuration valid for given tstamp\r
+  if (!GoodPairID(beam)) return 0;\r
+  return (AliLHCDipValI*)FindRecValidFor(fBunchConfMeas[beam][kStart],fBunchConfMeas[beam][kNStor],tstamp);\r
+}\r
+\r
+//___________________________________________________________________\r
+AliLHCDipValI* AliLHCData::GetBunchConfigDeclared(int beam,double tstamp) const\r
+{\r
+  // find declared bunch configuration valid for given tstamp\r
+  if (!GoodPairID(beam)) return 0;\r
+  return (AliLHCDipValI*)FindRecValidFor(fBunchConfDecl[beam][kStart],fBunchConfDecl[beam][kNStor],tstamp);\r
+}\r
+\r
+//___________________________________________________________________\r
+TObject* AliLHCData::FindRecValidFor(int start,int nrec, double tstamp) const\r
+{\r
+  // find record within this limits valid for given tstamp (i.e. the last one before or equal to tstamp)\r
+  AliLHCDipValI *prevObj = 0;\r
+  for (int i=0;i<nrec;i++) {\r
+    AliLHCDipValI* curObj = (AliLHCDipValI*)fData[start+i];\r
+    if (TimeDifference(tstamp,curObj->GetTimeStamp())<0) break;\r
+    prevObj = curObj;\r
+  }\r
+  if (!prevObj && nrec>0) prevObj = (AliLHCDipValI*)fData[start]; // if no exact match, return the 1st one\r
+  return prevObj;\r
+}\r
+\r
+//___________________________________________________________________\r
+Int_t AliLHCData::FillScalarRecord(int refs[2], const char* rec, const char* recErr)\r
+{\r
+  // fill record for scalar value, optionally accompanied by measurement error \r
+  //\r
+  AliInfo(Form("Acquiring record: %s",rec));\r
+  //\r
+  TObjArray *arr=0,*arrE=0;\r
+  Int_t iLast=0,iLastE=0,iFirst=0,iFirstE=0;\r
+  //\r
+  refs[kStart] = fData.GetEntriesFast();\r
+  refs[kNStor] = 0;\r
+  //\r
+  if ( !(arr=GetDCSEntry(rec,iFirst,iLast,fTMin,fTMax)) ) return -1;\r
+  //\r
+  int dim = 1;\r
+  if (recErr) {\r
+    arrE = GetDCSEntry(recErr,iFirstE,iLastE,fTMin,fTMax);\r
+    dim += 1;\r
+  }\r
+  //\r
+  Bool_t last = kFALSE;\r
+  while (iFirst<=iLast) {\r
+    AliDCSArray *dcsVal = (AliDCSArray*) arr->At(iFirst++);\r
+    double tstamp = dcsVal->GetTimeStamp();\r
+    //\r
+    AliLHCDipValF* curValF = new AliLHCDipValF(dim,tstamp);  // start new period\r
+    (*curValF)[0] = ExtractDouble(dcsVal,0);     // value\r
+    //\r
+    if (recErr) {\r
+      double errVal = -1;\r
+      while (iFirstE<=iLastE) {       // try to find corresponding error\r
+       AliDCSArray *dcsValE = (AliDCSArray*) arrE->At(iFirstE);\r
+        double tstampE = dcsValE->GetTimeStamp();\r
+        int tdif = TimeDifference(tstamp,tstampE);\r
+        if (!tdif) { // error matches to value\r
+          errVal = ExtractDouble(dcsValE,0);\r
+         iFirstE++; \r
+         break;\r
+       }\r
+        else if (tdif>0) iFirstE++; // error time lags behind, read the next one\r
+        else break;                 // error time is ahead of value, no error associated\r
+      }\r
+      (*curValF)[dim-1] = errVal;   // error\r
+      curValF->SetLastSpecial();    // lable the last entry as an error\r
+    }\r
+    //\r
+    fData.Add(curValF);\r
+    refs[kNStor]++;\r
+    if (last) break;\r
+  }\r
+  //\r
+  if (fFile2Process) {\r
+    delete arr;\r
+    delete arrE;\r
+  }\r
+  return refs[kNStor];\r
+}\r
+\r
+//___________________________________________________________________\r
+Int_t AliLHCData::FillBunchConfig(int refs[2],const char* rec)\r
+{\r
+  // fill record for bunch configuration\r
+  //\r
+  AliInfo(Form("Acquiring record: %s",rec));\r
+  TObjArray *arr;\r
+  Int_t iLast,iFirst;\r
+  //\r
+  refs[kStart] = fData.GetEntriesFast();\r
+  refs[kNStor] = 0;\r
+  //\r
+  if ( !(arr=GetDCSEntry(rec,iFirst,iLast,fTMin,fTMax)) ) return -1;\r
+  //\r
+  AliLHCDipValI* prevRecI=0;\r
+  //  \r
+  while (iFirst<=iLast) {\r
+    AliDCSArray *dcsVal = (AliDCSArray*) arr->At(iFirst++);\r
+    double tstamp = dcsVal->GetTimeStamp();\r
+    //\r
+    int bucket=0, nbunch=0, ndiff=0;\r
+    int nSlots = dcsVal->GetNEntries();     // count number of actual bunches (non-zeros)\r
+    int* dcsArr = dcsVal->GetInt();\r
+    while(nbunch<nSlots && (bucket=dcsArr[nbunch])) {\r
+      if (prevRecI && prevRecI->GetSize()>nbunch && bucket!=prevRecI->GetValue(nbunch)) ndiff++;\r
+      nbunch++;\r
+    }\r
+    if (!nbunch) AliWarning(Form("%s record is present but empty: no beam?",rec));\r
+    if (prevRecI && !ndiff && nbunch==prevRecI->GetSize()) continue; // record similar to previous one\r
+    AliLHCDipValI* curValI = new AliLHCDipValI(nbunch,tstamp);      \r
+    for (int i=nbunch;i--;) (*curValI)[i] = dcsArr[i];\r
+    fData.Add(curValI);\r
+    refs[kNStor]++;\r
+    prevRecI = curValI;\r
+  }\r
+  //\r
+  if (fFile2Process) delete arr;\r
+  return refs[kNStor];\r
+}\r
\r
+//___________________________________________________________________\r
+Int_t AliLHCData::FillAcqMode(int refs[2],const char* rec)\r
+{\r
+  // fill acquisition mode\r
+  //\r
+  AliInfo(Form("Acquiring record: %s",rec));\r
+  TObjArray *arr;\r
+  Int_t iLast,iFirst;\r
+  //\r
+  refs[kStart] = fData.GetEntriesFast();\r
+  refs[kNStor] = 0;\r
+  //\r
+  if ( !(arr=GetDCSEntry(rec,iFirst,iLast,fTMin,fTMax)) ) return -1;\r
+  //\r
+  AliLHCDipValI* prevRecI=0;\r
+  while (iFirst<=iLast) {\r
+    AliDCSArray *dcsVal = (AliDCSArray*) arr->At(iFirst++);\r
+    double tstamp = dcsVal->GetTimeStamp();\r
+    //\r
+    int nSlots = dcsVal->GetNEntries();\r
+    if (nSlots<1) continue;\r
+    int acqMode = dcsVal->GetInt()[0];\r
+    if (prevRecI && (*prevRecI)[0] == acqMode) continue; // record similar to previous one\r
+    AliLHCDipValI* curValI = new AliLHCDipValI(1,tstamp);      \r
+    (*curValI)[0] = acqMode;\r
+    fData.Add(curValI);\r
+    refs[kNStor]++;\r
+    prevRecI = curValI;\r
+  }\r
+  //\r
+  if (fFile2Process) delete arr;\r
+  return refs[kNStor];\r
+}\r
\r
+//___________________________________________________________________\r
+Int_t AliLHCData::FillStringRecord(int refs[2],const char* rec)\r
+{\r
+  // fill record with string value\r
+  //\r
+  AliInfo(Form("Acquiring record: %s",rec));\r
+  TString prevRec;\r
+  TObjArray *arr;\r
+  Int_t iLast,iFirst;\r
+  //\r
+  refs[kStart] = fData.GetEntriesFast();\r
+  refs[kNStor] = 0;\r
+  //\r
+  if ( !(arr=GetDCSEntry(rec,iFirst,iLast,fTMin,fTMax)) ) return -1;\r
+  //\r
+  while (iFirst<=iLast) {\r
+    AliDCSArray *dcsVal = (AliDCSArray*) arr->At(iFirst++);\r
+    double tstamp = dcsVal->GetTimeStamp();\r
+    //\r
+    TString &str = ExtractString(dcsVal);\r
+    if (!prevRec.IsNull()) {if (str == prevRec) continue;} // skip similar record\r
+    else prevRec = str;\r
+    //\r
+    AliLHCDipValC* curValS = new AliLHCDipValC(1,tstamp);      \r
+    curValS->SetValues(str.Data(),str.Length()+1);\r
+    //\r
+    fData.Add(curValS);\r
+    refs[kNStor]++;\r
+  }\r
+  if (fFile2Process) delete arr;\r
+  return refs[kNStor];\r
+}\r
+\r
+//___________________________________________________________________\r
+Int_t AliLHCData::FillBunchInfo(int refs[2],const char* rec, int ibm, Bool_t inRealSlots)\r
+{\r
+  // fill bunch properties for beam ibm\r
+  // if inRealSlots = true, then the value is taken from bunchRFbucket/10, otherwise, the value \r
+  // for the i-th bunch is taken from the i-th element\r
+  //\r
+  AliInfo(Form("Acquiring record: %s",rec));\r
+  TObjArray *arr;\r
+  Int_t iLast,iFirst;\r
+  //\r
+  refs[kStart] = fData.GetEntriesFast();\r
+  refs[kNStor] = 0;\r
+  //\r
+  if ( !(arr=GetDCSEntry(rec,iFirst,iLast,fTMin,fTMax)) ) return -1;\r
+  //\r
+  while (iFirst<=iLast) {\r
+    AliDCSArray *dcsVal = (AliDCSArray*) arr->At(iFirst++);\r
+    double tstamp = dcsVal->GetTimeStamp();\r
+    //\r
+    AliLHCDipValI *bconf = GetBunchConfigMeasured(ibm,tstamp);\r
+    if (!bconf) {\r
+      AliWarning(Form("Mearured bunch configuration for beam %d at t=%.1f is not available, trying declared one",ibm+1,tstamp));\r
+      bconf = GetBunchConfigDeclared(ibm,tstamp);\r
+    }\r
+    if (!bconf) {\r
+      AliWarning(Form("Declared bunch configuration for beam %d at t=%.1f is not available, skip this record",ibm+1,tstamp));\r
+      return -1;\r
+    }\r
+    int nSlots = dcsVal->GetNEntries();     // count number of actual bunches (non-zeros)\r
+    int nbunch = bconf->GetSize();\r
+    if (nbunch>nSlots) {\r
+      AliWarning(Form("More N bunches than slots in %s at time %.1f",rec,tstamp));\r
+      continue;\r
+    }\r
+    double* dcsArr = dcsVal->GetDouble();\r
+    AliLHCDipValF* curValF = new AliLHCDipValF(nbunch,tstamp);\r
+    for (int i=nbunch;i--;) {\r
+      int ind = inRealSlots ? (*bconf)[i]/10 : i;\r
+      if (ind>nSlots) {\r
+       AliError(Form("Bunch %d refers to wrong slot %d, set to -1",i,(*bconf)[i]));\r
+       (*curValF)[i] = -1;\r
+      }\r
+      else (*curValF)[i] = dcsArr[ind];\r
+    }\r
+    fData.Add(curValF);\r
+    refs[kNStor]++;\r
+  }\r
+  if (fFile2Process) delete arr;\r
+  return refs[kNStor];\r
+  //\r
+}\r
\r
+//___________________________________________________________________\r
+Int_t AliLHCData::FillBCLuminosities(int refs[2],const char* rec, const char* recErr, int useBeam)\r
+{\r
+  // fill luminosities per bunch crossing\r
+  //\r
+  AliInfo(Form("Acquiring record: %s",rec));\r
+  TObjArray *arr,*arrE=0;\r
+  Int_t iLast=0,iLastE=0,iFirst=0,iFirstE=0;\r
+  //\r
+  refs[kStart] = fData.GetEntriesFast();\r
+  refs[kNStor] = 0;\r
+  //\r
+  if ( !(arr=GetDCSEntry(rec,iFirst,iLast,fTMin,fTMax)) ) return -1;\r
+  //\r
+  while (iFirst<=iLast) {\r
+    AliDCSArray *dcsVal = (AliDCSArray*) arr->At(iFirst++);\r
+    double tstamp = dcsVal->GetTimeStamp();\r
+    //\r
+    AliLHCDipValI *bconf;\r
+    bconf = GetBunchConfigMeasured(useBeam,tstamp);  // luminosities are stored according to beam bunches\r
+    if (!bconf) {\r
+      AliWarning(Form("Mearured bunch configuration for beam%d at t=%.1f is not available, trying declared one",useBeam,tstamp));\r
+      bconf = GetBunchConfigDeclared(useBeam,tstamp);\r
+    }\r
+    if (!bconf) {\r
+      AliWarning(Form("Declared bunch configuration for beam%i at t=%.1f is not available, skip this record",useBeam,tstamp));\r
+      return -1;\r
+    }\r
+    int nSlots = dcsVal->GetNEntries();     // count number of actual bunches (non-zeros)\r
+    int nbunch = bconf->GetSize();\r
+    double* dcsArr = dcsVal->GetDouble();\r
+    //\r
+    if (nbunch>nSlots) {\r
+      AliWarning(Form("More N bunches than slots in %s at time %.1f",rec,tstamp));\r
+      continue;\r
+    }\r
+    int dim = 0;\r
+    if (!bconf->IsProcessed1()) {\r
+      AliWarning(Form("Bunch conf. for beam%d has no marked interacting bunches, store all luminosity for all filled bunches",useBeam));\r
+      dim = nbunch;\r
+    }\r
+    else { // count number of interacting bunches\r
+      for (int i=nbunch;i--;) if ((*bconf)[i]<0) dim++;\r
+    }\r
+    //\r
+    if (recErr) {\r
+      arrE=GetDCSEntry(recErr,iFirstE,iLastE,fTMin,fTMax);\r
+      dim += 1;\r
+    }\r
+    AliLHCDipValF* curValF = new AliLHCDipValF(dim,tstamp);\r
+    int cnt = 0;\r
+    for (int i=0;i<nbunch;i++) {\r
+      int slot = (*bconf)[i];\r
+      if (bconf->IsProcessed1() && slot>0) continue;\r
+      //\r
+      int ind = TMath::Abs(slot)/10;\r
+      if (ind>nSlots) {\r
+       AliError(Form("Bunch %d refers to wrong slot %d, set to -1",cnt,slot));\r
+       (*curValF)[cnt] = -1;\r
+      }\r
+      else (*curValF)[cnt] = dcsArr[ind];\r
+      cnt++;\r
+    }\r
+    //\r
+    if (recErr) {\r
+      double errVal = -1;\r
+      while (iFirstE<=iLastE) {       // try to find corresponding error\r
+       AliDCSArray *dcsValE = (AliDCSArray*) arrE->At(iFirstE);\r
+       double tstamp1 = dcsValE->GetTimeStamp();\r
+       int tdif = TimeDifference(tstamp,tstamp1);\r
+       if (!tdif) { // error matches to value\r
+         errVal = dcsValE->GetDouble()[0];\r
+         iFirstE++; \r
+         break;\r
+       }\r
+       else if (tdif>0) iFirstE++; // error time lags behind, read the next one\r
+       else break;                 // error time is ahead of value, no error associated\r
+      }\r
+      (*curValF)[dim-1] = errVal;   // error\r
+      curValF->SetLastSpecial();    // lable the last entry as an error\r
+    }\r
+    //\r
+    fData.Add(curValF);\r
+    refs[kNStor]++;\r
+  }\r
+  if (fFile2Process) {\r
+    delete arr;\r
+    delete arrE;\r
+  }\r
+  return refs[kNStor];\r
+  //\r
+}\r
+\r
+//___________________________________________________________________\r
+Int_t AliLHCData::ExtractInt(AliDCSArray* dcsArray,Int_t el) const\r
+{\r
+  // extract integer from the dcsArray\r
+  int val = -1;\r
+  //\r
+  int sz = dcsArray->GetNEntries();\r
+  if (sz<=el) return val;\r
+  //\r
+  if (dcsArray->GetType()==AliDCSArray::kInt)  val = dcsArray->GetInt(el);\r
+  else if (dcsArray->GetType()==AliDCSArray::kString) {\r
+    TObjString *stro = dcsArray->GetStringArray(el);\r
+    if (stro) val = stro->GetString().Atoi();\r
+    else AliError(Form("DCSArray TObjString for element %d is missing",el));\r
+  }\r
+  else if (dcsArray->GetType()==AliDCSArray::kUInt) val = dcsArray->GetUInt(el);\r
+  else AliError(Form("Integer requested from DCSArray of type %d",dcsArray->GetType()));\r
+  return val;\r
+}\r
+\r
+//___________________________________________________________________\r
+Double_t AliLHCData::ExtractDouble(AliDCSArray* dcsArray,Int_t el) const\r
+{\r
+  // extract double from the dcsArray\r
+  double val = 0;\r
+  //\r
+  int sz = dcsArray->GetNEntries();\r
+  if (sz<=el) return val;\r
+  //\r
+  if      (dcsArray->GetType()==AliDCSArray::kDouble) val = dcsArray->GetDouble(el);\r
+  else if (dcsArray->GetType()==AliDCSArray::kFloat)  val = dcsArray->GetFloat(el);\r
+  else if (dcsArray->GetType()==AliDCSArray::kString) {\r
+    TObjString *stro = dcsArray->GetStringArray(el);\r
+    if (stro) val = stro->GetString().Atof();\r
+    else AliError(Form("DCSArray has TObjString for element %d is missing",el));\r
+  }\r
+  else if (dcsArray->GetType()==AliDCSArray::kChar)   val = dcsArray->GetChar(el);\r
+  else if (dcsArray->GetType()==AliDCSArray::kInt)    val = dcsArray->GetInt(el);\r
+  else if (dcsArray->GetType()==AliDCSArray::kUInt)   val = dcsArray->GetUInt(el);\r
+  else     AliError(Form("Double requested from DCSArray of type %d",dcsArray->GetType()));\r
+  return val;\r
+}\r
+\r
+//___________________________________________________________________\r
+TString& AliLHCData::ExtractString(AliDCSArray* dcsArray) const\r
+{\r
+  // extract string from the dcsArray\r
+  static TString str;\r
+  str = "";\r
+  //\r
+  int sz = dcsArray->GetNEntries();\r
+  if (dcsArray->GetType()!=AliDCSArray::kString)  {\r
+    AliError(Form("String requested from DCSArray of type %d",dcsArray->GetType()));\r
+    return str;\r
+  }\r
+  //\r
+  for (int i=0;i<sz;i++) {\r
+    str += dcsArray->GetStringArray(i)->GetString();\r
+    if (i<sz-1) str += " ";\r
+  }\r
+  return str;\r
+}\r
+\r
+//___________________________________________________________________\r
+void AliLHCData::Print(const Option_t* opt) const\r
+{\r
+  // print full info\r
+  TString opts = opt;\r
+  opts.ToLower();\r
+  Bool_t utcTime = opts.Contains("loc") ? kFALSE:kTRUE;\r
+  Bool_t full = kTRUE;\r
+  if (!opts.Contains("f")) {\r
+    printf("Use Print(\"f\") to print full info\n");\r
+    printf("Printing short info:\n<RecordType>(number of records): <TimeStamp, value> for 1st record only\n");\r
+    full = kFALSE;\r
+  }\r
+  TString sdtmn = AliLHCDipValI::TimeAsString(fTMin,utcTime);\r
+  TString sdtmx = AliLHCDipValI::TimeAsString(fTMax,utcTime);\r
+  printf("Fill#%6d Validity: %s - %s (%s)\n",fFillNumber,sdtmn.Data(),sdtmx.Data(),utcTime ? "UTC":"LOC");\r
+  //\r
+  printf("********** SETTINGS FROM RUN CONTROL **********\n");\r
+  //\r
+  printf("* %-38s","Injection Scheme");\r
+  PrintAux(full,fRCInjScheme,opts);\r
+  //\r
+  printf("* %-38s","Beta Star");\r
+  PrintAux(full,fRCBeta,opts);\r
+  //\r
+  printf("* %-38s","Horisontal Crossing Angle");\r
+  PrintAux(full,fRCAngH,opts);\r
+  //\r
+  printf("* %-38s","Vertical   Crossing Angle");\r
+  PrintAux(full,fRCAngV,opts);\r
+  //\r
+  for (int ib=0;ib<2;ib++) {\r
+    printf("* Beam%d filling  [- interacts at IR2!]  ",ib+1);\r
+    PrintAux(full,fBunchConfDecl[ib],opts);\r
+  }\r
+  //\r
+  printf("\n**********       MEASURED DATA       **********\n");\r
+  //\r
+  for (int ib=0;ib<2;ib++) {\r
+    printf("* Beam%d filling  [- interacts at IR2!]  ",ib+1);\r
+    PrintAux(full,fBunchConfMeas[ib],opts);\r
+  } \r
+  //\r
+  for (int ib=0;ib<2;ib++) {\r
+    printf("* Beam%d total intensity                 ",ib+1);\r
+    PrintAux(full,fIntensTotal[ib],opts);\r
+  } \r
+  //\r
+  for (int ib=0;ib<2;ib++) {\r
+    printf("* Beam%d total intensity (bunch average) ",ib+1);\r
+    PrintAux(full,fIntensTotalAv[ib],opts);\r
+  } \r
+  //\r
+  for (int ib=0;ib<2;ib++) {\r
+    printf("* Beam%d intensity per bunch             ",ib+1);\r
+    PrintAux(full,fIntensPerBunch[ib],opts);\r
+  }\r
+  //\r
+  for (int ib=0;ib<2;ib++) {\r
+    printf("* Beam%d bunch lengths                   ",ib+1);\r
+    PrintAux(full,fBunchLengths[ib],opts);\r
+  } \r
+  //\r
+  for (int ib=0;ib<2;ib++) {\r
+    printf("* Beam%d Horisontal emittance            ",ib+1);\r
+    PrintAux(full,fEmittanceH[ib],opts);\r
+  }\r
+  //\r
+  for (int ib=0;ib<2;ib++) {\r
+    printf("* Beam%d Vertical emittance              ",ib+1);\r
+    PrintAux(full,fEmittanceV[ib],opts);\r
+  }\r
+  //\r
+  for (int ib=0;ib<2;ib++) {\r
+    printf("* Beam%d Horisontal sigma                ",ib+1);\r
+    PrintAux(full,fBeamSigmaH[ib],opts);\r
+  }\r
+  //\r
+  for (int ib=0;ib<2;ib++) {\r
+    printf("* Beam%d Vertical sigma                  ",ib+1);\r
+    PrintAux(full,fBeamSigmaV[ib],opts);\r
+  }\r
+  //\r
+  for (int lr=0;lr<2;lr++) {\r
+    printf("* Total luminosity from BRANB_4%c2       ",lr ? 'R':'L');\r
+    PrintAux(full,fLuminTotal[lr],opts);\r
+  } \r
+  //\r
+  for (int lr=0;lr<2;lr++) {\r
+    printf("* Luminosity acq.mode, BRANB_4%c2        ",lr ? 'R':'L');\r
+    PrintAux(full,fLuminAcqMode[lr],opts+"bit");\r
+  } \r
+  //\r
+  for (int lr=0;lr<2;lr++) {\r
+    printf("* Luminosity per BC from BRANB_4%c2      ",lr ? 'R':'L');\r
+    PrintAux(full,fLuminPerBC[lr],opts);\r
+  }\r
+  //\r
+  for (int lr=0;lr<2;lr++) {\r
+    printf("* Crossing angle, side %c                ",lr ? 'R':'L');\r
+    PrintAux(full,fCrossAngle[lr],opts);\r
+  }\r
+  //\r
+  for (int coll=0;coll<kNCollimators;coll++)\r
+    for (int jaw=0;jaw<kNJaws;jaw++) {\r
+      printf("* Collimator %10s:%16s",fgkDCSColNames[coll],fgkDCSColJaws[jaw]);\r
+      PrintAux(full,fCollimators[coll][jaw],opts);\r
+    }\r
+  //\r
+}\r
+\r
+//___________________________________________________________________\r
+void AliLHCData::PrintAux(Bool_t full, const Int_t refs[2], const Option_t *opt) const\r
+{\r
+  // aux method to print the reocrds of the same type\r
+  int nrec = refs[kNStor];\r
+  if (nrec<1) {\r
+    printf(": N/A\n"); \r
+    return;\r
+  }\r
+  printf(": (%3d):\t",nrec); // number of records\r
+  if (!full) nrec = 1;\r
+  int sz = ((AliLHCDipValI*)fData[refs[kStart]])->GetSizeTotal(); // dimension of the record\r
+  Bool_t isStr = ((AliLHCDipValI*)fData[refs[kStart]])->IsTypeC();\r
+  if ((!isStr && sz>2) || nrec>1) printf("\n"); // long record, open new line\r
+  for (int i=0;i<nrec;i++) fData[refs[kStart]+i]->Print(opt);\r
+  //\r
+}\r
+\r
+//___________________________________________________________________\r
+void AliLHCData::Clear(const Option_t *)\r
+{\r
+  // clear all info\r
+  fData.Delete();\r
+  fFillNumber = 0;\r
+  fTMin = 0;\r
+  fTMax = 1e10;\r
+  fFile2Process = 0;\r
+  fMap2Process  = 0;\r
+  //\r
+  for (int i=2;i--;) {\r
+    fRCInjScheme[i] = 0;\r
+    fRCBeta[i] = 0;\r
+    fRCAngH[i] = 0;\r
+    fRCAngV[i] = 0;\r
+    //\r
+    for (int icl=kNCollimators;icl--;) for (int jaw=kNJaws;jaw--;) fCollimators[icl][jaw][i]=0;\r
+    //\r
+    for (int j=2;j--;) {\r
+      fBunchConfDecl[j][i] = 0;\r
+      fBunchConfMeas[j][i] = 0;\r
+      fBunchLengths[j][i] = 0;\r
+      fIntensTotal[j][i] = 0;\r
+      fIntensTotalAv[j][i] = 0;\r
+      fIntensPerBunch[j][i] = 0;      \r
+      fCrossAngle[j][i] = 0;\r
+      fEmittanceH[j][i] = 0;\r
+      fEmittanceV[j][i] = 0;\r
+      fBeamSigmaH[j][i] = 0;\r
+      fBeamSigmaV[j][i] = 0;\r
+      fLuminTotal[j][i] = 0;\r
+      fLuminPerBC[j][i] = 0;\r
+      fLuminAcqMode[j][i] = 0;\r
+    }\r
+  }\r
+}\r
+\r
+//___________________________________________________________________\r
+Int_t AliLHCData::GetNInteractingBunchesMeasured(int i) const\r
+{\r
+  // get number of interacting bunches at IR2\r
+  AliLHCDipValI* rec = GetBunchConfigMeasured(kBeam1,i);\r
+  if (!rec) {AliInfo(Form("No record %d found",i)); return -1;}\r
+  if (!rec->IsProcessed1()) { AliInfo("Interacting bunches were not marked"); return -1;}\r
+  int n = 0;\r
+  for (int j=rec->GetSize();j--;) if ( (*rec)[j]<0 ) n++;\r
+  return n;\r
+}\r
+\r
+//___________________________________________________________________\r
+Int_t AliLHCData::GetNInteractingBunchesDeclared(int i) const\r
+{\r
+  // get number of interacting bunches at IR2\r
+  AliLHCDipValI* rec = GetBunchConfigMeasured(kBeam1,i);\r
+  if (!rec) {AliInfo(Form("No record %d found",i)); return -1;}\r
+  if (!rec->IsProcessed1()) { AliInfo("Interacting bunches were not marked"); return -1; }\r
+  int n = 0;\r
+  for (int j=rec->GetSize();j--;) if ( (*rec)[j]<0 ) n++;\r
+  return n;\r
+}\r
+\r
+//___________________________________________________________________\r
+Int_t AliLHCData::IsPilotPresent(int i) const\r
+{\r
+  // check in the filling scheme is the pilot bunch is present\r
+  AliLHCDipValC* rec = GetInjectionScheme();\r
+  if (!rec) {AliInfo(Form("No record %d found",i)); return -1;}\r
+  TString scheme = rec->GetValues();\r
+  return scheme.Contains("wp",TString::kIgnoreCase);\r
+}\r
+\r
+//___________________________________________________________________\r
+void AliLHCData::FlagInteractingBunches(const Int_t beam1[2],const Int_t beam2[2])\r
+{\r
+  // assign - sign to interacting bunches\r
+  const int kMaxSlots  = 3564;\r
+  const int kOffsBeam1 = 346;\r
+  const int kOffsBeam2 = 3019;\r
+  //\r
+  for (int ib1=0;ib1<beam1[kNStor];ib1++) {\r
+    AliLHCDipValI *bm1 = (AliLHCDipValI*)fData[ beam1[kStart] + ib1];\r
+    if (!bm1) continue;\r
+    AliLHCDipValI *bm2 = (AliLHCDipValI*)FindRecValidFor(beam2[kStart],beam2[kNStor], bm1->GetTimeStamp());\r
+    if (!bm2) continue;\r
+    //\r
+    int nb1 = bm1->GetSize();\r
+    int nb2 = bm2->GetSize();\r
+    int i1,i2;\r
+    for (i1=0;i1<nb1;i1++) {\r
+      int bunch2=-1, bunch1 = TMath::Abs((*bm1)[i1]);\r
+      int slot2 =-1, slot1  = (bunch1/10 + kOffsBeam1)%kMaxSlots;\r
+      for (i2=0;i2<nb2;i2++) {\r
+       bunch2 = TMath::Abs((*bm2)[i2]);\r
+       slot2 = (bunch2/10 + kOffsBeam2)%kMaxSlots;\r
+       if (slot1==slot2) break;\r
+      }\r
+      if (slot1!=slot2) continue;\r
+      (*bm1)[i1] = -bunch1;\r
+      (*bm2)[i2] = -bunch2;\r
+      bm1->SetProcessed1();\r
+      bm2->SetProcessed1();\r
+    }\r
+  }\r
+}\r
+\r
+//___________________________________________________________________\r
+Int_t AliLHCData::GetMeanIntensity(int beamID, Double_t &colliding, Double_t &noncolliding) const\r
+{\r
+  // get average intensity for all, colliding and non-colliding bunches\r
+  // on success returns number of intensity records used (1 per ~10 min)\r
+  colliding = noncolliding = -1.;\r
+  if (beamID<0||beamID>1) {\r
+    AliError(Form("BeamID must be either 0 or 1, %d requested",beamID));\r
+    return -10;\r
+  }\r
+  //\r
+  int nrec = GetNIntensityPerBunch(beamID);\r
+  if (nrec<1) return -1;\r
+  AliLHCDipValI *conf = GetBunchConfigMeasured(beamID);\r
+  if (!conf) conf = GetBunchConfigDeclared(beamID);\r
+  if (!conf) return -2;\r
+  int nb = conf->GetSize();\r
+  //\r
+  for (int irec=0;irec<nrec;irec++) {\r
+    AliLHCDipValF* rInt = GetIntensityPerBunch(beamID,irec);\r
+    for (int ib=0;ib<nb;ib++) {\r
+      double val = rInt->GetValue(ib);\r
+      if (val<0) continue;\r
+      int bID = conf->GetValue(ib);\r
+      if (bID<0) colliding += val;\r
+      else noncolliding += val;\r
+    }\r
+  }\r
+  colliding /= nrec;\r
+  noncolliding /= nrec;\r
+  return nrec;\r
+}\r