ATLAS Offline Software
Loading...
Searching...
No Matches
CscCalcSlope.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "CscCalcSlope.h"
6
10#include "GaudiKernel/Chrono.h"
14
15#include "TF1.h"
16#include "TGraphErrors.h"
17#include "TFile.h"
18#include "TProfile.h"
19
20#include <iostream>
21#include <fstream>
22#include <bitset>
23#include <inttypes.h>
24
25namespace MuonCalib {
26
27 CscCalcSlope::CscCalcSlope(const std::string& name, ISvcLocator* pSvcLocator) :
28 AthAlgorithm(name,pSvcLocator),
29 m_outputFileName("output.cal"),
30 m_dumpAllHists(false),
33 m_fracProfs(nullptr),
34 m_fracGraphs(nullptr),
35 m_bitHists(nullptr),
36 m_fitReturns(nullptr),
37 m_resGraph(nullptr),
38 m_calGraphs(nullptr),
39 m_currentAmpProf(nullptr),
40 m_ampProfs(nullptr),
41 m_pulsedChambers(nullptr),
42 m_eventCnt(0),
43 m_slopes(nullptr),
44 m_intercepts(nullptr),
45 m_peds(nullptr),
46 m_noises(nullptr),
47 m_peakTimeProf(nullptr),
48 m_peakTimes(nullptr),
49 m_numBits(12)
50 {
51 declareProperty("OutputFile", m_outputFileName = "");
52 declareProperty("IgnoreDatabaseError",m_ignoreDatabaseError = false); //Set to true to ignore database errors
53 declareProperty("TitlePrefix",m_titlePrefix = ""); //Prefix appended to title of histograms and graphs
54 declareProperty("TitlePostfix",m_titlePostfix = ""); //Postfix appended to title of histograms and graphs
55
56 //test parameters
57 declareProperty("DoBipolarFit", m_doBipolarFit = true);
58 declareProperty("DoCrossTalkFix",m_doCrossTalkFix = true);
59
60 declareProperty("GetPedFromFile",m_pedFile = false);
61 declareProperty("PedFileName",m_pedFileName = "");
62
63 declareProperty("ExpectedChamberLayer", m_expectedChamberLayer = 2);
64
65 declareProperty("DoLinPlot" , m_doLinPlot = false);
66 declareProperty("CalibFitFunction" , m_calFitFunc = "[0] + [1]*10^(x/-20)");
67 declareProperty("MinDeltaAdc",m_minDeltaAdc = 10, "Minimum change in ADC a calgraph needs to drop for a fit lower bound to be set");
68
69 /*
70 ADC = mC(db) = m*C_max*10^(db/20) + intercept // C_max = maximum charge
71
72 we divide by c_max later to get m (the function as in m_calFitFunc has
73 [1] = max ADC, so we divide max charge to get
74
75 since attenuation is negative
76
77 db = -20 log(ADC+intercept/mC_max)
78
79 db = -20 log(ADC - intercept / mC_max)
80
81 (-20 since V^2 gives power disipation)
82
83 */
84
85 declareProperty("FindPeakTime", m_findPeakTime = true);
86 declareProperty("DoBitHists", m_doBitHists = true);
87
88 declareProperty("CalOutputVersion", m_calOutputVersion="03-00");
89
90 m_crossTalkFix[0] = 1.0322840930;
91 m_crossTalkFix[1] = 1.0422690324;
92 m_crossTalkFix[2] = 1.0235384586;
93 m_crossTalkFix[3] = 1.0183445962;
94 m_crossTalkFix[4] = 1.0151409212;
95 m_crossTalkFix[5] = 1.0152511102;
96 m_crossTalkFix[6] = 1.0103618910;
97 m_crossTalkFix[7] = 1.0113985580;
98 m_crossTalkFix[8] = 1.0040464232;
99 m_crossTalkFix[9] = 1.0049431193;
100 m_crossTalkFix[10] = 0.9997829589;
101 m_crossTalkFix[11] = 1.0003994005;
102 m_crossTalkFix[12] = 0.9826108255;
103 m_crossTalkFix[13] = 0.9850002836;
104 m_crossTalkFix[14] = 0.9831852065;
105 m_crossTalkFix[15] = 0.9826508145;
106 m_crossTalkFix[16] = 0.9804885017;
107 m_crossTalkFix[17] = 0.9811262196;
108 m_crossTalkFix[18] = 0.9784119832;
109 m_crossTalkFix[19] = 0.9777689757;
110 m_crossTalkFix[20] = 0.9704773978;
111 m_crossTalkFix[21] = 0.9738781078;
112 m_crossTalkFix[22] = 0.9710430303;
113 m_crossTalkFix[23] = 0.9743144079;
114 }
115
117 {
118 ATH_MSG_INFO("CscCalcSlope::initialize() called");
119
120 //*******Register services and tools *********/
121 ATH_CHECK(m_idHelperSvc.retrieve());
122
123 m_chronoSvc = service("ChronoStatSvc");
124 ATH_CHECK(m_chronoSvc.isValid());
125
126 ATH_CHECK(m_cscCalibTool.retrieve());
127
128 ATH_CHECK(m_cscRdoDecoderTool.retrieve());
129
130 ATH_MSG_INFO("Finished initializing services. ");
131 //*****Initialize internal variables and histograms*******/
132 m_ampProfs = new std::map<int, TProfile* >();
133 //Setup lookup table for pulser levels
134 m_dbLevels.resize(64);
135 for(unsigned int pulserLevel=0; pulserLevel < 64; pulserLevel++)
136 m_dbLevels[pulserLevel] = pulserLevel*.5;
137
138 IdContext channelContext = m_idHelperSvc->cscIdHelper().channel_context();
139
141 //Loop through ids to find out what hash range we're working on, and to
142 //initialize histograms.
143 const std::vector<Identifier> & ids = m_idHelperSvc->cscIdHelper().idVector();
144
145
146 m_maxStripHash = 0;
147 for(const auto & thisChamberId:ids)
148 {
149 std::vector<Identifier> stripVect;
150 m_idHelperSvc->cscIdHelper().idChannels(thisChamberId,stripVect);
151
152
153
154 for(const auto & thisStripId:stripVect)
155 {
156 IdentifierHash stripHash;
157 m_idHelperSvc->cscIdHelper().get_channel_hash(thisStripId,stripHash);
158
159 if(m_maxStripHash < (unsigned int)stripHash)
160 m_maxStripHash = (unsigned int)stripHash;
161
162 if(m_bitHists)
163 {
164 Identifier id;
165 m_idHelperSvc->cscIdHelper().get_id((IdentifierHash)stripHash,id,&channelContext);
166 int wireLayer = m_idHelperSvc->cscIdHelper().wireLayer(id);
167 char orientation = (m_idHelperSvc->cscIdHelper().measuresPhi(id) ? 'Y':'X');
168
169 int stationName = m_idHelperSvc->cscIdHelper().stationName(id);
170 int stationPhi = m_idHelperSvc->cscIdHelper().stationPhi(id);
171 int stationEta = m_idHelperSvc->cscIdHelper().stationEta(id);
172
173 int stripNumber = m_idHelperSvc->cscIdHelper().strip(id);
174
175 char bitName[200], titleSeed[500];
176 //Bit histogram (for looking for stuck-bits)
177 sprintf(bitName, "bitHist%d",(int)stripHash);
178 sprintf(titleSeed, "Bit histogram for eta %d, sector %d, layer %d%c strip %d",
179 stationEta,(2*stationPhi+50 - stationName),wireLayer,orientation,stripNumber);
180 std::string title = m_titlePrefix + titleSeed + m_titlePostfix;
181 TH1I* hist = new TH1I(bitName, title.c_str(), m_numBits, 0, m_numBits); //12 bits
182 hist->GetXaxis()->SetTitle("Bit");
183 hist->GetYaxis()->SetTitle("Counts");
184 m_bitHists->push_back(hist);
185 }
186 }
187 }//end chamber loop
188
189 m_fitReturns = new std::vector<float>;
190 m_fitReturns->resize(m_maxStripHash+1,0);
191
193 for(unsigned int chanItr =0; chanItr <= m_maxStripHash; chanItr++)
194 {
195 m_calGraphs->push_back(nullptr);
196 }
197
198
199 if(m_pedFile)
200 {
201 ATH_MSG_INFO("Opening pedestal file");
202 std::ifstream in(m_pedFileName.c_str());
203 int stripHash;
204 double ped,noise;//,pedError,noiseError;
205 std::string buff;
206 in >> buff >> buff >> buff >> buff >> buff ;// skip header
207 m_peds = new float[m_maxStripHash+1];
208 m_noises = new float[m_maxStripHash+1];
209
210 while(!in.eof())
211 {
212 in >> stripHash >> buff >> buff >> ped >> noise;
213 ATH_MSG_INFO(stripHash << "\t" << ped << "\t" << noise);
214 if( stripHash < 0 || (unsigned int) stripHash > m_maxStripHash ) {
215 //cppcheck-suppress shiftNegative
216 ATH_MSG_FATAL("The hash "<< (int) stripHash << " is out of range for the Ped-Vector - Crashing!");
217 return StatusCode::FAILURE;
218 }
219 m_peds[stripHash] = ped;
220 m_noises[stripHash] = noise;
221 }
222 }
223 else
224 {
225 ATH_CHECK(m_readKey.initialize());
226 }
227
228 ATH_MSG_INFO("Counted " << m_maxStripHash +1 << " strips.");
229
230 m_slopes = new CscCalibResultCollection("pslope");
232
234 {
235 m_peakTimeProf = new TProfile("PeakTimes","Peaking Time for each channel",m_maxStripHash+1,
236 0,m_maxStripHash+1);
238 }
239
240 m_pulsedChambers = new std::set<int>;
241
242
243 ATH_MSG_DEBUG("End initialize");
244 return StatusCode::SUCCESS;
245 }//end initialize
246
247 //Execute loops through all strips and fills histograms
249 {
250 ATH_MSG_INFO("Begin execute");
251 //collectEventInfo collects infomation about each event by filling ampHistCollection and peaktHist.
252 StatusCode sc = collectEventInfo();
253
254 if(!sc.isSuccess())
255 {
256 ATH_MSG_WARNING("There was an error collecting information from the RDO this event.");
257 return sc;
258 }
259 ATH_MSG_INFO("End execute");
260 return StatusCode::SUCCESS;
261 } //end execute()
262
264 {
265 ATH_MSG_INFO("In finalize()");
266
267 StatusCode sc;
268
269 bool thereIsAFatal=false;
270
271 //calculateParameters() finds means and fits gain curves from the data in
274 if(sc.isFailure())
275 {
276 ATH_MSG_WARNING("Calculation of parameters failed!");
277 }
278 ATH_MSG_DEBUG("Finished calculating parameters");
279
280 //writeCalibrationFile() writes the calculated parameters into a calibration fie.
282 if(!sc.isSuccess())
283 {
284 ATH_MSG_FATAL("Failed to write parameters to disk!");
285 thereIsAFatal = true; //Not quiting yet to ensure memory is properly deleted
286 }
287
289 if(sc.isFailure())
290 {
291 ATH_MSG_FATAL("Failed to record parameters in StoreGate ");
292 thereIsAFatal = true;
293 }
294
295 delete m_peakTimeProf;
296
297 ATH_MSG_DEBUG("Finished finalize()");
298
299 if(thereIsAFatal)
300 return StatusCode::FAILURE;
301
302 return StatusCode::SUCCESS;
303 }//end finalize()
304
305
306 //Collect event info is run every event, gathering amplitutdes and peakting times.
308 {
309 MsgStream mLog( msgSvc(), name() );
310
311 // apparently not used since code is exited automatically if there is an error
312 // bool thereIsAnError = false;
313
314 Chrono chrono(m_chronoSvc,"collectEventInfo");
315 ATH_MSG_DEBUG("Collecting event info for event " << m_eventCnt);
316 //Below might need to be changed depending on how we get data
317 const CscRawDataContainer* fullRDO;
318 StatusCode sc_read = evtStore()->retrieve(fullRDO, "CSCRDO");
319 if (sc_read != StatusCode::SUCCESS)
320 {
321 ATH_MSG_FATAL("Could not find event");
322 return StatusCode::FAILURE;
323 }
324
326 const CscCondDbData* readCdo{*readHandle};
327
328 //Loop over RODs (data from 2 chambers), each of which is in
329 //a single CscRawaData collection
330
331
332 for(const auto rod:*fullRDO)
333 {
334 if(not rod->empty())
335 {
336
337 uint16_t pulsedWireLayer = rod->calLayer();
338
339 int pulserLevel = rod->calAmplitude();
340 ATH_MSG_VERBOSE("Pulser level is " << pulserLevel);
341 if( pulserLevel != m_lastPulserLevel)
342 {
343 ATH_MSG_INFO("New pulser level found. (" << pulserLevel <<").");
344
345 std::map<int,TProfile*>::iterator alreadyExistingProfile = m_ampProfs->find(pulserLevel);
346
347 if(alreadyExistingProfile == m_ampProfs->end())
348 {//No previous profile for this amplitude exists
349
350 ATH_MSG_DEBUG(" creating new amplitude profile");
351 std::stringstream name, title;
352 name << "ampProf_" << pulserLevel;
353 title << m_titlePrefix << "Amplitudes For Pulser Level " << pulserLevel << m_titlePostfix;
354 m_currentAmpProf = new TProfile(name.str().c_str(), title.str().c_str(),
356 m_currentAmpProf->GetXaxis()->SetTitle("Channel (Hash Id)");
357 m_currentAmpProf->GetYaxis()->SetTitle("Amplitude (ADC value)");
358 ATH_MSG_DEBUG("Adding new amplitude profile");
359 m_ampProfs->insert(std::pair<int, TProfile*>( pulserLevel, m_currentAmpProf));
360 }
361 else
362 {
363 ATH_MSG_DEBUG(" using existing amplitude profile");
364 m_currentAmpProf = alreadyExistingProfile->second;
365 }
366
367 m_lastPulserLevel = pulserLevel;
368 }
369
370 unsigned int samplingPhase = rod->samplingPhase();
371 uint8_t samplingPeriod = rod->rate(); //sampling period in ns
372
373
374 //Loop over strips in rod
375
376
377 for(const auto cluster: *rod)
378 {
379 //Note: For a pulser or ped run, the "cluster"
380 //is the size of an entire layer
381 int numStrips = cluster->width();
382 int samplesPerStrip = (cluster->samples()).size()/numStrips;
383
384 IdContext channelContext = m_idHelperSvc->cscIdHelper().channel_context();
385
386 for(int stripItr = 0; stripItr <numStrips; stripItr++)
387 {
388 Identifier stripId =m_cscRdoDecoderTool->channelIdentifier(cluster, &m_idHelperSvc->cscIdHelper(), stripItr);
389 IdentifierHash cscChannelHashId;
390 m_idHelperSvc->cscIdHelper().get_channel_hash(stripId, cscChannelHashId);
391 int stripHash = cscChannelHashId;
392 ATH_MSG_VERBOSE("The eta of this strip is: " << m_idHelperSvc->cscIdHelper().stationEta(stripId));
393
394 int chamberLayer = m_idHelperSvc->cscIdHelper().chamberLayer(stripId);
395 if(chamberLayer != m_expectedChamberLayer)
396 {
397 ATH_MSG_FATAL("Cluster includes strip in chamber layer "
398 << chamberLayer << ". Only " << m_expectedChamberLayer
399 << " is valid.");
400 return StatusCode::FAILURE;
401 }
402
403 int currentWireLayer = m_idHelperSvc->cscIdHelper().wireLayer(stripId) - 1;
404 if( currentWireLayer < 0 || currentWireLayer > 3)
405 {
406 ATH_MSG_FATAL("Problem in getting wire layer! - Current value is "
407 << m_idHelperSvc->cscIdHelper().wireLayer(stripId) << " while only values between 1-4 are allowed.");
408 return StatusCode::FAILURE;
409 }
410 bool isThisLayerPulsed = (pulsedWireLayer >> currentWireLayer)&0x1;
411 if(isThisLayerPulsed)
412 {
413
414 std::vector<uint16_t> samples;
415 cluster->samples(stripItr,samplesPerStrip,samples); //Retrieve samples for a single strip
416
417 float ped = 0;
418 float noise = 0;
419 if(m_pedFile)
420 {
421 ped = m_peds[stripHash];
422 noise = m_noises[stripHash];
423 }
424 else{
425
426 if(!readCdo->readChannelPed(stripHash, ped).isSuccess()){
427 ped = 2054;
428 if (m_ignoreDatabaseError) ATH_MSG_WARNING("Failed at getting pedestal from COOL for hash " << stripHash);
429 else ATH_MSG_ERROR("Failed at getting pedestal from COOL for hash " << stripHash);
431 return StatusCode::RECOVERABLE;
432 ATH_MSG_WARNING("Setting to " << ped);
433 }
434 else
435 ATH_MSG_VERBOSE("Got pedestal of " << ped);
436 if(!readCdo->readChannelNoise(stripHash, noise).isSuccess())
437 {
438 noise = .001;
439 if (m_ignoreDatabaseError) ATH_MSG_WARNING("Failed at getting noise from COOL for hash " << stripHash);
440 else ATH_MSG_ERROR("Failed at getting noise from COOL for hash " << stripHash);
442 return StatusCode::FAILURE;
443 ATH_MSG_WARNING("Setting to " << noise);
444 }
445
446 }
447
448 double peakAmp{}, peakTime{};
449 int success{};
450 if(!m_doBipolarFit)
451 {
452 //Need to convert vector from ints to floats to pass to findCharge
453 std::vector<float> floatSamples;
454 for(const auto & thisSample:samples){
455
456 floatSamples.push_back(thisSample-ped);
457 if(m_bitHists){
458 if(!fillBitHist((*m_bitHists)[stripHash],thisSample)){
459 ATH_MSG_WARNING("Failed recording bits for strip " << stripHash);
460 }
461
462 }
463 }
464
465 success = m_cscCalibTool->findCharge((float)samplingPeriod, samplingPhase,floatSamples,peakAmp,peakTime);
466
467 }
468 else
469 {
470 //Need to convert vector from ints to doubles to pass to bipolar fit
471 double adcSamples[4];
472 for(int i = 0; i < 4; i++) adcSamples[i] = samples[i] -ped;
473 double fitResult[3],fitErrors[3], chi2;
474 double width = samplingPeriod == 50 ? 7.2:14.4; //check if 50 or 25ns period
475
476 m_bipolarFit.Fit(adcSamples,noise,ped,width,fitResult,fitErrors,&chi2);
477 success = true;
478 peakAmp = fitResult[0];
479 peakTime = fitResult[1] - (samplingPhase ? 25 : 0);
480 }//end if m_doBipolarFit
481
482
483 if(success)
484 {
485 m_currentAmpProf->Fill(stripHash,peakAmp);
486 //((*m_ampHists)[stripHash])->Fill(peakAmp);
487
489 m_peakTimeProf->Fill(stripHash,peakTime);
490 }
491 else
492 {
493 ATH_MSG_WARNING("Failed at fitting pulse shape. Debug info: ");
494 ATH_MSG_WARNING("stripHash " << stripHash);
495 ATH_MSG_WARNING("strip in chamber " << stripItr);
496 ATH_MSG_WARNING(" and detailed id " << m_idHelperSvc->cscIdHelper().show_to_string(stripId,&channelContext));
497 ATH_MSG_WARNING("Pulsed layer " << pulsedWireLayer<< ", Samples: " << samples[0] <<", " << samples[1] << ", " << samples[2] << ", " << samples[3]);
498 }
499 }//end if (islayerPulsedand and is precision layer)
500 }//end strip loop
501
502 }//end cluster loop
503 }//end if rod >1
504 }//end rod loop
505
506
507 ATH_MSG_DEBUG("end collectEventInfo()");
508 m_eventCnt++;
509
510 // at this part of the code thereIsAnError is always false - if true it would exit earlier
511 // if(thereIsAnError)
512 // return StatusCode::RECOVERABLE;
513
514 return StatusCode::SUCCESS;
515 }// end collectEventInfo()
516
517
518 //Calculate parameters is called during finalize, and calculates the parameter values from the
519 //data taken by collectEventData()
521 {
522 Chrono chrono(m_chronoSvc,"calculateParameters");
523 StatusCode sc;
524 ATH_MSG_INFO("Calculating calibration constants.");
525
526 if(!m_ampProfs){
527 ATH_MSG_FATAL("m_ampProfs empty!");
528 return StatusCode::FAILURE;
529 }
530 unsigned int numCalibPoints = m_ampProfs->size();
531 ATH_MSG_INFO("There are " << numCalibPoints << " pulser levels to evaluate.");
532
533 IdContext channelContext = m_idHelperSvc->cscIdHelper().channel_context();
534
535 float chargeMax = 530.88; //in fC
536
537 int crossTalkCnt = 0;
538
539 for(unsigned int stripHash = 0 ;stripHash <= m_maxStripHash; stripHash++)
540 {
541
542 if(true)//stripHash < 50 || stripHash%1000 == 0)
543 {
544 ATH_MSG_INFO("Analyzing strip with hash " << stripHash << " out of " << m_maxStripHash);
545 }
546
547 //**Now tackle slope calculation
548
549
550 Identifier id;
551 m_idHelperSvc->cscIdHelper().get_id((IdentifierHash)stripHash,id,&channelContext);
552 int chamberLayer = m_idHelperSvc->cscIdHelper().chamberLayer(id);
553 char orientation = (m_idHelperSvc->cscIdHelper().measuresPhi(id) ? 'Y':'X');
554
555 int wireLayer = m_idHelperSvc->cscIdHelper().wireLayer(id);
556
557
558 int stationName = m_idHelperSvc->cscIdHelper().stationName(id);
559 int stationPhi = m_idHelperSvc->cscIdHelper().stationPhi(id);
560 int stationEta = m_idHelperSvc->cscIdHelper().stationEta(id);
561 int stripNumber = m_idHelperSvc->cscIdHelper().strip(id);
562
563 IdentifierHash chamHash;
564 m_idHelperSvc->cscIdHelper().get_module_hash(id,chamHash);
565
566 if(chamberLayer != m_expectedChamberLayer)
567 continue;
568
570 {
571 if(m_peakTimeProf->GetBinEntries(stripHash+1)) //See if any peaking times were recorded for strip
572 {
573 float peakt = m_peakTimeProf->GetBinContent(stripHash+1);
574 float peaktError = m_peakTimeProf->GetBinError(stripHash+1);
575 CscCalibResult * peaktResult = new CscCalibResult(stripHash,peakt, peaktError);
576 m_peakTimes->push_back(peaktResult);
577 }
578 }//end if(m_findPeakTime)
579
580 //Don't find slope for this strip if it is a transverse strip
581 if(orientation != 'X')
582 continue;
583
584 //For removing plateau's from fit
585 bool foundMin(false);
586 double fitMinX = 0;
587 double fitMaxX = 0;
588 double lastVal = -1;
589 double lastDrop=0;
590 double thisDrop=0;
591
592
593 TGraphErrors * calGraph = new TGraphErrors(numCalibPoints); //calGraph will be what the gain will be found on
594 char calName[20],titleSeed[500];
595 sprintf(calName, "calGraph%u",stripHash);
596 sprintf(titleSeed, "Calgraph for eta %d, sector %d, layer %d%c, strip %d",stationEta,(2*stationPhi+50 - stationName),wireLayer,orientation, stripNumber);
597 calGraph->SetName(calName);
598 std::string title = m_titlePrefix + titleSeed + m_titlePostfix;
599 calGraph->SetTitle(title.c_str());
600 calGraph->GetYaxis()->SetTitle("ADC counts");
601 calGraph->GetXaxis()->SetTitle("Attenuation (-db)");
602
603 ATH_MSG_DEBUG(" Generating " << title);
604
605 bool isGoodStrip = false;
606
607 //Loop over all attenuation levels, filling the calGraph with the amplitudes
608 //for this strip
609 ATH_MSG_DEBUG("Number of ampProfs " << m_ampProfs->size());
610 int calPointItr = 0;
611 for(const auto & [pulserLevel, pAmplitudeProfile] : *m_ampProfs)
612 {
613 if(!pAmplitudeProfile){
614 ATH_MSG_FATAL("Failed at accessing ampProf!");
615 return StatusCode::FAILURE;
616 }
617 ATH_MSG_DEBUG("\tLooking for data for pulser level "
618 << pulserLevel);
619
620 if(pAmplitudeProfile->GetBinEntries(stripHash+1))
621 {
622
623 ATH_MSG_VERBOSE("\nHave data for strip " << stripHash);
624
625 isGoodStrip = true;
626
627
628 float adcValue = pAmplitudeProfile->GetBinContent(stripHash+1);
629 float adcError = pAmplitudeProfile->GetBinError(stripHash+1);
631 {
632 ATH_MSG_VERBOSE("\tCrosstalk fix " << m_crossTalkFix[crossTalkCnt]);
633 adcValue /= m_crossTalkFix[crossTalkCnt];
634 adcError /= m_crossTalkFix[crossTalkCnt];
635 }
636 if(adcError != adcError)
637 adcError = 0.01;
638
639 float db = m_dbLevels[pulserLevel];
640
641
642 float attenValue =0;
643 if(m_doLinPlot)
644 attenValue = 300*std::pow(10,db/20);
645 else
646 attenValue = db;
647
648 ATH_MSG_DEBUG("\tStoring at db of " << db << " with attenValue " << attenValue << " from pulser level of " << pulserLevel << " and adcValue " << adcValue);
649
650
651
652 //See if the last two drops were far down enough
653 if(!foundMin){
654 thisDrop = lastVal - adcValue;
655 ATH_MSG_DEBUG("\tFinding fit min:"
656 << "\tlastVal = " << lastVal
657 << ";lastDrop " << lastDrop << "; thisDrop " << thisDrop);
658 if(thisDrop > m_minDeltaAdc && lastDrop > m_minDeltaAdc){
659 ATH_MSG_DEBUG("Found fitMin!");
660 foundMin = true;
661 fitMinX = attenValue;
662 }
663 else{
664 //Not enough deltaADC, store this iterations values for the next loop
665 lastDrop = thisDrop;
666 lastVal = adcValue;
667 }
668 }
669
670 //Use highest attenuation level as fitMaxX
671 if(attenValue > fitMaxX)
672 fitMaxX = attenValue;
673
674 calGraph->SetPoint(calPointItr,attenValue,adcValue);
675 calGraph->SetPointError(calPointItr,0.01,adcError);
676 calPointItr++;
677 }//done if(entries >0)
678
679 }//Done ampProfItr loop
680
681 if(!foundMin && isGoodStrip){
682 ATH_MSG_WARNING("Failed to find minium for " << title);
683 }
684
685 //***Do a simple fit to calGraph***
686 //Here we only fit the linear part of the plot. m_fitCutoff can be set by user.
687 if(isGoodStrip)
688 {
689 ATH_MSG_INFO("we have a good stripHash at " << stripHash);
690
691 m_pulsedChambers->insert(chamHash); //Programer note: Only gets filled on x-axis. Probably OK.
692
693 float slope, slopeError, intercept, interceptError, chiSquared;
694 int ndf;
695 int fitRet=0;
696
697 //Setup our gain fit function
698 TF1 myFunc("myFunction", m_calFitFunc.c_str(), fitMinX, fitMaxX);
699 myFunc.SetLineColor(kRed);
700 if(m_doLinPlot)
701 {
702 myFunc.SetParameters(0,5);
703 slope = myFunc.GetParameter(1);
704 slopeError = myFunc.GetParError(1);
705 intercept = myFunc.GetParameter(0);
706 interceptError = myFunc.GetParError(0);
707 chiSquared = myFunc.GetChisquare();
708 ndf = myFunc.GetNDF();
709 }
710 else
711 {
712 myFunc.SetParameters(0.1,2000);
713
714 fitRet = calGraph->Fit(&myFunc,"RV");
715
716 slope = myFunc.GetParameter(1)/chargeMax;
717 slopeError = myFunc.GetParError(1);
718 intercept = myFunc.GetParameter(0);
719 interceptError = myFunc.GetParError(0);
720 chiSquared = myFunc.GetChisquare();
721 ndf = myFunc.GetNDF();
722 }
723
724 float invertedSlope;
725 if(std::abs(slope) < 0.00001 || slope == -999) //watch out for slope==0
726 {
727 ATH_MSG_WARNING("Slope invalid ");
728 continue;
729 }
730
731 invertedSlope = 1/slope;
732
733 ATH_MSG_ERROR("Inserting calgraph in for hash " << stripHash);
734 (*m_calGraphs)[stripHash] = calGraph;
735
736 ATH_MSG_DEBUG("StripHash: " << stripHash << "; slope: " <<slope
737 << "; intercept: " << intercept
738 << "; chi^2/ndf: " << chiSquared << "/" << ndf);
739 CscCalibResult * slopeResult = new CscCalibResult(stripHash,invertedSlope,slopeError,chiSquared,ndf);
740 CscCalibResult * interceptResult = new CscCalibResult(stripHash, intercept, interceptError, chiSquared, ndf);
741
742 m_slopes->push_back(slopeResult);
743 m_intercepts->push_back(interceptResult);
744 (*m_fitReturns)[stripHash] = fitRet;
745
746 }//end if(isGoodStrip)
747
748
749 if(crossTalkCnt == 23)
750 crossTalkCnt = 0;
751 else
752 crossTalkCnt++;
753 ATH_MSG_DEBUG("Looping over next strip...");
754 }//end loop over strips
755 ATH_MSG_INFO("Completed calculating parameters for each strip");
756 return StatusCode::SUCCESS;
757 }//End calculateParameters()
758
759 //writeCalibrationFile() dumps the parameters to disk
761 {
762 Chrono chrono(m_chronoSvc,"writeCalibrationFile");
763 if(m_calOutputVersion == "00-00"){
764 ATH_MSG_INFO("Printing output file version 00-00");
765 return calOutput0();
766 }
767 else if(m_calOutputVersion == "03-00") {
768 ATH_MSG_INFO("Printing output file version 03-00");
769 return calOutput3();
770 }
771 else{
772 ATH_MSG_INFO("Don't know how to write calibration file version " << m_calOutputVersion);
773 return StatusCode::RECOVERABLE;
774 }
775 }
776
778 //***Take conditions data held in summary histograms and print to the calibration file***//
779 ATH_MSG_INFO("Parameters calculated, preparing to outputing to file: " << m_outputFileName);
780 std::ofstream out;
781 out.open(m_outputFileName.c_str());
782 if(!out.is_open())
783 {
784 ATH_MSG_FATAL("Can't open file " << m_outputFileName.c_str() << "for writing");
785 return StatusCode::FAILURE;
786 }
787 //Start by writing file version number (mainly for COOL program to read)
788 out << "00-00 ";
789 //Number of strips we have info for:
790 out << m_slopes->size() << " ";
791 //print out header
792 out << "pslope ";
793 if(m_findPeakTime) out << "peakt ";
794 out << "END_HEADER\n";
795 //Now we loop over each strip's parameters and print them out
796 ATH_MSG_DEBUG("Begining loop over all " << m_maxStripHash << " hash ids.");
797
798 //form is:
799 //hashID chamber LayerOrientationStrip parametervalue parametervalue
805 {
806 peaktItr = m_peakTimes->begin();
807 peaktEnd = m_peakTimes->end();
808 }
809 for(; slopeItr != slopeEnd; ++slopeItr)
810 {
811 if(m_findPeakTime && (peaktItr == peaktEnd) )
812 {
813 ATH_MSG_FATAL("Peaktimes out of sync with slopes. Quiting write.");
814
815 return StatusCode::FAILURE;
816 }
817
818 //Output hashId
819 out << (*slopeItr)->hashId();
820
821 //get id for next few outputs
822 Identifier id;
823 IdContext channelContext = m_idHelperSvc->cscIdHelper().channel_context();
824 m_idHelperSvc->cscIdHelper().get_id((*slopeItr)->hashId(),id, &channelContext);
825
826 //output chamber #
827 IdentifierHash chamberHash;
828 Identifier chamberId = m_idHelperSvc->cscIdHelper().elementID(id);
829 if(!m_idHelperSvc->cscIdHelper().valid(chamberId))
830 {
831 ATH_MSG_FATAL(chamberId.getString() << " is not a valid id!");
832 ATH_MSG_FATAL("identifier is: " << m_idHelperSvc->cscIdHelper().show_to_string(chamberId));
833 return StatusCode::FAILURE;
834 }
835
836 m_idHelperSvc->cscIdHelper().get_module_hash(id,chamberHash);
837 out <<" " << chamberHash;
838
839 //output strip details
840 out << " " << m_idHelperSvc->cscIdHelper().show_to_string(id) << " ";
841
842 //output parameter values
843 out << " " << (*slopeItr)->value();
844 if(m_findPeakTime) out << " " << (*peaktItr)->value();
845 out << "\n" ; //to improve readability
846 } //end loop over hash Ids
847
848 out.close(); //done writing
849
850 return StatusCode::SUCCESS;
851 }//end calOutput0
852
854 {
855 ATH_MSG_INFO("Recording csc calibration report.");
856
857 StatusCode sc = StatusCode::SUCCESS;
858
859 bool thereIsAnError = false;
860
861 std::string histKey = "cscSlopeCalibReport";
862 ATH_MSG_DEBUG("Recording calibration graphs to TDS with key " << histKey);
863
864 CscCalibReportSlope * report = new CscCalibReportSlope("calGraphs");
865
866 report->setCalGraphs(m_calGraphs);
867 report->setAmpProfs(m_ampProfs);
868 report->setPulsedChambers(m_pulsedChambers);
869 report->setBitHists(m_bitHists);
870 report->setFitResults(m_fitReturns);
871
872 CscCalibReportContainer * repCont = new CscCalibReportContainer(histKey);
873 repCont->push_back(report);
874
875 sc = evtStore()->record(repCont, histKey);
876 if(sc.isFailure())
877 {
878 ATH_MSG_ERROR("Failed to record CscCalibReportSlope to storegate");
879 thereIsAnError = true;
880 //Since storegate isn't taking ownership, we'll delete it:
881 delete repCont;
882 }
883
884 CscCalibResultContainer * calibResults
885 = new CscCalibResultContainer("CscCalibResultSlope");
886 calibResults->push_back(m_slopes);
887 calibResults->push_back(m_intercepts);
889 calibResults->push_back(m_peakTimes);
890 sc = evtStore()->record(calibResults,"CscCalibResultSlope");
891 if(sc.isFailure())
892 {
893 ATH_MSG_ERROR("Failed to record results to storegate");
894 thereIsAnError = true;
895 //Since storegate isn't taking ownership, we'll delete it
896 delete calibResults;
897 }
898
899 if(thereIsAnError)
900 return StatusCode::RECOVERABLE;
901
902 return StatusCode::SUCCESS;
903 }
904
905
906
908 std::ofstream out;
909 out.open(m_outputFileName.c_str());
910 if(!out.is_open())
911 {
912 ATH_MSG_ERROR("Can't open file " << m_outputFileName.c_str());
913 return StatusCode::RECOVERABLE;
914 }
915 out << "03-00 <END_HEADER>";
916
918 out << "\n<END_FILE>";
919 out.close();
920
921 ATH_MSG_INFO("Successfully opened file " << m_outputFileName);
922
923 return StatusCode::SUCCESS;
924 }
925
926
927 void CscCalcSlope::outputParameter3(const CscCalibResultCollection & results, std::ofstream & out){
928 ATH_MSG_INFO("Printing out parameter " << results.parName());
929
931 const CscCondDbData* readCdo{*readHandle};
932
933 out << "\n";
934 out << "<NEW_PAR> " << results.parName() << "\n";
935 std::string idString;
936
937 CscCalibResultCollection::const_iterator resItr = results.begin();
938 CscCalibResultCollection::const_iterator resEnd = results.end();
939 for(; resItr != resEnd; ++resItr){
940 unsigned int hashId = (*resItr)->hashId();
941 double value = (*resItr)->value();
942 std::string idString;
943
944 readCdo->indexToStringId(&m_idHelperSvc->cscIdHelper(), hashId, "CHANNEL", idString).ignore();
945
946 out << idString << " " << value << "\n";
947 }
948
949 out << "<END_PAR>" ;
950 }
951}//end namespace MuonCalib
#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
const double width
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 &, const std::string &, std::string &) const
StatusCode readChannelPed(IdentifierHash, float &) const
StatusCode readChannelNoise(IdentifierHash, float &) 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
This is a "hash" representation of an Identifier.
std::string getString() const
Provide a string form of the identifier - hexadecimal.
StatusCode initialize(void)
basic required functions
std::string m_outputFileName
Parameters input through joboptions.
CscCalibResultCollection * m_peakTimes
std::map< int, TProfile * > * m_ampProfs
std::array< double, 24 > m_crossTalkFix
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
SG::ReadCondHandleKey< CscCondDbData > m_readKey
CscCalibResultCollection * m_intercepts
StatusCode finalize(void)
StatusCode calculateParameters()
Finalize functions.
std::vector< float > * m_fitReturns
DataVector< TGraphErrors > * m_calGraphs
CscCalibResultCollection * m_slopes
std::string m_calOutputVersion
ToolHandle< ICscCalibTool > m_cscCalibTool
Services and tools.
int m_eventCnt
coherent correction array has the corrections to the coherently pulsed channels to get the basic chan...
DataVector< DataVector< TProfile > > * m_fracProfs
StatusCode execute(void)
unsigned int m_maxStripHash
Internally global variables.
StatusCode fillBitHist(TH1I *bitHist, const uint16_t &val)
CscCalcSlope(const std::string &name, ISvcLocator *pSvcLocator)
ToolHandle< Muon::ICSC_RDO_Decoder > m_cscRdoDecoderTool
void outputParameter3(const CscCalibResultCollection &results, std::ofstream &out)
std::vector< float > m_dbLevels
DataVector< DataVector< TGraph > > * m_fracGraphs
DataVector< TH1I > * m_bitHists
SmartIF< IChronoStatSvc > m_chronoSvc
std::set< int > * m_pulsedChambers
StatusCode collectEventInfo()
event loop functions
StatusCode writeCalibrationFile()
double chi2(TH1 *h0, TH1 *h1)
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