GRSISort "v4.0.0.5"
An extension of the ROOT analysis Framework
Loading...
Searching...
No Matches
TChannel.cxx
Go to the documentation of this file.
1#include "TChannel.h"
2
3#include <stdexcept>
4#include <fstream>
5#include <iostream>
6#include <iomanip>
7#include <fcntl.h>
8#include <unistd.h>
9#include <unordered_map>
10
11#include <vector>
12#include <sstream>
13#include <algorithm>
14#include <regex>
15
16#include "TFile.h"
17#include "TKey.h"
18
19#include "StoppableThread.h"
20#include "Globals.h"
21#include "TGRSIUtilities.h"
22
23/*
24 * Author: P.C. Bender, <pcbend@gmail.com>
25 *
26 * Please indicate changes with your initials.
27 *
28 *
29 */
30
31// NOTE: The fChannelMap is unordered. The easiest way to order it is using std::map<int, int> ordered(unordered.begin(), unordered.end());
32
33std::unordered_map<unsigned int, TChannel*>* TChannel::fChannelMap = new std::unordered_map<unsigned int, TChannel*>; // global maps of channels
34std::unordered_map<unsigned int, int>* TChannel::fMissingChannelMap = new std::unordered_map<unsigned int, int>; // global map of missing channels
35std::unordered_map<int, TChannel*>* TChannel::fChannelNumberMap = new std::unordered_map<int, TChannel*>;
36
37// TClass* TChannel::fMnemonicClass = TMnemonic::Class();
38TClassRef TChannel::fMnemonicClass = TClassRef("TMnemonic");
39
40std::string TChannel::fFileData;
41
43{
44 Clear();
45} // default constructor need to write to root file.
46
47TChannel::~TChannel() = default;
48
49TChannel::TChannel(const char* tempName)
50{
51 Clear();
52 // only set name if it's not empty
53 if(strlen(tempName) > 0) { SetName(tempName); }
54}
55
91
92TChannel::TChannel(TChannel&& chan) noexcept : TNamed(chan)
93{
94 /// Moves chan to this.
95 /// Just a copy of the copy constructor right now, needs to be changed.
96 Clear();
97 *(fMnemonic.Value()) = *(chan.fMnemonic.Value());
98 SetAddress(chan.GetAddress());
99 SetIntegration(chan.fIntegration);
100 SetNumber(chan.fNumber);
101 SetStream(chan.fStream);
102 SetName(chan.GetName());
103 SetDigitizerType(chan.fDigitizerTypeString);
104 SetTimeOffset(chan.fTimeOffset);
105 SetTimeDrift(chan.fTimeDrift);
106 SetAllENGCoefficients(chan.fENGCoefficients);
107 SetENGRanges(chan.fENGRanges);
108 SetAllENGChi2(chan.fENGChi2);
109 SetENGDriftCoefficents(chan.fENGDriftCoefficents);
110 SetCFDCoefficients(chan.fCFDCoefficients);
111 SetLEDCoefficients(chan.fLEDCoefficients);
112 SetTIMECoefficients(chan.fTIMECoefficients);
113 SetEFFCoefficients(chan.fEFFCoefficients);
114 SetCTCoefficients(chan.fCTCoefficients);
115 SetEnergyNonlinearity(chan.fEnergyNonlinearity);
116 SetCFDChi2(chan.fCFDChi2);
117 SetLEDChi2(chan.fLEDChi2);
118 SetTIMEChi2(chan.fTIMEChi2);
119 SetEFFChi2(chan.fEFFChi2);
120 SetUseCalFileIntegration(chan.fUseCalFileInt);
121 SetWaveParam(chan.GetWaveParam());
122 SetDetectorNumber(chan.GetDetectorNumber());
123 SetSegmentNumber(chan.GetSegmentNumber());
124 SetCrystalNumber(chan.GetCrystalNumber());
125
126 SetClassType(chan.GetClassType());
127}
128
164
203
205{
206 /// move assignment operator
207 /// Doesn't really move anything yet, it's just a copy of the copy assignment operator.
208 /// This needs to be changed.
209 Clear();
210 *(fMnemonic.Value()) = *(rhs.fMnemonic.Value());
211 SetAddress(rhs.GetAddress());
212 SetIntegration(rhs.fIntegration);
213 SetNumber(rhs.fNumber);
214 SetStream(rhs.fStream);
215 SetName(rhs.GetName());
216 SetDigitizerType(rhs.fDigitizerTypeString);
217 SetTimeOffset(rhs.fTimeOffset);
218 SetTimeDrift(rhs.fTimeDrift);
219 SetAllENGCoefficients(rhs.fENGCoefficients);
220 SetENGRanges(rhs.fENGRanges);
221 SetAllENGChi2(rhs.fENGChi2);
222 SetENGDriftCoefficents(rhs.fENGDriftCoefficents);
223 SetCFDCoefficients(rhs.fCFDCoefficients);
224 SetLEDCoefficients(rhs.fLEDCoefficients);
225 SetTIMECoefficients(rhs.fTIMECoefficients);
226 SetEFFCoefficients(rhs.fEFFCoefficients);
227 SetCTCoefficients(rhs.fCTCoefficients);
228 SetEnergyNonlinearity(rhs.fEnergyNonlinearity);
229 SetCFDChi2(rhs.fCFDChi2);
230 SetLEDChi2(rhs.fLEDChi2);
231 SetTIMEChi2(rhs.fTIMEChi2);
232 SetEFFChi2(rhs.fEFFChi2);
233 SetUseCalFileIntegration(rhs.fUseCalFileInt);
234 SetWaveParam(rhs.GetWaveParam());
235 SetDetectorNumber(rhs.GetDetectorNumber());
236 SetSegmentNumber(rhs.GetSegmentNumber());
237 SetCrystalNumber(rhs.GetCrystalNumber());
238
239 SetClassType(rhs.GetClassType());
240
241 return *this;
242}
243
244void TChannel::SetName(const char* tmpName)
245{
246 if(strlen(tmpName) == 0) { return; }
247 TNamed::SetName(tmpName);
248 // do not parse the default name
249 if(strcmp(tmpName, "DefaultTChannel") != 0) {
250 fMnemonic.Value()->Parse(GetName());
251 }
252}
253
255{
256 int channels_found = ParseInputData(fFileData.c_str(), "q", EPriority::kRootFile);
257 if(gFile != nullptr) {
258 std::cout << "Successfully read " << channels_found << " TChannels from " << CYAN << gFile->GetName() << RESET_COLOR << std::endl;
259 } else {
260 std::cout << "Successfully read " << channels_found << " TChannels" << std::endl;
261 }
262}
263
264bool TChannel::CompareChannels(const TChannel* chana, const TChannel* chanb)
265{
266 /// Compares the names of the two TChannels.
267 /// Returns true if the name of chana goes lexicographically before the name of chanb.
268 std::string namea(chana->GetName());
269
270 return namea.compare(chanb->GetName()) < 0;
271}
272
274{
275 /// Safely deletes fChannelMap and fChannelNumberMap
276 for(auto iter : *fChannelMap) {
277 delete iter.second;
278 // These maps should point to the same pointers, so this should clear out both
279 iter.second = nullptr;
280 }
281 fChannelMap->clear();
282 fChannelNumberMap->clear();
283}
284
285void TChannel::AddChannel(TChannel* chan, Option_t* opt)
286{
287 /// Add a TChannel to fChannelMap. If the TChannel doesn't exist, create a new TChannel and add that the fChannelMap.
288 /// Options:
289 /// "overwrite" - The TChannel in the fChannelMap at the same address is overwritten.
290 /// If this option is not specified, an Error is returned if the TChannel already
291 /// exists in the fChannelMap.
292 /// "save" - The temporary channel is not deleted after being placed in the map.
293 if(chan == nullptr) {
294 return;
295 }
296 if(fChannelMap->count(chan->GetAddress()) == 1) { // if this channel exists
297 if(strcmp(opt, "overwrite") == 0) {
298 TChannel* oldchan = GetChannel(chan->GetAddress());
299 int oldNumber = oldchan->GetNumber();
300 oldchan->OverWriteChannel(chan);
301 // Need to also update the channel number map RD
302 if(oldNumber != oldchan->GetNumber()) {
303 // channel number has changed so we need to delete the old one and insert the new one
304 fChannelNumberMap->erase(oldNumber);
305 if((oldchan->GetNumber() != 0) && (fChannelNumberMap->count(oldchan->GetNumber()) == 0)) {
306 fChannelNumberMap->insert(std::make_pair(oldchan->GetNumber(), oldchan));
307 }
308 }
309 return;
310 }
311 std::cout << "Trying to add a channel that already exists!" << std::endl;
312 return;
313 }
314 if((chan->GetAddress() & 0x00ffffff) == 0x00ffffff) {
315 // this is the default tigress value for i am not there.
316 // we should not imclude it in the map.
317 delete chan;
318 } else {
319 // We need to update the channel maps to correspond to the new channel that has been added.
320 fChannelMap->insert(std::make_pair(chan->GetAddress(), chan));
321 if((chan->GetNumber() != 0) && (fChannelNumberMap->count(chan->GetNumber()) == 0)) {
322 fChannelNumberMap->insert(std::make_pair(chan->GetNumber(), chan));
323 }
324 }
325}
326
328{
329 /// Overwrites the current TChannel with chan.
330 SetAddress(chan->GetAddress());
335 SetName(chan->GetName());
336
337 SetAllENGCoefficients(TPriorityValue<std::vector<std::vector<Float_t>>>(chan->GetAllENGCoeff(), EPriority::kForce));
338 SetENGRanges(TPriorityValue<std::vector<std::pair<double, double>>>(chan->GetENGRanges(), EPriority::kForce));
339 SetAllENGChi2(TPriorityValue<std::vector<double>>(chan->GetAllENGChi2(), EPriority::kForce));
341 SetCFDCoefficients(TPriorityValue<std::vector<double>>(chan->GetCFDCoeff(), EPriority::kForce));
342 SetLEDCoefficients(TPriorityValue<std::vector<double>>(chan->GetLEDCoeff(), EPriority::kForce));
344 SetEFFCoefficients(TPriorityValue<std::vector<double>>(chan->GetEFFCoeff(), EPriority::kForce));
345 SetCTCoefficients(TPriorityValue<std::vector<double>>(chan->GetCTCoeff(), EPriority::kForce));
347
352
354
355 SetWaveParam(chan->GetWaveParam());
356
362 SetClassType(chan->GetClassType());
363}
364
366{
367 /// Sets the current TChannel to chan
369 SetNumber(chan->fNumber);
370 SetStream(chan->fStream);
371 if(strcmp(chan->GetName(), "DefaultTChannel") != 0) { SetName(chan->GetName()); } // don't overwrite an existing name by the default name
377 SetAllENGChi2(chan->fENGChi2);
385 SetCFDChi2(chan->fCFDChi2);
386 SetLEDChi2(chan->fLEDChi2);
387 SetTIMEChi2(chan->fTIMEChi2);
388 SetEFFChi2(chan->fEFFChi2);
390 SetWaveParam(chan->GetWaveParam());
394
395 SetClassType(chan->GetClassType());
396}
397
399{
400 /// If there is information in the chan, the current TChannel with the same address is updated with that information.
401 if(chan == nullptr) {
402 return 0;
403 }
404 TChannel* oldchan = GetChannel(chan->GetAddress()); // look for already existing channel at this address
405 if(oldchan == nullptr) {
406 return 0;
407 }
408 oldchan->AppendChannel(chan);
409
410 return 0;
411}
412
414{
415 if(!fChannelMap->empty()) {
416 return fChannelMap->begin()->second;
417 }
418 return nullptr;
419}
420
421void TChannel::Clear(Option_t*)
422{
423 /// Clears all fields of a TChannel. There are currently no options to be specified.
424 fAddress = 0xffffffff;
427 // fDigitizerType.Reset(EDigitizer::kDefault);
428 fNumber.Reset(0);
429 fStream.Reset(0);
430 fUseCalFileInt.Reset(false);
431
432 fDetectorNumber = -1;
433 fSegmentNumber = -1;
434 fCrystalNumber = -1;
436 fTimeDrift.Reset(0);
437
439
441 SetName("DefaultTChannel");
442
443 fENGCoefficients.Reset(std::vector<std::vector<Float_t>>());
444 fENGRanges.Reset(std::vector<std::pair<double, double>>());
445 fENGChi2.Reset(std::vector<double>());
446 fENGDriftCoefficents.Reset(std::vector<Float_t>());
447 fCFDCoefficients.Reset(std::vector<double>());
448 fCFDChi2.Reset(0.0);
449 fLEDCoefficients.Reset(std::vector<double>());
450 fLEDChi2.Reset(0.0);
451 fTIMECoefficients.Reset(std::vector<double>());
452 fTIMEChi2.Reset(0.0);
453 fEFFCoefficients.Reset(std::vector<double>());
454 fEFFChi2.Reset(0.0);
455 fCTCoefficients.Reset(std::vector<double>());
456 fEnergyNonlinearity.Reset(TGraph());
457}
458
459TChannel* TChannel::GetChannel(unsigned int temp_address, bool warn)
460{
461 /// Returns the TChannel at the specified address. If the address doesn't exist, returns an empty gChannel.
462
463 TChannel* chan = nullptr;
464 if(fChannelMap->count(temp_address) == 1) { // found channel
465 chan = fChannelMap->at(temp_address);
466 }
467 if(warn && chan == nullptr) {
468 if(fMissingChannelMap->find(temp_address) == fMissingChannelMap->end()) {
469 // if there are threads running we're not in interactive mode, so we print a warning about sorting
471 std::ostringstream str;
472 str << RED << "Failed to find channel for address " << hex(temp_address, 4) << ", this channel won't get sorted properly!" << RESET_COLOR << std::endl;
473 std::cerr << str.str();
474 }
475 fMissingChannelMap->insert(std::pair<unsigned int, int>(temp_address, 0));
476 }
477 ++(*fMissingChannelMap)[temp_address];
478 }
479 return chan;
480}
481
483{
484 /// Returns the TChannel based on the channel number and not the channel address.
485 TChannel* chan = nullptr;
486 try {
487 chan = fChannelNumberMap->at(temp_num);
488 } catch(const std::out_of_range& oor) {
489 return nullptr;
490 }
491 return chan;
492}
493
495{
496 /// Finds the TChannel by the name of the channel
497 TChannel* chan = nullptr;
498 if(ccName == nullptr) {
499 return chan;
500 }
501
502 std::string name = ccName;
503 if(name.length() == 0) {
504 return chan;
505 }
506
507 for(auto iter : *fChannelMap) {
508 chan = iter.second;
509 std::string channelName = chan->GetName();
510 if(channelName.compare(0, name.length(), name) == 0) {
511 return chan;
512 }
513 }
514
515 return nullptr;
516}
517
518std::vector<TChannel*> TChannel::FindChannelByRegEx(const char* ccName)
519{
520 /// Finds the TChannel by the name of the channel
521 std::vector<TChannel*> result;
522 if(ccName == nullptr) {
523 return result;
524 }
525
526 std::regex regex(ccName);
527
528 TChannel* chan = nullptr;
529 for(auto iter : *fChannelMap) {
530 chan = iter.second;
531 std::string channelName = chan->GetName();
532 if(std::regex_match(channelName, regex)) {
533 result.push_back(chan);
534 }
535 }
536
537 return result;
538}
539
540void TChannel::SetAddress(unsigned int tmpadd)
541{
542 /// Sets the address of a TChannel and also overwrites that channel if it is in the channel map
543 for(auto iter1 : *fChannelMap) {
544 if(iter1.second == this) {
545 std::cout << "Channel at address: " << hex(fAddress, 4)
546 << " already exists. Please use AddChannel() or OverWriteChannel() to change this TChannel"
547 << std::dec << std::endl;
548 break;
549 }
550 }
551 fAddress = tmpadd;
552}
553
555{
556 /// Erases the ENGCoefficients vector
557 fENGCoefficients.Address()->clear();
558 fENGRanges.Address()->clear();
559 fENGChi2.Address()->clear();
560 fENGDriftCoefficents.Address()->clear();
561}
562
564{
565 /// Erases the CFDCoefficients vector
566 fCFDCoefficients.Address()->clear();
567}
568
570{
571 /// Erases the LEDCoefficients vector
572 fLEDCoefficients.Address()->clear();
573}
574
576{
577 /// Erases the TimeCal vector
578 fTIMECoefficients.Address()->clear();
579}
580
582{
583 /// Erases the EffCal vector
584 fEFFCoefficients.Address()->clear();
585}
586
588{
589 // Erases the CTCal vector
590 fCTCoefficients.Address()->clear();
591}
592
597
599{
600 /// Erases all Cal vectors
606 DestroyCTCal();
607}
608
609double TChannel::CalibrateENG(int charge, int temp_int) const
610{
611 /// Returns the calibrated energy of the channel when a charge is passed to it.
612 /// This is done by first adding a random number between 0 and 1 to the charge
613 /// bin. This is then taken and divided by the integration parameter. The
614 /// polynomial energy calibration formula is then applied to get the calibrated
615 /// energy.
616 if(charge == 0) {
617 return 0.0000;
618 }
619
620 // We need to add a random number between 0 and 1 before calibrating to avoid
621 // binning issues.
622 return CalibrateENG(static_cast<double>(charge) + gRandom->Uniform(), temp_int);
623}
624
625double TChannel::CalibrateENG(double charge, int temp_int) const
626{
627 /// Returns the calibrated energy of the channel when a charge is passed to it.
628 /// This is divided by the integration parameter. The
629 /// polynomial energy calibration formula is then applied to get the calibrated
630 /// energy.
631 if(charge == 0) {
632 return 0.0000;
633 }
634
635 if(temp_int == 0) {
636 if(fIntegration.Value() != 0) {
637 temp_int = fIntegration.Value();
638 } else {
639 temp_int = 1;
640 }
641 }
642
643 return CalibrateENG((charge) / static_cast<double>(temp_int));
644}
645
646double TChannel::CalibrateENG(double charge) const
647{
648 /// Returns the calibrated energy. The polynomial energy calibration formula is
649 /// applied to get the calibrated energy. This function does not use the
650 /// integration parameter. If multiple ranges are present, the calibration of the
651 /// range is used. In overlap regions the range used is chosen randomly.
652 if(fENGCoefficients.empty()) {
653 return charge;
654 }
655 // select range to use, they should be sorted
656 size_t currentRange = 0;
657 if(!fENGRanges.empty()) {
658 // we need a boolean to tell us if we found a range as the test
659 // currentRange+1 == fENGRanges.size()
660 // fails if the charge is in the overlap between the second-to-last and last range
661 // and the last range was selected
662 bool foundRange = false;
663 for(currentRange = 0; currentRange + 1 < fENGRanges.size(); ++currentRange) {
664 // check if the current range covers this charge
665 if(fENGRanges.Value()[currentRange].first < charge && charge < fENGRanges.Value()[currentRange].second) {
666 // check if there is an overlap with the next range in which case we select that one in 50% of the cases
667 if(fENGRanges.Value()[currentRange + 1].first < charge && charge < fENGRanges.Value()[currentRange + 1].second &&
668 gRandom->Uniform() > 0.5) {
669 ++currentRange;
670 }
671 foundRange = true;
672 break;
673 }
674 }
675 if(!foundRange) {
676 currentRange = fENGRanges.size() - 1;
677 if(charge < fENGRanges[currentRange].first || fENGRanges[currentRange].second < charge) {
678 std::cerr << "Charge " << charge << " outside all ranges of calibration (first " << fENGRanges.front().first << " - " << fENGRanges.front().second << ", last " << fENGRanges.back().first << " - " << fENGRanges.back().second << ")" << std::endl;
679 }
680 }
681 }
682
683 // apply the drift correction first
684 if(!fENGDriftCoefficents.empty()) {
685 double corrCharge = -fENGDriftCoefficents[0]; // ILL subtracts the offset instead of adding it
686 for(size_t i = 1; i < fENGDriftCoefficents.size(); i++) {
687 corrCharge += fENGDriftCoefficents[i] * pow(charge, static_cast<double>(i));
688 }
689 charge = corrCharge;
690 }
691 // if we had drift correction charge is now the corrected charge, otherwise it is still the charge
692 double cal_chg = fENGCoefficients[currentRange][0];
693 for(size_t i = 1; i < fENGCoefficients[currentRange].size(); i++) {
694 cal_chg += fENGCoefficients[currentRange][i] * pow((charge), static_cast<double>(i));
695 }
696 return cal_chg;
697}
698
699double TChannel::CalibrateCFD(int cfd) const
700{
701 /// Calibrates the CFD properly.
702 return CalibrateCFD(static_cast<double>(cfd) + gRandom->Uniform());
703}
704
705double TChannel::CalibrateCFD(double cfd) const
706{
707 /// Returns the calibrated CFD. The polynomial CFD calibration formula is
708 /// applied to get the calibrated CFD.
709 if(fCFDCoefficients.empty()) {
710 return cfd;
711 }
712
713 double cal_cfd = 0.0;
714 // std::cout<<cfd<<":";
715 for(size_t i = 0; i < fCFDCoefficients.size(); i++) {
716 cal_cfd += fCFDCoefficients[i] * pow(cfd, static_cast<double>(i));
717 // std::cout<<" "<<i<<" - "<<fCFDCoefficients[i]<<" = "<<cal_cfd;
718 }
719 // std::cout<<std::endl;
720
721 return cal_cfd;
722}
723
724double TChannel::CalibrateLED(int led) const
725{
726 /// Calibrates the LED
727 return CalibrateLED(static_cast<double>(led) + gRandom->Uniform());
728}
729
730double TChannel::CalibrateLED(double led) const
731{
732 /// Returns the calibrated LED. The polynomial LED calibration formula is
733 /// applied to get the calibrated LED.
734 if(fLEDCoefficients.empty()) {
735 return led;
736 }
737
738 double cal_led = 0.0;
739 for(size_t i = 0; i < fLEDCoefficients.size(); i++) {
740 cal_led += fLEDCoefficients[i] * pow(led, static_cast<double>(i));
741 }
742 return cal_led;
743}
744
745double TChannel::CalibrateTIME(int chg) const
746{
747 /// Calibrates the time spectrum
748 if(fTIMECoefficients.size() != 3 || (chg < 1)) {
749 return 0.0000;
750 }
751 return CalibrateTIME((CalibrateENG(chg)));
752}
753
754double TChannel::CalibrateTIME(double energy) const
755{
756 /// uses the values stored in TIMECOefficients to calculate a
757 /// "walk correction" factor. This function returns the correction
758 /// not an adjusted time stamp! pcb.
759 if(fTIMECoefficients.size() != 3 || (energy < 3.0)) {
760 return 0.0000;
761 }
762
763 double timeCorrection = 0.0;
764
765 timeCorrection = fTIMECoefficients.at(0) + (fTIMECoefficients.at(1) * pow(energy, fTIMECoefficients.at(2)));
766
767 return timeCorrection;
768}
769
770double TChannel::CalibrateEFF(double) const
771{
772 /// This needs to be added
773 return 1.0;
774}
775
776void TChannel::SetUseCalFileIntegration(const std::string& mnemonic, bool flag, EPriority prio)
777{
778 /// Writes this UseCalFileIntegration to all channels in the current TChannel Map
779 /// that starts with the mnemonic. Use "" to write to ALL channels
780 /// WARNING: This is case sensitive!
781 std::unordered_map<unsigned int, TChannel*>::iterator mapit;
782 std::unordered_map<unsigned int, TChannel*>* chanmap = TChannel::GetChannelMap();
783 for(mapit = chanmap->begin(); mapit != chanmap->end(); mapit++) {
784 if(mnemonic.empty() || (strncmp(mapit->second->GetName(), mnemonic.c_str(), mnemonic.size()) == 0)) {
785 mapit->second->SetUseCalFileIntegration(TPriorityValue<bool>(flag, prio));
786 }
787 }
788}
789
790void TChannel::SetIntegration(const std::string& mnemonic, int tmpint, EPriority prio)
791{
792 // Writes this integration to all channels in the current TChannel Map
793 // that starts with the mnemonic. Use "" to write to ALL channels
794 // WARNING: This is case sensitive!
795 std::unordered_map<unsigned int, TChannel*>::iterator mapit;
796 std::unordered_map<unsigned int, TChannel*>* chanmap = TChannel::GetChannelMap();
797 for(mapit = chanmap->begin(); mapit != chanmap->end(); mapit++) {
798 if(mnemonic.empty() || (strncmp(mapit->second->GetName(), mnemonic.c_str(), mnemonic.size()) == 0)) {
799 mapit->second->SetIntegration(TPriorityValue<int>(tmpint, prio));
800 }
801 }
802}
803
804void TChannel::SetDigitizerType(const std::string& mnemonic, const char* tmpstr, EPriority prio)
805{
806 // Writes this digitizer type to all channels in the current TChannel Map
807 // that starts with the mnemonic. Use "" to write to ALL channels
808 // WARNING: This is case sensitive!
809 std::unordered_map<unsigned int, TChannel*>::iterator mapit;
810 std::unordered_map<unsigned int, TChannel*>* chanmap = TChannel::GetChannelMap();
811 for(mapit = chanmap->begin(); mapit != chanmap->end(); mapit++) {
812 if(mnemonic.empty() || (strncmp(mapit->second->GetName(), mnemonic.c_str(), mnemonic.size()) == 0)) {
813 mapit->second->SetDigitizerType(TPriorityValue<std::string>(tmpstr, prio));
814 }
815 }
816}
817
818void TChannel::PrintCTCoeffs(Option_t*) const
819{
820 /// Prints out the current TChannel.
821 std::cout << GetName() << "\t{\n"; //,channelname.c_str();
822 std::cout << "Name: " << GetName() << std::endl;
823 std::cout << "Number: " << fNumber << std::endl;
824 std::cout << "Address: " << hex(fAddress, 8) << std::endl;
825 for(double fCTCoefficient : fCTCoefficients) {
826 std::cout << fCTCoefficient << "\t";
827 }
828 std::cout << std::endl;
829 std::cout << "}\n";
830 std::cout << "//====================================//\n";
831}
832
833void TChannel::Print(Option_t*) const
834{
835 /// Prints out the current TChannel.
836 std::cout << PrintToString();
837}
838
839std::string TChannel::PrintCTToString(Option_t*) const
840{
841 std::string buffer;
842 buffer.append("\n");
843 buffer.append(GetName());
844 buffer.append("\t{\n"); //,channelname.c_str();
845 buffer.append("Name: ");
846 buffer.append(GetName());
847 buffer.append("\n");
848 buffer.append(Form("Number: %d\n", fNumber.Value()));
849 buffer.append(Form("Address: 0x%08x\n", fAddress));
850 if(!fCTCoefficients.empty()) {
851 buffer.append("CTCoeff: ");
852 for(double fCTCoefficient : fCTCoefficients) {
853 buffer.append(Form("%f\t", fCTCoefficient));
854 }
855 buffer.append("\n");
856 }
857 buffer.append("}\n");
858
859 buffer.append("//====================================//\n");
860
861 return buffer;
862}
863
864std::string TChannel::PrintToString(Option_t*) const
865{
866 std::ostringstream str;
867
868 str << GetName() << "\t{" << std::endl; //,channelname.c_str();
869 str << "Type: ";
870 if(GetClassType() != nullptr) {
871 str << GetClassType()->GetName() << std::endl;
872 } else {
873 str << "None" << std::endl;
874 }
875
876 str << "Name: " << GetName() << std::endl;
877 str << "Number: " << fNumber << std::endl;
878 str << "Address: " << hex(fAddress, 4) << std::dec << std::endl;
879 if(!fDigitizerTypeString.empty()) {
880 str << "Digitizer: " << fDigitizerTypeString << std::endl;
881 }
882 str << "TimeOffset: " << fTimeOffset << std::endl;
883 str << "TimeDrift: " << fTimeDrift << std::endl;
884 str << "Integration: " << fIntegration << std::endl;
885 if(!fENGCoefficients.empty()) {
886 for(size_t i = 0; i < fENGCoefficients.size(); ++i) {
887 if(fENGCoefficients.size() == 1) {
888 str << "ENGCoeff: ";
889 } else {
890 str << "ENGCoeff: range " << i << "\t";
891 }
892 for(auto coeff : fENGCoefficients[i]) {
893 str << coeff << "\t";
894 }
895 str << std::endl;
896 }
897 }
898 if(!fENGChi2.empty()) {
899 for(size_t i = 0; i < fENGChi2.size(); ++i) {
900 if(fENGCoefficients.size() == 1) {
901 str << "ENGChi2: " << fENGChi2[i] << std::endl;
902 } else {
903 str << "ENGChi2: range " << i << "\t" << fENGChi2[i] << std::endl;
904 }
905 }
906 }
907 if(!fENGRanges.empty()) {
908 for(size_t i = 0; i < fENGRanges.size(); ++i) {
909 str << "ENGRange: " << i << "\t" << fENGRanges[i].first << " " << fENGRanges[i].second << std::endl;
910 }
911 }
912 if(!fENGDriftCoefficents.empty()) {
913 str << "ENGDrift: ";
914 auto oldPrecision = str.precision();
915 str.precision(9);
916 for(auto coeff : fENGDriftCoefficents) {
917 str << coeff << "\t";
918 }
919 str.precision(oldPrecision);
920 str << std::endl;
921 }
922 if(!fEFFCoefficients.empty()) {
923 str << "EFFCoeff: ";
924 for(auto coeff : fEFFCoefficients) {
925 str << coeff << "\t";
926 }
927 str << std::endl;
928 }
929 if(fEFFChi2 != 0) {
930 str << "EFFChi2: " << fEFFChi2 << std::endl;
931 }
932 if(!fCFDCoefficients.empty()) {
933 str << "CFDCoeff: ";
934 for(auto coeff : fCFDCoefficients) {
935 str << coeff << "\t";
936 }
937 str << std::endl;
938 }
939 if(fEnergyNonlinearity.Value().GetN() > 0) {
940 str << "EnergyNonlinearity: ";
941 double* x = fEnergyNonlinearity.Value().GetX();
942 double* y = fEnergyNonlinearity.Value().GetY();
943 for(int i = 0; i < fEnergyNonlinearity.Value().GetN(); ++i) {
944 str << x[i] << "\t" << y[i] << "\t";
945 }
946 str << std::endl;
947 }
948 if(!fCTCoefficients.empty()) {
949 str << "CTCoeff: ";
950 for(auto coeff : fCTCoefficients) {
951 str << coeff << "\t";
952 }
953 str << std::endl;
954 }
955 if(!fTIMECoefficients.empty()) {
956 str << "TIMECoeff: ";
957 for(auto coeff : fTIMECoefficients) {
958 str << coeff << "\t";
959 }
960 str << std::endl;
961 }
962 if(fUseCalFileInt) {
963 str << "FileInt: " << fUseCalFileInt << std::endl;
964 }
965 if(UseWaveParam()) {
966 str << "RiseTime: " << WaveFormShape.TauRise << std::endl;
967 str << "DecayTime: " << WaveFormShape.TauDecay << std::endl;
968 str << "BaseLine: " << WaveFormShape.BaseLine << std::endl;
969 }
970 str << "}" << std::endl;
971 str << "//====================================//" << std::endl;
972 std::string buffer = str.str();
973
974 return buffer;
975}
976
977std::vector<TChannel*> TChannel::SortedChannels()
978{
979 std::vector<TChannel*> chanVec;
980 for(auto iter : *fChannelMap) {
981 if(iter.second != nullptr) {
982 chanVec.push_back(iter.second);
983 }
984 }
985
986 // This orders channels nicely
987 std::sort(chanVec.begin(), chanVec.end(), TChannel::CompareChannels);
988
989 return chanVec;
990}
991
992void TChannel::WriteCalFile(const std::string& outfilename)
993{
994 /// Prints the context of addresschannelmap formatted correctly to stdout if
995 /// no file name is passed to the function. If a file name is passed to the function
996 /// prints the context of addresschannelmap formatted correctly to a file with the given
997 /// name. This will earse and rewrite the file if the file already exisits!
998
999 std::vector<TChannel*> chanVec = SortedChannels();
1000
1001 if(outfilename.length() > 0) {
1002 std::ofstream calout;
1003 calout.open(outfilename.c_str());
1004 for(auto* iter_vec : chanVec) {
1005 std::string chanstr = iter_vec->PrintToString();
1006 calout << chanstr.c_str();
1007 calout << std::endl;
1008 }
1009 calout << std::endl;
1010 calout.close();
1011 } else {
1012 for(auto* iter_vec : chanVec) {
1013 iter_vec->Print();
1014 }
1015 }
1016}
1017
1018void TChannel::WriteCTCorrections(const std::string& outfilename)
1019{
1020 std::vector<TChannel*> chanVec = SortedChannels();
1021
1022 if(outfilename.length() > 0) {
1023 std::ofstream calout;
1024 calout.open(outfilename.c_str());
1025 for(auto* iter_vec : chanVec) {
1026 if(iter_vec->fCTCoefficients.empty()) { continue; }
1027 std::string chanstr = iter_vec->PrintCTToString();
1028 calout << chanstr.c_str();
1029 calout << std::endl;
1030 }
1031 calout << std::endl;
1032 calout.close();
1033 } else {
1034 for(auto* iter_vec : chanVec) {
1035 iter_vec->PrintCTCoeffs();
1036 }
1037 }
1038}
1039
1041{
1042 /// writes any TChannels in memory to the internal buffer
1043 /// fFileData. Can be used to over write info that is there
1044 /// or create the buffer if the channels originated from the odb.
1045
1046 std::vector<TChannel*> chanVec = SortedChannels();
1047
1048 std::string data;
1049
1050 for(auto* iter_vec : chanVec) {
1051 data.append(iter_vec->PrintToString());
1052 }
1053 fFileData.clear();
1054 fFileData = data;
1055}
1056
1058{
1059 if(!gFile) {
1060 return 0;
1061 }
1062
1063 TFile* tempf = gFile->CurrentFile();
1064
1065 return ReadFile(tempf);
1066}
1067
1068Int_t TChannel::ReadCalFromFile(TFile* tempf, Option_t*)
1069{
1070 /// Reads the TChannel information from a TFile if it has already been written to that File.
1071 if(tempf == nullptr) {
1072 return 0;
1073 }
1074
1075 return ReadFile(tempf);
1076}
1077
1078Int_t TChannel::ReadCalFromTree(TTree* tree, Option_t*)
1079{
1080 /// Reads the TChannel information from a Tree if it has already been written to that Tree.
1081 if(tree == nullptr) {
1082 return 0;
1083 }
1084
1085 TFile* tempf = tree->GetCurrentFile();
1086
1087 return ReadFile(tempf);
1088}
1089
1090Int_t TChannel::ReadFile(TFile* tempf)
1091{
1092 TList* list = tempf->GetListOfKeys();
1093 TIter iter(list);
1094 while(TKey* key = static_cast<TKey*>(iter.Next())) {
1095 if((key == nullptr) || (strcmp(key->GetClassName(), "TChannel") != 0)) {
1096 continue;
1097 }
1098 key->ReadObj();
1099 return GetNumberOfChannels();
1100 }
1101 return 0;
1102}
1103
1104Int_t TChannel::ReadCalFile(std::ifstream& infile)
1105{
1106 if(!infile.is_open()) {
1107 std::cout << DRED << "could not open file." << RESET_COLOR << std::endl;
1108 return -2;
1109 }
1110
1111 infile.seekg(0, std::ios::end);
1112 int64_t length = infile.tellg();
1113 if(length < 1) {
1114 return -2;
1115 }
1116
1117 auto* buffer = new char[length + 1]; //+1 for the null character to terminate the string
1118 infile.seekg(0, std::ios::beg);
1119 infile.read(buffer, length);
1120 buffer[length] = '\0';
1121
1122 int channelsFound = ParseInputData(buffer, "q", EPriority::kInputFile);
1123 SaveToSelf();
1124
1125 fChannelNumberMap->clear(); // This isn't the nicest way to do this but will keep us consistent.
1126
1127 for(auto mapiter : *fChannelMap) {
1128 fChannelNumberMap->insert(std::make_pair(mapiter.second->GetNumber(), mapiter.second));
1129 }
1130
1131 return channelsFound;
1132}
1133
1134Int_t TChannel::ReadCalFile(const char* filename)
1135{
1136 /// Makes TChannels from a cal file to be used as the current calibration until grsisort
1137 /// is closed. Returns the number of channels properly read in.
1138 std::string infilename(filename);
1139
1140 if(infilename.length() == 0) {
1141 return -1;
1142 }
1143
1144 std::cout << "Reading from calibration file: " << CYAN << filename << RESET_COLOR << ".....";
1145 std::ifstream infile(infilename.c_str());
1146
1147 auto channelsFound = ReadCalFile(infile);
1148
1149 infile.close();
1150
1151 return channelsFound;
1152}
1153
1155{
1156 /// This function saves the current cal-file to fFileData.
1157 /// For some reason it does the latter not by using WriteCalBuffer ???
1158 std::ostringstream buffer;
1159 std::streambuf* std_out = std::cout.rdbuf(buffer.rdbuf());
1160 WriteCalFile();
1161 fFileData.assign(buffer.str());
1162 std::cout.rdbuf(std_out);
1163}
1164
1165Int_t TChannel::ParseInputData(const char* inputdata, Option_t* opt, EPriority prio)
1166{
1167 std::istringstream infile(inputdata);
1168
1169 TChannel* channel = nullptr;
1170
1171 std::string line;
1172 int linenumber = 0;
1173 int newchannels = 0;
1174
1175 // bool creatednewchannel = false;
1176 bool brace_open = false;
1177 // int detector = 0;
1178 std::string name;
1179
1180 // Parse the cal file. This is useful because if the cal file contains something that
1181 // the parser does not recognize, it just skips it!
1182 while(std::getline(infile, line)) {
1183 linenumber++;
1184 trimWS(line);
1185 size_t comment = line.find("//");
1186 if(comment != std::string::npos) {
1187 line = line.substr(0, comment);
1188 }
1189 if(line.length() == 0u) {
1190 continue;
1191 }
1192 size_t openbrace = line.find('{');
1193 size_t closebrace = line.find('}');
1194 size_t colon = line.find(':');
1195
1196 if(openbrace == std::string::npos && closebrace == std::string::npos && colon == std::string::npos) {
1197 continue;
1198 }
1199
1200 //*************************************//
1201 if(closebrace != std::string::npos) {
1202 brace_open = false;
1203 if(channel != nullptr) {
1204 TChannel* currentchan = GetChannel(channel->GetAddress(), false);
1205 if(currentchan == nullptr) {
1206 AddChannel(channel); // consider using a default option here
1207 newchannels++;
1208 } else {
1209 currentchan->UpdateChannel(channel);
1210 delete channel;
1211 newchannels++;
1212 }
1213 } else {
1214 delete channel;
1215 }
1216 channel = nullptr;
1217 name.clear();
1218 }
1219 //*************************************//
1220 if(openbrace != std::string::npos) {
1221 brace_open = true;
1222 name = line.substr(0, openbrace);
1223 trimWS(name);
1224 channel = new TChannel("");
1225 if(!name.empty()) { channel->SetName(name.c_str()); }
1226 }
1227 //*************************************//
1228 if(brace_open) {
1229 size_t ntype = line.find(':');
1230 if(ntype != std::string::npos) {
1231 std::string type = line.substr(0, ntype);
1232 line = line.substr(ntype + 1, line.length());
1233 trimWS(line);
1234 std::istringstream str(line);
1235 // transform type to upper case
1236 std::transform(type.begin(), type.end(), type.begin(), ::toupper);
1237 if(type == "NAME") {
1238 channel->SetName(line.c_str());
1239 } else if(type == "ADDRESS") {
1240 unsigned int tempadd = 0;
1241 str >> tempadd;
1242 if(tempadd == 0) { // maybe it is in hex...
1243 std::stringstream newss;
1244 newss << std::hex << line;
1245 newss >> tempadd;
1246 }
1247 tempadd = tempadd & 0x00ffffff; // front end number is not included in the odb...
1248 channel->SetAddress(tempadd);
1249 } else if(type == "INTEGRATION") {
1250 int tempint = 0;
1251 str >> tempint;
1252 channel->SetIntegration(TPriorityValue<int>(tempint, prio));
1253 } else if(type == "NUMBER") {
1254 int tempnum = 0;
1255 str >> tempnum;
1256 channel->SetNumber(TPriorityValue<int>(tempnum, prio));
1257 } else if(type == "TIMEOFFSET") {
1258 Long64_t tempoff = 0;
1259 str >> tempoff;
1260 channel->SetTimeOffset(TPriorityValue<Long64_t>(tempoff, prio));
1261 } else if(type == "TIMEDRIFT") {
1262 double tempdrift = 0.;
1263 str >> tempdrift;
1264 channel->SetTimeDrift(TPriorityValue<double>(tempdrift, prio));
1265 } else if(type == "STREAM") {
1266 int tempstream = 0;
1267 str >> tempstream;
1268 channel->SetStream(TPriorityValue<int>(tempstream, prio));
1269 } else if(type == "DIGITIZER") {
1270 channel->SetDigitizerType(TPriorityValue<std::string>(line, prio));
1271 } else if(type == "ENGCHI2") {
1272 size_t range = line.find("range");
1273 if(range != std::string::npos) {
1274 line = line.substr(range + 5, line.length());
1275 trimWS(line);
1276 str.str(line);
1277 str >> range;
1278 } else {
1279 range = 0;
1280 }
1281 double tempdbl = 0.;
1282 str >> tempdbl;
1283 channel->SetENGChi2(TPriorityValue<double>(tempdbl, prio), range);
1284 } else if(type == "CFDCHI2") {
1285 double tempdbl = 0.;
1286 str >> tempdbl;
1287 channel->SetCFDChi2(TPriorityValue<double>(tempdbl, prio));
1288 } else if(type == "LEDCHI2") {
1289 double tempdbl = 0.;
1290 str >> tempdbl;
1291 channel->SetLEDChi2(TPriorityValue<double>(tempdbl, prio));
1292 } else if(type == "TIMECHI2") {
1293 double tempdbl = 0.;
1294 str >> tempdbl;
1295 channel->SetTIMEChi2(TPriorityValue<double>(tempdbl, prio));
1296 } else if(type == "EFFCHI2") {
1297 double tempdbl = 0.;
1298 str >> tempdbl;
1299 channel->SetEFFChi2(TPriorityValue<double>(tempdbl, prio));
1300 } else if(type == "ENGCOEFF") {
1301 size_t range = line.find("range");
1302 if(range != std::string::npos) {
1303 line = line.substr(range + 5, line.length());
1304 trimWS(line);
1305 str.str(line);
1306 str >> range;
1307 } else {
1308 range = 0;
1309 }
1310 if(range == 0) {
1311 channel->DestroyENGCal();
1312 channel->fENGCoefficients.SetPriority(prio);
1313 }
1314 float value = 0.;
1315 while(!(str >> value).fail()) {
1316 channel->AddENGCoefficient(value, range);
1317 }
1318 } else if(type == "ENGRANGE") {
1319 size_t range = 0;
1320 double low = 0.;
1321 double high = 0.;
1322 str >> range >> low >> high;
1323 channel->SetENGRange(std::make_pair(low, high), range);
1324 } else if(type == "ENGDRIFT") {
1325 channel->fENGDriftCoefficents.SetPriority(prio);
1326 float value = 0.;
1327 while(!(str >> value).fail()) {
1328 channel->AddENGDriftCoefficent(value);
1329 }
1330 } else if(type == "LEDCOEFF") {
1331 channel->DestroyLEDCal();
1332 channel->fLEDCoefficients.SetPriority(prio);
1333 double value = 0.;
1334 while(!(str >> value).fail()) {
1335 channel->AddLEDCoefficient(value);
1336 }
1337 } else if(type == "CFDCOEFF") {
1338 channel->DestroyCFDCal();
1339 channel->fCFDCoefficients.SetPriority(prio);
1340 double value = 0.;
1341 while(!(str >> value).fail()) {
1342 channel->AddCFDCoefficient(value);
1343 }
1344 } else if(type == "TIMECOEFF" || type == "WALK") {
1345 channel->DestroyTIMECal();
1346 channel->fTIMECoefficients.SetPriority(prio);
1347 double value = 0.;
1348 while(!(str >> value).fail()) {
1349 channel->AddTIMECoefficient(value);
1350 }
1351 } else if(type == "CTCOEFF") {
1352 channel->DestroyCTCal();
1353 channel->fCTCoefficients.SetPriority(prio);
1354 double value = 0.;
1355 while(!(str >> value).fail()) {
1356 channel->AddCTCoefficient(value);
1357 }
1358 } else if(type == "ENERGYNONLINEARITY") {
1359 channel->DestroyEnergyNonlinearity();
1360 channel->fEnergyNonlinearity.SetPriority(prio);
1361 double x = 0.;
1362 double y = 0.;
1363 while(!(str >> x >> y).fail()) {
1364 channel->AddEnergyNonlinearityPoint(x, y);
1365 }
1366 channel->SetupEnergyNonlinearity();
1367 } else if(type == "EFFCOEFF") {
1368 channel->DestroyEFFCal();
1369 channel->fEFFCoefficients.SetPriority(prio);
1370 double value = 0.;
1371 while(!(str >> value).fail()) {
1372 channel->AddEFFCoefficient(value);
1373 }
1374 } else if(type == "FILEINT") {
1375 int tempstream = 0;
1376 str >> tempstream;
1377 if(tempstream > 0) {
1378 channel->SetUseCalFileIntegration(TPriorityValue<bool>(true, prio));
1379 } else {
1380 channel->SetUseCalFileIntegration(TPriorityValue<bool>(false, prio));
1381 }
1382 } else if(type == "RISETIME") {
1383 double tempdbl = 0.;
1384 str >> tempdbl;
1385 channel->SetWaveRise(tempdbl);
1386 } else if(type == "DECAYTIME") {
1387 double tempdbl = 0.;
1388 str >> tempdbl;
1389 channel->SetWaveDecay(tempdbl);
1390 } else if(type == "BASELINE") {
1391 double tempdbl = 0.;
1392 str >> tempdbl;
1393 channel->SetWaveBaseLine(tempdbl);
1394 } else {
1395 }
1396 }
1397 }
1398 }
1399 if(strcmp(opt, "q") != 0) {
1400 std::cout << "parsed " << linenumber << " lines." << std::endl;
1401 }
1402
1403 return newchannels;
1404}
1405
1406void TChannel::Streamer(TBuffer& R__b)
1407{
1408 SetBit(kCanDelete);
1409 UInt_t R__s = 0;
1410 UInt_t R__c = 0;
1411 if(R__b.IsReading()) { // reading from file
1412 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
1413 if(R__v != 0) {
1414 }
1415 TNamed::Streamer(R__b);
1416 {
1417 fMnemonicClass->Streamer(R__b);
1418 }
1419 if(R__v <= 5) {
1420 TString R__str;
1421 R__str.Streamer(R__b);
1422 }
1423 {
1424 TString R__str;
1425 R__str.Streamer(R__b);
1426 fFileData.assign(R__str.Data());
1427 }
1429 R__b.CheckByteCount(R__s, R__c, TChannel::IsA());
1430 } else { // writing to file
1431 R__c = R__b.WriteVersion(TChannel::IsA(), true);
1432 TNamed::Streamer(R__b);
1433 {
1434 fMnemonicClass->Streamer(R__b);
1435 }
1436 {
1437 TString R__str = fFileData.c_str();
1438 R__str.Streamer(R__b);
1439 }
1440 R__b.SetByteCount(R__c, true);
1441 }
1442}
1443
1444int TChannel::WriteToRoot(TFile* fileptr)
1445{
1446 /// Writes Cal File information to the tree
1447
1448 TChannel* chan = GetDefaultChannel();
1449 // Maintain old gDirectory info
1450 TDirectory* savdir = gDirectory;
1451
1452 if(chan == nullptr) {
1453 std::cout << "No TChannels found to write." << std::endl;
1454 return 0;
1455 }
1456 if(fileptr == nullptr) {
1457 fileptr = gDirectory->GetFile();
1458 }
1459
1460 // check if we got a file
1461 if(fileptr == nullptr) {
1462 std::cout << "Error, no file provided and no file open (gDirectory = " << gDirectory->GetName() << ")!" << std::endl;
1463 return 0;
1464 }
1465 fileptr->cd();
1466 std::string oldoption = std::string(fileptr->GetOption());
1467 if(oldoption == "READ") {
1468 fileptr->ReOpen("UPDATE");
1469 }
1470 if(!gDirectory) { // we don't compare to nullptr here, as ROOT >= 6.24.00 uses the TDirectoryAtomicAdapter structure with a bool() operator
1471 std::cout << "No file opened to write TChannel to." << std::endl;
1472 }
1473 TIter iter(gDirectory->GetListOfKeys());
1474
1475 bool found = false;
1476 std::string defaultName = "Channel";
1477 std::string defaultTitle = "TChannel";
1478 std::string channelbuffer = fFileData; // fFileData is the old TChannel information read from file
1479 WriteCalBuffer(); // replaces fFileData with the current channels
1480 std::string savedata = fFileData;
1481
1482 FILE* originalstdout = stdout;
1483 int fd = open("/dev/null", O_WRONLY); // turn off stdout.
1484 stdout = fdopen(fd, "w");
1485
1486 while(TKey* key = static_cast<TKey*>(iter.Next())) {
1487 if((key == nullptr) || (strcmp(key->GetClassName(), "TChannel") != 0)) {
1488 continue;
1489 }
1490 if(!found) {
1491 found = true;
1492 auto* curCh = static_cast<TChannel*>(key->ReadObj());
1493 defaultName.assign(curCh->GetName());
1494 defaultTitle.assign(curCh->GetTitle());
1495 }
1496 std::string cname = key->ReadObj()->GetName();
1497 cname.append(";*");
1498 gDirectory->Delete(cname.c_str());
1500 }
1501
1502 stdout = originalstdout; // Restore stdout
1503
1504 ParseInputData(savedata.c_str(), "q", EPriority::kRootFile);
1505 SaveToSelf();
1506 TChannel::ParseInputData(channelbuffer.c_str(), "q", EPriority::kRootFile);
1508 chan->SetNameTitle(defaultName.c_str(), defaultTitle.c_str());
1509 chan->Write("Channel", TObject::kOverwrite);
1510
1511 ParseInputData(savedata.c_str(), "q", EPriority::kRootFile);
1512 SaveToSelf();
1513
1514 std::cout << " " << GetNumberOfChannels() << " TChannels saved to " << gDirectory->GetFile()->GetName() << std::endl;
1515 if(oldoption == "READ") {
1516 std::cout << " Returning " << gDirectory->GetFile()->GetName() << " to \"READ\" mode." << std::endl;
1517 fileptr->ReOpen("READ");
1518 }
1519 savdir->cd(); // Go back to original gDirectory
1520
1521 return GetNumberOfChannels();
1522}
1523
1525{
1526 if(fDetectorNumber > -1) { //||fDetectorNumber==0x0fffffff)
1527 return fDetectorNumber;
1528 }
1529
1530 fDetectorNumber = static_cast<int32_t>(fMnemonic.Value()->ArrayPosition());
1531 return fDetectorNumber;
1532}
1533
1535{
1536 if(fSegmentNumber > -1) {
1537 return fSegmentNumber;
1538 }
1539
1540 std::string name = GetName();
1541 if(name.length() < 10) {
1542 fSegmentNumber = 0;
1543 } else {
1544 TString str = name[9];
1545 if(str.IsDigit()) {
1546 std::string buf;
1547 buf.clear();
1548 buf.assign(name, 7, 3);
1549 fSegmentNumber = static_cast<int32_t>(atoi(buf.c_str()));
1550 } else {
1551 fSegmentNumber = static_cast<int32_t>(fMnemonic.Value()->Segment());
1552 }
1553 }
1554
1555 return fSegmentNumber;
1556}
1557
1559{
1560 if(fCrystalNumber > -1) {
1561 return fCrystalNumber;
1562 }
1563
1565
1566 return fCrystalNumber;
1567}
1568
1569double TChannel::GetEnergyNonlinearity(double eng) const
1570{
1571 int nPoints = fEnergyNonlinearity.Value().GetN();
1572 if(nPoints < 1 || eng < fEnergyNonlinearity.Value().GetX()[0] || fEnergyNonlinearity.Value().GetX()[nPoints - 1] < eng) { return 0.; }
1573 return fEnergyNonlinearity.Value().Eval(eng);
1574}
1575
1577{
1578 fEnergyNonlinearity.Address()->Sort();
1579 fEnergyNonlinearity.Address()->SetBit(TGraph::kIsSortedX);
1580 fEnergyNonlinearity.Address()->SetName(Form("EnergyNonlinearity0x%04x", fAddress));
1581 fEnergyNonlinearity.Address()->SetTitle(Form("Energy nonlinearity of channel 0x%04x", fAddress));
1582}
1583
1584void TChannel::ReadEnergyNonlinearities(TFile* file, const char* graphName, bool all)
1585{
1586 /// Read energy nonlinearities as TGraphErrors from provided root file using "graphName%x" as names
1587 TList* list = file->GetListOfKeys();
1588 TIter iter(list);
1589 while(TKey* key = static_cast<TKey*>(iter.Next())) {
1590 TClass* cls = TClass::GetClass(key->GetClassName());
1591 if(!cls->InheritsFrom(TGraph::Class()) || strncmp(key->GetName(), graphName, strlen(graphName)) != 0) {
1592 continue;
1593 }
1594 // get address from keys name
1595 std::stringstream str;
1596 str << std::hex << key->GetName() + strlen(graphName);
1597 unsigned int address = 0;
1598 str >> address;
1599 if(GetChannel(address) != nullptr) {
1600 GetChannel(address)->fEnergyNonlinearity.Set(*(static_cast<TGraph*>(key->ReadObj())), EPriority::kRootFile);
1602 } else if(all) {
1603 auto* newChannel = new TChannel("");
1604 newChannel->SetAddress(address);
1605 newChannel->fEnergyNonlinearity.Set(*(static_cast<TGraph*>(key->ReadObj())), EPriority::kRootFile);
1606 newChannel->SetupEnergyNonlinearity();
1607 AddChannel(newChannel);
1608 }
1609 }
1610}
1611
1613{
1615 if(fMnemonic.Value() != nullptr) {
1617 } else {
1618 std::cerr << __PRETTY_FUNCTION__ << ": mnemonic not set, can't set digitizer type and timestamp unit from " << fDigitizerTypeString << std::endl; // NOLINT(cppcoreguidelines-pro-type-const-cast, cppcoreguidelines-pro-bounds-array-to-pointer-decay)
1619 }
1620}
1621
1622double TChannel::GetTime(Long64_t timestamp, Float_t cfd, double energy) const
1623{
1624 return fMnemonic.Value()->GetTime(timestamp, cfd, energy, this);
1625}
1626
1628{
1629 return fMnemonic.Value();
1630}
1631
1633{
1634 return fMnemonic.Value()->GetClassType();
1635}
1636
1637void TChannel::SetClassType(TClass* cl_type)
1638{
1639 fMnemonic.Value()->SetClassType(cl_type);
1640}
#define DRED
Definition Globals.h:18
#define RED
Definition Globals.h:9
std::string hex(T val, int width=-1)
Definition Globals.h:129
#define CYAN
Definition Globals.h:12
#define RESET_COLOR
Definition Globals.h:5
void trimWS(std::string &line)
static bool AnyThreadRunning()
TPriorityValue< double > fCFDChi2
Chi2 of the CFD calibration.
Definition TChannel.h:107
TPriorityValue< std::string > fDigitizerTypeString
Definition TChannel.h:86
TPriorityValue< std::vector< double > > fCFDCoefficients
CFD calibration coeffs (low to high order)
Definition TChannel.h:106
void SetWaveDecay(const double &temp)
Definition TChannel.h:262
TPriorityValue< bool > fUseCalFileInt
Definition TChannel.h:91
void SetWaveRise(const double &temp)
Definition TChannel.h:257
void SetENGRanges(const TPriorityValue< std::vector< std::pair< double, double > > > &tmp)
Definition TChannel.h:230
static TChannel * GetDefaultChannel()
Definition TChannel.cxx:413
static void SaveToSelf()
double CalibrateENG(double) const
Definition TChannel.cxx:646
void AddLEDCoefficient(double temp)
Definition TChannel.h:211
TPriorityValue< std::vector< double > > fENGChi2
Chi2 of the energy calibration.
Definition TChannel.h:104
std::vector< double > GetEFFCoeff() const
Definition TChannel.h:196
int GetStream() const
Definition TChannel.h:172
void AddCFDCoefficient(double temp)
Definition TChannel.h:210
static int WriteToRoot(TFile *fileptr=nullptr)
static std::unordered_map< unsigned int, int > * fMissingChannelMap
Definition TChannel.h:127
int GetDetectorNumber() const
std::string PrintToString(Option_t *opt="") const
Definition TChannel.cxx:864
void SetTIMEChi2(const TPriorityValue< double > &tmp)
Definition TChannel.h:254
static std::unordered_map< unsigned int, TChannel * > * GetChannelMap()
Definition TChannel.h:72
std::vector< double > GetTIMECoeff() const
Definition TChannel.h:195
int GetCrystalNumber() const
void AddCTCoefficient(double temp)
Definition TChannel.h:214
static int UpdateChannel(TChannel *, Option_t *opt="")
Definition TChannel.cxx:398
void SetENGDriftCoefficents(const TPriorityValue< std::vector< Float_t > > &tmp)
Definition TChannel.h:236
static void WriteCalFile(const std::string &outfilename="")
Definition TChannel.cxx:992
static bool CompareChannels(const TChannel *, const TChannel *)
Definition TChannel.cxx:264
std::vector< double > GetCTCoeff() const
Definition TChannel.h:197
TPriorityValue< Long64_t > fTimeOffset
Definition TChannel.h:97
static void WriteCalBuffer(Option_t *opt="")
TPriorityValue< std::vector< double > > fCTCoefficients
Cross talk coefficients.
Definition TChannel.h:114
TPriorityValue< TMnemonic * > fMnemonic
Definition TChannel.h:99
static TClassRef fMnemonicClass
Definition TChannel.h:100
void AddEFFCoefficient(double temp)
Definition TChannel.h:213
void SetCTCoefficients(const TPriorityValue< std::vector< double > > &tmp)
Definition TChannel.h:241
void SetTimeDrift(const TPriorityValue< double > &tmp)
Definition TChannel.h:155
static std::unordered_map< unsigned int, TChannel * > * fChannelMap
Definition TChannel.h:126
static void DeleteAllChannels()
Definition TChannel.cxx:273
void SetCFDChi2(const TPriorityValue< double > &tmp)
Definition TChannel.h:252
static Int_t ParseInputData(const char *inputdata="", Option_t *opt="", EPriority prio=EPriority::kUser)
void SetAllENGCoefficients(const TPriorityValue< std::vector< std::vector< Float_t > > > &tmp)
Definition TChannel.h:224
void SetLEDCoefficients(const TPriorityValue< std::vector< double > > &tmp)
Definition TChannel.h:238
void OverWriteChannel(TChannel *)
Definition TChannel.cxx:327
void DestroyLEDCal()
Definition TChannel.cxx:569
std::vector< double > GetLEDCoeff() const
Definition TChannel.h:194
void SetStream(const TPriorityValue< int > &tmp)
Definition TChannel.h:151
void SetLEDChi2(const TPriorityValue< double > &tmp)
Definition TChannel.h:253
int fSegmentNumber
Definition TChannel.h:94
void SetSegmentNumber(int tempint)
Definition TChannel.h:158
double CalibrateLED(double) const
Definition TChannel.cxx:730
void SetAddress(unsigned int tmpadd)
Definition TChannel.cxx:540
void SetTimeOffset(const TPriorityValue< Long64_t > &tmp)
Definition TChannel.h:154
double GetTime(Long64_t timestamp, Float_t cfd, double energy) const
void SetClassType(TClass *cl_type)
void SetTIMECoefficients(const TPriorityValue< std::vector< double > > &tmp)
Definition TChannel.h:239
void DestroyENGCal()
Definition TChannel.cxx:554
TPriorityValue< std::vector< double > > fTIMECoefficients
Time calibration coeffs (low to high order)
Definition TChannel.h:110
int GetSegmentNumber() const
unsigned int GetAddress() const
Definition TChannel.h:170
void SetEFFCoefficients(const TPriorityValue< std::vector< double > > &tmp)
Definition TChannel.h:240
const TMnemonic * GetMnemonic() const
TPriorityValue< std::vector< Float_t > > fENGDriftCoefficents
Energy drift coefficents (applied after energy calibration has been applied)
Definition TChannel.h:105
static Int_t ReadCalFromCurrentFile(Option_t *opt="overwrite")
static TChannel * FindChannelByName(const char *ccName)
Definition TChannel.cxx:494
static Int_t ReadCalFile(std::ifstream &infile)
void SetUseCalFileIntegration(const TPriorityValue< bool > &tmp=TPriorityValue< bool >(true, EPriority::kUser))
Definition TChannel.h:187
TGraph GetEnergyNonlinearity() const
Definition TChannel.h:198
static std::unordered_map< int, TChannel * > * fChannelNumberMap
Definition TChannel.h:128
std::vector< Float_t > GetENGDriftCoefficents() const
Definition TChannel.h:202
WaveFormShapePar WaveFormShape
Definition TChannel.h:124
static Int_t ReadCalFromFile(TFile *tempf, Option_t *opt="overwrite")
void SetENGChi2(const TPriorityValue< double > &tmp, const size_t &range=0)
Definition TChannel.h:245
std::string PrintCTToString(Option_t *opt="") const
Definition TChannel.cxx:839
unsigned int fAddress
Definition TChannel.h:84
bool UseCalFileIntegration()
Definition TChannel.h:189
double CalibrateTIME(double) const
Definition TChannel.cxx:754
TPriorityValue< EDigitizer > fDigitizerType
Definition TChannel.h:87
std::vector< double > GetAllENGChi2() const
Definition TChannel.h:180
void AddENGDriftCoefficent(Float_t temp)
Definition TChannel.h:209
static std::vector< TChannel * > SortedChannels()
Definition TChannel.cxx:977
static TChannel * GetChannel(unsigned int temp_address, bool warn=false)
Definition TChannel.cxx:459
int fDetectorNumber
Definition TChannel.h:93
TChannel & operator=(const TChannel &rhs)
Definition TChannel.cxx:165
std::vector< double > GetCFDCoeff() const
Definition TChannel.h:193
double CalibrateEFF(double) const
Definition TChannel.cxx:770
void SetupEnergyNonlinearity()
void AppendChannel(TChannel *)
Definition TChannel.cxx:365
void DestroyTIMECal()
Definition TChannel.cxx:575
Long64_t GetTimeOffset() const
Definition TChannel.h:176
TClass * GetClassType() const
double GetTimeDrift() const
Definition TChannel.h:177
TPriorityValue< int > fStream
Definition TChannel.h:90
TPriorityValue< double > fEFFChi2
Chi2 of Efficiency calibration.
Definition TChannel.h:113
static Int_t ReadCalFromTree(TTree *, Option_t *opt="overwrite")
TPriorityValue< double > fTimeDrift
Time drift factor.
Definition TChannel.h:98
TPriorityValue< std::vector< std::pair< double, double > > > fENGRanges
Range of energy calibrations.
Definition TChannel.h:103
static void WriteCTCorrections(const std::string &outfilename="")
void DestroyCFDCal()
Definition TChannel.cxx:563
void DestroyEFFCal()
Definition TChannel.cxx:581
TPriorityValue< int > fIntegration
Definition TChannel.h:85
void Print(Option_t *opt="") const override
Definition TChannel.cxx:833
void DestroyCalibrations()
Definition TChannel.cxx:598
void PrintCTCoeffs(Option_t *opt="") const
Definition TChannel.cxx:818
void SetIntegration(const TPriorityValue< int > &tmp)
Definition TChannel.h:149
TPriorityValue< int > fTimeStampUnit
Definition TChannel.h:88
void Clear(Option_t *opt="") override
Definition TChannel.cxx:421
TPriorityValue< double > fTIMEChi2
Chi2 of the Time calibration.
Definition TChannel.h:111
double CalibrateCFD(double) const
Definition TChannel.cxx:705
double GetTIMEChi2() const
Definition TChannel.h:184
void SetNumber(const TPriorityValue< int > &tmp)
Definition TChannel.h:139
void AddTIMECoefficient(double temp)
Definition TChannel.h:212
int GetNumber() const
Definition TChannel.h:169
int fCrystalNumber
Definition TChannel.h:95
TPriorityValue< double > fLEDChi2
Chi2 of LED calibration.
Definition TChannel.h:109
std::vector< std::vector< Float_t > > GetAllENGCoeff() const
Definition TChannel.h:191
TPriorityValue< std::vector< std::vector< Float_t > > > fENGCoefficients
Energy calibration coeffs (low to high order)
Definition TChannel.h:102
double GetLEDChi2() const
Definition TChannel.h:183
static TChannel * GetChannelByNumber(int temp_num)
Definition TChannel.cxx:482
void AddENGCoefficient(Float_t temp, size_t range=0)
Definition TChannel.h:204
static Int_t ReadFile(TFile *tempf)
static void InitChannelInput()
Definition TChannel.cxx:254
const char * GetDigitizerTypeString() const
Definition TChannel.h:173
void SetName(const char *tmpName) override
Definition TChannel.cxx:244
void SetCrystalNumber(int tempint)
Definition TChannel.h:159
void DestroyCTCal()
Definition TChannel.cxx:587
TPriorityValue< TGraph > fEnergyNonlinearity
Energy nonlinearity as TGraph, is used as E=E+GetEnergyNonlinearity(E), so y should be E(source)-cali...
Definition TChannel.h:115
void SetDetectorNumber(int tempint)
Definition TChannel.h:157
void DestroyEnergyNonlinearity()
Definition TChannel.cxx:593
void AddEnergyNonlinearityPoint(double x, double y)
Definition TChannel.h:215
TPriorityValue< std::vector< double > > fLEDCoefficients
LED calibration coeffs (low to high order)
Definition TChannel.h:108
TPriorityValue< int > fNumber
Definition TChannel.h:89
TPriorityValue< std::vector< double > > fEFFCoefficients
Efficiency calibration coeffs (low to high order)
Definition TChannel.h:112
bool UseWaveParam() const
Definition TChannel.h:279
double GetCFDChi2() const
Definition TChannel.h:182
double GetEFFChi2() const
Definition TChannel.h:185
static void AddChannel(TChannel *, Option_t *opt="")
Definition TChannel.cxx:285
void SetAllENGChi2(const TPriorityValue< std::vector< double > > &tmp)
Definition TChannel.h:244
static size_t GetNumberOfChannels()
Definition TChannel.h:68
void SetWaveParam(WaveFormShapePar temp)
Definition TChannel.h:274
static void ReadEnergyNonlinearities(TFile *, const char *graphName="EnergyNonlinearity0x", bool all=false)
void SetEnergyNonlinearity(const TPriorityValue< TGraph > &tmp)
Definition TChannel.h:242
static std::vector< TChannel * > FindChannelByRegEx(const char *ccName)
Definition TChannel.cxx:518
void SetENGRange(const std::pair< double, double > &tmp, const size_t &range)
Definition TChannel.h:231
void SetWaveBaseLine(double temp)
Definition TChannel.h:267
int GetIntegration() const
Definition TChannel.h:171
void SetDigitizerType(const TPriorityValue< std::string > &tmp)
static std::string fFileData
Definition TChannel.h:332
void SetCFDCoefficients(const TPriorityValue< std::vector< double > > &tmp)
Definition TChannel.h:237
std::vector< std::pair< double, double > > GetENGRanges() const
Definition TChannel.h:200
void SetEFFChi2(const TPriorityValue< double > &tmp)
Definition TChannel.h:255
WaveFormShapePar GetWaveParam() const
Definition TChannel.h:280
virtual int NumericArraySubPosition() const
virtual void EnumerateDigitizer(TPriorityValue< std::string > &, TPriorityValue< EDigitizer > &, TPriorityValue< int > &)
Definition TMnemonic.h:78
virtual void Parse(std::string *name)
Definition TMnemonic.cxx:57
virtual TClass * GetClassType() const
virtual void SetClassType(TClass *classType) const
Definition TMnemonic.h:92
virtual double GetTime(Long64_t timestamp, Float_t cfd, double energy, const TChannel *channel) const
void Set(const T &val, EPriority priority)
const T & Value() const
void Reset(T val)
void SetPriority(EPriority priority)
EPriority