Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-03 08:16:17

0001 #include "XingShiftCal.h"
0002 
0003 #include <cdbobjects/CDBTTree.h>
0004 
0005 #include <fun4all/Fun4AllReturnCodes.h>
0006 
0007 #include <phool/getClass.h>
0008 #include <phool/phool.h>
0009 #include <phool/recoConsts.h>
0010 
0011 #include <Event/Event.h>
0012 #include <Event/EventTypes.h>
0013 #include <Event/packet.h>
0014 
0015 #include <TCanvas.h>
0016 #include <TH1.h>
0017 
0018 #include <boost/format.hpp>
0019 #include <odbc++/connection.h>
0020 #include <odbc++/drivermanager.h>
0021 #include <odbc++/resultset.h>
0022 #include <odbc++/statement.h>
0023 #include <odbc++/types.h>
0024 
0025 #include <iostream>
0026 
0027 XingShiftCal::XingShiftCal(const std::string &name, const int poverwriteSpinEntry)
0028   : SubsysReco(name)
0029   , overwriteSpinEntry(poverwriteSpinEntry)
0030 {
0031   // overwriteSpinEntry = poverwriteSpinEntry;
0032   nevt = 0;
0033   
0034   for (auto &scalercount : scalercounts)
0035   {
0036     for (unsigned long &j : scalercount)
0037     {
0038       j = 0;
0039     }
0040   }
0041 
0042 
0043   std::cout << "XingShiftCal::XingShiftCal(const std::string &name) Calling ctor" << std::endl;
0044 }
0045 
0046 XingShiftCal::~XingShiftCal()
0047 {
0048   std::cout << "XingShiftCal::~XingShiftCal() Calling dtor" << std::endl;
0049 }
0050 
0051 int XingShiftCal::Init(PHCompositeNode * /*topNode*/)
0052 {
0053   std::cout << "XingShiftCal::Init(PHCompositeNode *topNode) Initializing" << std::endl;
0054   preset_pattern_blue["111x111_P1"] = "+-+--+-+-+-++-+--+-++-+-+-+--+-+-+-++-+--+-++-+-+-+--+-+-+-++-+--+-++-+-+-+--+-+-+-++-+--+-++-+-+-+--+-+-+-++-+*********";
0055   preset_pattern_yellow["111x111_P1"] = "++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++-*********";
0056   preset_pattern_blue["111x111_P2"] = "-+-++-+-+-+--+-++-+--+-+-+-++-+-+-+--+-++-+--+-+-+-++-+-+-+--+-++-+--+-+-+-++-+-+-+--+-++-+--+-+-+-++-+-+-+--+-*********";
0057   preset_pattern_yellow["111x111_P2"] = "++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++-*********";
0058   preset_pattern_blue["111x111_P3"] = "+-+--+-+-+-++-+--+-++-+-+-+--+-+-+-++-+--+-++-+-+-+--+-+-+-++-+--+-++-+-+-+--+-+-+-++-+--+-++-+-+-+--+-+-+-++-+*********";
0059   preset_pattern_yellow["111x111_P3"] = "--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--+*********";
0060   preset_pattern_blue["111x111_P4"] = "-+-++-+-+-+--+-++-+--+-+-+-++-+-+-+--+-++-+--+-+-+-++-+-+-+--+-++-+--+-+-+-++-+-+-+--+-++-+--+-+-+-++-+-+-+--+-*********";
0061   preset_pattern_yellow["111x111_P4"] = "--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--+*********";
0062   preset_pattern_blue["111x111_P5"] = "++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++-*********";
0063   preset_pattern_yellow["111x111_P5"] = "+-+--+-+-+-++-+--+-++-+-+-+--+-+-+-++-+--+-++-+-+-+--+-+-+-++-+--+-++-+-+-+--+-+-+-++-+--+-++-+-+-+--+-+-+-++-+*********";
0064   preset_pattern_blue["111x111_P6"] = "--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--+*********";
0065   preset_pattern_yellow["111x111_P6"] = "+-+--+-+-+-++-+--+-++-+-+-+--+-+-+-++-+--+-++-+-+-+--+-+-+-++-+--+-++-+-+-+--+-+-+-++-+--+-++-+-+-+--+-+-+-++-+*********";
0066   preset_pattern_blue["111x111_P7"] = "++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++-*********";
0067   preset_pattern_yellow["111x111_P7"] = "-+-++-+-+-+--+-++-+--+-+-+-++-+-+-+--+-++-+--+-+-+-++-+-+-+--+-++-+--+-+-+-++-+-+-+--+-++-+--+-+-+-++-+-+-+--+-*********";
0068   preset_pattern_blue["111x111_P8"] = "--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--++--+*********";
0069   preset_pattern_yellow["111x111_P8"] = "-+-++-+-+-+--+-++-+--+-+-+-++-+-+-+--+-++-+--+-+-+-++-+-+-+--+-++-+--+-+-+-++-+-+-+--+-++-+--+-+-+-++-+-+-+--+-*********";
0070 
0071   return Fun4AllReturnCodes::EVENT_OK;
0072 }
0073 
0074 int XingShiftCal::InitRun(PHCompositeNode * /*topNode*/)
0075 {
0076   // std::cout << "XingShiftCal::InitRun(PHCompositeNode *topNode) Initializing for Run XXX" << std::endl;
0077 
0078   recoConsts *rc = recoConsts::instance();
0079   runnumber = rc->get_IntFlag("RUNNUMBER");
0080   return Fun4AllReturnCodes::EVENT_OK;
0081 }
0082 
0083 int XingShiftCal::process_event(PHCompositeNode *topNode)
0084 {
0085   if (done == 1)
0086   {
0087     return Fun4AllReturnCodes::EVENT_OK;
0088   }
0089   // std::cout << "XingShiftCal::process_event(PHCompositeNode *topNode) Processing Event" << std::endl;
0090   Event *evt = findNode::getClass<Event>(topNode, "PRDF");
0091 
0092   if (evt->getEvtType() == BEGRUNEVENT)
0093   {
0094     //================ BeginRunEvent packets ================//
0095     pBluePol = evt->getPacket(packet_BLUEPOL);
0096     pYellPol = evt->getPacket(packet_YELLPOL);
0097 
0098     pBlueIntPattern = evt->getPacket(packet_BLUEINTPATTERN);
0099     pYellIntPattern = evt->getPacket(packet_YELLINTPATTERN);
0100     pBluePolPattern = evt->getPacket(packet_BLUEPOLPATTERN);
0101     pYellPolPattern = evt->getPacket(packet_YELLPOLPATTERN);
0102 
0103     pBlueAsym = evt->getPacket(packet_BLUEASYM);
0104     pYellAsym = evt->getPacket(packet_YELLASYM);
0105 
0106     pBlueFillNumber = evt->getPacket(packet_BLUEFILLNUMBER);
0107     pYellFillNumber = evt->getPacket(packet_YELLFILLNUMBER);
0108     //=======================================================//
0109 
0110     //========= Get beam polarizations ==============//
0111     polBlue = -999;
0112     polBlueErr = -999;
0113     if (pBluePol)
0114     {
0115       polBlue = pBluePol->iValue(0) / 10000.0;
0116       polBlueErr = pBluePol->iValue(1) / 10000.0;
0117       delete pBluePol;
0118     }
0119 
0120     polYellow = -999;
0121     polYellowErr = -999;
0122     if (pYellPol)
0123     {
0124       polYellow = pYellPol->iValue(0) / 10000.0;
0125       polYellowErr = pYellPol->iValue(1) / 10000.0;
0126       delete pYellPol;
0127     }
0128     //==========================================================//
0129 
0130     //============== Get intended spin patterns from buckets ==============//
0131     // there are 360 buckets for 120 bunches
0132 
0133     if (pBlueIntPattern && pBluePolPattern)
0134     {
0135       for (int i = 0; i < 360; i += 3)
0136       {
0137     blueFillPattern[i / 3] = pBlueIntPattern->iValue(i);
0138         if (pBlueIntPattern->iValue(i))
0139         {
0140           blueSpinPattern[i / 3] = pBluePolPattern->iValue(i);
0141         }
0142         else
0143         {
0144           blueSpinPattern[i / 3] = 10;
0145         }
0146       }
0147       delete pBlueIntPattern;
0148       delete pBluePolPattern;
0149     }
0150 
0151     if (pYellIntPattern && pYellPolPattern)
0152     {
0153       for (int i = 0; i < 360; i += 3)
0154       {
0155     yellFillPattern[i / 3] = pYellIntPattern->iValue(i);
0156         if (pYellIntPattern->iValue(i))
0157         {
0158           yellSpinPattern[i / 3] = pYellPolPattern->iValue(i);
0159         }
0160         else
0161         {
0162           yellSpinPattern[i / 3] = 10;
0163         }
0164       }
0165       delete pYellIntPattern;
0166       delete pYellPolPattern;
0167     }
0168     //=======================================================================//
0169 
0170 
0171      //============== Get pC spin patterns from buckets ==============//
0172 
0173     // Get bunch asymmetries for measured spin pattern
0174     // there are 360 buckets for 120 bunches
0175     if (pBlueAsym)
0176     {
0177       for (int i = 0; i < 360; i += 3)
0178       {
0179         float blueAsyms = pBlueAsym->iValue(i) / 10000.0;
0180         float blueAsymsErr = pBlueAsym->iValue(i + 360) / 10000.0;
0181 
0182         float bluebot = blueAsyms - blueAsymsErr;
0183         float bluetop = blueAsyms + blueAsymsErr;
0184 
0185         if (blueAsyms != 0 || bluebot != 0 || bluetop != 0)
0186         {
0187           if (bluebot > 0 && bluetop > 0)
0188           {
0189         bluePcSpinPattern[i / 3] = 1;
0190           }
0191           else if (bluebot < 0 && bluetop < 0)
0192           {
0193             bluePcSpinPattern[i / 3] = -1;
0194           }
0195           else if (bluebot <= 0 && bluetop >= 0)
0196           {
0197             bluePcSpinPattern[i / 3] = 0;
0198           }
0199         }
0200         else
0201         {
0202           bluePcSpinPattern[i / 3] = 10;
0203         }
0204       }
0205       delete pBlueAsym;
0206     }
0207 
0208     if (pYellAsym)
0209     {
0210       for (int i = 0; i < 360; i += 3)
0211       {
0212         float yellAsyms = pYellAsym->iValue(i) / 10000.0;
0213         float yellAsymsErr = pYellAsym->iValue(i + 360) / 10000.0;
0214 
0215         float yellbot = yellAsyms - yellAsymsErr;
0216         float yelltop = yellAsyms + yellAsymsErr;
0217 
0218         if (yellAsyms != 0 || yellbot != 0 || yelltop != 0)
0219         {
0220           if (yellbot > 0 && yelltop > 0)
0221           {
0222             yellPcSpinPattern[i / 3] = 1;
0223           }
0224           else if (yellbot < 0 && yelltop < 0)
0225           {
0226             yellPcSpinPattern[i / 3] = -1;
0227           }
0228           else if (yellbot <= 0 && yelltop >= 0)
0229           {
0230             yellPcSpinPattern[i / 3] = 0;
0231           }
0232         }
0233         else
0234         {
0235           yellPcSpinPattern[i / 3] = 10;
0236         }
0237       }
0238       delete pYellAsym;
0239     }
0240     //=======================================================================//
0241 
0242 
0243     //============== Get fill number ==============//
0244     fillnumberBlue = 0;
0245     fillnumberYellow = 0;
0246     if (pBlueFillNumber)
0247     {
0248       fillnumberBlue = pBlueFillNumber->iValue(0);
0249       delete pBlueFillNumber;
0250     }
0251     if (pYellFillNumber)
0252     {
0253       fillnumberYellow = pYellFillNumber->iValue(0);
0254       delete pYellFillNumber;
0255     }
0256     //=======================================================//
0257   }
0258   else if (evt->getEvtType() == DATAEVENT)
0259   {
0260     p = evt->getPacket(packet_GL1);
0261     int bunchnr = p->lValue(0, "BunchNumber");
0262     
0263     for (int i = 0; i < NTRIG; i++)
0264     {
0265       // 2nd arg of lValue: 0 is raw trigger count, 1 is live trigger count, 2 is scaled trigger count
0266       long gl1pscaler = p->lValue(i, "GL1PLIVE");
0267       scalercounts[i][bunchnr] = gl1pscaler;
0268     }
0269     delete p;
0270   }
0271 
0272   if (nevt > threshold)
0273   {
0274     Calibrate();
0275     if (success)
0276     {
0277       done = 1;
0278     }
0279     else
0280     {
0281       threshold += threshold;
0282     }
0283   }
0284 
0285   if (nevt > evtcap)
0286   {
0287     done = 1;
0288   }
0289 
0290   nevt++;
0291 
0292   return Fun4AllReturnCodes::EVENT_OK;
0293 }
0294 
0295 int XingShiftCal::ResetEvent(PHCompositeNode * /*topNode*/)
0296 {
0297   // std::cout << "XingShiftCal::ResetEvent(PHCompositeNode *topNode) Resetting internal structures, prepare for next event" << std::endl;
0298   return Fun4AllReturnCodes::EVENT_OK;
0299 }
0300 /*
0301 int XingShiftCal::EndRun(const int runnumber)
0302 {
0303   std::cout << "XingShiftCal::EndRun(const int runnumber) Ending Run for Run " << runnumber << std::endl;
0304   return Fun4AllReturnCodes::EVENT_OK;
0305 }
0306 */
0307 int XingShiftCal::End(PHCompositeNode * /*topNode*/)
0308 {
0309   std::cout << "XingShiftCal::End(PHCompositeNode *topNode) This is the End..." << std::endl;
0310 
0311   if (done)
0312   {
0313     // if (!success){
0314     Calibrate(1);
0315     //}
0316     // CommitConstantsToFile();
0317   }
0318   else
0319   {
0320     success = false;
0321     std::cout << "Not enough statistics. Did not calibrate." << std::endl;
0322   }
0323 
0324   const std::string cdbfname = (boost::format("SPIN-%08d_crossingshiftCDBTTree.root") % runnumber).str();
0325   WriteToCDB(cdbfname);
0326   CommitToSpinDB();
0327   
0328 
0329   if (commitSuccessCDB)
0330   {
0331     std::cout << "Commit to CDB : SUCCESS" << std::endl;
0332   }
0333   else
0334   {
0335     std::cout << "Commit to CDB : FAILURE" << std::endl;
0336   }
0337 
0338   if (commitSuccessSpinDB)
0339   {
0340     std::cout << "Commit to SpinDB : SUCCESS" << std::endl;
0341   }
0342   else
0343   {
0344     std::cout << "Commit to SpinDB : FAILURE" << std::endl;
0345   }
0346 
0347   return Fun4AllReturnCodes::EVENT_OK;
0348 }
0349 
0350 int XingShiftCal::Calibrate(const int final)
0351 {
0352   CalculateCrossingShift(xingshift, scalercounts, success);
0353   if (!success)
0354   {
0355     std::cout << "CROSSING CALIBRATION FAILED." << std::endl;
0356     if (final)
0357     {
0358       std::cout << "DONE CALIBRATING." << std::endl;
0359     }
0360     return 0;
0361   }
0362 
0363   if (final)
0364   {
0365     // ostringstream comment;
0366     std::cout << "CROSSING CALIBRATION SUCCESS. XINGSHIFT: " << xingshift << std::endl;
0367     std::cout << "DONE CALIBRATING." << std::endl;
0368     // AddComment(comment.str());
0369   }
0370 
0371   return 0;
0372 }
0373 
0374 int XingShiftCal::CalculateCrossingShift(int &xing, uint64_t counts[NTRIG][NBUNCHES], bool &succ)
0375 {
0376   succ = false;
0377   int shift_array[NTRIG] = {0};
0378 
0379   int trig_inactive_array[NTRIG] = {0};
0380 
0381   int last_active_index = 0;
0382 
0383   int _temp;
0384   for (int itrig = 0; itrig < NTRIG; itrig++)
0385   {
0386     long long _counts = 0;
0387     for (int ii = 0; ii < NBUNCHES; ii++)
0388     {
0389       _counts += counts[itrig][ii];
0390     }
0391 
0392     if (_counts < 10000)
0393     {
0394       trig_inactive_array[itrig] = 1;
0395     }
0396     else
0397     {
0398       last_active_index = itrig;
0399     }
0400 
0401     long long abort_sum_prev = _counts;
0402 
0403     _temp = 0;
0404     for (int ishift = 0; ishift < NBUNCHES; ishift++)
0405     {
0406       long long abort_sum = 0;
0407       for (int iunfillbunch = 0; iunfillbunch < NBUNCHES; iunfillbunch++)
0408       {
0409     if (blueFillPattern[iunfillbunch] && yellFillPattern[iunfillbunch])
0410     {
0411       continue;
0412     }
0413     int shiftbunch = iunfillbunch - ishift;
0414     if (shiftbunch < 0)
0415     {
0416       shiftbunch = 120 + shiftbunch;
0417     }
0418         abort_sum += counts[itrig][(shiftbunch) % NBUNCHES];
0419       }
0420       if (abort_sum < abort_sum_prev)
0421       {
0422         abort_sum_prev = abort_sum;
0423         _temp = ishift;
0424       }
0425     }
0426 
0427     shift_array[itrig] = _temp;
0428   }
0429 
0430   for (int itrig = 0; itrig < NTRIG; itrig++)
0431   {
0432     // if not matching for all trigger selections used, fails
0433     if (!trig_inactive_array[itrig])
0434     {
0435       if (shift_array[itrig] == shift_array[last_active_index])
0436       {
0437         xing = shift_array[itrig];
0438         succ = true;
0439       }
0440       else
0441       {
0442         xing = -999;
0443         succ = false;
0444         return 0;
0445       }
0446     }
0447   }
0448 
0449   // succ = true;
0450   return 0;
0451 }
0452 
0453 int XingShiftCal::WriteToCDB(const std::string &fname)
0454 {
0455   std::cout << "XingShiftCal::WriteToCDB()" << std::endl;
0456   int xing_correction_offset = 0;
0457   if (success)
0458   {
0459     xing_correction_offset = xingshift;
0460     CDBTTree *cdbttree = new CDBTTree(fname);
0461     cdbttree->SetSingleIntValue("crossingshift", xing_correction_offset);
0462     cdbttree->CommitSingle();
0463     // cdbttree->Print();
0464     cdbttree->WriteCDBTTree();
0465     delete cdbttree;
0466 
0467     commitSuccessCDB = 1;
0468   }
0469   else
0470   {
0471     // if (verbosity) {
0472     std::cout << "no successful calibration, do not commit crossing shift to CDB" << std::endl;
0473     //}
0474     commitSuccessCDB = 0;
0475   }
0476 
0477   return 0;
0478 }
0479 
0480 // Commit to spinDB ported from PHENIX
0481 int XingShiftCal::CommitToSpinDB()
0482 {
0483   std::cout << "XingShiftCal::CommitPatternToSpinDB()" << std::endl;
0484   std::string status;  //-------------------------------------------->
0485 
0486 
0487   if (runnumber == 0)
0488   {
0489     std::cout << "Run doesn't exist" << std::endl;
0490     commitSuccessSpinDB = 0;
0491     return 0;
0492   }
0493 
0494   if (fillnumberBlue != fillnumberYellow)
0495   {
0496     std::cout << "fillnumber is wrong : fillnumberBlue = " << fillnumberBlue
0497               << "fillnumberYellow = " << fillnumberYellow << std::endl;
0498     commitSuccessSpinDB = 0;
0499     return 0;
0500   }
0501 
0502   
0503 
0504   int xing_correction_offset = -999;
0505   if (success)
0506   {
0507     xing_correction_offset = xingshift;
0508   }
0509   else
0510   {
0511     // if (verbosity) {
0512     std::cout << "no successful calibration, commit crossing shift -999 to spinDB" << std::endl;
0513     
0514     //}
0515     commitSuccessSpinDB = 0;
0516     //return 0;
0517   }
0518 
0519   // prepare values for db
0520   unsigned int qa_level = 0xffff;
0521 
0522 
0523   //=============== connect to daq db to get gl1p scalers ===============
0524   std::string daqdbname = "daq";
0525   std::string daqdbowner = "phnxrc";
0526   std::string daqdbpasswd = "";
0527 
0528   odbc::Connection *conDAQ = nullptr;
0529   try
0530   {
0531     conDAQ = odbc::DriverManager::getConnection(daqdbname.c_str(), daqdbowner.c_str(), daqdbpasswd.c_str());
0532   }
0533   catch (odbc::SQLException &eDAQ)
0534   {
0535     std::cout << PHWHERE
0536               << " Exception caught at XingShiftCal::CommitPatternToSpinDB when connecting to DAQ DB" << std::endl;
0537     std::cout << "Message: " << eDAQ.getMessage() << std::endl;
0538     //commitSuccessDAQDB = 0;
0539     if (conDAQ)
0540     {
0541       delete conDAQ;
0542       conDAQ = nullptr;
0543     }
0544     return 0;
0545   }
0546 
0547   std::ostringstream sqlGL1PSelect;
0548   sqlGL1PSelect << "SELECT index, bunch, scaled FROM gl1_pscalers"
0549                 << " WHERE runnumber = " << runnumber
0550                 << ";";
0551   odbc::Statement *stmtGL1PSelect = conDAQ->createStatement();
0552   odbc::ResultSet *rsGL1P = nullptr;
0553   try
0554   {
0555     rsGL1P = stmtGL1PSelect->executeQuery(sqlGL1PSelect.str());
0556   }
0557   catch (odbc::SQLException &eGL1P)
0558   {
0559     std::cout << PHWHERE
0560               << " Exception caught at XingShiftCal::CommitPatternToSpinDB when querying DAQ DB" << std::endl;
0561     std::cout << "Message: " << eGL1P.getMessage() << std::endl;
0562     //commitSuccessSpinDB = 0;
0563     if (conDAQ)
0564     {
0565       delete conDAQ;
0566       conDAQ = nullptr;
0567     }
0568     return 0;
0569   }
0570 
0571 
0572   while (rsGL1P->next()) {
0573     int index = rsGL1P->getInt("index");
0574     int bunch = rsGL1P->getInt("bunch");
0575     //MBD NS
0576     if (index == 0)
0577     {
0578       mbdns[bunch] = rsGL1P->getInt("scaled");
0579     }
0580     else if (index == 1)
0581     {
0582       mbdvtx[bunch] = rsGL1P->getInt("scaled");
0583     }
0584     else if (index == 5)
0585     {
0586       zdcns[bunch] = rsGL1P->getInt("scaled");
0587     }
0588 
0589   }
0590   // =======================================================
0591   
0592 
0593   // if (verbosity) {
0594   std::cout << "polb = " << polBlue << " +- " << polBlueErr
0595             << std::endl
0596             << "poly = " << polYellow << " +- " << polYellowErr
0597             << std::endl;
0598   //}
0599 
0600   if (true /*0 && verbosity*/)
0601   {
0602     for (int ibeam = 0; ibeam < 2; ibeam++)
0603     {
0604       if (!ibeam)
0605       {
0606         std::cout << "spinpatternblue = {";
0607       }
0608       else
0609       {
0610         std::cout << "spinpatternyellow = {";
0611       }
0612       for (int icross = 0; icross < NBUNCHES; icross++)
0613       {
0614         if (!ibeam)
0615         {
0616           std::cout << blueSpinPattern[icross] << ",";
0617         }
0618         else
0619         {
0620           std::cout << yellSpinPattern[icross] << ",";
0621         }
0622       }
0623       std::cout << "\b}\n";
0624     }
0625   }
0626 
0627   if (true)
0628   {
0629     for (int i = 0; i < 3; i++)
0630     {
0631       if (i == 0)
0632       {
0633     std::cout << "mbdns = {";
0634       }
0635       else if (i == 1)
0636       {
0637     std::cout << "mbdvtx = {";
0638       }
0639       else if (i == 2)
0640       {
0641     std::cout << "zdcns = {";
0642       }
0643       for (int icross = 0; icross < NBUNCHES; icross++)
0644       {
0645         if (i == 0)
0646         {
0647           std::cout << mbdns[icross] << ",";
0648         }
0649         else if (i == 1)
0650         {
0651           std::cout << mbdvtx[icross] << ",";
0652         }
0653     else if (i == 2)
0654     {
0655       std::cout << zdcns[icross] << ",";
0656     }   
0657       }
0658       std::cout << "\b}\n";
0659     }  
0660   }
0661 
0662 
0663 
0664   //================ connect to spin db ====================
0665   std::string dbname = "spinDB_write";
0666   std::string dbowner = "phnxrc";
0667   std::string dbpasswd = "";
0668   std::string dbtable = "spin";
0669   odbc::Connection *conSpin = nullptr;
0670   try
0671   {
0672     conSpin = odbc::DriverManager::getConnection(dbname.c_str(), dbowner.c_str(), dbpasswd.c_str());
0673   }
0674   catch (odbc::SQLException &e)
0675   {
0676     std::cout << PHWHERE
0677               << " Exception caught at XingShiftCal::CommitPatternToSpinDB when connecting to spin DB" << std::endl;
0678     std::cout << "Message: " << e.getMessage() << std::endl;
0679     commitSuccessSpinDB = 0;
0680     if (conSpin)
0681     {
0682       delete conSpin;
0683       conSpin = nullptr;
0684     }
0685     return 0;
0686   }
0687   // if (verbosity) cout << "opened spin DB connection" << endl;
0688 
0689   // check if this run already exists in spin_oncal
0690   bool runExists = false;
0691   std::ostringstream sqlSpinSelect;
0692   sqlSpinSelect << "SELECT runnumber, qa_level FROM " << dbtable
0693                 << " WHERE runnumber = " << runnumber
0694                 << " AND qa_level = " << qa_level
0695                 << ";";
0696   // if (verbosity) cout<<sqlSpinSelect.str()<<endl;
0697   odbc::Statement *stmtSpinSelect = conSpin->createStatement();
0698   odbc::ResultSet *rsSpin = nullptr;
0699   try
0700   {
0701     rsSpin = stmtSpinSelect->executeQuery(sqlSpinSelect.str());
0702   }
0703   catch (odbc::SQLException &e)
0704   {
0705     std::cout << PHWHERE
0706               << " Exception caught at XingShiftCal::CommitPatternToSpinDB when querying spin DB" << std::endl;
0707     std::cout << "Message: " << e.getMessage() << std::endl;
0708     commitSuccessSpinDB = 0;
0709     if (conSpin)
0710     {
0711       delete conSpin;
0712       conSpin = nullptr;
0713     }
0714     return 0;
0715   }
0716   if (rsSpin->next())
0717   {
0718     if (true /*verbosity*/)
0719     {
0720       std::cout << "run " << runnumber << " exists in " << dbtable
0721                 << ", ready to UPDATE" << std::endl;
0722     }
0723     runExists = true;
0724   }
0725   else
0726   {
0727     if (true /*verbosity*/)
0728     {
0729       std::cout << "run " << runnumber << " NOT exists in " << dbtable
0730                 << ", ready to INSERT" << std::endl;
0731     }
0732   }
0733 
0734   if (runExists && !overwriteSpinEntry)
0735   {
0736     std::cout << "BUT overwriteSpinEntry = " << overwriteSpinEntry << std::endl;
0737     std::cout << "XingShiftCal is NOT going to UPDATE the entry" << std::endl;
0738     commitSuccessSpinDB = 0;
0739     if (conSpin)
0740     {
0741       delete conSpin;
0742       conSpin = nullptr;
0743     }
0744     return 0;
0745   }
0746 
0747   // prepare insert sql
0748   std::ostringstream sql;
0749   if (runExists)
0750   {
0751     // SQLArrayConstF(float x, int n)
0752     sql << "UPDATE " << dbtable
0753         << " SET fillnumber = " << fillnumberBlue << ", "
0754         << "polarblue = " << SQLArrayConstF(polBlue, NBUNCHES) << ", "
0755         << "polarblueerror = " << SQLArrayConstF(polBlueErr, NBUNCHES) << ", "
0756         << "polaryellow = " << SQLArrayConstF(polYellow, NBUNCHES) << ", "
0757         << "polaryellowerror = " << SQLArrayConstF(polYellowErr, NBUNCHES) << ", "
0758     << "crossingshift = " << xing_correction_offset << ", ";
0759     sql << "spinpatternblue = '{";
0760     for (int icross = 0; icross < NBUNCHES; icross++)
0761     {
0762       sql << blueSpinPattern[icross];
0763       if (icross < NBUNCHES - 1)
0764       {
0765         sql << ",";
0766       }
0767     }
0768     sql << "}'";
0769     sql << ", spinpatternyellow = '{";
0770     for (int icross = 0; icross < NBUNCHES; icross++)
0771     {
0772       sql << yellSpinPattern[icross];
0773       if (icross < NBUNCHES - 1)
0774       {
0775         sql << ",";
0776       }
0777     }
0778     sql << "}'";
0779 
0780     sql << ", mbdns = '{";
0781     for (int icross = 0; icross < NBUNCHES; icross++)
0782     {
0783       sql << mbdns[icross];
0784       if (icross < NBUNCHES - 1)
0785       {
0786         sql << ",";
0787       }
0788     }
0789     sql << "}'";
0790 
0791     sql << ", mbdvtx = '{";
0792     for (int icross = 0; icross < NBUNCHES; icross++)
0793     {
0794       sql << mbdvtx[icross];
0795       if (icross < NBUNCHES - 1)
0796       {
0797         sql << ",";
0798       }
0799     }
0800     sql << "}'";
0801 
0802     sql << ", zdcns = '{";
0803     for (int icross = 0; icross < NBUNCHES; icross++)
0804     {
0805       sql << zdcns[icross];
0806       if (icross < NBUNCHES - 1)
0807       {
0808         sql << ",";
0809       }
0810     }
0811     sql << "}'";
0812 
0813     sql << " WHERE runnumber = " << runnumber
0814         << " AND qa_level = " << qa_level
0815         << ";";
0816   }
0817   else
0818   {
0819     sql << "INSERT INTO " << dbtable;
0820     sql << " (runnumber, fillnumber, polarblue, polarblueerror, polaryellow, polaryellowerror, crossingshift, spinpatternblue, spinpatternyellow, mbdns, mbdvtx, zdcns, qa_level) VALUES (";
0821     sql << runnumber << ", "
0822         << fillnumberBlue << ", "
0823         << SQLArrayConstF(polBlue, NBUNCHES) << ", "
0824         << SQLArrayConstF(polBlueErr, NBUNCHES) << ", "
0825         << SQLArrayConstF(polYellow, NBUNCHES) << ", "
0826         << SQLArrayConstF(polYellowErr, NBUNCHES) << ", "
0827     << xing_correction_offset << ", ";  
0828     sql << "'{";
0829     for (int icross = 0; icross < NBUNCHES; icross++)
0830     {
0831       sql << blueSpinPattern[icross];
0832       if (icross < NBUNCHES - 1)
0833       {
0834         sql << ",";
0835       }
0836     }
0837     sql << "}'";
0838     sql << ", '{";
0839     for (int icross = 0; icross < NBUNCHES; icross++)
0840     {
0841       sql << yellSpinPattern[icross];
0842       if (icross < NBUNCHES - 1)
0843       {
0844         sql << ",";
0845       }
0846     }
0847     sql << "}'";
0848     sql << ", '{";
0849     for (int icross = 0; icross < NBUNCHES; icross++)
0850     {
0851       sql << mbdns[icross];
0852       if (icross < NBUNCHES - 1)
0853       {
0854         sql << ",";
0855       }
0856     }
0857     sql << "}'";
0858     sql << ", '{";
0859     for (int icross = 0; icross < NBUNCHES; icross++)
0860     {
0861       sql << mbdvtx[icross];
0862       if (icross < NBUNCHES - 1)
0863       {
0864         sql << ",";
0865       }
0866     }
0867     sql << "}'";
0868     sql << ", '{";
0869     for (int icross = 0; icross < NBUNCHES; icross++)
0870     {
0871       sql << zdcns[icross];
0872       if (icross < NBUNCHES - 1)
0873       {
0874         sql << ",";
0875       }
0876     }
0877     sql << "}'";
0878 
0879     sql << ", " << qa_level << ");";
0880   }
0881   if (true /*verbosity*/)
0882   {
0883     std::cout << sql.str() << std::endl;
0884   }
0885 
0886   // exec sql
0887 
0888   odbc::Statement *stmtSpin = conSpin->createStatement();
0889   try
0890   {
0891     stmtSpin->executeUpdate(sql.str());
0892   }
0893   catch (odbc::SQLException &e)
0894   {
0895     std::cout << PHWHERE
0896               << " Exception caught at XingShiftCal::CommitPatternToSpinDB when insert into spin DB" << std::endl;
0897     std::cout << "Message: " << e.getMessage() << std::endl;
0898     commitSuccessSpinDB = 0;
0899     if (conSpin)
0900     {
0901       delete conSpin;
0902       conSpin = nullptr;
0903     }
0904     return 0;
0905   }
0906 
0907   // if (verbosity) cout<<"spin db done"<<endl;
0908   commitSuccessSpinDB = 1;
0909 
0910   if (conDAQ)
0911   {
0912     delete conDAQ;
0913     conDAQ = nullptr;
0914   }
0915 
0916   if (conSpin)
0917   {
0918     delete conSpin;
0919     conSpin = nullptr;
0920   }
0921 
0922 
0923   // ========== Do spin db qa here =========== //
0924   SpinDBQA();
0925   // ========================================= //
0926 
0927 
0928   return 0;
0929 }
0930 
0931 
0932 int XingShiftCal::SpinDBQA()
0933 {
0934 
0935   // prepare values for db
0936   unsigned int qa_level = 0xffff;
0937 
0938   //================ connect to spin db ====================
0939   std::string dbname = "spinDB";
0940   std::string dbowner = "phnxrc";
0941   std::string dbpasswd = "";
0942   std::string dbtable = "spin";
0943   odbc::Connection *conSpin = nullptr;
0944   try
0945   {
0946     conSpin = odbc::DriverManager::getConnection(dbname.c_str(), dbowner.c_str(), dbpasswd.c_str());
0947   }
0948   catch (odbc::SQLException &e)
0949   {
0950     std::cout << PHWHERE
0951               << " Exception caught at XingShiftCal::CommitPatternToSpinDB when connecting to spin DB" << std::endl;
0952     std::cout << "Message: " << e.getMessage() << std::endl;
0953     commitSuccessSpinDB = 0;
0954     if (conSpin)
0955     {
0956       delete conSpin;
0957       conSpin = nullptr;
0958     }
0959     return 0;
0960   }
0961 
0962   // check if this run already exists in spin_oncal and get badrun value if it exists
0963   bool runExists = false;
0964   int prevbadrunval = 0;
0965   std::ostringstream sqlSpinSelect;
0966   sqlSpinSelect << "SELECT runnumber, qa_level, badrunqa FROM " << dbtable
0967                 << " WHERE runnumber = " << runnumber
0968                 << " AND qa_level = " << qa_level
0969                 << ";";
0970 
0971   std::cout << "SELECT runnumber, qa_level, badrunqa FROM " << dbtable
0972                 << " WHERE runnumber = " << runnumber
0973                 << " AND qa_level = " << qa_level
0974         << ";" << std::endl;
0975   
0976   odbc::Statement *stmtSpinSelect = conSpin->createStatement();
0977   odbc::ResultSet *rsSpin = nullptr;
0978   try
0979   {
0980     rsSpin = stmtSpinSelect->executeQuery(sqlSpinSelect.str());
0981   }
0982   catch (odbc::SQLException &e)
0983   {
0984     std::cout << PHWHERE
0985               << " Exception caught at XingShiftCal::SpinDBQA when querying spin DB" << std::endl;
0986     std::cout << "Message: " << e.getMessage() << std::endl;
0987     if (conSpin)
0988     {
0989       delete conSpin;
0990       conSpin = nullptr;
0991     }
0992     return 0;
0993   }
0994   if (rsSpin->next())
0995   {
0996     prevbadrunval = rsSpin->getInt("badrunqa");
0997     if (rsSpin->wasNull()) 
0998     {
0999       std::cout << "SPINDBQA: badrunqa is NULL. Setting to 0 for qa check. "<< std::endl;
1000       prevbadrunval = 0;
1001     }
1002     if (true)
1003     {
1004       std::cout << "run " << runnumber << " exists in " << dbtable
1005                 << ", ready to do QA" << std::endl;
1006     }
1007     runExists = true;
1008   }
1009   else
1010   {
1011     if (true)
1012     {
1013       std::cout << "run " << runnumber << " NOT exists in " << dbtable
1014                 << ", no QA" << std::endl;
1015     }
1016   }
1017 
1018   int badrunQA = 0;
1019   
1020   if (prevbadrunval > 0)
1021   {
1022     std::cout << "SPINDBQA: badrunqa is already > 0. No additional qa is performed." << std:: endl;
1023     if (conSpin)
1024     {
1025       delete conSpin;
1026       conSpin = nullptr;
1027     }
1028     return 0;  
1029   }
1030   else
1031   {
1032     // =========== Do bad run QA here =============
1033     // if (conditions pass && previously existing badRunQA != 1): badrunQA = 0
1034     // if (conditions fail (bad run)): badrunQA = 1
1035 
1036     //if spin pattern does not match known MCR pattern
1037     std::string scdev_blue = "";
1038     std::string scdev_yell = "";
1039     for (int crossing = 0; crossing < 120; crossing++)
1040     {
1041       int ibluespin = blueSpinPattern[crossing];
1042       int iyellspin = yellSpinPattern[crossing];
1043       if (ibluespin == 1)
1044       {
1045     scdev_blue.push_back('+');
1046       }
1047       else if (ibluespin == -1)
1048       {
1049     scdev_blue.push_back('-');
1050       }
1051       else
1052       {
1053     scdev_blue.push_back('*');
1054       }
1055 
1056       if (iyellspin == 1)
1057       {
1058     scdev_yell.push_back('+');
1059       }
1060       else if (iyellspin == -1)
1061       {
1062     scdev_yell.push_back('-');
1063       }
1064       else
1065       {
1066     scdev_yell.push_back('*');
1067       }
1068     }
1069     //std::string scdev_blue = TH1_to_string(hspinpatternBlue);
1070     //std::string scdev_yell = TH1_to_string(hspinpatternYellow);
1071     std::string pattern_name = "UNKNOWN";
1072     
1073     for (std::map<std::string, std::string>::const_iterator ii = preset_pattern_blue.begin(); ii != preset_pattern_blue.end(); ++ii)
1074     {
1075       std::string key = (*ii).first;
1076       if (preset_pattern_blue[key] == scdev_blue && preset_pattern_yellow[key] == scdev_yell)
1077       {
1078     pattern_name = key;
1079       }
1080     }
1081 
1082     if (pattern_name == "UNKNOWN")
1083     {
1084       badrunQA = 1;
1085       std::cout << "SPINDBQA: Pattern is unidentified from known CDEV pattern. Setting bad run." << std::endl;
1086     }
1087 
1088 
1089     //if pc spin pattern does not match intended spin pattern within < 10 bunches
1090     int mismatches = 0;
1091     std::string spin_pattern_blue = "";
1092     std::string spin_pattern_yell = "";
1093     for (int crossing = 0; crossing < 120; crossing++)
1094     {
1095       int spin_cdev_blue = blueSpinPattern[crossing];
1096       int spin_cdev_yell = yellSpinPattern[crossing];
1097       int spin_pC_blue = bluePcSpinPattern[crossing];
1098       int spin_pC_yell = yellPcSpinPattern[crossing];
1099 
1100       if(spin_pC_blue==-1 || spin_pC_blue==1)
1101       {
1102     if (spin_cdev_blue != spin_pC_blue && !(spin_cdev_blue == 0 && spin_pC_blue == 10))
1103     {
1104       mismatches += 1;
1105     }
1106       }
1107 
1108       if(spin_pC_yell==-1 || spin_pC_yell==1)
1109       {
1110     if (spin_cdev_yell != spin_pC_yell && !(spin_cdev_blue == 0 && spin_pC_blue == 10))
1111     {
1112       mismatches += 1;
1113     }
1114       } 
1115     }
1116 
1117     if (mismatches > 10)
1118     {
1119       badrunQA = 1;
1120       std::cout << "SPINDBQA: CDEV pattern has > 10 mismatched bunches from pC polarimeter. Setting bad run." << std::endl;
1121     }
1122 
1123     //if crossing shift != 0
1124     int xing_correction_offset = -999;
1125     if (success)
1126     {
1127       xing_correction_offset = xingshift;
1128     }
1129 
1130     if (xing_correction_offset != 0)
1131     {
1132       badrunQA = 1;
1133       std::cout << "SPINDBQA: Crossing shift does not equal 0. Setting bad run." << std::endl;
1134     }
1135 
1136     //if polarization <= 0 || > 1.00 //makes sure polarization from CNI aren't garbage values
1137     if (polBlue <= 0.0 || polBlue > 100.0)
1138     {
1139       badrunQA = 1;
1140       std::cout << "SPINDBQA: Blue beam polarization is unknown. Setting bad run." << std::endl;
1141     }
1142     if (polYellow <= 0.0 || polYellow > 100.0)
1143     {
1144       badrunQA = 1;
1145       std::cout << "SPINDBQA: Yellow beam polarization is unknown. Setting bad run." << std::endl;
1146     }
1147       
1148     // ============================================
1149     
1150   }
1151   
1152 
1153   //================ connect to spin db write ====================
1154   dbname = "spinDB_write";
1155   dbowner = "phnxrc";
1156   dbpasswd = "";
1157   dbtable = "spin";
1158   conSpin = nullptr;
1159   if (runExists)
1160   {
1161 
1162     try
1163     {
1164       conSpin = odbc::DriverManager::getConnection(dbname.c_str(), dbowner.c_str(), dbpasswd.c_str());
1165     }
1166     catch (odbc::SQLException &e)
1167     {
1168       std::cout << PHWHERE
1169         << " Exception caught at XingShiftCal::CommitPatternToSpinDB when connecting to spin DB" << std::endl;
1170       std::cout << "Message: " << e.getMessage() << std::endl;
1171       commitSuccessSpinDB = 0;
1172       if (conSpin)
1173       {
1174     delete conSpin;
1175     conSpin = nullptr;
1176       }
1177       return 0;
1178     }
1179 
1180 
1181     std::cout << "UPDATE " << dbtable
1182         << " SET badrunqa = " << badrunQA
1183     << " WHERE runnumber = " << runnumber
1184         << " AND qa_level = " << qa_level
1185           << ";" << std::endl;
1186 
1187     // prepare insert sql
1188     std::ostringstream sql;
1189     sql << "UPDATE " << dbtable
1190         << " SET badrunqa = " << badrunQA
1191     << " WHERE runnumber = " << runnumber
1192         << " AND qa_level = " << qa_level
1193         << ";";
1194 
1195     // exec sql
1196     odbc::Statement *stmtSpin = conSpin->createStatement();
1197     try
1198     {
1199       stmtSpin->executeUpdate(sql.str());
1200     }
1201     catch (odbc::SQLException &e)
1202     {
1203       std::cout << PHWHERE
1204         << " Exception caught at XingShiftCal::SpinDBQA when insert badrunqa into spin DB" << std::endl;
1205       std::cout << "Message: " << e.getMessage() << std::endl;
1206       commitSuccessSpinDB = 0;
1207       if (conSpin)
1208       {
1209     delete conSpin;
1210     conSpin = nullptr;
1211       }
1212       return 0;
1213     }
1214 
1215   }
1216 
1217   
1218   
1219 
1220   if (conSpin)
1221   {
1222     delete conSpin;
1223     conSpin = nullptr;
1224   }
1225 
1226 
1227   return 0;
1228 }
1229 
1230 
1231 std::string XingShiftCal::SQLArrayConstF(float x, int n)
1232 {
1233   std::ostringstream s;
1234   s << "'{";
1235   for (int i = 0; i < n; i++)
1236   {
1237     s << x;
1238     if (i < n - 1)
1239     {
1240       s << ",";
1241     }
1242   }
1243   s << "}'";
1244   return s.str();
1245 }
1246 
1247 //____________________________________________________________________________..
1248 int XingShiftCal::Reset(PHCompositeNode * /*topNode*/)
1249 {
1250   // std::cout << "XingShiftCal::Reset(PHCompositeNode *topNode) being Reset" << std::endl;
1251   return Fun4AllReturnCodes::EVENT_OK;
1252 }
1253 
1254 //____________________________________________________________________________..
1255 void XingShiftCal::Print(const std::string &what) const
1256 {
1257   std::cout << "XingShiftCal::Print(const std::string &what) const Printing info for " << what << std::endl;
1258 }
1259