ATLAS Offline Software
NSWCalibSmearingTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "NSWCalibSmearingTool.h"
7 
8 #include "CLHEP/Random/RandFlat.h"
9 #include "CLHEP/Random/RandGaussZiggurat.h"
10 
11 #include <iostream>
12 #include <fstream>
13 #include <string>
14 #include "TString.h"
15 
16 using namespace Muon;
17 
19  const std::string& n,
20  const IInterface* p ) :
21  AthAlgTool(t,n,p)
22 {
23  declareInterface<INSWCalibSmearingTool>(this);
24 }
25 
27 {
28  ATH_MSG_DEBUG("In initialize()");
29  ATH_CHECK(m_idHelperSvc.retrieve());
30 
31  if ( !(m_idHelperSvc->hasMM() || m_idHelperSvc->hasSTGC() ) ) {
32  ATH_MSG_ERROR("MM or STGC not part of initialized detector layout");
33  return StatusCode::FAILURE;
34  }
35 
36 
37  if (m_readEfficiencyFromFile || m_readGainFractionFromFile) {
38  ATH_CHECK(readHighVoltagesStatus());
39  }
40 
41  return StatusCode::SUCCESS;
42 }
43 
44 //
45 // check if a hit is acceppted
46 //
47 StatusCode Muon::NSWCalibSmearingTool::isAccepted(const Identifier id, bool& accepted, CLHEP::HepRandomEngine* rndmEngine) const
48 {
49  accepted = true;
50 
51  int etaSector = 0;
52  int phiSector = 0;
53  int gasGap = 0;
54 
55  if (!getIdFields(id,etaSector,phiSector,gasGap)) {
56  ATH_MSG_WARNING("Invalid identifier");
57  return StatusCode::SUCCESS;
58  }
59 
61  float efficiencyCut = 0.0;
62  if ( !(m_readEfficiencyFromFile || m_readGainFractionFromFile) ) {
63  efficiencyCut = m_clusterEfficiency.value()[gasGap-1];
64  }
65  else {
66  // get the efficiency from the HV map and the parametrization
67  Identifier pcb_id;
68  if ( !getPCBIdentifier(id, pcb_id) ) {
69  ATH_MSG_ERROR("Could not convert the id " << m_idHelperSvc->toString(id) << " to a PCB identifier" );
70  return StatusCode::FAILURE;
71  }
72 
73  // get the HV
74  std::map<Identifier,float>::const_iterator it = m_hvMap.find(pcb_id);
75  if ( it != m_hvMap.end() ) {
76  double hv = it->second;
77  efficiencyCut = getMMEfficiencyFromHV(hv);
78  }
79  else {
80  ATH_MSG_WARNING("PCB Id not found in the HV map " << m_idHelperSvc->toString(pcb_id));
81  accepted = true;
82  return StatusCode::SUCCESS;
83  }
84  }
85 
87  if ( CLHEP::RandFlat::shoot(rndmEngine, 0. , 1.) > efficiencyCut ) {
88  accepted = false;
89  }
90 
91  return StatusCode::SUCCESS;
92 
93 }
94 
95 
96 //
97 // smear only the charge
98 //
99 StatusCode Muon::NSWCalibSmearingTool::smearCharge(Identifier id, float& charge, bool& accepted, CLHEP::HepRandomEngine* rndmEngine) const
100 {
101 
102  ATH_MSG_DEBUG("Smearing the strips charge");
103 
104  int etaSector = 0;
105  int phiSector = 0;
106  int gasGap = 0;
107 
108  if (!getIdFields(id,etaSector,phiSector,gasGap)) {
109  ATH_MSG_WARNING("Invalid identifier");
110  return StatusCode::SUCCESS;
111  }
113 
114 
115  float efficiencyCut = 0.0;
116  if ( !(m_readEfficiencyFromFile || m_readGainFractionFromFile) ) {
117  efficiencyCut = m_clusterEfficiency.value()[gasGap-1];
118  }
119  else {
120  // get the efficiency from the HV map and the parametrization
121  Identifier pcb_id;
122  if ( !getPCBIdentifier(id, pcb_id) ) {
123  ATH_MSG_ERROR("Could not convert the id " << m_idHelperSvc->toString(id) << " to a PCB identifier" );
124  return StatusCode::FAILURE;
125  }
126  // get the HV
127  std::map<Identifier,float>::const_iterator it = m_hvMap.find(pcb_id);
128  if ( it != m_hvMap.end() ) {
129  double hv = it->second;
130  efficiencyCut = getMMEfficiencyFromHV(hv);
131  }
132  else {
133  ATH_MSG_WARNING("PCB Id not found in the HV map " << m_idHelperSvc->toString(pcb_id));
134  accepted = true;
135  return StatusCode::SUCCESS;
136  }
137  }
138 
139  if ( m_phiSectors.value()[phiSector-1] && m_etaSectors.value()[etaSector-1] ) {
140  // smear charge
141  double chargeSmear = m_chargeSmear.value()[gasGap-1];
142  charge = charge + CLHEP::RandGaussZiggurat::shoot(rndmEngine,0.0, chargeSmear);
143 
144  // check if the single strip can be accepted
145  accepted = true;
146  if ( CLHEP::RandFlat::shoot(rndmEngine, 0. , 1.) > efficiencyCut ) {
147  accepted = false;
148  }
149  }
150 
151  return StatusCode::SUCCESS;
152 }
153 
154 //
155 // smear time and charge
156 //
157 StatusCode Muon::NSWCalibSmearingTool::smearTimeAndCharge(Identifier id, float& time, float& charge, bool& accepted, CLHEP::HepRandomEngine* rndmEngine) const
158 {
159 
160  if ( m_idHelperSvc->issTgc(id) ) {
161  ATH_MSG_ERROR("Can't smear time for the STGC's");
162  return StatusCode::FAILURE;
163  }
164 
165  int etaSector = 0;
166  int phiSector = 0;
167  int gasGap = 0;
168 
169  if (!getIdFields(id,etaSector,phiSector,gasGap)) {
170  ATH_MSG_WARNING("Invalid identifier");
171  return StatusCode::SUCCESS;
172  }
173 
174  if ( m_phiSectors.value()[phiSector-1] && m_etaSectors.value()[etaSector-1] ) {
175 
176  // smear time and charge
177  double timeSmear = m_timeSmear.value()[gasGap-1];
178  double chargeSmear = m_chargeSmear.value()[gasGap-1];
179 
180  time = time + CLHEP::RandGaussZiggurat::shoot(rndmEngine,0.0, timeSmear);
181  charge = charge + CLHEP::RandGaussZiggurat::shoot(rndmEngine,0.0, chargeSmear);
182 
183  // check if the RDO can be accepted
184  accepted = true;
185  if ( CLHEP::RandFlat::shoot(rndmEngine, 0. , 1.) > m_channelEfficiency.value()[gasGap-1] ) {
186  accepted = false;
187  }
188  }
189 
190  return StatusCode::SUCCESS;
191 }
192 
193 //
194 // get the fraction of the actual gain for a given gap
195 //
197 {
198  int etaSector = 0;
199  int phiSector = 0;
200  int gasGap = 0;
201 
202  if (!getIdFields(id,etaSector,phiSector,gasGap)) {
203  ATH_MSG_WARNING("Invalid identifier");
204  return StatusCode::SUCCESS;
205  }
206 
207  gainFraction = 1.0;
208 
209  if(!m_readGainFractionFromFile) {
210  if ( m_phiSectors.value()[phiSector-1] && m_etaSectors.value()[etaSector-1] ) {
211  gainFraction = m_gainFraction.value()[gasGap-1];
212  }
213  }
214  else {
215  float hv = getHighVoltage(id);
216  if(hv == -2.0) { // could not convert id to PCB id
217  return StatusCode::FAILURE;
218  }
219  else if(hv == -1.0) { // could not find PCB in HV map
220  gainFraction = 1;
221  }
222  else {
223  gainFraction=getMMGainFractionFromHV(hv);
224  ATH_MSG_DEBUG("Got gain fraction: "<< gainFraction << " for id " << m_idHelperSvc->toString(id));
225  }
226  }
227  return StatusCode::SUCCESS;
228 }
229 
230 
231 //
232 // get id fields for both STGC and MM
233 //
234 bool NSWCalibSmearingTool::getIdFields(const Identifier id, int& etaSector, int& phiSector, int& gasGap) const
235 {
236  if ( m_idHelperSvc->isMM(id) ) {
237  int multilayer = m_idHelperSvc->mmIdHelper().multilayer(id);
238  gasGap = (multilayer-1)*4+m_idHelperSvc->mmIdHelper().gasGap(id);
239  etaSector = m_idHelperSvc->mmIdHelper().stationEta(id);
240  phiSector = m_idHelperSvc->mmIdHelper().stationPhi(id);
241  // transform the eta sector
242  etaSector < 0 ? etaSector = etaSector + 3 : etaSector = etaSector + 2;
243  }
244  else if ( m_idHelperSvc->issTgc(id) ) {
245  int multilayer = m_idHelperSvc->stgcIdHelper().multilayer(id);
246  gasGap = (multilayer-1)*4+m_idHelperSvc->stgcIdHelper().gasGap(id);
247  etaSector = m_idHelperSvc->stgcIdHelper().stationEta(id);
248  phiSector = m_idHelperSvc->stgcIdHelper().stationPhi(id);
249  // transform the eta sector
250  etaSector < 0 ? etaSector = etaSector + 4 : etaSector = etaSector + 3;
251  }
252  else {
253  ATH_MSG_WARNING("Wrong identifier: should be MM or STGC");
254  return false;
255  }
256 
257 
258  if ( phiSector < 1 || phiSector> (int) m_phiSectors.value().size()
259  || etaSector < (int) (-m_etaSectors.value().size()) || etaSector> (int) m_etaSectors.value().size() || etaSector==0
260  || gasGap < 1 || gasGap> (int) m_timeSmear.value().size() || gasGap>(int) m_chargeSmear.value().size() ) {
261  ATH_MSG_WARNING("Wrong phi, eta sector, or gasGap number: " << phiSector << " "
262  << etaSector << " " << gasGap << "Size of m_chargeSmear " << m_chargeSmear.value().size() << " size of m_etaSectors "<< m_etaSectors.value().size());
263  return false;
264  }
265 
266  return true;
267 }
268 
269 //
270 // get the high voltage from a strip identifier
272 {
273  Identifier pcbId;
274  bool foundPCB = getPCBIdentifier(stripId,pcbId);
275  if ( !foundPCB ) {
276  ATH_MSG_ERROR("Identifier " << m_idHelperSvc->toString(stripId) << " not converted" );
277  return -2.0;
278  }
279 
280  double hv = -1.0;
281  std::map<Identifier,float>::const_iterator it = m_hvMap.find(pcbId);
282  if (it == m_hvMap.end() ) {
283  ATH_MSG_DEBUG("Identifier " << m_idHelperSvc->toString(pcbId) << " not found in the map" );
284  return -1.0;
285  }
286 
287  hv = (*it).second;
288  return hv;
289 }
290 
291 
292 //
293 // get the efficiency from the parametrization vs HV for the MM
295 {
296 
297  // sigmoid to paramtrize efficiency (initial values from BB5 measurements)
298  double eff = 1.0/(1+exp(-0.0551*(hv-510.54)));
299 
300  return eff;
301 }
302 
303 //
304 // get the gain fraction from the parametrization vs HV for the MM
306 {
307 
308  // initial values from BB5 measurements. Scale cluster charge with respect to 570 V
309  return std::exp(-8.87971 + 0.0224561 * hv) / std::exp(-8.87971 + 0.0224561 * 570);
310 
311 }
312 
313 
314 
316 // get the PCB identifier as the identifier of the central strip ( 512 ) of each PCB (MM only)
319 {
320 
321  if ( m_idHelperSvc->isMM(id) ) {
322  // get the channel number
323  int channel = m_idHelperSvc->mmIdHelper().channel(id);
324  int pcb_strip = channel/1024;
325  pcb_strip = pcb_strip * 1024 + 512;
326 
327  int stationName = m_idHelperSvc->mmIdHelper().stationName(id);
328  int stationEta = m_idHelperSvc->mmIdHelper().stationEta(id);
329  int stationPhi = m_idHelperSvc->mmIdHelper().stationPhi(id);
330 
331  int multilayer = m_idHelperSvc->mmIdHelper().multilayer(id);
332  int gasGap = m_idHelperSvc->mmIdHelper().gasGap(id);
333 
334  pcb_id = m_idHelperSvc->mmIdHelper().channelID(stationName,stationEta,stationPhi,multilayer,gasGap,pcb_strip);
335  }
336  else {
337  ATH_MSG_WARNING("Requesting PCB id for STGC");
338  return false;
339  }
340 
341  return true;
342 }
343 
344 //
345 // read the MM HV map from a set of ascii files
346 //
348 {
349 
350  std::string fileNamesA[16] = {"A01.txt","A02.txt","A03.txt","A04.txt",
351  "A05.txt","A06.txt","A07.txt","A08.txt",
352  "A09.txt","A10.txt","A11.txt","A12.txt",
353  "A13.txt","A14.txt","A15.txt","A16.txt" };
354 
355  for (int ifile = 0 ; ifile<16 ; ++ifile) {
356 
357  std::string fileName = PathResolverFindCalibFile(Form("NSWCalibTools/210128_initial/%s", fileNamesA[ifile].c_str()));
358 
359  std::ifstream file(fileName,std::ios::in);
360  if ( !file.is_open() ) {
361  ATH_MSG_DEBUG("HV File " << fileNamesA[ifile] << " not available " );
362  continue;
363  }
364  ATH_MSG_INFO("Reading HV from configuration file: " << fileName);
365 
366  //LM sector
367  //Layer PCB HV_left HV_right HV_min
368  //LM1 - IP
369 
370  std::string line;
371  bool isLM,isSM,isIP,isHO;
372  int stationName,stationEta,stationPhi,multilayer,gasGap,HVval;
373  int side = 0;
374  std::string layerId[4] = {"L1","L2","L3","L4"};
375 
376  int endPCB=0;
377 
378  getline(file,line);
380  getline(file,line);
382 
383  while ( getline(file,line) ) {
385 
386  isIP=false;
387  isHO=false;
388 
389  std::string secName = fileNamesA[ifile].substr(0,2);
390 
391  if ( secName.substr(0,1)=="A" ) side = +1;
392  else if ( secName.substr(0,1)=="C" ) side = -1;
393  else {
394  ATH_MSG_ERROR("ERROR side not defined");
395  return StatusCode::FAILURE;
396  }
397  int phiSec = std::stoi(fileNamesA[ifile].substr(1,2));
398  stationPhi = (phiSec-1)/2+1;
399 
400  size_t fLM = line.find("LM");
401  size_t fSM = line.find("SM");
402  isLM = (fLM!=std::string::npos);
403  isSM = (fSM!=std::string::npos);
404 
405  // get layer 1 from the line with the module name
406  if ( isLM || isSM ) {
407  if ( isSM ) {
408  stationEta = side*std::stoi(line.substr(fSM+2,1));
409  }
410  else if ( isLM ) {
411  stationEta = side*std::stoi(line.substr(fLM+2,1));
412  }
413 
415  if (stationEta==1) endPCB=5;
416  else if (stationEta==2) endPCB=3;
417  else {
418  ATH_MSG_ERROR("wrong stationEta value = " << stationEta);
419  }
420 
421  isSM ? stationName=55 : stationName=56;
422 
423  std::size_t fIP = line.find("IP");
424  isIP = (fIP!=std::string::npos);
425  std::size_t fHO = line.find("HO");
426  isHO = (fHO!=std::string::npos);
427  if ( !isIP && !isHO ) {
428  ATH_MSG_ERROR("ERROR multilayer id not found (IP/HO) ");
429  return StatusCode::FAILURE;
430  }
431  else if ( isIP && isHO ) {
432  ATH_MSG_ERROR("ERROR multilayer id duplicated (IP and HO) ");
433  return StatusCode::FAILURE;
434  }
435  else if ( isIP ) {
436  multilayer = 1;
437  }
438  else if ( isHO ) {
439  multilayer = 2;
440  }
441 
442  // now read the various layers
443  //int ilayer = 1;
444  //int ipcb = 1;
445  for (int ilayer = 1; ilayer <= 4; ilayer++) {
446  for (int ipcb = 1; ipcb <= endPCB; ipcb++) {
447  getline(file,line);
449 
450  std::istringstream elem(line);
451  std::vector<std::string> elements;
452 
453  while(elem) {
454  std::string subs_elem;
455  elem >> subs_elem;
456  if (!subs_elem.empty()) elements.push_back(subs_elem);
457  }
458 
459  gasGap = std::stoi(elements[0]);
460  int readed_pcb = std::stoi(elements[1]);
461  if (gasGap != ilayer || readed_pcb != ipcb) {
462  ATH_MSG_ERROR("Layer or pcb wrong!");
463  return StatusCode::FAILURE;
464  }
465 
466  HVval=std::stoi(elements[4]);
467 
468  ATH_MSG_DEBUG("PCB done, stationName, stationEta, stationPhi, ml, layer, pcb, hv: "
469  << stationName<< " " << stationEta << " " << stationPhi << " " << multilayer << " "
470  << ilayer << " " << ipcb << " " << HVval );
471 
472  int chanNum = (ipcb-1)*1024+512;
474  Identifier pcbId = m_idHelperSvc->mmIdHelper().channelID(stationName,stationEta,stationPhi,
475  multilayer,ilayer,chanNum);
476  float hv = (float)HVval;
477  m_hvMap.insert(std::pair<Identifier,float>(pcbId,hv));
478 
479  }
480  if ( ilayer == 4 ) {
481  getline(file,line);
483  }
484  } // loop on the layers
485  }
486  }
487  } // loop on the files
488  return StatusCode::SUCCESS;
489 }
Muon::NSWCalibSmearingTool::getPCBIdentifier
bool getPCBIdentifier(const Identifier id, Identifier &pcb_id) const
Definition: NSWCalibSmearingTool.cxx:318
Muon::NSWCalibSmearingTool::m_phiSectors
Gaudi::Property< std::vector< bool > > m_phiSectors
Definition: NSWCalibSmearingTool.h:65
dumpTgcDigiDeadChambers.gasGap
list gasGap
Definition: dumpTgcDigiDeadChambers.py:33
checkFileSG.line
line
Definition: checkFileSG.py:75
plotting.yearwise_efficiency.channel
channel
Definition: yearwise_efficiency.py:24
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
NSWCalibSmearingTool.h
dumpTgcDigiDeadChambers.stationName
dictionary stationName
Definition: dumpTgcDigiDeadChambers.py:30
Muon::NSWCalibSmearingTool::smearTimeAndCharge
StatusCode smearTimeAndCharge(const Identifier id, float &time, float &charge, bool &accepted, CLHEP::HepRandomEngine *rndmEngine) const override
Definition: NSWCalibSmearingTool.cxx:157
skel.it
it
Definition: skel.GENtoEVGEN.py:396
Muon::NSWCalibSmearingTool::readHighVoltagesStatus
StatusCode readHighVoltagesStatus()
Definition: NSWCalibSmearingTool.cxx:347
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
Muon::NSWCalibSmearingTool::m_timeSmear
Gaudi::Property< std::vector< double > > m_timeSmear
Definition: NSWCalibSmearingTool.h:57
Muon::NSWCalibSmearingTool::initialize
virtual StatusCode initialize() override
Definition: NSWCalibSmearingTool.cxx:26
Muon
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
Definition: TrackSystemController.h:45
drawFromPickle.exp
exp
Definition: drawFromPickle.py:36
Muon::NSWCalibSmearingTool::getMMGainFractionFromHV
double getMMGainFractionFromHV(double hv) const
Definition: NSWCalibSmearingTool.cxx:305
TRT::Hit::side
@ side
Definition: HitInfo.h:83
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
FortranAlgorithmOptions.fileName
fileName
Definition: FortranAlgorithmOptions.py:13
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
checkCoolLatestUpdate.chanNum
chanNum
Definition: checkCoolLatestUpdate.py:27
Muon::NSWCalibSmearingTool::isAccepted
virtual StatusCode isAccepted(const Identifier id, bool &accepted, CLHEP::HepRandomEngine *rndmEngine) const override
Definition: NSWCalibSmearingTool.cxx:47
beamspotman.n
n
Definition: beamspotman.py:731
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
file
TFile * file
Definition: tile_monitor.h:29
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Muon::NSWCalibSmearingTool::getHighVoltage
double getHighVoltage(Identifier id) const
Definition: NSWCalibSmearingTool.cxx:271
PathResolver.h
charge
double charge(const T &p)
Definition: AtlasPID.h:756
Muon::NSWCalibSmearingTool::getGainFraction
virtual StatusCode getGainFraction(const Identifier id, float &charge) override
Definition: NSWCalibSmearingTool.cxx:196
PathResolverFindCalibFile
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Definition: PathResolver.cxx:431
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Muon::NSWCalibSmearingTool::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: NSWCalibSmearingTool.h:55
Muon::NSWCalibSmearingTool::m_chargeSmear
Gaudi::Property< std::vector< double > > m_chargeSmear
Definition: NSWCalibSmearingTool.h:58
dqt_zlumi_alleff_HIST.eff
int eff
Definition: dqt_zlumi_alleff_HIST.py:113
LArCellNtuple.ifile
string ifile
Definition: LArCellNtuple.py:133
AthAlgTool
Definition: AthAlgTool.h:26
Muon::NSWCalibSmearingTool::smearCharge
StatusCode smearCharge(const Identifier id, float &charge, bool &accepted, CLHEP::HepRandomEngine *rndmEngine) const override
Definition: NSWCalibSmearingTool.cxx:99
Muon::NSWCalibSmearingTool::m_hvMap
std::map< Identifier, float > m_hvMap
Definition: NSWCalibSmearingTool.h:73
Muon::NSWCalibSmearingTool::NSWCalibSmearingTool
NSWCalibSmearingTool(const std::string &, const std::string &, const IInterface *)
Definition: NSWCalibSmearingTool.cxx:18
Muon::NSWCalibSmearingTool::m_etaSectors
Gaudi::Property< std::vector< bool > > m_etaSectors
Definition: NSWCalibSmearingTool.h:66
Muon::NSWCalibSmearingTool::getMMEfficiencyFromHV
double getMMEfficiencyFromHV(double hv) const
Definition: NSWCalibSmearingTool.cxx:294
readCCLHist.float
float
Definition: readCCLHist.py:83
Muon::NSWCalibSmearingTool::getIdFields
bool getIdFields(const Identifier id, int &etaSector, int &phiSector, int &gasGap) const
Definition: NSWCalibSmearingTool.cxx:234
Identifier
Definition: IdentifierFieldParser.cxx:14