#include <RecoEgamma/EgammaElectronAlgos/interface/GsfElectronAlgo.h>
Description: top algorithm producing TrackCandidate and Electron objects from supercluster driven pixel seeded Ckf tracking.
Definition at line 35 of file GsfElectronAlgo.h.
GsfElectronAlgo::GsfElectronAlgo | ( | const edm::ParameterSet & | conf, | |
double | maxEOverPBarrel, | |||
double | maxEOverPEndcaps, | |||
double | minEOverPBarrel, | |||
double | minEOverPEndcaps, | |||
double | maxDeltaEta, | |||
double | maxDeltaPhi, | |||
bool | highPtPresel, | |||
double | highPtMin, | |||
bool | applyEtaCorrection, | |||
bool | applyAmbResolution | |||
) |
Definition at line 84 of file GsfElectronAlgo.cc.
References geomPropBw_, geomPropFw_, edm::ParameterSet::getParameter(), hcalRecHits_, mtsTransform_, and tracks_.
00089 : 00090 maxEOverPBarrel_(maxEOverPBarrel), maxEOverPEndcaps_(maxEOverPEndcaps), 00091 minEOverPBarrel_(minEOverPBarrel), minEOverPEndcaps_(minEOverPEndcaps), 00092 maxDeltaEta_(maxDeltaEta), maxDeltaPhi_(maxDeltaPhi), 00093 highPtPreselection_(highPtPresel), highPtMin_(highPtMin), 00094 applyEtaCorrection_(applyEtaCorrection), applyAmbResolution_(applyAmbResolution), 00095 cacheIDGeom_(0),cacheIDTDGeom_(0),cacheIDMagField_(0) 00096 { 00097 // this is the new version allowing to configurate the algo 00098 // interfaces still need improvement!! 00099 mtsTransform_ = new MultiTrajectoryStateTransform; 00100 geomPropBw_=0; 00101 geomPropFw_=0; 00102 00103 // get nested parameter set for the TransientInitialStateEstimator 00104 ParameterSet tise_params = conf.getParameter<ParameterSet>("TransientInitialStateEstimatorParameters") ; 00105 00106 // get input collections 00107 hcalRecHits_ = conf.getParameter<edm::InputTag>("hcalRecHits"); 00108 tracks_ = conf.getParameter<edm::InputTag>("tracks"); 00109 00110 }
GsfElectronAlgo::~GsfElectronAlgo | ( | ) |
Definition at line 112 of file GsfElectronAlgo.cc.
References geomPropBw_, geomPropFw_, and mtsTransform_.
00112 { 00113 delete geomPropBw_; 00114 delete geomPropFw_; 00115 delete mtsTransform_; 00116 }
bool GsfElectronAlgo::calculateTSOS | ( | const reco::GsfTrack & | t, | |
const reco::SuperCluster & | theClus, | |||
const math::XYZPoint & | bs | |||
) | [private] |
Definition at line 372 of file GsfElectronAlgo.cc.
References MultiTrajectoryStateTransform::innerStateOnSurface(), innTSOS_, TrajectoryStateOnSurface::isValid(), mtsTransform_, MultiTrajectoryStateTransform::outerStateOnSurface(), outTSOS_, edm::ESHandle< T >::product(), sclTSOS_, reco::SuperCluster::seed(), seedTSOS_, theMagField, trackerHandle_, vtxTSOS_, reco::CaloCluster::x(), reco::CaloCluster::y(), and reco::CaloCluster::z().
Referenced by process().
00373 { 00374 00375 //at innermost point 00376 innTSOS_ = mtsTransform_->innerStateOnSurface(t, *(trackerHandle_.product()), theMagField.product()); 00377 if (!innTSOS_.isValid()) return false; 00378 00379 //at vertex 00380 // innermost state propagation to the beam spot position 00381 vtxTSOS_ 00382 = TransverseImpactPointExtrapolator(*geomPropBw_).extrapolate(innTSOS_,GlobalPoint(bsPosition.x(),bsPosition.y(),bsPosition.z())); 00383 if (!vtxTSOS_.isValid()) vtxTSOS_=innTSOS_; 00384 00385 //at seed 00386 outTSOS_ 00387 = mtsTransform_->outerStateOnSurface(t, *(trackerHandle_.product()), theMagField.product()); 00388 if (!outTSOS_.isValid()) return false; 00389 00390 // TrajectoryStateOnSurface seedTSOS 00391 seedTSOS_ 00392 = TransverseImpactPointExtrapolator(*geomPropFw_).extrapolate(outTSOS_,GlobalPoint(theClus.seed()->position().x(),theClus.seed()->position().y(),theClus.seed()->position().z())); 00393 if (!seedTSOS_.isValid()) seedTSOS_=outTSOS_; 00394 00395 //at scl 00396 sclTSOS_ 00397 = TransverseImpactPointExtrapolator(*geomPropFw_).extrapolate(innTSOS_,GlobalPoint(theClus.x(),theClus.y(),theClus.z())); 00398 if (!sclTSOS_.isValid()) sclTSOS_=outTSOS_; 00399 return true; 00400 }
GlobalVector GsfElectronAlgo::computeMode | ( | const TrajectoryStateOnSurface & | tsos | ) | [private] |
Definition at line 286 of file GsfElectronAlgo.cc.
References TrajectoryStateOnSurface::components(), TrajectoryStateOnSurface::isValid(), SingleGaussianState1D::mean(), and GaussianSumUtilities1D::mode().
Referenced by createElectron(), and process().
00286 { 00287 00288 // mode computation for momentum cartesian co-ordinates 00289 // change to 5D in local parameters?? 00290 float mode_Px = 0.; 00291 float mode_Py = 0.; 00292 float mode_Pz = 0.; 00293 if ( tsos.isValid() ){ 00294 std::vector<TrajectoryStateOnSurface> components(tsos.components()); 00295 unsigned int numb = components.size(); 00296 std::vector<SingleGaussianState1D> pxStates; pxStates.reserve(numb); 00297 std::vector<SingleGaussianState1D> pyStates; pyStates.reserve(numb); 00298 std::vector<SingleGaussianState1D> pzStates; pzStates.reserve(numb); 00299 for ( std::vector<TrajectoryStateOnSurface>::const_iterator ic=components.begin(); 00300 ic!=components.end(); ++ic ) { 00301 GlobalVector momentum(ic->globalMomentum()); 00302 AlgebraicSymMatrix66 cov(ic->cartesianError().matrix()); 00303 pxStates.push_back(SingleGaussianState1D(momentum.x(),cov(3,3),ic->weight())); 00304 pyStates.push_back(SingleGaussianState1D(momentum.y(),cov(4,4),ic->weight())); 00305 pzStates.push_back(SingleGaussianState1D(momentum.z(),cov(5,5),ic->weight())); 00306 } 00307 MultiGaussianState1D pxState(pxStates); 00308 MultiGaussianState1D pyState(pyStates); 00309 MultiGaussianState1D pzState(pzStates); 00310 GaussianSumUtilities1D pxUtils(pxState); 00311 GaussianSumUtilities1D pyUtils(pyState); 00312 GaussianSumUtilities1D pzUtils(pzState); 00313 mode_Px = pxUtils.mode().mean(); 00314 mode_Py = pyUtils.mode().mean(); 00315 mode_Pz = pzUtils.mode().mean(); 00316 } else edm::LogInfo("") << "tsos not valid!!"; 00317 return GlobalVector(mode_Px,mode_Py,mode_Pz); 00318 00319 }
void GsfElectronAlgo::createElectron | ( | const reco::SuperClusterRef & | scRef, | |
const reco::GsfTrackRef & | trackRef, | |||
reco::GsfElectronCollection & | outEle | |||
) | [private] |
Definition at line 322 of file GsfElectronAlgo.cc.
References applyEtaCorrection_, computeMode(), ElectronEnergyCorrector::correct(), ElectronMomentumCorrector::correct(), ElectronClassification::correct(), ECALPositionCalculator::ecalEta(), ECALPositionCalculator::ecalPhi(), TrajectoryStateOnSurface::globalPosition(), innTSOS_, PV3DBase< T, PVType, FrameType >::mag(), mhbhe_, outTSOS_, pi, edm::ESHandle< T >::product(), scale, sclPos_, sclTSOS_, seedTSOS_, reco::GsfElectron::setDeltaEtaSuperClusterAtVtx(), reco::GsfElectron::setDeltaPhiSuperClusterAtVtx(), theCaloGeom, theMagField, reco::btau::trackEta, reco::btau::trackPhi, vtxMom_, vtxTSOS_, PV3DBase< T, PVType, FrameType >::x(), PV3DBase< T, PVType, FrameType >::y(), and PV3DBase< T, PVType, FrameType >::z().
Referenced by process().
00322 { 00323 GlobalVector innMom=computeMode(innTSOS_); 00324 GlobalPoint innPos=innTSOS_.globalPosition(); 00325 GlobalVector seedMom=computeMode(seedTSOS_); 00326 GlobalPoint seedPos=seedTSOS_.globalPosition(); 00327 GlobalVector sclMom=computeMode(sclTSOS_); 00328 00329 GlobalPoint vtxPos=vtxTSOS_.globalPosition(); 00330 GlobalVector outMom=computeMode(outTSOS_); 00331 GlobalPoint outPos=outTSOS_.globalPosition(); 00332 00333 //create electron 00334 double scale = (*scRef).energy()/vtxMom_.mag(); 00335 math::XYZTLorentzVectorD momentum= math::XYZTLorentzVector(vtxMom_.x()*scale, 00336 vtxMom_.y()*scale, 00337 vtxMom_.z()*scale, 00338 (*scRef).energy()); 00339 // should be coming from supercluster! 00340 HoECalculator calc(theCaloGeom); 00341 double HoE=calc(&(*scRef),mhbhe_); 00342 GsfElectron ele(momentum,scRef,trackRef,sclPos_,sclMom,seedPos,seedMom,innPos,innMom,vtxPos,vtxMom_,outPos,outMom,HoE); 00343 00344 //and set various properties 00345 ECALPositionCalculator ecpc; 00346 float trackEta=ecpc.ecalEta(trackRef->innerMomentum(),trackRef->innerPosition()); 00347 float trackPhi=ecpc.ecalPhi(theMagField.product(),trackRef->innerMomentum(),trackRef->innerPosition(),trackRef->charge()); 00348 00349 ele.setDeltaEtaSuperClusterAtVtx((*scRef).position().eta() - trackEta); 00350 float dphi = (*scRef).position().phi() - trackPhi; 00351 if (fabs(dphi)>CLHEP::pi) 00352 dphi = dphi < 0? CLHEP::twopi + dphi : dphi - CLHEP::twopi; 00353 ele.setDeltaPhiSuperClusterAtVtx(dphi); 00354 00355 // set corrections + classification 00356 ElectronClassification theClassifier; 00357 theClassifier.correct(ele); 00358 ElectronEnergyCorrector theEnCorrector; 00359 theEnCorrector.correct(ele, applyEtaCorrection_); 00360 ElectronMomentumCorrector theMomCorrector; 00361 theMomCorrector.correct(ele,vtxTSOS_); 00362 00363 outEle.push_back(ele); 00364 }
const SuperClusterRef GsfElectronAlgo::getTrSuperCluster | ( | const reco::GsfTrackRef & | trackRef | ) | [private] |
Definition at line 366 of file GsfElectronAlgo.cc.
References edm::RefToBase< T >::castTo().
Referenced by process().
00366 { 00367 edm::RefToBase<TrajectorySeed> seed = trackRef->extra()->seedRef(); 00368 ElectronPixelSeedRef elseed=seed.castTo<ElectronPixelSeedRef>(); 00369 return elseed->superCluster(); 00370 }
bool GsfElectronAlgo::preSelection | ( | const reco::SuperCluster & | clus | ) | [private] |
Definition at line 238 of file GsfElectronAlgo.cc.
References EcalBarrel, EcalEndcap, reco::CaloCluster::energy(), reco::CaloCluster::eta(), PV3DBase< T, PVType, FrameType >::eta(), highPtMin_, highPtPreselection_, LogDebug, PV3DBase< T, PVType, FrameType >::mag(), maxDeltaEta_, maxDeltaPhi_, maxEOverPBarrel_, maxEOverPEndcaps_, minEOverPBarrel_, minEOverPEndcaps_, PV3DBase< T, PVType, FrameType >::perp(), PV3DBase< T, PVType, FrameType >::phi(), reco::CaloCluster::phi(), pi, r2, sclPos_, funct::sqrt(), subdet_, vtxMom_, reco::CaloCluster::x(), reco::CaloCluster::y(), and reco::CaloCluster::z().
Referenced by process().
00239 { 00240 00241 LogDebug("")<< "========== preSelection =========="; 00242 00243 double rt2 = clus.x()*clus.x() + clus.y()*clus.y(); 00244 double r2 = rt2 + clus.z()*clus.z(); 00245 double Et =clus.energy()*sqrt(rt2/r2); 00246 00247 // pt min 00248 LogDebug("") << "pT : " << vtxMom_.perp(); 00249 00250 // E/p cut 00251 LogDebug("") << "E/p : " << clus.energy()/vtxMom_.mag(); 00252 00253 // no E/p preselection for high pT electrons 00254 if (!highPtPreselection_ || Et <= highPtMin_) { 00255 if ((subdet_==EcalBarrel) && (clus.energy()/vtxMom_.mag() > maxEOverPBarrel_)) return false; 00256 if ((subdet_==EcalEndcap) && (clus.energy()/vtxMom_.mag() > maxEOverPEndcaps_)) return false; 00257 if ((subdet_==EcalBarrel) && (clus.energy()/vtxMom_.mag() < minEOverPBarrel_)) return false; 00258 if ((subdet_==EcalEndcap) && (clus.energy()/vtxMom_.mag() < minEOverPEndcaps_)) return false; 00259 } 00260 LogDebug("") << "E/p criteria is satisfied "; 00261 00262 // delta eta criteria 00263 double etaclu = clus.eta(); 00264 double etatrk = sclPos_.eta(); 00265 double deta = etaclu-etatrk; 00266 LogDebug("") << "delta eta : " << deta; 00267 if (fabs(deta) > maxDeltaEta_) return false; 00268 LogDebug("") << "Delta eta criteria is satisfied "; 00269 00270 // delta phi criteria 00271 double phiclu = clus.phi(); 00272 double phitrk = sclPos_.phi(); 00273 double dphi = phiclu-phitrk; 00274 if (fabs(dphi)>CLHEP::pi) 00275 dphi = dphi < 0? (CLHEP::twopi) + dphi : dphi - CLHEP::twopi; 00276 LogDebug("") << "delta phi : " << dphi; 00277 if (fabs(dphi) > maxDeltaPhi_) return false; 00278 LogDebug("") << "Delta phi criteria is satisfied "; 00279 00280 LogDebug("") << "electron has passed preselection criteria "; 00281 LogDebug("") << "================================================="; 00282 return true; 00283 00284 }
void GsfElectronAlgo::process | ( | edm::Handle< reco::GsfTrackCollection > | tracksH, | |
const math::XYZPoint & | bs, | |||
reco::GsfElectronCollection & | outEle | |||
) | [private] |
Definition at line 207 of file GsfElectronAlgo.cc.
References calculateTSOS(), computeMode(), createElectron(), getTrSuperCluster(), TrajectoryStateOnSurface::globalPosition(), i, preSelection(), edm::Handle< T >::product(), sclPos_, sclTSOS_, reco::SuperCluster::seed(), subdet_, t, tracks, vtxMom_, and vtxTSOS_.
Referenced by run().
00209 { 00210 00211 00212 const GsfTrackCollection *tracks=tracksH.product(); 00213 for (unsigned int i=0;i<tracks->size();++i) { 00214 00215 // track -scl association 00216 00217 const GsfTrack & t=(*tracks)[i]; 00218 const GsfTrackRef trackRef = edm::Ref<GsfTrackCollection>(tracksH,i); 00219 const SuperClusterRef & scRef=getTrSuperCluster(trackRef); 00220 const SuperCluster theClus=*scRef; 00221 std::vector<DetId> vecId=theClus.seed()->getHitsByDetId(); 00222 subdet_ =vecId[0].subdetId(); 00223 00224 // calculate Trajectory StatesOnSurface.... 00225 if (!calculateTSOS(t,theClus, bsPosition)) continue; 00226 vtxMom_=computeMode(vtxTSOS_); 00227 sclPos_=sclTSOS_.globalPosition(); 00228 if (preSelection(theClus)) { 00229 00230 // interface to be improved... 00231 createElectron(scRef,trackRef,outEle); 00232 00233 LogInfo("")<<"Constructed new electron with energy "<< scRef->energy(); 00234 } 00235 } // loop over tracks 00236 }
void GsfElectronAlgo::resolveElectrons | ( | std::vector< reco::GsfElectron > & | , | |
reco::GsfElectronCollection & | outEle | |||
) | [private] |
Referenced by run().
void GsfElectronAlgo::run | ( | edm::Event & | e, | |
reco::GsfElectronCollection & | outEle | |||
) |
Definition at line 142 of file GsfElectronAlgo.cc.
References applyAmbResolution_, edm::Event::getByLabel(), edm::Event::getByType(), hcalRecHits_, edm::Event::id(), it, LogDebug, mhbhe_, process(), edm::Handle< T >::product(), resolveElectrons(), and tracks_.
Referenced by GsfElectronProducer::produce().
00142 { 00143 00144 // get the input 00145 edm::Handle<GsfTrackCollection> tracksH; 00146 e.getByLabel(tracks_,tracksH); 00147 00148 // for HoE calculation 00149 edm::Handle<HBHERecHitCollection> hbhe; 00150 mhbhe_=0; 00151 bool got = e.getByLabel(hcalRecHits_,hbhe); 00152 if (got) mhbhe_= new HBHERecHitMetaCollection(*hbhe); 00153 00154 // get the beamspot from the Event: 00155 edm::Handle<reco::BeamSpot> recoBeamSpotHandle; 00156 e.getByType(recoBeamSpotHandle); 00157 const math::XYZPoint bsPosition = recoBeamSpotHandle->position(); 00158 00159 // temporay array for electron before amb. solving 00160 std::vector<GsfElectron> tempEle; 00161 00162 // create electrons 00163 process(tracksH,bsPosition,tempEle); 00164 00165 std::ostringstream str; 00166 00167 str << "\n========== GsfElectronAlgo Info (before amb. solving) =========="; 00168 str << "\nEvent " << e.id(); 00169 str << "\nNumber of final electron tracks: " << tracksH.product()->size(); 00170 str << "\nNumber of final electrons: " << tempEle.size(); 00171 for (vector<GsfElectron>::const_iterator it = tempEle.begin(); it != tempEle.end(); it++) { 00172 str << "\nNew electron with charge, pt, eta, phi : " << it->charge() << " , " 00173 << it->pt() << " , " << it->eta() << " , " << it->phi(); 00174 } 00175 00176 str << "\n================================================="; 00177 LogDebug("GsfElectronAlgo") << str.str(); 00178 00179 std::ostringstream str2; 00180 00181 if (applyAmbResolution_) { 00182 00183 resolveElectrons(tempEle, outEle); 00184 00185 str2 << "\n========== GsfElectronAlgo Info (after amb. solving) =========="; 00186 str2 << "\nEvent " << e.id(); 00187 str2 << "\nNumber of final electron tracks: " << tracksH.product()->size(); 00188 str2 << "\nNumber of final electrons: " << outEle.size(); 00189 for (vector<GsfElectron>::const_iterator it = outEle.begin(); it != outEle.end(); it++) { 00190 str2 << "\nNew electron with charge, pt, eta, phi : " << it->charge() << " , " 00191 << it->pt() << " , " << it->eta() << " , " << it->phi(); 00192 } 00193 00194 str2 << "\n================================================="; 00195 LogDebug("GsfElectronAlgo") << str2.str(); 00196 00197 } else { 00198 00199 outEle = tempEle; 00200 00201 } 00202 00203 delete mhbhe_; 00204 return; 00205 }
void GsfElectronAlgo::setupES | ( | const edm::EventSetup & | setup | ) |
Definition at line 118 of file GsfElectronAlgo.cc.
References alongMomentum, AnalyticalPropagator_cfi::AnalyticalPropagator, cacheIDGeom_, cacheIDMagField_, cacheIDTDGeom_, geomPropBw_, geomPropFw_, edm::EventSetup::get(), oppositeToMomentum, edm::ESHandle< T >::product(), theCaloGeom, theMagField, and trackerHandle_.
Referenced by GsfElectronProducer::produce().
00118 { 00119 00120 // get EventSetupRecords if needed 00121 if (cacheIDMagField_!=es.get<IdealMagneticFieldRecord>().cacheIdentifier()){ 00122 cacheIDMagField_=es.get<IdealMagneticFieldRecord>().cacheIdentifier(); 00123 es.get<IdealMagneticFieldRecord>().get(theMagField); 00124 if (geomPropBw_) delete geomPropBw_; 00125 geomPropBw_ = new GsfPropagatorAdapter(AnalyticalPropagator(theMagField.product(), oppositeToMomentum)); 00126 if (geomPropFw_) delete geomPropFw_; 00127 geomPropFw_ = new GsfPropagatorAdapter(AnalyticalPropagator(theMagField.product(), alongMomentum)); 00128 } 00129 if (cacheIDTDGeom_!=es.get<TrackerDigiGeometryRecord>().cacheIdentifier()){ 00130 cacheIDTDGeom_=es.get<TrackerDigiGeometryRecord>().cacheIdentifier(); 00131 es.get<TrackerDigiGeometryRecord>().get(trackerHandle_); 00132 } 00133 00134 if (cacheIDGeom_!=es.get<CaloGeometryRecord>().cacheIdentifier()){ 00135 cacheIDGeom_=es.get<CaloGeometryRecord>().cacheIdentifier(); 00136 es.get<CaloGeometryRecord>().get(theCaloGeom); 00137 } 00138 00139 00140 }
bool GsfElectronAlgo::applyAmbResolution_ [private] |
bool GsfElectronAlgo::applyEtaCorrection_ [private] |
Definition at line 100 of file GsfElectronAlgo.h.
unsigned long long GsfElectronAlgo::cacheIDGeom_ [private] |
unsigned long long GsfElectronAlgo::cacheIDMagField_ [private] |
unsigned long long GsfElectronAlgo::cacheIDTDGeom_ [private] |
Definition at line 101 of file GsfElectronAlgo.h.
const GsfPropagatorAdapter* GsfElectronAlgo::geomPropBw_ [private] |
Definition at line 110 of file GsfElectronAlgo.h.
Referenced by GsfElectronAlgo(), setupES(), and ~GsfElectronAlgo().
const GsfPropagatorAdapter* GsfElectronAlgo::geomPropFw_ [private] |
Definition at line 111 of file GsfElectronAlgo.h.
Referenced by GsfElectronAlgo(), setupES(), and ~GsfElectronAlgo().
edm::InputTag GsfElectronAlgo::hcalRecHits_ [private] |
double GsfElectronAlgo::highPtMin_ [private] |
bool GsfElectronAlgo::highPtPreselection_ [private] |
Definition at line 117 of file GsfElectronAlgo.h.
Referenced by calculateTSOS(), and createElectron().
double GsfElectronAlgo::maxDeltaEta_ [private] |
double GsfElectronAlgo::maxDeltaPhi_ [private] |
double GsfElectronAlgo::maxEOverPBarrel_ [private] |
double GsfElectronAlgo::maxEOverPEndcaps_ [private] |
HBHERecHitMetaCollection* GsfElectronAlgo::mhbhe_ [private] |
double GsfElectronAlgo::minEOverPBarrel_ [private] |
double GsfElectronAlgo::minEOverPEndcaps_ [private] |
const MultiTrajectoryStateTransform* GsfElectronAlgo::mtsTransform_ [private] |
Definition at line 109 of file GsfElectronAlgo.h.
Referenced by calculateTSOS(), GsfElectronAlgo(), and ~GsfElectronAlgo().
Definition at line 118 of file GsfElectronAlgo.h.
Referenced by calculateTSOS(), and createElectron().
GlobalPoint GsfElectronAlgo::sclPos_ [private] |
Definition at line 115 of file GsfElectronAlgo.h.
Referenced by createElectron(), preSelection(), and process().
Definition at line 120 of file GsfElectronAlgo.h.
Referenced by calculateTSOS(), createElectron(), and process().
Definition at line 121 of file GsfElectronAlgo.h.
Referenced by calculateTSOS(), and createElectron().
int GsfElectronAlgo::subdet_ [private] |
Definition at line 105 of file GsfElectronAlgo.h.
Referenced by calculateTSOS(), createElectron(), and setupES().
edm::InputTag GsfElectronAlgo::tracks_ [private] |
GlobalVector GsfElectronAlgo::vtxMom_ [private] |
Definition at line 116 of file GsfElectronAlgo.h.
Referenced by createElectron(), preSelection(), and process().
Definition at line 119 of file GsfElectronAlgo.h.
Referenced by calculateTSOS(), createElectron(), and process().