Back to home page

sPhenix code displayed by LXR

 
 

    


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

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 "LocalPolMon.h"
0007 
0008 #include <onlmon/OnlMon.h>  // for OnlMon
0009 #include <onlmon/OnlMonDB.h>
0010 #include <onlmon/OnlMonServer.h>
0011 
0012 #include <caloreco/CaloWaveformFitting.h>
0013 
0014 #include <Event/Event.h>
0015 #include <Event/EventTypes.h>
0016 #include <Event/eventReceiverClient.h>
0017 #include <Event/msg_profile.h>
0018 
0019 #include <TH1.h>
0020 #include <TH2.h>
0021 #include <TObjArray.h>
0022 #include <TObjString.h>
0023 #include <TProfile.h>
0024 #include <TRandom.h>
0025 #include <TString.h>
0026 #include <TSystem.h>
0027 
0028 #include <cmath>
0029 #include <cstdio>  // for printf
0030 #include <ctime>
0031 #include <fstream>
0032 #include <iostream>
0033 #include <map>
0034 #include <sstream>
0035 #include <string>  // for allocator, string, char_traits
0036 #include <utility>
0037 
0038 LocalPolMon::LocalPolMon(const std::string& name)
0039   : OnlMon(name)
0040 {
0041   // leave ctor fairly empty, its hard to debug if code crashes already
0042   // during a new LocalPolMon()
0043   return;  // test
0044 }
0045 
0046 int LocalPolMon::Init()
0047 {
0048   iPoint = 0;
0049   for (bool& i : goodtrigger)
0050   {  // 16 triggers for gl1p
0051     i = false;
0052   }
0053   goodtrigger[10] = true;
0054   OnlMonServer* se = OnlMonServer::instance();
0055   const char* locpolcal = getenv("LOCALPOLCALIB");
0056   if (!locpolcal)
0057   {
0058     std::cout << "LOCALPOLCALIB environment variable not set" << std::endl;
0059     exit(1);
0060   }
0061   std::string lpconfigfilename = std::string(locpolcal) + "/" + "LocPolConfig.dat";
0062   std::ifstream config(lpconfigfilename);
0063   std::ostringstream msg_config(lpconfigfilename);
0064 
0065   if (!config)
0066   {
0067     msg_config << lpconfigfilename << " could not be opened.";
0068     se->send_message(this, MSG_SOURCE_LOCALPOL, MSG_SEV_FATAL, msg_config.str(), 2);
0069     exit(1);
0070   }
0071   int err_counter = 0;
0072   TString key;
0073   TString val;
0074   while (!config.eof())
0075   {
0076     config >> key >> val;
0077     std::cout << "Config in " << config.good() << " state\n";
0078     if (!config.good())
0079     {
0080       break;
0081     }
0082     key.ToLower();
0083     std::cout << "Reading " << key << " with value " << val << std::endl;
0084     if (key == "trigger")
0085     {
0086       if (!val.IsDigit())
0087       {
0088         std::cout << key << ": expecting an integer (2^(trigger bit number))\n keep only bit 10 as default value.\n";
0089         goodtrigger[10] = true;
0090       }
0091       else
0092       {
0093         int ival = val.Atoi();
0094         if (ival < 0 || ival > 65535)
0095         {
0096           std::cout << key << ": value outside expected range [0; 65535]\n Keep only bit 10 as default value.\n";
0097           goodtrigger[10] = true;
0098         }
0099         else
0100         {
0101           for (int i = 0; i < 16; i++)
0102           {
0103             goodtrigger[i] = false;
0104             if ((ival & (1 << i)))
0105             {
0106               goodtrigger[i] = true;
0107             }
0108           }
0109         }
0110       }
0111     }
0112     else if (key == "testfake")
0113     {
0114       if (!val.IsDigit())
0115       {
0116         std::cout << key << ": expecting 0/1 for true or false\n Keep false as default.\n";
0117         fake = false;
0118       }
0119       else
0120       {
0121         int ival = val.Atoi();
0122         if (ival != 0 && ival != 1)
0123         {
0124           std::cout << key << ": expecting 0/1 for true or false\n Keep false as default.\n";
0125           fake = false;
0126         }
0127         else
0128         {
0129           if (ival == 1)
0130           {
0131             fake = true;
0132             erc = nullptr;
0133           }
0134           else
0135           {
0136             fake = false;
0137           }
0138         }
0139       }
0140     }
0141     else if (key == "monitoring"){
0142       val.ToLower();
0143       if (val == "online"){
0144     erc = new eventReceiverClient(eventReceiverClientHost);
0145       }
0146       else if (val == "offline" ){
0147     erc = new eventReceiverClient("localhost");
0148       }
0149       else {
0150     std::cout<< key << ": expecting either online (data stream)/offline (with eventServer -d 5263250 -s 5 -i -v -f path to gl1 prdf) "<<std::endl;
0151     std::cout<<"Fall back to online monitoring"<<std::endl;
0152     erc = new eventReceiverClient(eventReceiverClientHost);
0153       }
0154     }
0155     else if (key == "sphenixgap")
0156     {
0157       if (!val.IsDigit())
0158       {
0159         std::cout << key << ": expecting an integer as the first bunch number of the continuous gap sequence\n Keep 111 as default.\n";
0160         ExpectedsPhenixGapPosition = 111;
0161       }
0162       else
0163       {
0164         int ival = val.Atoi();
0165         if (ival >= 0 && ival < 120)
0166         {
0167           ExpectedsPhenixGapPosition = ival;
0168         }
0169         else
0170         {
0171           std::cout << key << ": value outside expected range [0;119]\n Keep 117 as default value\n";
0172           ExpectedsPhenixGapPosition = 111;
0173         }
0174       }
0175     }
0176     else if (key == "threshold")
0177     {
0178       if (!val.IsDigit())
0179       {
0180         std::cout << key << ": expecting a positive integer\n Keep 6000 as default value\n";
0181         EventCountThresholdGap = 6000;
0182       }
0183       else
0184       {
0185         int ival = val.Atoi();
0186         if (ival > 0 && ival < 1e5)
0187         {
0188           EventCountThresholdGap = ival;
0189         }
0190         else
0191         {
0192           std::cout << key << ": integer seems too big (>1e5)\n Keep default 6000\n";
0193           EventCountThresholdGap = 6000;
0194         }
0195       }
0196     }
0197     else if (key == "verbosity")
0198     {
0199       if (!val.IsDigit())
0200       {
0201         std::cout << key << ": expecting 0/1 for false or true\n Keep 0(false) as default\n";
0202         verbosity = false;
0203       }
0204       else
0205       {
0206         int ival = val.Atoi();
0207         if (ival != 0 && ival != 1)
0208         {
0209           std::cout << key << ": value should be 0 or 1 for false of true\n Keep 0(false) as default\n";
0210           verbosity = false;
0211         }
0212         else if (ival == 1)
0213         {
0214           std::cout << "Making it verbose" << std::endl;
0215           verbosity = true;
0216         }
0217       }
0218     }
0219     else if (key == "integrated")
0220     {
0221       if (!val.IsDigit())
0222       {
0223         std::cout << key << ": expecting 0/1 for false or true\n Keep 0(false) as default\n";
0224         Integrated = false;
0225       }
0226       else
0227       {
0228         int ival = val.Atoi();
0229         if (ival != 0 && ival != 1)
0230         {
0231           std::cout << key << ": value should be 0 or 1 for false of true\n Keep 0(false) as default\n";
0232           Integrated = false;
0233         }
0234         else if (ival == 1)
0235         {
0236           std::cout << "Making it integrated" << std::endl;
0237           Integrated = true;
0238         }
0239       }
0240     }
0241     else if (key == "x0north")
0242     {
0243       if (val.IsFloat())
0244       {
0245         if (val.Atof() < -3. || val.Atof() > 3.)
0246         {
0247           std::cout << key << ": value outside the expected range [-3.;3]cm\n keeping 0.0 as default value." << std::endl;
0248         }
0249         else
0250         {
0251           ZeroPosition[1] = val.Atof();
0252         }
0253       }
0254       else
0255       {
0256         std::cout << key << ": value is not a float\n keeping 0.0 as default value" << std::endl;
0257         ZeroPosition[1] = 0.;
0258       }
0259     }
0260     else if (key == "y0north")
0261     {
0262       if (val.IsFloat())
0263       {
0264         if (val.Atof() < -3. || val.Atof() > 3.)
0265         {
0266           std::cout << key << ": value outside the expected range [-3.;3]cm\n keeping 0.0 as default value." << std::endl;
0267         }
0268         else
0269         {
0270           ZeroPosition[0] = val.Atof();
0271         }
0272       }
0273       else
0274       {
0275         std::cout << key << ": value is not a float\n keeping 0.0 as default value" << std::endl;
0276         ZeroPosition[0] = 0.;
0277       }
0278     }
0279     else if (key == "x0south")
0280     {
0281       if (val.IsFloat())
0282       {
0283         if (val.Atof() < -3. || val.Atof() > 3.)
0284         {
0285           std::cout << key << ": value outside the expected range [-3.;3]cm\n keeping 0.0 as default value." << std::endl;
0286         }
0287         else
0288         {
0289           ZeroPosition[3] = val.Atof();
0290         }
0291       }
0292       else
0293       {
0294         std::cout << key << ": value is not a float\n keeping 0.0 as default value" << std::endl;
0295         ZeroPosition[3] = 0.;
0296       }
0297     }
0298     else if (key == "y0south")
0299     {
0300       if (val.IsFloat())
0301       {
0302         if (val.Atof() < -3. || val.Atof() > 3.)
0303         {
0304           std::cout << key << ": value outside the expected range [-3.;3]cm\n keeping 0.0 as default value." << std::endl;
0305         }
0306         else
0307         {
0308           ZeroPosition[2] = val.Atof();
0309         }
0310       }
0311       else
0312       {
0313         std::cout << key << ": value is not a float\n keeping 0.0 as default value" << std::endl;
0314         ZeroPosition[2] = 0.;
0315       }
0316     }
0317     else if (key == "thresholdasymnewpoint")
0318     {
0319       if (!val.IsDigit())
0320       {
0321         std::cout << key << ": value is expected to be a positive integer\n Keeping default value of 5000 events." << std::endl;
0322       }
0323       else
0324       {
0325         std::cout << key << "Changed from " << EventsAsymmetryNewPoint << " to " << val.Atoi() << std::endl;
0326         EventsAsymmetryNewPoint = val.Atoi();
0327       }
0328     }
0329     else if (key == "zdc1cut")
0330       {
0331     if(!val.IsFloat())
0332       {
0333         std::cout<< key << " : value is expected to be a positive float\n Keeping default value of 60."<<std::endl; 
0334       }
0335     else
0336       {
0337         std::cout<< key << " Changed from "<< ZDC1Cut << " to "<<val.Atof()<<std::endl;
0338         ZDC1Cut = val.Atof();
0339       }
0340       }
0341     else if (key == "zdc2cut")
0342       {
0343     if(!val.IsFloat())
0344       {
0345         std::cout<< key << " : value is expected to be a positive float\n Keeping default value of 15."<<std::endl; 
0346       }
0347     else
0348       {
0349         std::cout<< key << " Changed from "<< ZDC2Cut << " to "<<val.Atof()<<std::endl;
0350         ZDC2Cut = val.Atof();
0351       }
0352       }
0353     else if (key == "vetocut")
0354       {
0355     if(!val.IsFloat())
0356       {
0357         std::cout<< key << " : value is expected to be a positive float\n Keeping default value of 150."<<std::endl; 
0358       }
0359     else
0360       {
0361         std::cout<< key << " Changed from "<< VetoCut << " to "<<val.Atof()<<std::endl;
0362         VetoCut = val.Atof();
0363       }
0364       }
0365     else if (key == "multiplicitylow")
0366       {
0367     if(!val.IsDigit())
0368       {
0369         std::cout<< key << " : value is expected to be a positive integer\n Keeping default value of 1"<<std::endl; 
0370       }
0371     else
0372       {
0373         std::cout<< key << " Changed from "<< MultiLow << " to "<<val.Atoi()<<std::endl;
0374         MultiLow = val.Atoi();
0375       }
0376       }
0377     else if (key == "multiplicityhigh")
0378       {
0379     if(!val.IsDigit())
0380       {
0381         std::cout<< key << " : value is expected to be a positive integer\n Keeping default value of 7 (for vertical and +1 for horizontal)"<<std::endl; 
0382       }
0383     else
0384       {
0385         std::cout<< key << " Changed from "<< MultiHigh << " to "<<val.Atoi()<<std::endl;
0386         MultiHigh = val.Atoi();
0387       }
0388       }
0389     else if (key == "smdthreshold")
0390       {
0391     if(!val.IsFloat())
0392       {
0393         std::cout<< key << " : value is expected to be a positive float\n Keeping default value of 5"<<std::endl; 
0394       }
0395     else
0396       {
0397         std::cout<< key << " Changed from "<< SMDthr << " to "<<val.Atof()<<std::endl;
0398         SMDthr = val.Atof();
0399       }
0400       }
0401     else
0402     {
0403       err_counter++;
0404       std::cout << "Unknown configuration \n Expected:\n -verbosity\n -threshold\n -sphenixgap\n -testfake\n -monitoring\n -multiplicitylow\n -multiplicityHigh\n -trigger\n -X0north\n -X0south\n -Y0north\n -Y0south\n -thresholdasymnewpoint\n -nVetocut\n -SMDthreshold\n -ZDC1cut\n -ZDC2cut\n -Integrated\n key words" << std::endl;
0405     }
0406     if (err_counter > 3)
0407     {
0408       std::cout << "More than 3 unknown key words, abort" << std::endl;
0409       exit(1);
0410     }
0411   }
0412 
0413   std::string lpmappingfilename = std::string(locpolcal) + "/" + "ChannelMapping.txt";
0414   std::ifstream mapping(lpmappingfilename);
0415   std::ostringstream msg_mapping(lpmappingfilename);
0416 
0417   if (!mapping)
0418   {
0419     msg_mapping << lpmappingfilename << " could not be opened.";
0420     se->send_message(this, MSG_SOURCE_LOCALPOL, MSG_SEV_FATAL, msg_mapping.str(), 2);
0421     exit(1);
0422   }
0423   int adc, array, lowcut, highcut;
0424   std::string ChannelName;
0425   for (int i = 0; i < 128; i++)
0426   {
0427     mapping >> adc >> array >> lowcut >> highcut >> ChannelName;
0428     Chmapping[adc] = array;
0429     if(array>-1){
0430       lowSample[array]=lowcut;
0431       highSample[array]=highcut;
0432     }
0433   }
0434 
0435   const char* zdccalib = getenv("ZDCCALIB");
0436   if (!zdccalib)
0437   {
0438     std::cout << "ZDCCALIB environment variable not set" << std::endl;
0439     exit(1);
0440   }
0441   std::string calibfilename = std::string(zdccalib) + "/" + "SMDRelativeGain.dat";
0442   std::ifstream calibinput(calibfilename);
0443   std::ostringstream msg(calibfilename);
0444 
0445   if (!calibinput)
0446   {
0447     msg << calibfilename << " could not be opened.";
0448     se->send_message(this, MSG_SOURCE_LOCALPOL, MSG_SEV_FATAL, msg.str(), 2);
0449     exit(1);
0450   }
0451   int NS;
0452   int channel;
0453   float gain;
0454   for (int ch = 0; ch < 32; ch++)
0455   {
0456     calibinput >> NS >> channel >> gain;
0457 
0458     if (NS == 0 && channel >= 0 && channel < 16)
0459     {
0460       smd_north_relatgain[channel] = gain;
0461     }
0462     else if (NS == 1 && channel >= 0 && channel < 16)
0463     {
0464       smd_south_relatgain[channel] = gain;
0465     }
0466     else
0467     {
0468       msg << calibfilename << "could not understand the content, expect int(0/1) int(0-15) float for North or South, channel number and relative gain";
0469       se->send_message(this, MSG_SOURCE_ZDC, MSG_SEV_FATAL, msg.str(), 2);
0470       exit(1);
0471     }
0472   }
0473 
0474   h_Counts = new TH1D*[4];
0475   h_CountsScramble = new TH1D*[4];
0476 
0477   h_Counts[0] = new TH1D("h_BlueCountsUD", "h_BlueCountsUD", 4, 0, 4);
0478   h_Counts[1] = new TH1D("h_BlueCountsLR", "h_BlueCountsLR", 4, 0, 4);
0479   h_Counts[2] = new TH1D("h_YellCountsUD", "h_YellCountsUD", 4, 0, 4);
0480   h_Counts[3] = new TH1D("h_YellCountsLR", "h_YellCountsLR", 4, 0, 4);
0481   h_CountsScramble[0] = new TH1D("h_BlueCountsScrambleUD", "h_BlueCountsScrambleUD", 4, 0, 4);
0482   h_CountsScramble[1] = new TH1D("h_BlueCountsScrambleLR", "h_BlueCountsScrambleLR", 4, 0, 4);
0483   h_CountsScramble[2] = new TH1D("h_YellCountsScrambleUD", "h_YellCountsScrambleUD", 4, 0, 4);
0484   h_CountsScramble[3] = new TH1D("h_YellCountsScrambleLR", "h_YellCountsScrambleLR", 4, 0, 4);
0485 
0486   for(int i=0; i<4; i++){
0487     se->registerHisto(this,h_Counts[i]);
0488     se->registerHisto(this,h_CountsScramble[i]);
0489   }
0490 
0491   h_time = new TProfile("h_times", "h_time", 5000, -0.5, 4999.5);
0492   se->registerHisto(this, h_time);
0493 
0494   TString BeamName[2] = {"Blue", "Yell"};
0495   TString MethodName[2] = {"Arithmetic", "Geometric"};
0496   //TString Orientation[2] = {"LR", "UD"};
0497   TString Orientation[2] = {"UD", "LR"};
0498   h_Asym = new TH1D***[2];
0499   h_AsymScramble = new TH1D***[2];
0500   for (int beam = 0; beam < 2; beam++)
0501   {
0502     h_Asym[beam] = new TH1D**[2];
0503     h_AsymScramble[beam] = new TH1D**[2];
0504     for (int method = 0; method < 2; method++)
0505     {
0506       h_Asym[beam][method] = new TH1D*[2];
0507       h_AsymScramble[beam][method] = new TH1D*[2];
0508       for (int orient = 0; orient < 2; orient++)
0509       {
0510         h_Asym[beam][method][orient] = new TH1D(Form("h_Asym%s%s%s", BeamName[beam].Data(), MethodName[method].Data(), Orientation[orient].Data()), Form("Fwd %s %s %s Asym.", BeamName[beam].Data(), Orientation[orient].Data(), MethodName[method].Data()), 5000, -0.5, 4999.5);
0511         h_AsymScramble[beam][method][orient] = new TH1D(Form("h_AsymScramble%s%s%s", BeamName[beam].Data(), MethodName[method].Data(), Orientation[orient].Data()), Form("Bwk %s %s %s Asym.", BeamName[beam].Data(), Orientation[orient].Data(), MethodName[method].Data()), 5000, -0.5, 4999.5);
0512 
0513         se->registerHisto(this, h_Asym[beam][method][orient]);
0514         se->registerHisto(this, h_AsymScramble[beam][method][orient]);
0515       }
0516     }
0517   }
0518   for(int itrig=0; itrig<16; itrig++){
0519     h_trigger[itrig]=new TH1D(Form("h_trigger%d",itrig),Form("h_trigger%d",itrig),120,0,120);
0520     se->registerHisto(this,h_trigger[itrig]);
0521   }
0522   h_events=new TH1D("h_events","h_events",20,0,20);
0523   se->registerHisto(this,h_events);
0524 
0525   hspinpattern=new TH2I("hspinpattern","hspinpattern",120,0,120,2,0,2);
0526   se->registerHisto(this,hspinpattern);
0527 
0528   hmultiplicity[0]=new TH1D("hmultiplicitySMD_NH","hmultiplicitySMD_NH",9,0,9);
0529   hmultiplicity[1]=new TH1D("hmultiplicitySMD_NV","hmultiplicitySMD_NV",8,0,8);
0530   hmultiplicity[2]=new TH1D("hmultiplicitySMD_SH","hmultiplicitySMD_SH",9,0,9);
0531   hmultiplicity[3]=new TH1D("hmultiplicitySMD_SV","hmultiplicitySMD_SV",8,0,8);
0532 
0533   hposition[0]=new TH1D("hpositionSMD_NH_up","hpositionSMD_NH_up",100,-5,5);
0534   hposition[1]=new TH1D("hpositionSMD_NV_up","hpositionSMD_NV_up",100,-5,5);
0535   hposition[2]=new TH1D("hpositionSMD_SH_up","hpositionSMD_SH_up",100,-5,5);
0536   hposition[3]=new TH1D("hpositionSMD_SV_up","hpositionSMD_SV_up",100,-5,5);
0537   hposition[4]=new TH1D("hpositionSMD_NH_dn","hpositionSMD_NH_dn",100,-5,5);
0538   hposition[5]=new TH1D("hpositionSMD_NV_dn","hpositionSMD_NV_dn",100,-5,5);
0539   hposition[6]=new TH1D("hpositionSMD_SH_dn","hpositionSMD_SH_dn",100,-5,5);
0540   hposition[7]=new TH1D("hpositionSMD_SV_dn","hpositionSMD_SV_dn",100,-5,5);
0541 
0542   hadcsum[0]=new TH1D("hadcsumSMD_NH","hadcsumSMD_NH",100,0,4.5);
0543   hadcsum[1]=new TH1D("hadcsumSMD_NV","hadcsumSMD_NV",100,0,4.5);
0544   hadcsum[2]=new TH1D("hadcsumSMD_SH","hadcsumSMD_SH",100,0,4.5);
0545   hadcsum[3]=new TH1D("hadcsumSMD_SV","hadcsumSMD_SV",100,0,4.5);
0546 
0547   for(int i=0; i<4; i++){
0548     se->registerHisto(this,hmultiplicity[i]);
0549     se->registerHisto(this,hposition[i]);
0550     se->registerHisto(this,hposition[i+4]);
0551     se->registerHisto(this,hadcsum[i]);
0552   }
0553 
0554   hwaveform[0]=new TH2D("hwaveform0","hwaveform0",16,-0.5,15.5,16384,0,16384);
0555   hwaveform[1]=new TH2D("hwaveform1","hwaveform1",16,-0.5,15.5,16384,0,16384);
0556   hwaveform[2]=new TH2D("hwaveform2","hwaveform2",16,-0.5,15.5,16384,0,16384);
0557   hwaveform[3]=new TH2D("hwaveform3","hwaveform3",16,-0.5,15.5,16384,0,16384);
0558   hwaveform[4]=new TH2D("hwaveform4","hwaveform4",16,-0.5,15.5,16384,0,16384);
0559   hwaveform[5]=new TH2D("hwaveform5","hwaveform5",16,-0.5,15.5,16384,0,16384);
0560   for(int i=0; i<6; i++){
0561     se->registerHisto(this,hwaveform[i]);
0562   }
0563   
0564   //htimesync=new TH2I("htimesync","htimesync",65000,0,65000,65000,0,65000);
0565   //se->registerHisto(this,htimesync);
0566   hsyncfrac=new TH1D("hsyncfrac","hsyncfrac",2,0,2);
0567   se->registerHisto(this,hsyncfrac);
0568 
0569   Bluespace=new TH2D("Bluespace","Bluespace",50,-5,5,50,-5,5);
0570   se->registerHisto(this,Bluespace);
0571  
0572   Yellowspace=new TH2D("Yellowspace","Yellowspace",50,-5,5,50,-5,5);
0573   se->registerHisto(this,Yellowspace);
0574 
0575   hclocks = new TH2D("hclocks","hclocks",8192,0,8192,8192,0,8192);
0576   se->registerHisto(this, hclocks);
0577 
0578   hevolsync = new TH2D("hevolsync","",10000,0,30000000,2,0,2);
0579   se->registerHisto(this,hevolsync);
0580 
0581   hshiftevol=new TH2D("hshiftevol","",10000,0,30000000,20,0,20);
0582   se->registerHisto(this,hshiftevol);
0583   
0584   WaveformProcessingFast = new CaloWaveformFitting();
0585   myRandomBunch = new TRandom(0);
0586   Reset();
0587   return 0;
0588 }
0589 
0590 int LocalPolMon::BeginRun(const int runno)
0591 {
0592   // if you need to read calibrations on a run by run basis
0593   // this is the place to do it
0594 
0595   // Initialisation of the map (hopefully this step will not be required when gl1p scalers become available
0596   for (int i = 0; i < 16; i++)
0597   {  // 16 triggers for gl1p
0598     for (int bunchnr = 0; bunchnr < 120; bunchnr++)
0599     {
0600       gl1_counter[i][bunchnr] = 0;
0601     }
0602     if (verbosity)
0603     {
0604       std::cout << goodtrigger[15 - i];
0605     }
0606   }
0607   if (verbosity)
0608   {
0609     std::cout << "\n";
0610   }
0611   EvtShift=0;
0612   Initfirstbunch=false;
0613   Reset();
0614   RetrieveSpinPattern(runno);
0615   // goodtrigger[10]=true;//In 2023, it was MBD N&S
0616   return 0;
0617 }
0618 
0619 float LocalPolMon::anaWaveformFast(Packet* p, const int channel, const int low, const int high, const int ihisto)
0620 {
0621   std::vector<float> waveform;
0622   waveform.reserve(high-low);
0623   //waveform.reserve(p->iValue(0, "SAMPLES"));
0624   //for (int s = 0; s < p->iValue(0, "SAMPLES"); s++)
0625   for (int s = low; s < high; s++)
0626   {
0627     waveform.push_back(p->iValue(s, channel));
0628     hwaveform[ihisto]->Fill(s,p->iValue(s, channel));
0629   }
0630   std::vector<std::vector<float>> multiple_wfs;
0631   multiple_wfs.push_back(waveform);
0632 
0633   std::vector<std::vector<float>> fitresults_zdc;
0634   fitresults_zdc = WaveformProcessingFast->calo_processing_fast(multiple_wfs);
0635 
0636   std::vector<float> result;
0637   result = fitresults_zdc.at(0);
0638   return result.at(0);
0639 }
0640 
0641 int LocalPolMon::process_event(Event* e /* evt */)
0642 {
0643 
0644   //if (e->getEvtType() == BEGRUNEVENT /*9*/)
0645   //{  // spin patterns stored in BeginRun event
0646   //  RetrieveSpinPattern(e);
0647   //}
0648 
0649   RetrieveTriggerDistribution(e);
0650   h_events->Fill(0);
0651   /******Here we do the matching to identify the crossing shift   ******************/
0652   if (evtcnt > EventCountThresholdGap){
0653     StartAbortGapData = RetrieveAbortGapData();
0654   }
0655   else
0656   {
0657     StartAbortGapData = ExpectedsPhenixGapPosition;  // default value from config
0658   }
0659 
0660   CrossingShift = StartAbortGapPattern - StartAbortGapData;
0661   if (verbosity)
0662   {
0663     std::cout << "Crossing shift: " << CrossingShift << " = ( " << StartAbortGapPattern << " - " << StartAbortGapData << " )\n";
0664   }
0665   /************* end of crossing shift *********************/
0666 
0667   Packet* psmd = e->getPacket(packetid_smd);
0668   int bunchnr = 0;
0669   if (psmd)
0670   {
0671     h_events->Fill(1);
0672     long long int zdc_clock=psmd->lValue(0,"CLOCK");
0673     bunchnr=RetrieveBunchNumber(e,zdc_clock);
0674     //Did not manage to retrieve the proper bunch number, no need to continue the calculation
0675     //let us clean and leave
0676     if(bunchnr<0){
0677       delete psmd;
0678       psmd=nullptr;
0679       return 0;
0680     }
0681     h_events->Fill(2);
0682 
0683     if (fake)
0684     {
0685       bunchnr += 15 + myRandomBunch->Integer(4);
0686     }
0687 
0688     // get minimum on ZDC second module
0689     // get minimum on ZDC second module
0690     signalZDCN1 = anaWaveformFast(psmd, ZDCN1, lowSample[ZDCN1], highSample[ZDCN1],0);
0691     signalZDCS1 = anaWaveformFast(psmd, ZDCS1, lowSample[ZDCS1], highSample[ZDCS1],1);
0692     signalZDCN2 = anaWaveformFast(psmd, ZDCN2, lowSample[ZDCN2], highSample[ZDCN2],0);
0693     signalZDCS2 = anaWaveformFast(psmd, ZDCS2, lowSample[ZDCS2], highSample[ZDCS2],1);
0694     vetoNF = anaWaveformFast(psmd, 16, lowSample[ivetoNF], highSample[ivetoNF],4);
0695     vetoNB = anaWaveformFast(psmd, 17, lowSample[ivetoNB], highSample[ivetoNB],4);
0696     vetoSF = anaWaveformFast(psmd, 80, lowSample[ivetoSF], highSample[ivetoSF],5);
0697     vetoSB = anaWaveformFast(psmd, 81, lowSample[ivetoSB], highSample[ivetoSB],5);
0698 
0699     if ( (signalZDCN2 < 10 || signalZDCN1<75) && (signalZDCS2 < 10 || signalZDCS1<75) )
0700     {
0701       delete psmd;
0702       psmd=nullptr;
0703       return 0;
0704     }
0705     h_events->Fill(3);
0706 
0707     // for(int ch=16; ch<47; ch++){//according to mapping in ZDC logbook entry #85 March 9th 2024
0708     for (auto& it : Chmapping)
0709     {  // new mapping for ZDC/SMD/Veto with 2 ADC boards//May 13th 2024
0710       if (it.second < 16)
0711       {
0712         continue;
0713       }
0714       if (it.second > 47)
0715       {
0716         continue;
0717       }
0718       float signalFast = anaWaveformFast(psmd, it.first, lowSample[it.second],highSample[it.second],it.second/32+2);  // fast waveform fitting
0719 
0720       int ch = it.second;
0721       // Scale according to relative gain calibration factor
0722       //if (ch < 16){
0723       //    zdc_adc[ch]=signalFast;
0724       //}
0725       //else 
0726       if (ch < 32)
0727       {
0728         smd_adc[ch - 16] = signalFast * smd_north_relatgain[ch - 16];
0729       }
0730       else
0731       {
0732         smd_adc[ch - 16] = signalFast * smd_south_relatgain[ch - 32];
0733       }
0734     }
0735     float Weights[4] = {0};
0736     memset(Weights, 0, sizeof(Weights));
0737     float AveragePosition[4] = {0};
0738     memset(AveragePosition, 0, sizeof(AveragePosition));
0739 
0740     for (int ch = 0; ch < 8; ch++)
0741     {
0742       Weights[0] += smd_adc[ch];
0743       AveragePosition[0] += ConversionSign[0] * pitchY * (ch - (nchannelsY-1.) / 2) * smd_adc[ch];  // North Y direction (Asym in blue)
0744       Weights[2] += smd_adc[ch + 16];
0745       AveragePosition[2] += ConversionSign[2] * pitchY * (ch - (nchannelsY-1.) / 2) * smd_adc[ch + 16];  // South Y direction (Asym in Yellow)
0746 
0747       if (ch == 7)
0748       {
0749         continue;
0750       }
0751       Weights[1] += smd_adc[ch + 8];
0752       AveragePosition[1] += ConversionSign[1] * pitchX * (ch - (nchannelsX-1.) / 2) * smd_adc[ch + 8];  // North X direction (Asym in Blue)
0753       Weights[3] += smd_adc[ch + 24];
0754       AveragePosition[3] += ConversionSign[3] * pitchX * (ch - (nchannelsX-1.) / 2) * smd_adc[ch + 24];  // South X direction (Asym in Yellow)
0755     }
0756 
0757     for (int i = 0; i < 4; i++)
0758     {
0759       if (Weights[i] > 0.0)
0760       {
0761         AveragePosition[i] /= Weights[i];
0762     h_events->Fill(4+i);
0763       }
0764       else
0765       {
0766     AveragePosition[i]=0.;
0767         continue;  // most likely the most appropriate
0768       }
0769 
0770       if (AveragePosition[i] < ZeroPosition[i] - 0.5)
0771       {
0772     h_events->Fill(8+i);
0773     if (verbosity)
0774       {
0775         std::cout<<"Spin pattern size for "<<i/2<<" : "<<SpinPatterns[i/2].size()<<std::endl;
0776       }
0777         // (i/2)=0 for blue beam=North, (i/2)=1 for yellow beam=South
0778         if (SpinPatterns[i / 2].at((120 + bunchnr + CrossingShift) % 120) > 0)
0779         {
0780           if(GoodSelection(i/2)) {
0781         h_Counts[i]->Fill(3);  // Right for pointing up
0782         hposition[i]->Fill(AveragePosition[i]);
0783       }
0784         }
0785         else if (SpinPatterns[i / 2].at((120 + bunchnr + CrossingShift) % 120) < 0)
0786         {
0787           if(GoodSelection(i/2)) {
0788         h_Counts[i]->Fill(1);  // Left for pointing down
0789         hposition[i+4]->Fill(AveragePosition[i]);
0790       }
0791         }
0792 
0793         // we swap the spin pattern to get random orientation and check biased asymmetry
0794         if (SpinPatterns[i / 2 == 0 ? 1 : 0].at((120 + bunchnr + CrossingShift) % 120) > 0)
0795         {
0796           if(GoodSelection(i/2))h_CountsScramble[i]->Fill(3);  // Right for pointing up
0797         }
0798         else if (SpinPatterns[i / 2 == 0 ? 1 : 0].at((120 + bunchnr + CrossingShift) % 120) < 0)
0799         {
0800           if(GoodSelection(i/2))h_CountsScramble[i]->Fill(1);  // Left for pointing down
0801         }
0802       }
0803       else if (AveragePosition[i] > ZeroPosition[i] + 0.5)
0804       {
0805     h_events->Fill(8+i);
0806         // (i/2)=0 for blue beam, =1 for yellow beam
0807         if (SpinPatterns[i / 2].at((120 + bunchnr + CrossingShift) % 120) > 0)
0808         {
0809           if(GoodSelection(i/2)){
0810         h_Counts[i]->Fill(0);  // Left for pointing up
0811         hposition[i]->Fill(AveragePosition[i]);
0812       }
0813         }
0814         else if (SpinPatterns[i / 2].at((120 + bunchnr + CrossingShift) % 120) < 0)
0815         {
0816           if(GoodSelection(i/2)){
0817         h_Counts[i]->Fill(2);  // Right for pointing down
0818         hposition[i+4]->Fill(AveragePosition[i]);
0819       }
0820         }
0821 
0822         // we swap the spin pattern to get random orientation and check biased asymmetry
0823         if (SpinPatterns[i / 2 == 0 ? 1 : 0].at((120 + bunchnr + CrossingShift) % 120) > 0)
0824         {
0825           if(GoodSelection(i/2))h_CountsScramble[i]->Fill(0);  // Left for pointing up
0826         }
0827         else if (SpinPatterns[i / 2 == 0 ? 1 : 0].at((120 + bunchnr + CrossingShift) % 120) < 0)
0828         {
0829           if(GoodSelection(i/2))h_CountsScramble[i]->Fill(2);  // Right for pointing down
0830         }
0831       }
0832     }
0833     double rnorth2=pow(AveragePosition[0]-ZeroPosition[0],2)+pow(AveragePosition[1]-ZeroPosition[1],2);
0834     double rsouth2=pow(AveragePosition[2]-ZeroPosition[2],2)+pow(AveragePosition[3]-ZeroPosition[3],2);
0835     if(rnorth2>1 && GoodSelection(0)){
0836       Bluespace->Fill(AveragePosition[1],AveragePosition[0]);
0837     }
0838     if(rsouth2>1 && GoodSelection(1)){
0839       Yellowspace->Fill(AveragePosition[3],AveragePosition[2]);
0840     }
0841     h_time->Fill(iPoint, e->getTime());
0842     evtcnt++;
0843     evtcntA++;
0844     delete psmd;
0845     psmd=nullptr;
0846   }
0847   else
0848   {
0849     if (verbosity)
0850     {
0851       std::cout << "Missing ZDC/SMD packet " << packetid_smd << std::endl;
0852     }
0853   }
0854 
0855   /**** Compute asymmetries if we have enough events ****************/
0856   //if (evtcnt % EventsAsymmetryNewPoint == 0)
0857   if (evtcntA > EventsAsymmetryNewPoint )
0858   {
0859     h_events->Fill(12);
0860     for (int ibeam = 0; ibeam < 2; ibeam++)
0861     {
0862       for (int orient = 0; orient < 2; orient++)
0863       {
0864         double L_U = h_Counts[2 * ibeam + orient]->GetBinContent(1);
0865         double R_D = h_Counts[2 * ibeam + orient]->GetBinContent(2);
0866         double L_D = h_Counts[2 * ibeam + orient]->GetBinContent(3);
0867         double R_U = h_Counts[2 * ibeam + orient]->GetBinContent(4);
0868         // if(L_U<0){
0869         //   std::cout<<iPoint<<" "<<evtcnt<<" "<<h_Counts[2*ibeam+orient]->GetEntries()<<" "<<std::endl;
0870         // }
0871         double* asymresult = ComputeAsymmetries(L_U, R_D, L_D, R_U);
0872 
0873         h_Asym[ibeam][0][orient]->SetBinContent(iPoint + 1, asymresult[0]);
0874         h_Asym[ibeam][0][orient]->SetBinError(iPoint + 1, asymresult[1]);
0875 
0876         h_Asym[ibeam][1][orient]->SetBinContent(iPoint + 1, asymresult[2]);
0877         h_Asym[ibeam][1][orient]->SetBinError(iPoint + 1, asymresult[3]);
0878 
0879         L_U = h_CountsScramble[2 * ibeam + orient]->GetBinContent(1);
0880         R_D = h_CountsScramble[2 * ibeam + orient]->GetBinContent(2);
0881         L_D = h_CountsScramble[2 * ibeam + orient]->GetBinContent(3);
0882         R_U = h_CountsScramble[2 * ibeam + orient]->GetBinContent(4);
0883 
0884         double* scrambleresult = ComputeAsymmetries(L_U, R_D, L_D, R_U);
0885 
0886         h_AsymScramble[ibeam][0][orient]->SetBinContent(iPoint + 1, scrambleresult[0]);
0887         h_AsymScramble[ibeam][0][orient]->SetBinError(iPoint + 1, scrambleresult[1]);
0888 
0889         h_AsymScramble[ibeam][1][orient]->SetBinContent(iPoint + 1, scrambleresult[2]);
0890         h_AsymScramble[ibeam][1][orient]->SetBinError(iPoint + 1, scrambleresult[3]);
0891 
0892         delete asymresult;
0893         delete scrambleresult;
0894       }
0895     }
0896     // Now that everything has been calculated, let move to the next point for next event
0897     iPoint++;
0898     evtcntA=0;
0899     if(!Integrated){
0900       for(int i =0; i<4; i++){
0901     h_Counts[i]->Reset();
0902     h_CountsScramble[i]->Reset();
0903       }
0904     }
0905   }
0906 
0907   return 0;
0908 }
0909 
0910 int LocalPolMon::Reset()
0911 {
0912   // reset our internal counters
0913   evtcnt = 0;
0914   evtcntA=0;
0915   iPoint = 0;
0916   failuredepth=0;
0917   for (int i = 0; i < 4; i++)
0918   {
0919     h_Counts[i]->Reset();
0920     h_CountsScramble[i]->Reset();
0921   }
0922   h_time->Reset();
0923   return 0;
0924 }
0925 
0926 bool LocalPolMon::GoodSelection(int i)
0927 {
0928   bool goodselection=true;
0929   if(i==0){//dealing with north side
0930     int nv=0; 
0931     int nh=0;
0932     double sumH=0;
0933     double sumV=0;
0934     for(int ch=0; ch<8; ch++) {
0935       nh +=(smd_adc[ch]  >SMDthr)?1:0;
0936       sumH+=smd_adc[ch];
0937     }
0938     for(int ch=0; ch<7; ch++) {
0939       nv +=(smd_adc[ch+8]>SMDthr)?1:0;
0940       sumV+=smd_adc[ch+8];
0941     }
0942     goodselection &=(signalZDCN1>ZDC1Cut && signalZDCN2>ZDC2Cut);
0943     goodselection &=(vetoNF<VetoCut&&vetoNB<VetoCut);
0944     if(goodselection&&(nv>MultiLow&&nv<MultiHigh+1)) hmultiplicity[0]->Fill(nh);
0945     if(goodselection&&(nh>MultiLow&&nh<MultiHigh+1)) hmultiplicity[1]->Fill(nv);
0946     goodselection &=(nv>MultiLow&&nh>MultiLow);
0947     goodselection &=(nv<MultiHigh&&nh<MultiHigh+1);
0948     if((sumH>0)&&goodselection) hadcsum[0]->Fill(log10(sumH));
0949     if((sumV>0)&&goodselection) hadcsum[1]->Fill(log10(sumV));
0950   }
0951   else{//south side
0952     int nv=0; 
0953     int nh=0;
0954     double sumH=0;
0955     double sumV=0;
0956     for(int ch=0; ch<8; ch++) {
0957       nh +=(smd_adc[ch+16] >SMDthr)?1:0;
0958       sumH+=smd_adc[ch+16];
0959     }
0960     for(int ch=0; ch<7; ch++) {
0961       nv +=(smd_adc[ch+24] >SMDthr)?1:0;
0962       sumV+=smd_adc[ch+24];
0963     }
0964     goodselection &=(signalZDCS1>ZDC1Cut && signalZDCS2>ZDC2Cut);
0965     goodselection &=(vetoSF<VetoCut&&vetoSB<VetoCut);
0966     if(goodselection&&(nv>MultiLow&&nv<MultiHigh+1)) hmultiplicity[2]->Fill(nh);
0967     if(goodselection&&(nh>MultiLow&&nh<MultiHigh+1)) hmultiplicity[3]->Fill(nv);
0968     goodselection &=(nv>MultiLow&&nh>MultiLow);
0969     goodselection &=(nv<MultiHigh+1&&nh<MultiHigh+1);
0970     if((sumH>0)&&goodselection) hadcsum[2]->Fill(log10(sumH));
0971     if((sumV>0)&&goodselection) hadcsum[3]->Fill(log10(sumV));
0972   }
0973 
0974   return goodselection;
0975 }
0976 
0977 double* LocalPolMon::ComputeAsymmetries(double L_U, double R_D, double L_D, double R_U)
0978 {
0979   double* result = new double[4];
0980   double leftA = L_U + R_D;
0981   double rightA = L_D + R_U;
0982   double tmpNumA = leftA - rightA;
0983   double tmpDenA = leftA + rightA;
0984   result[0] = 0;
0985   result[1] = 0;
0986 
0987   if (tmpDenA > 0)
0988   {
0989     result[0] = tmpNumA / tmpDenA;
0990     result[1] = 2 * sqrt(pow(rightA, 2) * leftA + pow(leftA, 2) * rightA) / pow(tmpDenA, 2);
0991   }
0992   //std::cout<<leftA<<" "<<rightA<<"\t\t"<<result[0]<<" +/- "<<result[1]<<std::endl;
0993 
0994   double leftG = sqrt(L_U * R_D);
0995   double rightG = sqrt(L_D * R_U);
0996   double tmpNumG = leftG - rightG;
0997   double tmpDenG = leftG + rightG;
0998   result[2] = 0;
0999   result[3] = 0;
1000 
1001   if (tmpDenG > 0)
1002   {
1003     result[2] = tmpNumG / tmpDenG;
1004     result[3] = sqrt(pow(rightG, 2) * leftA + pow(leftG, 2) * rightA) / pow(tmpDenG, 2);
1005   }
1006   return result;
1007 }
1008 
1009 void LocalPolMon::RetrieveSpinPattern(int runnb){
1010   SpinPatterns[BLUE].clear();
1011   SpinPatterns[YELLOW].clear();
1012   for(int i = 0; i < 120; i++){
1013     SpinPatterns[BLUE][i]=0;
1014     SpinPatterns[YELLOW][i]=0;
1015   }
1016   TString retvalBlue;
1017   TString retvalYellow;
1018   const char* user=getenv("USER");
1019   if(strcmp(user,"phnxrc")==0){
1020     //We are on machine which can access operator1 computer without password
1021     retvalBlue=gSystem->GetFromPipe(Form("$ONLMON_MACROS/GetSpinPatternHTTP.sh %d",14902));
1022     retvalYellow=gSystem->GetFromPipe(Form("$ONLMON_MACROS/GetSpinPatternHTTP.sh %d",14903));
1023     if(verbosity){
1024       std::cout<<"Retrieving SpinPattern from HTTP"<<std::endl;
1025     }
1026   }
1027   else{
1028     OnlMonServer* se = OnlMonServer::instance();
1029     TString runtype=se->GetRunType();
1030     runtype.ToLower();
1031     retvalBlue=gSystem->GetFromPipe(Form("$ONLMON_MACROS/GetSpinPatternGL1.sh %d %s %d",14902,runtype.Data(),runnb));
1032     retvalYellow=gSystem->GetFromPipe(Form("$ONLMON_MACROS/GetSpinPatternGL1.sh %d %s %d",14903,runtype.Data(),runnb));
1033     if(verbosity){
1034       std::cout<<"Retrieving SpinPattern from GL1 "<<runtype.Data() <<" prdf file for run "<<runnb<<std::endl;
1035     }
1036   }
1037   int flip=-1;//https://phenix-intra.sdcc.bnl.gov/phenix/WWW/offline/wikioff/index.php/Spin_Database_:_Note_for_Analyzer
1038   TObjArray* BunchSpinBlue=retvalBlue.Tokenize(" ");
1039   BunchSpinBlue->SetOwner(kTRUE);
1040   int nFilledBunchesBlue=BunchSpinBlue->GetEntries();
1041   if(verbosity){
1042     std::cout<<"Blue spin patterns for "<<nFilledBunchesBlue<<" bunches "<<std::endl;
1043     std::cout<<retvalBlue<<std::endl;
1044   }
1045   int stepBlue=(112-nFilledBunchesBlue)/28+1;
1046   //for(int i=0; i<120; i=i+stepBlue){
1047   for(int i=0; i<nFilledBunchesBlue; i++){
1048     SpinPatterns[BLUE][stepBlue*i]=flip*((TObjString*)BunchSpinBlue->At(i))->String().Atoi();
1049     hspinpattern->Fill(stepBlue*i,1,((TObjString*)BunchSpinBlue->At(i))->String().Atoi());
1050   }
1051   BunchSpinBlue->Clear();
1052   delete BunchSpinBlue;
1053 
1054   TObjArray* BunchSpinYellow=retvalYellow.Tokenize(" ");
1055   BunchSpinYellow->SetOwner(kTRUE);
1056   int nFilledBunchesYell=BunchSpinYellow->GetEntries();
1057   if(verbosity){
1058     std::cout<<"Yellow spin patterns for "<<nFilledBunchesYell<<" bunches "<<std::endl;
1059     std::cout<<retvalYellow<<std::endl;
1060   }
1061   int stepYellow=(112-nFilledBunchesYell)/28+1;
1062   //for(int i=0; i<120; i=i+stepYellow){
1063   for(int i=0; i<nFilledBunchesYell; i++){
1064     SpinPatterns[YELLOW][stepYellow*i]=flip*((TObjString*)BunchSpinYellow->At(i))->String().Atoi();
1065     hspinpattern->Fill(stepYellow*i,0.,((TObjString*)BunchSpinYellow->At(i))->String().Atoi());
1066   }
1067   //Check if consitent information (as the method works only with multiples of 28 filled bunches and a constant abort gap of 9 bunches
1068   if(stepYellow==stepBlue){
1069     nEmptyAbort=stepYellow-1;
1070   }
1071   BunchSpinYellow->Clear();
1072   delete BunchSpinYellow;
1073 }
1074 
1075 void LocalPolMon::RetrieveTriggerDistribution(Event* e){
1076   Event* egl1p=nullptr;
1077   Packet* pgl1p = nullptr;
1078   if (erc){
1079     if(verbosity){
1080       std::cout<<"Inside RetrieveTrigger::ERC"<<e->getEvtSequence()<<" "<<EvtShift<<std::endl;
1081     }
1082     egl1p = erc->getEvent(e->getEvtSequence()+EvtShift);
1083     if(verbosity){
1084       std::cout<<egl1p<<std::endl;
1085     }
1086   }
1087   if (egl1p){
1088     pgl1p = egl1p->getPacket(packetid_gl1);
1089     if (pgl1p){
1090       int bunchnr = pgl1p->lValue(0, "BunchNumber");
1091       for (int i=0; i<16; i++){//auto& i : gl1_counter)
1092     // 16 triggers for gl1p
1093     // With prdf pgl1->lValue(i,2); simply returns the current processed event number (which can shaddow the abort gap: the lagging bunch# at some point get back to the position of the others)
1094     // So instead, we increment the number of processed events per bunch number, for the various triggers
1095     //gl1_counter[i][bunchnr]+= (pgl1p->lValue(i,2)>0)?1:0;
1096     if(pgl1p->lValue(i,2)>0){
1097       gl1_counter[i][bunchnr]++;
1098       h_trigger[i]->Fill(bunchnr);
1099     }
1100       }
1101       delete pgl1p;
1102       pgl1p=nullptr;
1103     }
1104     delete egl1p;
1105     egl1p=nullptr;
1106   }
1107 }
1108 
1109 int LocalPolMon::RetrieveAbortGapData(){
1110   // Here we do the magic to identify the abort gap
1111   std::vector<int> gap[16];
1112   std::map<int, int> begingap;
1113   std::map<int, int> endgap;
1114 
1115   for (int i = 0; i < 16; i++){
1116     if (!goodtrigger[i]){
1117       continue;
1118     }
1119     if(h_trigger[i]->GetEntries()<1000) continue;
1120     std::map<int, long long> tmpmap = gl1_counter[i];
1121     for (int emptyfill = 0; emptyfill < 9; emptyfill++){
1122       int myminimum = min_element(tmpmap.begin(), tmpmap.end(), [](const std::pair<int, long long>& lhs, const std::pair<int, long long>& rhs)
1123                   { return lhs.second < rhs.second; })
1124     ->first;
1125       if (myminimum < 111){
1126     gap[i].push_back(120 + myminimum);
1127       }
1128       else{
1129     gap[i].push_back(myminimum);
1130       }
1131       tmpmap.erase(myminimum);
1132     }
1133     begingap[i] = (*min_element(gap[i].begin(), gap[i].end()))+nEmptyAbort;
1134     endgap[i] = (*max_element(gap[i].begin(), gap[i].end()));
1135     if (endgap[i] - begingap[i] > 9){
1136       std::cout << " Weird abort gap is larger than 9 bunches " << endgap[i] << " - " << begingap[i] << " for trigger " << i << std::endl;
1137     }
1138   }
1139   for (auto ib = begingap.begin(); ib != begingap.end(); ++ib){
1140     if (begingap.begin()->second != ib->second)
1141       {
1142     std::cout << " Weird abort gap not in the same location between trigger bit 0 and trigger bit " << ib->second << std::endl;
1143       }
1144   }
1145   if (begingap.empty()) return 111;
1146   else return (begingap.begin()->second) % 120;
1147 }
1148 
1149 
1150 int LocalPolMon::RetrieveBunchNumber(Event* e, long long int zdc_clock){
1151   Event* egl1 = nullptr;
1152   int bunch=-1;
1153   //static int localfail=0;
1154   if(!Initfirstbunch){
1155     EvtShift=0;
1156     EvtShiftValid=0;
1157     Prevzdc_clock=zdc_clock;
1158   }
1159   if(verbosity){
1160     std::cout<<"Inside RetrieveBunchNumber"<<std::endl;
1161   }
1162   if(failuredepth>1000){
1163     if(verbosity){
1164       std::cout<<"ZDC and GL1p asynchronous by more than 1000 events"<<std::endl;
1165       std::cout<<"Giving up this event and go to the next one"<<std::endl;
1166     }
1167     EvtShift=EvtShiftValid;
1168     failuredepth=0;
1169     return -1;
1170   }
1171   //std::cout<<e->getEvtSequence()<<std::endl;
1172   if (erc){
1173     if(verbosity){
1174       std::cout<<"Inside RetrieveBunchNumber::ERC "<<e->getEvtSequence() <<" "<<EvtShift <<std::endl;
1175     }
1176     egl1 = erc->getEvent(e->getEvtSequence()+EvtShift);
1177     if(verbosity){
1178       std::cout<<egl1<<std::endl;
1179     }
1180   }
1181   if (egl1){
1182     if(verbosity){
1183       std::cout<<"Inside RetrieveBunchNumber::GL1"<<std::endl;
1184     }
1185     Packet* pgl1p = egl1->getPacket(packetid_gl1);
1186     if (pgl1p){
1187       if(verbosity){
1188     std::cout<<"Inside RetrieveBunchNumber::PGL1p"<<std::endl;
1189       }
1190       long long int gl1_clock=pgl1p->lValue(0, "BCO");
1191       if(verbosity){
1192        std::cout<<"EvtShift: "<<EvtShift<<" zdc: "<<zdc_clock<<"    gl1p: "<<gl1_clock<<std::endl;
1193       }
1194 
1195       if(!Initfirstbunch){
1196     Prevgl1_clock=gl1_clock;
1197     Initfirstbunch=true;
1198     bunch = pgl1p->lValue(0, "BunchNumber");
1199     if(verbosity){
1200       std::cout<<"Init Bunch number is : "<<bunch<<std::endl;
1201     }
1202     delete pgl1p;
1203     pgl1p=nullptr;
1204     delete egl1;
1205     egl1=nullptr;
1206     return bunch;
1207       }
1208       if(zdc_clock<Prevzdc_clock){
1209     //Prevzdc_clock=Prevzdc_clock-4294967296;//despite the long long, it seems it is only 32 bits
1210     //std::cerr<<"Mismatched: "<< e->getEvtSequence()<<" shift: "<<EvtShift<<" zdc: "<<zdc_clock<<" - "<<Prevzdc_clock<<" = "<<(zdc_clock-Prevzdc_clock) <<"    gl1p: "<<gl1_clock<<" - "<<Prevgl1_clock<<" = "<<(gl1_clock-Prevgl1_clock) <<std::endl;
1211     zdc_clock+=(long long int)1<<32;
1212     //std::cerr<<"And now Mismatched: "<< e->getEvtSequence()<<" shift: "<<EvtShift<<" zdc: "<<zdc_clock<<" - "<<Prevzdc_clock<<" = "<<(zdc_clock-Prevzdc_clock) <<"    gl1p: "<<gl1_clock<<" - "<<Prevgl1_clock<<" = "<<(gl1_clock-Prevgl1_clock) <<std::endl;
1213     //exit(1);
1214       }
1215       hclocks->Fill((gl1_clock-Prevgl1_clock)%8192,(zdc_clock-Prevzdc_clock)%8192);
1216       if((gl1_clock-Prevgl1_clock)!=(zdc_clock-Prevzdc_clock)){
1217     if(verbosity){
1218       std::cout<<"Mismatched: "<<EvtShift<<" zdc: "<<(zdc_clock-Prevzdc_clock) <<"    gl1p: "<<(gl1_clock-Prevgl1_clock) <<std::endl;
1219         }
1220     //std::cerr<<"Mismatched: "<< e->getEvtSequence()<<" shift: "<<EvtShift<<" zdc: "<<zdc_clock<<" - "<<Prevzdc_clock<<" = "<<(zdc_clock-Prevzdc_clock) <<"    gl1p: "<<gl1_clock<<" - "<<Prevgl1_clock<<" = "<<(gl1_clock-Prevgl1_clock) <<std::endl;
1221     //if((zdc_clock-Prevzdc_clock)<0){
1222     //  exit(1) ;
1223     //}
1224     EvtShift++;
1225     delete pgl1p;
1226     pgl1p=nullptr;
1227     delete egl1;
1228     egl1=nullptr;
1229     failuredepth++;
1230     hsyncfrac->Fill(0.);
1231     hevolsync->Fill(e->getEvtSequence(),0);
1232     bunch=RetrieveBunchNumber(e,zdc_clock);
1233       }
1234       else{
1235     Prevgl1_clock=gl1_clock;
1236     if(zdc_clock>(long long int)1<<32){
1237       zdc_clock-=(long long int)1<<32;
1238     }
1239     Prevzdc_clock=zdc_clock;
1240     EvtShiftValid=EvtShiftValid;
1241     hsyncfrac->Fill(1.);
1242     hevolsync->Fill(e->getEvtSequence(),1);
1243     hshiftevol->Fill(e->getEvtSequence(),EvtShift);
1244     bunch = pgl1p->lValue(0, "BunchNumber");
1245     //failuredepth=0;
1246     if(verbosity){
1247       std::cout<<"Bunch number is : "<<bunch<<std::endl;
1248     }
1249       }
1250       delete pgl1p;
1251       pgl1p = nullptr;
1252     }
1253     else{
1254       if (verbosity){
1255     std::cout << "Failed grabing gl1 from event receiver, Bunch number unknown" << std::endl;
1256       }
1257     }
1258     delete egl1;
1259     egl1 = nullptr;
1260   }
1261   return bunch;
1262 }