696 def makeAlgs (self, config) :
697
698 if self.forceFullSimConfig:
699 warnings.warn_explicit(
700 "You are running ElectronWorkingPointSelectionConfig forcing"
701 " full sim config. This is only intended to be used for"
702 " testing purposes.",
703 TestingOnlyWarning, filename='', lineno=0)
704
705 selectionPostfix = self.selectionName
706 if selectionPostfix != '' and selectionPostfix[0] != '_' :
707 selectionPostfix = '_' + selectionPostfix
708
709
710 if config.geometry() is LHCPeriod.Run1:
711 raise ValueError ("Can't set up the ElectronWorkingPointSelectionConfig with %s, there must be something wrong!" % config.geometry().value)
712
713 postfix = self.postfix
714 if postfix is None :
715 postfix = self.selectionName
716 if postfix != '' and postfix[0] != '_' :
717 postfix = '_' + postfix
718
719 correlationModels = ["SIMPLIFIED", "FULL", "TOTAL", "TOYS"]
720 map_file = 'ElectronEfficiencyCorrection/2015_2025/rel22.2/2026_Run2Run3_Recommendation_v2/map1.txt'
721 sfList = []
722
723 if config.dataType() is not DataType.Data and not self.noEffSF:
724 if 'DNN' in self.identificationWP:
725 raise ValueError('DNN does not yet have efficiency correction, '
726 'please disable it by setting `noEffSF` to True.')
727
728 alg = config.createAlgorithm( 'CP::ElectronEfficiencyCorrectionAlg',
729 'ElectronEfficiencyCorrectionAlgReco' )
730 config.addPrivateTool( 'efficiencyCorrectionTool',
731 'AsgElectronEfficiencyCorrectionTool' )
732 alg.scaleFactorDecoration = 'el_reco_effSF' + selectionPostfix + '_%SYS%'
733 alg.efficiencyCorrectionTool.MapFilePath = map_file
734 alg.efficiencyCorrectionTool.RecoKey = "Reconstruction"
735 if self.correlationModelReco not in correlationModels:
736 raise ValueError('Invalid correlation model for reconstruction efficiency, '
737 f'has to be one of: {", ".join(correlationModels)}')
738 if config.geometry() >= LHCPeriod.Run3 and self.correlationModelReco != "TOTAL":
739 warnings.warn_explicit(
740 "Only TOTAL correlation model is currently supported "
741 "for reconstruction efficiency correction in Run 3.",
742 ElectronEfficiencyCorrelationWarning,
743 filename='', lineno=0)
744 alg.efficiencyCorrectionTool.CorrelationModel = "TOTAL"
745 else:
746 alg.efficiencyCorrectionTool.CorrelationModel = self.correlationModelReco
747 if config.dataType() is DataType.FastSim:
748 alg.efficiencyCorrectionTool.ForceDataType = (
749 PATCore.ParticleDataType.Full if self.forceFullSimConfig
750 else PATCore.ParticleDataType.Fast)
751 elif config.dataType() is DataType.FullSim:
752 alg.efficiencyCorrectionTool.ForceDataType = \
753 PATCore.ParticleDataType.Full
754 alg.outOfValidity = 2
755 alg.outOfValidityDeco = 'el_reco_bad_eff' + selectionPostfix
756 alg.electrons = config.readName (self.containerName)
757 alg.preselection = config.getPreselection (self.containerName, self.selectionName)
758 if self.saveDetailedSF:
759 config.addOutputVar (self.containerName, alg.scaleFactorDecoration,
760 'reco_effSF' + postfix)
761 sfList += [alg.scaleFactorDecoration]
762
763
764 if config.dataType() is not DataType.Data and not self.noEffSF and self.identificationWP != 'NoID':
765
766 alg = config.createAlgorithm( 'CP::ElectronEfficiencyCorrectionAlg',
767 'ElectronEfficiencyCorrectionAlgID' )
768 config.addPrivateTool( 'efficiencyCorrectionTool',
769 'AsgElectronEfficiencyCorrectionTool' )
770 alg.scaleFactorDecoration = 'el_id_effSF' + selectionPostfix + '_%SYS%'
771 alg.efficiencyCorrectionTool.MapFilePath = map_file
772 alg.efficiencyCorrectionTool.IdKey = self.identificationWP
773 if self.correlationModelId not in correlationModels:
774 raise ValueError('Invalid correlation model for identification efficiency, '
775 f'has to be one of: {", ".join(correlationModels)}')
776 alg.efficiencyCorrectionTool.CorrelationModel = self.correlationModelId
777 if config.dataType() is DataType.FastSim:
778 alg.efficiencyCorrectionTool.ForceDataType = (
779 PATCore.ParticleDataType.Full if self.forceFullSimConfig
780 else PATCore.ParticleDataType.Fast)
781 elif config.dataType() is DataType.FullSim:
782 alg.efficiencyCorrectionTool.ForceDataType = \
783 PATCore.ParticleDataType.Full
784 alg.outOfValidity = 2
785 alg.outOfValidityDeco = 'el_id_bad_eff' + selectionPostfix
786 alg.electrons = config.readName (self.containerName)
787 alg.preselection = config.getPreselection (self.containerName, self.selectionName)
788 if self.saveDetailedSF:
789 config.addOutputVar (self.containerName, alg.scaleFactorDecoration,
790 'id_effSF' + postfix)
791 sfList += [alg.scaleFactorDecoration]
792
793
794 if config.dataType() is not DataType.Data and self.isolationWP != 'NonIso' and not self.noEffSF:
795 alg = config.createAlgorithm( 'CP::ElectronEfficiencyCorrectionAlg',
796 'ElectronEfficiencyCorrectionAlgIsol' )
797 config.addPrivateTool( 'efficiencyCorrectionTool',
798 'AsgElectronEfficiencyCorrectionTool' )
799 alg.scaleFactorDecoration = 'el_isol_effSF' + selectionPostfix + '_%SYS%'
800 alg.efficiencyCorrectionTool.MapFilePath = map_file
801 alg.efficiencyCorrectionTool.IdKey = self.identificationWP
802 alg.efficiencyCorrectionTool.IsoKey = self.isolationWP
803 if self.correlationModelIso not in correlationModels:
804 raise ValueError('Invalid correlation model for isolation efficiency, '
805 f'has to be one of: {", ".join(correlationModels)}')
806 if self.correlationModelIso != 'TOTAL':
807 warnings.warn_explicit(
808 "Only TOTAL correlation model is currently supported "
809 "for isolation efficiency correction in Run 3.",
810 ElectronEfficiencyCorrelationWarning,
811 filename='', lineno=0)
812 alg.efficiencyCorrectionTool.CorrelationModel = "TOTAL"
813 if config.dataType() is DataType.FastSim:
814 alg.efficiencyCorrectionTool.ForceDataType = (
815 PATCore.ParticleDataType.Full if self.forceFullSimConfig
816 else PATCore.ParticleDataType.Fast)
817 elif config.dataType() is DataType.FullSim:
818 alg.efficiencyCorrectionTool.ForceDataType = \
819 PATCore.ParticleDataType.Full
820 alg.outOfValidity = 2
821 alg.outOfValidityDeco = 'el_isol_bad_eff' + selectionPostfix
822 alg.electrons = config.readName (self.containerName)
823 alg.preselection = config.getPreselection (self.containerName, self.selectionName)
824 if self.saveDetailedSF:
825 config.addOutputVar (self.containerName, alg.scaleFactorDecoration,
826 'isol_effSF' + postfix, auxType='float')
827 sfList += [alg.scaleFactorDecoration]
828
829 if (self.chargeIDSelectionRun2 and config.geometry() < LHCPeriod.Run3 and
830 config.dataType() is not DataType.Data and not self.noEffSF):
831 alg = config.createAlgorithm( 'CP::ElectronEfficiencyCorrectionAlg',
832 'ElectronEfficiencyCorrectionAlgEcids' )
833 config.addPrivateTool( 'efficiencyCorrectionTool',
834 'AsgElectronEfficiencyCorrectionTool' )
835 alg.scaleFactorDecoration = 'el_ecids_effSF' + selectionPostfix + '_%SYS%'
836 if self.isolationWP != 'Tight_VarRad':
837 raise ValueError('ECIDS SFs are supported only for Tight_VarRad isolation.')
838 if self.identificationWP == 'LooseBLayerLH':
839 ecids_lh = 'loose'
840 elif self.identificationWP == 'MediumLH':
841 ecids_lh = 'medium'
842 elif self.identificationWP == 'TightLH':
843 ecids_lh = 'tight'
844 else:
845 raise ValueError('ECIDS SFs are supported only for ID LooseBLayerLH, MediumLH, or TightLH')
846
847 alg.efficiencyCorrectionTool.CorrelationModel = "TOTAL"
848 alg.efficiencyCorrectionTool.CorrectionFileNameList = \
849 [f'ElectronEfficiencyCorrection/2015_2025/rel22.2/2025_Run2Rel22_Recommendation_v2/ecids/efficiencySF.ChargeID.{ecids_lh}_ECIDS_Tight_VarRad.root']
850 if config.dataType() is DataType.FastSim:
851 alg.efficiencyCorrectionTool.ForceDataType = (
852 PATCore.ParticleDataType.Full if self.forceFullSimConfig
853 else PATCore.ParticleDataType.Fast)
854 elif config.dataType() is DataType.FullSim:
855 alg.efficiencyCorrectionTool.ForceDataType = \
856 PATCore.ParticleDataType.Full
857 alg.outOfValidity = 2
858 alg.outOfValidityDeco = 'el_ecids_bad_eff' + selectionPostfix
859 alg.electrons = config.readName (self.containerName)
860 alg.preselection = config.getPreselection (self.containerName, self.selectionName)
861 if self.saveDetailedSF:
862 config.addOutputVar (self.containerName, alg.scaleFactorDecoration,
863 'ecids_effSF' + postfix)
864 sfList += [alg.scaleFactorDecoration]
865
866 if self.addChargeMisIDSF and config.dataType() is not DataType.Data and not self.noEffSF and config.geometry() >= LHCPeriod.Run3:
867 warnings.warn_explicit(
868 "Charge mis-ID SFs are only available for Run 2 and will not"
869 " have any effect in Run 3.",
870 Run2OnlyFeatureWarning, filename='', lineno=0)
871
872 elif self.addChargeMisIDSF and config.dataType() is not DataType.Data and not self.noEffSF and config.geometry() < LHCPeriod.Run3:
873 alg = config.createAlgorithm( 'CP::ElectronEfficiencyCorrectionAlg',
874 'ElectronEfficiencyCorrectionAlgMisid' )
875 config.addPrivateTool( 'efficiencyCorrectionTool',
876 'CP::ElectronChargeEfficiencyCorrectionTool' )
877 alg.scaleFactorDecoration = 'el_charge_misid_effSF' + selectionPostfix + '_%SYS%'
878 if self.isolationWP != 'Tight_VarRad':
879 raise ValueError('Charge mis-ID SFs are supported only for Tight_VarRad isolation.')
880 if self.identificationWP == 'LooseBLayerLH':
881 misid_lh = 'LooseAndBLayerLLH'
882 elif self.identificationWP == 'MediumLH':
883 misid_lh = 'MediumLLH'
884 elif self.identificationWP == 'TightLH':
885 misid_lh = 'TightLLH'
886 else:
887 raise ValueError('Charge mis-ID SFs are supported only for ID LooseBLayerLH, MediumLH, or TightLH')
888 misid_suffix = '_ECIDSloose' if self.chargeIDSelectionRun2 else ''
889
890 alg.efficiencyCorrectionTool.CorrectionFileName = \
891 f'ElectronEfficiencyCorrection/2015_2025/rel22.2/2025_Run2Rel22_Recommendation_v2/charge_misID/chargeEfficiencySF.{misid_lh}_d0z0_TightVarRad{misid_suffix}.root'
892 if config.dataType() is DataType.FastSim:
893 alg.efficiencyCorrectionTool.ForceDataType = (
894 PATCore.ParticleDataType.Full if self.forceFullSimConfig
895 else PATCore.ParticleDataType.Fast)
896 elif config.dataType() is DataType.FullSim:
897 alg.efficiencyCorrectionTool.ForceDataType = \
898 PATCore.ParticleDataType.Full
899 alg.outOfValidity = 2
900 alg.outOfValidityDeco = 'el_misid_bad_eff' + selectionPostfix
901 alg.electrons = config.readName (self.containerName)
902 alg.preselection = config.getPreselection (self.containerName, self.selectionName)
903 if self.saveDetailedSF:
904 config.addOutputVar (self.containerName, alg.scaleFactorDecoration,
905 'charge_misid_effSF' + postfix)
906 sfList += [alg.scaleFactorDecoration]
907
908 if config.dataType() is not DataType.Data and not self.noEffSF and self.saveCombinedSF:
909 alg = config.createAlgorithm( 'CP::AsgObjectScaleFactorAlg',
910 'ElectronCombinedEfficiencyScaleFactorAlg' )
911 alg.particles = config.readName (self.containerName)
912 alg.inScaleFactors = sfList
913 alg.outScaleFactor = 'effSF' + postfix + '_%SYS%'
914 config.addOutputVar (self.containerName, alg.outScaleFactor, 'effSF' + postfix)
915