Project
Loading...
Searching...
No Matches
HMPIDDCSProcessor.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
13#include <TCanvas.h>
14
15namespace o2::hmpid
16{
17
18// initialize map of DPIDs, function is called once in the
19// HMPIDDCSDataProcessorSpec::init() function
20void HMPIDDCSProcessor::init(const std::vector<DPID>& pids)
21{
22 for (const auto& it : pids) {
23 mPids[it] = false;
24 }
25 arNmean.resize(43);
26 arQthre.resize(42);
27}
28
29// process span of Datapoints, function is called repeatedly in the
30// HMPIDDCSDataProcessorSpec::run() function
31void HMPIDDCSProcessor::process(const gsl::span<const DPCOM> dps)
32{
33
34 // if there is no entries in span
35 if (dps.size() == 0) {
36 LOG(debug) << "Size = 0: ";
37 return;
38 }
39
40 if (mVerbose) {
41 LOG(debug) << "\n\n\nProcessing new DCS DP map\n-----------------";
42 }
43
44 if (!mFirstTimeSet) {
45 mFirstTime = mStartValidity;
46 mFirstTimeSet = true;
47 }
48
49 // itterate over span of datapoints
50 for (const auto& dp : dps) {
51 const auto& el = mPids.find(dp.id);
52
53 // check if datapoint is within the defined map of DPs for HMPID
54 if (el == mPids.end()) {
55 LOG(info) << "DP " << dp.id << "Not found, will not be processed";
56 continue;
57 }
58 // The aliasstring has been processed:
59 mPids[dp.id] = true;
60
61 // extract alias-string of DataPoints
62 const std::string_view alias(dp.id.get_alias());
63 const auto detectorId = alias.substr(0, 4); // HMP_
64 const auto transparencyId = alias.substr(0, 22); // HMP_TRANPLANT_MEASURE_
65
66 // check if given dp is from HMPID
67 if (transparencyId == TRANS_ID) {
68 processTRANS(dp);
69 } else if (detectorId == HMPID_ID) {
70 processHMPID(dp);
71 } else {
72 LOG(warn) << "Missing data point: " << alias;
73 }
74 } // end for
75}
76
77// if the string of the dp contains the HMPID-specifier "HMP_",
78// but not the Transparency-specifier
79void HMPIDDCSProcessor::processHMPID(const DPCOM& dp)
80{
81 const std::string alias(dp.id.get_alias());
82 const auto hmpidString = alias.substr(alias.length() - 8);
83
84 if (hmpidString == TEMP_IN_ID) {
85 if (mVerbose) {
86 LOG(info) << "Temperature_in DP: " << dp;
87 }
88 fillTempIn(dp);
89 } else if (hmpidString == TEMP_OUT_ID) {
90 if (mVerbose) {
91 LOG(info) << "Temperature_out DP: " << dp;
92 }
93 fillTempOut(dp);
94 } else if (hmpidString == HV_ID) {
95 if (mVerbose) {
96 LOG(info) << "HV DP: " << dp;
97 }
98 fillHV(dp);
99 } else if (hmpidString == ENV_PRESS_ID) {
100 if (mVerbose) {
101 LOG(info) << "Environment Pressure DP: " << dp;
102 }
103 fillEnvPressure(dp);
104 } else if (hmpidString == CH_PRESS_ID) {
105 if (mVerbose) {
106 LOG(info) << "Chamber Pressure DP: " << dp;
107 }
108 fillChPressure(dp);
109 } else {
110 LOG(warn) << "Missing data point: " << dp;
111 }
112}
113
114// if the string of the dp contains the Transparency-specifier
115// "HMP_TRANPLANT_MEASURE_"
116void HMPIDDCSProcessor::processTRANS(const DPCOM& dp)
117{
118 const auto& dpid = dp.id;
119 const std::string alias(dpid.get_alias());
120 const auto transparencyString = alias.substr(alias.length() - 9);
121
122 // Get index [0..29] of Transparency-measurement
123 const int dig1 = aliasStringToInt(dpid, 22);
124 const int dig2 = aliasStringToInt(dpid, 23);
125 const int num = dig1 * 10 + dig2;
126
127 if (dig1 == -1 || dig2 == -1) {
128 LOG(warn) << "digits in string invalid" << dig1 << " " << dig2;
129 return;
130 }
131
132 if (num < 0 || num > 29) {
133 LOG(warn) << "num out of range " << num;
134 return;
135 }
136
137 if (alias.substr(alias.length() - 10) == WAVE_LEN_ID) {
138 waveLenVec[num].emplace_back(dp);
139 if (mVerbose) {
140 LOG(info) << "WAVE_LEN_ID DP: " << dp;
141 }
142 } else if (transparencyString == FREON_CELL_ID) {
143 freonCellVec[num].emplace_back(dp);
144 if (mVerbose) {
145 LOG(info) << "FREON_CELL_ID DP: " << dp;
146 }
147 } else if (transparencyString == ARGON_CELL_ID) {
148 if (mVerbose) {
149 LOG(info) << "ARGON_CELL_ID DP: " << dp;
150 }
151 argonCellVec[num].emplace_back(dp);
152 } else if (transparencyString == REF_ID) {
153 if (alias.substr(alias.length() - 14) == ARGON_REF_ID) {
154 if (mVerbose) {
155 LOG(info) << "ARGON_REF_ID DP: " << dp;
156 }
157 argonRefVec[num].emplace_back(dp);
158 } else if (alias.substr(alias.length() - 14) == FREON_REF_ID) {
159 freonRefVec[num].emplace_back(dp);
160 if (mVerbose) {
161 LOG(info) << "FREON_REF_ID DP: " << dp;
162 }
163 } else {
164 LOG(warn) << "Missing Data point: " << dp;
165 }
166 } else {
167 LOG(warn) << "Missing Data point: " << dp;
168 }
169}
170
171// ======Fill
172// DPCOM-entries===========================================================
173
174// fill entries in environment pressure DPCOM-vector
175void HMPIDDCSProcessor::fillEnvPressure(const DPCOM& dpcom)
176{
177 auto& dpid = dpcom.id;
178 const auto& type = dpid.get_type();
179
180 // check if datatype is as expected
181 if (type == DeliveryType::DPVAL_DOUBLE) {
182 dpVecEnv.emplace_back(dpcom);
183 } else {
184 LOG(warn) << "Invalid Datatype for Env Pressure";
185 }
186}
187
188// fill entries in chamber-pressure DPCOM-vector
189void HMPIDDCSProcessor::fillChPressure(const DPCOM& dpcom)
190{
191 auto& dpid = dpcom.id;
192 const auto& type = dpid.get_type();
193
194 if (type == DeliveryType::DPVAL_DOUBLE) {
195
196 // find chamber number:
197 auto chNum = aliasStringToInt(dpid, indexChPr);
198 if (chNum < 7 && chNum >= 0) {
199 dpVecCh[chNum].emplace_back(dpcom);
200 } else {
201 LOGP(warn, "Chamber Number out of range for Pressure P{}: ", chNum);
202 const std::string inputString(dpid.get_alias());
203 char stringPos = inputString[indexChPr];
204 }
205 } else {
206 LOGP(warn, "Not correct datatype for Pressure");
207 }
208}
209
210// HV in each chamber_section = 7*3 --> will result in Q_thre
211void HMPIDDCSProcessor::fillHV(const DPCOM& dpcom)
212{
213 auto& dpid = dpcom.id;
214 const auto& type = dpid.get_type();
215
216 if (type == DeliveryType::DPVAL_DOUBLE) {
217 const auto chNum = aliasStringToInt(dpid, indexChHv);
218 const auto secNum = aliasStringToInt(dpid, indexSecHv);
219
220 if (chNum < 7 && chNum >= 0) {
221 if (secNum < 6 && secNum >= 0) {
222 dpVecHV[6 * chNum + secNum].emplace_back(dpcom);
223 } else {
224 LOGP(warn, "Sector Number out of range for High Voltage HV{}{}", chNum, secNum);
225 }
226 } else {
227 LOGP(warn, "Chamber Number out of range for High Voltage HV{}{}", chNum, secNum);
228 }
229 } else {
230 LOGP(warn, "Not correct datatype for High Voltage");
231 }
232}
233
234// Temp in (T1) in each chamber_radiator = 7*3
235void HMPIDDCSProcessor::fillTempIn(const DPCOM& dpcom)
236{
237 auto& dpid = dpcom.id;
238 const auto& type = dpid.get_type();
239
240 if (type == DeliveryType::DPVAL_DOUBLE) {
241 auto chNum = aliasStringToInt(dpid, indexChTemp);
242 auto radNum = aliasStringToInt(dpid, indexRadTemp);
243
244 // verify chamber- and raiator-numbers
245 if (chNum < 7 && chNum >= 0) {
246 if (radNum < 3 && radNum >= 0) {
247 dpVecTempIn[3 * chNum + radNum].emplace_back(dpcom);
248 } else {
249 LOGP(warn, "Radiator Number out of range for TempIn Tin{}{}", chNum, radNum);
250 }
251 } else {
252 LOGP(warn, "Chamber Number out of range for TempIn Tin{}{}", chNum, radNum);
253 }
254 } else {
255 LOGP(warn, "Not correct datatype for TempIn");
256 }
257}
258
259// Temp out (T2), in each chamber_radiator = 7*3
260void HMPIDDCSProcessor::fillTempOut(const DPCOM& dpcom)
261{
262 auto& dpid = dpcom.id;
263 const auto& type = dpid.get_type();
264
265 if (type == DeliveryType::DPVAL_DOUBLE) {
266 auto chNum = aliasStringToInt(dpid, indexChTemp);
267 auto radNum = aliasStringToInt(dpid, indexRadTemp);
268
269 // verify chamber- and raiator-numbers
270 if (chNum < 7 && chNum >= 0) {
271 if (radNum < 3 && radNum >= 0) {
272 dpVecTempOut[3 * chNum + radNum].emplace_back(dpcom);
273
274 } else {
275 LOGP(warn, "Radiator Number out of range for TempOut Tout{}{}", chNum, radNum);
276 }
277 } else {
278 LOGP(warn, "Chamber Number out of range for TempOut Tout{}{}", chNum, radNum);
279 }
280 } else {
281 LOGP(warn, "Not correct datatype for TempOut");
282 }
283}
284
285//==== Calculate mean photon energy=============================================
286// ef: if eMeanDefault is returned, this means eMeanDefault will be sent to the CCDB
287// in the last entry in the vector arNmean[42] (pPhotMean;)
288double HMPIDDCSProcessor::procTrans()
289{
290 for (int i = 0; i < 30; i++) {
291
292 // ef: calculatePhotonEnergy(i):
293 // if there is something wrong in calculating the photon-energy for the given
294 // wavelength (i.e., the current entry i in the waveLenVec holding the DPs
295 // of wavelenghts)
296 // then the default wavelength for the given iteration will be sent
297
298 photEn = calculatePhotonEnergy(i);
299
300 if (photEn < o2::hmpid::Param::ePhotMin() ||
301 photEn > o2::hmpid::Param::ePhotMax()) {
302 LOG(warn) << "photon energy out of range" << photEn;
303 lambda = arrWaveLenDefault[i];
304 photEn = nm2eV / lambda;
305 // continue; // ef: if photon energy is out of range; skip to next iteration
306 }
307
308 // ef: if any of the vectors fof DP-currents (argonRef, cellArgon..) are invalid,
309 // the function returns eMeanDefault, which subsequently will be directly sent to the CCDB
310
311 // ===== evaluate phototube current for argon reference ============================
312 TransparencyDpInfo refArgonDP = dpVector2Double(argonRefVec[i], "ARGONREF", i);
313 if (refArgonDP.isDpValid == false) {
314 return eMeanDefault;
315 } else {
316 refArgon = refArgonDP.dpVal;
317 }
318
319 //===== evaluate phototube current for argon cell===================================
320 TransparencyDpInfo cellArgonDP = dpVector2Double(argonCellVec[i], "ARGONCELL", i);
321 if (cellArgonDP.isDpValid == false) {
322 return eMeanDefault;
323 } else {
324 cellArgon = cellArgonDP.dpVal;
325 }
326
327 //==== evaluate phototube current for freon reference ==============================
328 TransparencyDpInfo refFreonDP = dpVector2Double(freonRefVec[i], "C6F14REFERENCE", i);
329 if (refFreonDP.isDpValid == false) {
330 return eMeanDefault;
331 } else {
332 refFreon = refFreonDP.dpVal;
333 }
334
335 // ==== evaluate phototube current for freon cell ==================================
336 TransparencyDpInfo cellFreonDP = dpVector2Double(freonCellVec[i], "C6F14CELL", i);
337 if (cellFreonDP.isDpValid == false) {
338 return eMeanDefault;
339 } else {
340 cellFreon = cellFreonDP.dpVal;
341 }
342
343 // evaluate correction factor to calculate trasparency
344 bool isEvalCorrOk = evalCorrFactor(refArgon, cellArgon, refFreon, cellFreon, photEn, i);
345
346 // ef: Returns false if dRefFreon * dRefArgon < 0
347 if (!isEvalCorrOk) {
348 return eMeanDefault;
349 }
350
351 } // end for
352
353 // evaluate total energy --> mean photon energy
354 if (sProb > 0) {
355 eMean = sEnergProb / sProb;
356 } else {
357 LOGP(warn, " sProb < 0 --> Default E mean used! ");
358 return eMeanDefault;
359 }
360
361 if (eMean < o2::hmpid::Param::ePhotMin() ||
362 eMean > o2::hmpid::Param::ePhotMax()) {
363 LOGP(warn, "eMean out of range ({}) --> Default E mean used! ", eMean);
364 return eMeanDefault;
365 }
366
367 return eMean;
368
369} // end ProcTrans
370
371// ==== procTrans help-functions =============================
372
373//==== evaluate photon energy
374//=======================================================
375
376// ef: if calculatePhotonEnergy returns eMeanDefault, it simply means that
377// there were something wrong in calculating the photon-energy for the given
378// wavelength (i.e., the current entry i in the waveLenVec holding the DPs
379// of wavelenghts)]
380// the value will not directly be sent to the CCDB
381
382double HMPIDDCSProcessor::calculatePhotonEnergy(int i)
383{
384 // if there is no entries
385 if (waveLenVec[i].size() == 0) {
386 LOGP(warn, "No Data Point values for HMP_TRANPLANT_MEASURE_{}_WAVELENGTH --> Default wavelength used for iteration procTrans{}", i, i);
387 // return lambda/
388 lambda = arrWaveLenDefault[i];
389 return nm2eV / lambda;
390 }
391
392 const DPCOM& dp = (waveLenVec[i])[0];
393
394 // check if datatype is as expected
395 if (dp.id.get_type() == DeliveryType::DPVAL_DOUBLE) {
396 lambda = o2::dcs::getValue<double>(dp);
397 } else {
398 LOGP(warn, "DP type is {}", (int)dp.id.get_type());
399 LOGP(warn, "Not correct datatype for HMP_TRANPLANT_MEASURE_{}_WAVELENGTH --> Default wavelength used for iteration procTrans{}", i, i);
400 lambda = arrWaveLenDefault[i];
401 }
402
403 // ef: can remove this?
404 if (lambda < 150. || lambda > 230.) {
405 LOGP(warn, "Wrong value for (lambda out of range) HMP_TRANPLANT_MEASURE_{}_WAVELENGTH --> Default wavelength used for iteration procTrans{}", i, i);
406 lambda = arrWaveLenDefault[i];
407 }
408
409 // find photon energy E in eV from radiation wavelength λ in nm
410 // nm2eV = 1239.842609; // 1239.842609 from nm to eV
411 photEn = nm2eV / lambda; // photon energy
412 return photEn;
413}
414
415// TransparencyDpInfo default value is
416// bool isDpValid = False
417// double dpVal = -999
418TransparencyDpInfo HMPIDDCSProcessor::dpVector2Double(const std::vector<DPCOM>& dpVec,
419 const char* dpString, int i)
420{
421
422 TransparencyDpInfo transDpInfo;
423 if (dpVec.size() == 0) {
424 LOGP(warn, "No Data Point values for HMP_TRANPLANT_MEASURE_{}_{}---> Default E mean used!",
425 dpString, i);
426 return transDpInfo; // returns transDpInfo with default values
427 }
428
429 const DPCOM& dp = dpVec[0];
430
431 if (dp.id.get_type() == DeliveryType::DPVAL_DOUBLE) {
432 transDpInfo.dpVal = o2::dcs::getValue<double>(dp);
433 transDpInfo.isDpValid = true;
434 } else {
435 LOGP(warn, "Not correct datatype for HMP_TRANPLANT_MEASURE_{}_{} -----> Default E mean used!",
436 dpString, i);
437 return transDpInfo; // returns transDpInfo with default values
438 }
439 return transDpInfo;
440}
441
442bool HMPIDDCSProcessor::evalCorrFactor(const double& dRefArgon, const double& dCellArgon, const double& dRefFreon,
443 const double& dCellFreon, const double& dPhotEn, const int& i)
444{
445 // evaluate correction factor to calculate trasparency (Ref. NIMA 486 (2002)
446 // 590-609)
447
448 // Double_t aN1 = AliHMPIDParam::NIdxRad(photEn,tRefCR5);
449 // Double_t aN2 = AliHMPIDParam::NMgF2Idx(photEn);
450 // Double_t aN3 = 1; // Argon Idx
451
452 // Double_t aR1 = ((aN1 - aN2)*(aN1 - aN2))/((aN1 + aN2)*(aN1 +
453 // aN2)); Double_t aR2 = ((aN2 - aN3)*(aN2 - aN3))/((aN2 +
454 // aN3)*(aN2 + aN3)); Double_t aT1 = (1 - aR1); Double_t aT2 =
455 // (1 - aR2); Double_t aCorrFactor = (aT1*aT1)/(aT2*aT2);
456
457 // evaluate 15 mm of thickness C6F14 Trans
458
459 if (dRefArgon == -999 || dCellArgon == -999 || dRefFreon == -999 || dCellFreon == -999) {
460 LOGP(warn, "One of the Phototube-currents was not assigned --> Default E mean used!");
461 return false;
462 }
463
464 if (dRefFreon * dRefArgon > 0) {
465 aTransRad = TMath::Power((dCellFreon / dRefFreon) /
466 (dCellArgon / dRefArgon) * aCorrFactor[i],
467 aConvFactor);
468 } else {
469 LOGP(warn, "dRefFreon*dRefArgon<0 --> Default E mean used! dRefFreon = {} | dRefArgon = {}", dRefFreon, dRefArgon);
470 return false;
471 }
472
473 // evaluate 0.5 mm of thickness SiO2 Trans
474
475 // TMath : Double_t Exp(Double_t x)
476 aTransSiO2 = TMath::Exp(-0.5 / o2::hmpid::Param::lAbsWin(dPhotEn));
477
478 // evaluate 80 cm of thickness Gap (low density CH4) transparency
479 aTransGap = TMath::Exp(-80. / o2::hmpid::Param::lAbsGap(dPhotEn));
480
481 // evaluate CsI quantum efficiency
482 // if dPhotEn < 6.07267, the value is zero
483 aCsIQE = o2::hmpid::Param::qEffCSI(dPhotEn);
484
485 // evaluate total convolution of all material optical properties
486 aTotConvolution = aTransRad * aTransSiO2 * aTransGap * aCsIQE;
487
488 sEnergProb += aTotConvolution * dPhotEn;
489 double sProbPrev = sProb;
490 sProb += aTotConvolution;
491
492 return true;
493}
494// end Calculate mean photon energy=============================================
495
496// ==== Functions that are called after run is finished ========================
497
498// will return nullptr if there is no entry in Environment-pressure
499// DPCOM-vector dpVecEnvPress
500std::unique_ptr<TF1> HMPIDDCSProcessor::finalizeEnvPressure()
501{
502 std::unique_ptr<TF1> pEnv;
503 if (dpVecEnv.size() != 0) {
504
505 envPrFirstTime = getMinTime(dpVecEnv);
506 envPrLastTime = getMaxTime(dpVecEnv);
507
508 int cntEnvPressure = 0;
509 std::unique_ptr<TGraph> pGrPenv;
510 pGrPenv.reset(new TGraph);
511
512 for (const DPCOM& dp : dpVecEnv) {
513 auto dpVal = o2::dcs::getValue<double>(dp);
514 auto time = dp.data.get_epoch_time(); //-envPrFirstTime
515 pGrPenv->SetPoint(cntEnvPressure++, time, dpVal);
516 }
517 // envPrLastTime -= envPrFirstTime;
518 // envPrFirstTime = 0;
519
520 if (cntEnvPressure <= 0) {
521 LOGP(warn, "No entries in Environment Pressure");
522 } else if (pGrPenv == nullptr) {
523 LOGP(warn, "NullPtr in Environment Pressure");
524 } else if (cntEnvPressure == 1) {
525 pGrPenv->GetPoint(0, xP, yP);
526 pEnv.reset(
527 new TF1("Penv", Form("%f", yP), envPrFirstTime, envPrLastTime));
528 } else {
529 pEnv.reset(new TF1("Penv", "1000+x*[0]", envPrFirstTime, envPrLastTime));
530 pGrPenv->Fit("Penv", "Q");
531 }
532 } else {
533 LOG(warn) << Form("No entries in environment pressure Penv");
534 }
535 return pEnv;
536}
537
538// returns nullptr if the element in array of DPCOM-vector has no entries
539std::unique_ptr<TF1> HMPIDDCSProcessor::finalizeChPressure(int iCh)
540{
541 std::unique_ptr<TF1> pCh;
542 if (dpVecCh[iCh].size() != 0) {
543 cntChPressure = 0;
544
545 std::unique_ptr<TGraph> pGrP;
546 pGrP.reset(new TGraph);
547
548 chPrFirstTime = getMinTime(dpVecCh[iCh]);
549 chPrLastTime = getMaxTime(dpVecCh[iCh]);
550
551 for (const DPCOM& dp : dpVecCh[iCh]) {
552 auto dpVal = o2::dcs::getValue<double>(dp);
553 auto time = dp.data.get_epoch_time();
554 pGrP->SetPoint(cntChPressure++, time, dpVal);
555 }
556 // chPrLastTime -= chPrFirstTime;
557 // chPrFirstTime = 0;
558
559 if (pGrP == nullptr || cntChPressure <= 0) {
560 LOGP(warn, "nullptr in chamber-pressure for P{}", iCh);
561 } else if (cntChPressure == 1) {
562 pGrP->GetPoint(0, xP, yP);
563 (pCh).reset(new TF1(Form("P%i", iCh), Form("%f", yP), chPrFirstTime,
564 chPrLastTime));
565 } else {
566 (pCh).reset(new TF1(Form("P%i", iCh), "[0] + x*[1]", chPrFirstTime,
567 chPrLastTime));
568 pGrP->Fit(Form("P%i", iCh), "Q");
569 }
570 } else {
571 LOGP(warn, "No entries in chamber-pressure for P{}", iCh);
572 }
573 return pCh;
574}
575
576// process Tempout
577bool HMPIDDCSProcessor::finalizeTempOut(int iCh, int iRad)
578{
579 if (dpVecTempOut[3 * iCh + iRad].size() != 0) {
580 cntTOut = 0;
581
582 auto minTime = getMinTime(dpVecTempOut[3 * iCh + iRad]);
583 auto maxTime = getMaxTime(dpVecTempOut[3 * iCh + iRad]);
584
585 if (iCh == 0 && iRad == 0) { // ef: for mean-photon energy
586 mTimeEMean.first = minTime; // DPs here are forced to produce sor/eor
587 mTimeEMean.last = maxTime; // using same timesamps for eMean
588 }
589
590 std::unique_ptr<TGraph> pGrTOut;
591 pGrTOut.reset(new TGraph);
592
593 for (const DPCOM& dp : dpVecTempOut[3 * iCh + iRad]) {
594 auto dpVal = o2::dcs::getValue<double>(dp);
595 auto time = dp.data.get_epoch_time();
596 pGrTOut->SetPoint(cntTOut++, time, dpVal);
597 }
598
599 std::unique_ptr<TF1> pTout;
600 pTout.reset(
601 new TF1(Form("Tout%i%i", iCh, iRad), "[0]+[1]*x", minTime, maxTime));
602
603 if (pTout == nullptr || pGrTOut == nullptr || cntTOut <= 0) {
604 LOGP(warn, "NullPtr in Temperature out Tout{}{}", iCh, iRad);
605 return false;
606 } else if (cntTOut == 1) {
607 pGrTOut->GetPoint(0, xP, yP);
608 pTout->SetParameter(0, yP);
609 pTout->SetParameter(1, 0);
610 } else {
611 pGrTOut->Fit(Form("Tout%i%i", iCh, iRad), "R");
612 }
613
614 // ef: in this case everything is ok, and we can set title and put entry in CCDB:
615 // have to check all for nullptr, because pTout is defined before if/else block,
616 // and thus will not be nullptr no matter the outcome of the if/else block
617 if (pTout != nullptr && pGrTOut != nullptr && cntTOut > 0) {
618 pTout->SetTitle(Form("Temp-Out Fit Chamber%i Radiator%i; Time [ms];Temp [C]", iCh, iRad));
619 arNmean[6 * iCh + 2 * iRad + 1] = *(pTout.get());
620 return true;
621 } else {
622 LOGP(warn, "NullPtr in Temperature out Tout{}{}", iCh, iRad);
623 return false;
624 }
625 } else {
626 LOGP(warn, "No entries in Temperature out Tout{}{}", iCh, iRad);
627 return false;
628 }
629}
630
631// process Tempin
632bool HMPIDDCSProcessor::finalizeTempIn(int iCh, int iRad)
633{
634 if (dpVecTempIn[3 * iCh + iRad].size() != 0) {
635 cntTin = 0;
636
637 auto minTime = getMinTime(dpVecTempIn[3 * iCh + iRad]);
638 auto maxTime = getMaxTime(dpVecTempIn[3 * iCh + iRad]);
639
640 std::unique_ptr<TGraph> pGrTIn;
641 pGrTIn.reset(new TGraph);
642
643 for (const DPCOM& dp : dpVecTempIn[3 * iCh + iRad]) {
644 auto dpVal = o2::dcs::getValue<double>(dp);
645 auto time = dp.data.get_epoch_time();
646 pGrTIn->SetPoint(cntTin++, time, dpVal);
647 }
648
649 std::unique_ptr<TF1> pTin;
650 pTin.reset(
651 new TF1(Form("Tin%i%i", iCh, iRad), "[0]+[1]*x", minTime, maxTime));
652
653 if (pTin == nullptr || pGrTIn == nullptr || cntTin <= 0) {
654 LOGP(warn, "NullPtr in Temperature in Tin{}{}", iCh, iRad);
655 return false;
656 } else if (cntTOut == 1) {
657 pGrTIn->GetPoint(0, xP, yP);
658 pTin->SetParameter(0, yP);
659 pTin->SetParameter(1, 0);
660 } else {
661 pGrTIn->Fit(Form("Tin%i%i", iCh, iRad), "R");
662 }
663
664 // ef: in this case everything is ok, and we can set title and put entry in CCDB:
665 // have to check all for nullptr, because pTin is defined before if/else block,
666 // and thus will not be nullptr no matter the outcome of the if/else block
667 if (pTin != nullptr && pGrTIn != nullptr && cntTin > 0) {
668 pTin->SetTitle(Form("Temp-In Fit Chamber%i Radiator%i; Time [ms];Temp [C]", iCh, iRad));
669 arNmean[6 * iCh + 2 * iRad] = *(pTin.get());
670 return true;
671 } else {
672 LOGP(warn, "NullPtr in Temperature in Tin{}{}", iCh, iRad);
673 return false;
674 }
675 } else {
676 LOGP(warn, "No entries in Temperature in Tin{}{}", iCh, iRad);
677 return false;
678 }
679}
680
681// returns nullptr if the element in array of DPCOM-vector has no entries
682std::unique_ptr<TF1> HMPIDDCSProcessor::finalizeHv(int iCh, int iSec)
683{
684 std::unique_ptr<TF1> pHvTF;
685 if (dpVecHV[3 * iCh + iSec].size() != 0) {
686
687 std::unique_ptr<TGraph> pGrHV;
688 pGrHV.reset(new TGraph);
689 cntHV = 0;
690
691 hvFirstTime = getMinTime(dpVecHV[3 * iCh + iSec]);
692 hvLastTime = getMaxTime(dpVecHV[3 * iCh + iSec]);
693
694 for (const DPCOM& dp : dpVecHV[3 * iCh + iSec]) {
695 auto dpVal = o2::dcs::getValue<double>(dp);
696 auto time = dp.data.get_epoch_time();
697 pGrHV->SetPoint(cntHV++, time, dpVal);
698 }
699 // hvLastTime -= hvFirstTime;
700 // hvFirstTime = 0;
701
702 if (pGrHV == nullptr || cntHV <= 0) {
703 LOGP(warn, "nullptr in High Voltage for HV{}{}", iCh, iSec);
704 } else if (cntHV == 1) {
705 pGrHV->GetPoint(0, xP, yP);
706 (pHvTF).reset(new TF1(Form("HV%i%i", iCh, iSec), Form("%f", yP),
707 hvFirstTime, hvLastTime));
708 } else {
709 (pHvTF).reset(new TF1(Form("HV%i%i", iCh, iSec), "[0]+x*[1]",
710 hvFirstTime, hvLastTime));
711 pGrHV->Fit(Form("HV%i%i", iCh, iSec), "Q"); // ef added
712 }
713 } else {
714 LOGP(warn, "No entries in High Voltage for HV{}{}", iCh, iSec);
715 }
716 return pHvTF;
717}
718
719// Process all arrays of DPCOM-vectors, perform fits
720// Called At the end of the Stream of DPs, in
721// HMPIDDCSDataProcessorSpec::endOfStream() function
723{
724
725 LOG(info) << "finalize=================================== ";
726 std::unique_ptr<TF1> pEnv = finalizeEnvPressure();
727 for (int iCh = 0; iCh < 7; iCh++) {
728
729 std::unique_ptr<TF1> pChPres = finalizeChPressure(iCh);
730
731 // fills up entries 0..41 of arNmean
732 for (int iRad = 0; iRad < 3; iRad++) {
733
734 // 6*iCh + 2*iRad
735 bool isTempInValid = finalizeTempIn(iCh, iRad);
736
737 if (isTempInValid == false) {
738 LOGP(warn, "Tin{}{} not valid! Setting default TF1!", iCh, iRad);
739 // this means that the entry was not valid, and thus the vector is not filled
740 std::unique_ptr<TF1> pTinDefault;
741 pTinDefault.reset(new TF1());
742 setDefault(pTinDefault.get(), true);
743
744 // ef: set flag in invalid object, such that it can be read in receiving
745 // side (Ckov reconstruction) as invalid and thus use default value
746 arNmean[6 * iCh + 2 * iRad] = *(pTinDefault.get());
747 }
748
749 // 6*iCh + 2*iRad + 1
750 bool isTempOutValid = finalizeTempOut(iCh, iRad);
751
752 if (isTempOutValid == false) {
753 LOGP(warn, "Tout{}{} not valid! Setting default TF1!", iCh, iRad);
754 // this means that the entry was not valid, and thus the vector is not filled
755 std::unique_ptr<TF1> pToutDefault;
756 pToutDefault.reset(new TF1());
757 setDefault(pToutDefault.get(), true);
758
759 // ef: set flag in invalid object, such that it can be read on receiving
760 // side (Ckov reconstruction) as invalid and thus use default value
761 arNmean[6 * iCh + 2 * iRad + 1] = *(pToutDefault.get());
762 }
763 }
764
765 // Fill entries in arQthre
766 for (int iSec = 0; iSec < 6; iSec++) {
767
768 std::unique_ptr<TF1> pHV = finalizeHv(iCh, iSec);
769
770 // only fill if envP, chamP and HV datapoints are all fetched
771 if (pEnv != nullptr && pChPres != nullptr && pHV != nullptr) {
772 const char* hvChar = (pHV.get())->GetName(); // pArrHv[3 * iCh + iSec]
773 const char* chChar = (pChPres.get())->GetName(); // pArrCh[iCh]
774 const char* envChar = (pEnv.get())->GetName();
775 const char* fFormula =
776 "3*10^(3.01e-3*%s - 4.72)+170745848*exp(-(%s+%s)*0.0162012)";
777 const char* fName = Form(fFormula, hvChar, chChar, envChar);
778
779 auto minTime = std::max({envPrFirstTime, hvFirstTime, chPrFirstTime});
780 auto maxTime = std::min({envPrLastTime, hvLastTime, chPrLastTime});
781
782 std::unique_ptr<TF1> pQthre;
783 pQthre.reset(new TF1(Form("HMP_QthreC%iS%i", iCh, iSec), fName, minTime,
784 maxTime));
785 pQthre->SetTitle(Form(
786 "Charge-Threshold Ch%iSec%i; Time [mS]; Threshold ", iCh, iSec));
787
788 if (pQthre != nullptr) {
789 arQthre[6 * iCh + iSec] = *(pQthre.get());
790 } else {
791 std::unique_ptr<TF1> pQthreDefault;
792 pQthreDefault.reset(new TF1());
793 setDefault(pQthreDefault.get(), true);
794 // setDefault(TF1* f, bool v)// const {f->SetBit(kDefault, v);}
795
796 arQthre[6 * iCh + iSec] = *(pQthreDefault.get());
797 LOGP(warn, "Nullptr in Charge-Threshold arQthre{} in chamber{} sector{} ", 6 * iCh + iSec, iCh, iSec);
798 }
799 } else {
800 std::unique_ptr<TF1> pQthreDefault;
801 pQthreDefault.reset(new TF1());
802 setDefault(pQthreDefault.get(), true);
803 // setDefault(TF1* f, bool v)// const {f->SetBit(kDefault, v);}
804
805 arQthre[6 * iCh + iSec] = *(pQthreDefault.get());
806 LOGP(warn, "Missing entry in Charge-Threshold arQthre{} in chamber{} sector{} ", 6 * iCh + iSec, iCh, iSec);
807 // ef: not printing which one is missing as it is done already in the given function
808 }
809 }
810 }
811
812 LOG(info) << "======================================== ";
813
814 double eMean = procTrans();
815
816 std::unique_ptr<TF1> pPhotMean;
817 pPhotMean.reset(new TF1("HMP_PhotEmean", Form("%f", eMean), mTimeEMean.first,
818 mTimeEMean.last));
819
820 pPhotMean->SetTitle(Form("HMP_PhotEmean; Time [mS]; Photon Energy [eV]"));
821
822 if (pPhotMean != nullptr) {
823 arNmean[42] = *(pPhotMean.get());
824 // const auto& timeRange = pPhotMean->GetXaxis();
825 // LOGP(info, "TimeRange {} {}", pPhotMean->GetXmin(), pPhotMean->GetXmax());
826 } else {
827 std::unique_ptr<TF1> pPhotMeanDefault;
828 pPhotMeanDefault.reset(new TF1());
829 setDefault(pPhotMeanDefault.get(), true);
830 arNmean[42] = *(pPhotMeanDefault.get());
831 }
832
833 /*//save canvas
834 std::unique_ptr<TCanvas> photMeanCanvas;
835 photMeanCanvas.reset(new TCanvas("c1", "Mean Photon Energy",800,800));
836 photMeanCanvas->cd();
837 arNmean[42].Draw();
838 photMeanCanvas->SaveAs(("test.png"));*/
839
840 // Check entries of CCDB-objects
841 // checkEntries(arQthre, arNmean);
842
843 // prepare CCDB: =============================================================
844
845 std::map<std::string, std::string> md;
846 md["responsible"] = "Erlend Flatland";
847
848 // Refractive index (T_out, T_in, mean photon energy);
850 arNmean, mccdbRefInfo, "HMP/Calib/RefIndex", md, mStartValidity, mStartValidity + 3 * o2::ccdb::CcdbObjectInfo::DAY);
851
852 // charge threshold;
854 arQthre, mccdbChargeInfo, "HMP/Calib/ChargeCut", md, mStartValidity, mStartValidity + 3 * o2::ccdb::CcdbObjectInfo::DAY);
855}
856
858 const char* pid)
859{
860
861 // function to process the flag. the return code zero means that all is fine.
862 // anything else means that there was an issue
863
864 // for now, I don't know how to use the flags, so I do nothing
865
867 LOG(debug) << "KEEP_ALIVE_FLAG active for DP " << pid;
868 }
869 if (flags & DPVAL::END_FLAG) {
870 LOG(debug) << "END_FLAG active for DP " << pid;
871 }
872 return 0;
873}
874
875// extract string from DPID, convert char at specified element in string
876// to int
877int HMPIDDCSProcessor::aliasStringToInt(const DPID& dpid, std::size_t startIndex)
878{
879
880 const std::string inputString(dpid.get_alias());
881 char stringPos = inputString[startIndex];
882 int charInt = ((int)stringPos) - ((int)'0');
883 if (charInt < 10 && charInt >= 0) {
884 return charInt;
885 } else {
886 return -1;
887 }
888}
889} // namespace o2::hmpid
int16_t time
Definition RawEventData.h:4
int32_t i
uint16_t pid
Definition RawData.h:2
std::ostringstream debug
double num
static constexpr long DAY
DeliveryType get_type() const noexcept
const char *const get_alias() const noexcept
void init(const std::vector< DPID > &pids)
int aliasStringToInt(const DPID &dpid, std::size_t startIndex)
uint64_t processFlags(const uint64_t flags, const char *pid)
void process(const gsl::span< const DPCOM > dps)
static double ePhotMin()
Definition Param.h:138
static double lAbsGap(double eV)
Definition Param.h:149
static double lAbsWin(double eV)
Definition Param.h:148
static double qEffCSI(double eV)
Definition Param.h:150
static double ePhotMax()
Definition Param.h:139
GLsizeiptr size
Definition glcorearb.h:659
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLbitfield flags
Definition glcorearb.h:1570
static void prepareCCDBobjectInfo(T &obj, o2::ccdb::CcdbObjectInfo &info, const std::string &path, const std::map< std::string, std::string > &md, long start, long end=-1)
Definition Utils.h:91
uint64_t get_epoch_time() const noexcept
static constexpr uint16_t END_FLAG
static constexpr uint16_t KEEP_ALIVE_FLAG
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"