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