def make_ntuple(*legs, **kwargs): ''' Build an ntuple for a set of input legs. You can passes extra branches by passing a dict of branch:strings using the keyword argument: branches You can specify that no disambiguation can be applied (i.e. a dimuon candidate will appear twice in the mu-mu ntuple, in both orders) by setting 'noclean' to True in kwargs. ''' # Make sure we only use allowed leg types allowed = set(['m', 'e', 't', 'g', 'j']) assert (all(x in allowed for x in legs)) # Make object labels object_labels = [] format_labels = {} # Count how many objects of each type we put in counts = { 't': 0, 'm': 0, 'e': 0, 'g': 0, 'j': 0, } ntuple_config = _common_template.clone() # If we have two legs or photons, we are interested in VBF selections. if len(legs) == 2 or 'g' in legs: ntuple_config = PSet(ntuple_config, templates.topology.vbf) # Optionally apply extra branches in kwargs if 'branches' in kwargs: for branch, value in kwargs['branches'].iteritems(): setattr(ntuple_config, branch, cms.string(value)) # Check if we want to use special versions of the FSA producers # via a suffix on the producer name. producer_suffix = kwargs.get('suffix', '') for i, leg in enumerate(legs): counts[leg] += 1 # Check if we need to append an index (we have same flavor objects) label = leg if legs.count(leg) > 1: label = leg + str(counts[leg]) format_labels[label] = 'daughter(%i)' % i format_labels[label + '_idx'] = '%i' % i object_labels.append(label) # Get a PSet describing the branches for this leg leg_branches = _leg_templates[leg].replace(object=label) # Add to the total config ntuple_config = PSet(ntuple_config, leg_branches) #pdb.set_trace() # Now we need to add all the information about the pairs for leg_a, leg_b in itertools.combinations(object_labels, 2): ntuple_config = PSet( ntuple_config, templates.topology.pairs.replace(object1=leg_a, object2=leg_b), templates.topology.zboson.replace(object1=leg_a, object2=leg_b), ) # Check if we want to enable SVfit # Only do SVfit in states with 2 or 4 leptons do_svfit = kwargs.get("svFit", False) if not len(legs) % 2 == 0: do_svfit = False leg_a_type = leg_a[0] leg_b_type = leg_b[0] leg_a_index = legs.index(leg_a_type) \ if counts[leg_a_type] == 1 else legs.index(leg_a_type) + int(leg_a[1]) - 1 leg_b_index = legs.index(leg_b_type) \ if counts[leg_b_type] == 1 else legs.index(leg_b_type) + int(leg_b[1]) - 1 # Never do SVfit on 'non-paired' leptons (eg legs 0 & 2), or legs 1&3 # legs either adjacent or both ends (0 and 3) if leg_a_index % 2 != 0 or abs(leg_a_index - leg_b_index) % 2 != 1: do_svfit = False # Only do SVfit on mu + tau, e + tau, e + mu, & tau + tau combinations if leg_a_type == leg_b_type and leg_a_type in ('m', 'e'): do_svfit = False # Always ignore photons if 'g' in legs: do_svfit = False if do_svfit: print "SV fitting legs %s and %s in final state %s" % ( leg_a, leg_b, ''.join(legs)) ntuple_config = PSet( ntuple_config, templates.topology.svfit.replace(object1=leg_a, object2=leg_b)) # Are we running on the ZZ-specific collections? zz_mode = kwargs.get('zz_mode', False) analyzerSrc = "finalState" + "".join(_producer_translation[x] for x in legs) + producer_suffix if zz_mode: analyzerSrc += "Hzz" ntuple_config = PSet(ntuple_config, templates.topology.zzfsr) # Now build our analyzer EDFilter skeleton output = cms.EDFilter( "PATFinalStateAnalysisFilter", weights=cms.vstring(), # input final state collection. src=cms.InputTag(analyzerSrc), evtSrc=cms.InputTag("patFinalStateEventProducer"), # counter of events before any selections skimCounter=cms.InputTag("eventCount", "", "TUPLE"), analysis=cms.PSet( selections=cms.VPSet(), EventView=cms.bool(False), final=cms.PSet( sort=cms.string('daughter(0).pt'), # Doesn't really matter take=cms.uint32(50), plot=cms.PSet( histos=cms.VPSet(), # Don't make any final plots # ntuple has all generated branches in it. ntuple=ntuple_config.clone(), )), )) # Apply the basic selection to each leg for i, leg in enumerate(legs): output.analysis.selections.append( cms.PSet(name=cms.string('Leg%iPt' % i), cut=cms.string( 'daughter(%i).pt>%s' % (i, _pt_cuts[legs[i]]), ))) output.analysis.selections.append( cms.PSet(name=cms.string('Leg%iEta' % i), cut=cms.string('abs(daughter(%i).eta) < %s' % (i, _eta_cuts[legs[i]]))), ) # Apply "uniqueness requirements" to reduce final processing/storage. # This make sure there is only one ntuple entry per-final state. The # combinatorics due to different orderings are removed. # Algorithm: # if there are 2 of any given type, order them by pt # if there are 3 # first put best Z in initial position # then order first two by pt # if there are 4 # first put best Z in initial position # then order first two by pt # then order third and fourth by pt noclean = kwargs.get('noclean', False) # ZZ-producer does not require this cleaning step make_unique = not noclean and not zz_mode if make_unique: for type, count in counts.iteritems(): if count == 2: leg1_idx = format_labels['%s1_idx' % type] leg2_idx = format_labels['%s2_idx' % type] output.analysis.selections.append( cms.PSet(name=cms.string('%s_UniqueByPt' % type), cut=cms.string('orderedInPt(%s, %s)' % (leg1_idx, leg2_idx)))) if count == 3: leg1_idx_label = format_labels['%s1_idx' % type] leg2_idx_label = format_labels['%s2_idx' % type] leg3_idx_label = format_labels['%s3_idx' % type] # Require first two leptons make the best Z output.analysis.selections.append( cms.PSet( name=cms.string('Z12_Better_Z13'), cut=cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg1_idx_label, leg3_idx_label)))) output.analysis.selections.append( cms.PSet( name=cms.string('Z12_Better_Z23'), cut=cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg2_idx_label, leg3_idx_label)))) # Require first two leptons are ordered in PT output.analysis.selections.append( cms.PSet(name=cms.string('%s_UniqueByPt' % type), cut=cms.string('orderedInPt(%s, %s)' % (leg1_idx_label, leg2_idx_label)))) if count == 4: leg1_idx_label = format_labels['%s1_idx' % type] leg2_idx_label = format_labels['%s2_idx' % type] leg3_idx_label = format_labels['%s3_idx' % type] leg4_idx_label = format_labels['%s4_idx' % type] # Require first two leptons make the best Z output.analysis.selections.append( cms.PSet( name=cms.string('Z12_Better_Z13'), cut=cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg1_idx_label, leg3_idx_label)))) output.analysis.selections.append( cms.PSet( name=cms.string('Z12_Better_Z23'), cut=cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg2_idx_label, leg3_idx_label)))) output.analysis.selections.append( cms.PSet( name=cms.string('Z12_Better_Z14'), cut=cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg1_idx_label, leg4_idx_label)))) output.analysis.selections.append( cms.PSet( name=cms.string('Z12_Better_Z24'), cut=cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg2_idx_label, leg4_idx_label)))) output.analysis.selections.append( cms.PSet( name=cms.string('Z12_Better_Z34'), cut=cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg3_idx_label, leg4_idx_label)))) # Require first two leptons are ordered in PT output.analysis.selections.append( cms.PSet(name=cms.string('%s_UniqueByPt12' % type), cut=cms.string('orderedInPt(%s, %s)' % (leg1_idx_label, leg2_idx_label)))) # Require last two leptons are ordered in PT output.analysis.selections.append( cms.PSet(name=cms.string('%s_UniqueByPt34' % type), cut=cms.string('orderedInPt(%s, %s)' % (leg3_idx_label, leg4_idx_label)))) # Now apply our formatting operations format(output, **format_labels) # return LHEFilter*output return output
def make_ntuple(*legs, **kwargs): ''' Build an ntuple for a set of input legs. You can passes extra branches by passing a dict of branch:strings using the keyword argument: branches You can specify that no disambiguation can be applied (i.e. a dimuon candidate will appear twice in the mu-mu ntuple, in both orders) by setting 'noclean' to True in kwargs. ''' # Make sure we only use allowed leg types allowed = set(['m', 'e', 't', 'g','j']) assert(all(x in allowed for x in legs)) # Make object labels object_labels = [] format_labels = { } # Count how many objects of each type we put in counts = { 't': 0, 'm': 0, 'e': 0, 'g': 0, 'j': 0, } ntuple_config = _common_template.clone() if kwargs.get('runTauSpinner', False): for parName in templates.event.tauSpinner.parameterNames_(): setattr( ntuple_config, parName, getattr( templates.event.tauSpinner, parName ) ) # If we have two legs or photons, we are interested in VBF selections. if len(legs) == 2 or 'g' in legs: ntuple_config = PSet( ntuple_config, templates.topology.vbf ) # Optionally apply extra branches in kwargs if 'branches' in kwargs: for branch, value in kwargs['branches'].iteritems(): setattr(ntuple_config, branch, cms.string(value)) # Check if we want to use special versions of the FSA producers # via a suffix on the producer name. producer_suffix = kwargs.get('suffix', '') for i, leg in enumerate(legs): counts[leg] += 1 # Check if we need to append an index (we have same flavor objects) label = leg if legs.count(leg) > 1: label = leg + str(counts[leg]) format_labels[label] = 'daughter(%i)' % i format_labels[label + '_idx'] = '%i' % i object_labels.append(label) # Get a PSet describing the branches for this leg leg_branches = _leg_templates[leg].replace(object=label) # Add to the total config ntuple_config = PSet( ntuple_config, leg_branches ) #pdb.set_trace() # Now we need to add all the information about the pairs for leg_a, leg_b in itertools.combinations(object_labels, 2): ntuple_config = PSet( ntuple_config, templates.topology.pairs.replace(object1=leg_a, object2=leg_b), templates.topology.zboson.replace(object1=leg_a, object2=leg_b), ) # Check if we want to enable SVfit # Only do SVfit in states with 2 or 4 leptons do_svfit = kwargs.get("svFit", False) if not len(legs) % 2 == 0: do_svfit = False leg_a_type = leg_a[0] leg_b_type = leg_b[0] leg_a_index = legs.index(leg_a_type) \ if counts[leg_a_type] == 1 else legs.index(leg_a_type) + int(leg_a[1]) - 1 leg_b_index = legs.index(leg_b_type) \ if counts[leg_b_type] == 1 else legs.index(leg_b_type) + int(leg_b[1]) - 1 # Never do SVfit on 'non-paired' leptons (eg legs 0 & 2), or legs 1&3 # legs either adjacent or both ends (0 and 3) if leg_a_index % 2 != 0 or abs(leg_a_index - leg_b_index) % 2 != 1: do_svfit = False # Only do SVfit on mu + tau, e + tau, e + mu, & tau + tau combinations if leg_a_type == leg_b_type and leg_a_type in ('m', 'e'): do_svfit = False # Always ignore photons if 'g' in legs: do_svfit = False if do_svfit: print "SV fitting legs %s and %s in final state %s" % ( leg_a, leg_b, ''.join(legs)) ntuple_config = PSet( ntuple_config, templates.topology.svfit.replace(object1=leg_a, object2=leg_b) ) # Are we running on the ZZ-specific collections? zz_mode = kwargs.get('zz_mode', False) analyzerSrc = "finalState" + "".join( _producer_translation[x] for x in legs ) + producer_suffix if zz_mode: analyzerSrc += "Hzz" ntuple_config = PSet( ntuple_config, templates.topology.zzfsr ) # Now build our analyzer EDFilter skeleton output = cms.EDFilter( "PATFinalStateAnalysisFilter", weights=cms.vstring(), # input final state collection. src=cms.InputTag( analyzerSrc ), evtSrc=cms.InputTag("patFinalStateEventProducer"), # counter of events before any selections skimCounter=cms.InputTag("eventCount", "", "TUPLE"), analysis=cms.PSet( selections=cms.VPSet(), EventView=cms.bool(False), final=cms.PSet( sort=cms.string('daughter(0).pt'), # Doesn't really matter take=cms.uint32(50), plot=cms.PSet( histos=cms.VPSet(), # Don't make any final plots # ntuple has all generated branches in it. ntuple=ntuple_config.clone(), ) ), ) ) # Apply the basic selection to each leg for i, leg in enumerate(legs): output.analysis.selections.append( cms.PSet( name=cms.string('Leg%iPt' % i), cut=cms.string('daughter(%i).pt>%s' % ( i, _pt_cuts[legs[i]]), ) ) ) output.analysis.selections.append( cms.PSet( name=cms.string('Leg%iEta' % i), cut=cms.string('abs(daughter(%i).eta) < %s' % ( i, _eta_cuts[legs[i]])) ), ) #Apply additional selections if 'skimCuts' in kwargs and kwargs['skimCuts']: for cut in kwargs['skimCuts']: output.analysis.selections.append( cms.PSet( name = cms.string(cut), cut = cms.string(cut) ), ) # Apply "uniqueness requirements" to reduce final processing/storage. # This make sure there is only one ntuple entry per-final state. The # combinatorics due to different orderings are removed. # Algorithm: # if there are 2 of any given type, order them by pt # if there are 3 # first put best Z in initial position # then order first two by pt # if there are 4 # first put best Z in initial position # then order first two by pt # then order third and fourth by pt # # Algorithm for dblhMode: # if there are 4 # first two leptons must be positive # third and fourth leptons must be negative # order first two by pt # order third and fourth by pt noclean = kwargs.get('noclean', False) # ZZ-producer does not require this cleaning step make_unique = not noclean and not zz_mode isDblH = kwargs.get('dblhMode', False) if make_unique: for type, count in counts.iteritems(): if count == 2: leg1_idx = format_labels['%s1_idx' % type] leg2_idx = format_labels['%s2_idx' % type] output.analysis.selections.append(cms.PSet( name=cms.string('%s_UniqueByPt' % type), cut=cms.string('orderedInPt(%s, %s)' % (leg1_idx, leg2_idx)) )) if count == 3: leg1_idx_label = format_labels['%s1_idx' % type] leg2_idx_label = format_labels['%s2_idx' % type] leg3_idx_label = format_labels['%s3_idx' % type] # Require first two leptons make the best Z output.analysis.selections.append(cms.PSet( name=cms.string('Z12_Better_Z13'), cut=cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg1_idx_label, leg3_idx_label) ) )) output.analysis.selections.append(cms.PSet( name=cms.string('Z12_Better_Z23'), cut=cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg2_idx_label, leg3_idx_label) ) )) # Require first two leptons are ordered in PT output.analysis.selections.append(cms.PSet( name=cms.string('%s_UniqueByPt' % type), cut=cms.string('orderedInPt(%s, %s)' % (leg1_idx_label, leg2_idx_label)) )) if count == 4: leg1_idx_label = format_labels['%s1_idx' % type] leg2_idx_label = format_labels['%s2_idx' % type] leg3_idx_label = format_labels['%s3_idx' % type] leg4_idx_label = format_labels['%s4_idx' % type] if isDblH: output.analysis.selections.append(cms.PSet( name=cms.string('hpp12_and_hmm34'), cut=cms.string( 'hppCompatibility(%s, %s, 1) &&' 'hppCompatibility(%s, %s, -1)' % (leg1_idx_label, leg2_idx_label, leg3_idx_label, leg4_idx_label) ) )) else: # Require first two leptons make the best Z output.analysis.selections.append(cms.PSet( name=cms.string('Z12_Better_Z13'), cut=cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg1_idx_label, leg3_idx_label) ) )) output.analysis.selections.append(cms.PSet( name=cms.string('Z12_Better_Z23'), cut=cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg2_idx_label, leg3_idx_label) ) )) output.analysis.selections.append(cms.PSet( name=cms.string('Z12_Better_Z14'), cut=cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg1_idx_label, leg4_idx_label) ) )) output.analysis.selections.append(cms.PSet( name=cms.string('Z12_Better_Z24'), cut=cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg2_idx_label, leg4_idx_label) ) )) output.analysis.selections.append(cms.PSet( name=cms.string('Z12_Better_Z34'), cut=cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg3_idx_label, leg4_idx_label) ) )) # Require first two leptons are ordered in PT output.analysis.selections.append(cms.PSet( name=cms.string('%s_UniqueByPt12' % type), cut=cms.string('orderedInPt(%s, %s)' % (leg1_idx_label, leg2_idx_label)) )) # Require last two leptons are ordered in PT output.analysis.selections.append(cms.PSet( name=cms.string('%s_UniqueByPt34' % type), cut=cms.string('orderedInPt(%s, %s)' % (leg3_idx_label, leg4_idx_label)) )) # Now apply our formatting operations format(output, **format_labels) # return LHEFilter*output return output
def make_ntuple(*legs, **kwargs): ''' Build an ntuple for a set of input legs. You can passes extra branches by passing a dict of branch:strings using the keyword argument: branches ''' # Make sure we only use allowed leg types allowed = set(['m', 'e', 't']) assert(all(x in allowed for x in legs)) # Make object labels object_labels = [] format_labels = { } # Count how many objects of each type we put in counts = { 't' : 0, 'm' : 0, 'e' : 0 } ntuple_config = _common_template.clone() # Optionally apply extra branches in kwargs if 'branches' in kwargs: for branch, value in kwargs['branches'].iteritems(): setattr(ntuple_config, branch, cms.string(value)) for i, leg in enumerate(legs): counts[leg] += 1 # Check if we need to append an index (i.e. we have same flavor objects) label = leg if legs.count(leg) > 1: label = leg + str(counts[leg]) format_labels[label] = 'daughter(%i)' % i format_labels[label+ '_idx'] = '%i' % i object_labels.append(label) # Get a PSet describing the branches for this leg leg_branches = _leg_templates[leg].replace(object=label) # Add to the total config ntuple_config = PSet( ntuple_config, leg_branches ) #pdb.set_trace() # Now we need to add all the information about the pairs for leg_a, leg_b in itertools.combinations(object_labels, 2): ntuple_config = PSet( ntuple_config, templates.topology.pairs.replace(object1=leg_a, object2=leg_b), templates.topology.zboson.replace(object1=leg_a, object2=leg_b), ) # Now build our analyzer EDFilter skeleton output = cms.EDFilter( "PATFinalStateAnalysisFilter", weights = cms.vstring(), src = cms.InputTag("finalState" + "".join( _producer_translation[x] for x in legs)), evtSrc = cms.InputTag("patFinalStateEventProducer"), skimCounter = cms.InputTag("eventCount", "", "TUPLE"), analysis = cms.PSet( selections = cms.VPSet(), final = cms.PSet( sort = cms.string('daughter(0).pt'), # Doesn't really matter take = cms.uint32(50), plot = cms.PSet( histos = cms.VPSet(), # Don't make any final plots ntuple = ntuple_config.clone(), ) ), ) ) # Apply the basic selection to each leg for i, leg in enumerate(legs): output.analysis.selections.append( cms.PSet( name = cms.string('Leg%iPt' % i), cut = cms.string('daughter(%i).pt>%s' % ( i, _pt_cuts[legs[i]]), ) ) ) output.analysis.selections.append( cms.PSet( name = cms.string('Leg%iEta' % i), cut = cms.string('abs(daughter(%i).eta) < %s' % ( i, _eta_cuts[legs[i]])) ), ) # Apply "uniqueness requirements" to reduce final processing/storage. # This make sure there is only one ntuple entry per-final state. The # combinatorics due to different orderings are removed. # Algorithm: # if there are 2 of any given type, order them by pt # if there are 3 # first put best Z in initial position # then order first two by pt # if there are 4 # first put best Z in initial position # then order first two by pt # then order third and fourth by pt for type, count in counts.iteritems(): if count == 2: leg1_idx = format_labels['%s1_idx' % type] leg2_idx = format_labels['%s2_idx' % type] output.analysis.selections.append(cms.PSet( name = cms.string('%s_UniqueByPt' % type), cut = cms.string('orderedInPt(%s, %s)' % (leg1_idx, leg2_idx)) )) if count == 3: leg1_idx_label = format_labels['%s1_idx' % type] leg2_idx_label = format_labels['%s2_idx' % type] leg3_idx_label = format_labels['%s3_idx' % type] # Require first two leptons make the best Z output.analysis.selections.append(cms.PSet( name = cms.string('Z12_Better_Z13'), cut = cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg1_idx_label, leg3_idx_label) ) )) output.analysis.selections.append(cms.PSet( name = cms.string('Z12_Better_Z23'), cut = cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg2_idx_label, leg3_idx_label) ) )) # Require first two leptons are ordered in PT output.analysis.selections.append(cms.PSet( name = cms.string('%s_UniqueByPt' % type), cut = cms.string('orderedInPt(%s, %s)' % (leg1_idx_label, leg2_idx_label)) )) if count == 4: leg1_idx_label = format_labels['%s1_idx' % type] leg2_idx_label = format_labels['%s2_idx' % type] leg3_idx_label = format_labels['%s3_idx' % type] leg4_idx_label = format_labels['%s4_idx' % type] # Require first two leptons make the best Z output.analysis.selections.append(cms.PSet( name = cms.string('Z12_Better_Z13'), cut = cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg1_idx_label, leg3_idx_label) ) )) output.analysis.selections.append(cms.PSet( name = cms.string('Z12_Better_Z23'), cut = cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg2_idx_label, leg3_idx_label) ) )) output.analysis.selections.append(cms.PSet( name = cms.string('Z12_Better_Z14'), cut = cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg1_idx_label, leg4_idx_label) ) )) output.analysis.selections.append(cms.PSet( name = cms.string('Z12_Better_Z24'), cut = cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg2_idx_label, leg4_idx_label) ) )) output.analysis.selections.append(cms.PSet( name = cms.string('Z12_Better_Z34'), cut = cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg3_idx_label, leg4_idx_label) ) )) # Require first two leptons are ordered in PT output.analysis.selections.append(cms.PSet( name = cms.string('%s_UniqueByPt12' % type), cut = cms.string('orderedInPt(%s, %s)' % (leg1_idx_label, leg2_idx_label)) )) # Require last two leptons are ordered in PT output.analysis.selections.append(cms.PSet( name = cms.string('%s_UniqueByPt34' % type), cut = cms.string('orderedInPt(%s, %s)' % (leg3_idx_label, leg4_idx_label)) )) # Now apply our formatting operations format(output, **format_labels) return output
def make_ntuple(*legs, **kwargs): ''' Build an ntuple for a set of input legs. You can passes extra branches by passing a dict of branch:strings using the keyword argument: branches You can specify that no disambiguation can be applied (i.e. a dimuon candidate will appear twice in the mu-mu ntuple, in both orders) by setting 'noclean' to True in kwargs. ''' # Make sure we only use allowed leg types allowed = set(['m', 'e', 't', 'g']) assert(all(x in allowed for x in legs)) # Make object labels object_labels = [] format_labels = { } # Count how many objects of each type we put in counts = { 't' : 0, 'm' : 0, 'e' : 0, 'g' : 0 } ntuple_config = _common_template.clone() # If we only have two legs, we are interested in VBF selections. if len(legs) == 2: ntuple_config = PSet( ntuple_config, templates.topology.vbf ) # Optionally apply extra branches in kwargs if 'branches' in kwargs: for branch, value in kwargs['branches'].iteritems(): setattr(ntuple_config, branch, cms.string(value)) for i, leg in enumerate(legs): counts[leg] += 1 # Check if we need to append an index (i.e. we have same flavor objects) label = leg if legs.count(leg) > 1: label = leg + str(counts[leg]) format_labels[label] = 'daughter(%i)' % i format_labels[label+ '_idx'] = '%i' % i object_labels.append(label) # Get a PSet describing the branches for this leg leg_branches = _leg_templates[leg].replace(object=label) # Add to the total config ntuple_config = PSet( ntuple_config, leg_branches ) #pdb.set_trace() # Now we need to add all the information about the pairs for leg_a, leg_b in itertools.combinations(object_labels, 2): ntuple_config = PSet( ntuple_config, templates.topology.pairs.replace(object1=leg_a, object2=leg_b), templates.topology.zboson.replace(object1=leg_a, object2=leg_b), ) # Now build our analyzer EDFilter skeleton output = cms.EDFilter( "PATFinalStateAnalysisFilter", weights = cms.vstring(), src = cms.InputTag("finalState" + "".join( _producer_translation[x] for x in legs)), evtSrc = cms.InputTag("patFinalStateEventProducer"), skimCounter = cms.InputTag("eventCount", "", "TUPLE"), analysis = cms.PSet( selections = cms.VPSet(), final = cms.PSet( sort = cms.string('daughter(0).pt'), # Doesn't really matter take = cms.uint32(50), plot = cms.PSet( histos = cms.VPSet(), # Don't make any final plots ntuple = ntuple_config.clone(), ) ), ) ) # Apply the basic selection to each leg for i, leg in enumerate(legs): output.analysis.selections.append( cms.PSet( name = cms.string('Leg%iPt' % i), cut = cms.string('daughter(%i).pt>%s' % ( i, _pt_cuts[legs[i]]), ) ) ) output.analysis.selections.append( cms.PSet( name = cms.string('Leg%iEta' % i), cut = cms.string('abs(daughter(%i).eta) < %s' % ( i, _eta_cuts[legs[i]])) ), ) # Apply "uniqueness requirements" to reduce final processing/storage. # This make sure there is only one ntuple entry per-final state. The # combinatorics due to different orderings are removed. # Algorithm: # if there are 2 of any given type, order them by pt # if there are 3 # first put best Z in initial position # then order first two by pt # if there are 4 # first put best Z in initial position # then order first two by pt # then order third and fourth by pt make_unique = True if 'noclean' in kwargs: make_unique = False if make_unique: for type, count in counts.iteritems(): if count == 2: leg1_idx = format_labels['%s1_idx' % type] leg2_idx = format_labels['%s2_idx' % type] output.analysis.selections.append(cms.PSet( name = cms.string('%s_UniqueByPt' % type), cut = cms.string('orderedInPt(%s, %s)' % (leg1_idx, leg2_idx)) )) if count == 3: leg1_idx_label = format_labels['%s1_idx' % type] leg2_idx_label = format_labels['%s2_idx' % type] leg3_idx_label = format_labels['%s3_idx' % type] # Require first two leptons make the best Z output.analysis.selections.append(cms.PSet( name = cms.string('Z12_Better_Z13'), cut = cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg1_idx_label, leg3_idx_label) ) )) output.analysis.selections.append(cms.PSet( name = cms.string('Z12_Better_Z23'), cut = cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg2_idx_label, leg3_idx_label) ) )) # Require first two leptons are ordered in PT output.analysis.selections.append(cms.PSet( name = cms.string('%s_UniqueByPt' % type), cut = cms.string('orderedInPt(%s, %s)' % (leg1_idx_label, leg2_idx_label)) )) if count == 4: leg1_idx_label = format_labels['%s1_idx' % type] leg2_idx_label = format_labels['%s2_idx' % type] leg3_idx_label = format_labels['%s3_idx' % type] leg4_idx_label = format_labels['%s4_idx' % type] # Require first two leptons make the best Z output.analysis.selections.append(cms.PSet( name = cms.string('Z12_Better_Z13'), cut = cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg1_idx_label, leg3_idx_label) ) )) output.analysis.selections.append(cms.PSet( name = cms.string('Z12_Better_Z23'), cut = cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg2_idx_label, leg3_idx_label) ) )) output.analysis.selections.append(cms.PSet( name = cms.string('Z12_Better_Z14'), cut = cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg1_idx_label, leg4_idx_label) ) )) output.analysis.selections.append(cms.PSet( name = cms.string('Z12_Better_Z24'), cut = cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg2_idx_label, leg4_idx_label) ) )) output.analysis.selections.append(cms.PSet( name = cms.string('Z12_Better_Z34'), cut = cms.string( 'zCompatibility(%s, %s) < zCompatibility(%s, %s)' % (leg1_idx_label, leg2_idx_label, leg3_idx_label, leg4_idx_label) ) )) # Require first two leptons are ordered in PT output.analysis.selections.append(cms.PSet( name = cms.string('%s_UniqueByPt12' % type), cut = cms.string('orderedInPt(%s, %s)' % (leg1_idx_label, leg2_idx_label)) )) # Require last two leptons are ordered in PT output.analysis.selections.append(cms.PSet( name = cms.string('%s_UniqueByPt34' % type), cut = cms.string('orderedInPt(%s, %s)' % (leg3_idx_label, leg4_idx_label)) )) # Now apply our formatting operations format(output, **format_labels) return output