636 def makeAlgs (self, config) :
637
638 log = logging.getLogger('ElectronWorkingPointEfficiencyConfig')
639
640 if self.forceFullSimConfig:
641 log.warning("You are running ElectronWorkingPointSelectionConfig forcing full sim config")
642 log.warning("This is only intended to be used for testing purposes")
643
644 selectionPostfix = self.selectionName
645 if selectionPostfix != '' and selectionPostfix[0] != '_' :
646 selectionPostfix = '_' + selectionPostfix
647
648
649 if config.geometry() is LHCPeriod.Run1:
650 raise ValueError ("Can't set up the ElectronWorkingPointSelectionConfig with %s, there must be something wrong!" % config.geometry().value)
651
652 postfix = self.postfix
653 if postfix is None :
654 postfix = self.selectionName
655 if postfix != '' and postfix[0] != '_' :
656 postfix = '_' + postfix
657
658 correlationModels = ["SIMPLIFIED", "FULL", "TOTAL", "TOYS"]
659 map_file = 'ElectronEfficiencyCorrection/2015_2025/rel22.2/2025_Run2Rel22_Recommendation_v3/map1.txt' \
660 if config.geometry() is LHCPeriod.Run2 else \
661 'ElectronEfficiencyCorrection/2015_2025/rel22.2/2025_Run3_Consolidated_Recommendation_v4/map2.txt'
662 sfList = []
663
664 if config.dataType() is not DataType.Data and not self.noEffSF:
665 if 'DNN' in self.identificationWP:
666 raise ValueError('DNN does not yet have efficiency correction, '
667 'please disable it by setting `noEffSF` to True.')
668
669 alg = config.createAlgorithm( 'CP::ElectronEfficiencyCorrectionAlg',
670 'ElectronEfficiencyCorrectionAlgReco' )
671 config.addPrivateTool( 'efficiencyCorrectionTool',
672 'AsgElectronEfficiencyCorrectionTool' )
673 alg.scaleFactorDecoration = 'el_reco_effSF' + selectionPostfix + '_%SYS%'
674 alg.efficiencyCorrectionTool.MapFilePath = map_file
675 alg.efficiencyCorrectionTool.RecoKey = "Reconstruction"
676 if self.correlationModelReco not in correlationModels:
677 raise ValueError('Invalid correlation model for reconstruction efficiency, '
678 f'has to be one of: {", ".join(correlationModels)}')
679 if config.geometry() >= LHCPeriod.Run3 and self.correlationModelReco != "TOTAL":
680 log.warning("Only TOTAL correlation model is currently supported "
681 "for reconstruction efficiency correction in Run 3.")
682 alg.efficiencyCorrectionTool.CorrelationModel = "TOTAL"
683 else:
684 alg.efficiencyCorrectionTool.CorrelationModel = self.correlationModelReco
685 if config.dataType() is DataType.FastSim:
686 alg.efficiencyCorrectionTool.ForceDataType = (
687 PATCore.ParticleDataType.Full if self.forceFullSimConfig
688 else PATCore.ParticleDataType.Fast)
689 elif config.dataType() is DataType.FullSim:
690 alg.efficiencyCorrectionTool.ForceDataType = \
691 PATCore.ParticleDataType.Full
692 alg.outOfValidity = 2
693 alg.outOfValidityDeco = 'el_reco_bad_eff' + selectionPostfix
694 alg.electrons = config.readName (self.containerName)
695 alg.preselection = config.getPreselection (self.containerName, self.selectionName)
696 if self.saveDetailedSF:
697 config.addOutputVar (self.containerName, alg.scaleFactorDecoration,
698 'reco_effSF' + postfix)
699 sfList += [alg.scaleFactorDecoration]
700
701
702 if config.dataType() is not DataType.Data and not self.noEffSF and self.identificationWP != 'NoID':
703
704 alg = config.createAlgorithm( 'CP::ElectronEfficiencyCorrectionAlg',
705 'ElectronEfficiencyCorrectionAlgID' )
706 config.addPrivateTool( 'efficiencyCorrectionTool',
707 'AsgElectronEfficiencyCorrectionTool' )
708 alg.scaleFactorDecoration = 'el_id_effSF' + selectionPostfix + '_%SYS%'
709 alg.efficiencyCorrectionTool.MapFilePath = map_file
710 alg.efficiencyCorrectionTool.IdKey = self.identificationWP.
replace(
"LH",
"")
711 if self.correlationModelId not in correlationModels:
712 raise ValueError('Invalid correlation model for identification efficiency, '
713 f'has to be one of: {", ".join(correlationModels)}')
714 alg.efficiencyCorrectionTool.CorrelationModel = self.correlationModelId
715 if config.dataType() is DataType.FastSim:
716 alg.efficiencyCorrectionTool.ForceDataType = (
717 PATCore.ParticleDataType.Full if self.forceFullSimConfig
718 else PATCore.ParticleDataType.Fast)
719 elif config.dataType() is DataType.FullSim:
720 alg.efficiencyCorrectionTool.ForceDataType = \
721 PATCore.ParticleDataType.Full
722 alg.outOfValidity = 2
723 alg.outOfValidityDeco = 'el_id_bad_eff' + selectionPostfix
724 alg.electrons = config.readName (self.containerName)
725 alg.preselection = config.getPreselection (self.containerName, self.selectionName)
726 if self.saveDetailedSF:
727 config.addOutputVar (self.containerName, alg.scaleFactorDecoration,
728 'id_effSF' + postfix)
729 sfList += [alg.scaleFactorDecoration]
730
731
732 if config.dataType() is not DataType.Data and self.isolationWP != 'NonIso' and not self.noEffSF:
733 alg = config.createAlgorithm( 'CP::ElectronEfficiencyCorrectionAlg',
734 'ElectronEfficiencyCorrectionAlgIsol' )
735 config.addPrivateTool( 'efficiencyCorrectionTool',
736 'AsgElectronEfficiencyCorrectionTool' )
737 alg.scaleFactorDecoration = 'el_isol_effSF' + selectionPostfix + '_%SYS%'
738 alg.efficiencyCorrectionTool.MapFilePath = map_file
739 alg.efficiencyCorrectionTool.IdKey = self.identificationWP.
replace(
"LH",
"")
740 alg.efficiencyCorrectionTool.IsoKey = self.isolationWP
741 if self.correlationModelIso not in correlationModels:
742 raise ValueError('Invalid correlation model for isolation efficiency, '
743 f'has to be one of: {", ".join(correlationModels)}')
744 if self.correlationModelIso != 'TOTAL':
745 log.warning("Only TOTAL correlation model is currently supported "
746 "for isolation efficiency correction in Run 3.")
747 alg.efficiencyCorrectionTool.CorrelationModel = "TOTAL"
748 if config.dataType() is DataType.FastSim:
749 alg.efficiencyCorrectionTool.ForceDataType = (
750 PATCore.ParticleDataType.Full if self.forceFullSimConfig
751 else PATCore.ParticleDataType.Fast)
752 elif config.dataType() is DataType.FullSim:
753 alg.efficiencyCorrectionTool.ForceDataType = \
754 PATCore.ParticleDataType.Full
755 alg.outOfValidity = 2
756 alg.outOfValidityDeco = 'el_isol_bad_eff' + selectionPostfix
757 alg.electrons = config.readName (self.containerName)
758 alg.preselection = config.getPreselection (self.containerName, self.selectionName)
759 if self.saveDetailedSF:
760 config.addOutputVar (self.containerName, alg.scaleFactorDecoration,
761 'isol_effSF' + postfix)
762 sfList += [alg.scaleFactorDecoration]
763
764 if (self.chargeIDSelectionRun2 and config.geometry() < LHCPeriod.Run3 and
765 config.dataType() is not DataType.Data and not self.noEffSF):
766 alg = config.createAlgorithm( 'CP::ElectronEfficiencyCorrectionAlg',
767 'ElectronEfficiencyCorrectionAlgEcids' )
768 config.addPrivateTool( 'efficiencyCorrectionTool',
769 'AsgElectronEfficiencyCorrectionTool' )
770 alg.scaleFactorDecoration = 'el_ecids_effSF' + selectionPostfix + '_%SYS%'
771 if self.isolationWP != 'Tight_VarRad':
772 raise ValueError('ECIDS SFs are supported only for Tight_VarRad isolation.')
773 if self.identificationWP == 'LooseBLayerLH':
774 ecids_lh = 'loose'
775 elif self.identificationWP == 'MediumLH':
776 ecids_lh = 'medium'
777 elif self.identificationWP == 'TightLH':
778 ecids_lh = 'tight'
779 else:
780 raise ValueError('ECIDS SFs are supported only for ID LooseBLayerLH, MediumLH, or TightLH')
781
782 alg.efficiencyCorrectionTool.CorrelationModel = "TOTAL"
783 alg.efficiencyCorrectionTool.CorrectionFileNameList = \
784 [f'ElectronEfficiencyCorrection/2015_2025/rel22.2/2025_Run2Rel22_Recommendation_v2/ecids/efficiencySF.ChargeID.{ecids_lh}_ECIDS_Tight_VarRad.root']
785 if config.dataType() is DataType.FastSim:
786 alg.efficiencyCorrectionTool.ForceDataType = (
787 PATCore.ParticleDataType.Full if self.forceFullSimConfig
788 else PATCore.ParticleDataType.Fast)
789 elif config.dataType() is DataType.FullSim:
790 alg.efficiencyCorrectionTool.ForceDataType = \
791 PATCore.ParticleDataType.Full
792 alg.outOfValidity = 2
793 alg.outOfValidityDeco = 'el_ecids_bad_eff' + selectionPostfix
794 alg.electrons = config.readName (self.containerName)
795 alg.preselection = config.getPreselection (self.containerName, self.selectionName)
796 if self.saveDetailedSF:
797 config.addOutputVar (self.containerName, alg.scaleFactorDecoration,
798 'ecids_effSF' + postfix)
799 sfList += [alg.scaleFactorDecoration]
800
801 if self.addChargeMisIDSF and config.dataType() is not DataType.Data and not self.noEffSF and config.geometry() >= LHCPeriod.Run3:
802 log.warning("Charge mis-ID SFs are only available for Run 2 and will not have any effect in Run 3.")
803
804 elif self.addChargeMisIDSF and config.dataType() is not DataType.Data and not self.noEffSF and config.geometry() < LHCPeriod.Run3:
805 alg = config.createAlgorithm( 'CP::ElectronEfficiencyCorrectionAlg',
806 'ElectronEfficiencyCorrectionAlgMisid' )
807 config.addPrivateTool( 'efficiencyCorrectionTool',
808 'CP::ElectronChargeEfficiencyCorrectionTool' )
809 alg.scaleFactorDecoration = 'el_charge_misid_effSF' + selectionPostfix + '_%SYS%'
810 if self.isolationWP != 'Tight_VarRad':
811 raise ValueError('Charge mis-ID SFs are supported only for Tight_VarRad isolation.')
812 if self.identificationWP == 'LooseBLayerLH':
813 misid_lh = 'LooseAndBLayerLLH'
814 elif self.identificationWP == 'MediumLH':
815 misid_lh = 'MediumLLH'
816 elif self.identificationWP == 'TightLH':
817 misid_lh = 'TightLLH'
818 else:
819 raise ValueError('Charge mis-ID SFs are supported only for ID LooseBLayerLH, MediumLH, or TightLH')
820 misid_suffix = '_ECIDSloose' if self.chargeIDSelectionRun2 else ''
821
822 alg.efficiencyCorrectionTool.CorrectionFileName = \
823 f'ElectronEfficiencyCorrection/2015_2025/rel22.2/2025_Run2Rel22_Recommendation_v2/charge_misID/chargeEfficiencySF.{misid_lh}_d0z0_TightVarRad{misid_suffix}.root'
824 if config.dataType() is DataType.FastSim:
825 alg.efficiencyCorrectionTool.ForceDataType = (
826 PATCore.ParticleDataType.Full if self.forceFullSimConfig
827 else PATCore.ParticleDataType.Fast)
828 elif config.dataType() is DataType.FullSim:
829 alg.efficiencyCorrectionTool.ForceDataType = \
830 PATCore.ParticleDataType.Full
831 alg.outOfValidity = 2
832 alg.outOfValidityDeco = 'el_misid_bad_eff' + selectionPostfix
833 alg.electrons = config.readName (self.containerName)
834 alg.preselection = config.getPreselection (self.containerName, self.selectionName)
835 if self.saveDetailedSF:
836 config.addOutputVar (self.containerName, alg.scaleFactorDecoration,
837 'charge_misid_effSF' + postfix)
838 sfList += [alg.scaleFactorDecoration]
839
840 if config.dataType() is not DataType.Data and not self.noEffSF and self.saveCombinedSF:
841 alg = config.createAlgorithm( 'CP::AsgObjectScaleFactorAlg',
842 'ElectronCombinedEfficiencyScaleFactorAlg' )
843 alg.particles = config.readName (self.containerName)
844 alg.inScaleFactors = sfList
845 alg.outScaleFactor = 'effSF' + postfix + '_%SYS%'
846 config.addOutputVar (self.containerName, alg.outScaleFactor, 'effSF' + postfix)
847
std::string replace(std::string s, const std::string &s2, const std::string &s3)