CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/CalibTracker/SiStripDCS/src/SiStripDetVOffBuilder.cc

Go to the documentation of this file.
00001 #include "CalibTracker/SiStripDCS/interface/SiStripDetVOffBuilder.h"
00002 #include "boost/foreach.hpp"
00003 #include <sys/stat.h>
00004 
00005 // constructor
00006 SiStripDetVOffBuilder::SiStripDetVOffBuilder(const edm::ParameterSet& pset, const edm::ActivityRegistry&) : 
00007   onlineDbConnectionString(pset.getParameter<std::string>("onlineDB")),
00008   authenticationPath(pset.getParameter<std::string>("authPath")),
00009   whichTable(pset.getParameter<std::string>("queryType")),
00010   lastValueFileName(pset.getParameter<std::string>("lastValueFile")),
00011   fromFile(pset.getParameter<bool>("lastValueFromFile")),
00012   psuDetIdMapFile_(pset.getParameter<std::string>("PsuDetIdMapFile")),
00013   debug_(pset.getParameter<bool>("debugModeOn")),
00014   tDefault(7,0),
00015   tmax_par(pset.getParameter< std::vector<int> >("Tmax")),
00016   tmin_par(pset.getParameter< std::vector<int> >("Tmin")),
00017   tset_par(pset.getParameter< std::vector<int> >("TSetMin")),
00018   detIdListFile_(pset.getParameter< std::string >("DetIdListFile")),
00019   excludedDetIdListFile_(pset.getParameter< std::string >("ExcludedDetIdListFile")),
00020   highVoltageOnThreshold_(pset.getParameter<double>("HighVoltageOnThreshold"))
00021 { 
00022   lastStoredCondObj.first = NULL;
00023   lastStoredCondObj.second = 0;
00024 
00025   edm::LogError("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::SiStripDetVOffBuilder] constructor" << endl;
00026 
00027   // set up vectors based on pset parameters (tDefault purely for initialization)
00028 
00029   whichQuery=(whichTable == "STATUSCHANGE" || (whichTable == "LASTVALUE" && !fromFile));
00030 
00031   //Define the query interval [Tmin, Tmax]
00032   //where Tmax comes from the cfg
00033   //      Tmin comes from the cfg for the first o2o, after that it is extracted from Offline DB 
00034 
00035   tmax = coral::TimeStamp(tmax_par[0],tmax_par[1],tmax_par[2],tmax_par[3],tmax_par[4],tmax_par[5],tmax_par[6]);
00036 
00037   if (whichQuery) {
00038     // Is there a better way to do this?  TODO - investigate
00039     tmin=coral::TimeStamp(tmin_par[0],tmin_par[1],tmin_par[2],tmin_par[3],tmin_par[4],tmin_par[5],tmin_par[6]);
00040   }
00041   
00042   if (whichTable == "LASTVALUE") {
00043     tsetmin = coral::TimeStamp(tset_par[0],tset_par[1],tset_par[2],tset_par[3],tset_par[4],tset_par[5],tset_par[6]);
00044   }
00045   
00046   if (onlineDbConnectionString == "") {
00047     edm::LogError("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::SiStripDetVOffBuilder] DB name has not been set properly ... Returning ...";
00048     return;
00049   }
00050   
00051   if (fromFile && whichTable == "LASTVALUE" && lastValueFileName == "") {
00052     edm::LogError("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::SiStripDetVOffBuilder] File expected for lastValue table, but filename not specified ... Returning ...";
00053     return;
00054   }
00055   
00056   // write out the parameters
00057   std::stringstream ss;
00058   ss << "[SiStripDetVOffBuilder::SiStripDetVOffBuilder]\n" 
00059      << "     Parameters:\n" 
00060      << "     DB connection string: " << onlineDbConnectionString << "\n"
00061      << "     Authentication path: "  << authenticationPath       << "\n"
00062      << "     Table to be queried: "  << whichTable               << "\n"
00063      << "     MapFile: "  << psuDetIdMapFile_                << "\n";
00064   
00065   if (whichQuery){
00066     ss << "     Tmin: "; printPar(ss,tmin_par);  ss << std::endl;
00067   }
00068   ss << "     Tmax: "  ; printPar(ss,tmax_par);  ss << std::endl;
00069 
00070   if (whichTable == "LASTVALUE"){ 
00071     ss << "     TSetMin: "; printPar(ss,tset_par);  ss << std::endl;
00072   }
00073    edm::LogError("SiStripDetVOffBuilder") << ss.str();
00074 
00075 }
00076 
00077 // destructor
00078 SiStripDetVOffBuilder::~SiStripDetVOffBuilder() { 
00079   edm::LogError("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::" << __func__ << "]: destructing ...";
00080 }
00081 
00082 void SiStripDetVOffBuilder::printPar(std::stringstream& ss, const std::vector<int>& par){
00083   BOOST_FOREACH(int val, par){
00084     ss << val << " ";
00085   }
00086 }
00087 
00088 void SiStripDetVOffBuilder::BuildDetVOffObj()
00089 {
00090   // vectors for storing output from DB or text file
00091   TimesAndValues timesAndValues;
00092 
00093   // Open the PVSS DB connection
00094   coralInterface.reset( new SiStripCoralIface(onlineDbConnectionString, authenticationPath, debug_) );
00095   edm::LogError("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::BuildDetVOff]: Query type is " << whichTable << endl;
00096 
00097   if (whichTable == "LASTVALUE") {edm::LogError("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::BuildDetVOff]: Use file? " << ((fromFile) ? "TRUE" : "FALSE");}
00098 
00099   if (lastStoredCondObj.second > 0) {edm::LogError("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::BuildDetVOff]: retrieved last time stamp from DB: " 
00100                                                                             << lastStoredCondObj.second  << endl;}
00101   // access the information!
00102   //We've been using the STATUSCHANGE query only in last year or so... LASTVALUE may have untested issues...
00103   //In either case the idea is that the results of the query are saved into the timesAndValues struct
00104   //ready to be anaylized (i.e. translated into detIDs, HV/LV statuses)
00105 
00106   if (whichQuery) {
00107     if( whichTable == "STATUSCHANGE" ) {
00108       statusChange( lastStoredCondObj.second, timesAndValues );
00109     }
00110     if( whichTable == "LASTVALUE" ) {
00111       if( fromFile ) {
00112         lastValueFromFile(timesAndValues);
00113       }
00114       else {
00115         lastValue(timesAndValues);
00116       }
00117     }
00118   }
00119 
00120   //Initialize the stuct that will be used to keep the detID-translated information 
00121   DetIdListTimeAndStatus dStruct;
00122 
00123   // build PSU - det ID map
00124   //The following method actually "builds" 4 maps: LVMap, HVMap, HVUnmapped_Map, HVCrosstalking_Map.
00125   //It also takes the timesAndValues from the query above and using the maps, it processes the information
00126   //populating the DetIDListTimeAndStatus struct that will hold the information by detid.
00127   buildPSUdetIdMap(timesAndValues, dStruct);
00128 
00129 
00130   // initialize variables
00131   modulesOff.clear();
00132   cond::Time_t saveIovTime = 0;
00133   
00134 
00135   // - If there is already an object stored in the database
00136   // -- store it in the modulesOff vector
00137   // -- set the saveIovTime as that
00138   // -- set the payload stats to empty
00139   // Successivamente:
00140   // - loop su tutti gli elementi del detidV, che è stato letto dal pvss (questi elementi sono pair<vettore di detid, time>)
00141   // -- setta il tempo dell'IOV:
00142   // --- LASTVALUE -> iovtime settato a latestTime
00143   // --- altrimenti iovtime = tempo associato al detId vector del loop
00144 
00145 
00146   // check if there is already an object stored in the DB
00147   // This happens only if you are using STATUSCHANGE
00148   if (lastStoredCondObj.first != NULL && lastStoredCondObj.second > 0) {
00149     modulesOff.push_back( lastStoredCondObj );
00150     saveIovTime = lastStoredCondObj.second;
00151     setPayloadStats(0, 0, 0);
00152   }
00153 
00154 
00155   //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).
00156   for (unsigned int i = 0; i < dStruct.detidV.size(); i++) {
00157  
00158     //     std::vector<uint32_t> detids = dStruct.detidV[i].first;
00159     //     removeDuplicates(detids);
00160     std::vector<uint32_t> * detids = &(dStruct.detidV[i].first);
00161 
00162     // set the condition time for the transfer
00163     cond::Time_t iovtime = 0;
00164 
00165     if (whichTable == "LASTVALUE") {iovtime = timesAndValues.latestTime;}
00166 
00167     else {iovtime = getCondTime((dStruct.detidV[i]).second);}
00168 
00169     // decide how to initialize modV
00170     SiStripDetVOff *modV = 0;
00171 
00172     // When using STATUSCHANGE they are equal only for the first
00173     // When using LASTVALUE they are equal only if the tmin was set to tsetmin
00174 
00175     if (iovtime != saveIovTime) { // time is different, so create new object
00176 
00177       // This can be only when using LASTVALUE or with a new tag
00178       if (modulesOff.empty()) {
00179         // create completely new object and set the initial state to Tracker all off
00180         modV = new SiStripDetVOff();
00181 
00182         // Use the file
00183         edm::FileInPath fp(detIdListFile_);
00184         SiStripDetInfoFileReader reader(fp.fullPath());
00185         const std::map<uint32_t, SiStripDetInfoFileReader::DetInfo > detInfos  = reader.getAllData();
00186 
00187         //FIXME:
00188         //Following code is actually broken (well not until the cfg has "" for excludedDetIDListFile parameter!
00189         //Fix it if felt necessary (remember that it assumes that whatever detids are excluded should NOT be in the regular map
00190         //breaking our current situation with a fully mapped (LV-wise) tracker...
00191         // Careful: if a module is in the exclusion list it must be ignored and the initial status is set to ON.
00192         // These modules are expected to not be in the PSU-DetId map, so they will never get any status change from the query.
00193         SiStripPsuDetIdMap map;
00194         std::vector< std::pair<uint32_t, std::string> > excludedDetIdMap;
00195         if( excludedDetIdListFile_ != "" ) {
00196           map.BuildMap(excludedDetIdListFile_, excludedDetIdMap);
00197         }
00198         for(std::map<uint32_t, SiStripDetInfoFileReader::DetInfo >::const_iterator it = detInfos.begin(); it != detInfos.end(); ++it) {
00199           std::vector< std::pair<uint32_t, std::string> >::const_iterator exclIt = excludedDetIdMap.begin();
00200           bool excluded = false;
00201           for( ; exclIt != excludedDetIdMap.end(); ++exclIt ) {
00202             if( it->first == exclIt->first ) {
00203               excluded = true;
00204               break;
00205             }
00206           }
00207           if( !excluded ) {
00208             modV->put( it->first, 1, 1 );
00209           }
00210         }
00211 
00212       }
00213       else {modV = new SiStripDetVOff( *(modulesOff.back().first) );} // start from copy of previous object
00214     }
00215     else {
00216       modV = (modulesOff.back()).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!
00217     }
00218 
00219 
00220     
00221     // extract the detID vector before modifying for stats calculation
00222     std::vector<uint32_t> beforeV;
00223     modV->getDetIds(beforeV);
00224 
00225     //CHECKTHIS
00226     //The following method call is potentially problematic: 
00227     //passing modV as argument while extracting information about dStruct,
00228     //modV is not currently used in the method!
00229     std::pair<int, int> hvlv = extractDetIdVector(i, modV, dStruct);//Returns a pair like this HV OFF->1,-1 HV ON->0,-1 LV OFF->-1,1 LV ON->-1,0
00230     //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.
00231     //This could be confusing when reading the debug output!
00232  
00233     for (unsigned int j = 0; j < detids->size(); j++) {
00234       if( debug_ ) cout << "at time = " << iovtime << " detid["<<j<<"] = " << (*detids)[j] << " has hv = " << hvlv.first << " and lv = " << hvlv.second << endl;
00235       modV->put((*detids)[j],hvlv.first,hvlv.second);
00236     }
00237 
00238     // calculate the stats for storage
00239     unsigned int numAdded = 0, numRemoved = 0;
00240     if (iovtime == saveIovTime) {
00241       std::vector<uint32_t> oldStats = payloadStats.back();
00242       numAdded = oldStats[1];
00243       numRemoved = oldStats[2];
00244     }
00245     std::vector<uint32_t> afterV;
00246     modV->getDetIds(afterV);
00247     
00248     if ((afterV.size() - beforeV.size()) > 0) {
00249       numAdded += afterV.size() - beforeV.size();
00250     } else if ((beforeV.size() - afterV.size()) > 0) {
00251       numRemoved += beforeV.size() - afterV.size();
00252     }
00253 
00254     
00255     // store the object if it's a new object
00256     if (iovtime != saveIovTime) {
00257       SiStripDetVOff * testV = 0;
00258       if (!modulesOff.empty()) {testV = modulesOff.back().first;}
00259       if (modulesOff.empty() ||  !(*modV == *testV) ) {
00260         modulesOff.push_back( std::make_pair(modV,iovtime) );
00261         // save the time of the object
00262         saveIovTime = iovtime;
00263         // save stats
00264         setPayloadStats(afterV.size(), numAdded, numRemoved);
00265       }
00266     } else {
00267       (payloadStats.back())[0] = afterV.size();
00268       (payloadStats.back())[1] = numAdded;
00269       (payloadStats.back())[2] = numRemoved;
00270     }
00271   }
00272 
00273 
00274   // compare the first element and the last from previous transfer
00275   if (lastStoredCondObj.first != NULL && lastStoredCondObj.second > 0) {
00276     if ( lastStoredCondObj.second == modulesOff[0].second &&
00277          *(lastStoredCondObj.first) == *(modulesOff[0].first) ) {
00278       std::vector< std::pair<SiStripDetVOff*,cond::Time_t> >::iterator moIt = modulesOff.begin();
00279       modulesOff.erase(moIt);
00280       std::vector< std::vector<uint32_t> >::iterator plIt = payloadStats.begin();
00281       payloadStats.erase(plIt);
00282     }
00283   }
00284   
00285   if (debug_) {
00286     std::cout << std::endl;
00287     std::cout << "Size of modulesOff = " << modulesOff.size() << std::endl;
00288     for (unsigned int i = 0; i < modulesOff.size(); i++) {
00289       std::vector<uint32_t> finalids;
00290       (modulesOff[i].first)->getDetIds(finalids);
00291       std::cout << "Index = " << i << " Size of DetIds vector = " << finalids.size() << std::endl;
00292       std::cout << "Time = " << modulesOff[i].second << std::endl;
00293       for (unsigned int j = 0; j < finalids.size(); j++) {
00294         std::cout << "detid = " << finalids[j] << " LV off = " << (modulesOff[i].first)->IsModuleLVOff(finalids[j]) << " HV off = " 
00295                   << (modulesOff[i].first)->IsModuleHVOff(finalids[j]) << std::endl;
00296       }
00297     }
00298   }
00299 }
00300 
00301 int SiStripDetVOffBuilder::findSetting(uint32_t id, coral::TimeStamp changeDate, std::vector<uint32_t> settingID, std::vector<coral::TimeStamp> settingDate) {
00302   int setting = -1;
00303   // find out how many channel entries there are
00304   std::vector<int> locations;
00305   for (unsigned int i = 0; i < settingID.size(); i++) { if (settingID[i] == id) {locations.push_back((int)i);} }
00306 
00307   // simple cases
00308   if (locations.size() == 0) {setting = -1;}
00309   else if (locations.size() == 1) {setting = locations[0];}
00310   // more than one entry for this channel
00311   // NB.  entries ordered by date!
00312   else {
00313     for (unsigned int j = 0; j < locations.size(); j++) {
00314 #ifdef USING_NEW_CORAL
00315       const boost::posix_time::ptime& testSec = changeDate.time();
00316       const boost::posix_time::ptime& limitSec = settingDate[(unsigned int)locations[j]].time();
00317 #else
00318       long testSec = changeDate.time().ns();
00319       long limitSec = settingDate[(unsigned int)locations[j]].time().ns();
00320 #endif
00321       if (testSec >= limitSec) {setting = locations[j];}
00322     }
00323   }
00324   return setting;
00325 }
00326 
00327 int SiStripDetVOffBuilder::findSetting(std::string dpname, coral::TimeStamp changeDate, std::vector<std::string> settingDpname, std::vector<coral::TimeStamp> settingDate) {
00328   int setting = -1;
00329   // find out how many channel entries there are
00330   std::vector<int> locations;
00331   for (unsigned int i = 0; i < settingDpname.size(); i++) { if (settingDpname[i] == dpname) {locations.push_back((int)i);} }
00332   
00333   // simple cases
00334   if (locations.size() == 0) {setting = -1;}
00335   else if (locations.size() == 1) {setting = locations[0];}
00336   // more than one entry for this channel
00337   // NB.  entries ordered by date!
00338   else {
00339     for (unsigned int j = 0; j < locations.size(); j++) {
00340 #ifdef USING_NEW_CORAL
00341       const boost::posix_time::ptime& testSec = changeDate.time();
00342       const boost::posix_time::ptime& limitSec = settingDate[(unsigned int)locations[j]].time();
00343 #else
00344       long testSec = changeDate.time().ns();
00345       long limitSec = settingDate[(unsigned int)locations[j]].time().ns();
00346 #endif
00347       if (testSec >= limitSec) {setting = locations[j];}
00348     }
00349   }
00350   return setting;
00351 }
00352 
00353 void SiStripDetVOffBuilder::readLastValueFromFile(std::vector<uint32_t> &dpIDs, std::vector<float> &vmonValues, std::vector<coral::TimeStamp> &dateChange) {
00354   std::ifstream lastValueFile(lastValueFileName.c_str());
00355   if (lastValueFile.bad()) {
00356     edm::LogError("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::" << __func__ << "]: last Value file does not exist!";
00357     return;
00358   }
00359 
00360   dpIDs.clear();
00361   vmonValues.clear();
00362   dateChange.clear();
00363   std::vector<std::string> changeDates;
00364 
00365   std::string line;
00366   // remove the first line as it is the title line
00367   //  std::getline(lastValueFile,line);
00368   //  line.clear();
00369   // now extract data
00370   while( std::getline(lastValueFile,line) ) {
00371     std::istringstream ss(line);
00372     uint32_t dpid;
00373     float vmon;
00374     std::string changeDate;
00375     ss >> std::skipws >> dpid >> vmon >> changeDate;
00376     dpIDs.push_back(dpid);
00377     vmonValues.push_back(vmon);
00378     changeDates.push_back(changeDate);
00379   }
00380   lastValueFile.close();  
00381 
00382   // Now convert dates to coral::TimeStamp
00383   for (unsigned int i = 0; i < changeDates.size(); i++) {
00384     std::string part = changeDates[i].substr(0,4);
00385     int year = atoi(part.c_str());
00386     part.clear();
00387 
00388     part = changeDates[i].substr(5,2);
00389     int month = atoi(part.c_str());
00390     part.clear();
00391 
00392     part = changeDates[i].substr(8,2);
00393     int day = atoi(part.c_str());
00394     part.clear();
00395 
00396     part = changeDates[i].substr(11,2);
00397     int hour = atoi(part.c_str());
00398     part.clear();
00399 
00400     part = changeDates[i].substr(14,2);
00401     int minute = atoi(part.c_str());
00402     part.clear();
00403 
00404     part = changeDates[i].substr(17,2);
00405     int second = atoi(part.c_str());
00406     part.clear();
00407 
00408     coral::TimeStamp date(year,month,day,hour,minute,second,0);
00409     dateChange.push_back(date);
00410   }
00411 
00412   if (changeDates.size() != dateChange.size()) {edm::LogError("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::" << __func__ << "]: date conversion failed!!";}
00413 }
00414 
00415 cond::Time_t SiStripDetVOffBuilder::getCondTime(coral::TimeStamp coralTime) {
00416 
00417   // const boost::posix_time::ptime& t = coralTime.time();
00418   cond::Time_t condTime = cond::time::from_boost(coralTime.time());
00419 
00420   // cout << "[SiStripDetVOffBuilder::getCondTime] Converting CoralTime into CondTime: "
00421   //      << " coralTime = (coralTimeInNs) " <<  coralTime.total_nanoseconds() << " condTime " << (condTime>> 32) << " - " << (condTime & 0xFFFFFFFF) << endl;
00422 
00423   return condTime;
00424 }
00425 
00426 coral::TimeStamp SiStripDetVOffBuilder::getCoralTime(cond::Time_t iovTime)
00427 {
00428   // This method is defined in the TimeConversions header and it does the following:
00429   // - takes the seconds part of the iovTime (bit-shifting of 32)
00430   // - adds the nanoseconds part (first 32 bits mask)
00431   // - adds the time0 that is the time from begin of times (boost::posix_time::from_time_t(0);)
00432   coral::TimeStamp coralTime(cond::time::to_boost(iovTime));
00433 
00434   if( debug_ ) {
00435     unsigned long long iovSec = iovTime >> 32;
00436     uint32_t iovNanoSec = uint32_t(iovTime);
00437     cond::Time_t testTime=getCondTime(coralTime);
00438     cout << "[SiStripDetVOffBuilder::getCoralTime] Converting CondTime into CoralTime: "
00439          << " condTime = " <<  iovSec << " - " << iovNanoSec 
00440          << " getCondTime(coralTime) = " << (testTime>>32) << " - " << (testTime&0xFFFFFFFF)  << endl;
00441   }
00442 
00443   return coralTime;
00444 }
00445 
00446 void SiStripDetVOffBuilder::removeDuplicates( std::vector<uint32_t> & vec ) {
00447   std::sort(vec.begin(),vec.end());
00448   std::vector<uint32_t>::iterator it = std::unique(vec.begin(),vec.end());
00449   vec.resize( it - vec.begin() );
00450 }
00451 
00452 void SiStripDetVOffBuilder::setLastSiStripDetVOff( SiStripDetVOff * lastPayload, cond::Time_t lastTimeStamp ) {
00453   lastStoredCondObj.first = lastPayload;
00454   lastStoredCondObj.second = lastTimeStamp;
00455 }
00456 
00457 cond::Time_t SiStripDetVOffBuilder::findMostRecentTimeStamp( std::vector<coral::TimeStamp> coralDate ) {
00458   cond::Time_t latestDate = getCondTime(coralDate[0]);
00459   
00460   if( debug_ ) {
00461     std::cout << "latestDate: condTime = " 
00462               << (latestDate>>32) 
00463               << " - " 
00464               << (latestDate&0xFFFFFFFF) 
00465       //<< " coralTime= " << coralDate[0] 
00466               << std::endl;
00467   }
00468 
00469   for (unsigned int i = 1; i < coralDate.size(); i++) {
00470     cond::Time_t testDate = getCondTime(coralDate[i]);
00471     if (testDate > latestDate) {
00472       latestDate = testDate;
00473     }
00474   }
00475   return latestDate;
00476 }
00477 
00478 void SiStripDetVOffBuilder::reduce( std::vector< std::pair<SiStripDetVOff*,cond::Time_t> >::iterator & it,
00479                                     std::vector< std::pair<SiStripDetVOff*,cond::Time_t> >::iterator & initialIt,
00480                                     std::vector< std::pair<SiStripDetVOff*,cond::Time_t> > & resultVec,
00481                                     const bool last )
00482 {
00483   //const bool last is set to false by default in the header file...
00484   int first = 0;
00485   // Check if it is the first
00486   if( distance(resultVec.begin(), initialIt) == 0 ) {
00487     first = 1;
00488   }
00489 
00490   if( debug_ && ( it->first->getLVoffCounts() - initialIt->first->getLVoffCounts() == 0 ) && ( it->first->getHVoffCounts() - initialIt->first->getHVoffCounts() == 0 ) ) {
00491     cout << "Same number of LV and HV at start and end of sequence: LV off = " << it->first->getLVoffCounts() << " HV off = " << it->first->getHVoffCounts() << endl;
00492   }
00493 
00494   // if it was going off
00495   if( ( it->first->getLVoffCounts() - initialIt->first->getLVoffCounts() > 0 ) || ( it->first->getHVoffCounts() - initialIt->first->getHVoffCounts() > 0 ) ) {
00496     // Set the time of the current (last) iov as the time of the initial iov of the sequence
00497     // replace the first iov with the last one
00498     //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 
00499     (it+last)->second = (initialIt)->second;
00500     discardIOVs(it, initialIt, resultVec, last, 0);
00501     if( debug_ ) cout << "Reducing IOV sequence (going off)" << endl;
00502   }
00503   // if it was going on
00504   else if( ( it->first->getLVoffCounts() - initialIt->first->getLVoffCounts() <= 0 ) || ( it->first->getHVoffCounts() - initialIt->first->getHVoffCounts() <= 0 ) ) {
00505     // replace the last minus one iov with the first one
00506     discardIOVs(it, initialIt, resultVec, last, first);
00507     if( debug_ ) cout << "Reducing IOV sequence (going on)" << endl;
00508   }
00509 }
00510 
00511 void SiStripDetVOffBuilder::discardIOVs( std::vector< std::pair<SiStripDetVOff*,cond::Time_t> >::iterator & it,
00512                                          std::vector< std::pair<SiStripDetVOff*,cond::Time_t> >::iterator & initialIt,
00513                                          std::vector< std::pair<SiStripDetVOff*,cond::Time_t> > & resultVec,
00514                                          const bool last, const unsigned int first )
00515 {
00516   if( debug_ ) {
00517     cout << "first (1->means the sequence started at the first timestamp in the query results, 0-> that it did not)= " << first << endl;
00518     cout << "initial->first (initial SiStripDetVOff object of the IOV sequence)= " << initialIt->first << ", second (initial timestamp of the IOV sequence) = " << initialIt->second << endl;
00519     cout << "last (0->means that the sequence is not ending with the last item in the query results, 1-> that it DOES!)= " << last << endl;
00520   }
00521   if( last == true ) {
00522     resultVec.erase(initialIt+first, it+1);
00523     // Minus 2 because it will be incremented at the end of the loop becoming end()-1.
00524     it = resultVec.end()-2;
00525   }
00526   else {
00527     it = resultVec.erase(initialIt+first, it);
00528   }
00529 }
00530 
00531 //This is the method that (called by GetModulesOff, declared in the header file) executes the reduction by massaging modulesOff
00532 void SiStripDetVOffBuilder::reduction(const uint32_t deltaTmin, const uint32_t maxIOVlength)
00533 {
00534 
00535   int count = 0;
00536   std::vector< std::pair<SiStripDetVOff*,cond::Time_t> >::iterator initialIt;
00537 
00538   int resultVecSize = modulesOff.size();
00539   int resultsIndex = 0;
00540 
00541   if( resultVecSize > 1 ) {
00542   std::vector< std::pair<SiStripDetVOff*,cond::Time_t> >::iterator it = modulesOff.begin();
00543     for( ; it != modulesOff.end()-1; ++it, ++resultsIndex ) {
00544       unsigned long long deltaT = ((it+1)->second - it->second) >> 32;
00545       unsigned long long deltaTsequence = 0;
00546       if( count > 1 ) {
00547         deltaTsequence = ((it+1)->second - initialIt->second) >> 32;
00548       }
00549       // Save the initial pair
00550       if( (deltaT < deltaTmin) && ( (count == 0) || ( deltaTsequence < maxIOVlength ) ) ) {
00551         // If we are not in a the sequence
00552         if( count == 0 ) {
00553           initialIt = it;
00554         }
00555         // Increase the counter in any case.
00556         ++count;
00557       }
00558       // We do it only if the sequence is bigger than two cases
00559       else if( count > 1 ) {
00560         reduce(it, initialIt, modulesOff);
00561         // reset all
00562         count = 0;
00563       }
00564       else {
00565         // reset all
00566         count = 0;
00567       }
00568       // Border case
00569       if( resultsIndex == resultVecSize-2 && count != 0 ) {
00570         reduce(it, initialIt, modulesOff, true);
00571       }
00572     }
00573   }
00574 }
00575 
00576 void SiStripDetVOffBuilder::statusChange( cond::Time_t & lastTime, TimesAndValues & tStruct )
00577 {
00578   // Setting tmin to the last value IOV of the database tag
00579   if( lastTime > 0 ) {
00580     tmin = getCoralTime(lastTime);
00581   }
00582   
00583   coralInterface->doQuery(whichTable, tmin ,tmax, tStruct.changeDate, tStruct.actualValue, tStruct.dpname);
00584   //UNIT TEST DEBUG to bypass the query wait time!!!
00585   //coral::TimeStamp testtime=getCoralTime(lastTime);
00586   //tStruct.changeDate.push_back(testtime);
00587   //tStruct.actualValue.push_back(1.);
00588   //tStruct.dpname.push_back("cms_trk_dcs_03:CAEN/CMS_TRACKER_SY1527_3/branchController00/easyCrate3/easyBoard17/channel002");
00589 
00590   // preset the size of the status vector
00591   tStruct.actualStatus.resize(tStruct.actualValue.size());
00592   tStruct.actualStatus.clear();
00593   
00594   BOOST_FOREACH(float val, tStruct.actualValue) {
00595     tStruct.actualStatus.push_back(static_cast<int>(val));
00596   }
00597 }
00598 
00599 void SiStripDetVOffBuilder::lastValue(TimesAndValues & tStruct)
00600 {
00601   coralInterface->doQuery(whichTable, tmin ,tmax, tStruct.changeDate, tStruct.actualValue, tStruct.dpname);
00602   
00603   tStruct.latestTime = findMostRecentTimeStamp( tStruct.changeDate );
00604   
00605   // preset the size of the status vector
00606   tStruct.actualStatus.resize(tStruct.actualValue.size());
00607   
00608   // retrieve the channel settings from the PVSS DB
00609   std::vector<coral::TimeStamp> settingDate;
00610   std::vector<float> settingValue;
00611   std::vector<std::string> settingDpname;
00612   std::vector<uint32_t> settingDpid;
00613   coralInterface->doSettingsQuery(tsetmin,tmax,settingDate,settingValue,settingDpname,settingDpid);
00614   LogDebug("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::BuildDetVOff]: Channel settings retrieved";
00615   LogDebug("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::BuildDetVOff]: Number of PSU channels: " << settingDpname.size();
00616     
00617   unsigned int missing = 0;
00618   std::stringstream ss;
00619   for (unsigned int j = 0; j < tStruct.dpname.size(); j++) {
00620     int setting = findSetting(tStruct.dpname[j],tStruct.changeDate[j],settingDpname,settingDate);
00621     if (setting >= 0) {
00622       if (tStruct.actualValue[j] > (highVoltageOnThreshold_*(settingValue[setting]))) {tStruct.actualStatus[j] = 1;}
00623       else {tStruct.actualStatus[j] = 0;}
00624     } else {
00625       tStruct.actualStatus[j] = -1;
00626       missing++;
00627       ss << "Channel = " << tStruct.dpname[j] << std::endl;
00628     }
00629   }
00630   LogDebug("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::BuildDetVOff]: Number of channels with no setting information " << missing;
00631   LogDebug("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::BuildDetVOff]: Number of entries in dpname vector " << tStruct.dpname.size();
00632 }
00633 
00634 void SiStripDetVOffBuilder::lastValueFromFile(TimesAndValues & tStruct)
00635 {
00636   readLastValueFromFile(tStruct.dpid,tStruct.actualValue,tStruct.changeDate);
00637   tStruct.latestTime = findMostRecentTimeStamp( tStruct.changeDate );
00638   LogDebug("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::BuildDetVOff]: File access complete \n\t Number of values read from file: " << tStruct.dpid.size();
00639   
00640   // retrieve the channel settings from the PVSS DB
00641   std::vector<coral::TimeStamp> settingDate;
00642   std::vector<float> settingValue;
00643   std::vector<std::string> settingDpname;
00644   std::vector<uint32_t> settingDpid;
00645   
00646   coralInterface->doSettingsQuery(tsetmin,tmax,settingDate,settingValue,settingDpname,settingDpid);
00647   LogDebug("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::BuildDetVOff]: Channel settings retrieved";
00648   LogDebug("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::BuildDetVOff]: Number of PSU channels: " << settingDpname.size();
00649   
00650   unsigned int missing = 0;
00651   std::stringstream ss;
00652   // need to get the PSU channel names from settings
00653   tStruct.dpname.clear();
00654   tStruct.dpname.resize(tStruct. dpid.size());
00655   for (unsigned int j = 0; j < tStruct.dpid.size(); j++) {
00656     int setting = findSetting(tStruct.dpid[j],tStruct.changeDate[j],settingDpid,settingDate);
00657     if (setting >= 0) {
00658       if (tStruct.actualValue[j] > (highVoltageOnThreshold_*settingValue[setting])) {tStruct.actualStatus[j] = 1;}
00659       else {
00660         tStruct.actualStatus[j] = 0;
00661       }
00662       tStruct.dpname[j] = settingDpname[setting];
00663     } else {
00664       tStruct.actualStatus[j] = -1;
00665       tStruct.dpname[j] = "UNKNOWN";
00666       missing++;
00667       ss << "DP ID = " << tStruct.dpid[j] << std::endl;
00668     }
00669   }
00670   LogDebug("SiStripDetVOffBuilder") << "Number of missing psu channels = " << missing << std::endl;
00671   LogDebug("SiStripDetVOffBuilder") << "IDs are: = " << ss.str();
00672 }
00673 
00674 string SiStripDetVOffBuilder::timeToStream(const cond::Time_t & condTime, const string & comment)
00675 {
00676   stringstream ss;
00677   ss << comment << (condTime>> 32) << " - " << (condTime & 0xFFFFFFFF) << std::endl;
00678   return ss.str();
00679 }
00680 
00681 string SiStripDetVOffBuilder::timeToStream(const coral::TimeStamp & coralTime, const string & comment)
00682 {
00683   stringstream ss;
00684   ss << "Starting from IOV time in the database : year = " << coralTime.year()
00685      << ", month = " << coralTime.month()
00686      << ", day = " << coralTime.day()
00687      << ", hour = " << coralTime.hour()
00688      << ", minute = " << coralTime.minute()
00689      << ", second = " << coralTime.second()
00690      << ", nanosecond = " << coralTime.nanosecond() << std::endl;
00691   return ss.str();
00692 }
00693 bool SiStripDetVOffBuilder::FileExists(string FileName) {
00694   //Helper method to check if local files exist (needed to handle HVUnmapped, HVCrosstalking modules)
00695   struct stat FileInfo;
00696   bool Existence;
00697   int Stat;
00698   //Try to get file attributes
00699   Stat=stat(FileName.c_str(),&FileInfo);
00700   if (Stat==0) {
00701     Existence=true;
00702   }
00703   else {
00704     Existence=false;
00705   }
00706   return Existence;
00707 }
00708 
00709 void SiStripDetVOffBuilder::buildPSUdetIdMap(TimesAndValues & psuStruct, DetIdListTimeAndStatus & detIdStruct)
00710 //This function builds a PSU to DetID map one way or the other. Then it processes the psuStruct that contains
00711 //the results of the CAEN status query to the Online DB, filling the detIdStruct with the detIDs corresponding
00712 //to the PSU (channel in some cases, PSU only in others) reported in the CAEN status query to the Online DB.
00713 //It may make sense to split this method eventually.
00714 {
00715   SiStripPsuDetIdMap map_;
00716   if( psuDetIdMapFile_ == "" ) {
00717     std::cout<<"PLEASE provide the name of a valid PSUDetIDMapFile in the cfg: currently still necessary to have a file, soon will access the info straight from the DB!"<<endl;
00718     //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!)
00719   }
00720   else {
00721     map_.BuildMap(psuDetIdMapFile_,debug_); //This is the method used to build the map.
00722   }
00723   LogTrace("SiStripDetVOffBuilder") <<"[SiStripDetVOffBuilder::BuildDetVOff] PSU(Channel)-detID map(s) built";
00724   //Following method to be replaced by printMaps... to print all 4 maps built!
00725   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.
00726 
00727   // use map info to build input for list of objects
00728   // no need to check for duplicates, as put method for SiStripDetVOff checks for you!
00729 
00730   //Debug variables
00731   unsigned int ch0bad = 0, ch1bad = 0, ch2bad = 0, ch3bad = 0;
00732   std::vector<unsigned int> numLvBad, numHvBad;
00733 
00734   //Create 2 extra maps that we'll use to keep track of unmapped and crosstalking detids when turning ON and OFF HV:
00735   //-unmapped need to be both turned OFF when any HV goes OFF and to be turned ON when both are ON
00736   //-crosstaling need to be both turned ON when any HV goes ON and to be turned OFF ONLY when BOTH are OFF.
00737   std::map<std::string,bool> UnmappedState, CrosstalkingState;
00738   //Get the HVUnmapped map from the map, so that we can set know which PSU are unmapped:
00739   std::map<std::string,std::vector<uint32_t> > UnmappedPSUs=map_.getHVUnmappedMap();
00740   //Check here if there is a file already, otherwise initialize to OFF all channels in these PSU!
00741   if (FileExists("HVUnmappedChannelState.dat")) {
00742     std::cout<<"File HVUnmappedChannelState.dat exists!"<<std::endl;
00743     ifstream ifs("HVUnmappedChannelState.dat");
00744     string line;
00745     while( getline( ifs, line ) ) {
00746       if( line != "" ) {
00747         // split the line and insert in the map
00748         stringstream ss(line);
00749         string PSUChannel;
00750         bool HVStatus;
00751         ss >> PSUChannel;
00752         ss >> HVStatus;
00753         //Extract the PSU from the PSUChannel (since the HVUnmapped_Map uses PSU as key
00754         std::string PSU=PSUChannel.substr(0,PSUChannel.size()-10);
00755         //Look for the PSU in the unmapped map!
00756         std::map<std::string,std::vector<uint32_t> >::iterator iter=UnmappedPSUs.find(PSU);
00757         if (iter!=UnmappedPSUs.end()) {
00758           UnmappedState[PSUChannel]=HVStatus;
00759         }
00760         else {
00761           std::cout<<"WARNING!!! There are channels in the local file with the channel status for HVUnmapped channels, that ARE NOT CONSIDERED AS UNMAPPED in the current map!"<<std::endl;
00762         }
00763       }
00764     }//End of the while loop reading and initializing UnmappedState map from file
00765     //Extra check:
00766     //Should check if there any HVUnmapped channels in the map that are not listed in the local file!
00767     bool MissingChannels=false;
00768     for (std::map<std::string, vector<uint32_t> >::iterator it=UnmappedPSUs.begin(); it!=UnmappedPSUs.end(); it++) {
00769       std::string chan002=it->first+"channel002";
00770       std::string chan003=it->first+"channel003";
00771       std::map<std::string,bool>::iterator iter=UnmappedState.find(chan002);
00772       if (iter==UnmappedState.end()) {
00773         std::cout<<"ERROR! The local file with the channel status for HVUnmapped channels IS MISSING one of the following unmapped channel voltage status information:"<<std::endl;
00774         std::cout<<chan002<<std::endl;
00775         MissingChannels=true;
00776       }
00777       iter=UnmappedState.find(chan003);
00778       if (iter==UnmappedState.end()) {
00779         std::cout<<"ERROR! The local file with the channel status for HVUnmapped channels IS MISSING one of the following unmapped channel voltage status information:"<<std::endl;
00780         std::cout<<chan003<<std::endl;
00781         MissingChannels=true;
00782       }
00783     }
00784     //Now if any channel WAS missing, exit!
00785     if (MissingChannels) {
00786       std::cout<<"!!!!\n"<<"Exiting now... please check the local HVUnmappedChannelState.dat and the mapfile you provided ("<<psuDetIdMapFile_<<")"<<std::endl;
00787       exit(1);
00788     }
00789   }
00790   else { //If the file HVUnmappedChannelState.dat does not exist, initialize the map to all OFF. 
00791     //(see below for creating the file at the end of the execution with the latest state of unmapped channels. 
00792     for (std::map<std::string, vector<uint32_t> >::iterator it=UnmappedPSUs.begin(); it!=UnmappedPSUs.end(); it++) {
00793       std::string chan002=it->first+"channel002";
00794       std::string chan003=it->first+"channel003";
00795       UnmappedState[chan002]=false;
00796       UnmappedState[chan003]=false;
00797     }
00798   }
00799   //Get the HVCrosstalking map from the map, so that we can set know which PSU are crosstalking:
00800   std::map<std::string,std::vector<uint32_t> > CrosstalkingPSUs=map_.getHVCrosstalkingMap();
00801   //Check here if there is a file already, otherwise initialize to OFF all channels in these PSU!
00802   if (FileExists("HVCrosstalkingChannelState.dat")) {
00803     std::cout<<"File HVCrosstalkingChannelState.dat exists!"<<std::endl;
00804     ifstream ifs("HVCrosstalkingChannelState.dat");
00805     string line;
00806     while( getline( ifs, line ) ) {
00807       if( line != "" ) {
00808         // split the line and insert in the map
00809         stringstream ss(line);
00810         string PSUChannel;
00811         bool HVStatus;
00812         ss >> PSUChannel;
00813         ss >> HVStatus;
00814         //Extract the PSU from the PSUChannel (since the HVCrosstalking_Map uses PSU as key
00815         std::string PSU=PSUChannel.substr(0,PSUChannel.size()-10);
00816         //Look for the PSU in the unmapped map!
00817         std::map<std::string,std::vector<uint32_t> >::iterator iter=CrosstalkingPSUs.find(PSU);
00818         if (iter!=CrosstalkingPSUs.end()) {
00819           CrosstalkingState[PSUChannel]=HVStatus;
00820         }
00821         else {
00822           std::cout<<"WARNING!!! There are channels in the local file with the channel status for HVUnmapped channels, that ARE NOT CONSIDERED AS UNMAPPED in the current map!"<<std::endl;
00823         }
00824       }
00825     }//End of the while loop reading and initializing CrosstalkingState map from file
00826     //Extra check:
00827     //Should check if there any HVCrosstalking channels in the map that are not listed in the local file!
00828     bool MissingChannels=false;
00829     for (std::map<std::string, vector<uint32_t> >::iterator it=CrosstalkingPSUs.begin(); it!=CrosstalkingPSUs.end(); it++) {
00830       std::string chan002=it->first+"channel002";
00831       std::string chan003=it->first+"channel003";
00832       std::map<std::string,bool>::iterator iter=CrosstalkingState.find(chan002);
00833       if (iter==CrosstalkingState.end()) {
00834         std::cout<<"ERROR! The local file with the channel status for HVCrosstalking channels IS MISSING one of the following unmapped channel voltage status information:"<<std::endl;
00835         std::cout<<chan002<<std::endl;
00836         MissingChannels=true;
00837       }
00838       iter=CrosstalkingState.find(chan003);
00839       if (iter==CrosstalkingState.end()) {
00840         std::cout<<"ERROR! The local file with the channel status for HVCrosstalking channels IS MISSING one of the following unmapped channel voltage status information:"<<std::endl;
00841         std::cout<<chan003<<std::endl;
00842         MissingChannels=true;
00843       }
00844     }
00845     //Now if any channel WAS missing, exit!
00846     if (MissingChannels) {
00847       std::cout<<"!!!!\n"<<"Exiting now... please check the local HVCrosstalkingChannelState.dat and the mapfile you provided ("<<psuDetIdMapFile_<<")"<<std::endl;
00848       exit(1);
00849     }
00850   }
00851   else { //If the file HVCrosstalkingChannelState.dat does not exist, initialize the map to all OFF. 
00852     //(see below for creating the file at the end of the execution with the latest state of unmapped channels. 
00853     for (std::map<std::string, vector<uint32_t> >::iterator it=CrosstalkingPSUs.begin(); it!=CrosstalkingPSUs.end(); it++) {
00854       std::string chan002=it->first+"channel002";
00855       std::string chan003=it->first+"channel003";
00856       CrosstalkingState[chan002]=false;
00857       CrosstalkingState[chan003]=false;
00858     }
00859   }
00860   
00861   if (debug_) {
00862     //print out the UnmappedState map:
00863     std::cout<<"Printing the UnmappedChannelState initial map:"<<std::endl;
00864     std::cout<<"PSUChannel\t\tHVON?(true or false)"<<std::endl;
00865     for (std::map<std::string,bool>::iterator it=UnmappedState.begin(); it!=UnmappedState.end(); it++) {
00866       std::cout<<it->first<<"\t\t"<<it->second<<std::endl;
00867     }
00868     //print out the CrosstalkingState map:
00869     std::cout<<"Printing the CrosstalkingChannelState initial map:"<<std::endl;
00870     std::cout<<"PSUChannel\t\tHVON?(true or false)"<<std::endl;
00871     for (std::map<std::string,bool>::iterator it=CrosstalkingState.begin(); it!=CrosstalkingState.end(); it++) {
00872       std::cout<<it->first<<"\t\t"<<it->second<<std::endl;
00873     }
00874   }
00875   
00876   //Loop over the psuStruct (DB query results), lopping over the PSUChannels
00877   //This will probably change int he future when we will change the query itself 
00878   //to report directly the detIDs associated with a channel
00879   //Probably we will report in the query results the detID, the changeDate 
00880   //and whether the channel is HV mapped, HV unmapped, HV crosstalking using a flag...
00881   for (unsigned int dp = 0; dp < psuStruct.dpname.size(); dp++) {
00882     //FIX ME:
00883     //Check if the following if condition can EVER be true!
00884     std::string PSUChannel=psuStruct.dpname[dp];
00885     if (PSUChannel != "UNKNOWN") {
00886 
00887       // figure out the channel and the PSU individually
00888       std::string Channel = PSUChannel.substr(PSUChannel.size()-10); //Channel is the channel, i.e. channel000, channel001 etc
00889       std::string PSU = PSUChannel.substr(0,PSUChannel.size()-10);
00890       
00891       // Get the detIDs corresponding to the given PSU channel using the getDetID function of SiStripPsuDetIdMap.cc
00892       //NOTA BENE
00893       //Need to make sure the information is treated consistently here:
00894       //The map by convention has 
00895       //detID-> channel002 or channel003 IF the channel is HV mapped,
00896       //detID->channel000 if it is not HV mapped
00897       //We want to differentiate the behavior depending on the status reported for the channel for channels that are unmapped!
00898       //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.
00899       //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!
00900       //Need to handle the case of coupled Power supplies (that only turn off when both are turned off).
00901 
00902       //Fixed SiStripPSUdetidMap.cc to make sure now getDetID gets the correct list of detIDs:
00903       //-for channels 000/001 all the detIDs connected to the PSU
00904       //-for channels 002/003 HV1/HV2 modules only (exclusively) 
00905       //UPDATE for HV channels: 
00906       //actually fixed it to report also detIDs listed as 
00907       //channel000 on the same supply of channel002 or channel003 
00908       //and the crosstalking ones (channel999) too..
00909 
00910       //Get the detIDs associated with the DPNAME (i.e. PSUChannel) reported by the query
00911       //Declare the vector to be passed as reference parameters to the getDetID method
00912       //std::vector<uint32_t> ids,unmapped_ids,crosstalking_ids;
00913       std::vector<uint32_t> ids;
00914       //map_.getDetID(PSUChannel, debug_, ids, unmapped_ids, crosstalking_ids);
00915       //Actually the method above is a bit of an overkill, we could already use the individual methods:
00916       //getLvDetID
00917       //getHvDetID
00918 
00919       //Declaring the two vector needed for the HV case in this scope.
00920       std::vector<uint32_t> unmapped_ids,crosstalking_ids;
00921       bool LVCase;
00922       //LV CASE
00923       if (Channel=="channel000" || Channel=="channel001") {
00924         LVCase=true;
00925         ids=map_.getLvDetID(PSU); //Since in the LV case only 1 list of detids is returned (unmapped and crosstalking are irrelevant for LV) return the vector directly
00926       }
00927       //HV CASE
00928       else { //if (Channel=="channel002" || Channel=="channel003") {
00929         LVCase=false;
00930         map_.getHvDetID(PSUChannel,ids,unmapped_ids,crosstalking_ids); //In the HV case since 3 vectors are filled, use reference parameters
00931       }
00932 
00933       if ( debug_ ) {
00934         cout <<"dpname["<<dp<<"] = "<<PSUChannel<<", for time = "<<timeToStream(psuStruct.changeDate[dp])<<endl;
00935         if (!ids.empty()) {
00936           if (Channel=="channel000" || Channel=="channel001") {
00937             cout << "Corresponding to LV (PSU-)matching detids: "<<endl;
00938             for (unsigned int i_detid=0;i_detid<ids.size();i_detid++) {
00939               cout<< ids[i_detid] << std::endl;
00940             }
00941           }
00942           else {
00943             cout << "Corresponding to straight HV matching detids: "<<endl;
00944             for (unsigned int i_detid=0;i_detid<ids.size();i_detid++) {
00945               cout<< ids[i_detid] << std::endl;
00946             }
00947           }
00948         }
00949         //The unmapped_ids and crosstalking_ids are only filled for HV channels!
00950         if (!unmapped_ids.empty()) {
00951           cout << "Corresponding to HV unmapped (PSU-)matching detids: "<<endl;
00952           for (unsigned int i_detid=0;i_detid<unmapped_ids.size();i_detid++) {
00953             cout<< unmapped_ids[i_detid] << std::endl;
00954           }
00955         }
00956         if (!crosstalking_ids.empty()) {
00957           cout << "Corresponding to HV crosstalking (PSU-)matching detids: "<<endl;
00958           for (unsigned int i_detid=0;i_detid<crosstalking_ids.size();i_detid++) {
00959             cout<< crosstalking_ids[i_detid] << std::endl;
00960           }
00961         }
00962       }
00963               
00964       //NOW implement the new logic using the detids, unmapped_detids, crosstalking_detids!
00965 
00966       //First check whether the channel we're looking at is turning OFF or turning ON!
00967       
00968       //TURN OFF case:
00969       if (psuStruct.actualStatus[dp] != 1) {
00970         //Behavior is different for LV vs HV channels:
00971         //LV case:
00972         if (LVCase) {
00973           //Turn OFF all: 
00974           //-positively matching 
00975           //-unmapped matching
00976           //-crosstalking
00977           //for the LV case all the detids are automatically reported in the ids vector
00978           //unmapped and crosstalking are only differentiated (relevant) for HV.
00979           if (!ids.empty()) {
00980             //debug variables increment
00981             ch0bad++;
00982             ch1bad++;
00983             
00984             //Create a pair with the relevant detIDs (vector) and its timestamp
00985             //And put it in the detidV vector of the detIdStruct that will contain all the 
00986             //results
00987             detIdStruct.detidV.push_back( std::make_pair(ids,psuStruct.changeDate[dp]) );
00988             
00989             //Set the status to OFF
00990             detIdStruct.StatusGood.push_back(false);
00991             
00992             //debug variable population
00993             numLvBad.insert(numLvBad.end(),ids.begin(),ids.end());
00994 
00995             //Set the flag for LV/HV:
00996             detIdStruct.isHV.push_back(0); //LV
00997 
00998             //Set the PSUChannel (I guess for debug purposes?)
00999             detIdStruct.psuName.push_back( PSUChannel );
01000           }
01001         }
01002         //HV case:
01003         else { //if (!LVCase) {
01004           //Debug variables increment:
01005           if (!ids.empty() || !unmapped_ids.empty() || !crosstalking_ids.empty()) {
01006             if (Channel=="channel002") {
01007               ch2bad++;
01008             }
01009             else if (Channel=="channel003") {
01010               ch3bad++;
01011             }
01012           }
01013           //First sum the ids (positively matching detids) and the unmapped_ids (since both should be TURNED OFF):
01014           std::vector<uint32_t> OFFids;
01015           OFFids.insert(OFFids.end(),ids.begin(),ids.end()); //Add the ids (if any!)
01016           OFFids.insert(OFFids.end(),unmapped_ids.begin(),unmapped_ids.end()); //Add the unmapped_ids (if any!)
01017           //Now for the cross-talking ids this is a bit more complicated!
01018           if (!crosstalking_ids.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!
01019             //Set the channel OFF in the CrosstalkingState map!
01020             CrosstalkingState[PSUChannel]=false; //Turn OFF the channel in the state map!
01021             
01022             //Need to check if both channels (HV1==channel002 or HV2==channel003) are OFF!
01023             if (!CrosstalkingState[PSUChannel.substr(0,PSUChannel.size()-1)+"2"] && !CrosstalkingState[PSUChannel.substr(0,PSUChannel.size()-1)+"3"]) { //if HV1 & HV2 both OFF (false)
01024                 OFFids.insert(OFFids.end(),crosstalking_ids.begin(),crosstalking_ids.end()); //Add the crosstalking_ids (if any!) since both HV1 and HV2 are OFF!
01025                 if (debug_) {
01026                   std::cout<<"Adding the unmapped detids corresponding to (HV1/2 cross-talking) PSU "<<PSUChannel.substr(0,PSUChannel.size()-10)<<" to the list of detids turning OFF"<<std::endl;
01027                 }
01028             }
01029           }
01030           //Handle the crosstalking channel by setting it to OFF in the CrosstalkingState map!
01031           if (!unmapped_ids.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!
01032             UnmappedState[PSUChannel]=false; //Turn OFF the channel in the state map!
01033           }
01034           if (!OFFids.empty()) {
01035             //Create a pair with the relevant detIDs (vector) and its timestamp
01036             //And put it in the detidV vector of the detIdStruct that will contain all the 
01037             //results
01038             
01039             //Going OFF HV:
01040             //report not only ids, but also unmapped_ids.
01041             //have to handle crosstalking_ids here... (only OFF if they corresponding PSU HV1/HV2 is off already...
01042             //then add all three vectors to the pair below...
01043             detIdStruct.detidV.push_back( std::make_pair(OFFids,psuStruct.changeDate[dp]) );
01044             
01045             //Set the status to OFF
01046             detIdStruct.StatusGood.push_back(false);
01047             
01048             //debug variable population
01049             numHvBad.insert(numHvBad.end(),ids.begin(),ids.end());
01050 
01051             //Set the flag for LV/HV:
01052             detIdStruct.isHV.push_back(1); //HV
01053 
01054             //Set the PSUChannel (I guess for debug purposes?)
01055             detIdStruct.psuName.push_back( PSUChannel );
01056           }
01057         }
01058       }
01059       //TURNING ON CASE
01060       else {
01061         //Implement the rest of the logic!
01062         //Behavior is different for LV vs HV channels:
01063         //LV case:
01064         if (LVCase) {
01065           //Turn ON all (PSU)matching detids: 
01066           //for the LV case all the detids are automatically reported in the ids vector
01067           //unmapped and crosstalking are only differentiated (relevant) for HV.
01068           if (!ids.empty()) {
01069             //Create a pair with the relevant detIDs (vector) and its timestamp
01070             //And put it in the detidV vector of the detIdStruct that will contain all the 
01071             //results
01072             detIdStruct.detidV.push_back( std::make_pair(ids,psuStruct.changeDate[dp]) );
01073             
01074             //Set the status to ON
01075             detIdStruct.StatusGood.push_back(true);
01076             
01077             //Set the flag for LV/HV:
01078             detIdStruct.isHV.push_back(0); //LV
01079 
01080             //Set the PSUChannel (I guess for debug purposes?)
01081             detIdStruct.psuName.push_back( PSUChannel );
01082           }
01083         }
01084         //HV case:
01085         else { //if (!LVCase) {
01086           //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):
01087           std::vector<uint32_t> ONids;
01088           ONids.insert(ONids.end(),ids.begin(),ids.end()); //Add the ids (if any!)
01089           ONids.insert(ONids.end(),crosstalking_ids.begin(),crosstalking_ids.end()); //Add the crosstalking_ids (if any!)
01090           //Now for the unmapped ids this is a bit more complicated!
01091           if (!unmapped_ids.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!
01092             //Set the HV1 channel on in the UnmappedState map!
01093             UnmappedState[PSUChannel]=true; //Turn ON the channel in the state map!
01094 
01095             //Need to check if BOTH channels (HV1==channel002 or HV2==channel003) are ON!
01096             if (UnmappedState[PSUChannel.substr(0,PSUChannel.size()-1)+"2"] && UnmappedState[PSUChannel.substr(0,PSUChannel.size()-1)+"3"]) { //if HV1 & HV2 are both ON (true)
01097               ONids.insert(ONids.end(),unmapped_ids.begin(),unmapped_ids.end()); //Add the unmapped_ids (if any!) since both HV1 and HV2 are ON!
01098               if (debug_) {
01099                   std::cout<<"Adding the detids corresponding to HV-unmapped PSU "<<PSUChannel.substr(0,PSUChannel.size()-10)<<" to the list of detids turning ON"<<std::endl;
01100                 }
01101             }
01102           }
01103           //Handle the crosstalking channel by setting it to OFF in the CrosstalkingState map!
01104           if (!crosstalking_ids.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!
01105             CrosstalkingState[PSUChannel]=true; //Turn ON the channel in the state map!
01106           }
01107           if (!ONids.empty()) {
01108             //Create a pair with the relevant detIDs (vector) and its timestamp
01109             //And put it in the detidV vector of the detIdStruct that will contain all the 
01110             //results
01111             
01112             //Going OFF HV:
01113             //report not only ids, but also unmapped_ids.
01114             //have to handle crosstalking_ids here... (only OFF if they corresponding PSU HV1/HV2 is off already...
01115             //then add all three vectors to the pair below...
01116             detIdStruct.detidV.push_back( std::make_pair(ONids,psuStruct.changeDate[dp]) );
01117             
01118             //Set the status to ON
01119             detIdStruct.StatusGood.push_back(true);
01120             
01121             //Set the flag for LV/HV:
01122             detIdStruct.isHV.push_back(1); //HV
01123 
01124             //Set the PSUChannel (I guess for debug purposes?)
01125             detIdStruct.psuName.push_back( PSUChannel );
01126           }
01127         }
01128       }
01129     }//End of if dpname not "UNKNOWN" 
01130     else {
01131       //if (debug) {
01132       //std::cout<<"PSU Channel name WAS NOT RECOGNIZED"<<std::endl;
01133       //}
01134       detIdStruct.notMatched++;
01135     }
01136   }//End of the loop over all PSUChannels reported by the DB query.
01137   //At this point we need to (over)write the 2 files that will keep the HVUnmapped and HVCrosstalking channels status:
01138   ofstream ofsUnmapped("HVUnmappedChannelState.dat");
01139   for (std::map<std::string,bool>::iterator it=UnmappedState.begin(); it!=UnmappedState.end(); it++) {
01140     ofsUnmapped<<it->first<<"\t"<<it->second<<std::endl;
01141   }
01142   ofstream ofsCrosstalking("HVCrosstalkingChannelState.dat");
01143   for (std::map<std::string,bool>::iterator it=CrosstalkingState.begin(); it!=CrosstalkingState.end(); it++) {
01144     ofsCrosstalking<<it->first<<"\t"<<it->second<<std::endl;
01145   }
01146 
01147   removeDuplicates(numLvBad);
01148   removeDuplicates(numHvBad);
01149 
01150 
01151   // useful debugging stuff!
01152   if( debug_ ) {
01153     std::cout << "Number of channels that turned OFF in this O2O interval"<<std::endl;
01154     std::cout << "Channel000 = " << ch0bad << " Channel001 = " << ch1bad << std::endl;
01155     std::cout << "Channel002 = " << ch2bad << " Channel003 = " << ch3bad << std::endl;
01156     std::cout << "Number of LV detIDs that turned OFF in this O2O interval = " << numLvBad.size() << std::endl;
01157     std::cout << "Number of HV detIDs that turned OFF in this O2O interval = " << numHvBad.size() << std::endl;
01158   }
01159 
01160   LogTrace("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::" << __func__ << "]: Number of PSUs retrieved from DB with map information    " << detIdStruct.detidV.size();
01161   LogTrace("SiStripDetVOffBuilder") << "[SiStripDetVOffBuilder::" << __func__ << "]: Number of PSUs retrieved from DB with no map information " << detIdStruct.notMatched;
01162   
01163   unsigned int dupCount = 0;
01164   for (unsigned int t = 0; t < numLvBad.size(); t++) {
01165     std::vector<unsigned int>::iterator iter = std::find(numHvBad.begin(),numHvBad.end(),numLvBad[t]);
01166     if (iter != numHvBad.end()) {dupCount++;}
01167   }
01168   if( debug_ ) std::cout << "Number of channels for which LV & HV turned OFF in this O2O interval = " << dupCount << std::endl;
01169   
01170 }
01171 
01172 void SiStripDetVOffBuilder::setPayloadStats(const uint32_t afterV, const uint32_t numAdded, const uint32_t numRemoved)
01173 {
01174   std::vector<uint32_t> pStats(3,0);
01175   pStats.push_back(afterV);
01176   pStats.push_back(numAdded);
01177   pStats.push_back(numRemoved);
01178   payloadStats.push_back(pStats);
01179 }
01180 
01181 pair<int, int> SiStripDetVOffBuilder::extractDetIdVector( const unsigned int i, SiStripDetVOff * modV, DetIdListTimeAndStatus & detIdStruct )
01182 {
01183   // set the LV and HV off flags ready for storing
01184   int lv_off = -1, hv_off = -1;
01185   if (detIdStruct.isHV[i] == 0) {lv_off = !(detIdStruct.StatusGood[i]);}
01186   if (detIdStruct.isHV[i] == 1) {
01187     hv_off = !(detIdStruct.StatusGood[i]);
01188 
01189     // TESTING WITHOUT THE FIX
01190     // -----------------------
01191 
01192     if( psuDetIdMapFile_ == "" ) {
01193       // temporary fix to handle the fact that we don't know which HV channel the detIDs are associated to
01194       if (i > 0) {
01195         std::string iChannel = detIdStruct.psuName[i].substr( (detIdStruct.psuName[i].size()-3) );
01196         std::string iPsu = detIdStruct.psuName[i].substr(0, (detIdStruct.psuName[i].size()-3) );
01197         if (iChannel == "002" || iChannel == "003") {
01198           bool lastStatusOfOtherChannel = true;
01199           for (unsigned int j = 0; j < i; j++) {
01200             std::string jPsu = detIdStruct.psuName[j].substr(0, (detIdStruct.psuName[j].size()-3) );
01201             std::string jChannel = detIdStruct.psuName[j].substr( (detIdStruct.psuName[j].size()-3) );
01202             if (iPsu == jPsu && iChannel != jChannel && (jChannel == "002" || jChannel == "003")) {
01203               if( debug_ ) cout << "psu["<<i<<"] = " << detIdStruct.psuName[i] << " with status = " << detIdStruct.StatusGood[i] << " and psu["<<j<<"] = " << detIdStruct.psuName[j] << " with status " << detIdStruct.StatusGood[j] << endl;
01204               lastStatusOfOtherChannel = detIdStruct.StatusGood[j];
01205             }
01206           }
01207           if (detIdStruct.StatusGood[i] != lastStatusOfOtherChannel) {
01208             if( debug_ ) cout << "turning off hv" << endl;
01209             hv_off = 1;
01210           }
01211         }
01212       }
01213     }
01214 
01215     // -----------------------
01216 
01217   }
01218 
01219   return make_pair(hv_off, lv_off);
01220 }