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