17 #include "TRestDetectorSingleChannelAnalysisProcess.h"
19 #include <TFitResult.h>
23 #include <TPaveText.h>
25 #include <TSpectrum.h>
31 TRestDetectorSingleChannelAnalysisProcess::TRestDetectorSingleChannelAnalysisProcess() { Initialize(); }
33 TRestDetectorSingleChannelAnalysisProcess::~TRestDetectorSingleChannelAnalysisProcess() {}
36 SetSectionName(this->ClassName());
37 SetLibraryVersion(LIBRARY_VERSION);
39 fSignalEvent =
nullptr;
45 fReadout = GetMetadata<TRestDetectorReadout>();
46 fCalib = GetMetadata<TRestDetectorGainMap>();
47 if (fReadout ==
nullptr) {
49 for (
int i = 0; i < fReadout->GetNumberOfReadoutPlanes(); i++) {
50 auto plane = fReadout->GetReadoutPlane(i);
51 for (
size_t j = 0; j < plane->GetNumberOfModules(); j++) {
52 auto mod = plane->GetModule(j);
53 for (
size_t k = 0; k < mod->GetNumberOfChannels(); k++) {
54 auto channel = mod->GetChannel(k);
55 fChannelGain[channel->GetDaqID()] = 1;
56 fChannelGainError[channel->GetDaqID()] = 1;
57 fChannelThrIntegral[channel->GetDaqID()] =
58 new TH1D(Form(
"h%i", channel->GetDaqID()), Form(
"h%i", channel->GetDaqID()), 100, 0,
59 fSpecFitRange.Y() * 1.5);
65 if (fApplyGainCorrection) {
66 if (fCalib !=
nullptr) {
67 for (
auto iter = fChannelGain.begin(); iter != fChannelGain.end(); iter++) {
68 if (fCalib->fChannelGain.count(iter->first) == 0) {
69 RESTError <<
"in consistent gain mapping and readout definition!" << RESTendl;
70 RESTError <<
"channel: " << iter->first <<
" not fount in mapping file!" << RESTendl;
76 RESTError <<
"You must set a TRestDetectorGainMap metadata object to apply gain correction!"
82 if (GetFriend(
"TRestRawSignalAnalysisProcess") ==
nullptr) {
83 RESTError <<
"please add friend process TRestRawSignalAnalysisProcess and "
84 "TRestRawReadoutAnalysisProcess "
85 "and turn on all their observables!"
94 Double_t new_PeakAmplitudeIntegral = 0;
95 Double_t new_ThresholdIntegral = 0;
97 map<int, Double_t> sAna_max_amplitude_map = GetObservableValue<map<int, Double_t>>(
"max_amplitude_map");
98 map<int, Double_t> sAna_thr_integral_map = GetObservableValue<map<int, Double_t>>(
"thr_integral_map");
99 Double_t sAna_ThresholdIntegral = GetObservableValue<Double_t>(
"ThresholdIntegral");
100 Double_t sAna_NumberOfGoodSignals = GetObservableValue<int>(
"NumberOfGoodSignals");
102 if (fCreateGainMap) {
103 if ((sAna_ThresholdIntegral > fThrIntegralCutRange.X() &&
104 sAna_ThresholdIntegral < fThrIntegralCutRange.Y()) &&
105 (sAna_NumberOfGoodSignals > fNGoodSignalsCutRange.X() &&
106 sAna_NumberOfGoodSignals < fNGoodSignalsCutRange.Y())) {
109 for (
auto iter = sAna_thr_integral_map.begin(); iter != sAna_thr_integral_map.end(); iter++) {
110 if (fChannelThrIntegral[iter->first] ==
nullptr) {
111 fChannelThrIntegral[iter->first] =
new TH1D(
112 Form(
"h%i", iter->first), Form(
"h%i", iter->first), 100, 0, fSpecFitRange.Y() * 1.5);
115 fChannelThrIntegral[iter->first]->Fill(iter->second);
120 else if (fApplyGainCorrection) {
122 for (
auto iter = sAna_max_amplitude_map.begin(); iter != sAna_max_amplitude_map.end(); iter++) {
123 if (fCalib->fChannelGain.count(iter->first)) {
124 iter->second *= fCalib->fChannelGain[iter->first];
126 new_PeakAmplitudeIntegral += iter->second;
129 for (
auto iter = sAna_thr_integral_map.begin(); iter != sAna_thr_integral_map.end(); iter++) {
130 if (fCalib->fChannelGain.count(iter->first)) {
131 iter->second *= fCalib->fChannelGain[iter->first];
133 new_ThresholdIntegral += iter->second;
137 for (
int i = 0; i < fSignalEvent->GetNumberOfSignals(); i++) {
139 if (fCalib->fChannelGain.count(sgn->GetID()) == 0 || fCalib->fChannelGain[sgn->GetID()] == 0) {
140 cout <<
"warning! unrecorded gain for channel: " << sgn->GetID() << endl;
143 double gain = fCalib->fChannelGain[sgn->GetID()];
144 for (
int j = 0; j < sgn->GetNumberOfPoints(); j++) {
145 auto timecharge = sgn->GetPoint(j);
146 sgn->
SetPoint(j, timecharge.X(), timecharge.Y() * gain);
151 SetObservableValue(
"ChnCorr_AmpInt", new_PeakAmplitudeIntegral);
152 SetObservableValue(
"ChnCorr_ThrInt", new_ThresholdIntegral);
158 if (fCreateGainMap) {
164 void TRestDetectorSingleChannelAnalysisProcess::FitChannelGain() {
165 cout <<
"TRestDetectorSingleChannelAnalysisProcess: fitting channel gain..." << endl;
167 double channelFitMeanSum = 0;
169 for (
auto iter = fChannelThrIntegral.begin(); iter != fChannelThrIntegral.end(); iter++) {
170 TH1D* h = iter->second;
171 if (h->GetEntries() > 100) {
173 double middle = (fSpecFitRange.X() + fSpecFitRange.Y()) / 2;
174 double range = (fSpecFitRange.Y() - fSpecFitRange.X()) / 2;
175 TFitResultPtr r = h->Fit(
"gaus",
"QS",
"", fSpecFitRange.X(), fSpecFitRange.Y());
177 const double* results = r->GetParams();
178 double mean = results[1];
179 double sigma = results[2];
181 if (mean > middle - range / 1.2 && mean < middle + range / 1.2 && sigma / mean < 0.5) {
182 fChannelFitMean[iter->first] = mean;
183 channelFitMeanSum += mean;
184 fChannelGainError[iter->first] = sigma / mean;
185 cout << iter->first <<
", mean: " << mean <<
", error: " << sigma / mean << endl;
192 int n = spc.Search(h);
193 double* peaks = spc.GetPositionX();
196 for (
int i = 0; i < n; i++) {
197 double dist = abs(peaks[i] - middle);
203 if (min < range * 2) {
204 fChannelFitMean[iter->first] = peaks[minpos];
205 channelFitMeanSum += peaks[minpos];
206 fChannelGainError[iter->first] = 1;
207 cout << iter->first <<
", peak position: " << peaks[minpos] <<
", total peaks: " << n << endl;
212 cout << iter->first <<
", too bad to fit" << endl;
216 double meanmean = channelFitMeanSum / fChannelFitMean.size();
218 cout << meanmean << endl;
221 for (
auto iter = fChannelGain.begin(); iter != fChannelGain.end(); iter++) {
222 if (fChannelFitMean.count(iter->first) == 0) {
225 iter->second = meanmean / fChannelFitMean[iter->first];
237 void TRestDetectorSingleChannelAnalysisProcess::SaveGainMetadata(
string filename) {
238 cout <<
"TRestDetectorSingleChannelAnalysisProcess: saving result..." << endl;
245 fCalib->fChannelGain = fChannelGain;
246 fCalib->SetName(
"ChannelCalibration");
249 r->SetOutputFileName(filename);
255 PrintChannelSpectrums(filename);
259 TH1D* TRestDetectorSingleChannelAnalysisProcess::GetChannelSpectrum(
int id) {
260 if (fChannelThrIntegral.count(
id) != 0)
return fChannelThrIntegral[id];
264 void TRestDetectorSingleChannelAnalysisProcess::PrintChannelSpectrums(
string filename) {
265 TCanvas* c =
new TCanvas();
267 pText.SetTextColor(kBlack);
268 pText.SetTextFont(132);
269 pText.SetTextSize(0.05);
271 pLine.SetLineColor(1);
272 pLine.SetLineWidth(1);
273 pLine.SetLineColor(1);
275 c->Print((filename +
".pdf[").c_str());
276 for (
auto iter = fChannelThrIntegral.begin(); iter != fChannelThrIntegral.end(); iter++) {
277 if (iter->second !=
nullptr && iter->second->GetEntries() > 0) {
278 cout <<
"Drawing: " << iter->first << endl;
280 iter->second->Draw();
281 pText.DrawLatex(fChannelFitMean[iter->first], iter->second->GetMaximum(),
282 Form(
"Relative gain: %.3f", fChannelGain[iter->first]));
283 pText.DrawLatex(fChannelFitMean[iter->first], iter->second->GetMaximum() * 0.9,
284 Form(
"Error: %.2f", fChannelGainError[iter->first]));
285 pLine.DrawLine(fChannelFitMean[iter->first], 0, fChannelFitMean[iter->first],
286 iter->second->GetMaximum() * 0.9);
287 c->Print((filename +
".pdf").c_str());
291 c->Print((filename +
".pdf]").c_str());
300 string mode = GetParameter(
"mode",
"apply");
301 if (mode ==
"create") {
302 fCreateGainMap =
true;
303 fApplyGainCorrection =
false;
304 fSingleThreadOnly =
true;
305 }
else if (mode ==
"apply") {
306 fCreateGainMap =
false;
307 fApplyGainCorrection =
true;
308 fSingleThreadOnly =
false;
310 RESTError <<
"illegal mode definition! supported: create, apply" << RESTendl;
314 fThrIntegralCutRange =
StringTo2DVector(GetParameter(
"thrEnergyRange",
"(0,1e9)"));
315 fNGoodSignalsCutRange =
StringTo2DVector(GetParameter(
"nGoodSignalsRange",
"(4,14)"));
316 fSpecFitRange =
StringTo2DVector(GetParameter(
"specFitRange",
"(1e4,2e4)"));
317 fCalibSave = GetParameter(
"save",
"calib.root");
void SetPoint(TVector2 p)
If the point already exists inside the detector signal event, it will be overwritten....
TRestEvent * ProcessEvent(TRestEvent *inputEvent) override
Process one event.
void Initialize() override
Making default settings.
void EndProcess() override
To be executed at the end of the run (outside event loop)
void InitProcess() override
To be executed at the beginning of the run (outside event loop)
void InitFromConfigFile() override
To make settings from rml file. This method must be implemented in the derived class.
A base class for any REST event.
Data provider and manager in REST.
TFile * FormOutputFile()
Create a new TFile as REST output file. Writing metadata objects into it.
void AddMetadata(TRestMetadata *meta)
add metadata object to the metadata list
TVector2 StringTo2DVector(std::string in)
Gets a 2D-vector from a string.