Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:17:32

0001 #include "CaloTowerBuilder.h"
0002 #include "CaloTowerDefs.h"
0003 
0004 #include <calobase/TowerInfo.h>
0005 #include <calobase/TowerInfoContainer.h>
0006 #include <calobase/TowerInfoContainerSimv1.h>
0007 #include <calobase/TowerInfoContainerSimv2.h>
0008 #include <calobase/TowerInfoContainerv1.h>
0009 #include <calobase/TowerInfoContainerv2.h>
0010 #include <calobase/TowerInfoContainerv3.h>
0011 #include <calobase/TowerInfoContainerv4.h>
0012 
0013 #include <ffarawobjects/CaloPacket.h>
0014 #include <ffarawobjects/CaloPacketContainer.h>
0015 
0016 #include <fun4all/Fun4AllReturnCodes.h>
0017 #include <fun4all/SubsysReco.h>  // for SubsysReco
0018 #include <phool/recoConsts.h>
0019 
0020 #include <phool/PHCompositeNode.h>
0021 #include <phool/PHIODataNode.h>    // for PHIODataNode
0022 #include <phool/PHNode.h>          // for PHNode
0023 #include <phool/PHNodeIterator.h>  // for PHNodeIterator
0024 #include <phool/PHObject.h>        // for PHObject
0025 #include <phool/getClass.h>
0026 
0027 #include <cdbobjects/CDBTTree.h>  // for CDBTTree
0028 
0029 #include <ffamodules/CDBInterface.h>
0030 
0031 #include <Event/Event.h>
0032 #include <Event/EventTypes.h>
0033 #include <Event/packet.h>
0034 
0035 #include <TSystem.h>
0036 
0037 #include <climits>
0038 #include <iostream>  // for operator<<, endl, basic...
0039 #include <memory>    // for allocator_traits<>::val...
0040 #include <variant>
0041 #include <vector>  // for vector
0042 
0043 static const std::map<CaloTowerDefs::DetectorSystem, std::string> nodemap{
0044     {CaloTowerDefs::CEMC, "CEMCPackets"},
0045     {CaloTowerDefs::HCALIN, "HCALPackets"},
0046     {CaloTowerDefs::HCALOUT, "HCALPackets"},
0047     {CaloTowerDefs::ZDC, "ZDCPackets"},
0048     {CaloTowerDefs::SEPD, "SEPDPackets"}};
0049 //____________________________________________________________________________..
0050 CaloTowerBuilder::CaloTowerBuilder(const std::string &name)
0051   : SubsysReco(name)
0052   , WaveformProcessing(new CaloWaveformProcessing())
0053 {
0054 }
0055 
0056 //____________________________________________________________________________..
0057 CaloTowerBuilder::~CaloTowerBuilder()
0058 {
0059   delete cdbttree;
0060   delete cdbttree_tbt_zs;
0061   delete WaveformProcessing;
0062 }
0063 
0064 //____________________________________________________________________________..
0065 int CaloTowerBuilder::InitRun(PHCompositeNode *topNode)
0066 {
0067   WaveformProcessing->set_processing_type(_processingtype);
0068   WaveformProcessing->set_softwarezerosuppression(m_bdosoftwarezerosuppression, m_nsoftwarezerosuppression);
0069   if (m_setTimeLim)
0070   {
0071     WaveformProcessing->set_timeFitLim(m_timeLim_low, m_timeLim_high);
0072   }
0073   if (m_dobitfliprecovery)
0074   {
0075     WaveformProcessing->set_bitFlipRecovery(m_dobitfliprecovery);
0076   }
0077 
0078   if (m_dettype == CaloTowerDefs::CEMC)
0079   {
0080     m_detector = "CEMC";
0081     m_packet_low = 6001;
0082     m_packet_high = 6128;
0083     m_nchannels = 192;
0084     WaveformProcessing->set_template_name("CEMC_TEMPLATE");
0085     if (_processingtype == CaloWaveformProcessing::NONE)
0086     {
0087       WaveformProcessing->set_processing_type(CaloWaveformProcessing::TEMPLATE);
0088     }
0089 
0090     //===============
0091     // conditions DB flags
0092     //===============
0093 
0094     m_calibName = "cemc_adcskipmask";
0095 
0096     m_fieldname = "adcskipmask";
0097 
0098     calibdir = CDBInterface::instance()->getUrl(m_calibName);
0099     if (calibdir.empty())
0100     {
0101       std::cout << PHWHERE << "ADC Skip mask not found in CDB, not even in the default... " << std::endl;
0102       exit(1);
0103     }
0104     cdbttree = new CDBTTree(calibdir);
0105   }
0106   else if (m_dettype == CaloTowerDefs::HCALIN)
0107   {
0108     m_packet_low = 7001;
0109     m_packet_high = 7008;
0110     m_detector = "HCALIN";
0111     m_nchannels = 192;
0112     WaveformProcessing->set_template_name("IHCAL_TEMPLATE");
0113     if (_processingtype == CaloWaveformProcessing::NONE)
0114     {
0115       WaveformProcessing->set_processing_type(CaloWaveformProcessing::TEMPLATE);
0116     }
0117   }
0118   else if (m_dettype == CaloTowerDefs::HCALOUT)
0119   {
0120     m_detector = "HCALOUT";
0121     m_packet_low = 8001;
0122     m_packet_high = 8008;
0123     m_nchannels = 192;
0124     WaveformProcessing->set_template_name("OHCAL_TEMPLATE");
0125     if (_processingtype == CaloWaveformProcessing::NONE)
0126     {
0127       WaveformProcessing->set_processing_type(CaloWaveformProcessing::TEMPLATE);
0128     }
0129   }
0130   else if (m_dettype == CaloTowerDefs::SEPD)
0131   {
0132     m_detector = "SEPD";
0133     m_packet_low = 9001;
0134     m_packet_high = 9006;
0135     m_nchannels = 128;
0136     WaveformProcessing->set_template_name("SEPD_TEMPLATE");
0137     if (_processingtype == CaloWaveformProcessing::NONE)
0138     {
0139       WaveformProcessing->set_processing_type(CaloWaveformProcessing::TEMPLATE);  // default the EPD to fast processing
0140     }
0141 
0142     m_calibName = "SEPD_CHANNELMAP2";
0143     m_fieldname = "epd_channel_map2";
0144 
0145     calibdir = CDBInterface::instance()->getUrl(m_calibName);
0146 
0147     if (calibdir.empty())
0148     {
0149       std::cout << PHWHERE << "No sEPD mapping file for domain " << m_calibName << " found" << std::endl;
0150       exit(1);
0151     }
0152 
0153     cdbttree_sepd_map = new CDBTTree(calibdir);
0154   }
0155   else if (m_dettype == CaloTowerDefs::ZDC)
0156   {
0157     m_detector = "ZDC";
0158     m_packet_low = 12001;
0159     m_packet_high = 12001;
0160     m_nchannels = 128;
0161     if (_processingtype == CaloWaveformProcessing::NONE)
0162     {
0163       WaveformProcessing->set_processing_type(CaloWaveformProcessing::FAST);  // default the ZDC to fast processing
0164     }
0165   }
0166   WaveformProcessing->initialize_processing();
0167   if (m_dotbtszs)
0168   {
0169     cdbttree_tbt_zs = new CDBTTree(m_zsURL);
0170   }
0171 
0172   CreateNodeTree(topNode);
0173   return Fun4AllReturnCodes::EVENT_OK;
0174 }
0175 
0176 int CaloTowerBuilder::process_sim()
0177 {
0178   std::vector<std::vector<float>> waveforms;
0179 
0180   for (int ich = 0; ich < (int) m_CalowaveformContainer->size(); ich++)
0181   {
0182     TowerInfo *towerinfo = m_CalowaveformContainer->get_tower_at_channel(ich);
0183     std::vector<float> waveform;
0184     waveform.reserve(m_nsamples);
0185     bool fillwaveform = true;
0186     // get key
0187     if (m_dotbtszs)
0188     {
0189       unsigned int key = m_CalowaveformContainer->encode_key(ich);
0190       int zs_threshold = cdbttree_tbt_zs->GetIntValue(key, m_zs_fieldname);
0191       int pre = towerinfo->get_waveform_value(0);
0192       // this is always safe since towerinfo v3 has 31 samples
0193       int post = towerinfo->get_waveform_value(6);
0194       if ((post - pre) <= zs_threshold)
0195       {
0196         // zero suppressed
0197         fillwaveform = false;
0198         waveform.push_back(pre);
0199         waveform.push_back(post);
0200       }
0201     }
0202     if (fillwaveform)
0203     {
0204       for (int samp = 0; samp < m_nsamples; samp++)
0205       {
0206         waveform.push_back(towerinfo->get_waveform_value(samp));
0207       }
0208     }
0209     waveforms.push_back(waveform);
0210     waveform.clear();
0211   }
0212 
0213   std::vector<std::vector<float>> processed_waveforms = WaveformProcessing->process_waveform(waveforms);
0214   int n_channels = processed_waveforms.size();
0215   for (int i = 0; i < n_channels; i++)
0216   {
0217     // this is for copying the truth info to the downstream object
0218     TowerInfo *towerwaveform = m_CalowaveformContainer->get_tower_at_channel(i);
0219     TowerInfo *towerinfo = m_CaloInfoContainer->get_tower_at_channel(i);
0220     towerinfo->copy_tower(towerwaveform);
0221     towerinfo->set_time(processed_waveforms.at(i).at(1));
0222     towerinfo->set_energy(processed_waveforms.at(i).at(0));
0223     towerinfo->set_time_float(processed_waveforms.at(i).at(1));
0224     towerinfo->set_pedestal(processed_waveforms.at(i).at(2));
0225     towerinfo->set_chi2(processed_waveforms.at(i).at(3));
0226     bool SZS = isSZS(processed_waveforms.at(i).at(1), processed_waveforms.at(i).at(3));
0227     if (processed_waveforms.at(i).at(4) == 0)
0228     {
0229       towerinfo->set_isRecovered(false);
0230     }
0231     else
0232     {
0233       towerinfo->set_isRecovered(true);
0234     }
0235     int n_samples = waveforms.at(i).size();
0236     if (n_samples == m_nzerosuppsamples || SZS)
0237     {
0238       towerinfo->set_isZS(true);
0239     }
0240     for (int j = 0; j < n_samples; j++)
0241     {
0242       towerinfo->set_waveform_value(j, waveforms.at(i).at(j));
0243       if (std::round(waveforms.at(i).at(j)) >= m_saturation)
0244       {
0245         towerinfo->set_isSaturated(true);
0246       }
0247     }
0248   }
0249   waveforms.clear();
0250 
0251   return Fun4AllReturnCodes::EVENT_OK;
0252 }
0253 
0254 int CaloTowerBuilder::process_data(PHCompositeNode *topNode, std::vector<std::vector<float>> &waveforms)
0255 {
0256   std::variant<CaloPacketContainer *, Event *> event;
0257   if (m_UseOfflinePacketFlag)
0258   {
0259     CaloPacketContainer *calopacketcontainer = findNode::getClass<CaloPacketContainer>(topNode, nodemap.find(m_dettype)->second);
0260     if (!calopacketcontainer)
0261     {
0262       for (int pid = m_packet_low; pid <= m_packet_high; pid++)
0263       {
0264         if (findNode::getClass<CaloPacket>(topNode, pid))
0265         {
0266           m_PacketNodesFlag = true;
0267           break;
0268         }
0269       }
0270       if (!m_PacketNodesFlag)
0271       {
0272         return Fun4AllReturnCodes::EVENT_OK;
0273       }
0274     }
0275     else
0276     {
0277       event = calopacketcontainer;
0278     }
0279   }
0280   else
0281   {
0282     Event *_event = findNode::getClass<Event>(topNode, "PRDF");
0283     if (_event == nullptr)
0284     {
0285       std::cout << PHWHERE << " Event not found" << std::endl;
0286       return Fun4AllReturnCodes::ABORTEVENT;
0287     }
0288     if (_event->getEvtType() != DATAEVENT)
0289     {
0290       return Fun4AllReturnCodes::ABORTEVENT;
0291     }
0292     event = _event;
0293   }
0294   // since the function call on Packet and CaloPacket is the same, maybe we can use lambda?
0295   auto process_packet = [&](auto *packet, int pid)
0296   {
0297     if (packet)
0298     {
0299       int nchannels = packet->iValue(0, "CHANNELS");
0300       unsigned int adc_skip_mask = 0;
0301 
0302       if (m_dettype == CaloTowerDefs::CEMC)
0303       {
0304         adc_skip_mask = cdbttree->GetIntValue(pid, m_fieldname);
0305       }
0306       if (m_dettype == CaloTowerDefs::ZDC)
0307       {
0308         nchannels = m_nchannels;
0309       }
0310       if (nchannels > m_nchannels)  // packet is corrupted and reports too many channels
0311       {
0312         return Fun4AllReturnCodes::ABORTEVENT;
0313       }
0314 
0315       int n_pad_skip_mask = 0;
0316       for (int channel = 0; channel < nchannels; channel++)
0317       {
0318         if (skipChannel(channel, pid))
0319         {
0320           continue;
0321         }
0322         if (m_dettype == CaloTowerDefs::CEMC)
0323         {
0324           if (channel % 64 == 0)
0325           {
0326             unsigned int adcboard = (unsigned int) channel / 64;
0327             if ((adc_skip_mask >> adcboard) & 0x1U)
0328             {
0329               for (int iskip = 0; iskip < 64; iskip++)
0330               {
0331                 n_pad_skip_mask++;
0332                 std::vector<float> waveform;
0333                 waveform.reserve(m_nsamples);
0334 
0335                 for (int samp = 0; samp < m_nzerosuppsamples; samp++)
0336                 {
0337                   waveform.push_back(0);
0338                 }
0339                 waveforms.push_back(waveform);
0340                 waveform.clear();
0341               }
0342             }
0343           }
0344         }
0345 
0346         std::vector<float> waveform;
0347         waveform.reserve(m_nsamples);
0348         if (packet->iValue(channel, "SUPPRESSED"))
0349         {
0350           waveform.push_back(packet->iValue(channel, "PRE"));
0351           waveform.push_back(packet->iValue(channel, "POST"));
0352         }
0353         else
0354         {
0355           for (int samp = 0; samp < m_nsamples; samp++)
0356           {
0357             waveform.push_back(packet->iValue(samp, channel));
0358           }
0359         }
0360         waveforms.push_back(waveform);
0361         waveform.clear();
0362       }
0363 
0364       int nch_padded = nchannels;
0365       if (m_dettype == CaloTowerDefs::CEMC)
0366       {
0367         nch_padded += n_pad_skip_mask;
0368       }
0369       if (nch_padded < m_nchannels)
0370       {
0371         for (int channel = 0; channel < m_nchannels - nch_padded; channel++)
0372         {
0373           if (skipChannel(channel, pid))
0374           {
0375             continue;
0376           }
0377           std::vector<float> waveform;
0378           waveform.reserve(m_nsamples);
0379 
0380           for (int samp = 0; samp < m_nzerosuppsamples; samp++)
0381           {
0382             waveform.push_back(0);
0383           }
0384           waveforms.push_back(waveform);
0385           waveform.clear();
0386         }
0387       }
0388     }
0389     else  // if the packet is missing treat constitutent channels as zero suppressed
0390     {
0391       for (int channel = 0; channel < m_nchannels; channel++)
0392       {
0393         if (skipChannel(channel, pid))
0394         {
0395           continue;
0396         }
0397         std::vector<float> waveform;
0398         waveform.reserve(2);
0399         for (int samp = 0; samp < m_nzerosuppsamples; samp++)
0400         {
0401           waveform.push_back(0);
0402         }
0403         waveforms.push_back(waveform);
0404         waveform.clear();
0405       }
0406     }
0407     return Fun4AllReturnCodes::EVENT_OK;
0408   };
0409 
0410   for (int pid = m_packet_low; pid <= m_packet_high; pid++)
0411   {
0412     if (!m_PacketNodesFlag)
0413     {
0414       if (auto *hcalcont = std::get_if<CaloPacketContainer *>(&event))
0415       {
0416         CaloPacket *packet = (*hcalcont)->getPacketbyId(pid);
0417         if (process_packet(packet, pid) == Fun4AllReturnCodes::ABORTEVENT)
0418         {
0419           return Fun4AllReturnCodes::ABORTEVENT;
0420         }
0421       }
0422       else if (auto *_event = std::get_if<Event *>(&event))
0423       {
0424         Packet *packet = (*_event)->getPacket(pid);
0425         if (process_packet(packet, pid) == Fun4AllReturnCodes::ABORTEVENT)
0426         {
0427           // I think it is safe to delete a nullptr...
0428           delete packet;
0429           return Fun4AllReturnCodes::ABORTEVENT;
0430         }
0431         delete packet;
0432       }
0433     }
0434     else
0435     {
0436       CaloPacket *calopacket = findNode::getClass<CaloPacket>(topNode, pid);
0437       process_packet(calopacket, pid);
0438     }
0439   }
0440 
0441   return Fun4AllReturnCodes::EVENT_OK;
0442 }
0443 //____________________________________________________________________________..
0444 int CaloTowerBuilder::process_event(PHCompositeNode *topNode)
0445 {
0446   if (!m_isdata)
0447   {
0448     return process_sim();
0449   }
0450   std::vector<std::vector<float>> waveforms;
0451   if (process_data(topNode, waveforms) == Fun4AllReturnCodes::ABORTEVENT)
0452   {
0453     return Fun4AllReturnCodes::ABORTEVENT;
0454   }
0455   if (waveforms.empty())
0456   {
0457     return Fun4AllReturnCodes::EVENT_OK;
0458   }
0459   // waveform vector is filled here, now fill our output. methods from the base class make sure
0460   // we only fill what the chosen container version supports
0461   std::vector<std::vector<float>> processed_waveforms = WaveformProcessing->process_waveform(waveforms);
0462 
0463   int n_channels = processed_waveforms.size();
0464   for (int i = 0; i < n_channels; i++)
0465   {
0466     int idx = i;
0467     // Align sEPD ADC channels to TowerInfoContainer
0468     if (m_dettype == CaloTowerDefs::SEPD)
0469     {
0470       idx = cdbttree_sepd_map->GetIntValue(i, m_fieldname);
0471     }
0472     TowerInfo *towerinfo = m_CaloInfoContainer->get_tower_at_channel(i);
0473     towerinfo->set_time(processed_waveforms.at(idx).at(1));
0474     towerinfo->set_energy(processed_waveforms.at(idx).at(0));
0475     towerinfo->set_time_float(processed_waveforms.at(idx).at(1));
0476     towerinfo->set_pedestal(processed_waveforms.at(idx).at(2));
0477     towerinfo->set_chi2(processed_waveforms.at(idx).at(3));
0478     bool SZS = isSZS(processed_waveforms.at(idx).at(1), processed_waveforms.at(idx).at(3));
0479     if (processed_waveforms.at(idx).at(4) == 0)
0480     {
0481       towerinfo->set_isRecovered(false);
0482     }
0483     else
0484     {
0485       towerinfo->set_isRecovered(true);
0486     }
0487     int n_samples = waveforms.at(idx).size();
0488     if (n_samples == m_nzerosuppsamples || SZS)
0489     {
0490       if (waveforms.at(idx).at(0) == 0)
0491       {
0492         towerinfo->set_isNotInstr(true);
0493       }
0494       else
0495       {
0496         towerinfo->set_isZS(true);
0497       }
0498     }
0499 
0500     for (int j = 0; j < n_samples; j++)
0501     {
0502       if (std::round(waveforms.at(idx).at(j)) >= m_saturation)
0503       {
0504         towerinfo->set_isSaturated(true);
0505       }
0506       towerinfo->set_waveform_value(j, waveforms.at(idx).at(j));
0507     }
0508   }
0509   waveforms.clear();
0510 
0511   return Fun4AllReturnCodes::EVENT_OK;
0512 }
0513 
0514 bool CaloTowerBuilder::skipChannel(int ich, int pid)
0515 {
0516   if (m_dettype == CaloTowerDefs::SEPD)
0517   {
0518     int sector = ((ich + 1) / 32);
0519     int emptych = -999;
0520     if ((sector == 0) && (pid == 9001))
0521     {
0522       emptych = 1;
0523     }
0524     else
0525     {
0526       emptych = 14 + 32 * sector;
0527     }
0528     if (ich == emptych)
0529     {
0530       return true;
0531     }
0532   }
0533 
0534   if (m_dettype == CaloTowerDefs::ZDC)
0535   {
0536     if (((ich > 17) && (ich < 48)) || ((ich > 63) && (ich < 80)) || ((ich > 81) && (ich < 112)))
0537     {
0538       return true;
0539     }
0540   }
0541 
0542   return false;
0543 }
0544 
0545 bool CaloTowerBuilder::isSZS(float time, float chi2)
0546 {
0547   // isfinite
0548   if (!std::isfinite(time) && !std::isfinite(chi2))
0549   {
0550     return true;
0551   }
0552   return false;
0553 }
0554 
0555 void CaloTowerBuilder::CreateNodeTree(PHCompositeNode *topNode)
0556 {
0557   PHNodeIterator topNodeItr(topNode);
0558   // DST node
0559   PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(topNodeItr.findFirst("PHCompositeNode", "DST"));
0560   if (!dstNode)
0561   {
0562     std::cout << "PHComposite node created: DST" << std::endl;
0563     dstNode = new PHCompositeNode("DST");
0564     topNode->addNode(dstNode);
0565   }
0566   if (!m_isdata)
0567   {
0568     std::string waveformNodeName = m_inputNodePrefix + m_detector;
0569     m_CalowaveformContainer = findNode::getClass<TowerInfoContainer>(topNode, waveformNodeName);
0570     if (!m_CalowaveformContainer)
0571     {
0572       std::cout << PHWHERE << "simulation waveform container " << waveformNodeName << " not found" << std::endl;
0573       gSystem->Exit(1);
0574       exit(1);
0575     }
0576   }
0577 
0578   // towers
0579   PHNodeIterator nodeItr(dstNode);
0580   PHCompositeNode *DetNode;
0581   // enum CaloTowerDefs::DetectorSystem and TowerInfoContainer::DETECTOR are different!!!!
0582   TowerInfoContainer::DETECTOR DetectorEnum = TowerInfoContainer::DETECTOR::DETECTOR_INVALID;
0583   std::string DetectorNodeName;
0584   if (m_dettype == CaloTowerDefs::CEMC)
0585   {
0586     DetectorEnum = TowerInfoContainer::DETECTOR::EMCAL;
0587     DetectorNodeName = "CEMC";
0588   }
0589   else if (m_dettype == CaloTowerDefs::SEPD)
0590   {
0591     DetectorEnum = TowerInfoContainer::DETECTOR::SEPD;
0592     DetectorNodeName = "SEPD";
0593   }
0594   else if (m_dettype == CaloTowerDefs::ZDC)
0595   {
0596     DetectorEnum = TowerInfoContainer::DETECTOR::ZDC;
0597     DetectorNodeName = "ZDC";
0598   }
0599   else if (m_dettype == CaloTowerDefs::HCALIN)
0600   {
0601     DetectorEnum = TowerInfoContainer::DETECTOR::HCAL;
0602     DetectorNodeName = "HCALIN";
0603   }
0604   else if (m_dettype == CaloTowerDefs::HCALOUT)
0605   {
0606     DetectorEnum = TowerInfoContainer::DETECTOR::HCAL;
0607     DetectorNodeName = "HCALOUT";
0608   }
0609   else
0610   {
0611     std::cout << PHWHERE << " Invalid detector type " << m_dettype << std::endl;
0612     gSystem->Exit(1);
0613     exit(1);
0614   }
0615   DetNode = dynamic_cast<PHCompositeNode *>(nodeItr.findFirst("PHCompositeNode", DetectorNodeName));
0616   if (!DetNode)
0617   {
0618     DetNode = new PHCompositeNode(DetectorNodeName);
0619     dstNode->addNode(DetNode);
0620   }
0621   if (m_buildertype == CaloTowerDefs::kPRDFTowerv1)
0622   {
0623     m_CaloInfoContainer = new TowerInfoContainerv1(DetectorEnum);
0624   }
0625   else if (m_buildertype == CaloTowerDefs::kPRDFWaveform)
0626   {
0627     m_CaloInfoContainer = new TowerInfoContainerv3(DetectorEnum);
0628   }
0629   else if (m_buildertype == CaloTowerDefs::kWaveformTowerv2)
0630   {
0631     m_CaloInfoContainer = new TowerInfoContainerv2(DetectorEnum);
0632   }
0633   else if (m_buildertype == CaloTowerDefs::kPRDFTowerv4)
0634   {
0635     m_CaloInfoContainer = new TowerInfoContainerv4(DetectorEnum);
0636   }
0637   else if (m_buildertype == CaloTowerDefs::kWaveformTowerSimv1)
0638   {
0639     m_CaloInfoContainer = new TowerInfoContainerSimv1(DetectorEnum);
0640   }
0641   else
0642   {
0643     std::cout << PHWHERE << "invalid builder type " << m_buildertype << std::endl;
0644     gSystem->Exit(1);
0645     exit(1);
0646   }
0647   TowerNodeName = m_outputNodePrefix + m_detector;
0648   PHIODataNode<PHObject> *newTowerNode = new PHIODataNode<PHObject>(m_CaloInfoContainer, TowerNodeName, "PHObject");
0649   DetNode->addNode(newTowerNode);
0650 }