Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-07-05 04:09:21

0001 #include "CalibTracker/SiStripCommon/interface/SiStripDetInfoFileReader.h"
0002 #include "CalibTracker/SiStripDCS/interface/SiStripDetVOffBuilder.h"
0003 #include <sys/stat.h>
0004 
0005 #include <memory>
0006 
0007 // constructor
0008 SiStripDetVOffBuilder::SiStripDetVOffBuilder(const edm::ParameterSet& pset, const edm::ActivityRegistry&)
0009     : onlineDbConnectionString(pset.getParameter<std::string>("onlineDB")),
0010       authenticationPath(pset.getParameter<std::string>("authPath")),
0011       whichTable(pset.getParameter<std::string>("queryType")),
0012       lastValueFileName(pset.getParameter<std::string>("lastValueFile")),
0013       fromFile(pset.getParameter<bool>("lastValueFromFile")),
0014       psuDetIdMapFile_(pset.getParameter<std::string>("PsuDetIdMapFile")),
0015       debug_(pset.getParameter<bool>("debugModeOn")),
0016       tDefault(7, 0),
0017       tmax_par(pset.getParameter<std::vector<int> >("Tmax")),
0018       tmin_par(pset.getParameter<std::vector<int> >("Tmin")),
0019       tset_par(pset.getParameter<std::vector<int> >("TSetMin")),
0020       deltaTmin_(pset.getParameter<uint32_t>("DeltaTmin")),
0021       maxIOVlength_(pset.getParameter<uint32_t>("MaxIOVlength")),
0022       detIdListFile_(pset.getParameter<std::string>("DetIdListFile")),
0023       excludedDetIdListFile_(pset.getParameter<std::string>("ExcludedDetIdListFile")),
0024       highVoltageOnThreshold_(pset.getParameter<double>("HighVoltageOnThreshold")) {
0025   lastStoredCondObj.first = nullptr;
0026   lastStoredCondObj.second = 0;
0027 
0028   edm::LogError("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::SiStripDetVOffBuilder] constructor" << endl;
0029 
0030   // set up vectors based on pset parameters (tDefault purely for initialization)
0031 
0032   whichQuery = (whichTable == "STATUSCHANGE" || (whichTable == "LASTVALUE" && !fromFile));
0033 
0034   //Define the query interval [Tmin, Tmax]
0035   //where Tmax comes from the cfg
0036   //      Tmin comes from the cfg for the first o2o, after that it is extracted from Offline DB
0037 
0038   tmax = coral::TimeStamp(tmax_par[0], tmax_par[1], tmax_par[2], tmax_par[3], tmax_par[4], tmax_par[5], tmax_par[6]);
0039 
0040   if (whichQuery) {
0041     // Is there a better way to do this?  TODO - investigate
0042     tmin = coral::TimeStamp(tmin_par[0], tmin_par[1], tmin_par[2], tmin_par[3], tmin_par[4], tmin_par[5], tmin_par[6]);
0043   }
0044 
0045   if (whichTable == "LASTVALUE") {
0046     tsetmin =
0047         coral::TimeStamp(tset_par[0], tset_par[1], tset_par[2], tset_par[3], tset_par[4], tset_par[5], tset_par[6]);
0048   }
0049 
0050   if (onlineDbConnectionString.empty()) {
0051     edm::LogError("SiStripDetVOffBuilder")
0052         << "[SiStripDetVOffBuilder::SiStripDetVOffBuilder] DB name has not been set properly ... Returning ...";
0053     return;
0054   }
0055 
0056   if (fromFile && whichTable == "LASTVALUE" && lastValueFileName.empty()) {
0057     edm::LogError("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::SiStripDetVOffBuilder] File expected for "
0058                                               "lastValue table, but filename not specified ... Returning ...";
0059     return;
0060   }
0061 
0062   // write out the parameters
0063   std::stringstream ss;
0064   ss << "[SiStripDetVOffBuilder::SiStripDetVOffBuilder]\n"
0065      << "     Parameters:\n"
0066      << "     DB connection string: " << onlineDbConnectionString << "\n"
0067      << "     Authentication path: " << authenticationPath << "\n"
0068      << "     Table to be queried: " << whichTable << "\n"
0069      << "     MapFile: " << psuDetIdMapFile_ << "\n";
0070 
0071   if (whichQuery) {
0072     ss << "     Tmin: ";
0073     printPar(ss, tmin_par);
0074     ss << std::endl;
0075   }
0076   ss << "     Tmax: ";
0077   printPar(ss, tmax_par);
0078   ss << std::endl;
0079 
0080   if (whichTable == "LASTVALUE") {
0081     ss << "     TSetMin: ";
0082     printPar(ss, tset_par);
0083     ss << std::endl;
0084   }
0085   edm::LogError("SiStripDetVOffBuilder") << ss.str();
0086 }
0087 
0088 // destructor
0089 SiStripDetVOffBuilder::~SiStripDetVOffBuilder() {
0090   edm::LogError("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::" << __func__ << "]: destructing ...";
0091 }
0092 
0093 void SiStripDetVOffBuilder::printPar(std::stringstream& ss, const std::vector<int>& par) {
0094   for (int val : par) {
0095     ss << val << " ";
0096   }
0097 }
0098 
0099 void SiStripDetVOffBuilder::BuildDetVOffObj() {
0100   // vectors for storing output from DB or text file
0101   TimesAndValues timesAndValues;
0102 
0103   // Open the PVSS DB connection
0104   coralInterface = std::make_unique<SiStripCoralIface>(onlineDbConnectionString, authenticationPath, debug_);
0105   edm::LogError("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::BuildDetVOff]: Query type is " << whichTable
0106                                          << endl;
0107 
0108   if (whichTable == "LASTVALUE") {
0109     edm::LogError("SiStripDetVOffBuilder")
0110         << "[SiStripDetVOffBuilder::BuildDetVOff]: Use file? " << ((fromFile) ? "TRUE" : "FALSE");
0111   }
0112 
0113   if (lastStoredCondObj.second > 0) {
0114     edm::LogError("SiStripDetVOffBuilder")
0115         << "[SiStripDetVOffBuilder::BuildDetVOff]: retrieved last time stamp from DB: " << lastStoredCondObj.second
0116         << endl;
0117   }
0118   // access the information!
0119   //We've been using the STATUSCHANGE query only in last year or so... LASTVALUE may have untested issues...
0120   //In either case the idea is that the results of the query are saved into the timesAndValues struct
0121   //ready to be anaylized (i.e. translated into detIDs, HV/LV statuses)
0122 
0123   if (whichQuery) {
0124     if (whichTable == "STATUSCHANGE") {
0125       statusChange(lastStoredCondObj.second, timesAndValues);
0126     }
0127     if (whichTable == "LASTVALUE") {
0128       if (fromFile) {
0129         lastValueFromFile(timesAndValues);
0130       } else {
0131         lastValue(timesAndValues);
0132       }
0133     }
0134   }
0135 
0136   //Initialize the stuct that will be used to keep the detID-translated information
0137   DetIdListTimeAndStatus dStruct;
0138 
0139   // build PSU - det ID map
0140   //The following method actually "builds" 4 maps: LVMap, HVMap, HVUnmapped_Map, HVCrosstalking_Map.
0141   //It also takes the timesAndValues from the query above and using the maps, it processes the information
0142   //populating the DetIDListTimeAndStatus struct that will hold the information by detid.
0143   buildPSUdetIdMap(timesAndValues, dStruct);
0144 
0145   // initialize variables
0146   modulesOff.clear();
0147   cond::Time_t saveIovTime = 0;
0148 
0149   // - If there is already an object stored in the database
0150   // -- store it in the modulesOff vector
0151   // -- set the saveIovTime as that
0152   // -- set the payload stats to empty
0153   // Successivamente:
0154   // - loop su tutti gli elementi del detidV, che stato letto dal pvss (questi elementi sono pair<vettore di detid, time>)
0155   // -- setta il tempo dell'IOV:
0156   // --- LASTVALUE -> iovtime settato a latestTime
0157   // --- altrimenti iovtime = tempo associato al detId vector del loop
0158 
0159   // check if there is already an object stored in the DB
0160   // This happens only if you are using STATUSCHANGE
0161   if (lastStoredCondObj.first != nullptr && lastStoredCondObj.second > 0) {
0162     modulesOff.push_back(lastStoredCondObj);
0163     saveIovTime = lastStoredCondObj.second;
0164     setPayloadStats(0, 0, 0);
0165   }
0166 
0167   //Master loop over all the results of the query stored in the dStruct (that contains vectors with vectors of detids, statuses, isHV flags, etc and in particular a vector of timestamps for which the info is valid... basically it is a loop over the timestamps (i.e. IOVs).
0168   for (unsigned int i = 0; i < dStruct.detidV.size(); i++) {
0169     //     std::vector<uint32_t> detids = dStruct.detidV[i].first;
0170     //     removeDuplicates(detids);
0171     std::vector<uint32_t>* detids = &(dStruct.detidV[i].first);
0172 
0173     // set the condition time for the transfer
0174     cond::Time_t iovtime = 0;
0175 
0176     if (whichTable == "LASTVALUE") {
0177       iovtime = timesAndValues.latestTime;
0178     }
0179 
0180     else {
0181       iovtime = getCondTime((dStruct.detidV[i]).second);
0182     }
0183 
0184     // decide how to initialize modV
0185     SiStripDetVOff* modV = nullptr;
0186 
0187     // When using STATUSCHANGE they are equal only for the first
0188     // When using LASTVALUE they are equal only if the tmin was set to tsetmin
0189 
0190     if (iovtime != saveIovTime) {  // time is different, so create new object
0191 
0192       // This can be only when using LASTVALUE or with a new tag
0193       if (modulesOff.empty()) {
0194         // create completely new object and set the initial state to Tracker all off
0195         modV = new SiStripDetVOff();
0196 
0197         // Use the file
0198         const auto detInfo = SiStripDetInfoFileReader::read(edm::FileInPath{detIdListFile_}.fullPath());
0199 
0200         //FIXME:
0201         //Following code is actually broken (well not until the cfg has "" for excludedDetIDListFile parameter!
0202         //Fix it if felt necessary (remember that it assumes that whatever detids are excluded should NOT be in the regular map
0203         //breaking our current situation with a fully mapped (LV-wise) tracker...
0204         // Careful: if a module is in the exclusion list it must be ignored and the initial status is set to ON.
0205         // These modules are expected to not be in the PSU-DetId map, so they will never get any status change from the query.
0206         SiStripPsuDetIdMap map;
0207         std::vector<std::pair<uint32_t, std::string> > excludedDetIdMap;
0208         if (!excludedDetIdListFile_.empty()) {
0209           map.BuildMap(excludedDetIdListFile_, excludedDetIdMap);
0210         }
0211         for (const auto& it : detInfo.getAllData()) {
0212           bool excluded = false;
0213           for (const auto& exclIt : excludedDetIdMap) {
0214             if (it.first == exclIt.first) {
0215               excluded = true;
0216               break;
0217             }
0218           }
0219           if (!excluded) {
0220             modV->put(it.first, 1, 1);
0221           }
0222         }
0223 
0224       } else {
0225         modV = new SiStripDetVOff(*(modulesOff.back().first));
0226       }  // start from copy of previous object
0227     } else {
0228       modV =
0229           (modulesOff.back())
0230               .first;  // modify previous object (TEST THIS if possible! it's fundamental in handling changes at the edges of O2O executions and also in case of PVSS DB buffering!
0231     }
0232 
0233     // extract the detID vector before modifying for stats calculation
0234     std::vector<uint32_t> beforeV;
0235     modV->getDetIds(beforeV);
0236 
0237     //CHECKTHIS
0238     //The following method call is potentially problematic:
0239     //passing modV as argument while extracting information about dStruct,
0240     //modV is not currently used in the method!
0241     std::pair<int, int> hvlv = extractDetIdVector(
0242         i, modV, dStruct);  //Returns a pair like this HV OFF->1,-1 HV ON->0,-1 LV OFF->-1,1 LV ON->-1,0
0243     //Basically a LV OFF of -1  means that the information (IOV) in question is from an HV channel turning on or off and viceversa for an HVOFF of -1.
0244     //This could be confusing when reading the debug output!
0245 
0246     for (unsigned int j = 0; j < detids->size(); j++) {
0247       if (debug_)
0248         cout << "at time = " << iovtime << " detid[" << j << "] = " << (*detids)[j] << " has hv = " << hvlv.first
0249              << " and lv = " << hvlv.second << endl;
0250       modV->put((*detids)[j], hvlv.first, hvlv.second);
0251     }
0252 
0253     // calculate the stats for storage
0254     unsigned int numAdded = 0, numRemoved = 0;
0255     if (iovtime == saveIovTime) {
0256       std::vector<uint32_t> oldStats = payloadStats.back();
0257       numAdded = oldStats[1];
0258       numRemoved = oldStats[2];
0259     }
0260     std::vector<uint32_t> afterV;
0261     modV->getDetIds(afterV);
0262 
0263     if ((afterV.size() - beforeV.size()) > 0) {
0264       numAdded += afterV.size() - beforeV.size();
0265     } else if ((beforeV.size() - afterV.size()) > 0) {
0266       numRemoved += beforeV.size() - afterV.size();
0267     }
0268 
0269     // store the object if it's a new object
0270     if (iovtime != saveIovTime) {
0271       SiStripDetVOff* testV = nullptr;
0272       if (!modulesOff.empty()) {
0273         testV = modulesOff.back().first;
0274       }
0275       if (modulesOff.empty() || !(*modV == *testV)) {
0276         modulesOff.push_back(std::make_pair(modV, iovtime));
0277         // save the time of the object
0278         saveIovTime = iovtime;
0279         // save stats
0280         setPayloadStats(afterV.size(), numAdded, numRemoved);
0281       } else {
0282         // modV will not be used anymore, DELETE it to avoid memory leak!
0283         delete modV;
0284       }
0285     } else {
0286       (payloadStats.back())[0] = afterV.size();
0287       (payloadStats.back())[1] = numAdded;
0288       (payloadStats.back())[2] = numRemoved;
0289     }
0290   }
0291 
0292   // compare the first element and the last from previous transfer
0293   if (lastStoredCondObj.first != nullptr && lastStoredCondObj.second > 0) {
0294     if (*(lastStoredCondObj.first) == *(modulesOff[0].first)) {
0295       if (modulesOff.size() == 1) {
0296         // if no HV/LV transition was found in this period: update the last IOV to be tmax
0297         modulesOff[0].second = getCondTime(tmax);
0298       } else {
0299         // HV/LV transitions found: remove the first one (which came from previous transfer)
0300         modulesOff.erase(modulesOff.begin());
0301         payloadStats.erase(payloadStats.begin());
0302       }
0303     }
0304   }
0305 
0306   if (debug_) {
0307     std::cout << std::endl;
0308     std::cout << "Size of modulesOff = " << modulesOff.size() << std::endl;
0309     for (unsigned int i = 0; i < modulesOff.size(); i++) {
0310       std::vector<uint32_t> finalids;
0311       (modulesOff[i].first)->getDetIds(finalids);
0312       std::cout << "Index = " << i << " Size of DetIds vector = " << finalids.size() << std::endl;
0313       std::cout << "Time = " << modulesOff[i].second << std::endl;
0314       for (unsigned int j = 0; j < finalids.size(); j++) {
0315         std::cout << "detid = " << finalids[j] << " LV off = " << (modulesOff[i].first)->IsModuleLVOff(finalids[j])
0316                   << " HV off = " << (modulesOff[i].first)->IsModuleHVOff(finalids[j]) << std::endl;
0317       }
0318     }
0319   }
0320 }
0321 
0322 int SiStripDetVOffBuilder::findSetting(uint32_t id,
0323                                        const coral::TimeStamp& changeDate,
0324                                        const std::vector<uint32_t>& settingID,
0325                                        const std::vector<coral::TimeStamp>& settingDate) {
0326   int setting = -1;
0327   // find out how many channel entries there are
0328   std::vector<int> locations;
0329   for (unsigned int i = 0; i < settingID.size(); i++) {
0330     if (settingID[i] == id) {
0331       locations.push_back((int)i);
0332     }
0333   }
0334 
0335   // simple cases
0336   if (locations.empty()) {
0337     setting = -1;
0338   } else if (locations.size() == 1) {
0339     setting = locations[0];
0340   }
0341   // more than one entry for this channel
0342   // NB.  entries ordered by date!
0343   else {
0344     for (unsigned int j = 0; j < locations.size(); j++) {
0345 #ifdef USING_NEW_CORAL
0346       const boost::posix_time::ptime& testSec = changeDate.time();
0347       const boost::posix_time::ptime& limitSec = settingDate[(unsigned int)locations[j]].time();
0348 #else
0349       long testSec = changeDate.time().ns();
0350       long limitSec = settingDate[(unsigned int)locations[j]].time().ns();
0351 #endif
0352       if (testSec >= limitSec) {
0353         setting = locations[j];
0354       }
0355     }
0356   }
0357   return setting;
0358 }
0359 
0360 int SiStripDetVOffBuilder::findSetting(std::string dpname,
0361                                        const coral::TimeStamp& changeDate,
0362                                        const std::vector<std::string>& settingDpname,
0363                                        const std::vector<coral::TimeStamp>& settingDate) {
0364   int setting = -1;
0365   // find out how many channel entries there are
0366   std::vector<int> locations;
0367   for (unsigned int i = 0; i < settingDpname.size(); i++) {
0368     if (settingDpname[i] == dpname) {
0369       locations.push_back((int)i);
0370     }
0371   }
0372 
0373   // simple cases
0374   if (locations.empty()) {
0375     setting = -1;
0376   } else if (locations.size() == 1) {
0377     setting = locations[0];
0378   }
0379   // more than one entry for this channel
0380   // NB.  entries ordered by date!
0381   else {
0382     for (unsigned int j = 0; j < locations.size(); j++) {
0383 #ifdef USING_NEW_CORAL
0384       const boost::posix_time::ptime& testSec = changeDate.time();
0385       const boost::posix_time::ptime& limitSec = settingDate[(unsigned int)locations[j]].time();
0386 #else
0387       long testSec = changeDate.time().ns();
0388       long limitSec = settingDate[(unsigned int)locations[j]].time().ns();
0389 #endif
0390       if (testSec >= limitSec) {
0391         setting = locations[j];
0392       }
0393     }
0394   }
0395   return setting;
0396 }
0397 
0398 void SiStripDetVOffBuilder::readLastValueFromFile(std::vector<uint32_t>& dpIDs,
0399                                                   std::vector<float>& vmonValues,
0400                                                   std::vector<coral::TimeStamp>& dateChange) {
0401   std::ifstream lastValueFile(lastValueFileName.c_str());
0402   if (lastValueFile.bad()) {
0403     edm::LogError("SiStripDetVOffBuilder")
0404         << "[SiStripDetVOffBuilder::" << __func__ << "]: last Value file does not exist!";
0405     return;
0406   }
0407 
0408   dpIDs.clear();
0409   vmonValues.clear();
0410   dateChange.clear();
0411   std::vector<std::string> changeDates;
0412 
0413   std::string line;
0414   // remove the first line as it is the title line
0415   //  std::getline(lastValueFile,line);
0416   //  line.clear();
0417   // now extract data
0418   while (std::getline(lastValueFile, line)) {
0419     std::istringstream ss(line);
0420     uint32_t dpid;
0421     float vmon;
0422     std::string changeDate;
0423     ss >> std::skipws >> dpid >> vmon >> changeDate;
0424     dpIDs.push_back(dpid);
0425     vmonValues.push_back(vmon);
0426     changeDates.push_back(changeDate);
0427   }
0428   lastValueFile.close();
0429 
0430   // Now convert dates to coral::TimeStamp
0431   for (unsigned int i = 0; i < changeDates.size(); i++) {
0432     std::string part = changeDates[i].substr(0, 4);
0433     int year = atoi(part.c_str());
0434     part.clear();
0435 
0436     part = changeDates[i].substr(5, 2);
0437     int month = atoi(part.c_str());
0438     part.clear();
0439 
0440     part = changeDates[i].substr(8, 2);
0441     int day = atoi(part.c_str());
0442     part.clear();
0443 
0444     part = changeDates[i].substr(11, 2);
0445     int hour = atoi(part.c_str());
0446     part.clear();
0447 
0448     part = changeDates[i].substr(14, 2);
0449     int minute = atoi(part.c_str());
0450     part.clear();
0451 
0452     part = changeDates[i].substr(17, 2);
0453     int second = atoi(part.c_str());
0454     part.clear();
0455 
0456     coral::TimeStamp date(year, month, day, hour, minute, second, 0);
0457     dateChange.push_back(date);
0458   }
0459 
0460   if (changeDates.size() != dateChange.size()) {
0461     edm::LogError("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::" << __func__ << "]: date conversion failed!!";
0462   }
0463 }
0464 
0465 cond::Time_t SiStripDetVOffBuilder::getCondTime(const coral::TimeStamp& coralTime) {
0466   // const boost::posix_time::ptime& t = coralTime.time();
0467   cond::Time_t condTime = cond::time::from_boost(coralTime.time());
0468 
0469   // cout << "[SiStripDetVOffBuilder::getCondTime] Converting CoralTime into CondTime: "
0470   //      << " coralTime = (coralTimeInNs) " <<  coralTime.total_nanoseconds() << " condTime " << (condTime>> 32) << " - " << (condTime & 0xFFFFFFFF) << endl;
0471 
0472   return condTime;
0473 }
0474 
0475 coral::TimeStamp SiStripDetVOffBuilder::getCoralTime(cond::Time_t iovTime) {
0476   // This method is defined in the TimeConversions header and it does the following:
0477   // - takes the seconds part of the iovTime (bit-shifting of 32)
0478   // - adds the nanoseconds part (first 32 bits mask)
0479   // - adds the time0 that is the time from begin of times (boost::posix_time::from_time_t(0);)
0480   coral::TimeStamp coralTime(cond::time::to_boost(iovTime));
0481 
0482   if (debug_) {
0483     unsigned long long iovSec = iovTime >> 32;
0484     uint32_t iovNanoSec = uint32_t(iovTime);
0485     cond::Time_t testTime = getCondTime(coralTime);
0486     cout << "[SiStripDetVOffBuilder::getCoralTime] Converting CondTime into CoralTime: "
0487          << " condTime = " << iovSec << " - " << iovNanoSec << " getCondTime(coralTime) = " << (testTime >> 32) << " - "
0488          << (testTime & 0xFFFFFFFF) << endl;
0489   }
0490 
0491   return coralTime;
0492 }
0493 
0494 void SiStripDetVOffBuilder::removeDuplicates(std::vector<uint32_t>& vec) {
0495   std::sort(vec.begin(), vec.end());
0496   std::vector<uint32_t>::iterator it = std::unique(vec.begin(), vec.end());
0497   vec.resize(it - vec.begin());
0498 }
0499 
0500 void SiStripDetVOffBuilder::setLastSiStripDetVOff(SiStripDetVOff* lastPayload, cond::Time_t lastTimeStamp) {
0501   lastStoredCondObj.first = lastPayload;
0502   lastStoredCondObj.second = lastTimeStamp;
0503 }
0504 
0505 cond::Time_t SiStripDetVOffBuilder::findMostRecentTimeStamp(const std::vector<coral::TimeStamp>& coralDate) {
0506   cond::Time_t latestDate = getCondTime(coralDate[0]);
0507 
0508   if (debug_) {
0509     std::cout << "latestDate: condTime = " << (latestDate >> 32) << " - "
0510               << (latestDate & 0xFFFFFFFF)
0511               //<< " coralTime= " << coralDate[0]
0512               << std::endl;
0513   }
0514 
0515   for (unsigned int i = 1; i < coralDate.size(); i++) {
0516     cond::Time_t testDate = getCondTime(coralDate[i]);
0517     if (testDate > latestDate) {
0518       latestDate = testDate;
0519     }
0520   }
0521   return latestDate;
0522 }
0523 
0524 void SiStripDetVOffBuilder::reduce(std::vector<std::pair<SiStripDetVOff*, cond::Time_t> >::iterator& it,
0525                                    std::vector<std::pair<SiStripDetVOff*, cond::Time_t> >::iterator& initialIt,
0526                                    std::vector<std::pair<SiStripDetVOff*, cond::Time_t> >& resultVec,
0527                                    const bool last) {
0528   //const bool last is set to false by default in the header file...
0529   int first = 0;
0530   // Check if it is the first
0531   if (distance(resultVec.begin(), initialIt) == 0) {
0532     first = 1;
0533   }
0534 
0535   if (debug_ && (it->first->getLVoffCounts() - initialIt->first->getLVoffCounts() == 0) &&
0536       (it->first->getHVoffCounts() - initialIt->first->getHVoffCounts() == 0)) {
0537     cout << "Same number of LV and HV at start and end of sequence: LV off = " << it->first->getLVoffCounts()
0538          << " HV off = " << it->first->getHVoffCounts() << endl;
0539   }
0540 
0541   // if it was going off
0542   if ((it->first->getLVoffCounts() - initialIt->first->getLVoffCounts() > 0) ||
0543       (it->first->getHVoffCounts() - initialIt->first->getHVoffCounts() > 0)) {
0544     // Set the time of the current (last) iov as the time of the initial iov of the sequence
0545     // replace the first iov with the last one
0546     //Naughty use of const bool last... by default it is false (=0), and for the case of the last timestamp in the query results it is set to true(=1) in the call
0547     (it + last)->second = (initialIt)->second;
0548     discardIOVs(it, initialIt, resultVec, last, 0);
0549     if (debug_)
0550       cout << "Reducing IOV sequence (going off)" << endl;
0551   }
0552   // if it was going on
0553   else if ((it->first->getLVoffCounts() - initialIt->first->getLVoffCounts() <= 0) ||
0554            (it->first->getHVoffCounts() - initialIt->first->getHVoffCounts() <= 0)) {
0555     // replace the last minus one iov with the first one
0556     discardIOVs(it, initialIt, resultVec, last, first);
0557     if (debug_)
0558       cout << "Reducing IOV sequence (going on)" << endl;
0559   }
0560 }
0561 
0562 void SiStripDetVOffBuilder::discardIOVs(std::vector<std::pair<SiStripDetVOff*, cond::Time_t> >::iterator& it,
0563                                         std::vector<std::pair<SiStripDetVOff*, cond::Time_t> >::iterator& initialIt,
0564                                         std::vector<std::pair<SiStripDetVOff*, cond::Time_t> >& resultVec,
0565                                         const bool last,
0566                                         const unsigned int first) {
0567   if (debug_) {
0568     cout << "first (1->means the sequence started at the first timestamp in the query results, 0-> that it did not)= "
0569          << first << endl;
0570     cout << "initial->first (initial SiStripDetVOff object of the IOV sequence)= " << initialIt->first
0571          << ", second (initial timestamp of the IOV sequence) = " << initialIt->second << endl;
0572     cout << "last (0->means that the sequence is not ending with the last item in the query results, 1-> that it "
0573             "DOES!)= "
0574          << last << endl;
0575   }
0576   if (last == true) {
0577     resultVec.erase(initialIt + first, it + 1);
0578     // Minus 2 because it will be incremented at the end of the loop becoming end()-1.
0579     it = resultVec.end() - 2;
0580   } else {
0581     it = resultVec.erase(initialIt + first, it);
0582   }
0583 }
0584 
0585 //This is the method that (called by GetModulesOff, declared in the header file) executes the reduction by massaging modulesOff
0586 void SiStripDetVOffBuilder::reduction(const uint32_t deltaTmin, const uint32_t maxIOVlength) {
0587   int count = 0;
0588   std::vector<std::pair<SiStripDetVOff*, cond::Time_t> >::iterator initialIt;
0589 
0590   int resultVecSize = modulesOff.size();
0591   int resultsIndex = 0;
0592 
0593   if (resultVecSize > 1) {
0594     std::vector<std::pair<SiStripDetVOff*, cond::Time_t> >::iterator it = modulesOff.begin();
0595     for (; it != modulesOff.end() - 1; ++it, ++resultsIndex) {
0596       unsigned long long deltaT = ((it + 1)->second - it->second) >> 32;
0597       unsigned long long deltaTsequence = 0;
0598       if (count > 1) {
0599         deltaTsequence = ((it + 1)->second - initialIt->second) >> 32;
0600       }
0601       // Save the initial pair
0602       if ((deltaT < deltaTmin) && ((count == 0) || (deltaTsequence < maxIOVlength))) {
0603         // If we are not in a the sequence
0604         if (count == 0) {
0605           initialIt = it;
0606         }
0607         // Increase the counter in any case.
0608         ++count;
0609       }
0610       // We do it only if the sequence is bigger than two cases
0611       else if (count > 1) {
0612         reduce(it, initialIt, modulesOff);
0613         // reset all
0614         count = 0;
0615       } else {
0616         // reset all
0617         count = 0;
0618       }
0619       // Border case
0620       if (resultsIndex == resultVecSize - 2 && count != 0) {
0621         reduce(it, initialIt, modulesOff, true);
0622       }
0623     }
0624   }
0625 }
0626 
0627 void SiStripDetVOffBuilder::statusChange(cond::Time_t& lastTime, TimesAndValues& tStruct) {
0628   // Setting tmin to the last value IOV of the database tag
0629   if (lastTime > 0) {
0630     tmin = getCoralTime(lastTime);
0631   }
0632 
0633   coralInterface->doQuery(whichTable, tmin, tmax, tStruct.changeDate, tStruct.actualValue, tStruct.dpname);
0634   //UNIT TEST DEBUG to bypass the query wait time!!!
0635   //coral::TimeStamp testtime=getCoralTime(lastTime);
0636   //tStruct.changeDate.push_back(testtime);
0637   //tStruct.actualValue.push_back(1.);
0638   //tStruct.dpname.push_back("cms_trk_dcs_03:CAEN/CMS_TRACKER_SY1527_3/branchController00/easyCrate3/easyBoard17/channel002");
0639 
0640   // preset the size of the status vector
0641   tStruct.actualStatus.resize(tStruct.actualValue.size());
0642   tStruct.actualStatus.clear();
0643 
0644   for (float val : tStruct.actualValue) {
0645     tStruct.actualStatus.push_back(static_cast<int>(val));
0646   }
0647 }
0648 
0649 void SiStripDetVOffBuilder::lastValue(TimesAndValues& tStruct) {
0650   coralInterface->doQuery(whichTable, tmin, tmax, tStruct.changeDate, tStruct.actualValue, tStruct.dpname);
0651 
0652   tStruct.latestTime = findMostRecentTimeStamp(tStruct.changeDate);
0653 
0654   // preset the size of the status vector
0655   tStruct.actualStatus.resize(tStruct.actualValue.size());
0656 
0657   // retrieve the channel settings from the PVSS DB
0658   std::vector<coral::TimeStamp> settingDate;
0659   std::vector<float> settingValue;
0660   std::vector<std::string> settingDpname;
0661   std::vector<uint32_t> settingDpid;
0662   coralInterface->doSettingsQuery(tsetmin, tmax, settingDate, settingValue, settingDpname, settingDpid);
0663   LogDebug("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::BuildDetVOff]: Channel settings retrieved";
0664   LogDebug("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::BuildDetVOff]: Number of PSU channels: "
0665                                     << settingDpname.size();
0666 
0667   unsigned int missing = 0;
0668   std::stringstream ss;
0669   for (unsigned int j = 0; j < tStruct.dpname.size(); j++) {
0670     int setting = findSetting(tStruct.dpname[j], tStruct.changeDate[j], settingDpname, settingDate);
0671     if (setting >= 0) {
0672       if (tStruct.actualValue[j] > (highVoltageOnThreshold_ * (settingValue[setting]))) {
0673         tStruct.actualStatus[j] = 1;
0674       } else {
0675         tStruct.actualStatus[j] = 0;
0676       }
0677     } else {
0678       tStruct.actualStatus[j] = -1;
0679       missing++;
0680       ss << "Channel = " << tStruct.dpname[j] << std::endl;
0681     }
0682   }
0683   LogDebug("SiStripDetVOffBuilder")
0684       << "[SiStripDetVOffBuilder::BuildDetVOff]: Number of channels with no setting information " << missing;
0685   LogDebug("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::BuildDetVOff]: Number of entries in dpname vector "
0686                                     << tStruct.dpname.size();
0687 }
0688 
0689 void SiStripDetVOffBuilder::lastValueFromFile(TimesAndValues& tStruct) {
0690   readLastValueFromFile(tStruct.dpid, tStruct.actualValue, tStruct.changeDate);
0691   tStruct.latestTime = findMostRecentTimeStamp(tStruct.changeDate);
0692   LogDebug("SiStripDetVOffBuilder")
0693       << "[SiStripDetVOffBuilder::BuildDetVOff]: File access complete \n\t Number of values read from file: "
0694       << tStruct.dpid.size();
0695 
0696   // retrieve the channel settings from the PVSS DB
0697   std::vector<coral::TimeStamp> settingDate;
0698   std::vector<float> settingValue;
0699   std::vector<std::string> settingDpname;
0700   std::vector<uint32_t> settingDpid;
0701 
0702   coralInterface->doSettingsQuery(tsetmin, tmax, settingDate, settingValue, settingDpname, settingDpid);
0703   LogDebug("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::BuildDetVOff]: Channel settings retrieved";
0704   LogDebug("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::BuildDetVOff]: Number of PSU channels: "
0705                                     << settingDpname.size();
0706 
0707   unsigned int missing = 0;
0708   std::stringstream ss;
0709   // need to get the PSU channel names from settings
0710   tStruct.dpname.clear();
0711   tStruct.dpname.resize(tStruct.dpid.size());
0712   for (unsigned int j = 0; j < tStruct.dpid.size(); j++) {
0713     int setting = findSetting(tStruct.dpid[j], tStruct.changeDate[j], settingDpid, settingDate);
0714     if (setting >= 0) {
0715       if (tStruct.actualValue[j] > (highVoltageOnThreshold_ * settingValue[setting])) {
0716         tStruct.actualStatus[j] = 1;
0717       } else {
0718         tStruct.actualStatus[j] = 0;
0719       }
0720       tStruct.dpname[j] = settingDpname[setting];
0721     } else {
0722       tStruct.actualStatus[j] = -1;
0723       tStruct.dpname[j] = "UNKNOWN";
0724       missing++;
0725       ss << "DP ID = " << tStruct.dpid[j] << std::endl;
0726     }
0727   }
0728   LogDebug("SiStripDetVOffBuilder") << "Number of missing psu channels = " << missing << std::endl;
0729   LogDebug("SiStripDetVOffBuilder") << "IDs are: = " << ss.str();
0730 }
0731 
0732 string SiStripDetVOffBuilder::timeToStream(const cond::Time_t& condTime, const string& comment) {
0733   stringstream ss;
0734   ss << comment << (condTime >> 32) << " - " << (condTime & 0xFFFFFFFF) << std::endl;
0735   return ss.str();
0736 }
0737 
0738 string SiStripDetVOffBuilder::timeToStream(const coral::TimeStamp& coralTime, const string& comment) {
0739   stringstream ss;
0740   ss << "Starting from IOV time in the database : year = " << coralTime.year() << ", month = " << coralTime.month()
0741      << ", day = " << coralTime.day() << ", hour = " << coralTime.hour() << ", minute = " << coralTime.minute()
0742      << ", second = " << coralTime.second() << ", nanosecond = " << coralTime.nanosecond() << std::endl;
0743   return ss.str();
0744 }
0745 bool SiStripDetVOffBuilder::FileExists(string FileName) {
0746   //Helper method to check if local files exist (needed to handle HVUnmapped, HVCrosstalking modules)
0747   struct stat FileInfo;
0748   bool Existence;
0749   int Stat;
0750   //Try to get file attributes
0751   Stat = stat(FileName.c_str(), &FileInfo);
0752   if (Stat == 0) {
0753     Existence = true;
0754   } else {
0755     Existence = false;
0756   }
0757   return Existence;
0758 }
0759 
0760 void SiStripDetVOffBuilder::buildPSUdetIdMap(TimesAndValues& psuStruct, DetIdListTimeAndStatus& detIdStruct)
0761 //This function builds a PSU to DetID map one way or the other. Then it processes the psuStruct that contains
0762 //the results of the CAEN status query to the Online DB, filling the detIdStruct with the detIDs corresponding
0763 //to the PSU (channel in some cases, PSU only in others) reported in the CAEN status query to the Online DB.
0764 //It may make sense to split this method eventually.
0765 {
0766   SiStripPsuDetIdMap map_;
0767   if (psuDetIdMapFile_.empty()) {
0768     std::cout << "PLEASE provide the name of a valid PSUDetIDMapFile in the cfg: currently still necessary to have a "
0769                  "file, soon will access the info straight from the DB!"
0770               << endl;
0771     //map_.BuildMap();//This method is not currently used (it would try to build a map based on a query to SiStripConfigDB, and the info there is STALE!)
0772   } else {
0773     map_.BuildMap(psuDetIdMapFile_, debug_);  //This is the method used to build the map.
0774   }
0775   LogTrace("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::BuildDetVOff] PSU(Channel)-detID map(s) built";
0776   //Following method to be replaced by printMaps... to print all 4 maps built!
0777   map_.printMap();  //This method prints to the info.log file, notice that it is overwritten by each individual O2O job running in the same dir.
0778 
0779   // use map info to build input for list of objects
0780   // no need to check for duplicates, as put method for SiStripDetVOff checks for you!
0781 
0782   //Debug variables
0783   unsigned int ch0bad = 0, ch1bad = 0, ch2bad = 0, ch3bad = 0;
0784   std::vector<unsigned int> numLvBad, numHvBad;
0785 
0786   //Create 2 extra maps that we'll use to keep track of unmapped and crosstalking detids when turning ON and OFF HV:
0787   //-unmapped need to be both turned OFF when any HV goes OFF and to be turned ON when both are ON
0788   //-crosstaling need to be both turned ON when any HV goes ON and to be turned OFF ONLY when BOTH are OFF.
0789   std::map<std::string, bool> UnmappedState, CrosstalkingState;
0790   //Get the HVUnmapped map from the map, so that we can set know which PSU are unmapped:
0791   std::map<std::string, std::vector<uint32_t> > UnmappedPSUs = map_.getHVUnmappedMap();
0792   //Check here if there is a file already, otherwise initialize to OFF all channels in these PSU!
0793   if (FileExists("HVUnmappedChannelState.dat")) {
0794     std::cout << "File HVUnmappedChannelState.dat exists!" << std::endl;
0795     std::ifstream ifs("HVUnmappedChannelState.dat");
0796     string line;
0797     while (getline(ifs, line)) {
0798       if (!line.empty()) {
0799         // split the line and insert in the map
0800         stringstream ss(line);
0801         string PSUChannel;
0802         bool HVStatus;
0803         ss >> PSUChannel;
0804         ss >> HVStatus;
0805         //Extract the PSU from the PSUChannel (since the HVUnmapped_Map uses PSU as key
0806         std::string PSU = PSUChannel.substr(0, PSUChannel.size() - 10);
0807         //Look for the PSU in the unmapped map!
0808         std::map<std::string, std::vector<uint32_t> >::iterator iter = UnmappedPSUs.find(PSU);
0809         if (iter != UnmappedPSUs.end()) {
0810           UnmappedState[PSUChannel] = HVStatus;
0811         } else {
0812           std::cout << "WARNING!!! There are channels in the local file with the channel status for HVUnmapped "
0813                        "channels, that ARE NOT CONSIDERED AS UNMAPPED in the current map!"
0814                     << std::endl;
0815         }
0816       }
0817     }  //End of the while loop reading and initializing UnmappedState map from file
0818     //Extra check:
0819     //Should check if there any HVUnmapped channels in the map that are not listed in the local file!
0820     bool MissingChannels = false;
0821     for (std::map<std::string, vector<uint32_t> >::iterator it = UnmappedPSUs.begin(); it != UnmappedPSUs.end(); it++) {
0822       std::string chan002 = it->first + "channel002";
0823       std::string chan003 = it->first + "channel003";
0824       std::map<std::string, bool>::iterator iter = UnmappedState.find(chan002);
0825       if (iter == UnmappedState.end()) {
0826         std::cout << "ERROR! The local file with the channel status for HVUnmapped channels IS MISSING one of the "
0827                      "following unmapped channel voltage status information:"
0828                   << std::endl;
0829         std::cout << chan002 << std::endl;
0830         MissingChannels = true;
0831       }
0832       iter = UnmappedState.find(chan003);
0833       if (iter == UnmappedState.end()) {
0834         std::cout << "ERROR! The local file with the channel status for HVUnmapped channels IS MISSING one of the "
0835                      "following unmapped channel voltage status information:"
0836                   << std::endl;
0837         std::cout << chan003 << std::endl;
0838         MissingChannels = true;
0839       }
0840     }
0841     //Now if any channel WAS missing, exit!
0842     if (MissingChannels) {
0843       std::cout << "!!!!\n"
0844                 << "Exiting now... please check the local HVUnmappedChannelState.dat and the mapfile you provided ("
0845                 << psuDetIdMapFile_ << ")" << std::endl;
0846       exit(1);
0847     }
0848   } else {  //If the file HVUnmappedChannelState.dat does not exist, initialize the map to all OFF.
0849     //(see below for creating the file at the end of the execution with the latest state of unmapped channels.
0850     for (std::map<std::string, vector<uint32_t> >::iterator it = UnmappedPSUs.begin(); it != UnmappedPSUs.end(); it++) {
0851       std::string chan002 = it->first + "channel002";
0852       std::string chan003 = it->first + "channel003";
0853       UnmappedState[chan002] = false;
0854       UnmappedState[chan003] = false;
0855     }
0856   }
0857   //Get the HVCrosstalking map from the map, so that we can set know which PSU are crosstalking:
0858   std::map<std::string, std::vector<uint32_t> > CrosstalkingPSUs = map_.getHVCrosstalkingMap();
0859   //Check here if there is a file already, otherwise initialize to OFF all channels in these PSU!
0860   if (FileExists("HVCrosstalkingChannelState.dat")) {
0861     std::cout << "File HVCrosstalkingChannelState.dat exists!" << std::endl;
0862     std::ifstream ifs("HVCrosstalkingChannelState.dat");
0863     string line;
0864     while (getline(ifs, line)) {
0865       if (!line.empty()) {
0866         // split the line and insert in the map
0867         stringstream ss(line);
0868         string PSUChannel;
0869         bool HVStatus;
0870         ss >> PSUChannel;
0871         ss >> HVStatus;
0872         //Extract the PSU from the PSUChannel (since the HVCrosstalking_Map uses PSU as key
0873         std::string PSU = PSUChannel.substr(0, PSUChannel.size() - 10);
0874         //Look for the PSU in the unmapped map!
0875         std::map<std::string, std::vector<uint32_t> >::iterator iter = CrosstalkingPSUs.find(PSU);
0876         if (iter != CrosstalkingPSUs.end()) {
0877           CrosstalkingState[PSUChannel] = HVStatus;
0878         } else {
0879           std::cout << "WARNING!!! There are channels in the local file with the channel status for HVUnmapped "
0880                        "channels, that ARE NOT CONSIDERED AS UNMAPPED in the current map!"
0881                     << std::endl;
0882         }
0883       }
0884     }  //End of the while loop reading and initializing CrosstalkingState map from file
0885     //Extra check:
0886     //Should check if there any HVCrosstalking channels in the map that are not listed in the local file!
0887     bool MissingChannels = false;
0888     for (std::map<std::string, vector<uint32_t> >::iterator it = CrosstalkingPSUs.begin(); it != CrosstalkingPSUs.end();
0889          it++) {
0890       std::string chan002 = it->first + "channel002";
0891       std::string chan003 = it->first + "channel003";
0892       std::map<std::string, bool>::iterator iter = CrosstalkingState.find(chan002);
0893       if (iter == CrosstalkingState.end()) {
0894         std::cout << "ERROR! The local file with the channel status for HVCrosstalking channels IS MISSING one of the "
0895                      "following unmapped channel voltage status information:"
0896                   << std::endl;
0897         std::cout << chan002 << std::endl;
0898         MissingChannels = true;
0899       }
0900       iter = CrosstalkingState.find(chan003);
0901       if (iter == CrosstalkingState.end()) {
0902         std::cout << "ERROR! The local file with the channel status for HVCrosstalking channels IS MISSING one of the "
0903                      "following unmapped channel voltage status information:"
0904                   << std::endl;
0905         std::cout << chan003 << std::endl;
0906         MissingChannels = true;
0907       }
0908     }
0909     //Now if any channel WAS missing, exit!
0910     if (MissingChannels) {
0911       std::cout << "!!!!\n"
0912                 << "Exiting now... please check the local HVCrosstalkingChannelState.dat and the mapfile you provided ("
0913                 << psuDetIdMapFile_ << ")" << std::endl;
0914       exit(1);
0915     }
0916   } else {  //If the file HVCrosstalkingChannelState.dat does not exist, initialize the map to all OFF.
0917     //(see below for creating the file at the end of the execution with the latest state of unmapped channels.
0918     for (std::map<std::string, vector<uint32_t> >::iterator it = CrosstalkingPSUs.begin(); it != CrosstalkingPSUs.end();
0919          it++) {
0920       std::string chan002 = it->first + "channel002";
0921       std::string chan003 = it->first + "channel003";
0922       CrosstalkingState[chan002] = false;
0923       CrosstalkingState[chan003] = false;
0924     }
0925   }
0926 
0927   if (debug_) {
0928     //print out the UnmappedState map:
0929     std::cout << "Printing the UnmappedChannelState initial map:" << std::endl;
0930     std::cout << "PSUChannel\t\tHVON?(true or false)" << std::endl;
0931     for (std::map<std::string, bool>::iterator it = UnmappedState.begin(); it != UnmappedState.end(); it++) {
0932       std::cout << it->first << "\t\t" << it->second << std::endl;
0933     }
0934     //print out the CrosstalkingState map:
0935     std::cout << "Printing the CrosstalkingChannelState initial map:" << std::endl;
0936     std::cout << "PSUChannel\t\tHVON?(true or false)" << std::endl;
0937     for (std::map<std::string, bool>::iterator it = CrosstalkingState.begin(); it != CrosstalkingState.end(); it++) {
0938       std::cout << it->first << "\t\t" << it->second << std::endl;
0939     }
0940   }
0941 
0942   //Loop over the psuStruct (DB query results), lopping over the PSUChannels
0943   //This will probably change int he future when we will change the query itself
0944   //to report directly the detIDs associated with a channel
0945   //Probably we will report in the query results the detID, the changeDate
0946   //and whether the channel is HV mapped, HV unmapped, HV crosstalking using a flag...
0947   for (unsigned int dp = 0; dp < psuStruct.dpname.size(); dp++) {
0948     //FIX ME:
0949     //Check if the following if condition can EVER be true!
0950     std::string PSUChannel = psuStruct.dpname[dp];
0951     if (PSUChannel != "UNKNOWN") {
0952       // figure out the channel and the PSU individually
0953       std::string Channel =
0954           PSUChannel.substr(PSUChannel.size() - 10);  //Channel is the channel, i.e. channel000, channel001 etc
0955       std::string PSU = PSUChannel.substr(0, PSUChannel.size() - 10);
0956 
0957       // Get the detIDs corresponding to the given PSU channel using the getDetID function of SiStripPsuDetIdMap.cc
0958       //NOTA BENE
0959       //Need to make sure the information is treated consistently here:
0960       //The map by convention has
0961       //detID-> channel002 or channel003 IF the channel is HV mapped,
0962       //detID->channel000 if it is not HV mapped
0963       //We want to differentiate the behavior depending on the status reported for the channel for channels that are unmapped!
0964       //1-if the channel is turning OFF (!=1) then we want to report all detIDs for that channel and all detIDs that are listed as channel000 for that PSU.
0965       //2-if the channel is turning ON (==1) then we want to turn on all detIDs for that channel but turn on all detIDs listed as channel000 for that PSU ONLY IF BOTH channel002 and channel003 are BOTH ON!
0966       //Need to handle the case of coupled Power supplies (that only turn off when both are turned off).
0967 
0968       //Fixed SiStripPSUdetidMap.cc to make sure now getDetID gets the correct list of detIDs:
0969       //-for channels 000/001 all the detIDs connected to the PSU
0970       //-for channels 002/003 HV1/HV2 modules only (exclusively)
0971       //UPDATE for HV channels:
0972       //actually fixed it to report also detIDs listed as
0973       //channel000 on the same supply of channel002 or channel003
0974       //and the crosstalking ones (channel999) too..
0975 
0976       //Get the detIDs associated with the DPNAME (i.e. PSUChannel) reported by the query
0977       //Declare the vector to be passed as reference parameters to the getDetID method
0978       //std::vector<uint32_t> ids,unmapped_ids,crosstalking_ids;
0979       std::vector<uint32_t> ids;
0980       //map_.getDetID(PSUChannel, debug_, ids, unmapped_ids, crosstalking_ids);
0981       //Actually the method above is a bit of an overkill, we could already use the individual methods:
0982       //getLvDetID
0983       //getHvDetID
0984 
0985       //Declaring the two vector needed for the HV case in this scope.
0986       std::vector<uint32_t> unmapped_ids, crosstalking_ids;
0987       bool LVCase;
0988       //LV CASE
0989       if (Channel == "channel000" || Channel == "channel001") {
0990         LVCase = true;
0991         ids = map_.getLvDetID(
0992             PSU);  //Since in the LV case only 1 list of detids is returned (unmapped and crosstalking are irrelevant for LV) return the vector directly
0993       }
0994       //HV CASE
0995       else {  //if (Channel=="channel002" || Channel=="channel003") {
0996         LVCase = false;
0997         map_.getHvDetID(PSUChannel,
0998                         ids,
0999                         unmapped_ids,
1000                         crosstalking_ids);  //In the HV case since 3 vectors are filled, use reference parameters
1001       }
1002 
1003       if (debug_) {
1004         cout << "dpname[" << dp << "] = " << PSUChannel << ", for time = " << timeToStream(psuStruct.changeDate[dp])
1005              << endl;
1006         if (!ids.empty()) {
1007           if (Channel == "channel000" || Channel == "channel001") {
1008             cout << "Corresponding to LV (PSU-)matching detids: " << endl;
1009             for (unsigned int i_detid = 0; i_detid < ids.size(); i_detid++) {
1010               cout << ids[i_detid] << std::endl;
1011             }
1012           } else {
1013             cout << "Corresponding to straight HV matching detids: " << endl;
1014             for (unsigned int i_detid = 0; i_detid < ids.size(); i_detid++) {
1015               cout << ids[i_detid] << std::endl;
1016             }
1017           }
1018         }
1019         //The unmapped_ids and crosstalking_ids are only filled for HV channels!
1020         if (!unmapped_ids.empty()) {
1021           cout << "Corresponding to HV unmapped (PSU-)matching detids: " << endl;
1022           for (unsigned int i_detid = 0; i_detid < unmapped_ids.size(); i_detid++) {
1023             cout << unmapped_ids[i_detid] << std::endl;
1024           }
1025         }
1026         if (!crosstalking_ids.empty()) {
1027           cout << "Corresponding to HV crosstalking (PSU-)matching detids: " << endl;
1028           for (unsigned int i_detid = 0; i_detid < crosstalking_ids.size(); i_detid++) {
1029             cout << crosstalking_ids[i_detid] << std::endl;
1030           }
1031         }
1032       }
1033 
1034       //NOW implement the new logic using the detids, unmapped_detids, crosstalking_detids!
1035 
1036       //First check whether the channel we're looking at is turning OFF or turning ON!
1037 
1038       //TURN OFF case:
1039       if (psuStruct.actualStatus[dp] != 1) {
1040         //Behavior is different for LV vs HV channels:
1041         //LV case:
1042         if (LVCase) {
1043           //Turn OFF all:
1044           //-positively matching
1045           //-unmapped matching
1046           //-crosstalking
1047           //for the LV case all the detids are automatically reported in the ids vector
1048           //unmapped and crosstalking are only differentiated (relevant) for HV.
1049           if (!ids.empty()) {
1050             //debug variables increment
1051             ch0bad++;
1052             ch1bad++;
1053 
1054             //Create a pair with the relevant detIDs (vector) and its timestamp
1055             //And put it in the detidV vector of the detIdStruct that will contain all the
1056             //results
1057             detIdStruct.detidV.push_back(std::make_pair(ids, psuStruct.changeDate[dp]));
1058 
1059             //Set the status to OFF
1060             detIdStruct.StatusGood.push_back(false);
1061 
1062             //debug variable population
1063             numLvBad.insert(numLvBad.end(), ids.begin(), ids.end());
1064 
1065             //Set the flag for LV/HV:
1066             detIdStruct.isHV.push_back(0);  //LV
1067 
1068             //Set the PSUChannel (I guess for debug purposes?)
1069             detIdStruct.psuName.push_back(PSUChannel);
1070           }
1071         }
1072         //HV case:
1073         else {  //if (!LVCase) {
1074           //Debug variables increment:
1075           if (!ids.empty() || !unmapped_ids.empty() || !crosstalking_ids.empty()) {
1076             if (Channel == "channel002") {
1077               ch2bad++;
1078             } else if (Channel == "channel003") {
1079               ch3bad++;
1080             }
1081           }
1082           //First sum the ids (positively matching detids) and the unmapped_ids (since both should be TURNED OFF):
1083           std::vector<uint32_t> OFFids;
1084           OFFids.insert(OFFids.end(), ids.begin(), ids.end());                    //Add the ids (if any!)
1085           OFFids.insert(OFFids.end(), unmapped_ids.begin(), unmapped_ids.end());  //Add the unmapped_ids (if any!)
1086           //Now for the cross-talking ids this is a bit more complicated!
1087           if (!crosstalking_ids
1088                    .empty()) {  //This already means that the PSUChannel is one of the crosstalking ones (even if only a few modules in that PSU are showing crosstalking behavior both its channels have to be considered crosstalking of course!
1089             //Set the channel OFF in the CrosstalkingState map!
1090             CrosstalkingState[PSUChannel] = false;  //Turn OFF the channel in the state map!
1091 
1092             //Need to check if both channels (HV1==channel002 or HV2==channel003) are OFF!
1093             if (!CrosstalkingState[PSUChannel.substr(0, PSUChannel.size() - 1) + "2"] &&
1094                 !CrosstalkingState[PSUChannel.substr(0, PSUChannel.size() - 1) + "3"]) {  //if HV1 & HV2 both OFF (false)
1095               OFFids.insert(
1096                   OFFids.end(),
1097                   crosstalking_ids.begin(),
1098                   crosstalking_ids.end());  //Add the crosstalking_ids (if any!) since both HV1 and HV2 are OFF!
1099               if (debug_) {
1100                 std::cout << "Adding the unmapped detids corresponding to (HV1/2 cross-talking) PSU "
1101                           << PSUChannel.substr(0, PSUChannel.size() - 10) << " to the list of detids turning OFF"
1102                           << std::endl;
1103               }
1104             }
1105           }
1106           //Handle the crosstalking channel by setting it to OFF in the CrosstalkingState map!
1107           if (!unmapped_ids
1108                    .empty()) {  //This already means that the PSUChannel is one of the unmapped ones (even if only a few modules in that PSU are unmapped both its channels have to be considered crosstalking of course!
1109             UnmappedState[PSUChannel] = false;  //Turn OFF the channel in the state map!
1110           }
1111           if (!OFFids.empty()) {
1112             //Create a pair with the relevant detIDs (vector) and its timestamp
1113             //And put it in the detidV vector of the detIdStruct that will contain all the
1114             //results
1115 
1116             //Going OFF HV:
1117             //report not only ids, but also unmapped_ids.
1118             //have to handle crosstalking_ids here... (only OFF if they corresponding PSU HV1/HV2 is off already...
1119             //then add all three vectors to the pair below...
1120             detIdStruct.detidV.push_back(std::make_pair(OFFids, psuStruct.changeDate[dp]));
1121 
1122             //Set the status to OFF
1123             detIdStruct.StatusGood.push_back(false);
1124 
1125             //debug variable population
1126             numHvBad.insert(numHvBad.end(), ids.begin(), ids.end());
1127 
1128             //Set the flag for LV/HV:
1129             detIdStruct.isHV.push_back(1);  //HV
1130 
1131             //Set the PSUChannel (I guess for debug purposes?)
1132             detIdStruct.psuName.push_back(PSUChannel);
1133           }
1134         }
1135       }
1136       //TURNING ON CASE
1137       else {
1138         //Implement the rest of the logic!
1139         //Behavior is different for LV vs HV channels:
1140         //LV case:
1141         if (LVCase) {
1142           //Turn ON all (PSU)matching detids:
1143           //for the LV case all the detids are automatically reported in the ids vector
1144           //unmapped and crosstalking are only differentiated (relevant) for HV.
1145           if (!ids.empty()) {
1146             //Create a pair with the relevant detIDs (vector) and its timestamp
1147             //And put it in the detidV vector of the detIdStruct that will contain all the
1148             //results
1149             detIdStruct.detidV.push_back(std::make_pair(ids, psuStruct.changeDate[dp]));
1150 
1151             //Set the status to ON
1152             detIdStruct.StatusGood.push_back(true);
1153 
1154             //Set the flag for LV/HV:
1155             detIdStruct.isHV.push_back(0);  //LV
1156 
1157             //Set the PSUChannel (I guess for debug purposes?)
1158             detIdStruct.psuName.push_back(PSUChannel);
1159           }
1160         }
1161         //HV case:
1162         else {  //if (!LVCase) {
1163           //First sum the ids (positively matching detids) and the crosstalking_ids (since all ids on a crosstalking PSU should be TURNED ON when at least one HV channel is ON):
1164           std::vector<uint32_t> ONids;
1165           ONids.insert(ONids.end(), ids.begin(), ids.end());  //Add the ids (if any!)
1166           ONids.insert(
1167               ONids.end(), crosstalking_ids.begin(), crosstalking_ids.end());  //Add the crosstalking_ids (if any!)
1168           //Now for the unmapped ids this is a bit more complicated!
1169           if (!unmapped_ids
1170                    .empty()) {  //This already means that the PSUChannel is one of the unmapped ones (even if only a few modules in that PSU are unmapped both its channels have to be considered unmapped of course!
1171             //Set the HV1 channel on in the UnmappedState map!
1172             UnmappedState[PSUChannel] = true;  //Turn ON the channel in the state map!
1173 
1174             //Need to check if BOTH channels (HV1==channel002 or HV2==channel003) are ON!
1175             if (UnmappedState[PSUChannel.substr(0, PSUChannel.size() - 1) + "2"] &&
1176                 UnmappedState[PSUChannel.substr(0, PSUChannel.size() - 1) + "3"]) {  //if HV1 & HV2 are both ON (true)
1177               ONids.insert(ONids.end(),
1178                            unmapped_ids.begin(),
1179                            unmapped_ids.end());  //Add the unmapped_ids (if any!) since both HV1 and HV2 are ON!
1180               if (debug_) {
1181                 std::cout << "Adding the detids corresponding to HV-unmapped PSU "
1182                           << PSUChannel.substr(0, PSUChannel.size() - 10) << " to the list of detids turning ON"
1183                           << std::endl;
1184               }
1185             }
1186           }
1187           //Handle the crosstalking channel by setting it to OFF in the CrosstalkingState map!
1188           if (!crosstalking_ids
1189                    .empty()) {  //This already means that the PSUChannel is one of the crosstalking ones (even if only a few modules in that PSU are showing crosstalking behavior both its channels have to be considered crosstalking of course!
1190             CrosstalkingState[PSUChannel] = true;  //Turn ON the channel in the state map!
1191           }
1192           if (!ONids.empty()) {
1193             //Create a pair with the relevant detIDs (vector) and its timestamp
1194             //And put it in the detidV vector of the detIdStruct that will contain all the
1195             //results
1196 
1197             //Going OFF HV:
1198             //report not only ids, but also unmapped_ids.
1199             //have to handle crosstalking_ids here... (only OFF if they corresponding PSU HV1/HV2 is off already...
1200             //then add all three vectors to the pair below...
1201             detIdStruct.detidV.push_back(std::make_pair(ONids, psuStruct.changeDate[dp]));
1202 
1203             //Set the status to ON
1204             detIdStruct.StatusGood.push_back(true);
1205 
1206             //Set the flag for LV/HV:
1207             detIdStruct.isHV.push_back(1);  //HV
1208 
1209             //Set the PSUChannel (I guess for debug purposes?)
1210             detIdStruct.psuName.push_back(PSUChannel);
1211           }
1212         }
1213       }
1214     }  //End of if dpname not "UNKNOWN"
1215     else {
1216       //if (debug) {
1217       //std::cout<<"PSU Channel name WAS NOT RECOGNIZED"<<std::endl;
1218       //}
1219       detIdStruct.notMatched++;
1220     }
1221   }  //End of the loop over all PSUChannels reported by the DB query.
1222   //At this point we need to (over)write the 2 files that will keep the HVUnmapped and HVCrosstalking channels status:
1223   std::ofstream ofsUnmapped("HVUnmappedChannelState.dat");
1224   for (std::map<std::string, bool>::iterator it = UnmappedState.begin(); it != UnmappedState.end(); it++) {
1225     ofsUnmapped << it->first << "\t" << it->second << std::endl;
1226   }
1227   std::ofstream ofsCrosstalking("HVCrosstalkingChannelState.dat");
1228   for (std::map<std::string, bool>::iterator it = CrosstalkingState.begin(); it != CrosstalkingState.end(); it++) {
1229     ofsCrosstalking << it->first << "\t" << it->second << std::endl;
1230   }
1231 
1232   removeDuplicates(numLvBad);
1233   removeDuplicates(numHvBad);
1234 
1235   // useful debugging stuff!
1236   if (debug_) {
1237     std::cout << "Number of channels that turned OFF in this O2O interval" << std::endl;
1238     std::cout << "Channel000 = " << ch0bad << " Channel001 = " << ch1bad << std::endl;
1239     std::cout << "Channel002 = " << ch2bad << " Channel003 = " << ch3bad << std::endl;
1240     std::cout << "Number of LV detIDs that turned OFF in this O2O interval = " << numLvBad.size() << std::endl;
1241     std::cout << "Number of HV detIDs that turned OFF in this O2O interval = " << numHvBad.size() << std::endl;
1242   }
1243 
1244   LogTrace("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::" << __func__
1245                                     << "]: Number of PSUs retrieved from DB with map information    "
1246                                     << detIdStruct.detidV.size();
1247   LogTrace("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::" << __func__
1248                                     << "]: Number of PSUs retrieved from DB with no map information "
1249                                     << detIdStruct.notMatched;
1250 
1251   unsigned int dupCount = 0;
1252   for (unsigned int t = 0; t < numLvBad.size(); t++) {
1253     std::vector<unsigned int>::iterator iter = std::find(numHvBad.begin(), numHvBad.end(), numLvBad[t]);
1254     if (iter != numHvBad.end()) {
1255       dupCount++;
1256     }
1257   }
1258   if (debug_)
1259     std::cout << "Number of channels for which LV & HV turned OFF in this O2O interval = " << dupCount << std::endl;
1260 }
1261 
1262 void SiStripDetVOffBuilder::setPayloadStats(const uint32_t afterV, const uint32_t numAdded, const uint32_t numRemoved) {
1263   std::vector<uint32_t> pStats(3, 0);
1264   pStats.push_back(afterV);
1265   pStats.push_back(numAdded);
1266   pStats.push_back(numRemoved);
1267   payloadStats.push_back(pStats);
1268 }
1269 
1270 pair<int, int> SiStripDetVOffBuilder::extractDetIdVector(const unsigned int i,
1271                                                          SiStripDetVOff* modV,
1272                                                          DetIdListTimeAndStatus& detIdStruct) {
1273   // set the LV and HV off flags ready for storing
1274   int lv_off = -1, hv_off = -1;
1275   if (detIdStruct.isHV[i] == 0) {
1276     lv_off = !(detIdStruct.StatusGood[i]);
1277   }
1278   if (detIdStruct.isHV[i] == 1) {
1279     hv_off = !(detIdStruct.StatusGood[i]);
1280 
1281     // TESTING WITHOUT THE FIX
1282     // -----------------------
1283 
1284     if (psuDetIdMapFile_.empty()) {
1285       // temporary fix to handle the fact that we don't know which HV channel the detIDs are associated to
1286       if (i > 0) {
1287         std::string iChannel = detIdStruct.psuName[i].substr((detIdStruct.psuName[i].size() - 3));
1288         std::string iPsu = detIdStruct.psuName[i].substr(0, (detIdStruct.psuName[i].size() - 3));
1289         if (iChannel == "002" || iChannel == "003") {
1290           bool lastStatusOfOtherChannel = true;
1291           for (unsigned int j = 0; j < i; j++) {
1292             std::string jPsu = detIdStruct.psuName[j].substr(0, (detIdStruct.psuName[j].size() - 3));
1293             std::string jChannel = detIdStruct.psuName[j].substr((detIdStruct.psuName[j].size() - 3));
1294             if (iPsu == jPsu && iChannel != jChannel && (jChannel == "002" || jChannel == "003")) {
1295               if (debug_)
1296                 cout << "psu[" << i << "] = " << detIdStruct.psuName[i]
1297                      << " with status = " << detIdStruct.StatusGood[i] << " and psu[" << j
1298                      << "] = " << detIdStruct.psuName[j] << " with status " << detIdStruct.StatusGood[j] << endl;
1299               lastStatusOfOtherChannel = detIdStruct.StatusGood[j];
1300             }
1301           }
1302           if (detIdStruct.StatusGood[i] != lastStatusOfOtherChannel) {
1303             if (debug_)
1304               cout << "turning off hv" << endl;
1305             hv_off = 1;
1306           }
1307         }
1308       }
1309     }
1310 
1311     // -----------------------
1312   }
1313 
1314   return make_pair(hv_off, lv_off);
1315 }