365 log = logging.getLogger(
'ElectronWorkingPointConfig')
368 log.warning(
"You are running ElectronWorkingPointConfig forcing full sim config")
369 log.warning(
"This is only intended to be used for testing purposes")
372 if selectionPostfix !=
'' and selectionPostfix[0] !=
'_' :
373 selectionPostfix =
'_' + selectionPostfix
376 if config.geometry()
is LHCPeriod.Run1:
377 raise ValueError (
"Can't set up the ElectronWorkingPointConfig with %s, there must be something wrong!" % config.geometry().value)
379 postfix = self.postfix
382 if postfix !=
'' and postfix[0] !=
'_' :
383 postfix =
'_' + postfix
387 alg = config.createAlgorithm(
'CP::AsgLeptonTrackSelectionAlg',
388 'ElectronTrackSelectionAlg',
390 alg.selectionDecoration =
'trackSelection' + postfix +
',as_bits'
391 alg.maxD0Significance = self.maxD0Significance
392 alg.maxDeltaZ0SinTheta = self.maxDeltaZ0SinTheta
394 alg.preselection = config.getPreselection (self.
containerName,
'')
397 preselection=self.addSelectionToPreselection)
402 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
'ElectronLikelihoodAlg' )
403 alg.selectionDecoration =
'selectLikelihood' + selectionPostfix +
',as_char'
406 config.addPrivateTool(
'selectionTool',
'AsgElectronLikelihoodTool' )
407 alg.selectionTool.primaryVertexContainer =
'PrimaryVertices'
410 if config.geometry() >= LHCPeriod.Run3:
415 elif config.geometry()
is LHCPeriod.Run2:
419 config.addPrivateTool(
'selectionTool',
'CP::AsgFlagSelectionTool' )
421 dfFlag = dfFlag.replace(
"BLayer",
"BL")
422 alg.selectionTool.selectionFlags = [dfFlag]
425 algVeto = config.createAlgorithm(
'CP::AsgSelectionAlg',
'ElectronLikelihoodAlgVeto')
426 algVeto.selectionDecoration =
'selectLikelihoodVeto' + postfix +
',as_char'
427 config.addPrivateTool(
'selectionTool',
'CP::AsgFlagSelectionTool' )
428 algVeto.selectionTool.selectionFlags = [
"DFCommonElectronsLHLoose"]
429 algVeto.selectionTool.invertFlags = [
True]
434 preselection=self.addSelectionToPreselection)
437 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
'ElectronLikelihoodAlg' )
438 alg.selectionDecoration =
'selectSiHit' + selectionPostfix +
',as_char'
440 config.addPrivateTool(
'selectionTool',
'CP::AsgMaskSelectionTool' )
441 dfVar =
"DFCommonElectronsLHLooseBLIsEMValue"
442 alg.selectionTool.selectionVars = [dfVar]
443 mask = int( 0 | 0x1 << 1 | 0x1 << 2)
444 alg.selectionTool.selectionMasks = [mask]
447 raise ValueError(
'DNN is not intended to be used with '
448 '`chargeIDSelectionRun2` option as there are '
449 'DNN WPs containing charge flip rejection.')
451 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
'ElectronDNNAlg' )
452 alg.selectionDecoration =
'selectDNN' + selectionPostfix +
',as_char'
455 config.addPrivateTool(
'selectionTool',
'AsgElectronSelectorTool' )
457 if config.geometry()
is LHCPeriod.Run3:
458 raise ValueError (
"DNN working points are not available for Run 3 yet.")
463 config.addPrivateTool(
'selectionTool',
'CP::AsgFlagSelectionTool' )
465 alg.selectionTool.selectionFlags = [dfFlag]
469 raise ValueError (f
"Electron ID working point '{self.identificationWP}' is not recognised!")
475 preselection=self.addSelectionToPreselection)
480 algDec = config.createAlgorithm(
'CP::ElectronSiHitDecAlg',
'ElectronSiHitDecAlg' )
481 selDec =
'siHitEvtHasLeptonPair' + selectionPostfix +
',as_char'
482 algDec.selectionName = selDec.split(
",")[0]
483 algDec.ElectronContainer = config.readName (self.
containerName)
485 algDec.RequireTwoLeptons =
True
487 preselection=self.addSelectionToPreselection)
493 raise ValueError(f
"convSelection can only be used with TightLH ID, "
494 f
"whereas {self.identificationWP} has been selected. convSelection option will be ignored.")
496 allowedValues = [
"Veto",
"GammaStar",
"MatConv"]
498 raise ValueError(f
"convSelection has been set to {self.convSelection}, which is not a valid option. "
499 f
"convSelection option must be one of {allowedValues}.")
502 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
'ElectronAmbiguityTypeAlg' )
503 alg.selectionDecoration =
'selectAmbiguityType' + selectionPostfix +
',as_char'
504 config.addPrivateTool(
'selectionTool',
'CP::AsgNumDecorationSelectionToolUInt8' )
505 alg.selectionTool.decorationName =
"ambiguityType"
506 alg.selectionTool.doEqual =
True
507 alg.selectionTool.equal = 0
511 preselection=self.addSelectionToPreselection)
514 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
'ElectronDFCommonAddAmbiguityAlg' )
515 alg.selectionDecoration =
'selectDFCommonAddAmbiguity' + selectionPostfix +
',as_char'
516 config.addPrivateTool(
'selectionTool',
'CP::AsgNumDecorationSelectionToolInt' )
517 alg.selectionTool.decorationName =
"DFCommonAddAmbiguity"
519 alg.selectionTool.doMax =
True
520 alg.selectionTool.max = 1
522 alg.selectionTool.doEqual =
True
523 alg.selectionTool.equal = 1
525 alg.selectionTool.doEqual =
True
526 alg.selectionTool.equal = 2
530 preselection=self.addSelectionToPreselection)
535 wpFlag = alg.selectionDecoration.split(
",")[0]
536 alg = config.createAlgorithm(
'CP::EgammaFSRForMuonsCollectorAlg',
'EgammaFSRForMuonsCollectorAlg' )
537 alg.selectionDecoration = wpFlag
538 alg.ElectronOrPhotonContKey = config.readName (self.
containerName)
546 if self.isolationWP !=
'NonIso' :
547 alg = config.createAlgorithm(
'CP::EgammaIsolationSelectionAlg',
548 'ElectronIsolationSelectionAlg' )
549 alg.selectionDecoration =
'isolated' + selectionPostfix +
',as_char'
550 config.addPrivateTool(
'selectionTool',
'CP::IsolationSelectionTool' )
551 alg.selectionTool.ElectronWP = self.isolationWP
553 alg.selectionTool.IsoDecSuffix =
"CloseByCorr"
557 preselection=self.addSelectionToPreselection)
560 log.warning(
"ECIDS is only available for Run 2 and will not have any effect in Run 3.")
564 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
565 'ElectronChargeIDSelectionAlg' )
566 alg.selectionDecoration =
'chargeID' + selectionPostfix +
',as_char'
569 config.addPrivateTool(
'selectionTool',
570 'AsgElectronChargeIDSelectorTool' )
571 alg.selectionTool.TrainingFile = \
572 'ElectronPhotonSelectorTools/ChargeID/ECIDS_20180731rel21Summer2018.root'
573 alg.selectionTool.WorkingPoint =
'Loose'
574 alg.selectionTool.CutOnBDT = -0.337671
577 config.addPrivateTool(
'selectionTool',
'CP::AsgFlagSelectionTool' )
578 alg.selectionTool.selectionFlags = [
"DFCommonElectronsECIDS"]
583 preselection=self.addSelectionToPreselection)
585 correlationModels = [
"SIMPLIFIED",
"FULL",
"TOTAL",
"TOYS"]
586 map_file =
'ElectronEfficiencyCorrection/2015_2025/rel22.2/2025_Run2Rel22_Recommendation_v3/map1.txt' \
587 if config.geometry()
is LHCPeriod.Run2
else \
588 'ElectronEfficiencyCorrection/2015_2025/rel22.2/2025_Run3_Consolidated_Recommendation_v4/map2.txt'
591 if config.dataType()
is not DataType.Data
and not self.
noEffSF:
593 raise ValueError(
'DNN does not yet have efficiency correction, '
594 'please disable it by setting `noEffSF` to True.')
596 alg = config.createAlgorithm(
'CP::ElectronEfficiencyCorrectionAlg',
597 'ElectronEfficiencyCorrectionAlgReco' )
598 config.addPrivateTool(
'efficiencyCorrectionTool',
599 'AsgElectronEfficiencyCorrectionTool' )
600 alg.scaleFactorDecoration =
'el_reco_effSF' + selectionPostfix +
'_%SYS%'
601 alg.efficiencyCorrectionTool.MapFilePath = map_file
602 alg.efficiencyCorrectionTool.RecoKey =
"Reconstruction"
603 if self.correlationModelReco
not in correlationModels:
604 raise ValueError(
'Invalid correlation model for reconstruction efficiency, '
605 f
'has to be one of: {", ".join(correlationModels)}')
606 if config.geometry() >= LHCPeriod.Run3
and self.correlationModelReco !=
"TOTAL":
607 log.warning(
"Only TOTAL correlation model is currently supported "
608 "for reconstruction efficiency correction in Run 3.")
609 alg.efficiencyCorrectionTool.CorrelationModel =
"TOTAL"
611 alg.efficiencyCorrectionTool.CorrelationModel = self.correlationModelReco
612 if config.dataType()
is DataType.FastSim:
613 alg.efficiencyCorrectionTool.ForceDataType = (
615 else PATCore.ParticleDataType.Fast)
616 elif config.dataType()
is DataType.FullSim:
617 alg.efficiencyCorrectionTool.ForceDataType = \
618 PATCore.ParticleDataType.Full
619 alg.outOfValidity = 2
620 alg.outOfValidityDeco =
'el_reco_bad_eff' + selectionPostfix
624 config.addOutputVar (self.
containerName, alg.scaleFactorDecoration,
625 'reco_effSF' + postfix)
626 sfList += [alg.scaleFactorDecoration]
631 alg = config.createAlgorithm(
'CP::ElectronEfficiencyCorrectionAlg',
632 'ElectronEfficiencyCorrectionAlgID' )
633 config.addPrivateTool(
'efficiencyCorrectionTool',
634 'AsgElectronEfficiencyCorrectionTool' )
635 alg.scaleFactorDecoration =
'el_id_effSF' + selectionPostfix +
'_%SYS%'
636 alg.efficiencyCorrectionTool.MapFilePath = map_file
638 if self.correlationModelId
not in correlationModels:
639 raise ValueError(
'Invalid correlation model for identification efficiency, '
640 f
'has to be one of: {", ".join(correlationModels)}')
641 alg.efficiencyCorrectionTool.CorrelationModel = self.correlationModelId
642 if config.dataType()
is DataType.FastSim:
643 alg.efficiencyCorrectionTool.ForceDataType = (
645 else PATCore.ParticleDataType.Fast)
646 elif config.dataType()
is DataType.FullSim:
647 alg.efficiencyCorrectionTool.ForceDataType = \
648 PATCore.ParticleDataType.Full
649 alg.outOfValidity = 2
650 alg.outOfValidityDeco =
'el_id_bad_eff' + selectionPostfix
654 config.addOutputVar (self.
containerName, alg.scaleFactorDecoration,
655 'id_effSF' + postfix)
656 sfList += [alg.scaleFactorDecoration]
659 if config.dataType()
is not DataType.Data
and self.isolationWP !=
'NonIso' and not self.
noEffSF:
660 alg = config.createAlgorithm(
'CP::ElectronEfficiencyCorrectionAlg',
661 'ElectronEfficiencyCorrectionAlgIsol' )
662 config.addPrivateTool(
'efficiencyCorrectionTool',
663 'AsgElectronEfficiencyCorrectionTool' )
664 alg.scaleFactorDecoration =
'el_isol_effSF' + selectionPostfix +
'_%SYS%'
665 alg.efficiencyCorrectionTool.MapFilePath = map_file
667 alg.efficiencyCorrectionTool.IsoKey = self.isolationWP
668 if self.correlationModelIso
not in correlationModels:
669 raise ValueError(
'Invalid correlation model for isolation efficiency, '
670 f
'has to be one of: {", ".join(correlationModels)}')
671 if self.correlationModelIso !=
'TOTAL':
672 log.warning(
"Only TOTAL correlation model is currently supported "
673 "for isolation efficiency correction in Run 3.")
674 alg.efficiencyCorrectionTool.CorrelationModel =
"TOTAL"
675 if config.dataType()
is DataType.FastSim:
676 alg.efficiencyCorrectionTool.ForceDataType = (
678 else PATCore.ParticleDataType.Fast)
679 elif config.dataType()
is DataType.FullSim:
680 alg.efficiencyCorrectionTool.ForceDataType = \
681 PATCore.ParticleDataType.Full
682 alg.outOfValidity = 2
683 alg.outOfValidityDeco =
'el_isol_bad_eff' + selectionPostfix
687 config.addOutputVar (self.
containerName, alg.scaleFactorDecoration,
688 'isol_effSF' + postfix)
689 sfList += [alg.scaleFactorDecoration]
692 config.dataType()
is not DataType.Data
and not self.
noEffSF):
693 alg = config.createAlgorithm(
'CP::ElectronEfficiencyCorrectionAlg',
694 'ElectronEfficiencyCorrectionAlgEcids' )
695 config.addPrivateTool(
'efficiencyCorrectionTool',
696 'AsgElectronEfficiencyCorrectionTool' )
697 alg.scaleFactorDecoration =
'el_ecids_effSF' + selectionPostfix +
'_%SYS%'
698 if self.isolationWP !=
'Tight_VarRad':
699 raise ValueError(
'ECIDS SFs are supported only for Tight_VarRad isolation.')
707 raise ValueError(
'ECIDS SFs are supported only for ID LooseBLayerLH, MediumLH, or TightLH')
709 alg.efficiencyCorrectionTool.CorrelationModel =
"TOTAL"
710 alg.efficiencyCorrectionTool.CorrectionFileNameList = \
711 [f
'ElectronEfficiencyCorrection/2015_2025/rel22.2/2025_Run2Rel22_Recommendation_v2/ecids/efficiencySF.ChargeID.{ecids_lh}_ECIDS_Tight_VarRad.root']
712 if config.dataType()
is DataType.FastSim:
713 alg.efficiencyCorrectionTool.ForceDataType = (
715 else PATCore.ParticleDataType.Fast)
716 elif config.dataType()
is DataType.FullSim:
717 alg.efficiencyCorrectionTool.ForceDataType = \
718 PATCore.ParticleDataType.Full
719 alg.outOfValidity = 2
720 alg.outOfValidityDeco =
'el_ecids_bad_eff' + selectionPostfix
724 config.addOutputVar (self.
containerName, alg.scaleFactorDecoration,
725 'ecids_effSF' + postfix)
726 sfList += [alg.scaleFactorDecoration]
728 if self.addChargeMisIDSF
and config.dataType()
is not DataType.Data
and not self.
noEffSF:
729 if config.geometry() >= LHCPeriod.Run3:
730 raise ValueError(
'Run 3 does not yet have charge mis-ID correction, '
731 'please disable it by setting `noEffSF` to False.')
733 alg = config.createAlgorithm(
'CP::ElectronEfficiencyCorrectionAlg',
734 'ElectronEfficiencyCorrectionAlgMisid' )
735 config.addPrivateTool(
'efficiencyCorrectionTool',
736 'CP::ElectronChargeEfficiencyCorrectionTool' )
737 alg.scaleFactorDecoration =
'el_charge_misid_effSF' + selectionPostfix +
'_%SYS%'
738 if self.isolationWP !=
'Tight_VarRad':
739 raise ValueError(
'Charge mis-ID SFs are supported only for Tight_VarRad isolation.')
741 misid_lh =
'LooseAndBLayerLLH'
743 misid_lh =
'MediumLLH'
745 misid_lh =
'TightLLH'
747 raise ValueError(
'Charge mis-ID SFs are supported only for ID LooseBLayerLH, MediumLH, or TightLH')
750 alg.efficiencyCorrectionTool.CorrectionFileName = \
751 f
'ElectronEfficiencyCorrection/2015_2025/rel22.2/2025_Run2Rel22_Recommendation_v2/charge_misID/chargeEfficiencySF.{misid_lh}_d0z0_TightVarRad{misid_suffix}.root'
752 if config.dataType()
is DataType.FastSim:
753 alg.efficiencyCorrectionTool.ForceDataType = (
755 else PATCore.ParticleDataType.Fast)
756 elif config.dataType()
is DataType.FullSim:
757 alg.efficiencyCorrectionTool.ForceDataType = \
758 PATCore.ParticleDataType.Full
759 alg.outOfValidity = 2
760 alg.outOfValidityDeco =
'el_misid_bad_eff' + selectionPostfix
764 config.addOutputVar (self.
containerName, alg.scaleFactorDecoration,
765 'charge_misid_effSF' + postfix)
766 sfList += [alg.scaleFactorDecoration]
769 alg = config.createAlgorithm(
'CP::AsgObjectScaleFactorAlg',
770 'ElectronCombinedEfficiencyScaleFactorAlg' )
772 alg.inScaleFactors = sfList
773 alg.outScaleFactor =
'effSF' + postfix +
'_%SYS%'
774 config.addOutputVar (self.
containerName, alg.outScaleFactor,
'effSF' + postfix)