Beispiel #1
0
    def generate_virtuals(self):
        """For each process among the born_processes, creates the corresponding
        virtual amplitude"""
        
        # If not using MadLoop, then the LH order file generation and processing
        # will be entirely done during the output, so nothing must be done at
        # this stage yet.
        if self['OLP']!='MadLoop':
            logger.info("The loop matrix elements will be generated by "+\
                                     '%s at the output stage only.'%self['OLP'])
            return

        # determine the orders to be used to generate the loop
        loop_orders = {}
        for  born in self['born_processes']:
            for coup, val in fks_common.find_orders(born.born_amp).items():
                try:
                    loop_orders[coup] = max([loop_orders[coup], val])
                except KeyError:
                    loop_orders[coup] = val

        for i, born in enumerate(self['born_processes']):
            logger.info('Generating virtual matrix elements using MadLoop:')
            myproc = copy.copy(born.born_proc)
            # take the orders that are actually used bu the matrix element
            myproc['orders'] = loop_orders
            myproc['legs'] = fks_common.to_legs(copy.copy(myproc['legs']))
            logger.info('Generating virtual matrix element with MadLoop for process%s (%d / %d)' \
                    % (myproc.nice_string(print_weighted = False).replace(\
                                                             'Process', ''),
                        i + 1, len(self['born_processes'])))
            myamp = loop_diagram_generation.LoopAmplitude(myproc)
            if myamp.get('diagrams'):
                born.virt_amp = myamp
Beispiel #2
0
    def generate_virtuals(self):
        """For each process among the born_processes, creates the corresponding
        virtual amplitude"""
        
        # If not using MadLoop, then the LH order file generation and processing
        # will be entirely done during the output, so nothing must be done at
        # this stage yet.
        if self['OLP']!='MadLoop':
            logger.info("The loop matrix elements will be generated by "+\
                                     '%s at the output stage only.'%self['OLP'])
            return

        # determine the orders to be used to generate the loop
        loop_orders = {}
        for  born in self['born_processes']:
            for coup, val in fks_common.find_orders(born.born_amp).items():
                try:
                    loop_orders[coup] = max([loop_orders[coup], val])
                except KeyError:
                    loop_orders[coup] = val

        for i, born in enumerate(self['born_processes']):
            logger.info('Generating virtual matrix elements using MadLoop:')
            myproc = copy.copy(born.born_proc)
            # take the orders that are actually used bu the matrix element
            myproc['orders'] = loop_orders
            myproc['legs'] = fks_common.to_legs(copy.copy(myproc['legs']))
            logger.info('Generating virtual matrix element with MadLoop for process%s (%d / %d)' \
                    % (myproc.nice_string(print_weighted = False).replace(\
                                                             'Process', ''),
                        i + 1, len(self['born_processes'])))
            myamp = loop_diagram_generation.LoopAmplitude(myproc)
            if myamp.get('diagrams'):
                born.virt_amp = myamp
Beispiel #3
0
    def __init__(self, start_proc = None, remove_reals = True):
        """initialization: starts either from an amplitude or a process,
        then init the needed variables.
        remove_borns tells if the borns not needed for integration will be removed
        from the born list (mainly used for testing)"""
                
        self.splittings = {}
        self.reals = []
        self.fks_dirs = []
        self.leglist = []
        self.myorders = {}
        self.pdg_codes = []
        self.colors = []
        self.nlegs = 0
        self.fks_ipos = []
        self.fks_j_from_i = {}
        self.real_amps = []
        self.remove_reals = remove_reals
        self.nincoming = 0
        self.virt_amp = None

        if not remove_reals in [True, False]:
            raise fks_common.FKSProcessError(\
                    'Not valid type for remove_reals in FKSProcess')
        
        if start_proc:
            if isinstance(start_proc, MG.Process):
                self.born_proc = fks_common.sort_proc(start_proc) 
                self.born_amp = diagram_generation.Amplitude(self.born_proc)
            elif isinstance(start_proc, diagram_generation.Amplitude):
                self.born_proc = fks_common.sort_proc(start_proc.get('process'))
                self.born_amp = diagram_generation.Amplitude(self.born_proc)
            else:
                raise fks_common.FKSProcessError(\
                    'Not valid start_proc in FKSProcess')

            self.born_proc.set('legs_with_decays', MG.LegList())

            self.leglist = fks_common.to_fks_legs(
                                    self.born_proc['legs'], self.born_proc['model'])
            self.nlegs = len(self.leglist)
            self.pdg_codes = [leg.get('id') for leg in self.leglist]
            self.colors = [leg.get('color') for leg in self.leglist]
            self.isr = set([leg.get('color') for leg in self.leglist if not leg.get('state')]) != set([1])
            self.fsr = set([leg.get('color') for leg in self.leglist if leg.get('state')]) != set([1])
            for leg in self.leglist:
                if not leg['state']:
                    self.nincoming += 1
            self.orders = self.born_amp['process']['orders']
            # this is for cases in which the user specifies e.g. QED=0
            if sum(self.orders.values()) == 0:
                self.orders = fks_common.find_orders(self.born_amp)
                
            self.ndirs = 0
            for order in self.born_proc.get('perturbation_couplings'):
                self.find_reals(order)
    def __init__(self,
                 fksmulti,
                 loop_optimized=False,
                 gen_color=True,
                 decay_ids=[]):
        """Initialization from a FKSMultiProcess"""

        #swhich the other loggers off
        loggers_off = [
            logging.getLogger('madgraph.diagram_generation'),
            logging.getLogger('madgraph.helas_objects')
        ]
        old_levels = [logg.level for logg in loggers_off]
        for logg in loggers_off:
            logg.setLevel(logging.WARNING)

        self.loop_optimized = loop_optimized

        self['used_lorentz'] = []
        self['used_couplings'] = []
        self['processes'] = []

        self['max_particles'] = -1
        self['max_configs'] = -1

        if not fksmulti['ncores_for_proc_gen']:
            # generate the real ME's if they are needed.
            # note that it may not be always the case, e.g. it the NLO_mode is LOonly
            if fksmulti['real_amplitudes']:
                logger.info('Generating real emission matrix-elements...')
                self['real_matrix_elements'] = self.generate_matrix_elements(
                    copy.copy(fksmulti['real_amplitudes']),
                    combine_matrix_elements=False)
            else:
                self[
                    'real_matrix_elements'] = helas_objects.HelasMatrixElementList(
                    )

            self['matrix_elements'] = self.generate_matrix_elements_fks(
                fksmulti, gen_color, decay_ids)
            self['initial_states'] = []
            self['has_loops'] = len(self.get_virt_matrix_elements()) > 0

        else:
            self['has_loops'] = False
            #more efficient generation
            born_procs = fksmulti.get('born_processes')
            born_pdg_list = [[l['id'] for l in born.born_proc['legs']] \
            for born in born_procs ]
            loop_orders = {}
            for born in born_procs:
                for coup, val in fks_common.find_orders(born.born_amp).items():
                    try:
                        loop_orders[coup] = max([loop_orders[coup], val])
                    except KeyError:
                        loop_orders[coup] = val
            pdg_list = []
            real_amp_list = []
            for born in born_procs:
                for amp in born.real_amps:
                    if not pdg_list.count(amp.pdgs):
                        pdg_list.append(amp.pdgs)
                        real_amp_list.append(amp)

            #generating and store in tmp files all output corresponding to each real_amplitude
            real_out_list = []
            realmapin = []
            for i, real_amp in enumerate(real_amp_list):
                realmapin.append([i, real_amp])

            # start the pool instance with a signal instance to catch ctr+c
            original_sigint_handler = signal.signal(signal.SIGINT,
                                                    signal.SIG_IGN)
            if fksmulti['ncores_for_proc_gen'] < 0:  # use all cores
                pool = multiprocessing.Pool(maxtasksperchild=1)
            else:
                pool = multiprocessing.Pool(
                    processes=fksmulti['ncores_for_proc_gen'],
                    maxtasksperchild=1)
            signal.signal(signal.SIGINT, original_sigint_handler)

            logger.info('Generating real matrix elements...')
            try:
                # the very large timeout passed to get is to be able to catch
                # KeyboardInterrupts
                realmapout = pool.map_async(async_generate_real,
                                            realmapin).get(9999999)
            except KeyboardInterrupt:
                pool.terminate()
                raise KeyboardInterrupt

            realmapfiles = []
            for realout in realmapout:
                realmapfiles.append(realout[0])

            logger.info('Generating born and virtual matrix elements...')
            #now loop over born and consume reals, generate virtuals
            bornmapin = []
            OLP = fksmulti['OLP']
            for i, born in enumerate(born_procs):
                bornmapin.append([
                    i, born, born_pdg_list, loop_orders, pdg_list,
                    loop_optimized, OLP, realmapfiles
                ])

            try:
                bornmapout = pool.map_async(async_generate_born,
                                            bornmapin).get(9999999)
            except KeyboardInterrupt:
                pool.terminate()
                raise KeyboardInterrupt

            #remove real temp files
            for realtmp in realmapout:
                os.remove(realtmp[0])

            logger.info('Collecting infos and finalizing matrix elements...')
            unique_me_list = []
            duplicate_me_lists = []
            for bornout in bornmapout:
                mefile = bornout[0]
                metag = bornout[1]
                has_loops = bornout[2]
                self['has_loops'] = self['has_loops'] or has_loops
                processes = bornout[3]
                self['processes'].extend(processes)
                self['max_particles'] = max(
                    [self['max_configs']] +
                    [len(p['legs']) + 1 for p in bornout[3]])
                self['max_configs'] = max(self['max_configs'], bornout[4])
                unique = True
                for ime2, bornout2 in enumerate(unique_me_list):
                    mefile2 = bornout2[0]
                    metag2 = bornout2[1]
                    if metag == metag2:
                        duplicate_me_lists[ime2].append(mefile)
                        unique = False
                        break
                if unique:
                    unique_me_list.append(bornout)
                    duplicate_me_lists.append([])

            memapin = []
            for i, bornout in enumerate(unique_me_list):
                mefile = bornout[0]
                memapin.append([i, mefile, duplicate_me_lists[i]])

            try:
                memapout = pool.map_async(async_finalize_matrix_elements,
                                          memapin).get(9999999)
            except KeyboardInterrupt:
                pool.terminate()
                raise KeyboardInterrupt

            #remove born+virtual temp files
            for bornout in bornmapout:
                mefile = bornout[0]
                os.remove(mefile)

            pool.close()
            pool.join()

            #set final list of matrix elements (paths to temp files)
            matrix_elements = []
            for meout in memapout:
                matrix_elements.append(meout[0])

            self['matrix_elements'] = matrix_elements

            #cache information needed for output which will not be available from
            #the matrix elements later
            initial_states = []
            for meout in memapout:
                me_initial_states = meout[1]
                for state in me_initial_states:
                    initial_states.append(state)

            # remove doubles from the list
            checked = []
            for e in initial_states:
                if e not in checked:
                    checked.append(e)
            initial_states = checked

            self['initial_states'] = initial_states

            helas_list = []
            for meout in memapout:
                helas_list.extend(meout[2])
            self['used_lorentz'] = list(set(helas_list))

            coupling_list = []
            for meout in memapout:
                coupling_list.extend([c for l in meout[3] for c in l])
            self['used_couplings'] = list(set(coupling_list))

            has_virtuals = False
            for meout in memapout:
                if meout[4]:
                    has_virtuals = True
                    break
            self['has_virtuals'] = has_virtuals

            configs_list = [self['max_configs']]
            for meout in realmapout:
                configs_list.append(meout[1])
            self['max_configs'] = max(configs_list)

            nparticles_list = [self['max_particles']]
            for meout in realmapout:
                nparticles_list.append(meout[2])
            self['max_particles'] = max(nparticles_list)

        self['has_isr'] = fksmulti['has_isr']
        self['has_fsr'] = fksmulti['has_fsr']

        logger.info('... Done')

        for i, logg in enumerate(loggers_off):
            logg.setLevel(old_levels[i])
Beispiel #5
0
    def __init__(self, start_proc = None, remove_reals = True, ncores_for_proc_gen=0):
        """initialization: starts either from an amplitude or a process,
        then init the needed variables.
        remove_borns tells if the borns not needed for integration will be removed
        from the born list (mainly used for testing)
        ncores_for_proc_gen has the following meaning
           0 : do things the old way
           > 0 use ncores_for_proc_gen
           -1 : use all cores
        """
                
        self.splittings = {}
        self.reals = []
        self.fks_dirs = []
        self.leglist = []
        self.myorders = {}
        self.pdg_codes = []
        self.colors = [] # color
        self.charges = [] # charge
        self.nlegs = 0
        self.fks_ipos = []
        self.fks_j_from_i = {}
        self.real_amps = []
        self.remove_reals = remove_reals
        self.nincoming = 0
        self.virt_amp = None
        self.perturbation = 'QCD'
        self.ncores_for_proc_gen = ncores_for_proc_gen

        if not remove_reals in [True, False]:
            raise fks_common.FKSProcessError(\
                    'Not valid type for remove_reals in FKSProcess')

        if start_proc:
            if isinstance(start_proc, MG.Process):
                pertur = start_proc['perturbation_couplings']
                if pertur:
                    self.perturbation = sorted(pertur)[0]
                self.born_proc = fks_common.sort_proc(start_proc,pert = self.perturbation)
                # filter in Amplitude will legs sorted in bornproc
                bornproc = copy.copy(self.born_proc) # deepcopy might let T -> array
                assert bornproc==self.born_proc
                self.born_amp = diagram_generation.Amplitude(bornproc)
            elif isinstance(start_proc, diagram_generation.Amplitude):
                pertur = start_proc.get('process')['perturbation_couplings']
                if pertur:
                    self.perturbation = sorted(pertur)[0]
                self.born_proc = fks_common.sort_proc(start_proc.get('process'),\
                                                      pert = self.perturbation)
                # filter in Amplitude will legs sorted in bornproc
                bornproc = copy.copy(self.born_proc)
                assert bornproc == self.born_proc
                self.born_amp = diagram_generation.Amplitude(bornproc)
            else:
                raise fks_common.FKSProcessError(\
                    'Not valid start_proc in FKSProcess')
            self.born_proc.set('legs_with_decays', MG.LegList())

            self.leglist = fks_common.to_fks_legs(
                                    self.born_proc['legs'], self.born_proc['model'])
            self.nlegs = len(self.leglist)
            self.pdg_codes = [leg.get('id') for leg in self.leglist]
            if self.perturbation == 'QCD':
                self.colors = [leg.get('color') for leg in self.leglist]
                # in QCD, charge is irrelevant but impact the combine process !
                self.charges = [0. for leg in self.leglist]
                color = 'color'
                zero = 1
            elif self.perturbation == 'QED':
                self.colors = [leg.get('color') for leg in self.leglist]
                self.charges = [leg.get('charge') for leg in self.leglist]
                color = 'charge'
                zero = 0.
            # special treatment of photon is needed !
            self.isr = set([leg.get(color) for leg in self.leglist if not leg.get('state')]) != set([zero])
            self.fsr = set([leg.get(color) for leg in self.leglist if leg.get('state')]) != set([zero])
            for leg in self.leglist:
                if not leg['state']:
                    self.nincoming += 1
            self.orders = self.born_amp['process']['orders']
            # this is for cases in which the user specifies e.g. QED=0
            if sum(self.orders.values()) == 0:
                self.orders = fks_common.find_orders(self.born_amp)
                
            self.ndirs = 0
            # generate reals, when the mode is not LOonly
            # when is LOonly it is supposed to be a 'fake' NLO process
            # e.g. to be used in merged sampels at high multiplicities
            if self.born_proc['NLO_mode'] != 'LOonly':
                for order in self.born_proc.get('perturbation_couplings'):
                    self.find_reals(order)
Beispiel #6
0
    def __init__(self, start_proc = None, remove_reals = True, ncores_for_proc_gen=0):
        """initialization: starts either from an amplitude or a process,
        then init the needed variables.
        remove_borns tells if the borns not needed for integration will be removed
        from the born list (mainly used for testing)
        ncores_for_proc_gen has the following meaning
           0 : do things the old way
           > 0 use ncores_for_proc_gen
           -1 : use all cores
        """
                
        self.splittings = {}
        self.reals = []
        self.fks_dirs = []
        self.leglist = []
        self.myorders = {}
        self.pdg_codes = []
        self.colors = [] # color
        self.charges = [] # charge
        self.nlegs = 0
        self.fks_ipos = []
        self.fks_j_from_i = {}
        self.real_amps = []
        self.remove_reals = remove_reals
        self.nincoming = 0
        self.virt_amp = None
        self.perturbation = 'QCD'
        self.ncores_for_proc_gen = ncores_for_proc_gen

        if not remove_reals in [True, False]:
            raise fks_common.FKSProcessError(\
                    'Not valid type for remove_reals in FKSProcess')

        if start_proc:
            if isinstance(start_proc, MG.Process):
                pertur = start_proc['perturbation_couplings']
                if pertur:
                    self.perturbation = sorted(pertur)[0]
                self.born_proc = fks_common.sort_proc(start_proc,pert = self.perturbation)
                # filter in Amplitude will legs sorted in bornproc
                bornproc = copy.copy(self.born_proc) # deepcopy might let T -> array
                assert bornproc==self.born_proc
                self.born_amp = diagram_generation.Amplitude(bornproc)
            elif isinstance(start_proc, diagram_generation.Amplitude):
                pertur = start_proc.get('process')['perturbation_couplings']
                if pertur:
                    self.perturbation = sorted(pertur)[0]
                self.born_proc = fks_common.sort_proc(start_proc.get('process'),\
                                                      pert = self.perturbation)
                # filter in Amplitude will legs sorted in bornproc
                bornproc = copy.copy(self.born_proc)
                assert bornproc == self.born_proc
                self.born_amp = diagram_generation.Amplitude(bornproc)
            else:
                raise fks_common.FKSProcessError(\
                    'Not valid start_proc in FKSProcess')
            self.born_proc.set('legs_with_decays', MG.LegList())

            self.leglist = fks_common.to_fks_legs(
                                    self.born_proc['legs'], self.born_proc['model'])
            self.nlegs = len(self.leglist)
            self.pdg_codes = [leg.get('id') for leg in self.leglist]
            if self.perturbation == 'QCD':
                self.colors = [leg.get('color') for leg in self.leglist]
                # in QCD, charge is irrelevant but impact the combine process !
                self.charges = [0. for leg in self.leglist]
                color = 'color'
                zero = 1
            elif self.perturbation == 'QED':
                self.colors = [leg.get('color') for leg in self.leglist]
                self.charges = [leg.get('charge') for leg in self.leglist]
                color = 'charge'
                zero = 0.
            # special treatment of photon is needed !
            self.isr = set([leg.get(color) for leg in self.leglist if not leg.get('state')]) != set([zero])
            self.fsr = set([leg.get(color) for leg in self.leglist if leg.get('state')]) != set([zero])
            for leg in self.leglist:
                if not leg['state']:
                    self.nincoming += 1
            self.orders = self.born_amp['process']['orders']
            # this is for cases in which the user specifies e.g. QED=0
            if sum(self.orders.values()) == 0:
                self.orders = fks_common.find_orders(self.born_amp)
                
            self.ndirs = 0
            # generate reals, when the mode is not LOonly
            # when is LOonly it is supposed to be a 'fake' NLO process
            # e.g. to be used in merged sampels at high multiplicities
            if self.born_proc['NLO_mode'] != 'LOonly':
                for order in self.born_proc.get('perturbation_couplings'):
                    self.find_reals(order)
    def __init__(self, fksmulti, loop_optimized = False, gen_color =True, decay_ids =[]):
        """Initialization from a FKSMultiProcess"""

        #swhich the other loggers off
        loggers_off = [logging.getLogger('madgraph.diagram_generation'),
                       logging.getLogger('madgraph.helas_objects')]
        old_levels = [logg.level for logg in loggers_off]
        for logg in loggers_off:
            logg.setLevel(logging.WARNING)

        self.loop_optimized = loop_optimized

        self['used_lorentz'] = []
        self['used_couplings'] = []
        self['processes'] = []

        self['max_particles'] = -1
        self['max_configs'] = -1

        if not fksmulti['ncores_for_proc_gen']:
            # generate the real ME's if they are needed.
            # note that it may not be always the case, e.g. it the NLO_mode is LOonly
            if fksmulti['real_amplitudes']:
                logger.info('Generating real emission matrix-elements...')
                self['real_matrix_elements'] = self.generate_matrix_elements(
                        copy.copy(fksmulti['real_amplitudes']), combine_matrix_elements = False)
            else:
                self['real_matrix_elements'] = helas_objects.HelasMatrixElementList()

            self['matrix_elements'] = self.generate_matrix_elements_fks(
                                    fksmulti, 
                                    gen_color, decay_ids)
            self['initial_states']=[]
            self['has_loops'] = len(self.get_virt_matrix_elements()) > 0 

        else: 
            self['has_loops'] = False
            #more efficient generation
            born_procs = fksmulti.get('born_processes')
            born_pdg_list = [[l['id'] for l in born.born_proc['legs']] \
            for born in born_procs ]
            loop_orders = {}
            for  born in born_procs:
                for coup, val in fks_common.find_orders(born.born_amp).items():
                    try:
                        loop_orders[coup] = max([loop_orders[coup], val])
                    except KeyError:
                        loop_orders[coup] = val        
            pdg_list = []        
            real_amp_list = []
            for born in born_procs:
                for amp in born.real_amps:
                    if not pdg_list.count(amp.pdgs):
                        pdg_list.append(amp.pdgs)
                        real_amp_list.append(amp)
                        
            #generating and store in tmp files all output corresponding to each real_amplitude
            real_out_list = []
            realmapin = []
            for i,real_amp in enumerate(real_amp_list):
                realmapin.append([i,real_amp])

            # start the pool instance with a signal instance to catch ctr+c
            original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN)
            if fksmulti['ncores_for_proc_gen'] < 0: # use all cores
                pool = multiprocessing.Pool(maxtasksperchild=1)
            else:
                pool = multiprocessing.Pool(processes=fksmulti['ncores_for_proc_gen'],maxtasksperchild=1)
            signal.signal(signal.SIGINT, original_sigint_handler)

            logger.info('Generating real matrix elements...')
            try:
                # the very large timeout passed to get is to be able to catch
                # KeyboardInterrupts
                realmapout = pool.map_async(async_generate_real,realmapin).get(9999999)
            except KeyboardInterrupt:
                pool.terminate()
                raise KeyboardInterrupt 

            realmapfiles = []
            for realout in realmapout:
                realmapfiles.append(realout[0])

            logger.info('Generating born and virtual matrix elements...')
            #now loop over born and consume reals, generate virtuals
            bornmapin = []
            OLP=fksmulti['OLP']
            for i,born in enumerate(born_procs):
                bornmapin.append([i,born,born_pdg_list,loop_orders,pdg_list,loop_optimized,OLP,realmapfiles])

            try:
                bornmapout = pool.map_async(async_generate_born,bornmapin).get(9999999)
            except KeyboardInterrupt:
                pool.terminate()
                raise KeyboardInterrupt 

            #remove real temp files
            for realtmp in realmapout:
                os.remove(realtmp[0])
                
            logger.info('Collecting infos and finalizing matrix elements...')
            unique_me_list = []
            duplicate_me_lists = []
            for bornout in bornmapout:
                mefile = bornout[0]
                metag = bornout[1]
                has_loops = bornout[2]
                self['has_loops'] = self['has_loops'] or has_loops
                processes = bornout[3]
                self['processes'].extend(processes)
                unique = True
                for ime2,bornout2 in enumerate(unique_me_list):
                    mefile2 = bornout2[0]
                    metag2 = bornout2[1]
                    if metag==metag2:
                        duplicate_me_lists[ime2].append(mefile)
                        unique = False
                        break;
                if unique:
                    unique_me_list.append(bornout)
                    duplicate_me_lists.append([])
            
            memapin = []
            for i,bornout in enumerate(unique_me_list):
                mefile = bornout[0]
                memapin.append([i,mefile, duplicate_me_lists[i]])

            try:
                memapout = pool.map_async(async_finalize_matrix_elements,memapin).get(9999999)
            except KeyboardInterrupt:
                pool.terminate()
                raise KeyboardInterrupt 

            #remove born+virtual temp files
            for bornout in bornmapout:
                mefile = bornout[0]
                os.remove(mefile)

            pool.close()
            pool.join()

            #set final list of matrix elements (paths to temp files)
            matrix_elements = []
            for meout in memapout:
                matrix_elements.append(meout[0])
  
            self['matrix_elements']=matrix_elements
  
            #cache information needed for output which will not be available from
            #the matrix elements later
            initial_states = []
            for meout in memapout:
                me_initial_states = meout[1]
                for state in me_initial_states:
                    initial_states.append(state)
                              
            # remove doubles from the list
            checked = []
            for e in initial_states:
                if e not in checked:
                    checked.append(e)
            initial_states=checked

            self['initial_states']=initial_states
            
            helas_list = []
            for meout in memapout:
                helas_list.extend(meout[2])
            self['used_lorentz']=list(set(helas_list))        
            
            coupling_list = []
            for meout in memapout:
                coupling_list.extend([c for l in meout[3] for c in l])
            self['used_couplings'] = list(set(coupling_list)) 
            
            has_virtuals = False
            for meout in memapout:
                if meout[4]:
                    has_virtuals = True
                    break
            self['has_virtuals'] = has_virtuals
            
            configs_list = []
            for meout in realmapout:
                configs_list.append(meout[1])
            self['max_configs'] = max(configs_list)
            
            nparticles_list = []
            for meout in realmapout:
                nparticles_list.append(meout[2])
            self['max_particles'] = max(nparticles_list)        

        self['has_isr'] = fksmulti['has_isr']
        self['has_fsr'] = fksmulti['has_fsr']

        logger.info('... Done')

        for i, logg in enumerate(loggers_off):
            logg.setLevel(old_levels[i])