File indexing completed on 2026-10-15 08:26:12
0001 #include "TpcConditionsReco.h"
0002 #include "TpcConditions.h"
0003
0004 #include <ffamodules/CDBInterface.h>
0005
0006 #include <cdbobjects/CDBTTree.h>
0007
0008 #include <ffarawobjects/Gl1Packet.h>
0009
0010 #include <fun4all/Fun4AllReturnCodes.h>
0011
0012 #include <phool/PHCompositeNode.h>
0013 #include <phool/PHDataNode.h>
0014 #include <phool/PHNodeIterator.h>
0015 #include <phool/getClass.h>
0016
0017 #include <phool/recoConsts.h>
0018
0019 #include <algorithm>
0020 #include <cstddef>
0021 #include <cstdint>
0022 #include <iostream>
0023 #include <iterator>
0024 #include <string>
0025 #include <vector>
0026
0027
0028
0029 namespace
0030 {
0031 const std::vector<std::string> SR1 = {
0032 "S_01_R1_G4_IMon",
0033 "S_04_R1_G4_IMon",
0034 "S_05_R1_G4_IMon",
0035 "S_10_R1_G4_IMon"};
0036
0037 const std::vector<std::string> SR2 = {
0038 "S_01_R2_G4_IMon",
0039 "S_02_R2_G4_IMon",
0040 "S_07_R2_G4_IMon",
0041 "S_09_R2_G4_IMon",
0042 "S_10_R2_G4_IMon",
0043 "S_12_R2_G4_IMon"};
0044
0045 const std::vector<std::string> SR3 = {
0046 "S_08_R3_G4_IMon",
0047 "S_09_R3_G4_IMon",
0048 "S_10_R3_G4_IMon",
0049 };
0050
0051 const std::vector<std::string> NR1 = {
0052 "N_03_R1_G4_IMon",
0053 "N_04_R1_G4_IMon",
0054 "N_06_R1_G4_IMon",
0055 "N_07_R1_G4_IMon",
0056 "N_08_R1_G4_IMon",
0057 "N_10_R1_G4_IMon",
0058 "N_11_R1_G4_IMon",
0059 "N_12_R1_G4_IMon"};
0060
0061 const std::vector<std::string> NR2 = {
0062 "N_02_R2_G4_IMon",
0063 "N_04_R2_G4_IMon",
0064 "N_05_R2_G4_IMon",
0065 "N_09_R2_G4_IMon",
0066 "N_10_R2_G4_IMon",
0067 "N_11_R2_G4_IMon",
0068 "N_12_R2_G4_IMon"};
0069
0070 const std::vector<std::string> NR3 = {
0071 "N_02_R3_G4_IMon",
0072 "N_10_R3_G4_IMon"};
0073
0074 const std::vector<std::string> SOUTH = []()
0075 {
0076 std::vector<std::string> v;
0077 v.insert(v.end(), SR1.begin(), SR1.end());
0078 v.insert(v.end(), SR2.begin(), SR2.end());
0079 v.insert(v.end(), SR3.begin(), SR3.end());
0080 return v;
0081 }();
0082
0083 const std::vector<std::string> NORTH = []()
0084 {
0085 std::vector<std::string> v;
0086 v.insert(v.end(), NR1.begin(), NR1.end());
0087 v.insert(v.end(), NR2.begin(), NR2.end());
0088 v.insert(v.end(), NR3.begin(), NR3.end());
0089 return v;
0090 }();
0091
0092 const std::vector<std::string> ALL = []()
0093 {
0094 std::vector<std::string> v;
0095 v.insert(v.end(), SOUTH.begin(), SOUTH.end());
0096 v.insert(v.end(), NORTH.begin(), NORTH.end());
0097 return v;
0098 }();
0099 }
0100
0101 TpcConditionsReco::TpcConditionsReco(const std::string &name)
0102 : SubsysReco(name)
0103 {
0104 }
0105
0106 TpcConditionsReco::~TpcConditionsReco()
0107 {
0108 delete m_tree;
0109 }
0110
0111 float TpcConditionsReco::get_AverageMedianCurrent(
0112 const std::vector<std::string> &channels)
0113 {
0114 if (m_bco_to_channel.empty())
0115 {
0116 return 0.0F;
0117 }
0118
0119 double sum = 0.0;
0120
0121 for (const auto &entry : m_bco_to_channel)
0122 {
0123 sum += get_MedianCurrent(entry.second, channels);
0124 }
0125
0126 return static_cast<float>(sum / static_cast<double>(m_bco_to_channel.size()));
0127 }
0128
0129 float TpcConditionsReco::get_InterpolatedMedianCurrent(const uint64_t bco, const std::vector<std::string> &channels)
0130 {
0131 if (m_bco_to_channel.empty())
0132 {
0133 return 0.0F;
0134 }
0135
0136 if (m_bco_to_channel.size() == 1)
0137 {
0138 return get_MedianCurrent(m_bco_to_channel.begin()->second, channels);
0139 }
0140
0141 const auto first = m_bco_to_channel.begin();
0142 const auto last = std::prev(m_bco_to_channel.end());
0143
0144 if (bco <= first->first)
0145 {
0146 return get_MedianCurrent(first->second, channels);
0147 }
0148
0149 if (bco >= last->first)
0150 {
0151 return get_MedianCurrent(last->second, channels);
0152 }
0153
0154 const auto right = m_bco_to_channel.upper_bound(bco);
0155 const auto left = std::prev(right);
0156
0157 const double x1 = static_cast<double>(left->first);
0158 const double x2 = static_cast<double>(right->first);
0159 const double y1 = get_MedianCurrent(left->second, channels);
0160 const double y2 = get_MedianCurrent(right->second, channels);
0161
0162 const double h1 = x2 - x1;
0163 const double d1 = (y2 - y1) / h1;
0164
0165 double m1 = d1;
0166 double m2 = d1;
0167
0168 if (left != m_bco_to_channel.begin())
0169 {
0170 const auto left2 = std::prev(left);
0171 const double x0 = static_cast<double>(left2->first);
0172 const double y0 = get_MedianCurrent(left2->second, channels);
0173 const double h0 = x1 - x0;
0174 const double d0 = (y1 - y0) / h0;
0175
0176 if (d0 * d1 > 0.0)
0177 {
0178 const double w1 = 2.0 * h1 + h0;
0179 const double w2 = h1 + 2.0 * h0;
0180 m1 = (w1 + w2) / (w1 / d0 + w2 / d1);
0181 }
0182 else
0183 {
0184 m1 = 0.0;
0185 }
0186 }
0187
0188 const auto right2 = std::next(right);
0189 if (right2 != m_bco_to_channel.end())
0190 {
0191 const double x3 = static_cast<double>(right2->first);
0192 const double y3 = get_MedianCurrent(right2->second, channels);
0193 const double h2 = x3 - x2;
0194 const double d2 = (y3 - y2) / h2;
0195
0196 if (d1 * d2 > 0.0)
0197 {
0198 const double w1 = 2.0 * h2 + h1;
0199 const double w2 = h2 + 2.0 * h1;
0200 m2 = (w1 + w2) / (w1 / d1 + w2 / d2);
0201 }
0202 else
0203 {
0204 m2 = 0.0;
0205 }
0206 }
0207
0208 const double t = (static_cast<double>(bco) - x1) / h1;
0209 const double t2 = t * t;
0210 const double t3 = t2 * t;
0211
0212 return static_cast<float>(
0213 (2.0 * t3 - 3.0 * t2 + 1.0) * y1 +
0214 (t3 - 2.0 * t2 + t) * h1 * m1 +
0215 (-2.0 * t3 + 3.0 * t2) * y2 +
0216 (t3 - t2) * h1 * m2);
0217 }
0218
0219 void TpcConditionsReco::fillConditions(int channel)
0220 {
0221 m_conditions->set_Temperature(m_tree->GetFloatValue(channel, "gas_temperature"));
0222 m_conditions->set_Pressure(m_tree->GetFloatValue(channel, "gas_pressure"));
0223 m_conditions->set_FieldOK(m_tree->GetFloatValue(channel, "FieldOK") != 0.0);
0224 m_conditions->set_GainOK(m_tree->GetFloatValue(channel, "GainOK") != 0.0);
0225
0226 m_conditions->set_LoadCurrent(get_MedianCurrent(channel, ALL));
0227 m_conditions->set_LoadNorth(get_MedianCurrent(channel, NORTH));
0228 m_conditions->set_LoadSouth(get_MedianCurrent(channel, SOUTH));
0229 m_conditions->set_LoadSR1(get_MedianCurrent(channel, SR1));
0230 m_conditions->set_LoadSR2(get_MedianCurrent(channel, SR2));
0231 m_conditions->set_LoadSR3(get_MedianCurrent(channel, SR3));
0232 m_conditions->set_LoadNR1(get_MedianCurrent(channel, NR1));
0233 m_conditions->set_LoadNR2(get_MedianCurrent(channel, NR2));
0234 m_conditions->set_LoadNR3(get_MedianCurrent(channel, NR3));
0235 }
0236
0237 int TpcConditionsReco::InitRun(PHCompositeNode *topNode)
0238 {
0239 std::cout << "TpcConditionsReco::InitRun(PHCompositeNode *topNode) Initializing"
0240 << std::endl;
0241
0242 PHNodeIterator iter(topNode);
0243 PHCompositeNode *parNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "PAR"));
0244
0245 if (!parNode)
0246 {
0247 parNode = new PHCompositeNode("PAR");
0248 topNode->addNode(parNode);
0249 }
0250
0251 m_conditions = findNode::getClass<TpcConditions>(topNode, "TpcConditions");
0252 if (!m_conditions)
0253 {
0254 m_conditions = new TpcConditions();
0255 auto *conditionsNode = new PHDataNode<TpcConditions>(m_conditions, "TpcConditions", "Data");
0256 parNode->addNode(conditionsNode);
0257 }
0258
0259 m_conditions->set_ConditionsAvailable(false);
0260
0261 delete m_tree;
0262 m_tree = nullptr;
0263 m_bco_to_channel.clear();
0264
0265 Gl1Packet *gl1 = findNode::getClass<Gl1Packet>(topNode, "GL1RAWHIT");
0266 if (!gl1)
0267 {
0268 gl1 = findNode::getClass<Gl1Packet>(topNode, "GL1Packet");
0269 }
0270
0271 if (!gl1)
0272 {
0273 std::cout << "TpcConditionsReco::InitRun - could not find GL1 packet"
0274 << std::endl;
0275 m_conditions->set_ConditionsAvailable(false);
0276 return Fun4AllReturnCodes::EVENT_OK;
0277 }
0278
0279 const int64_t rawBco = gl1->lValue(0, "BCO");
0280
0281 if (rawBco <= 0)
0282 {
0283 std::cout << "TpcConditionsReco::InitRun - invalid GL1 BCO "
0284 << rawBco << std::endl;
0285 m_conditions->set_ConditionsAvailable(false);
0286 return Fun4AllReturnCodes::EVENT_OK;
0287 }
0288
0289 const uint64_t targetBco = static_cast<uint64_t>(rawBco);
0290
0291 std::cout << " targetBCO = " << targetBco << std::endl;
0292
0293
0294 std::string calibdir = CDBInterface::instance()->getUrl("TPC_CONDITIONS");
0295
0296 if (calibdir.empty())
0297 {
0298 std::cout << "TpcConditionsReco::InitRun - WARNING: "
0299 << "TPC_CONDITIONS not available for this run; "
0300 << "continuing without TPC conditions"
0301 << std::endl;
0302 return Fun4AllReturnCodes::EVENT_OK;
0303 }
0304
0305 m_tree = new CDBTTree(calibdir);
0306 m_tree->LoadCalibrations();
0307
0308
0309 m_bco_to_channel.clear();
0310 for (unsigned int channel = 0;
0311 channel < m_tree->GetUInt64EntryMap().size();
0312 ++channel)
0313 {
0314 uint64_t bco = m_tree->GetUInt64Value(channel, "bco");
0315 m_bco_to_channel[bco] = channel;
0316 }
0317
0318 if (m_bco_to_channel.empty())
0319 {
0320 std::cout << "TpcConditionsReco::InitRun - WARNING: "
0321 << "TPC_CONDITIONS contains no BCO entries; "
0322 << "continuing without TPC conditions"
0323 << std::endl;
0324 return Fun4AllReturnCodes::EVENT_OK;
0325 }
0326
0327 m_conditions->set_AverageLoadCurrent(get_AverageMedianCurrent(ALL));
0328 m_conditions->set_AverageLoadNorth(get_AverageMedianCurrent(NORTH));
0329 m_conditions->set_AverageLoadSouth(get_AverageMedianCurrent(SOUTH));
0330
0331 m_conditions->set_AverageLoadSR1(get_AverageMedianCurrent(SR1));
0332 m_conditions->set_AverageLoadSR2(get_AverageMedianCurrent(SR2));
0333 m_conditions->set_AverageLoadSR3(get_AverageMedianCurrent(SR3));
0334
0335 m_conditions->set_AverageLoadNR1(get_AverageMedianCurrent(NR1));
0336 m_conditions->set_AverageLoadNR2(get_AverageMedianCurrent(NR2));
0337 m_conditions->set_AverageLoadNR3(get_AverageMedianCurrent(NR3));
0338
0339 if (!m_bco_to_channel.empty())
0340 {
0341 recoConsts *rc = recoConsts::instance();
0342 const int segment = rc->get_IntFlag("RUNSEGMENT");
0343
0344
0345 auto upper = m_bco_to_channel.upper_bound(targetBco);
0346 auto selected = upper;
0347
0348 if (upper == m_bco_to_channel.end())
0349 {
0350 selected = std::prev(m_bco_to_channel.end());
0351 }
0352 else if (upper != m_bco_to_channel.begin())
0353 {
0354 auto lower = std::prev(upper);
0355
0356 if ((targetBco - lower->first) <= (upper->first - targetBco))
0357 {
0358 selected = lower;
0359 }
0360 }
0361
0362 const auto first = m_bco_to_channel.begin();
0363 const auto last = std::prev(m_bco_to_channel.end());
0364 const auto middle = std::next(
0365 m_bco_to_channel.begin(),
0366 static_cast<long>(m_bco_to_channel.size() / 2));
0367
0368 std::cout << "R1 conditions:"
0369 << "\n FIRST BCO=" << first->first
0370 << " NR1=" << get_MedianCurrent(first->second, NR1)
0371 << " SR1=" << get_MedianCurrent(first->second, SR1)
0372 << "\n MIDDLE BCO=" << middle->first
0373 << " NR1=" << get_MedianCurrent(middle->second, NR1)
0374 << " SR1=" << get_MedianCurrent(middle->second, SR1)
0375 << "\n LAST BCO=" << last->first
0376 << " NR1=" << get_MedianCurrent(last->second, NR1)
0377 << " SR1=" << get_MedianCurrent(last->second, SR1)
0378 << "\n AVERAGE NR1=" << m_conditions->get_AverageLoadNR1()
0379 << " SR1=" << m_conditions->get_AverageLoadSR1()
0380 << std::endl;
0381
0382 fillConditions(selected->second);
0383
0384
0385 m_conditions->set_LoadCurrent(get_InterpolatedMedianCurrent(targetBco, ALL));
0386 m_conditions->set_LoadNorth(get_InterpolatedMedianCurrent(targetBco, NORTH));
0387 m_conditions->set_LoadSouth(get_InterpolatedMedianCurrent(targetBco, SOUTH));
0388
0389 m_conditions->set_LoadSR1(get_InterpolatedMedianCurrent(targetBco, SR1));
0390 m_conditions->set_LoadSR2(get_InterpolatedMedianCurrent(targetBco, SR2));
0391 m_conditions->set_LoadSR3(get_InterpolatedMedianCurrent(targetBco, SR3));
0392
0393 m_conditions->set_LoadNR1(get_InterpolatedMedianCurrent(targetBco, NR1));
0394 m_conditions->set_LoadNR2(get_InterpolatedMedianCurrent(targetBco, NR2));
0395 m_conditions->set_LoadNR3(get_InterpolatedMedianCurrent(targetBco, NR3));
0396
0397 std::cout << "TpcConditionsReco::InitRun - segment " << segment
0398 << ", target BCO " << targetBco
0399 << ", nearest conditions BCO " << selected->first
0400 << ", interpolated LoadNR1 " << m_conditions->get_LoadNR1()
0401 << ", interpolated LoadSR1 " << m_conditions->get_LoadSR1()
0402 << std::endl;
0403 }
0404
0405 m_conditions->set_ConditionsAvailable(true);
0406 return Fun4AllReturnCodes::EVENT_OK;
0407 }
0408
0409 int TpcConditionsReco::process_event(PHCompositeNode *topNode)
0410 {
0411 if (!m_tree || m_bco_to_channel.empty())
0412 {
0413 return Fun4AllReturnCodes::EVENT_OK;
0414 }
0415
0416
0417 Gl1Packet *gl1 = findNode::getClass<Gl1Packet>(topNode, "GL1RAWHIT");
0418 if (!gl1)
0419 {
0420 std::cout << "TpcConditionsReco::process_event - "
0421 << "could not find GL1RAWHIT node"
0422 << std::endl;
0423 m_conditions->set_ConditionsAvailable(false);
0424 return Fun4AllReturnCodes::EVENT_OK;
0425 }
0426
0427 uint64_t bco = gl1->getBCO();
0428
0429 auto iter = m_bco_to_channel.upper_bound(bco);
0430
0431 if (iter == m_bco_to_channel.begin())
0432 {
0433 iter = m_bco_to_channel.begin();
0434 }
0435 else
0436 {
0437 --iter;
0438 }
0439
0440 int channel = iter->second;
0441
0442 m_conditions->set_Temperature(m_tree->GetFloatValue(channel, "gas_temperature"));
0443 m_conditions->set_Pressure(m_tree->GetFloatValue(channel, "gas_pressure"));
0444 m_conditions->set_FieldOK(m_tree->GetFloatValue(channel, "FieldOK") != 0.0);
0445 m_conditions->set_GainOK(m_tree->GetFloatValue(channel, "GainOK") != 0.0);
0446
0447 m_conditions->set_LoadCurrent(get_InterpolatedMedianCurrent(bco, ALL));
0448 m_conditions->set_LoadNorth(get_InterpolatedMedianCurrent(bco, NORTH));
0449 m_conditions->set_LoadSouth(get_InterpolatedMedianCurrent(bco, SOUTH));
0450
0451 m_conditions->set_LoadSR1(get_InterpolatedMedianCurrent(bco, SR1));
0452 m_conditions->set_LoadSR2(get_InterpolatedMedianCurrent(bco, SR2));
0453 m_conditions->set_LoadSR3(get_InterpolatedMedianCurrent(bco, SR3));
0454
0455 m_conditions->set_LoadNR1(get_InterpolatedMedianCurrent(bco, NR1));
0456 m_conditions->set_LoadNR2(get_InterpolatedMedianCurrent(bco, NR2));
0457 m_conditions->set_LoadNR3(get_InterpolatedMedianCurrent(bco, NR3));
0458
0459 m_conditions->set_ConditionsAvailable(true);
0460
0461
0462 if (m_conditions->get_ConditionsAvailable() &&
0463 (!m_conditions->get_FieldOK() ||
0464 !m_conditions->get_GainOK()))
0465 {
0466 return Fun4AllReturnCodes::ABORTEVENT;
0467 }
0468
0469 return Fun4AllReturnCodes::EVENT_OK;
0470 }
0471
0472 float TpcConditionsReco::get_MedianCurrent(
0473 int channel,
0474 const std::vector<std::string> &channels)
0475 {
0476 std::vector<float> currents;
0477 currents.reserve(channels.size());
0478
0479 for (const auto &name : channels)
0480 {
0481 currents.push_back(m_tree->GetFloatValue(channel, name));
0482 }
0483
0484 std::sort(currents.begin(), currents.end());
0485
0486 const size_t n = currents.size();
0487
0488 if (n % 2)
0489 {
0490 return currents[n / 2];
0491 }
0492
0493 return 0.5F * (currents[n / 2 - 1] + currents[n / 2]);
0494 }