ATLAS Offline Software
Loading...
Searching...
No Matches
CscCalcPed.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "CscCalcPed.h"
6
7#include "GaudiKernel/Chrono.h"
14
15#include "TF1.h"
16
17#include <iostream>
18#include <fstream>
19#include <inttypes.h>
20
21namespace MuonCalib {
22
23 CscCalcPed::CscCalcPed(const std::string& name, ISvcLocator* pSvcLocator) :
24 AthAlgorithm(name,pSvcLocator),
26 m_numBits(12),
27 m_bitProds(nullptr),
28 m_bitCorrelation(nullptr),
29 m_peds(nullptr),
30 m_noises(nullptr),
31 m_rmses(nullptr),
32 m_f001s(nullptr),
33 m_onlineTHoldBreaches(nullptr),
34 m_eventCnt(0),
35 m_crossTalkFix(nullptr)
36 {
37 declareProperty("OutputFile", m_outputFileName = "output.cal");
38 declareProperty("TitlePrefix",m_titlePrefix = ""); //Prefix appended to title of histograms and graphs
39 declareProperty("TitlePostfix",m_titlePostfix = ""); //Prefix appended to title of histograms and graphs
40 declareProperty("PedAmpHighBound", m_ampHistHighBound = 2600);
41 declareProperty("PedAmpLowBound", m_ampHistLowBound = 1800);
42 declareProperty("PedAmpNumBins", m_ampHistNumBins = 800);
43 declareProperty("ExpectedChamberLayer", m_expectedChamberLayer = 2);
44 declareProperty("ThresholdMultiplier", m_thresholdMultiplier = 3.1);
45 declareProperty("DoBitHists", m_doBitHists = false);
46 declareProperty("CalOutputVersion", m_calOutputVersion="03-00");
47 declareProperty("DoCorrelation", m_doCorrelation = false);
48
49 declareProperty("DoSampHists", m_doSampleHists = false);
50 declareProperty("NumSamplesExpected", m_numSamplesExpected = 4);
51 declareProperty("DoF001", m_doF001 = true);
52
53 declareProperty("OnlineCalibFile", m_onlineDbFile = "", "File with data currently stored in online configuration database");
54 declareProperty("CompareOnlineCalibFile",m_doOnlineDbFile = true, "Compare new to online data?");
55
56
57 //Can't do correlation without bitHists
58 if(!m_doBitHists){
59 m_doCorrelation = false;
60 }
61 }
62
64 {
65 ATH_MSG_INFO("CscCalcPed::initialize() called");
66
68 ATH_MSG_FATAL("Either specify an OnlineCalibFile or set CompareOnlineCalibFile to false");
69 return StatusCode::FAILURE;
70 }
71
72 //*******Register services and tools *********/
74
75 ATH_CHECK(m_idHelperSvc.retrieve());
76
77 ATH_CHECK(m_readKey.initialize());
78
79 m_chronoSvc = service("ChronoStatSvc");
80 ATH_CHECK(m_chronoSvc.isValid());
81
83
84 // Histograms are owned by ROOT.
85 m_ampHists.clear();
86 if(m_doSampleHists) m_sampHists.clear();
87 if(m_doBitHists) m_bitHists.clear();
88
89 //Loop through ids to find out what hash range we're working on (in case we're using some
90 //unusual geometry)
91 const std::vector<Identifier> &ids = m_idHelperSvc->cscIdHelper().idVector();
92
93
95
96 for(const auto &thisChamberId: ids)
97 {
98 std::vector<Identifier> stripVect;
99 m_idHelperSvc->cscIdHelper().idChannels(thisChamberId,stripVect);
100
101
102
103 for(const auto & thisStrip: stripVect)
104 {
105 IdentifierHash stripHash;
106 m_idHelperSvc->cscIdHelper().get_channel_hash(thisStrip,stripHash);
107 if((unsigned int)stripHash > m_maxStripHash)
108 m_maxStripHash = (int)stripHash;
109 }//End strip loop
110 }//end chamber loop
111
112
113 //Now creating ampHists. It wasn't done in last loop since there
114 //is no gaurantee that it will come out in strip order, and we assume
115 //later that m_ampHists's index = stripHash
116 ATH_MSG_DEBUG("Preparing ampHists. Only allowing those for " << " chamberLayer " << m_expectedChamberLayer);
117 for(unsigned int stripItr = 0 ; stripItr <=m_maxStripHash; stripItr++)
118 {
119
120 IdentifierHash stripHash =stripItr;
121 Identifier stripId;
122 IdContext channelContext = m_idHelperSvc->cscIdHelper().channel_context();
123 m_idHelperSvc->cscIdHelper().get_id(stripHash, stripId, &channelContext);
124
125 int chamLayer = m_idHelperSvc->cscIdHelper().chamberLayer(stripId);
126 if(chamLayer == m_expectedChamberLayer) //Only second chamber layer exists
127 {
128 int stationEta = m_idHelperSvc->cscIdHelper().stationEta(stripId);
129 int stationPhi = m_idHelperSvc->cscIdHelper().stationPhi(stripId);
130 int stripNumber = m_idHelperSvc->cscIdHelper().strip(stripId);
131 int wireLayer = m_idHelperSvc->cscIdHelper().wireLayer(stripId);
132 char orientation = m_idHelperSvc->cscIdHelper().measuresPhi(stripId) ? 'Y':'X';
133
134
135 char name[30],titleSeed[600];
136 TH1I* hist = nullptr;
137
138 int stationName = m_idHelperSvc->cscIdHelper().stationName(stripId);
139 //Amplitude histogram
140 sprintf(name, "ampHist%u",stripItr);
141 sprintf(titleSeed, "Amplitude Histogram for eta %d, sector %d, layer %d%c, strip %d",
142 stationEta,(2*stationPhi+50 - stationName),wireLayer,orientation,stripNumber);
143 std::string title = m_titlePrefix + titleSeed + m_titlePostfix;
144
145 hist = new TH1I(name,title.c_str(),m_ampHistNumBins,m_ampHistLowBound,
147 hist->GetXaxis()->SetTitle("Amplitude (ADC value)");
148 hist->GetYaxis()->SetTitle("Counts");
149 m_ampHists.push_back(hist);
150
151 if(m_doSampleHists) {
152 std::vector<TH1I*> tempVect;
153 for(int cnt = 0; cnt < m_numSamplesExpected ; cnt++) {
154 sprintf(name, "sampHist%u_%d",stripItr,cnt);
155 sprintf(titleSeed, "Amplitude Histogram for eta %d, sector %d, layer %d%c, strip %d, sample %d",
156 stationEta,(2*stationPhi+50 - stationName),wireLayer,orientation,stripNumber,cnt);
157
158 hist = new TH1I(name,title.c_str(),m_ampHistNumBins,m_ampHistLowBound,
160 tempVect.push_back(hist);
161
162 }
163 m_sampHists.push_back(std::move(tempVect));
164 }
165
166 if(m_doBitHists)
167 {
168 //Bit histogram (for looking for stuck-bits)
169 sprintf(name, "bitHist%u",stripItr);
170 sprintf(titleSeed, "Bit histogram for eta %d, sector %d, layer %d%c strip %d",
171 stationEta,(2*stationPhi+50 - stationName),wireLayer,orientation,stripNumber);
172 title = m_titlePrefix + titleSeed + m_titlePostfix;
173 hist = new TH1I(name, title.c_str(), m_numBits, 0, m_numBits); //12 bits
174 hist->GetXaxis()->SetTitle("Bit");
175 hist->GetYaxis()->SetTitle("Counts");
176 m_bitHists.push_back(hist);
177 if(m_doCorrelation) {
178 (*m_bitProds)[stripItr] = new TH2F(TString::Format("bitProds%d",stripItr),"Bit products", m_numBits,0,m_numBits, m_numBits, 0, m_numBits);
179
180 }
181 }
182 }
183 else
184 {
185 m_ampHists.push_back(nullptr);
186 if(m_doBitHists) m_bitHists.push_back(nullptr);
187 if(m_doSampleHists) m_sampHists.push_back(std::vector<TH1I*>());
188 }
189 }//end strip loop
190
191 //Setup result collections. These will be passed to storegate for any monitoring later
192 m_peds = new CscCalibResultCollection("ped");
193 m_noises = new CscCalibResultCollection("noise");
195 if(m_doF001){
196 ATH_MSG_DEBUG("Doing f001");
197 //For f001 values
198 m_f001s = new CscCalibResultCollection("f001");
199
200 //Initializing for comparing new values to an online database file
202
203 //How many samples failed the online threshold test of f001 +2*RMS
204 //(f001 and RMS read from a file from online configuration db)
205 m_onlineTHoldBreaches = new CscCalibResultCollection("OnlTHoldBreaches");
206
207
208
209 //Vector we use to count the online thresholds
211
212 //Retrieve current online thresholds
214 std::ifstream ifile; ifile.open(m_onlineDbFile.c_str());
215 if(!ifile.is_open()){
216 ATH_MSG_FATAL("Failed to open online database file " << m_onlineDbFile);
217 return StatusCode::FAILURE;
218 }
219 std::string buf;
220 ifile >> buf; // skip 32 at start of file
221 unsigned int onlineId;
222 unsigned int hashId;
223 double rms;
224 double f001;
225
226 if(!ifile){
227 ATH_MSG_FATAL("Problem with file after one word read in.");
228 return StatusCode::FAILURE;
229 }
230
231
232 ATH_MSG_DEBUG("Reading in online thresholds from file " << m_onlineDbFile);
233 ATH_MSG_DEBUG("First (junk) word: " << buf);
234 int chanCnt = 0;
235 while(ifile >> std::hex >> onlineId >> std::dec) {
236 chanCnt++;
237 onlineToOfflineHashId(onlineId,hashId);
238
239 ifile >> buf >> buf >> buf >> buf >> rms >> buf >> f001;
240 double thold = f001 + 2*rms;
241 ATH_MSG_VERBOSE("onlid: " << std::hex << onlineId << std::dec << " hash: " << hashId << " rms: " << rms << " f001: " << f001 << " thold: " << thold);
242 m_onlineThresholds.at(hashId) = thold;
243 if(!ifile)
244 ATH_MSG_VERBOSE("input file is done, ready to close!");
245 else
246 ATH_MSG_VERBOSE("Input file still good!");
247
248
249 }
250 if(chanCnt != 30720){
251 ATH_MSG_FATAL("Did not retrieve expected 30720 channels from online database! Retrieved: " << chanCnt);
252 ATH_MSG_FATAL("Last onlineId read: " << std::hex << onlineId << std::dec);
253 return StatusCode::FAILURE;
254 }
255
256 }//if m_doOnlineDBFile
257 }//db file
258
259 ATH_MSG_INFO("highest strip hash id is " << m_maxStripHash);
260
261 //If we're doing correlation plots, set up the product histogram array
262 if(m_doCorrelation){
264 m_bitProds->resize(m_maxStripHash+1);
265 }
266
267
268
269
270
271 ATH_MSG_INFO("m_prods value: " << m_bitProds << "\ndoCorrelation" << m_doCorrelation);
272 return StatusCode::SUCCESS;
273 }
274
275 //Execute loops through all strips and fills histograms
277 {
278 ATH_MSG_DEBUG("Begin execute");
279 //collectEventInfo collects infomation about each event by filling ampHistCollection and peaktHist.
280 StatusCode sc = collectEventInfo();
281
282 if(!sc.isSuccess())
283 {
284 ATH_MSG_ERROR("There was an error collecting information from the RDO this event.");
285 return StatusCode::RECOVERABLE;
286 }
287 ATH_MSG_DEBUG("End execute");
288 return StatusCode::SUCCESS;
289 } //end execute()
290
291 StatusCode CscCalcPed::finalize() {
292 if(m_eventCnt ==0)
293 {
294 ATH_MSG_FATAL("No events processed!");
295 return StatusCode::FAILURE;
296 }
297 else
298 ATH_MSG_INFO("In finalize() after analyzing " << m_eventCnt << " events ");
299
300 StatusCode sc;
301
302 ATH_MSG_INFO("not dump all hists!");
303
304 //calculateParameters() finds means and fits gain curves from the data in
305 //m_ampHistCollection and/or m_peaktHist
307 if(!sc.isSuccess())
308 {
309 ATH_MSG_FATAL("Calculation of parameters failed!");
310 return StatusCode::FAILURE;
311 }
312 ATH_MSG_DEBUG("Finished calculating parameters");
313
314
315 //writeCalibrationFile() writes the calculated parameters into a calibration fie.
317 if(!sc.isSuccess())
318 {
319 ATH_MSG_FATAL("Calculation of parameters failed!");
320 return StatusCode::FAILURE;
321 }
322
323 //Record report (ampHists) and results to storegate for future algorithms
324 //like COOL database storage or monitoring to collect
326 if (!sc.isSuccess())
327 {
328 ATH_MSG_FATAL("Failed recording data in storegate");
329 return StatusCode::FAILURE;
330 }
331
332 ATH_MSG_INFO("Finished finalize");
333 return StatusCode::SUCCESS;
334 }//end finalize()
335
336
337 //Collect event info is run every event, gathering amplitutdes and peakting times.
339 {
340 //start the timer
341 Chrono chrono(m_chronoSvc,"collectEventInfo");
342
343
344 m_eventCnt++;
345 ATH_MSG_DEBUG("Collecting event info for event " << m_eventCnt);
346 //Below might need to be changed depending on how we get data
347 const CscRawDataContainer* rawDataContainer;
348 StatusCode sc_read = evtStore()->retrieve(rawDataContainer, "CSCRDO");
349 if (sc_read != StatusCode::SUCCESS)
350 {
351 ATH_MSG_FATAL("Could not find event");
352 return StatusCode::FAILURE;
353 }
354
355 ATH_MSG_VERBOSE("Retrieved RDO from storegate ");
356
357 if(rawDataContainer->size() == 0)
358 {
359 ATH_MSG_FATAL("no rods in RDO!");
360 return StatusCode::FAILURE;
361 }
362
363 ATH_MSG_VERBOSE("There are " << rawDataContainer->size() << " rods in the RDO");
364
365 IdContext channelContext = m_idHelperSvc->cscIdHelper().channel_context();
366
367 //Loop over RODs (data from 2 chambers), each of which is in
368 //a single CscRawaData collection.
369 //Names of timers used in this loop
370 static const std::string rodChronoStr{"RodItr"};
371 static const std::string clusterChronoStr{"ClusterItr"};
372 static const std::string stripChronoStr{"stripItr"};
373 static const std::string afterId1Str{"afterID1"};
374 static const std::string afterId2Str{"afterID2"};
375 //
376 for(const auto rod : *rawDataContainer)
377 {
378 Chrono chronoRod(m_chronoSvc,rodChronoStr);
379 ATH_MSG_VERBOSE("Examining a ROD");
380
381 ATH_MSG_VERBOSE("There are " << rod->size() << " clusters in the ROD");
382 if(rod->size() >0)
383 {
384 //Loop over strips in rod
385
386
387 for(const auto cluster: *rod)
388 {
389 Chrono chronoClus(m_chronoSvc,clusterChronoStr);
390 int numStrips = cluster->width();
391 int samplesPerStrip = (cluster->samples()).size()/numStrips;
392
393 ATH_MSG_VERBOSE("About to collect info from " << numStrips << " strips");
394 for(int stripItr = 0; stripItr <numStrips; stripItr++)
395 {
396
397 Chrono chronoStrip(m_chronoSvc,stripChronoStr);
398 // WP Added
399 Identifier channelId =m_cscRdoDecoderTool->channelIdentifier(cluster, &m_idHelperSvc->cscIdHelper(), stripItr);
400 IdentifierHash cscChannelHashId;
401 m_idHelperSvc->cscIdHelper().get_channel_hash(channelId, cscChannelHashId);
402
404 int stripHash = cscChannelHashId;
405
406 Identifier stripId;
407 m_idHelperSvc->cscIdHelper().get_id(stripHash, stripId, &channelContext);
408
409
410 Chrono chronoAfterId(m_chronoSvc,afterId1Str);
411
412 if( m_idHelperSvc->cscIdHelper().chamberLayer(channelId) != m_expectedChamberLayer)
413 {
414 ATH_MSG_WARNING("Wrong chamber layer a hash ("
415 << stripHash << ") from the wrong multilayer has appeared in the data. Its string id is " << m_idHelperSvc->cscIdHelper().show_to_string(stripId)
416 << " " << m_idHelperSvc->cscIdHelper().show_to_string(channelId));
417
418 ATH_MSG_INFO("WP added (1) "
419 << m_idHelperSvc->cscIdHelper().stationEta(stripId) << " " << m_idHelperSvc->cscIdHelper().measuresPhi(stripId) << " "
420 << stripHash << " " << cscChannelHashId);
421
422 ATH_MSG_INFO("WP added (2) "
423 << m_idHelperSvc->cscIdHelper().stationEta(stripId) << " " << m_idHelperSvc->cscIdHelper().measuresPhi(stripId) << " "
424 << stripId << " " << channelId);
425
426 stripId = m_idHelperSvc->cscIdHelper().channelID(
427 m_idHelperSvc->cscIdHelper().stationName(stripId),
428 m_idHelperSvc->cscIdHelper().stationEta(stripId),
429 m_idHelperSvc->cscIdHelper().stationPhi(stripId),
430 2,
431 m_idHelperSvc->cscIdHelper().wireLayer(stripId),
432 m_idHelperSvc->cscIdHelper().measuresPhi(stripId),
433 m_idHelperSvc->cscIdHelper().strip(stripId)
434 );
435 IdentifierHash newHash;
436 m_idHelperSvc->cscIdHelper().get_channel_hash(stripId, newHash );
437 if (!newHash.is_valid())[[unlikely]]{
438 ATH_MSG_WARNING("Hash "<< newHash <<" is invalid");
439 continue;
440 }
441 stripHash = newHash;
442 ATH_MSG_DEBUG("New hash " << stripHash);
443 }
444 else{
445 if(m_idHelperSvc->cscIdHelper().measuresPhi(stripId))
446 ATH_MSG_VERBOSE(" good id Measures Phi");
447 else
448 ATH_MSG_VERBOSE(" good id is eta");
449 }
450
451 Chrono chronoAfterId2(m_chronoSvc, afterId2Str);
452
453 //Get samples. Each shows amplitude of pulse at different
454 //time slice.
455 std::vector<uint16_t> samples;
456 cluster->samples(stripItr,samplesPerStrip,samples);
457
458 //Test for threshold breach...
459 size_t sampCnt = 0;
460
461
462 for(const auto & thisSample: samples)
463 {
464 m_ampHists[stripHash]->Fill(thisSample);
466 m_sampHists[stripHash][sampCnt]->Fill(thisSample);
467 if(m_doBitHists && sampCnt==1)
468 {
469 TH2F* prodHist = nullptr;
470 if(m_bitProds)
471 prodHist = (*m_bitProds)[stripHash];
472 if(!fillBitHist(m_bitHists[stripHash],thisSample, prodHist).isSuccess())
473 ATH_MSG_WARNING("Failed recording bits for strip " << stripHash);
474 }//end if(m_doBitHists)
475
476 if(m_doOnlineDbFile){//m_doF001){
477 //test if any samples are obvoe the online threshold
478 if (thisSample > m_onlineThresholds[stripHash] ){
480 ATH_MSG_VERBOSE("StripHash: " << stripHash <<
481 " has online threshold breach. Sample: " << thisSample << " Thold: "
482 << m_onlineThresholds[stripHash]);
483 }
484 }
485 sampCnt++;
486 }//end Sample loop
487 }//end strip loop
488 }//end cluster loop
489 }
490 else
491 ATH_MSG_DEBUG("There is an empty rod (CscRawDataContainer).");
492 }//end rod loop
493 ATH_MSG_DEBUG("end collectEventInfo()");
494 return StatusCode::SUCCESS;
495 }// end collectEventInfo()
496
497
498 //Calculate parameters is called during finalize,
499 //calculates the parameter values.
501 {
502 Chrono chrono(m_chronoSvc,"calculateParameters");
503
504
505 //**********Calculate all the parameters from data collected during execute*****************//
506
507 for(unsigned int stripHash = 0 ;stripHash <= m_maxStripHash; stripHash++)
508 {
509 if(stripHash < 50 || stripHash%1000 == 0)
510 {
511 ATH_MSG_INFO("Analyzing strip with hash " << stripHash << " out of " << m_maxStripHash);
512 ATH_MSG_VERBOSE((float)clock()/((float)CLOCKS_PER_SEC) << " is the time");
513 }
514
515 TH1I * ampHist = m_ampHists[stripHash];
516 if(ampHist)
517 {
518 ATH_MSG_VERBOSE("Have data for strip hash " << stripHash);
519 if(ampHist->GetEntries() >0) //If strip wasn't tested, it won't have entries
520 {
521 //Following Schernau's work
522 float histMean = ampHist->GetMean();
523 float histRMS = ampHist->GetRMS();
524 float histRMSError = ampHist->GetRMSError();
525
526 float lowbound = histMean - 3*histRMS;
527 float highbound = histMean + 3*histRMS;
528 ATH_MSG_VERBOSE("About to fit...");
529
530 int result = ampHist->Fit("gaus","QL","",lowbound,highbound);
531 ATH_MSG_VERBOSE("Result is " << result);
532 TF1 * fittedFunction = ampHist->GetFunction("gaus");
533 double meanError = fittedFunction->GetParError(1);
534 double sigma = fittedFunction->GetParameter(2);
535 double sigmaError = fittedFunction->GetParError(2);
536 double chi2 = fittedFunction->GetChisquare();
537 int ndf = fittedFunction->GetNDF();
538
539 m_peds->push_back(new CscCalibResult(stripHash,histMean,meanError,chi2,ndf));
540 m_noises->push_back(new CscCalibResult(stripHash,sigma,sigmaError,chi2,ndf));
541 m_rmses->push_back(new CscCalibResult(stripHash,histRMS,histRMSError,0,0));
542
543
544
545 //Integrated threshold (f001) calculation
546 if(m_doF001){
547 int num = (int)ampHist->GetEntries();
548 int thr = ampHist->GetNbinsX() + 1; // start at overflow bin
549 double maxSum = 0.001*num; // 99.90 of pedestals under thr
550 //double maxSum = 0.0001*num; // 99.99 of pedestals under thr
551
552 double sum = 0;
553 do{
554 sum += ampHist->GetBinContent(thr);
555 thr--;
556 } while ((thr>0)&&(sum<maxSum));
557
558 //double threshold = ampHist->GetXaxis()->GetBinLowEdge(thr) +2; //For some reason +2 here matches Michael Schernau's +1
559 double threshold = ampHist->GetXaxis()->GetBinLowEdge(thr) +1; //For some reason +2 here matches Michael Schernau's +1
560 m_f001s->push_back(new CscCalibResult(stripHash,threshold,0,0,0));
561
563 m_onlineTHoldBreaches->push_back(new CscCalibResult(stripHash,m_onlineThresholdFailureCount[stripHash],0));
564 }
565 }
566 }
567 }
568 else
569 ATH_MSG_VERBOSE("Don't have data for strip hash " << stripHash);
570 }//end loop over strips
571
572
573 //don't need it anymore, clear ram taken by m_failure tests
574 ATH_MSG_DEBUG("Clearing m_onlineThresholdFailureCount");
576
577
578 ATH_MSG_INFO("Completed calculating parameters.");
579
580 return StatusCode::SUCCESS;
581 }//End calculateParameters()
582
583 //writeCalibrationFile() dumps the parameters to disk
585 {
586 Chrono chrono(m_chronoSvc,"writeFile");
587 //***Take conditions data held in summary histograms and print to the calibration file***//
588 ATH_MSG_INFO("Parameters calculated, preparing to output to file: " << m_outputFileName << " Types 1 and " << m_calOutputVersion);
589
591
592 if(m_calOutputVersion == "00-00"){
593 return calOutput0();
594 }
595 else if(m_calOutputVersion == "03-00") {
596 return calOutput3();
597 }
598 else{
599 ATH_MSG_WARNING("Don't know how to write calibration file version " << m_calOutputVersion);
600 return StatusCode::RECOVERABLE;
601 }
602 // this part of the code cannot be reached since one of the if statements before already exits the code
603 // return StatusCode::SUCCESS;
604 }
605
607
608 std::ofstream out;
609 out.open(m_outputFileName.c_str());
610 if(!out.is_open())
611 {
612 ATH_MSG_ERROR("Can't open file " << m_outputFileName.c_str());
613 return StatusCode::RECOVERABLE;
614 }
615
616 out << "00-00 ";
617 out << m_peds->size() << " ";
618 out << "ped ";
619 out << "noise ";
620 out << "rms ";
621 out << "END_HEADER\n";
622
623 ATH_MSG_DEBUG("Begining loop over all " << m_peds->size() << " channels data was collected for.");
624
625 //form is:hashID chamber LayerOrientationStrip parametervalue parametervalue
628 CscCalibResultCollection::iterator noiseItr = m_noises->begin();
630 for(;pedItr!= pedEnd;++pedItr,++noiseItr, ++rmsItr)//,tholdItr++)
631 {
632 int hashId = (*pedItr)->hashId();
633 double ped = (*pedItr)->value();
634 double noise = (*noiseItr)->value();
635 double rms = (*rmsItr)->value();
636
637 ATH_MSG_DEBUG("we're on hash " << hashId << " with pedestal " << ped << "and noise " << noise);
638 Identifier id;
639 IdContext channelContext = m_idHelperSvc->cscIdHelper().channel_context();
640 m_idHelperSvc->cscIdHelper().get_id(hashId,id, &channelContext);
641
642 Identifier chamberId = m_idHelperSvc->cscIdHelper().elementID(id);
643 if(!m_idHelperSvc->cscIdHelper().valid(chamberId))
644 {
645 ATH_MSG_WARNING(chamberId.getString() << " is not a valid id!");
646 ATH_MSG_WARNING("identifier is: " << m_idHelperSvc->cscIdHelper().show_to_string(chamberId));
647 }
648
649 IdentifierHash chamberHash;
650 m_idHelperSvc->cscIdHelper().get_module_hash(id,chamberHash);
651
652 //print out values.
653 out << hashId;
654 out <<" " << chamberHash;
655 out << " " << m_idHelperSvc->cscIdHelper().show_to_string(id) << " ";
656 out << " " << ped;
657 out << " " << noise;
658 out << " " << rms;
659 out << "\n" ;
660 } //end loop over hash Ids
661
662 out.close(); //done writing
663 ATH_MSG_INFO("File written");
664 return StatusCode::SUCCESS;
665 }//end calOutput0
666
667 //calOutput1 prints out calibration output file in format Michael Schernau's
668 //online software likes to read
670
671 std::ofstream out;
672 std::string onlineFileName = m_outputFileName + "_online";
673
674 out.open(onlineFileName.c_str());
675 if(!out.is_open())
676 {
677 ATH_MSG_ERROR("Can't open online file " << m_outputFileName.c_str());
678 return StatusCode::RECOVERABLE;
679 }
680
681 out << "32\n";
682
683 ATH_MSG_DEBUG("Begining loop over all " << m_peds->size() << " channels data was collected for.");
684
686 const CscCondDbData* readCdo{*readHandle};
687
688 //form is:hashID chamber LayerOrientationStrip parametervalue parametervalue
691 CscCalibResultCollection::iterator noiseItr = m_noises->begin();
694 for(;pedItr!= pedEnd;++pedItr,++noiseItr, ++rmsItr, ++f001Itr)//,tholdItr++)
695 {
696 int hashId = (*pedItr)->hashId();
697 double ped = (*pedItr)->value();
698 double noise = (*noiseItr)->value();
699 //double rms = (*rmsItr)->value();
700 double f001 = (*f001Itr)->value();
701
702 //double thold = (*tholdItr)->value();
703 std::string onlineHexId;
704
705 //Online ids are same as "string ids" used internally in COOL db.
706 readCdo->indexToStringId(&m_idHelperSvc->cscIdHelper(), hashId, "CHANNEL", onlineHexId).ignore();
707
708 ATH_MSG_DEBUG("we're on hash " << hashId << " with pedestal " << ped << "and noise " << noise);
709 Identifier id;
710 IdContext channelContext = m_idHelperSvc->cscIdHelper().channel_context();
711 m_idHelperSvc->cscIdHelper().get_id(hashId,id, &channelContext);
712
713 Identifier chamberId = m_idHelperSvc->cscIdHelper().elementID(id);
714 if(!m_idHelperSvc->cscIdHelper().valid(chamberId))
715 {
716 ATH_MSG_WARNING(chamberId.getString() << " is not a valid id!");
717 ATH_MSG_WARNING("identifier is: " << m_idHelperSvc->cscIdHelper().show_to_string(chamberId));
718 }
719
720 char orientationChar = (m_idHelperSvc->cscIdHelper().measuresPhi(id) ? 'Y':'X');
721
722
723 IdentifierHash chamberHash;
724 m_idHelperSvc->cscIdHelper().get_module_hash(id,chamberHash);
725
726 //print out values.
727 out.setf(std::ios::right);//right aligned columns
728 out << std::setfill('0') << std::setw(8) << onlineHexId;
729 out <<" "
730 << std::setw(2) << chamberHash << orientationChar << (m_idHelperSvc->cscIdHelper().wireLayer(id)-1)
731 <<" "
732 << std::setw(3) << m_idHelperSvc->cscIdHelper().strip(id) -1 << " " ;
733 out.setf(std::ios::fixed);
734
735
736 out << " " << std::setprecision(3) << std::setw(8) << ped << " 0000.00";
737 out << " " << std::setprecision(3) << std::setw(8) << noise << " 0000.000";
738 out << " " << f001;
739 out << "\n" ;
740 } //end loop over hash Ids
741
742 out.close(); //done writing
743 ATH_MSG_INFO("File written");
744 return StatusCode::SUCCESS;
745 }//end calOutput1
746
747 //calOutput3 outputs version 03-00 calibration files, which are what the most recent version
748 //of CscCoolReadWrite takes for input
750 std::ofstream out;
751 out.open(m_outputFileName.c_str());
752 if(!out.is_open())
753 {
754 ATH_MSG_ERROR("Can't open output 3 type file " << m_outputFileName.c_str() << " for writing ");
755 return StatusCode::RECOVERABLE;
756 }
757 out << "03-00 <END_HEADER>";
758
762 if(m_doF001)
764 out << "\n<END_FILE>";
765 out.close();
766
767 return StatusCode::SUCCESS;
768 }
769
770
771 //Outputs a single parameter in version 03-00
772 void CscCalcPed::outputParameter3(const CscCalibResultCollection & results, std::ofstream & out){
773
775 const CscCondDbData* readCdo{*readHandle};
776
777 out << "\n";
778 out << "<NEW_PAR> " << results.parName() << "\n";
779 std::string idString;
780
781 CscCalibResultCollection::const_iterator resItr = results.begin();
782 CscCalibResultCollection::const_iterator resEnd = results.end();
783 for(; resItr != resEnd; ++resItr){
784 unsigned int hashId = (*resItr)->hashId();
785 double value = (*resItr)->value();
786 std::string idString;
787
788 readCdo->indexToStringId(&m_idHelperSvc->cscIdHelper(), hashId, "CHANNEL", idString).ignore();
789
790 out << idString << " " << value << "\n";
791 }
792
793 out << "<END_PAR>" ;
794 }
795
796
797
798 //Record ampHist and calib results to storegate for monitoring and maybe other
799 //programs
801 {
802 StatusCode sc = StatusCode::SUCCESS;
803
804 bool thereIsAnError = false;
805
806 std::string histKey = "cscPedCalibReport";
807 ATH_MSG_DEBUG("Recording pedestal amplitude histograms to TDS with key " << histKey);
808
809 //CscCalibReport has extraraneous monitoring information
810 CscCalibReportPed * report = new CscCalibReportPed("pedAmps");
811 report->setPedAmpHists(std::move(m_ampHists));
812 report->setBitHists(std::move(m_bitHists));
813 if(m_doSampleHists){
814 report->setSampHists(std::move(m_sampHists));
815 }
816 if(m_bitProds){
817 report->setBitCorrelation( makeBitCorrelation());
818 }
819
820 CscCalibReportContainer * repCont = new CscCalibReportContainer(histKey);
821 repCont->push_back(report);
822
823 sc = evtStore()->record(repCont, histKey);
824 if(!sc.isSuccess())
825 {
826 ATH_MSG_ERROR("Failed to record CscCalibReportPed to storegate");
827 thereIsAnError = true;
828 delete repCont;
829 }
830
831
832 //CscCalibResult contains the actual parameters that we recorded, mostly things that should be entered
833 //into cool
834 std::string key = "CscCalibResultPed";
835 ATH_MSG_DEBUG("Recording calibration results to TDS with key " << key);
836
837 CscCalibResultContainer * calibResults
838 = new CscCalibResultContainer("CscCalibResultPed");
839 calibResults->push_back(m_peds);
840 calibResults->push_back(m_noises);
841 calibResults->push_back(m_rmses);
842 calibResults->push_back(m_f001s);
844 calibResults->push_back(m_onlineTHoldBreaches);
845
846 sc = evtStore()->record(calibResults,key);
847 if(!sc.isSuccess())
848 {
849 ATH_MSG_ERROR("Failed to record data to storegate");
850 thereIsAnError = true;
851 delete calibResults;
852 }
853
854 if(thereIsAnError)
855 return StatusCode::RECOVERABLE;
856
857 return StatusCode::SUCCESS;
858 }
859
860 //Does bit correlation study. Likely will be dropped
861 std::vector<TH2F*> CscCalcPed::makeBitCorrelation() {
862
863 std::vector<TH2F*> correlations;
864 if(!m_bitProds || !m_doBitHists)
865 return correlations;
866
867 correlations.resize(m_maxStripHash +1);
868
869 for(unsigned int hashItr =0; hashItr <= m_maxStripHash; hashItr++) {
870 IdentifierHash stripHash =hashItr;
871 Identifier stripId;
872 IdContext channelContext = m_idHelperSvc->cscIdHelper().channel_context();
873 m_idHelperSvc->cscIdHelper().get_id(stripHash, stripId, &channelContext);
874
875 int chamLayer = m_idHelperSvc->cscIdHelper().chamberLayer(stripId);
876 if(chamLayer == m_expectedChamberLayer) //Only second chamber layer exists
877 {
878 int stationName = m_idHelperSvc->cscIdHelper().stationName(stripId);
879 //int stationEta = m_idHelperSvc->cscIdHelper().stationEta(stripId);
880 int stationPhi = m_idHelperSvc->cscIdHelper().stationPhi(stripId);
881 int stripNumber = m_idHelperSvc->cscIdHelper().strip(stripId);
882 int wireLayer = m_idHelperSvc->cscIdHelper().wireLayer(stripId);
883 char orientation = m_idHelperSvc->cscIdHelper().measuresPhi(stripId) ? 'Y':'X';
884
885 int sector = 2*stationPhi + 50 - stationName;
886
887 std::stringstream name;
888 name << "h_bitCorr_sector_" << std::setfill('0') << std::setw(2) << sector <<
889 "_lay_" << wireLayer << orientation << "_strip_" << std::setw(3) << stripNumber;
890 std::stringstream title;
891 title << "h_bitCorr_sector_" << std::setfill('0') << std::setw(2) << sector <<
892 "_lay_" << wireLayer << orientation << "_strip_" << std::setw(3) << stripNumber;
893
894 TH2F* correlationHist = new TH2F(
895 name.str().c_str(),
896 title.str().c_str(),
899 );
900 correlations[hashItr] = correlationHist;
901
902 //each amphis is filled exaclty the number of times the bits are sampled,
903 //so its a good place to get n
904 double n = m_ampHists[hashItr]->GetEntries();
905 TH1I * bitHist = m_bitHists[hashItr];
906 TH2F * bitProds = (*m_bitProds)[hashItr];
907 for(unsigned int bit1 = 1; bit1 <=m_numBits; bit1++){
908 for(unsigned int bit2 = 1; bit2 <=bit1; bit2++){
909
910 float xy = bitProds->GetBinContent(bit1,bit2);
911 float x = bitHist->GetBinContent(bit1);
912 float y = bitHist->GetBinContent(bit2);
913
914 float r;
915 float denom = (n*x-x*x)*(n*y-y*y);
916 if(denom <= 0 )
917 r= 0;
918 else
919 r = (n*xy - x*y)/std::sqrt(denom);
920
921 //Pearson r
922 correlationHist->SetBinContent(bit1,bit2,r);
923 if(bit1!=bit2)
924 correlationHist->SetBinContent(bit2,bit1,r);
925
926
927 }
928 }
929 }
930 }
931 return correlations;
932 }//end makeBitCorrelations
933
934
935 void CscCalcPed::onlineToOfflineHashId(const unsigned int & onlineId, unsigned int &hashId) const
936 {
937 int stationName = ((onlineId >> 16)&0x1) + 50;
938 int phi = ((onlineId >> 13)&0x7)+1;
939 int eta = ((((onlineId >> 12)&0x1) == 1) ? 1:-1);
940 int chamLay = ((onlineId>>11)&0x1) +1;
941 int wireLay = ((onlineId>>9)&0x3) +1;
942 int measuresPhi = ((onlineId >> 8)&0x1);
943 int strip;
944
945 // Online and offline phi ids are flipped on A wheel
946 if( measuresPhi && eta == 1){
947 strip = 48 - ((onlineId)&0xff) ; //equivalent: 49 -( onlineId&0xff +1)
948 }
949 else {
950 strip = ((onlineId)&0xff) +1;
951 }
952
953 Identifier chanId = m_idHelperSvc->cscIdHelper().channelID(stationName,eta,phi,chamLay,wireLay,measuresPhi,strip);
954
955 IdentifierHash chanHash;
956 m_idHelperSvc->cscIdHelper().get_channel_hash(chanId, chanHash);
957
958 hashId = (unsigned int)chanHash;
959
960 }
961
962 }//end namespace MuonCalib
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static Double_t sc
#define y
#define x
AthAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
StatusCode indexToStringId(const CscIdHelper *, const unsigned int &, std::string_view, std::string &) const
This container provides access to collections of CSC RDOs and a mechanism for recording them.
Derived DataVector<T>.
Definition DataVector.h:795
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
value_type push_back(value_type pElem)
Add an element to the end of the collection.
DataModel_detail::iterator< DataVector > iterator
Definition DataVector.h:842
This class saves the "context" of an expanded identifier (ExpandedIdentifier) for compact or hash ver...
Definition IdContext.h:26
size_t size() const
Duplicate of fullSize for backwards compatability.
This is a "hash" representation of an Identifier.
constexpr bool is_valid() const
std::string getString() const
Provide a string form of the identifier - hexadecimal.
std::string m_titlePostfix
Definition CscCalcPed.h:91
CscCalibResultCollection * m_noises
Definition CscCalcPed.h:124
CscCalibResultCollection * m_peds
Definition CscCalcPed.h:123
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Services and tools.
Definition CscCalcPed.h:83
unsigned int m_ampHistNumBins
Definition CscCalcPed.h:105
SmartIF< IChronoStatSvc > m_chronoSvc
Definition CscCalcPed.h:84
unsigned int m_ampHistHighBound
Definition CscCalcPed.h:105
DataVector< TH2F > * m_bitProds
Definition CscCalcPed.h:119
StatusCode initialize(void)
basic required functions
StatusCode fillBitHist(TH1I *bitHist, const uint16_t &val, TH2F *bitProds)
Definition CscCalcPed.h:139
const unsigned int m_numBits
Definition CscCalcPed.h:107
StatusCode execute(void)
StatusCode calOutput1()
StatusCode finalize(void)
StatusCode calculateParameters()
Finalize functions.
DataVector< TH1F > * m_bitCorrelation
Definition CscCalcPed.h:120
StatusCode storeGateRecord()
CscCalibResultCollection * m_f001s
Definition CscCalcPed.h:126
std::vector< std::vector< TH1I * > > m_sampHists
Definition CscCalcPed.h:117
std::string m_onlineDbFile
filename for file with online database information
Definition CscCalcPed.h:100
unsigned int m_maxStripHash
Internally global variables.
Definition CscCalcPed.h:103
void onlineToOfflineHashId(const unsigned int &onlineId, unsigned int &hashId) const
CscCalcPed(const std::string &name, ISvcLocator *pSvcLocator)
std::vector< TH1I * > m_bitHists
Definition CscCalcPed.h:118
StatusCode collectEventInfo()
event loop functions
std::vector< int > m_onlineThresholdFailureCount
Definition CscCalcPed.h:122
std::vector< int > m_onlineThresholds
Definition CscCalcPed.h:121
std::string m_calOutputVersion
Definition CscCalcPed.h:92
std::string m_titlePrefix
Definition CscCalcPed.h:91
StatusCode calOutput3()
void outputParameter3(const CscCalibResultCollection &results, std::ofstream &out)
CscCalibResultCollection * m_onlineTHoldBreaches
Definition CscCalcPed.h:127
StatusCode writeCalibrationFile()
std::vector< TH2F * > makeBitCorrelation()
SG::ReadCondHandleKey< CscCondDbData > m_readKey
Definition CscCalcPed.h:86
std::vector< TH1I * > m_ampHists
Definition CscCalcPed.h:116
StatusCode calOutput0()
ToolHandle< Muon::ICSC_RDO_Decoder > m_cscRdoDecoderTool
Definition CscCalcPed.h:85
unsigned int m_ampHistLowBound
Definition CscCalcPed.h:105
CscCalibResultCollection * m_rmses
Definition CscCalcPed.h:125
std::string m_outputFileName
Parameters input through joboptions.
Definition CscCalcPed.h:90
double chi2(TH1 *h0, TH1 *h1)
int r
Definition globals.cxx:22
CscCalcPed - algorithm that finds the Cathode Strip Chamber pedestals from an RDO.
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
#define unlikely(x)