35 _analysisname(analysisname),
39 _hltProcessName(pset.getParameter<std::
string>(
"hltProcessName")),
40 _histDirectory(pset.getParameter<std::
string>(
"histDirectory")),
43 _recoHtJetLabel(iC.consumes<
reco::
PFJetCollection>(pset.getUntrackedParameter<std::
string>(
"recoHtJetLabel",
"ak4PFJetsCHS"))),
44 _parametersEta(pset.getParameter<std::vector<double> >(
"parametersEta")),
45 _parametersPhi(pset.getParameter<std::vector<double> >(
"parametersPhi")),
46 _parametersPu(pset.getParameter<std::vector<double> >(
"parametersPu")),
48 _parametersTurnOn(pset.getParameter<std::vector<double> >(
"parametersTurnOn")),
53 _recCaloMETSelector(0),
56 _recPhotonSelector(0),
66 if( anpset.
exists(
"parametersTurnOn") )
73 for(std::map<unsigned int,std::string>::const_iterator it =
_recLabels.begin();
83 for(std::map<unsigned int,std::string>::const_iterator it =
_recLabels.begin();
95 if(anpset.
existsAs<
double>( objStr+
"_cutMinPt" ,
false) )
99 if(anpset.
existsAs<
double>( objStr+
"_cutMaxEta" ,
false) )
107 std::vector<double> default_parametersHt;
108 default_parametersHt.push_back(100);
109 default_parametersHt.push_back(0);
110 default_parametersHt.push_back(1000);
116 if( _HtJetPtMin>0 && _HtJetEtaMax>0 )
_bookHtPlots =
true;
119 if( pset.
exists(
"pileUpInfoLabel") )
124 if( anpset.
existsAs<std::vector<double>>(
"NminOneCuts" ,
false) )
128 edm::LogError(
"HiggsValidation") <<
"In HLTHiggsSubAnalysis::HLTHiggsSubAnalysis, "
129 <<
"Incoherence found in the python configuration file!!\nThe SubAnalysis '"
131 <<
_NminOneCuts.size() <<
", while it needs to be at least of size "
188 edm::LogError(
"HiggsValidations") <<
"HLTHiggsSubAnalysis::beginRun: "
189 <<
"Initializtion of HLTConfigProvider failed!!";
203 if(TString(thetriggername).Contains(pattern))
211 LogDebug(
"HiggsValidations") <<
"HLTHiggsSubAnalysis::beginRun, In "
218 <<
"\nHLT Trigger Paths found >>>";
221 for(std::set<std::string>::iterator iPath =
_hltPaths.begin();
228 if(path.rfind(
"_v") < path.length())
230 shortpath = path.substr(0, path.rfind(
"_v"));
235 const std::vector<unsigned int> objsNeedHLT = this->
getObjectsType(shortpath);
238 std::vector<unsigned int> userInstantiate;
239 for(std::map<unsigned int,std::string>::iterator it =
_recLabels.begin() ;
242 userInstantiate.push_back(it->first);
244 for(std::vector<unsigned int>::const_iterator it = objsNeedHLT.begin(); it != objsNeedHLT.end();
247 if(
std::find(userInstantiate.begin(),userInstantiate.end(), *it) ==
248 userInstantiate.end() )
250 edm::LogError(
"HiggsValidation") <<
"In HLTHiggsSubAnalysis::beginRun, "
251 <<
"Incoherence found in the python configuration file!!\nThe SubAnalysis '"
252 <<
_analysisname <<
"' has been asked to evaluate the trigger path '"
253 << shortpath <<
"' (found it in 'hltPathsToCheck') BUT this path"
255 <<
"' which has not been instantiate ('recVariableLabels'"
260 LogTrace(
"HiggsValidation") <<
" --- " << shortpath;
274 std::vector<std::string> sources(2);
278 for(std::map<unsigned int,std::string>::const_iterator it =
_recLabels.begin();
284 for(
size_t i = 0;
i < sources.size();
i++)
288 if( source ==
"gen" )
continue;
296 else bookHist(source, objStr,
"CSV1", ibooker);
303 bookHist(source, objStr,
"Eta", ibooker);
304 bookHist(source, objStr,
"Phi", ibooker);
309 bookHist(source, objStr, maxPt.Data(), ibooker);
315 for(std::vector<HLTHiggsPlotter>::iterator it =
_analyzers.begin();
321 for(
size_t i = 0;
i < sources.size();
i++)
323 std::string nameGlobalEfficiency =
"SummaryPaths_"+_analysisname+
"_"+sources[
i];
327 std::string nameGlobalEfficiencyPassing= nameGlobalEfficiency+
"_passingHLT";
330 std::string titlePu =
"nb of interations in the event";
331 std::string nameVtxPlot =
"trueVtxDist_"+_analysisname+
"_"+sources[
i];
333 int nBinsPu = (int)paramsPu[0];
334 double minPu = paramsPu[1];
335 double maxPu = paramsPu[2];
337 std::string titleHt =
"sum of jet pT in the event";
338 std::string nameHtPlot =
"HtDist_"+_analysisname+
"_"+sources[
i];
340 int nBinsHt = (int)paramsHt[0];
341 double minHt = paramsHt[1];
342 double maxHt = paramsHt[2];
344 _elements[nameVtxPlot] = ibooker.
book1D(nameVtxPlot.c_str(), titlePu.c_str(), nBinsPu, minPu, maxPu);
350 if(path.rfind(
"_v") < path.length())
352 shortpath = path.substr(0, path.rfind(
"_v"));
354 std::string titlePassingPu =
"nb of interations in the event passing path " + shortpath;
355 _elements[nameVtxPlot+
"_"+shortpath] = ibooker.
book1D(nameVtxPlot+
"_"+shortpath, titlePassingPu.c_str(), nBinsPu, minPu, maxPu);
357 std::string titlePassingHt =
"sum of jet pT in the event passing path " + shortpath;
361 _elements[nameGlobalEfficiency]->setBinLabel(
j+1,shortpath);
362 _elements[nameGlobalEfficiencyPassing]->setBinLabel(
j+1,shortpath);
375 std::map<unsigned int,std::string> u2str;
379 std::map<unsigned int,double> Htmap;
387 std::vector<PileupSummaryInfo>::const_iterator PVI;
388 for(PVI = puInfo->begin(); PVI != puInfo->end(); ++PVI) {
389 if(PVI->getBunchCrossing()==0){
390 nbMCvtx = PVI->getPU_NumInteractions();
401 std::vector<MatchStruct> * matches =
new std::vector<MatchStruct>;
403 for(std::map<unsigned int,std::string>::iterator it =
_recLabels.begin();
418 for(
size_t i = 0;
i < cols->
genJets->size(); ++
i)
458 std::map<unsigned int,std::vector<MatchStruct> > sourceMatchMap;
460 sourceMatchMap[
GEN] = *matches;
467 std::map<std::string,bool> nMinOne;
468 std::map<std::string,bool> jetCutResult;
475 bool passAllCuts =
false;
488 this->
passJetCuts(matches, jetCutResult, dEtaqq, mqq, dPhibb, CSV1, CSV2, CSV3);
492 for(std::map<unsigned int,std::string>::iterator it =
_recLabels.begin();
510 for(std::map<std::string,bool>::const_iterator it = jetCutResult.begin(); it != jetCutResult.end(); ++it)
512 nMinOne[it->first] =
true;
513 for(std::map<std::string,bool>::const_iterator it2 = jetCutResult.begin(); it2 != jetCutResult.end(); ++it2)
516 if( it->first==
"CSV1" && it2->first==
"CSV3")
continue;
517 if( it->first==
"CSV1" && it2->first==
"CSV2")
continue;
520 if( it->first==
"CSV2" && it2->first==
"CSV3")
continue;
522 if( it->first != it2->first && !(it2->second) ) {
523 nMinOne[it->first] =
false;
529 for(std::map<std::string,bool>::const_iterator it = nMinOne.begin(); it != nMinOne.end(); ++it)
531 if( temp && it->second ) {
535 if( it->second ) temp =
true;
540 sourceMatchMap[
RECO] = *matches;
551 for( reco::PFJetCollection::const_iterator iJet = recoJet->begin(); iJet != recoJet->end(); iJet++ ){
552 double pt = iJet->pt();
553 double eta = iJet->eta();
563 for( reco::GenJetCollection::const_iterator iJet = genJet->begin(); iJet != genJet->end(); iJet++ ){
564 double pt = iJet->pt();
565 double eta = iJet->eta();
575 for(
std::map<
unsigned int,std::vector<MatchStruct> >::iterator it = sourceMatchMap.begin();
576 it != sourceMatchMap.end(); ++it)
586 std::map<unsigned int,int> * countobjects =
new std::map<unsigned int,int>;
588 for(std::map<unsigned int,std::string>::iterator co =
_recLabels.begin();
592 countobjects->insert(std::pair<unsigned int,int>(co->first,0));
595 const int totalobjectssize2 =
NptPlots*countobjects->size();
596 for(
size_t j = 0;
j < it->second.size(); ++
j)
598 const unsigned int objType = it->second[
j].objType;
601 float pt = (it->second)[
j].pt;
602 float eta = (it->second)[
j].eta;
603 float phi = (it->second)[
j].phi;
611 if( (
unsigned)(*countobjects)[objType] <
NptPlots )
614 maxPt += (*countobjects)[objType]+1;
616 if( nMinOne[maxPt.Data()] )
618 this->
fillHist(u2str[it->first],objTypeStr,maxPt.Data(),
pt);
622 this->
fillHist(u2str[it->first],objTypeStr,maxPt.Data(),
pt);
625 ++((*countobjects)[objType]);
630 ++((*countobjects)[objType]);
639 this->
fillHist(u2str[it->first],objTypeStr,
"Eta",eta);
640 this->
fillHist(u2str[it->first],objTypeStr,
"Phi",phi);
644 this->
fillHist(u2str[it->first],objTypeStr,
"Eta",eta);
645 this->
fillHist(u2str[it->first],objTypeStr,
"Phi",phi);
649 if( counttotal == totalobjectssize2 )
691 for(std::vector<HLTHiggsPlotter>::iterator an =
_analyzers.begin();
695 const std::string fillShortPath = an->gethltpath();
699 an->analyze(ispassTrigger,source,it->second, nMinOne, dEtaqq, mqq, dPhibb, CSV1, CSV2, CSV3, passAllCuts);
705 int refOfThePath = -1;
710 _elements[SummaryName]->Fill(refOfThePath);
712 _elements[SummaryName+
"_passingHLT"]->Fill(refOfThePath,1);
713 _elements[nameVtxPlot+
"_"+fillShortPath.c_str()]->Fill(nbMCvtx);
717 _elements[SummaryName+
"_passingHLT"]->Fill(refOfThePath,0);
727 static const unsigned int objSize = 7;
728 static const unsigned int objtriggernames[] = {
739 std::set<unsigned int> objsType;
741 for(
unsigned int i = 0;
i < objSize; ++
i)
745 if( ! TString(hltPath).Contains(objTypeStr) )
749 objsType.insert(objtriggernames[i]);
750 else if (objtriggernames[i] ==
EVTColContainer::PHOTON && TString(hltPath).Contains(
"Diphoton") ) objsType.insert(objtriggernames[i]);
753 if( objtriggernames[i] ==
EVTColContainer::CALOMET && (TString(hltPath).Contains(
"PFMET") || TString(hltPath).Contains(
"MHT") ) )
continue;
755 objsType.insert(objtriggernames[i]);
758 return std::vector<unsigned int>(objsType.begin(),objsType.end());
765 if( anpset.
exists(
"recMuonLabel") )
771 if( anpset.
exists(
"recElecLabel") )
777 if( anpset.
exists(
"recPhotonLabel") )
783 if( anpset.
exists(
"recCaloMETLabel") )
789 if( anpset.
exists(
"recPFMETLabel") )
795 if( anpset.
exists(
"recPFTauLabel") )
801 if( anpset.
exists(
"recJetLabel") )
805 if( anpset.
exists(
"jetTagLabel") )
817 edm::LogError(
"HiggsValidation") <<
"HLTHiggsSubAnalysis::bookobjects, "
818 <<
"Not included any object (recMuonLabel, recElecLabel, ...) "
850 for(std::map<unsigned int,std::string>::iterator it =
_recLabels.begin();
904 edm::LogError(
"HiggsValidation") <<
"HLTHiggsSubAnalysis::initobjects "
905 <<
" NOT IMPLEMENTED (yet) ERROR: '" << it->second <<
"'";
915 sourceUpper[0] = std::toupper(sourceUpper[0]);
919 if(variable.find(
"MaxPt") != std::string::npos)
922 if (variable ==
"MaxPt1") desc =
"Leading";
923 else if (variable ==
"MaxPt2") desc =
"Next-to-Leading";
924 else desc = variable.substr(5,6) +
"th Leading";
927 size_t nBins = nBinsStandard;
928 float *
edges =
new float[nBinsStandard + 1];
929 for(
size_t i = 0;
i < nBinsStandard + 1;
i++)
935 if( objType == jetObj ) {
936 const size_t nBinsJets = 25;
939 edges =
new float[nBinsJets+1];
940 for(
size_t i = 0;
i < nBinsJets + 1;
i++)
946 const size_t nBinsJets = 30;
949 edges =
new float[nBinsJets+1];
950 for(
size_t i = 0;
i < nBinsJets + 1;
i++)
955 h =
new TH1F(name.c_str(), title.c_str(), nBins,
edges);
958 else if( variable ==
"dEtaqq" ){
963 h =
new TH1F(name.c_str(), title.c_str(), nBins,
min,
max);
965 else if ( variable ==
"mqq" ){
970 h =
new TH1F(name.c_str(), title.c_str(), nBins,
min,
max);
972 else if ( variable ==
"dPhibb" ){
977 h =
new TH1F(name.c_str(), title.c_str(), nBins,
min,
max);
979 else if ( variable ==
"CSV1" ){
984 h =
new TH1F(name.c_str(), title.c_str(), nBins,
min,
max);
986 else if ( variable ==
"CSV2" ){
991 h =
new TH1F(name.c_str(), title.c_str(), nBins,
min,
max);
993 else if ( variable ==
"CSV3" ){
998 h =
new TH1F(name.c_str(), title.c_str(), nBins,
min,
max);
1000 else if ( variable ==
"maxCSV" ){
1005 h =
new TH1F(name.c_str(), title.c_str(), nBins,
min,
max);
1009 std::string symbol = (variable ==
"Eta") ?
"#eta" :
"#phi";
1013 int nBins = (int)params[0];
1014 double min = params[1];
1015 double max = params[2];
1016 h =
new TH1F(name.c_str(), title.c_str(), nBins,
min,
max);
1027 sourceUpper[0] = toupper(sourceUpper[0]);
1077 std::vector<MatchStruct> * matches)
1088 for(reco::PFJetCollection::const_iterator it = PFJetHandle->begin();
1089 it != PFJetHandle->end(); ++it)
1098 float bTag = (*(JetTagHandle.
product()))[jetBaseRef];
1108 void HLTHiggsSubAnalysis::passJetCuts(std::vector<MatchStruct> * matches, std::map<std::string,bool> & jetCutResult,
float & dEtaqq,
float & mqq,
float & dPhibb,
float & CSV1,
float & CSV2,
float & CSV3)
1118 if( (*matches)[
i].pt >
_NminOneCuts[9+
i] ) jetCutResult[maxPt.Data()] =
true;
1119 else jetCutResult[maxPt.Data()] =
false;
1123 if( matches->size() < NbTag ) NbTag = matches->size();
1128 dEtaqq = fabs((*matches)[2].
eta - (*matches)[3].
eta);
1129 if( dEtaqq >
_NminOneCuts[0] ) jetCutResult[
"dEtaqq"] =
true;
1130 else jetCutResult[
"dEtaqq"] =
false;
1134 mqq = ((*matches)[2].lorentzVector + (*matches)[3].lorentzVector).M();
1135 if( mqq >
_NminOneCuts[1] ) jetCutResult[
"mqq"] =
true;
1136 else jetCutResult[
"mqq"] =
false;
1140 dPhibb = fmod(fabs((*matches)[0].
phi - (*matches)[1].
phi),3.1416);
1141 if( dPhibb <
_NminOneCuts[2] ) jetCutResult[
"dPhibb"] =
true;
1142 else jetCutResult[
"dPhibb"] =
false;
1146 CSV2 = (*matches)[1].bTag;
1149 if( CSV2 >
_NminOneCuts[4] ) jetCutResult[nameCSV2plot] =
true;
1150 else jetCutResult[nameCSV2plot] =
false;
1154 CSV3 = (*matches)[2].bTag;
1157 if( CSV3 >
_NminOneCuts[5] ) jetCutResult[nameCSV3plot] =
true;
1158 else jetCutResult[nameCSV3plot] =
false;
1163 CSV1 = (*matches)[0].bTag;
1167 if( CSV1 >
_NminOneCuts[3] ) jetCutResult[nameCSVplot] =
true;
1168 else jetCutResult[nameCSVplot] =
false;
1173 CSV1 = (*matches)[0].bTag;
1175 if (
_NminOneCuts[6] > matches->size()) Njets = matches->size();
1176 for(
unsigned int i=1;
i < (
unsigned int) Njets ; ++
i) {
1177 if( (*matches)[
i].bTag > CSV1 && (*matches)[
i].pt >
_NminOneCuts[7] ) CSV1 = (*matches)[
i].bTag;
1185 jetCutResult[
"PFMET"] =
false;
1186 for(std::vector<MatchStruct>::const_iterator it = matches.begin(); it != matches.end(); ++it)
1189 if( it->pt >
_NminOneCuts[8] ) jetCutResult[
"PFMET"] =
true;
1197 std::vector<MatchStruct> * matches)
1201 for(
size_t i = 0;
i < cols->
muons->size();
i++)
1221 for(
size_t i = 0;
i < cols->
photons->size();
i++)
1231 for(
size_t i = 0;
i < cols->
caloMETs->size();
i++)
1241 for(
size_t i = 0;
i < cols->
pfMETs->size();
i++)
1251 for(
size_t i = 0;
i < cols->
pfTaus->size();
i++)
const std::vector< reco::Muon > * muons
std::vector< double > _parametersTurnOn
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
std::vector< GenParticle > GenParticleCollection
collection of GenParticles
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
void InitSelector(const unsigned int &objtype)
virtual edm::TriggerNames const & triggerNames(edm::TriggerResults const &triggerResults) const
std::map< std::string, std::string > _shortpath2long
Relation between the short version of a path.
StringCutObjectSelector< reco::CaloMET > * _recCaloMETSelector
std::vector< PFTau > PFTauCollection
collection of PFTau objects
edm::EDGetTokenT< reco::PFMETCollection > _recLabelsPFMET
edm::EDGetTokenT< reco::PFJetCollection > _recLabelsPFJet
bool existsAs(std::string const ¶meterName, bool trackiness=true) const
checks if a parameter exists as a given type
edm::EDGetTokenT< reco::GenParticleCollection > _genParticleLabel
void passJetCuts(std::vector< MatchStruct > *matches, std::map< std::string, bool > &jetCutResult, float &dEtaqq, float &mqq, float &dPhibb, float &CSV1, float &CSV2, float &CSV3)
std::map< unsigned int, std::string > _genCut
gen/rec objects cuts
void initobjects(const edm::Event &iEvent, EVTColContainer *col)
edm::EDGetTokenT< reco::PFJetCollection > _recoHtJetLabel
const std::vector< reco::CaloMET > * caloMETs
bool getByToken(EDGetToken token, Handle< PROD > &result) const
edm::EDGetTokenT< reco::PFTauCollection > _recLabelsPFTau
unsigned int _minCandidates
The minimum number of reco/gen candidates needed by the analysis.
std::map< std::string, MonitorElement * > _elements
std::vector< double > _NminOneCuts
bool accept() const
Has at least one path accepted the event?
std::vector< GenJet > GenJetCollection
collection of GenJet objects
const std::vector< std::string > & triggerNames() const
names of trigger paths
bool exists(std::string const ¶meterName) const
checks if a parameter exists
std::set< std::string > _hltPaths
the hlt paths found in the hltConfig
const reco::GenParticleCollection * genParticles
container with all the objects needed
StringCutObjectSelector< reco::PFMET > * _recPFMETSelector
edm::EDGetTokenT< reco::GenJetCollection > _genJetLabel
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
HLTConfigProvider _hltConfig
edm::EDGetTokenT< reco::JetTagCollection > _recTagPFJet
std::vector< GsfElectron > GsfElectronCollection
collection of GsfElectron objects
const std::vector< reco::PFTau > * pfTaus
std::vector< Muon > MuonCollection
collection of Muon objects
void bookHistograms(DQMStore::IBooker &)
std::vector< double > _parametersPu
edm::EDGetTokenT< reco::PhotonCollection > _recLabelsPhoton
edm::EDGetTokenT< reco::CaloMETCollection > _recLabelsCaloMET
StringCutObjectSelector< reco::Track > * _recTrackSelector
std::map< unsigned int, std::string > _recCut
void passOtherCuts(const std::vector< MatchStruct > &matches, std::map< std::string, bool > &jetCutResult)
std::map< unsigned int, StringCutObjectSelector< reco::GenParticle > * > _genSelectorMap
void set(const reco::MuonCollection *v)
Setter: multiple overloaded function.
tuple path
else: Piece not in the list, fine.
const reco::GenJetCollection * genJets
unsigned int triggerIndex(std::string const &name) const
std::string _hltProcessName
StringCutObjectSelector< reco::GenJet > * _genJetSelector
void initAndInsertJets(const edm::Event &iEvent, EVTColContainer *cols, std::vector< MatchStruct > *matches)
void addParameter(std::string const &name, T const &value)
edm::EDGetTokenT< std::vector< PileupSummaryInfo > > _puSummaryInfo
std::vector< HLTHiggsPlotter > _analyzers
MonitorElement * book1D(Args &&...args)
std::map< unsigned int, std::string > _recLabels
const std::vector< reco::Photon > * photons
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
void analyze(const edm::Event &iEvent, const edm::EventSetup &iEventSetup, EVTColContainer *cols)
std::map< unsigned int, double > _cutMinPt
StringCutObjectSelector< reco::PFTau > * _recPFTauSelector
void beginRun(const edm::Run &iRun, const edm::EventSetup &iEventSetup)
edm::EDGetTokenT< edm::TriggerResults > _trigResultsTag
static const char *const trigNames[]
void bookHist(const std::string &source, const std::string &objType, const std::string &variable, DQMStore::IBooker &)
void setCurrentFolder(const std::string &fullpath)
std::vector< reco::CaloMET > CaloMETCollection
collection of CaloMET objects
std::vector< double > _parametersHt
edm::EDGetTokenT< reco::GsfElectronCollection > _recLabelsElec
HLTHiggsSubAnalysis(const edm::ParameterSet &pset, const std::string &analysisname, edm::ConsumesCollector &&iC)
T const * product() const
StringCutObjectSelector< reco::Muon > * _recMuonSelector
std::string _histDirectory
void fillHist(const std::string &source, const std::string &objType, const std::string &variable, const float &value)
std::vector< Photon > PhotonCollection
collectin of Photon objects
bool init(const edm::Run &iRun, const edm::EventSetup &iSetup, const std::string &processName, bool &changed)
d'tor
const std::vector< reco::GsfElectron > * electrons
Helper structure to order MatchStruct.
const std::vector< unsigned int > getObjectsType(const std::string &hltpath) const
Extract what objects need this analysis.
void insertcandidates(const unsigned int &objtype, const EVTColContainer *col, std::vector< MatchStruct > *matches)
std::vector< PFJet > PFJetCollection
collection of PFJet objects
edm::EDGetTokenT< reco::MuonCollection > _recLabelsMuon
std::vector< double > _parametersPhi
std::string _analysisname
std::vector< std::string > _hltPathsToCheck
the hlt paths with regular expressions
std::vector< reco::PFMET > PFMETCollection
collection of PFMET objects
std::vector< double > _parametersEta
Some kinematical parameters.
std::map< unsigned int, double > _cutMaxEta
void bookobjects(const edm::ParameterSet &anpset, edm::ConsumesCollector &iC)
StringCutObjectSelector< reco::Photon > * _recPhotonSelector
const std::vector< reco::PFMET > * pfMETs
StringCutObjectSelector< reco::PFJet > * _recPFJetSelector
static const std::string getTypeString(const unsigned int &objtype)
Tranform types into strings.
const edm::TriggerResults * triggerResults
static std::string const source
StringCutObjectSelector< reco::GsfElectron > * _recElecSelector