Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2026-04-04 08:16:13

0001 // use #include "" only for your local include and put
0002 // those in the first line(s) before any #include <>
0003 // otherwise you are asking for weird behavior
0004 // (more info - check the difference in include path search when using "" versus <>)
0005 
0006 #include "SepdMon.h"
0007 
0008 #include <onlmon/OnlMon.h>  // for OnlMon
0009 #include <onlmon/OnlMonDB.h>
0010 #include <onlmon/OnlMonServer.h>
0011 #include <onlmon/pseudoRunningMean.h>
0012 #include <onlmon/triggerEnum.h> // for trigger selection
0013 
0014 #include <calobase/TowerInfoDefs.h>
0015 #include <caloreco/CaloWaveformFitting.h>
0016 
0017 #include <Event/Event.h>
0018 #include <Event/eventReceiverClient.h>
0019 #include <Event/msg_profile.h>
0020 
0021 #include <TH1.h>
0022 #include <TH2.h>
0023 #include <TProfile.h>
0024 #include <TRandom.h>
0025 
0026 #include <cmath>
0027 #include <cstdio>  // for printf
0028 #include <fstream>
0029 #include <iostream>
0030 #include <sstream>
0031 #include <string>  // for allocator, string, char_traits
0032 
0033 enum
0034 {
0035   TRGMESSAGE = 1,
0036   FILLMESSAGE = 2
0037 };
0038 
0039 SepdMon::SepdMon(const std::string &name)
0040   : OnlMon(name)
0041 {
0042   // leave ctor fairly empty, its hard to debug if code crashes already
0043   // during a new EpdMon()
0044   return;
0045 }
0046 
0047 SepdMon::~SepdMon()
0048 {
0049   // you can delete NULL pointers it results in a NOOP (No Operation)
0050   std::vector<runningMean *>::iterator rm_it;
0051   for (auto iter : rm_packet_number)
0052   {
0053     delete iter;
0054   }
0055   for (auto iter : rm_packet_length)
0056   {
0057     delete iter;
0058   }
0059   for (auto iter : rm_packet_chans)
0060   {
0061     delete iter;
0062   }
0063   for (auto iter : rm_packet_event)
0064   {
0065     delete iter;
0066   }
0067   if (erc)
0068   {
0069     delete erc;
0070   }
0071   return;
0072 }
0073 
0074 int SepdMon::Init()
0075 {
0076   gRandom->SetSeed(rand());
0077   // read our calibrations from EpdMonData.dat
0078   /*
0079   const char *sepdcalib = getenv("SEPDCALIB");
0080   if (!sepdcalib)
0081   {
0082     std::cout << "SEPDCALIB environment variable not set" << std::endl;
0083     exit(1);
0084   }
0085   std::string fullfile = std::string(sepdcalib) + "/" + "SepdMonData.dat";
0086   std::ifstream calib(fullfile);
0087 
0088   calib.close();
0089    */
0090   // use printf for stuff which should go the screen but not into the message
0091   // system (all couts are redirected)
0092   printf("doing the Init\n");
0093 
0094   // --- copied straight from the MBD code
0095   mbdns = (0x1UL << TriggerEnum::MBD_NS2) | (0x1UL << TriggerEnum::MBD_NS1); // mbd wide triggers
0096   mbdnsvtx10 = (0x1UL << TriggerEnum::MBD_NS1_ZVRTX10) | (0x1UL << TriggerEnum::MBD_NS2_ZVRTX10);
0097   mbdnsvtx30 = (0x1UL << TriggerEnum::MBD_NS1_ZVRTX13);
0098   mbdnsvtx150 = (0x1UL << TriggerEnum::MBD_NS1_ZVRTX150);
0099   mbdtrig = mbdns | mbdnsvtx10 | mbdnsvtx30 | mbdnsvtx150;
0100 
0101 
0102   h_ADC_all_channel = new TH1D("h_ADC_all_channel",";;",768,-0.5,767.5);
0103   h_hits_all_channel = new TH1D("h_hits_all_channel",";;",768,-0.5,767.5);
0104 
0105   p_noiserms_all_channel = new TProfile("p_noiserms_all_channel","",768,0,768,"S");
0106 
0107   int nADCcorr = 500;
0108   //double ADCcorrmax = 6e6; // AuAu
0109   //double ADCcorrmax = 2e4; // pp
0110   double ADCcorrmax = 2.5e5; // OO
0111   int nhitscorr = 500;
0112   double hitscorrmax = 1000;
0113   h_ADC_corr = new TH2F("h_ADC_corr", ";ADC sum (south); ADC sum (north)", nADCcorr, 0, ADCcorrmax, nADCcorr, 0, ADCcorrmax);
0114   h_hits_corr = new TH2F("h_hits_corr", ";N hits sum (south); N hits sum (north)", nhitscorr, 0, hitscorrmax, nhitscorr, 0, hitscorrmax);
0115 
0116   h_event = new TH1D("h_event", "", 1, 0, 1);
0117 
0118   // waveform processing
0119   h1_waveform_twrAvg = new TH1D("h1_waveform_twrAvg", "", n_samples_show, 0.5, n_samples_show + 0.5);
0120   h1_waveform_time = new TH1D("h1_waveform_time", "", n_samples_show, 0.5, n_samples_show + 0.5);
0121   //h1_waveform_pedestal = new TH1D("h1_waveform_pedestal", "", 42, 1.0e3, 2.0e3);
0122   // --- wider range and more bins, copied from HCal
0123   h1_waveform_pedestal = new TH1F("h1_waveform_pedestal", "", 5e3, 0, 5e3);
0124   h2_sepd_waveform = new TH2F("h2_sepd_waveform", "", n_samples_show, 0.5, n_samples_show + 0.5, 1000, 0, 15000);
0125 
0126   // waveform processing, template vs. fast interpolation
0127   h1_sepd_fitting_sigDiff = new TH1D("h1_fitting_sigDiff", "", 50, 0, 2);
0128   h1_sepd_fitting_pedDiff = new TH1D("h1_fitting_pedDiff", "", 50, 0, 2);
0129   h1_sepd_fitting_timeDiff = new TH1D("h1_fitting_timeDiff", "", 50, -10, 10);
0130 
0131   // packet stuff
0132   h1_packet_number = new TH1D("h1_packet_number", "", 6, packetlow - 0.5, packethigh + 0.5);
0133   h1_packet_length = new TH1D("h1_packet_length", "", 6, packetlow - 0.5, packethigh + 0.5);
0134   h1_packet_chans = new TH1D("h1_packet_chans", "", 6, packetlow - 0.5, packethigh + 0.5);
0135   h1_packet_event = new TH1D("h1_packet_event", "", 6, packetlow - 0.5, packethigh + 0.5);
0136   for(int i = 0; i < nPacketStatus; i++) h1_packet_status[i] = new TH1F(Form("h1_packet_status_%d",i),"",5,packetlow-0.5, packethigh+0.5);
0137 
0138 
0139   for (int i = 0; i < 6; i++)
0140   {
0141     rm_packet_number.push_back(new pseudoRunningMean(1, packet_depth));
0142     rm_packet_length.push_back(new pseudoRunningMean(1, packet_depth));
0143     rm_packet_chans.push_back(new pseudoRunningMean(1, packet_depth));
0144     rm_packet_event.push_back(new pseudoRunningMean(1, packet_depth));
0145   }
0146 
0147   OnlMonServer *se = OnlMonServer::instance();
0148   // register histograms with server otherwise client won't get them
0149   // first histogram uses the TH1->GetName() as key
0150   se->registerHisto(this, h_ADC_all_channel);
0151   se->registerHisto(this, h_hits_all_channel);
0152   se->registerHisto(this, h_ADC_corr);
0153   se->registerHisto(this, h_hits_corr);
0154   se->registerHisto(this, h_event);
0155   se->registerHisto(this, h1_waveform_twrAvg);
0156   se->registerHisto(this, h1_waveform_time);
0157   se->registerHisto(this, h1_waveform_pedestal);
0158   se->registerHisto(this, h2_sepd_waveform);
0159   se->registerHisto(this, h1_packet_number);
0160   se->registerHisto(this, h1_packet_length);
0161   se->registerHisto(this, h1_packet_chans);
0162   se->registerHisto(this, h1_packet_event);
0163   for(int i = 0; i < nPacketStatus; i++) se->registerHisto(this, h1_packet_status[i]);
0164 
0165 
0166   //  se->registerHisto(this, h1_sepd_fitting_sigDiff);
0167   //  se->registerHisto(this, h1_sepd_fitting_pedDiff);
0168   //  se->registerHisto(this, h1_sepd_fitting_timeDiff);
0169 
0170   // save inidividual channel ADC distribution
0171   //for (int ichannel = 0; ichannel < nChannels; ichannel++)
0172   for (int ichannel = 0; ichannel < 768; ichannel++)
0173   {
0174     h_ADC_channel[ichannel] = new TH1D(Form("h_ADC_channel_%d", ichannel), ";ADC;Counts", 1000, 0, 1000);
0175     se->registerHisto(this, h_ADC_channel[ichannel]);
0176   }
0177   se->registerHisto(this, p_noiserms_all_channel);
0178 
0179   // initialize waveform extraction tool
0180   WaveformProcessingFast = new CaloWaveformFitting();
0181 
0182   WaveformProcessingTemp = new CaloWaveformFitting();
0183 
0184   std::string sepdtemplate;
0185   if (getenv("SEPDCALIB"))
0186   {
0187     sepdtemplate = getenv("SEPDCALIB");
0188   }
0189   else
0190   {
0191     sepdtemplate = ".";
0192   }
0193   sepdtemplate += std::string("/testbeam_sepd_template.root");
0194   // WaveformProcessingTemp->initialize_processing(sepdtemplate);
0195 
0196   Reset();
0197 
0198   erc = new eventReceiverClient(eventReceiverClientHost);
0199 
0200   return 0;
0201 }
0202 
0203 int SepdMon::BeginRun(const int /* runno */)
0204 {
0205   // if you need to read calibrations on a run by run basis
0206   // this is the place to do it
0207   std::vector<runningMean *>::iterator rm_it;
0208   for (rm_it = rm_packet_number.begin(); rm_it != rm_packet_number.end(); ++rm_it)
0209   {
0210     (*rm_it)->Reset();
0211   }
0212   for (rm_it = rm_packet_length.begin(); rm_it != rm_packet_length.end(); ++rm_it)
0213   {
0214     (*rm_it)->Reset();
0215   }
0216   for (rm_it = rm_packet_chans.begin(); rm_it != rm_packet_chans.end(); ++rm_it)
0217   {
0218     (*rm_it)->Reset();
0219   }
0220   for (rm_it = rm_packet_event.begin(); rm_it != rm_packet_event.end(); ++rm_it)
0221   {
0222     (*rm_it)->Reset();
0223   }
0224   // if (anaGL1)
0225   // {
0226   OnlMonServer *se = OnlMonServer::instance();
0227   se->UseGl1();
0228   // }
0229   return 0;
0230 }
0231 
0232 // simple wavefrom analysis for possibe issues with the wavforProcessor
0233 std::vector<float> SepdMon::getSignal(Packet *p, const int channel)
0234 {
0235   double baseline = 0;
0236   for (int s = 0; s < 3; s++)
0237   {
0238     baseline += p->iValue(s, channel);
0239   }
0240   baseline /= 3.;
0241 
0242   double signal = 0;
0243   float x = 0;
0244   for (int s = 3; s < p->iValue(0, "SAMPLES"); s++)
0245   {
0246     x++;
0247     signal += p->iValue(s, channel) - baseline;
0248   }
0249 
0250   signal /= x;
0251 
0252   // simulate a failure  if ( evtcount > 450 && p->getIdentifier() ==6011) return 0;
0253 
0254   std::vector<float> result;
0255   result.push_back(signal);
0256   result.push_back(2);
0257   result.push_back(1);
0258   return result;
0259 }
0260 
0261 std::vector<float> SepdMon::anaWaveformFast(Packet *p, const int channel)
0262 {
0263   std::vector<float> waveform;
0264   for (int s = 0; s < p->iValue(0, "SAMPLES"); s++)
0265   {
0266     waveform.push_back(p->iValue(s, channel));
0267   }
0268   std::vector<std::vector<float>> multiple_wfs;
0269   multiple_wfs.push_back(waveform);
0270 
0271   std::vector<std::vector<float>> fitresults_sepd;
0272   fitresults_sepd = WaveformProcessingFast->calo_processing_fast(multiple_wfs);
0273 
0274   std::vector<float> result;
0275   result = fitresults_sepd.at(0);
0276 
0277   return result;
0278 }
0279 
0280 std::vector<float> SepdMon::anaWaveformTemp(Packet *p, const int channel)
0281 {
0282   std::vector<float> waveform;
0283   for (int s = 0; s < p->iValue(0, "SAMPLES"); s++)
0284   {
0285     waveform.push_back(p->iValue(s, channel));
0286   }
0287   std::vector<std::vector<float>> multiple_wfs;
0288   multiple_wfs.push_back(waveform);
0289 
0290   std::vector<std::vector<float>> fitresults_sepd;
0291   fitresults_sepd = WaveformProcessingTemp->process_waveform(multiple_wfs);
0292 
0293   std::vector<float> result;
0294   result = fitresults_sepd.at(0);
0295 
0296   return result;
0297 }
0298 
0299 int SepdMon::process_event(Event *e /* evt */)
0300 {
0301   evtcnt++;
0302   //h1_packet_event->Reset(); // not sure about this...
0303   unsigned int ChannelNumber = 0;
0304   //  float sectorAvg[Nsector] = {0};
0305   // int phi_in = 0;
0306   // float phi;
0307   // float r;
0308   int sumhit_s = 0;
0309   int sumhit_n = 0;
0310   long double sumADC_s = 0;
0311   long double sumADC_n = 0;
0312 
0313   // --- get the trigger info...
0314   // --- don't need trigger info for pp
0315   // bool is_trigger_okay = false;
0316   // int evtnr = e->getEvtSequence();
0317   // Event* gl1Event = erc->getEvent(evtnr);
0318   // // --- only do this insanity for diagnostic purposes and a small number of events
0319   // // std::cout << "event number evtnr is " << evtnr << std::endl;
0320   // // std::cout << "gl1Event pointer is " << gl1Event << std::endl;
0321   // if ( gl1Event )
0322   //   {
0323   //     OnlMonServer *se = OnlMonServer::instance();
0324   //     se->IncrementGl1FoundCounter();
0325   //     Packet* pgl1 = gl1Event->getPacket(14001);
0326   //     // --- only do this insanity for diagnostic purposes and a small number of events
0327   //     // std::cout << "gl1 packet 14001 pointer is " << pgl1 << std::endl;
0328   //     if ( pgl1 )
0329   //       {
0330   //         uint64_t triggervec = pgl1->lValue(0, "ScaledVector");
0331   //         is_trigger_okay = triggervec & mbdtrig;
0332   //         // --- only do this insanity for diagnostic purposes and a small number of events
0333   //         // std::cout << "triggervec is " << triggervec << std::endl;
0334   //         // std::cout << "mbdtrig is " << mbdtrig << std::endl;
0335   //         // std::cout << "trigger decision is " << is_trigger_okay << std::endl;
0336   //         delete pgl1;
0337   //       }
0338   //     delete gl1Event;
0339   //   }
0340 
0341   uint64_t zdc_clock = 0;
0342   Packet* pzdc = e->getPacket(12001);
0343   if ( pzdc )
0344     {
0345       zdc_clock = pzdc->lValue(0,"CLOCK");
0346       // --- only do this insanity for diagnostic purposes and a small number of events
0347       // std::cout << "ZDC clock is " << zdc_clock << std::endl;
0348       delete pzdc;
0349     }
0350   // --- only do this insanity for diagnostic purposes and a small number of events
0351   // else std::cout << "Why no ZDC packet..." << std::endl;
0352 
0353   // loop over packets which contain a single sector
0354   for (int packet = packetlow; packet <= packethigh; packet++)
0355   {
0356     Packet *p = e->getPacket(packet);
0357     int packet_index = packet - packetlow;
0358     int packet_bin = packet - packetlow + 1;
0359     if (p)
0360     {
0361       int one[1] = {1};
0362       rm_packet_number[packet_index]->Add(one);
0363       int packet_length[1] = {p->getLength()};
0364       rm_packet_length[packet_index]->Add(packet_length);
0365       h1_packet_status[(int)p->getStatus()]->Fill(packet);
0366       h1_packet_length->SetBinContent(packet_bin, rm_packet_length[packet_index]->getMean(0));
0367 
0368       // ---
0369       uint64_t p_clock = p->lValue(0,"CLOCK");
0370       long long clock_diff = p_clock-zdc_clock;
0371       double cd = (double)clock_diff;
0372       // --- only do this insanity for diagnostic purposes and a small number of events
0373       // std::cout << "Packet clock is " << p_clock << " and clock diff is " << clock_diff << " " << cd << std::endl;
0374       // --- trying to improve clock diff...
0375       // --- currently we overwrite the histogram with the difference from the latest event
0376       // --- not sure if we want to do that or running mean, which is done for the number, length, channels
0377       // h1_packet_event->SetBinContent(packet - packetlow + 1, p->lValue(0, "CLOCK"));
0378       // h1_packet_event->SetBinContent(packet_bin, clock_diff);
0379       // h1_packet_event->SetBinContent(packet_bin, cd);
0380       rm_packet_event[packet_index]->Add(&cd);
0381       h1_packet_event->SetBinContent(packet_bin, rm_packet_event[packet_index]->getMean(0));
0382       // --- only do this insanity for diagnostic purposes and a small number of events
0383       // std::cout << "Histogram bin " << packet_bin << " center " << h1_packet_event->GetBinCenter(packet_bin) << " bin content " << h1_packet_event->GetBinContent(packet_bin) << std::endl;
0384       int nPacketChannels = p->iValue(0, "CHANNELS");
0385       if (nPacketChannels > m_nChannels)
0386       {
0387         return -1;  // packet is corrupted, reports too many channels
0388       }
0389       // else
0390       // {
0391       //   rm_packet_chans[packet - packetlow]->Add(&nChannels);
0392       //   h1_packet_chans->SetBinContent(packet_bin, rm_packet_chans[packet - packetlow]->getMean(0));
0393       // }
0394       int channel_counter = 0;
0395       for (int c = 0; c < p->iValue(0, "CHANNELS"); c++)
0396       {
0397         // msg << "Filling channel: " << c << " for packet: " << packet << std::endl;
0398         // se->send_message(this, MSG_SOURCE_UNSPECIFIED, MSG_SEV_INFORMATIONAL, msg.str(), TRGMESSAGE);
0399         //  record waveform to show the average waveform
0400         channel_counter++;
0401 
0402         ChannelNumber++;
0403         int ch = ChannelNumber-1;
0404 
0405         // -- bit flipped ADC channels
0406         //bool reject_this_channel = false;
0407         //if ( ( packet == 9001 || packet == 9002 || packet == 9006 ) && c == 30 )
0408         //  reject_this_channel = true;
0409 
0410         //if ( reject_this_channel ) continue;
0411 
0412         // std::vector result =  getSignal(p,c); // simple peak extraction
0413         std::vector<float> resultFast = anaWaveformFast(p, c);  // fast waveform fitting
0414         float signalFast = resultFast.at(0);
0415         float timeFast = resultFast.at(1);
0416         float pedestalFast = resultFast.at(2);
0417         float prepost = p->iValue(c, "PRE") - p->iValue(c, "POST");
0418         if ( prepost > 0 )
0419           {
0420             p_noiserms_all_channel->Fill(ch,prepost);
0421             p_noiserms_all_channel->Fill(ch,-prepost);
0422           }
0423 
0424         // --- Run24pp
0425         //bool is_good_hit = ( signalFast > 50 && signalFast < 3000 );
0426         // --- Run25AuAu
0427         // --- Run25OO using same to start
0428         bool is_good_hit = ( signalFast > 50 && signalFast < 15000 );
0429 
0430         // std::vector<float> resultTemp = anaWaveformTemp(p, c);  // template waveform fitting
0431         // float signalTemp = resultTemp.at(0);
0432         // float timeTemp  = resultTemp.at(1);
0433         // float pedestalTemp = resultTemp.at(2);
0434         if (signalFast > hit_threshold)
0435         {
0436           for (int s = 0; s < p->iValue(0, "SAMPLES"); s++)
0437           {
0438             h2_sepd_waveform->Fill(s, p->iValue(s, c) - pedestalFast);
0439           }
0440         }
0441         // ---
0442         if ( signalFast > 0 && signalFast < 1e10 )
0443           {
0444             // --- 1d ADC distributions for all channels
0445             h_ADC_channel[ch]->Fill(signalFast);
0446             // --- total ADC vs channel number
0447             h_ADC_all_channel->Fill(ch,signalFast);
0448             // --- total hits vs channel number
0449             if ( is_good_hit ) h_hits_all_channel->Fill(ch);
0450             // --- 1d waveform
0451             h1_waveform_time->Fill(timeFast);
0452             h1_waveform_pedestal->Fill(pedestalFast);
0453           }
0454         // ---
0455 
0456         // h1_sepd_fitting_sigDiff -> Fill(signalFast/signalTemp);
0457         // h1_sepd_fitting_pedDiff -> Fill(pedestalFast/pedestalTemp);
0458         // h1_sepd_fitting_timeDiff -> Fill(timeFast - timeTemp);
0459 
0460         int z_bin = -1;
0461         if ( ch >= 384 && ch <= 767 ) z_bin = 0;
0462         if ( ch <= 383 && ch >= 0 ) z_bin = 1;
0463 
0464         if ( z_bin == 0 && is_good_hit )
0465         {
0466           sumhit_s++;
0467           sumADC_s += signalFast;
0468         }
0469         if ( z_bin == 1 && is_good_hit )
0470         {
0471           sumhit_n++;
0472           sumADC_n += signalFast;
0473         }
0474 
0475       }  // channel loop end
0476     rm_packet_chans[packet_index]->Add(&channel_counter);
0477     h1_packet_chans->SetBinContent(packet_bin, rm_packet_chans[packet_index]->getMean(0));
0478     }    //  if packet good
0479     else
0480     {
0481       ChannelNumber += 128;
0482       int zero[1] = {0};
0483       rm_packet_number[packet_index]->Add(zero);
0484     }
0485     h1_packet_number->SetBinContent(packet_bin, rm_packet_number[packet_index]->getMean(0));
0486     delete p;
0487 
0488   }  // packet id loop end
0489 
0490   h_event->Fill(0);
0491   // h1_waveform_twrAvg->Scale(1. / 32. / 48.);  // average tower waveform
0492   h1_waveform_twrAvg->Scale((float) 1 / ChannelNumber);
0493 
0494   // --- need to make a trigger selection?
0495   // --- yes in AuAu, no in pp, leaving out to start in OO
0496   //  if ( is_trigger_okay )
0497   //    {
0498   h_ADC_corr->Fill(sumADC_s, sumADC_n);
0499   h_hits_corr->Fill(sumhit_s, sumhit_n);
0500   //    }
0501 
0502   return 0;
0503 
0504 }
0505 
0506 int SepdMon::Reset()
0507 {
0508   // reset our internal counters
0509   evtcnt = 0;
0510   idummy = 0;
0511 
0512   return 0;
0513 }