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