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