File indexing completed on 2025-12-19 09:24:42
0001 #include "CaloCalibration.h"
0002
0003 #include "PROTOTYPE4_FEM.h"
0004 #include "RawTower_Prototype4.h"
0005
0006 #include <calobase/RawTower.h> // for RawTower
0007 #include <calobase/RawTowerContainer.h>
0008 #include <calobase/RawTowerDefs.h> // for keytype
0009
0010 #include <phparameter/PHParameters.h> // for PHParameters
0011
0012 #include <fun4all/Fun4AllReturnCodes.h>
0013 #include <fun4all/SubsysReco.h> // for SubsysReco
0014
0015 #include <phool/PHCompositeNode.h>
0016 #include <phool/PHIODataNode.h> // for PHIODataNode
0017 #include <phool/PHNode.h> // for PHNode
0018 #include <phool/PHNodeIterator.h> // for PHNodeIterator
0019 #include <phool/PHObject.h> // for PHObject
0020 #include <phool/getClass.h>
0021
0022 #include <boost/format.hpp>
0023
0024 #include <cassert>
0025 #include <cmath> // for NAN, isnan
0026 #include <cstdlib> // for exit
0027 #include <iostream>
0028 #include <limits> // for numeric_limits
0029 #include <map> // for map, _Rb_tree_iter...
0030 #include <stdexcept> // for runtime_error
0031 #include <string>
0032 #include <utility> // for pair
0033 #include <vector> // for vector
0034
0035 using namespace std;
0036
0037
0038 CaloCalibration::CaloCalibration(const std::string &name)
0039 : SubsysReco(string("CaloCalibration_") + name)
0040 , _calib_towers(nullptr)
0041 , _raw_towers(nullptr)
0042 , detector(name)
0043 , _calib_tower_node_prefix("CALIB")
0044 , _raw_tower_node_prefix("RAW")
0045 , _calib_params(name)
0046 , _fit_type(kPowerLawDoubleExpWithGlobalFitConstraint)
0047 {
0048 SetDefaultParameters(_calib_params);
0049 }
0050
0051
0052 int CaloCalibration::InitRun(PHCompositeNode *topNode)
0053 {
0054 CreateNodeTree(topNode);
0055
0056 if (Verbosity())
0057 {
0058 std::cout << Name() << "::" << detector << "::" << __PRETTY_FUNCTION__
0059 << " - print calibration parameters: " << endl;
0060 _calib_params.Print();
0061 }
0062
0063 return Fun4AllReturnCodes::EVENT_OK;
0064 }
0065
0066
0067 int CaloCalibration::process_event(PHCompositeNode *topNode)
0068 {
0069 if (Verbosity())
0070 {
0071 std::cout << Name() << "::" << detector << "::" << __PRETTY_FUNCTION__
0072 << "Process event entered" << std::endl;
0073 }
0074
0075 map<int, double> parameters_constraints;
0076 if (_fit_type == kPowerLawDoubleExpWithGlobalFitConstraint and
0077 _raw_towers->size() > 1)
0078 {
0079 if (Verbosity())
0080 {
0081 std::cout
0082 << Name() << "::" << detector << "::" << __PRETTY_FUNCTION__
0083 << "Extract global fit parameter for constraining individual fits"
0084 << std::endl;
0085 }
0086
0087
0088
0089 vector<double> vec_signal_samples(PROTOTYPE4_FEM::NSAMPLES, 0);
0090
0091 int count = 0;
0092
0093 RawTowerContainer::Range begin_end = _raw_towers->getTowers();
0094 RawTowerContainer::Iterator rtiter;
0095 for (rtiter = begin_end.first; rtiter != begin_end.second; ++rtiter)
0096 {
0097 RawTower_Prototype4 *raw_tower =
0098 dynamic_cast<RawTower_Prototype4 *>(rtiter->second);
0099 assert(raw_tower);
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114 ++count;
0115
0116 for (int i = 0; i < RawTower_Prototype4::NSAMPLES; i++)
0117 {
0118 if (raw_tower->get_signal_samples(i) <= 10 or
0119 raw_tower->get_signal_samples(i) >= ((1 << 14) - 10))
0120 vec_signal_samples[i] =
0121 numeric_limits<double>::quiet_NaN();
0122 else
0123 vec_signal_samples[i] += raw_tower->get_signal_samples(i);
0124 }
0125
0126 }
0127
0128 if (count > 0)
0129 {
0130 for (int i = 0; i < RawTower_Prototype4::NSAMPLES; i++)
0131 {
0132 vec_signal_samples[i] /= count;
0133 }
0134
0135 double peak = NAN;
0136 double peak_sample = NAN;
0137 double pedstal = NAN;
0138 map<int, double> parameters_io;
0139
0140 PROTOTYPE4_FEM::SampleFit_PowerLawDoubleExp(vec_signal_samples, peak,
0141 peak_sample, pedstal,
0142 parameters_io, Verbosity());
0143
0144
0145
0146
0147
0148
0149 parameters_constraints[1] = parameters_io[1];
0150 parameters_constraints[2] = parameters_io[2];
0151 parameters_constraints[3] = parameters_io[3];
0152 parameters_constraints[5] = parameters_io[5];
0153 parameters_constraints[6] = parameters_io[6];
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175 }
0176 else
0177 {
0178 std::cout << Name() << "::" << detector << "::" << __PRETTY_FUNCTION__
0179 << ": Failed to build signal template! Fit each channel "
0180 "individually instead"
0181 << std::endl;
0182 }
0183 }
0184
0185 const double calib_const_scale =
0186 _calib_params.get_double_param("calib_const_scale");
0187 const bool use_chan_calibration =
0188 _calib_params.get_int_param("use_chan_calibration") > 0;
0189
0190 RawTowerContainer::Range begin_end = _raw_towers->getTowers();
0191 RawTowerContainer::Iterator rtiter;
0192 for (rtiter = begin_end.first; rtiter != begin_end.second; ++rtiter)
0193 {
0194 RawTowerDefs::keytype key = rtiter->first;
0195 RawTower_Prototype4 *raw_tower =
0196 dynamic_cast<RawTower_Prototype4 *>(rtiter->second);
0197 assert(raw_tower);
0198
0199 double calibration_const = calib_const_scale;
0200
0201 if (use_chan_calibration)
0202 {
0203
0204 const int column = raw_tower->get_column();
0205 const int row = raw_tower->get_row();
0206
0207 assert(column >= 0);
0208 assert(row >= 0);
0209
0210 string calib_const_name(
0211 (boost::format("calib_const_column%d_row%d") % column % row).str());
0212
0213 calibration_const *= _calib_params.get_double_param(calib_const_name);
0214 }
0215
0216 vector<double> vec_signal_samples;
0217 for (int i = 0; i < RawTower_Prototype4::NSAMPLES; i++)
0218 {
0219 vec_signal_samples.push_back(raw_tower->get_signal_samples(i));
0220 }
0221
0222 double peak = NAN;
0223 double peak_sample = NAN;
0224 double pedstal = NAN;
0225
0226 switch (_fit_type)
0227 {
0228 case kPowerLawExp:
0229 PROTOTYPE4_FEM::SampleFit_PowerLawExp(vec_signal_samples, peak,
0230 peak_sample, pedstal, Verbosity());
0231 break;
0232
0233 case kPeakSample:
0234 PROTOTYPE4_FEM::SampleFit_PeakSample(vec_signal_samples, peak,
0235 peak_sample, pedstal, Verbosity());
0236 break;
0237
0238 case kPowerLawDoubleExp:
0239 {
0240 map<int, double> parameters_io;
0241
0242 PROTOTYPE4_FEM::SampleFit_PowerLawDoubleExp(vec_signal_samples, peak,
0243 peak_sample, pedstal,
0244 parameters_io, Verbosity());
0245 }
0246 break;
0247
0248 case kPowerLawDoubleExpWithGlobalFitConstraint:
0249 {
0250 map<int, double> parameters_io(parameters_constraints);
0251
0252 PROTOTYPE4_FEM::SampleFit_PowerLawDoubleExp(vec_signal_samples, peak,
0253 peak_sample, pedstal,
0254 parameters_io, Verbosity());
0255 }
0256 break;
0257 default:
0258 cout << __PRETTY_FUNCTION__ << " - FATAL error - unkown fit type "
0259 << _fit_type << endl;
0260 exit(3);
0261 break;
0262 }
0263
0264
0265 if (std::isnan(raw_tower->get_energy()))
0266 {
0267
0268
0269 raw_tower->set_energy(peak);
0270 raw_tower->set_time(peak_sample);
0271
0272 if (Verbosity())
0273 {
0274 raw_tower->identify();
0275 }
0276 }
0277
0278
0279 RawTower_Prototype4 *calib_tower = new RawTower_Prototype4(*raw_tower);
0280 calib_tower->set_energy(peak * calibration_const);
0281 calib_tower->set_time(peak_sample);
0282
0283 for (int i = 0; i < RawTower_Prototype4::NSAMPLES; i++)
0284 {
0285 calib_tower->set_signal_samples(i, (vec_signal_samples[i] - pedstal) *
0286 calibration_const);
0287 }
0288
0289 _calib_towers->AddTower(key, calib_tower);
0290
0291 }
0292
0293 if (Verbosity())
0294 {
0295 std::cout << Name() << "::" << detector << "::" << __PRETTY_FUNCTION__
0296 << "input sum energy = " << _raw_towers->getTotalEdep()
0297 << ", output sum digitalized value = "
0298 << _calib_towers->getTotalEdep() << std::endl;
0299 }
0300
0301 return Fun4AllReturnCodes::EVENT_OK;
0302 }
0303
0304
0305 void CaloCalibration::CreateNodeTree(PHCompositeNode *topNode)
0306 {
0307 PHNodeIterator iter(topNode);
0308
0309 PHCompositeNode *dstNode =
0310 dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
0311 if (!dstNode)
0312 {
0313 std::cerr << Name() << "::" << detector << "::" << __PRETTY_FUNCTION__
0314 << "DST Node missing, doing nothing." << std::endl;
0315 throw std::runtime_error(
0316 "Failed to find DST node in RawTowerCalibration::CreateNodes");
0317 }
0318
0319 RawTowerNodeName = "TOWER_" + _raw_tower_node_prefix + "_" + detector;
0320 _raw_towers =
0321 findNode::getClass<RawTowerContainer>(dstNode, RawTowerNodeName.c_str());
0322 if (!_raw_towers)
0323 {
0324 std::cerr << Name() << "::" << detector << "::" << __PRETTY_FUNCTION__
0325 << " " << RawTowerNodeName << " Node missing, doing bail out!"
0326 << std::endl;
0327 throw std::runtime_error("Failed to find " + RawTowerNodeName +
0328 " node in RawTowerCalibration::CreateNodes");
0329 }
0330
0331
0332 PHNodeIterator dstiter(dstNode);
0333 PHCompositeNode *DetNode = dynamic_cast<PHCompositeNode *>(
0334 dstiter.findFirst("PHCompositeNode", detector));
0335 if (!DetNode)
0336 {
0337 DetNode = new PHCompositeNode(detector);
0338 dstNode->addNode(DetNode);
0339 }
0340
0341
0342
0343 CaliTowerNodeName = "TOWER_" + _calib_tower_node_prefix + "_" + detector;
0344 _calib_towers =
0345 findNode::getClass<RawTowerContainer>(DetNode, CaliTowerNodeName.c_str());
0346 if (!_calib_towers)
0347 {
0348 _calib_towers = new RawTowerContainer(_raw_towers->getCalorimeterID());
0349 PHIODataNode<PHObject> *towerNode = new PHIODataNode<PHObject>(
0350 _calib_towers, CaliTowerNodeName.c_str(), "PHObject");
0351 DetNode->addNode(towerNode);
0352 }
0353
0354
0355 PHCompositeNode *parNode =
0356 dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "RUN"));
0357 assert(parNode);
0358 const string paramnodename = string("Calibration_") + detector;
0359
0360
0361
0362 _calib_params.SaveToNodeTree(parNode, paramnodename);
0363 }
0364
0365 void CaloCalibration::SetDefaultParameters(PHParameters ¶m)
0366 {
0367 param.set_int_param("use_chan_calibration", 0);
0368
0369
0370
0371 param.set_double_param("calib_const_scale", 1);
0372 }