implemented new LHCData records storage, added option to skip missing records in...
[u/mrichter/AliRoot.git] / STEER / STEER / AliLHCData.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  *                                                                        *
15  **************************************************************************/
16
17 /********************************************************************************
18 *                                                                               *
19 *   AliLHCData: summary of the LHC related information from LHC DIP.            *
20 *   Created from the TMap provided by the AliLHCReader with optional beginning  *
21 *                                                                               *
22 *   The data are (wrapped in the AliLHCDipValT):                                *
23 *   made of TimeStamp (double) and array of values                              *
24 *                                                                               *
25 *   Multiple entries for each type of data are possible. To obtaine number of   *
26 *   records (with distinct timestamp) for give type od records use:             *
27 *   int GetNBunchConfigMeasured(int beam) (with beam=0,1) etc.                  *
28 *                                                                               *
29 *   To get i-th entry, use brec= AliLHCDipValI* GetBunchConfigMeasured(bm,i);   *
30 *   Note: exact type of templated AliLHCDipValT pointer depends on the record   *
31 *   type, concult getters to know it.                                           *
32 *                                                                               *
33 *   Then, once the pointer is obtained, details can be accessed:                *
34 *   int nBunches = brec->GetSize();                                             *
35 *   for (int i=0;i<nBunches;i++) printf("Bunch#%d: %d\n",i,(*brec)[i]);         *
36 *                                                                               *
37 *                                                                               *
38 *   Author: ruben.shahoyan@cern.ch                                              *
39 *                                                                               *
40 ********************************************************************************/
41
42 #include "AliLHCData.h"
43 #include "TMap.h"
44 #include "AliDCSArray.h"
45 #include "AliLHCReader.h"
46 #include "AliTriggerBCMask.h"
47 #include <TString.h>
48 #include <TObjArray.h>
49 #include <TGraph.h>
50
51 ClassImp(AliLHCData)
52
53 const Char_t* AliLHCData::fgkDCSNames[] = {
54   "LHC_IntensityBeam%1d_totalIntensity"
55   ,"LHC_BeamIntensityPerBunchBeam%1d_averageBeamIntensity"
56   ,"LHC_BeamIntensityPerBunchBeam%1d_Average_BunchIntensities"
57   //
58   ,"LHC_LumAverageBRANB_4%c2_acqMode"
59   ,"LHC_LumAverageBRANB_4%c2_meanLuminosity"
60   ,"LHC_LumAverageBRANB_4%c2_meanLuminosityError"
61   ,"LHC_BeamLuminosityPerBunchBRANB_4%c2_Average_BunchLuminosity"
62   ,"LHC_BeamLuminosityPerBunchBRANB_4%c2_BunchLuminosityError"
63   ,"LHC_LumAverageBRANB_4%c2_meanCrossingAngle"
64   ,"LHC_LumAverageBRANB_4%c2_meanCrossingAngleError"
65   ,"LHC_CirculatingBunchConfig_Beam%d"
66   ,"LHC_FillNumber"
67   //
68   ,"LHC_BunchLengthBeam%1d_nBunches"
69   ,"LHC_BunchLengthBeam%1d_bunchesLenghts"
70   ,"LHC_BunchLengthBeam%1d_filledBuckets"
71   //
72   ,"LHC_RunControl_ActiveInjectionScheme"
73   ,"LHC_RunControl_BetaStar"
74   ,"LHC_RunControl_IP2_Xing_Murad"
75   ,"LHC_RunControl_IP2_ALICE_Murad"
76
77   ,"LHC_BeamSizeBeam%1d_acqMode"
78   ,"LHC_BeamSizeBeam%1d_sigmaH"
79   ,"LHC_BeamSizeBeam%1d_sigmaV"
80   ,"LHC_BeamSizeBeam%1d_emittanceH"
81   ,"LHC_BeamSizeBeam%1d_emittanceV"
82   ,"LHC_BeamSizeBeam%1d_errorSigmaH"
83   ,"LHC_BeamSizeBeam%1d_errorSigmaV"
84   //
85   ,"LHC_CollimatorPos_%s_lvdt_%s"
86   //
87   ,"BPTX_deltaT_B1_B2"
88   ,"BPTX_deltaTRMS_B1_B2"
89   ,"BPTX_Phase_B%1d"
90   ,"BPTX_PhaseRMS_B%1d"
91   ,"BPTX_Phase_Shift_B%1d"
92   //
93   ,"ALI_Lumi_Total_Inst"
94   ,"ALI_Lumi_Total_Delivered_StabBeam"
95   ,"ALI_Lumi_Bunch_Inst"
96   ,"ALI_Background%1d"
97 };
98
99 const Char_t* AliLHCData::fgkDCSColNames[] = {
100   "TCTVB_4L2",
101   "TCTVB_4R2",
102   "TCLIA_4R2"
103 };
104
105 const Char_t* AliLHCData::fgkDCSColJaws[] = {
106   "gap_downstream","gap_upstream","left_downstream",
107   "left_upstream","right_downstream","right_upstream"};
108
109 //___________________________________________________________________
110 AliLHCData::AliLHCData(const TMap* dcsMap, double tmin, double tmax)
111   : fTMin(0),fTMax(0),fFillNumber(0),fData(0),fkFile2Process(0),fkMap2Process(0)
112 {
113   FillData(dcsMap,tmin,tmax);
114 }
115
116 //___________________________________________________________________
117 AliLHCData::AliLHCData(const Char_t* dcsFile, double tmin, double tmax)
118   : fTMin(0),fTMax(0),fFillNumber(0),fData(0),fkFile2Process(dcsFile),fkMap2Process(0)
119 {
120   FillData(dcsFile,tmin,tmax);
121 }
122
123 //___________________________________________________________________
124 Bool_t AliLHCData::FillData(const TMap*   dcsMap,double tmin, double tmax)
125 {
126   // process DCS map and fill all fields. 
127   Clear();
128   fkMap2Process = dcsMap;
129   FillData(tmin,tmax);
130   return kTRUE;
131 }
132
133 //___________________________________________________________________
134 Bool_t AliLHCData::FillData(const Char_t* dcsFile,double tmin, double tmax)
135 {
136   // process DCS file and fill all fields. 
137   Clear();
138   fkFile2Process = dcsFile;
139   FillData(tmin,tmax);
140   return kTRUE;
141 }
142
143 //___________________________________________________________________
144 Bool_t AliLHCData::FillData(double tmin, double tmax)
145 {
146   // process DCS map and fill all fields. 
147   // Accept only entries with timestamp between tmin and tmax
148   //
149   char buff[100],buff1[100];
150   //
151   SetTMin(tmin);
152   SetTMax(tmax);
153   //
154   // -------------------------- extract Fill Number
155   int iFirst=0,iLast=0;
156   TObjArray* arr = GetDCSEntry(fgkDCSNames[kFillNum],iFirst,iLast,fTMin,fTMax);
157   if (arr) SetFillNumber( ExtractInt( (AliDCSArray*)arr->At(iFirst), 0) );
158   if (fkFile2Process) delete arr; // array was created on demand
159   //
160   for (int ibm=0;ibm<2;ibm++) {
161     //
162     snprintf(buff,99,fgkDCSNames[kBunchConf],ibm+1);         // ----- declared bunch configuration
163     FillBunchConfig(fBunchConfDecl[ibm], buff);
164     //
165     snprintf(buff,99,fgkDCSNames[kBunchLgtFillB],ibm+1);     // ----- measured bunch configuration
166     FillBunchConfig(fBunchConfMeas[ibm], buff);
167     //
168     snprintf(buff,99,fgkDCSNames[kBunchLgt],ibm+1);          // ----- measured bunch lenghts
169     FillBunchInfo(fBunchLengths[ibm],buff,ibm,kFALSE);  
170     //
171     snprintf(buff,99,fgkDCSNames[kIntBunchAv],ibm+1);        // ----- B-by-B intensities
172     FillBunchInfo(fIntensPerBunch[ibm],buff,ibm,kTRUE);
173     //
174     //
175     snprintf(buff,99,fgkDCSNames[kIntTot],ibm+1);            // ----- total intensities for beam 1 and 2
176     FillScalarRecord(fIntensTotal[ibm], buff);
177     //
178     snprintf(buff,99,fgkDCSNames[kIntTotAv],ibm+1);          // ----- total intensities for beam 1 and 2 from B-by-B average
179     FillScalarRecord(fIntensTotalAv[ibm], buff);
180     //
181     snprintf(buff,99,fgkDCSNames[kBeamSzEmittH],ibm+1);      // ----- H emittance for beam 1 and 2 
182     FillScalarRecord(fEmittanceH[ibm], buff);
183     //
184     snprintf(buff,99,fgkDCSNames[kBeamSzEmittV],ibm+1);      // ----- V emittance for beam 1 and 2 
185     FillScalarRecord(fEmittanceV[ibm], buff);
186     //
187     snprintf(buff,99 ,fgkDCSNames[kBeamSzSigH],   ibm+1);    // ----- H sigmas and errors for beam 1 and 2 
188     snprintf(buff1,99,fgkDCSNames[kBeamSzSigHErr],ibm+1);
189     FillScalarRecord(fBeamSigmaH[ibm], buff, buff1);
190     //
191     snprintf(buff,99 ,fgkDCSNames[kBeamSzSigV],   ibm+1);    // ----- V sigmas and errors for beam 1 and 2 
192     snprintf(buff1,99,fgkDCSNames[kBeamSzSigVErr],ibm+1);
193     FillScalarRecord(fBeamSigmaV[ibm], buff, buff1);
194     //
195     //
196     snprintf(buff,99,fgkDCSNames[kBPTXPhase],ibm+1);         // ----- BPTXPhase beam 1 and 2
197     FillScalarRecord(fBPTXPhase[ibm], buff);
198     //
199     snprintf(buff,99,fgkDCSNames[kBPTXPhaseRMS],ibm+1);      // ----- BPTXPhaseRMS beam 1 and 2
200     FillScalarRecord(fBPTXPhaseRMS[ibm], buff);
201     //
202     snprintf(buff,99,fgkDCSNames[kBPTXPhaseShift],ibm+1);    // ----- BPTXPhaseShift beam 1 and 2
203     FillScalarRecord(fBPTXPhaseShift[ibm], buff);
204     //
205   }
206   //
207   for (int ibg=0;ibg<kNBGs;ibg++) {
208     snprintf(buff,99,fgkDCSNames[kALIBackground],ibg+1);    // ----- Alice backgrounds 1,2,3
209     FillScalarRecord(fBckgAlice[ibg], buff);
210   }
211   //
212   FlagInteractingBunches(fBunchConfMeas[0],fBunchConfMeas[1]);
213   FlagInteractingBunches(fBunchConfDecl[0],fBunchConfDecl[1]);
214   //
215   for (int ilr=0;ilr<2;ilr++) {
216     //
217     snprintf(buff,99 ,fgkDCSNames[kLumBunch], ilr ? 'R':'L');       // ---- BC-by-BC luminosity at IP2 and its error
218     snprintf(buff1,99,fgkDCSNames[kLumBunchErr], ilr ? 'R':'L');
219     FillBCLuminosities(fLuminPerBC[ilr], buff, buff1, 0); // BRAN L uses beam2 as a reference, BRAN R - beam1
220     //
221     snprintf(buff,99 ,fgkDCSNames[kLumTot]   , ilr ? 'R':'L');       // ---- total luminosity at IP2 and its error
222     snprintf(buff1,99,fgkDCSNames[kLumTotErr], ilr ? 'R':'L');
223     FillScalarRecord(fLuminTotal[ilr], buff, buff1);
224     //
225     snprintf(buff,99 ,fgkDCSNames[kLumAcqMode], ilr ? 'R':'L');      // ---- luminosity acquisition mode
226     FillAcqMode(fLuminAcqMode[ilr], buff);
227     //
228     snprintf(buff,99, fgkDCSNames[kLumCrossAng]   , ilr ? 'R':'L');  //----- crossing angle at IP2 and its error
229     snprintf(buff1,99,fgkDCSNames[kLumCrossAngErr], ilr ? 'R':'L');
230     FillScalarRecord(fCrossAngle[ilr], buff, buff1);
231     //    
232   }
233   //
234   for (int icl=0;icl<kNCollimators;icl++) {             // ----- collimators positions
235     for (int jaw=0;jaw<kNJaws;jaw++) {
236       snprintf(buff,99,fgkDCSNames[kCollPos], fgkDCSColNames[icl],fgkDCSColJaws[jaw]);        
237       FillScalarRecord(fCollimators[icl][jaw], buff);
238     } // jaws
239   } // collimators
240   //
241   //
242   // RunControl info
243   FillStringRecord(fRCInjScheme, fgkDCSNames[kRCInjSch]);   // ---- active injection scheme
244   FillScalarRecord(fRCBeta, fgkDCSNames[kRCBeta]);          // ---- target beta 
245   FillScalarRecord(fRCAngH, fgkDCSNames[kRCCrossAng]);      // ---- horisontal angle
246   FillScalarRecord(fRCAngV,fgkDCSNames[kRCVang] );          // ---- vertical angle
247   //
248   FillScalarRecord(fBPTXdTB1B2,    fgkDCSNames[kBPTXdeltaTB1B2]);
249   FillScalarRecord(fBPTXdTRMSB1B2, fgkDCSNames[kBPTXdeltaTRMSB1B2]);
250   FillScalarRecord(fLumiAlice,     fgkDCSNames[kALILumiTotalInst]);
251   FillScalarRecord(fLumiAliceStB,  fgkDCSNames[kALILumiTotalDeliveredStabBeam]);  
252   FillBCLuminosities(fLumiAliceBbB,fgkDCSNames[kALILumiBunchInst],0,0);  
253   //
254   return kTRUE;
255 }
256
257 //___________________________________________________________________
258 TObjArray* AliLHCData::GetDCSEntry(const char* key,int &entry,int &last,double tmin,double tmax) const
259 {
260   // extract array from the DCS map or file and find the first entry within the time limits
261   entry = -1;
262   last = -2;
263   TObjArray* arr;
264   if (fkMap2Process) arr = (TObjArray*)fkMap2Process->GetValue(key);
265   else if (fkFile2Process) {
266     AliLHCReader rd;
267     arr = rd.ReadSingleLHCDP(fkFile2Process,key);
268   }
269   else {
270     AliError("Neither DCS map nor DCS filename are set");
271     return 0;  
272   }
273   //
274   if (!arr || !arr->GetEntriesFast()) { 
275     AliWarning(Form("No data for %s",key)); 
276     if (fkMap2Process) delete arr; // created on demand
277     return 0;
278   }
279   int ntot = arr->GetEntriesFast();
280   //
281   // search 1st entry before or at tmin
282   AliDCSArray* ent = 0;
283   Bool_t found = kFALSE;
284   for (entry=0;entry<ntot;entry++) {
285     ent = (AliDCSArray*)arr->At(entry);
286     if (ent->GetTimeStamp()>=tmin-kMarginSOR && ent->GetTimeStamp()<=tmax+kMarginEOR) {
287       found = kTRUE;
288       if (ent->GetTimeStamp()>tmin) break;
289     }
290   }
291   if (!found) {
292     entry = -1;
293     TString str;
294     str += AliLHCDipValF::TimeAsString(tmin);
295     str += " : ";
296     str += AliLHCDipValF::TimeAsString(tmax);
297     AliWarning(Form("All entries for %s are outside the requested range:\n%s",key,str.Data()));
298     if (fkMap2Process) delete arr; // created on demand
299     return 0;
300   }
301   if (entry>0) entry--;
302   //
303   // search last entry at or after tmin
304   ent = 0;
305   for (last=entry;last<ntot;last++) {
306     ent = (AliDCSArray*)arr->At(last);
307     if (ent->GetTimeStamp()>tmax) break;
308   }
309   if (last == ntot) last--;
310   else if (ent->GetTimeStamp()>tmax+kMarginEOR) last--;
311   //
312   return arr;
313 }
314
315 //___________________________________________________________________
316 Int_t AliLHCData::TimeDifference(double v1,double v2,double tol) const
317 {
318   // return 0 if the times are the same within the tolerance
319   //        1 if v1>v2
320   //       -1 if v1<v2
321   v1-=v2;
322   if (v1>tol)  return  1;
323   if (v1<-tol) return -1;
324   return 0;
325 }
326
327 //___________________________________________________________________
328 Bool_t AliLHCData::GoodPairID(int beam) const
329 {
330   // check for correct beam identifier 
331   if (beam>kBeam2||beam<0) {AliError(Form("BeamID can be 0 or 1, %d requested",beam)); return kFALSE;}
332   return kTRUE;
333 }
334
335 //___________________________________________________________________
336 AliLHCDipValI* AliLHCData::GetBunchConfigMeasured(int beam,double tstamp) const
337 {
338   // find measured bunch configuration valid for given tstamp
339   if (!GoodPairID(beam)) return 0;
340   return (AliLHCDipValI*)FindRecValidFor(fBunchConfMeas[beam][kStart],fBunchConfMeas[beam][kNStor],tstamp);
341 }
342
343 //___________________________________________________________________
344 AliLHCDipValI* AliLHCData::GetBunchConfigDeclared(int beam,double tstamp) const
345 {
346   // find declared bunch configuration valid for given tstamp
347   if (!GoodPairID(beam)) return 0;
348   return (AliLHCDipValI*)FindRecValidFor(fBunchConfDecl[beam][kStart],fBunchConfDecl[beam][kNStor],tstamp);
349 }
350
351 //___________________________________________________________________
352 TObject* AliLHCData::FindRecValidFor(int start,int nrec, double tstamp) const
353 {
354   // find record within this limits valid for given tstamp (i.e. the last one before or equal to tstamp)
355   AliLHCDipValI *prevObj = 0;
356   for (int i=0;i<nrec;i++) {
357     AliLHCDipValI* curObj = (AliLHCDipValI*)fData[start+i];
358     if (TimeDifference(tstamp,curObj->GetTimeStamp())<=0) break;
359     prevObj = curObj;
360   }
361   if (!prevObj && nrec>0) prevObj = (AliLHCDipValI*)fData[start]; // if no exact match, return the 1st one
362   return prevObj;
363 }
364
365 //___________________________________________________________________
366 Int_t AliLHCData::FillScalarRecord(int refs[2], const char* rec, const char* recErr, Double_t maxAbsVal)
367 {
368   // fill record for scalar value, optionally accompanied by measurement error 
369   //
370   AliInfo(Form("Acquiring record: %s",rec));
371   //
372   TObjArray *arr=0,*arrE=0;
373   Int_t iLast=0,iLastE=0,iFirst=0,iFirstE=0;
374   //
375   refs[kStart] = fData.GetEntriesFast();
376   refs[kNStor] = 0;
377   //
378   if ( !(arr=GetDCSEntry(rec,iFirst,iLast,fTMin,fTMax)) ) return -1;
379   //
380   int dim = 1;
381   if (recErr) {
382     arrE = GetDCSEntry(recErr,iFirstE,iLastE,fTMin,fTMax);
383     dim += 1;
384   }
385   //
386   // Bool_t last = kFALSE;
387   while (iFirst<=iLast) {
388     AliDCSArray *dcsVal = (AliDCSArray*) arr->At(iFirst++);
389     double tstamp = dcsVal->GetTimeStamp();
390     //
391     AliLHCDipValF* curValD = new AliLHCDipValF(dim,tstamp);  // start new period
392     double vcheck = ExtractDouble(dcsVal,0);     // value
393     if (TMath::Abs(vcheck) > maxAbsVal) {
394       AliError(Form("ANOMALOUS VALUE %e for slot %d of %s: exceeds %e",vcheck, 0, rec, maxAbsVal));
395       vcheck = 0.;
396     }    
397     (*curValD)[0] = vcheck;
398     //
399     if (recErr) {
400       double errVal = -1;
401       while (iFirstE<=iLastE) {       // try to find corresponding error
402         AliDCSArray *dcsValE = (AliDCSArray*) arrE->At(iFirstE);
403         double tstampE = dcsValE->GetTimeStamp();
404         int tdif = TimeDifference(tstamp,tstampE);
405         if (!tdif) { // error matches to value
406           errVal = ExtractDouble(dcsVal,0);     // value
407           if (TMath::Abs(errVal) > maxAbsVal) {
408             AliError(Form("ANOMALOUS VALUE %e for slot %d of %s: exceeds %e",errVal, 0, recErr, maxAbsVal));
409             errVal = 0.;
410           }
411           iFirstE++; 
412           break;
413         }
414         else if (tdif>0) iFirstE++; // error time lags behind, read the next one
415         else break;                 // error time is ahead of value, no error associated
416       }
417       (*curValD)[dim-1] = errVal;   // error
418       curValD->SetLastSpecial();    // lable the last entry as an error
419     }
420     //
421     fData.Add(curValD);
422     refs[kNStor]++;
423     // if (last) break;
424   }
425   //
426   if (fkFile2Process) {
427     delete arr;
428     delete arrE;
429   }
430   return refs[kNStor];
431 }
432
433 //___________________________________________________________________
434 Int_t AliLHCData::FillBunchConfig(int refs[2],const char* rec)
435 {
436   // fill record for bunch configuration
437   //
438   AliInfo(Form("Acquiring record: %s",rec));
439   TObjArray *arr;
440   Int_t iLast,iFirst;
441   //
442   refs[kStart] = fData.GetEntriesFast();
443   refs[kNStor] = 0;
444   //
445   if ( !(arr=GetDCSEntry(rec,iFirst,iLast,fTMin,fTMax)) ) return -1;
446   //
447   AliLHCDipValI* prevRecI=0;
448   //  
449   while (iFirst<=iLast) {
450     AliDCSArray *dcsVal = (AliDCSArray*) arr->At(iFirst++);
451     double tstamp = dcsVal->GetTimeStamp();
452     //
453     int bucket=0, nbunch=0, ndiff=0;
454     int nSlots = dcsVal->GetNEntries();     // count number of actual bunches (non-zeros)
455     int* dcsArr = dcsVal->GetInt();
456     while(nbunch<nSlots && (bucket=dcsArr[nbunch])) {
457       if (prevRecI && prevRecI->GetSize()>nbunch && bucket!=prevRecI->GetValue(nbunch)) ndiff++;
458       nbunch++;
459     }
460     if (!nbunch) AliWarning(Form("%s record is present but empty: no beam?",rec));
461     if (prevRecI && !ndiff && nbunch==prevRecI->GetSize()) continue; // record similar to previous one
462     AliLHCDipValI* curValI = new AliLHCDipValI(nbunch,tstamp);      
463     for (int i=nbunch;i--;) (*curValI)[i] = dcsArr[i];
464     fData.Add(curValI);
465     refs[kNStor]++;
466     prevRecI = curValI;
467   }
468   //
469   if (fkFile2Process) delete arr;
470   return refs[kNStor];
471 }
472  
473 //___________________________________________________________________
474 Int_t AliLHCData::FillAcqMode(int refs[2],const char* rec)
475 {
476   // fill acquisition mode
477   //
478   AliInfo(Form("Acquiring record: %s",rec));
479   TObjArray *arr;
480   Int_t iLast,iFirst;
481   //
482   refs[kStart] = fData.GetEntriesFast();
483   refs[kNStor] = 0;
484   //
485   if ( !(arr=GetDCSEntry(rec,iFirst,iLast,fTMin,fTMax)) ) return -1;
486   //
487   AliLHCDipValI* prevRecI=0;
488   while (iFirst<=iLast) {
489     AliDCSArray *dcsVal = (AliDCSArray*) arr->At(iFirst++);
490     double tstamp = dcsVal->GetTimeStamp();
491     //
492     int nSlots = dcsVal->GetNEntries();
493     if (nSlots<1) continue;
494     int acqMode = dcsVal->GetInt()[0];
495     if (prevRecI && (*prevRecI)[0] == acqMode) continue; // record similar to previous one
496     AliLHCDipValI* curValI = new AliLHCDipValI(1,tstamp);      
497     (*curValI)[0] = acqMode;
498     fData.Add(curValI);
499     refs[kNStor]++;
500     prevRecI = curValI;
501   }
502   //
503   if (fkFile2Process) delete arr;
504   return refs[kNStor];
505 }
506  
507 //___________________________________________________________________
508 Int_t AliLHCData::FillStringRecord(int refs[2],const char* rec)
509 {
510   // fill record with string value
511   //
512   AliInfo(Form("Acquiring record: %s",rec));
513   TString prevRec;
514   TObjArray *arr;
515   Int_t iLast,iFirst;
516   //
517   refs[kStart] = fData.GetEntriesFast();
518   refs[kNStor] = 0;
519   //
520   if ( !(arr=GetDCSEntry(rec,iFirst,iLast,fTMin,fTMax)) ) return -1;
521   //
522   while (iFirst<=iLast) {
523     AliDCSArray *dcsVal = (AliDCSArray*) arr->At(iFirst++);
524     double tstamp = dcsVal->GetTimeStamp();
525     //
526     TString &str = ExtractString(dcsVal);
527     if (!prevRec.IsNull()) {if (str == prevRec) continue;} // skip similar record
528     else prevRec = str;
529     //
530     AliLHCDipValC* curValS = new AliLHCDipValC(1,tstamp);      
531     curValS->SetValues(str.Data(),str.Length()+1);
532     //
533     fData.Add(curValS);
534     refs[kNStor]++;
535   }
536   if (fkFile2Process) delete arr;
537   return refs[kNStor];
538 }
539
540 //___________________________________________________________________
541 Int_t AliLHCData::FillBunchInfo(int refs[2],const char* rec, int ibm, Bool_t inRealSlots, Double_t maxAbsVal)
542 {
543   // fill bunch properties for beam ibm
544   // if inRealSlots = true, then the value is taken from bunchRFbucket/10, otherwise, the value 
545   // for the i-th bunch is taken from the i-th element
546   //
547   AliInfo(Form("Acquiring record: %s",rec));
548   TObjArray *arr;
549   Int_t iLast,iFirst;
550   //
551   refs[kStart] = fData.GetEntriesFast();
552   refs[kNStor] = 0;
553   //
554   if ( !(arr=GetDCSEntry(rec,iFirst,iLast,fTMin,fTMax)) ) return -1;
555   //
556   while (iFirst<=iLast) {
557     AliDCSArray *dcsVal = (AliDCSArray*) arr->At(iFirst++);
558     double tstamp = dcsVal->GetTimeStamp();
559     //
560     AliLHCDipValI *bconf = GetBunchConfigMeasured(ibm,tstamp);
561     if (!bconf) {
562       AliWarning(Form("Mearured bunch configuration for beam %d at t=%.1f is not available, trying declared one",ibm+1,tstamp));
563       bconf = GetBunchConfigDeclared(ibm,tstamp);
564     }
565     if (!bconf) {
566       AliWarning(Form("Declared bunch configuration for beam %d at t=%.1f is not available, skip this record",ibm+1,tstamp));
567       return -1;
568     }
569     int nSlots = dcsVal->GetNEntries();     // count number of actual bunches (non-zeros)
570     int nbunch = bconf->GetSize();
571     if (nbunch>nSlots) {
572       AliWarning(Form("More N bunches than slots in %s at time %.1f",rec,tstamp));
573       continue;
574     }
575     double* dcsArr = dcsVal->GetDouble();
576     AliLHCDipValF* curValD = new AliLHCDipValF(nbunch,tstamp);
577     for (int i=nbunch;i--;) {
578       int ind = inRealSlots ? (*bconf)[i]/10 : i;
579       if (ind>nSlots) {
580         AliError(Form("Bunch %d refers to wrong slot %d, set to -1",i,(*bconf)[i]));
581         (*curValD)[i] = -1;
582       }
583       else {
584         double vcheck = dcsArr[ind];
585         if (TMath::Abs(vcheck) > maxAbsVal) {
586           AliError(Form("ANOMALOUS VALUE %e for slot %d of %s: exceeds %e",vcheck, ind, rec, maxAbsVal));
587           vcheck = 0.;
588         }
589         (*curValD)[i] = vcheck;
590       }
591     }
592     fData.Add(curValD);
593     refs[kNStor]++;
594   }
595   if (fkFile2Process) delete arr;
596   return refs[kNStor];
597   //
598 }
599  
600 //___________________________________________________________________
601 Int_t AliLHCData::FillBCLuminosities(int refs[2],const char* rec, const char* recErr, int useBeam, Double_t maxAbsVal)
602 {
603   // fill luminosities per bunch crossing
604   //
605   AliInfo(Form("Acquiring record: %s",rec));
606   TObjArray *arr,*arrE=0;
607   Int_t iLast=0,iLastE=0,iFirst=0,iFirstE=0;
608   //
609   refs[kStart] = fData.GetEntriesFast();
610   refs[kNStor] = 0;
611   //
612   if ( !(arr=GetDCSEntry(rec,iFirst,iLast,fTMin,fTMax)) ) return -1;
613   //
614   while (iFirst<=iLast) {
615     AliDCSArray *dcsVal = (AliDCSArray*) arr->At(iFirst++);
616     double tstamp = dcsVal->GetTimeStamp();
617     //
618     AliLHCDipValI *bconf;
619     bconf = GetBunchConfigMeasured(useBeam,tstamp);  // luminosities are stored according to beam bunches
620     if (!bconf) {
621       AliWarning(Form("Mearured bunch configuration for beam%d at t=%.1f is not available, trying declared one",useBeam,tstamp));
622       bconf = GetBunchConfigDeclared(useBeam,tstamp);
623     }
624     if (!bconf) {
625       AliWarning(Form("Declared bunch configuration for beam%i at t=%.1f is not available, skip this record",useBeam,tstamp));
626       return -1;
627     }
628     int nSlots = dcsVal->GetNEntries();     // count number of actual bunches (non-zeros)
629     int nbunch = bconf->GetSize();
630     double* dcsArr = dcsVal->GetDouble();
631     //
632     if (nbunch>nSlots) {
633       AliWarning(Form("More N bunches than slots in %s at time %.1f",rec,tstamp));
634       continue;
635     }
636     int dim = 0;
637     if (!bconf->IsProcessed1()) {
638       AliWarning(Form("Bunch conf. for beam%d has no marked interacting bunches, store all luminosity for all filled bunches",useBeam));
639       dim = nbunch;
640     }
641     else { // count number of interacting bunches
642       for (int i=nbunch;i--;) if ((*bconf)[i]<0) dim++;
643     }
644     //
645     if (recErr) {
646       arrE=GetDCSEntry(recErr,iFirstE,iLastE,fTMin,fTMax);
647       dim += 1;
648     }
649     AliLHCDipValF* curValD = new AliLHCDipValF(dim,tstamp);
650     int cnt = 0;
651     for (int i=0;i<nbunch;i++) {
652       int slot = (*bconf)[i];
653       if (bconf->IsProcessed1() && slot>0) continue;
654       //
655       int ind = TMath::Abs(slot)/10;
656       if (ind>nSlots) {
657         AliError(Form("Bunch %d refers to wrong slot %d, set to -1",cnt,slot));
658         (*curValD)[cnt] = -1;
659       }
660       else {
661         double vcheck = dcsArr[ind];
662         if (TMath::Abs(vcheck) > maxAbsVal) {
663           AliError(Form("ANOMALOUS VALUE %e for slot %d of %s: exceeds %e",vcheck, ind, rec, maxAbsVal));
664           vcheck = 0.;
665         }
666         (*curValD)[i] = vcheck;
667       }
668       cnt++;
669     }
670     //
671     if (recErr) {
672       double errVal = -1;
673       while (iFirstE<=iLastE) {       // try to find corresponding error
674         AliDCSArray *dcsValE = (AliDCSArray*) arrE->At(iFirstE);
675         double tstamp1 = dcsValE->GetTimeStamp();
676         int tdif = TimeDifference(tstamp,tstamp1);
677         if (!tdif) { // error matches to value
678           errVal = dcsValE->GetDouble()[0];
679           if (TMath::Abs(errVal) > maxAbsVal) {
680             AliError(Form("ANOMALOUS VALUE %e for slot %d of %s: exceeds %e",errVal,0, rec, maxAbsVal));
681             errVal = 0.;
682           }       
683           iFirstE++; 
684           break;
685         }
686         else if (tdif>0) iFirstE++; // error time lags behind, read the next one
687         else break;                 // error time is ahead of value, no error associated
688       }
689       (*curValD)[dim-1] = errVal;   // error
690       curValD->SetLastSpecial();    // lable the last entry as an error
691     }
692     //
693     fData.Add(curValD);
694     refs[kNStor]++;
695   }
696   if (fkFile2Process) {
697     delete arr;
698     delete arrE;
699   }
700   return refs[kNStor];
701   //
702 }
703
704 //___________________________________________________________________
705 Int_t AliLHCData::ExtractInt(AliDCSArray* dcsArray,Int_t el) const
706 {
707   // extract integer from the dcsArray
708   int val = -1;
709   //
710   int sz = dcsArray->GetNEntries();
711   if (sz<=el) return val;
712   //
713   if (dcsArray->GetType()==AliDCSArray::kInt)  val = dcsArray->GetInt(el);
714   else if (dcsArray->GetType()==AliDCSArray::kString) {
715     TObjString *stro = dcsArray->GetStringArray(el);
716     if (stro) val = stro->GetString().Atoi();
717     else AliError(Form("DCSArray TObjString for element %d is missing",el));
718   }
719   else if (dcsArray->GetType()==AliDCSArray::kUInt) val = dcsArray->GetUInt(el);
720   else AliError(Form("Integer requested from DCSArray of type %d",dcsArray->GetType()));
721   return val;
722 }
723
724 //___________________________________________________________________
725 Double_t AliLHCData::ExtractDouble(AliDCSArray* dcsArray,Int_t el) const
726 {
727   // extract double from the dcsArray
728   double val = 0;
729   //
730   int sz = dcsArray->GetNEntries();
731   if (sz<=el) return val;
732   //
733   if      (dcsArray->GetType()==AliDCSArray::kDouble) val = dcsArray->GetDouble(el);
734   else if (dcsArray->GetType()==AliDCSArray::kFloat)  val = dcsArray->GetFloat(el);
735   else if (dcsArray->GetType()==AliDCSArray::kString) {
736     TObjString *stro = dcsArray->GetStringArray(el);
737     if (stro) val = stro->GetString().Atof();
738     else AliError(Form("DCSArray has TObjString for element %d is missing",el));
739   }
740   else if (dcsArray->GetType()==AliDCSArray::kChar)   val = dcsArray->GetChar(el);
741   else if (dcsArray->GetType()==AliDCSArray::kInt)    val = dcsArray->GetInt(el);
742   else if (dcsArray->GetType()==AliDCSArray::kUInt)   val = dcsArray->GetUInt(el);
743   else     AliError(Form("Double requested from DCSArray of type %d",dcsArray->GetType()));
744   return val;
745 }
746
747 //___________________________________________________________________
748 TString& AliLHCData::ExtractString(AliDCSArray* dcsArray) const
749 {
750   // extract string from the dcsArray
751   static TString str;
752   str = "";
753   //
754   int sz = dcsArray->GetNEntries();
755   if (dcsArray->GetType()!=AliDCSArray::kString)  {
756     AliError(Form("String requested from DCSArray of type %d",dcsArray->GetType()));
757     return str;
758   }
759   //
760   for (int i=0;i<sz;i++) {
761     str += dcsArray->GetStringArray(i)->GetString();
762     if (i<sz-1) str += " ";
763   }
764   return str;
765 }
766
767 //___________________________________________________________________
768 void AliLHCData::Print(const Option_t* opt) const
769 {
770   // print full info
771   TString opts = opt;
772   opts.ToLower();
773   Bool_t utcTime = opts.Contains("loc") ? kFALSE:kTRUE;
774   //
775   Bool_t includeMissing = opts.Contains("m");
776   if (!includeMissing) printf("Missing records are skept, use Print(\"m\") to print missing record names\n");
777   else                 printf("Missing records are printed, remove \"m\" from Print options to skip them\n");
778   Bool_t full = kTRUE;
779   if (!opts.Contains("f")) {
780     printf("Use Print(\"f\") to print full info\n");
781     printf("Printing short info:\n<RecordType>(number of records): <TimeStamp, value> for 1st record only\n");
782     full = kFALSE;
783   }
784   TString sdtmn = AliLHCDipValI::TimeAsString(fTMin,utcTime);
785   TString sdtmx = AliLHCDipValI::TimeAsString(fTMax,utcTime);
786   printf("Fill#%6d Validity: %s - %s (%s)\n",fFillNumber,sdtmn.Data(),sdtmx.Data(),utcTime ? "UTC":"LOC");
787   //
788   printf("********** SETTINGS FROM RUN CONTROL **********\n");
789   //
790   if (fRCInjScheme[kNStor] || includeMissing) {
791     printf("* %-38s","Injection Scheme");
792     PrintAux(full,fRCInjScheme,opts);
793   }
794   //
795   if (fRCBeta[kNStor] || includeMissing) {
796     printf("* %-38s","Beta Star");
797     PrintAux(full,fRCBeta,opts);
798   }
799   //
800   if (fRCAngH[kNStor] || includeMissing) {
801     printf("* %-38s","Horisontal Crossing Angle");
802     PrintAux(full,fRCAngH,opts);
803   }
804   //
805   if (fRCAngV[kNStor] || includeMissing) {
806     printf("* %-38s","Vertical   Crossing Angle");
807     PrintAux(full,fRCAngV,opts);
808   }
809   //
810   for (int ib=0;ib<2;ib++) {
811     if (fBunchConfDecl[ib][kNStor] || includeMissing) {
812       printf("* Beam%d filling  [- interacts at IR2!]  ",ib+1);
813       PrintAux(full,fBunchConfDecl[ib],opts);
814     }
815   }
816   //
817   printf("\n**********       MEASURED DATA       **********\n");
818   //
819   for (int ib=0;ib<2;ib++) {
820     if (fBunchConfMeas[ib][kNStor] || includeMissing) {
821       printf("* Beam%d filling  [- interacts at IR2!]  ",ib+1);
822       PrintAux(full,fBunchConfMeas[ib],opts);
823     }
824   } 
825   //
826   for (int ib=0;ib<2;ib++) {
827     if (fIntensTotal[ib][kNStor] || includeMissing) {
828       printf("* Beam%d total intensity                 ",ib+1);
829       PrintAux(full,fIntensTotal[ib],opts);
830     }
831   } 
832   //
833   for (int ib=0;ib<2;ib++) {
834     if (fIntensTotalAv[ib][kNStor] || includeMissing) {
835       printf("* Beam%d total intensity (bunch average) ",ib+1);
836       PrintAux(full,fIntensTotalAv[ib],opts);
837     }
838   } 
839   //
840   for (int ib=0;ib<2;ib++) {
841     if (fIntensPerBunch[ib][kNStor] || includeMissing) {
842       printf("* Beam%d intensity per bunch             ",ib+1);
843       PrintAux(full,fIntensPerBunch[ib],opts);
844     }
845   }
846   //
847   for (int ib=0;ib<2;ib++) {
848     if (fBunchLengths[ib][kNStor] || includeMissing) {
849       printf("* Beam%d bunch lengths                   ",ib+1);
850       PrintAux(full,fBunchLengths[ib],opts);
851     }
852   } 
853   //
854   for (int ib=0;ib<2;ib++) {
855     if (fEmittanceH[ib][kNStor] || includeMissing) {
856       printf("* Beam%d Horisontal emittance            ",ib+1);
857       PrintAux(full,fEmittanceH[ib],opts);
858     }
859   }
860   //
861   for (int ib=0;ib<2;ib++) {
862     if (fEmittanceV[ib][kNStor] || includeMissing) {
863       printf("* Beam%d Vertical emittance              ",ib+1);
864       PrintAux(full,fEmittanceV[ib],opts);
865     }
866   }
867   //
868   for (int ib=0;ib<2;ib++) {
869     if (fBeamSigmaH[ib][kNStor] || includeMissing) {
870       printf("* Beam%d Horisontal sigma                ",ib+1);
871       PrintAux(full,fBeamSigmaH[ib],opts);
872     }
873   }
874   //
875   for (int ib=0;ib<2;ib++) {
876     if (fBeamSigmaV[ib][kNStor] || includeMissing) {
877       printf("* Beam%d Vertical sigma                  ",ib+1);
878       PrintAux(full,fBeamSigmaV[ib],opts);
879     }
880   }
881   //
882   for (int lr=0;lr<2;lr++) {
883     if (fLuminTotal[lr][kNStor] || includeMissing) {
884       printf("* Total luminosity from BRANB_4%c2       ",lr ? 'R':'L');
885       PrintAux(full,fLuminTotal[lr],opts);
886     }
887   } 
888   //
889   for (int lr=0;lr<2;lr++) {
890     if (fLuminAcqMode[lr][kNStor] || includeMissing) {
891       printf("* Luminosity acq.mode, BRANB_4%c2        ",lr ? 'R':'L');
892       PrintAux(full,fLuminAcqMode[lr],opts+"bit");
893     }
894   } 
895   //
896   for (int lr=0;lr<2;lr++) {
897     if (fLuminPerBC[lr][kNStor] || includeMissing) {
898       printf("* Luminosity per BC from BRANB_4%c2      ",lr ? 'R':'L');
899       PrintAux(full,fLuminPerBC[lr],opts);
900     }
901   }
902   //
903   for (int lr=0;lr<2;lr++) {
904     if (fCrossAngle[lr][kNStor] || includeMissing) {
905       printf("* Crossing angle, side %c                ",lr ? 'R':'L');
906       PrintAux(full,fCrossAngle[lr],opts);
907     }
908   }
909   //
910   for (int coll=0;coll<kNCollimators;coll++)
911     for (int jaw=0;jaw<kNJaws;jaw++) {
912       if (fCollimators[coll][jaw][kNStor] || includeMissing) {
913         printf("* Collimator %10s:%16s",fgkDCSColNames[coll],fgkDCSColJaws[jaw]);
914         PrintAux(full,fCollimators[coll][jaw],opts);
915       }
916     }
917   //
918   printf("\n**********    ALICE MEASURED DATA    **********\n");
919   //
920   if (fLumiAlice[kNStor] || includeMissing) {
921     printf("* %-38s","Alice luminosity total");
922     PrintAux(full,fLumiAlice,opts);
923   }
924   //
925   if (fLumiAliceStB[kNStor] || includeMissing) {
926     printf("* %-38s","Alice luminosity delivered stable beam");
927     PrintAux(full,fLumiAliceStB,opts);
928   }
929   //
930   if (fLumiAliceBbB[kNStor] || includeMissing) {
931     printf("* %-38s","Alice luminosity B-by-B, stable beam");
932     PrintAux(full,fLumiAliceBbB,opts);
933   }
934   //
935   for (int ib=0;ib<3;ib++) {
936     if (fBckgAlice[ib][kNStor] || includeMissing) {
937       printf("* Alice background%d                     ",ib+1);
938       PrintAux(full,fBckgAlice[ib],opts);
939     }
940   }
941   //
942   if (fBPTXdTB1B2[kNStor] || includeMissing) {
943     printf("* %-38s","BPTX DeltaT Beam1 Beam2");
944     PrintAux(full,fBPTXdTB1B2,opts);
945   }
946   //
947   if (fBPTXdTRMSB1B2[kNStor] || includeMissing) {
948     printf("* %-38s","BPTX DeltaT RMS Beam1 Beam2");
949     PrintAux(full,fBPTXdTRMSB1B2,opts);
950   }
951   //
952   for (int ib=0;ib<2;ib++) {
953     if (fBPTXPhase[ib][kNStor] || includeMissing) {
954       printf("* BPTX Phase Beam%d                      ",ib+1);
955       PrintAux(full,fBPTXPhase[ib],opts);
956     }
957   }
958   //
959   for (int ib=0;ib<2;ib++) {
960     if (fBPTXPhaseRMS[ib][kNStor] || includeMissing) {
961       printf("* BPTX Phase RMS Beam%d                  ",ib+1);
962       PrintAux(full,fBPTXPhaseRMS[ib],opts);
963     }
964   }
965   //
966   for (int ib=0;ib<2;ib++) {
967     if (fBPTXPhaseShift[ib][kNStor] || includeMissing) {
968       printf("* BPTX Phase Shift Beam%d                ",ib+1);
969       PrintAux(full,fBPTXPhaseShift[ib],opts);
970     }
971   }
972   //
973 }
974
975 //___________________________________________________________________
976 void AliLHCData::PrintAux(Bool_t full, const Int_t refs[2], const Option_t *opt) const
977 {
978   // aux method to print the reocrds of the same type
979   int nrec = refs[kNStor];
980   if (nrec<1) {
981     printf(": N/A\n"); 
982     return;
983   }
984   printf(": (%3d):\t",nrec); // number of records
985   if (!full) nrec = 1;
986   int sz = ((AliLHCDipValI*)fData[refs[kStart]])->GetSizeTotal(); // dimension of the record
987   Bool_t isStr = ((AliLHCDipValI*)fData[refs[kStart]])->IsTypeC();
988   if ((!isStr && sz>2) || nrec>1) printf("\n"); // long record, open new line
989   for (int i=0;i<nrec;i++) fData[refs[kStart]+i]->Print(opt);
990   //
991 }
992
993 //___________________________________________________________________
994 void AliLHCData::Clear(const Option_t *)
995 {
996   // clear all info
997   fData.Delete();
998   fFillNumber = 0;
999   fTMin = 0;
1000   fTMax = 1e10;
1001   fkFile2Process = 0;
1002   fkMap2Process  = 0;
1003   //
1004   for (int i=2;i--;) {
1005     fRCInjScheme[i] = 0;
1006     fRCBeta[i] = 0;
1007     fRCAngH[i] = 0;
1008     fRCAngV[i] = 0;
1009     fLumiAlice[i] = 0;
1010     fLumiAliceStB[i] = 0;
1011     fLumiAliceBbB[i] = 0;
1012     for (int ibg=kNBGs;ibg--;) fBckgAlice[ibg][i] = 0;
1013     fBPTXdTB1B2[i] = 0;
1014     fBPTXdTRMSB1B2[i] = 0;
1015     //
1016     for (int icl=kNCollimators;icl--;) for (int jaw=kNJaws;jaw--;) fCollimators[icl][jaw][i]=0;
1017     //
1018     for (int j=2;j--;) {
1019       fBPTXPhase[j][i] = 0;
1020       fBPTXPhaseRMS[j][i] = 0;
1021       fBPTXPhaseShift[j][i] = 0;
1022       //
1023       fBunchConfDecl[j][i] = 0;
1024       fBunchConfMeas[j][i] = 0;
1025       fBunchLengths[j][i] = 0;
1026       fIntensTotal[j][i] = 0;
1027       fIntensTotalAv[j][i] = 0;
1028       fIntensPerBunch[j][i] = 0;      
1029       fCrossAngle[j][i] = 0;
1030       fEmittanceH[j][i] = 0;
1031       fEmittanceV[j][i] = 0;
1032       fBeamSigmaH[j][i] = 0;
1033       fBeamSigmaV[j][i] = 0;
1034       fLuminTotal[j][i] = 0;
1035       fLuminPerBC[j][i] = 0;
1036       fLuminAcqMode[j][i] = 0;
1037     }
1038   }
1039 }
1040
1041 //___________________________________________________________________
1042 Int_t AliLHCData::GetNInteractingBunchesMeasured(int i) const
1043 {
1044   // get number of interacting bunches at IR2
1045   AliLHCDipValI* rec = GetBunchConfigMeasured(kBeam1,i);
1046   if (!rec) {AliInfo(Form("No record %d found",i)); return -1;}
1047   if (!rec->IsProcessed1()) { AliInfo("Interacting bunches were not marked"); return -1;}
1048   int n = 0;
1049   for (int j=rec->GetSize();j--;) if ( (*rec)[j]<0 ) n++;
1050   return n;
1051 }
1052
1053 //___________________________________________________________________
1054 Int_t AliLHCData::GetNInteractingBunchesDeclared(int i) const
1055 {
1056   // get number of interacting bunches at IR2
1057   AliLHCDipValI* rec = GetBunchConfigMeasured(kBeam1,i);
1058   if (!rec) {AliInfo(Form("No record %d found",i)); return -1;}
1059   if (!rec->IsProcessed1()) { AliInfo("Interacting bunches were not marked"); return -1; }
1060   int n = 0;
1061   for (int j=rec->GetSize();j--;) if ( (*rec)[j]<0 ) n++;
1062   return n;
1063 }
1064
1065 //___________________________________________________________________
1066 Int_t AliLHCData::IsPilotPresent(int i) const
1067 {
1068   // check in the filling scheme is the pilot bunch is present
1069   AliLHCDipValC* rec = GetInjectionScheme();
1070   if (!rec) {AliInfo(Form("No record %d found",i)); return -1;}
1071   TString scheme = rec->GetValues();
1072   return scheme.Contains("wp",TString::kIgnoreCase);
1073 }
1074
1075 //___________________________________________________________________
1076 void AliLHCData::FlagInteractingBunches(const Int_t beam1[2],const Int_t beam2[2])
1077 {
1078   // assign - sign to interacting bunches
1079   //
1080   for (int ib1=0;ib1<beam1[kNStor];ib1++) {
1081     AliLHCDipValI *bm1 = (AliLHCDipValI*)fData[ beam1[kStart] + ib1];
1082     if (!bm1) continue;
1083     AliLHCDipValI *bm2 = (AliLHCDipValI*)FindRecValidFor(beam2[kStart],beam2[kNStor], bm1->GetTimeStamp());
1084     if (!bm2) continue;
1085     //
1086     int nb1 = bm1->GetSize();
1087     int nb2 = bm2->GetSize();
1088     int i1,i2;
1089     for (i1=0;i1<nb1;i1++) {
1090       int bunch2=-1, bunch1 = TMath::Abs((*bm1)[i1]);
1091       int slot2 =-1, slot1  = GetBCId(bunch1,0);
1092       for (i2=0;i2<nb2;i2++) {
1093         bunch2 = TMath::Abs((*bm2)[i2]);
1094         slot2 = GetBCId(bunch2,1);
1095         if (slot1==slot2) break;
1096       }
1097       if (slot1!=slot2) continue;
1098       (*bm1)[i1] = -bunch1;
1099       (*bm2)[i2] = -bunch2;
1100       bm1->SetProcessed1();
1101       bm2->SetProcessed1();
1102     }
1103   }
1104 }
1105
1106 //___________________________________________________________________
1107 Int_t AliLHCData::GetMeanIntensity(int beamID, Double_t &colliding, Double_t &noncolliding, const TObjArray* bcmasks) const
1108 {
1109   // get average intensity for all, colliding and non-colliding bunches
1110   // on success returns number of intensity records used (1 per ~10 min)
1111   // If triggered BC masks are provided, calculation is done for Triggered BC only
1112   colliding = noncolliding = -1.;
1113   if (beamID<0||beamID>1) {
1114     AliError(Form("BeamID must be either 0 or 1, %d requested",beamID));
1115     return -10;
1116   }
1117   //
1118   AliTriggerBCMask *bcMaskBoth=0,*bcMaskSingle=0;
1119   int nbcm = 0;
1120   if (bcmasks && (nbcm=bcmasks->GetEntries())) {
1121     if (nbcm>1) bcMaskBoth = (AliTriggerBCMask*)bcmasks->At(1);
1122     if      (nbcm>0 && beamID==kBeam1) bcMaskSingle = (AliTriggerBCMask*)bcmasks->At(0);
1123     else if (nbcm>2 && beamID==kBeam2) bcMaskSingle = (AliTriggerBCMask*)bcmasks->At(2);
1124     //
1125     if (!bcMaskSingle) AliError(Form("Only triggered BSs are requested but %c mask is not provided",beamID ? 'C':'A'));
1126     if (!bcMaskBoth)   AliError("Only triggered BSs are requested but B mask is not provided");
1127   }
1128   else {
1129     AliWarning("No BC masks are provided");
1130   }
1131   //
1132   int nrec = GetNIntensityPerBunch(beamID);
1133   if (nrec<1) return -1;
1134   AliLHCDipValI *conf = GetBunchConfigMeasured(beamID);
1135   if (!conf) conf = GetBunchConfigDeclared(beamID);
1136   if (!conf) return -2;
1137   int nb = conf->GetSize();
1138   //
1139   for (int irec=0;irec<nrec;irec++) {
1140     //
1141     AliLHCDipValD* rIntD = 0;
1142     AliLHCDipValF* rIntF = GetIntensityPerBunch(beamID,irec);
1143     // for BWD compatibility of some periods
1144     if (rIntF->IsA() == AliLHCDipValD::Class()) {rIntD=(AliLHCDipValD*)rIntF; rIntF=0;}
1145     if (!rIntF && !rIntD) {
1146       AliError(Form("Failed to get GetIntensityPerBunch(%d,%d)",beamID,irec));
1147       continue;
1148     }
1149     for (int ib=0;ib<nb;ib++) {
1150       double val = 0;
1151       if (rIntF) val = rIntF->GetValue(ib);
1152       else if (rIntD) val = rIntD->GetValue(ib);
1153       if (val<0) continue;
1154       int bID = conf->GetValue(ib);
1155       // check if this is a triggered bunch
1156       int bcID = GetBCId(bID, beamID);
1157       if (bID<0) { // interacting
1158         if (bcMaskBoth && bcMaskBoth->GetMask(bcID)) continue; // masked
1159         colliding += val;
1160       }
1161       else {
1162         if (bcMaskSingle && bcMaskSingle->GetMask(bcID)) continue; // masked    
1163         noncolliding += val;
1164       }
1165     }
1166   }
1167   colliding /= nrec;
1168   noncolliding /= nrec;
1169   return nrec;
1170 }
1171
1172 /***************************************************************************************
1173 // this is for the obsolete retrofitting
1174
1175 //___________________________________________________________________
1176 void AliLHCData::FillLumiAliceOFL(Int_t nrec, Int_t* timeArr, Double_t* valArr)
1177 {
1178   // Create a record for lumi integrated from the beginning of fill
1179   // We need dedicated method since this info comes from Alice (not LHCDip) as instantaneous values
1180   // and is retrofitted for past runs
1181   fLumiAlice[kStart] = fData.GetEntriesFast();
1182   fLumiAlice[kNStor] = 0;
1183   if (nrec<2 || !timeArr || !valArr) return;
1184   double tprv,period,currTime;
1185   if ((currTime=double(UInt_t(timeArr[0])))>fTMin) {
1186     AliError(Form("TimeStamp of 1st record: %s > TimeStamp of SOR: %s, STOP",
1187                   AliLHCDipValI::TimeAsString(currTime),AliLHCDipValI::TimeAsString(fTMin)));
1188     return;
1189   }
1190   //
1191   if ((tprv=double(UInt_t(timeArr[nrec-1])))<fTMax) {
1192     AliWarning(Form("TimeStamp of last (%d) record: %s < TimeStamp of EOR: %s, Data will be truncated",nrec-1,
1193                     AliLHCDipValI::TimeAsString(tprv),AliLHCDipValI::TimeAsString(fTMax)));
1194   }
1195   //
1196   // init the average time step
1197   period = (tprv - currTime)/(nrec-1);
1198   double lumiInt  = 0;
1199   //
1200   for (int i=0;i<nrec;i++) {
1201     tprv = currTime;
1202     currTime = double(UInt_t(timeArr[i]));
1203     if (i>0) period = currTime - tprv;
1204     if (currTime-period>fTMax) continue;    
1205     lumiInt += valArr[i]*period;    
1206     //    printf("%d %.2f V:%f Int:%f\n",i,period,valArr[i],lumiInt);
1207     if (currTime+period<fTMin) continue;
1208     AliLHCDipValF* curValF = new AliLHCDipValF(1,currTime);
1209     (*curValF)[0] = lumiInt;
1210     fData.Add(curValF);
1211     fLumiAlice[kNStor]++;
1212   }
1213   //
1214   printf("Stored %d Alice Integrated luminosity records out of %d provided\n",fLumiAlice[kNStor],nrec);
1215 }
1216
1217 //___________________________________________________________________
1218 void AliLHCData::FillBckgAliceOFL(Int_t nrec, Int_t* timeArr, Double_t* valArr)
1219 {
1220   // Create a record for lumi integrated from the beginning of fill
1221   // We need dedicated method since this info comes from Alice (not LHCDip) as instantaneous values
1222   // and is retrofitted for past runs
1223   fBckgAlice[kStart] = fData.GetEntriesFast();
1224   fBckgAlice[kNStor] = 0;
1225   if (nrec<2 || !timeArr || !valArr) return;
1226   double tprv,period,currTime;
1227   if ((currTime=double(UInt_t(timeArr[0])))>fTMin) {
1228     AliError(Form("TimeStamp of 1st record: %s > TimeStamp of SOR: %s, STOP",
1229                   AliLHCDipValI::TimeAsString(currTime),AliLHCDipValI::TimeAsString(fTMin)));
1230     return;
1231   }
1232   //
1233   if ((tprv=double(UInt_t(timeArr[nrec-1])))<fTMax) {
1234     AliWarning(Form("TimeStamp of last (%d) record: %s < TimeStamp of EOR: %s, Data will be truncated",nrec-1,
1235                     AliLHCDipValI::TimeAsString(tprv),AliLHCDipValI::TimeAsString(fTMax)));
1236   }
1237   //
1238   // init the average time step
1239   period = (tprv - currTime)/(nrec-1);
1240   double bckgInt  = 0;
1241   //
1242   for (int i=0;i<nrec;i++) {
1243     tprv = currTime;
1244     currTime = double(UInt_t(timeArr[i]));
1245     if (i>0) period = currTime - tprv;
1246     if (currTime-period>fTMax) continue;    
1247     bckgInt += valArr[i]*period;    
1248     if (currTime+period<fTMin) continue;
1249     AliLHCDipValF* curValF = new AliLHCDipValF(1,currTime);
1250     (*curValF)[0] = bckgInt;
1251     fData.Add(curValF);
1252     fBckgAlice[kNStor]++;
1253   }
1254   //
1255   printf("Stored %d Alice Integrated Background records out of %d provided\n",fBckgAlice[kNStor],nrec);
1256 }
1257
1258 ***************************************************************************************/
1259
1260 /*
1261 //_____________________________________________________________________________
1262 Float_t AliLHCData::GetLumiInstAlice(Double_t tStamp) const 
1263 {
1264   // get closest in time value on inst luminosity
1265   int idx = FindEntryValidFor(fLumiAlice[kStart],fLumiAlice[kNStor],tStamp);
1266   if (idx<0) return -1;
1267   AliLHCDipValF *rec=GetLumiAlice(idx),*rec1=GetLumiAlice(idx>0 ? idx-1:idx+1);
1268   if (!rec || !rec1) return -1;
1269   double dt = rec->GetTimeStamp() - rec1->GetTimeStamp();
1270   return TMath::Abs(dt)>1e-6 ? (rec->GetValue()-rec1->GetValue())/dt : -1;
1271 }
1272
1273 //_____________________________________________________________________________
1274 Float_t AliLHCData::GetBckgInstAlice(Double_t tStamp) const 
1275 {
1276   // get closest in time value on inst luminosity
1277   int idx = FindEntryValidFor(fBckgAlice[kStart],fBckgAlice[kNStor],tStamp);
1278   if (idx<0) return -1;
1279   AliLHCDipValF *rec=GetBckgAliceRecord(idx),*rec1=GetBckgAliceRecord(idx>0 ? idx-1:idx+1);
1280   if (!rec || !rec1) return -1;
1281   double dt = rec->GetTimeStamp() - rec1->GetTimeStamp();
1282   return TMath::Abs(dt)>1e-6 ? (rec->GetValue()-rec1->GetValue())/dt : -1;
1283 }
1284 */
1285
1286 //_____________________________________________________________________________
1287 TGraph* AliLHCData::ExportGraph(Int_t *coord, Int_t elID) const
1288 {
1289   // export time/values to graph:
1290   // coord: int[2] array with 1st entry and number of entries stored, obtained via GetOffs... method 
1291   // elID - element of the AliLHCDipValT array to extract
1292   if (!coord || coord[1]<1) return 0;
1293   TGraph* gr = new TGraph(coord[1]);
1294   for (int i=0;i<coord[1];i++) {
1295     TObject* obj = fData.At(coord[0]+i);
1296     if (!obj) {
1297       AliError(Form("Entry %d does not exist",i));
1298       continue;
1299     }
1300     if (obj->IsA()==AliLHCDipValD::Class()) {
1301       AliLHCDipValD* objD =  (AliLHCDipValD*)obj;
1302       gr->SetPoint(i,objD->GetTimeStamp(),objD->GetValue(elID));
1303     }
1304     else if (obj->IsA()==AliLHCDipValF::Class()) {
1305       AliLHCDipValF* objF =  (AliLHCDipValF*)obj;
1306       gr->SetPoint(i,objF->GetTimeStamp(),objF->GetValue(elID));
1307     }
1308     else if (obj->IsA()==AliLHCDipValI::Class()) {
1309       AliLHCDipValI* objI =  (AliLHCDipValI*)obj;
1310       gr->SetPoint(i,objI->GetTimeStamp(),objI->GetValue(elID));
1311     }
1312     else if (obj->IsA()==AliLHCDipValC::Class()) {
1313       AliLHCDipValC* objC =  (AliLHCDipValC*)obj;
1314       gr->SetPoint(i,objC->GetTimeStamp(),objC->GetValue(elID));
1315     }
1316     else {
1317       AliError(Form("Graph cannot be exported for records of type %s",obj->IsA()->GetName()));
1318     }
1319   }
1320   return gr;
1321 }