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