378 log = logging.getLogger(
'ElectronWorkingPointConfig')
381 log.warning(
"You are running ElectronWorkingPointConfig forcing full sim config")
382 log.warning(
"This is only intended to be used for testing purposes")
385 if selectionPostfix !=
'' and selectionPostfix[0] !=
'_' :
386 selectionPostfix =
'_' + selectionPostfix
389 if config.geometry()
is LHCPeriod.Run1:
390 raise ValueError (
"Can't set up the ElectronWorkingPointConfig with %s, there must be something wrong!" % config.geometry().value)
392 postfix = self.postfix
395 if postfix !=
'' and postfix[0] !=
'_' :
396 postfix =
'_' + postfix
400 alg = config.createAlgorithm(
'CP::AsgLeptonTrackSelectionAlg',
401 'ElectronTrackSelectionAlg',
403 alg.selectionDecoration =
'trackSelection' + postfix +
',as_bits'
404 alg.maxD0Significance = self.maxD0Significance
405 alg.maxDeltaZ0SinTheta = self.maxDeltaZ0SinTheta
407 alg.preselection = config.getPreselection (self.
containerName,
'')
410 preselection=self.addSelectionToPreselection)
415 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
'ElectronLikelihoodAlg' )
416 alg.selectionDecoration =
'selectLikelihood' + selectionPostfix +
',as_char'
419 config.addPrivateTool(
'selectionTool',
'AsgElectronLikelihoodTool' )
420 alg.selectionTool.primaryVertexContainer =
'PrimaryVertices'
423 if config.geometry() >= LHCPeriod.Run3:
428 elif config.geometry()
is LHCPeriod.Run2:
432 config.addPrivateTool(
'selectionTool',
'CP::AsgFlagSelectionTool' )
434 dfFlag = dfFlag.replace(
"BLayer",
"BL")
435 alg.selectionTool.selectionFlags = [dfFlag]
438 algVeto = config.createAlgorithm(
'CP::AsgSelectionAlg',
'ElectronLikelihoodAlgVeto')
439 algVeto.selectionDecoration =
'selectLikelihoodVeto' + postfix +
',as_char'
440 config.addPrivateTool(
'selectionTool',
'CP::AsgFlagSelectionTool' )
441 algVeto.selectionTool.selectionFlags = [
"DFCommonElectronsLHLoose"]
442 algVeto.selectionTool.invertFlags = [
True]
447 preselection=self.addSelectionToPreselection)
450 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
'ElectronLikelihoodAlg' )
451 alg.selectionDecoration =
'selectSiHit' + selectionPostfix +
',as_char'
453 config.addPrivateTool(
'selectionTool',
'CP::AsgMaskSelectionTool' )
454 dfVar =
"DFCommonElectronsLHLooseBLIsEMValue"
455 alg.selectionTool.selectionVars = [dfVar]
456 mask = int( 0 | 0x1 << 1 | 0x1 << 2)
457 alg.selectionTool.selectionMasks = [mask]
460 raise ValueError(
'DNN is not intended to be used with '
461 '`chargeIDSelectionRun2` option as there are '
462 'DNN WPs containing charge flip rejection.')
464 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
'ElectronDNNAlg' )
465 alg.selectionDecoration =
'selectDNN' + selectionPostfix +
',as_char'
468 config.addPrivateTool(
'selectionTool',
'AsgElectronSelectorTool' )
470 if config.geometry()
is LHCPeriod.Run3:
471 raise ValueError (
"DNN working points are not available for Run 3 yet.")
476 config.addPrivateTool(
'selectionTool',
'CP::AsgFlagSelectionTool' )
478 alg.selectionTool.selectionFlags = [dfFlag]
482 raise ValueError (f
"Electron ID working point '{self.identificationWP}' is not recognised!")
488 preselection=self.addSelectionToPreselection)
493 algDec = config.createAlgorithm(
'CP::ElectronSiHitDecAlg',
'ElectronSiHitDecAlg' )
494 selDec =
'siHitEvtHasLeptonPair' + selectionPostfix +
',as_char'
495 algDec.selectionName = selDec.split(
",")[0]
496 algDec.ElectronContainer = config.readName (self.
containerName)
498 algDec.RequireTwoLeptons =
True
500 preselection=self.addSelectionToPreselection)
506 raise ValueError(f
"convSelection can only be used with TightLH ID, "
507 f
"whereas {self.identificationWP} has been selected. convSelection option will be ignored.")
509 allowedValues = [
"Veto",
"GammaStar",
"MatConv"]
511 raise ValueError(f
"convSelection has been set to {self.convSelection}, which is not a valid option. "
512 f
"convSelection option must be one of {allowedValues}.")
515 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
'ElectronAmbiguityTypeAlg' )
516 alg.selectionDecoration =
'selectAmbiguityType' + selectionPostfix +
',as_char'
517 config.addPrivateTool(
'selectionTool',
'CP::AsgNumDecorationSelectionToolUInt8' )
518 alg.selectionTool.decorationName =
"ambiguityType"
519 alg.selectionTool.doEqual =
True
520 alg.selectionTool.equal = 0
524 preselection=self.addSelectionToPreselection)
527 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
'ElectronDFCommonAddAmbiguityAlg' )
528 alg.selectionDecoration =
'selectDFCommonAddAmbiguity' + selectionPostfix +
',as_char'
529 config.addPrivateTool(
'selectionTool',
'CP::AsgNumDecorationSelectionToolInt' )
530 alg.selectionTool.decorationName =
"DFCommonAddAmbiguity"
532 alg.selectionTool.doMax =
True
533 alg.selectionTool.max = 1
535 alg.selectionTool.doEqual =
True
536 alg.selectionTool.equal = 1
538 alg.selectionTool.doEqual =
True
539 alg.selectionTool.equal = 2
543 preselection=self.addSelectionToPreselection)
548 wpFlag = alg.selectionDecoration.split(
",")[0]
549 alg = config.createAlgorithm(
'CP::EgammaFSRForMuonsCollectorAlg',
'EgammaFSRForMuonsCollectorAlg' )
550 alg.selectionDecoration = wpFlag
551 alg.ElectronOrPhotonContKey = config.readName (self.
containerName)
559 if self.isolationWP !=
'NonIso' :
560 alg = config.createAlgorithm(
'CP::EgammaIsolationSelectionAlg',
561 'ElectronIsolationSelectionAlg' )
562 alg.selectionDecoration =
'isolated' + selectionPostfix +
',as_char'
563 config.addPrivateTool(
'selectionTool',
'CP::IsolationSelectionTool' )
564 alg.selectionTool.ElectronWP = self.isolationWP
566 alg.selectionTool.IsoDecSuffix =
"CloseByCorr"
570 preselection=self.addSelectionToPreselection)
573 log.warning(
"ECIDS is only available for Run 2 and will not have any effect in Run 3.")
577 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
578 'ElectronChargeIDSelectionAlg' )
579 alg.selectionDecoration =
'chargeID' + selectionPostfix +
',as_char'
582 config.addPrivateTool(
'selectionTool',
583 'AsgElectronChargeIDSelectorTool' )
584 alg.selectionTool.TrainingFile = \
585 'ElectronPhotonSelectorTools/ChargeID/ECIDS_20180731rel21Summer2018.root'
586 alg.selectionTool.WorkingPoint =
'Loose'
587 alg.selectionTool.CutOnBDT = -0.337671
590 config.addPrivateTool(
'selectionTool',
'CP::AsgFlagSelectionTool' )
591 alg.selectionTool.selectionFlags = [
"DFCommonElectronsECIDS"]
596 preselection=self.addSelectionToPreselection)
598 correlationModels = [
"SIMPLIFIED",
"FULL",
"TOTAL",
"TOYS"]
599 map_file =
'ElectronEfficiencyCorrection/2015_2025/rel22.2/2025_Run2Rel22_Recommendation_v3/map1.txt' \
600 if config.geometry()
is LHCPeriod.Run2
else \
601 'ElectronEfficiencyCorrection/2015_2025/rel22.2/2025_Run3_Consolidated_Recommendation_v4/map2.txt'
604 if config.dataType()
is not DataType.Data
and not self.
noEffSF:
606 raise ValueError(
'DNN does not yet have efficiency correction, '
607 'please disable it by setting `noEffSF` to True.')
609 alg = config.createAlgorithm(
'CP::ElectronEfficiencyCorrectionAlg',
610 'ElectronEfficiencyCorrectionAlgReco' )
611 config.addPrivateTool(
'efficiencyCorrectionTool',
612 'AsgElectronEfficiencyCorrectionTool' )
613 alg.scaleFactorDecoration =
'el_reco_effSF' + selectionPostfix +
'_%SYS%'
614 alg.efficiencyCorrectionTool.MapFilePath = map_file
615 alg.efficiencyCorrectionTool.RecoKey =
"Reconstruction"
616 if self.correlationModelReco
not in correlationModels:
617 raise ValueError(
'Invalid correlation model for reconstruction efficiency, '
618 f
'has to be one of: {", ".join(correlationModels)}')
619 if config.geometry() >= LHCPeriod.Run3
and self.correlationModelReco !=
"TOTAL":
620 log.warning(
"Only TOTAL correlation model is currently supported "
621 "for reconstruction efficiency correction in Run 3.")
622 alg.efficiencyCorrectionTool.CorrelationModel =
"TOTAL"
624 alg.efficiencyCorrectionTool.CorrelationModel = self.correlationModelReco
625 if config.dataType()
is DataType.FastSim:
626 alg.efficiencyCorrectionTool.ForceDataType = (
628 else PATCore.ParticleDataType.Fast)
629 elif config.dataType()
is DataType.FullSim:
630 alg.efficiencyCorrectionTool.ForceDataType = \
631 PATCore.ParticleDataType.Full
632 alg.outOfValidity = 2
633 alg.outOfValidityDeco =
'el_reco_bad_eff' + selectionPostfix
637 config.addOutputVar (self.
containerName, alg.scaleFactorDecoration,
638 'reco_effSF' + postfix)
639 sfList += [alg.scaleFactorDecoration]
644 alg = config.createAlgorithm(
'CP::ElectronEfficiencyCorrectionAlg',
645 'ElectronEfficiencyCorrectionAlgID' )
646 config.addPrivateTool(
'efficiencyCorrectionTool',
647 'AsgElectronEfficiencyCorrectionTool' )
648 alg.scaleFactorDecoration =
'el_id_effSF' + selectionPostfix +
'_%SYS%'
649 alg.efficiencyCorrectionTool.MapFilePath = map_file
651 if self.correlationModelId
not in correlationModels:
652 raise ValueError(
'Invalid correlation model for identification efficiency, '
653 f
'has to be one of: {", ".join(correlationModels)}')
654 alg.efficiencyCorrectionTool.CorrelationModel = self.correlationModelId
655 if config.dataType()
is DataType.FastSim:
656 alg.efficiencyCorrectionTool.ForceDataType = (
658 else PATCore.ParticleDataType.Fast)
659 elif config.dataType()
is DataType.FullSim:
660 alg.efficiencyCorrectionTool.ForceDataType = \
661 PATCore.ParticleDataType.Full
662 alg.outOfValidity = 2
663 alg.outOfValidityDeco =
'el_id_bad_eff' + selectionPostfix
667 config.addOutputVar (self.
containerName, alg.scaleFactorDecoration,
668 'id_effSF' + postfix)
669 sfList += [alg.scaleFactorDecoration]
672 if config.dataType()
is not DataType.Data
and self.isolationWP !=
'NonIso' and not self.
noEffSF:
673 alg = config.createAlgorithm(
'CP::ElectronEfficiencyCorrectionAlg',
674 'ElectronEfficiencyCorrectionAlgIsol' )
675 config.addPrivateTool(
'efficiencyCorrectionTool',
676 'AsgElectronEfficiencyCorrectionTool' )
677 alg.scaleFactorDecoration =
'el_isol_effSF' + selectionPostfix +
'_%SYS%'
678 alg.efficiencyCorrectionTool.MapFilePath = map_file
680 alg.efficiencyCorrectionTool.IsoKey = self.isolationWP
681 if self.correlationModelIso
not in correlationModels:
682 raise ValueError(
'Invalid correlation model for isolation efficiency, '
683 f
'has to be one of: {", ".join(correlationModels)}')
684 if self.correlationModelIso !=
'TOTAL':
685 log.warning(
"Only TOTAL correlation model is currently supported "
686 "for isolation efficiency correction in Run 3.")
687 alg.efficiencyCorrectionTool.CorrelationModel =
"TOTAL"
688 if config.dataType()
is DataType.FastSim:
689 alg.efficiencyCorrectionTool.ForceDataType = (
691 else PATCore.ParticleDataType.Fast)
692 elif config.dataType()
is DataType.FullSim:
693 alg.efficiencyCorrectionTool.ForceDataType = \
694 PATCore.ParticleDataType.Full
695 alg.outOfValidity = 2
696 alg.outOfValidityDeco =
'el_isol_bad_eff' + selectionPostfix
700 config.addOutputVar (self.
containerName, alg.scaleFactorDecoration,
701 'isol_effSF' + postfix)
702 sfList += [alg.scaleFactorDecoration]
705 config.dataType()
is not DataType.Data
and not self.
noEffSF):
706 alg = config.createAlgorithm(
'CP::ElectronEfficiencyCorrectionAlg',
707 'ElectronEfficiencyCorrectionAlgEcids' )
708 config.addPrivateTool(
'efficiencyCorrectionTool',
709 'AsgElectronEfficiencyCorrectionTool' )
710 alg.scaleFactorDecoration =
'el_ecids_effSF' + selectionPostfix +
'_%SYS%'
711 if self.isolationWP !=
'Tight_VarRad':
712 raise ValueError(
'ECIDS SFs are supported only for Tight_VarRad isolation.')
720 raise ValueError(
'ECIDS SFs are supported only for ID LooseBLayerLH, MediumLH, or TightLH')
722 alg.efficiencyCorrectionTool.CorrelationModel =
"TOTAL"
723 alg.efficiencyCorrectionTool.CorrectionFileNameList = \
724 [f
'ElectronEfficiencyCorrection/2015_2025/rel22.2/2025_Run2Rel22_Recommendation_v2/ecids/efficiencySF.ChargeID.{ecids_lh}_ECIDS_Tight_VarRad.root']
725 if config.dataType()
is DataType.FastSim:
726 alg.efficiencyCorrectionTool.ForceDataType = (
728 else PATCore.ParticleDataType.Fast)
729 elif config.dataType()
is DataType.FullSim:
730 alg.efficiencyCorrectionTool.ForceDataType = \
731 PATCore.ParticleDataType.Full
732 alg.outOfValidity = 2
733 alg.outOfValidityDeco =
'el_ecids_bad_eff' + selectionPostfix
737 config.addOutputVar (self.
containerName, alg.scaleFactorDecoration,
738 'ecids_effSF' + postfix)
739 sfList += [alg.scaleFactorDecoration]
741 if self.addChargeMisIDSF
and config.dataType()
is not DataType.Data
and not self.
noEffSF:
742 if config.geometry() >= LHCPeriod.Run3:
743 raise ValueError(
'Run 3 does not yet have charge mis-ID correction, '
744 'please disable it by setting `noEffSF` to False.')
746 alg = config.createAlgorithm(
'CP::ElectronEfficiencyCorrectionAlg',
747 'ElectronEfficiencyCorrectionAlgMisid' )
748 config.addPrivateTool(
'efficiencyCorrectionTool',
749 'CP::ElectronChargeEfficiencyCorrectionTool' )
750 alg.scaleFactorDecoration =
'el_charge_misid_effSF' + selectionPostfix +
'_%SYS%'
751 if self.isolationWP !=
'Tight_VarRad':
752 raise ValueError(
'Charge mis-ID SFs are supported only for Tight_VarRad isolation.')
754 misid_lh =
'LooseAndBLayerLLH'
756 misid_lh =
'MediumLLH'
758 misid_lh =
'TightLLH'
760 raise ValueError(
'Charge mis-ID SFs are supported only for ID LooseBLayerLH, MediumLH, or TightLH')
763 alg.efficiencyCorrectionTool.CorrectionFileName = \
764 f
'ElectronEfficiencyCorrection/2015_2025/rel22.2/2025_Run2Rel22_Recommendation_v2/charge_misID/chargeEfficiencySF.{misid_lh}_d0z0_TightVarRad{misid_suffix}.root'
765 if config.dataType()
is DataType.FastSim:
766 alg.efficiencyCorrectionTool.ForceDataType = (
768 else PATCore.ParticleDataType.Fast)
769 elif config.dataType()
is DataType.FullSim:
770 alg.efficiencyCorrectionTool.ForceDataType = \
771 PATCore.ParticleDataType.Full
772 alg.outOfValidity = 2
773 alg.outOfValidityDeco =
'el_misid_bad_eff' + selectionPostfix
777 config.addOutputVar (self.
containerName, alg.scaleFactorDecoration,
778 'charge_misid_effSF' + postfix)
779 sfList += [alg.scaleFactorDecoration]
782 alg = config.createAlgorithm(
'CP::AsgObjectScaleFactorAlg',
783 'ElectronCombinedEfficiencyScaleFactorAlg' )
785 alg.inScaleFactors = sfList
786 alg.outScaleFactor =
'effSF' + postfix +
'_%SYS%'
787 config.addOutputVar (self.
containerName, alg.outScaleFactor,
'effSF' + postfix)