예제 #1
0
 def get_particles(part,target='p+'):
     finalstate = [part,target]
     part_list = []
     for item in ParticleDataToolFetcher.getOriginParticles(finalstate):
         energythreshold = ParticleDataSource.getMass(item[1][0])-ParticleDataSource.getMass(target)
         part_list.append([energythreshold,item])
     return part_list
예제 #2
0
    def _build_all_particles(self):
        particles_list = []
        for output in self._outputs:
            thispart=[]
            possibleparts = (part for part in output[1] if 't' not in part)
            for part in possibleparts:
                try:
                    partarray = ExtraInfoFetcher.getParticleByComposition(part)
                    thispart.append(partarray)
                except:
                    print ('Not found', part)
                    thispart.append(None)
            if [] not in thispart and len(thispart)>1:
                particles_list.append([output[0],thispart])
        new_particle_list = []
        for item in particles_list:
            [new_particle_list.append([item[0],[x,y]]) for (x,y) in product(item[1][0],item[1][1])]

        newer_particle_list = []
        init_charge = self._part1.charge + self._part2.charge
        for item in new_particle_list:
            final_charge = ParticleDataSource.getCharge(item[1][0]) + ParticleDataSource.getCharge(item[1][1])
            if final_charge ==  init_charge:
                newer_particle_list .append(item)

        self._particle_list = newer_particle_list
예제 #3
0
 def _buildVirtualChannels(self):
     assert self._channel.length == 3
     virtualchannels = []
     for index, item in enumerate(self._channel.names):
         output1 = item
         output23 = self._channel.names[:index] + self._channel.names[
             index + 1:]
         virtuallist = self._alldecays.getParticlesfromDecay(output23)
         for item in virtuallist:
             BR1 = item.BR
             virtual = item.name
             if item.BR != 0.0 and not any(obj.particles[1].name == virtual
                                           for obj in virtualchannels):
                 BRW = VirtualParticleChannel.breit_wigner(
                     self._particle.name, virtual)
                 try:
                     BR2 = ParticleDataToolFetcher.getBR(
                         virtual, [
                             self._particle.name,
                             ParticleDataSource.getAnti(output1)
                         ])
                     prob = BR1 * BR2 * BRW
                     mass = ParticleDataSource.getMass(
                         virtual
                     )  #VirtualParticleChannel.totalMass(output23)  #
                     ri = RealInfo(output1)
                     vi = VirtualInfo(virtual, mass, output23)
                     vc = VirtualChannel(prob, [ri, vi])
                     virtualchannels.append(vc)
                 except:
                     pass
     return virtualchannels
예제 #4
0
 def breit_wigner(part0,virtpart):
     E = ParticleDataSource.getMass(part0)**2
     M = ParticleDataSource.getMass(virtpart)**2
     T = ParticleDataSource.getWidth(virtpart)**2
     gamma = math.sqrt((M+T)*M)
     k = 2*math.sqrt(2*M*T)*gamma/(math.pi*math.sqrt(M+gamma))
     result = k/((E-M)**2 + M*T)
     return result
예제 #5
0
def test_particle():
    # for part in ['u', "ubar", "d", "dbar","c","cbar","s","sbar","b","bbar"]:
    #     this = QuantumUniverseParticle(part)
    #     print (this.transformtime)
    particle = QuantumUniverseParticle('Omega*_c0')
    print(particle.decay_channels)
    print(particle.mass)
    for item in particle.decay_channels[0][1]:
        print(ParticleDataSource.getName(item))
    particle2 = QuantumUniverseParticle('Omega_c0')
    print(particle2.type)
    print(particle2.mass)
    print(particle.name in ParticleDataSource.getExcludedParticles())
    print(TransformationChannels.from_decaylist(particle.decay_channels).all)
예제 #6
0
 def _setMassArray(mass, decay):
     masses = [
         mass
     ]  # array of masses 0: parent particle, 1: first decay particle, ...
     for particle in decay:
         masses.append(ParticleDataSource.getMass(particle))
     return masses
예제 #7
0
    def from_decaylist(cls, decaylist, energy=0):
        '''
        We only accept 2body and 3body channels
        If we find a 1 body channel we use the decay channels of that particle
        '''
        tclist = []
        for channel in decaylist:
            TC = TransformationChannel(channel[0], channel[1])
            if all([
                    TC.length in [2, 3, 4],
                    TC.BR > 0.0,
                    TC.nameSet.intersection(
                        TransformationChannels.EXCLUDEDSET) == set([]),
                    #TC.totalMass <= energy
            ]):
                tclist.append(TC)
            elif TC.length == 1:
                oldBR = TC.BR

                newDCS = ParticleDataSource.getDecayChannels(TC.names[0])
                for newTC in TransformationChannels.from_decaylist(newDCS).all:
                    thisBR = newTC.BR
                    newTC = newTC._replace(BR=oldBR * thisBR)
                    tclist.append(newTC)
        return cls(tclist)
예제 #8
0
    def build_2body_file():
        particle_array = ['pi+','pi-','pi0','K+','K-','K0','J/psi','phi','Upsilon','B0','B+','B-','B_s0','B_c+','D+','D-','D0','D_s+','n0','p+','pbar-','Omega-','Omegabar+','Omega_c0','Omega_b-','Omega_bbar+','Xi0','Xi-','Xibar+','Xi_b0','Xi_b-','Xi_bbar+','Xi_cbar0','Xi_cbar-','Xi_c+','Sigma-','Sigma+','Sigma_b-','Sigma_b+','Sigma_cbar-','Sigma_cbar--','Sigma_c+','Sigma_c++','Delta++','Delta-','Deltabar--']
        inelastic_2body_data={}
        for target in ['p+','n0']:
            inelastic_2body_data[target] = {}
            for particle in particle_array:

                inelastic_output =Inelastic2BodyFile(particle,target)._particle_list
                if inelastic_output != []:
                    inelastic_2body_data[target][particle] = []
                    for output in inelastic_output:
                        mass = round(ParticleDataSource.getMass(output[0]) + ParticleDataSource.getMass(output[1]) - ParticleDataSource.getMass(target),4)
                        inelastic_2body_data[target][particle].append([mass,output])
        print (inelastic_2body_data)
        with open('./inelastic_2body_data.json', 'w') as f:
            f.write(json.dumps(inelastic_2body_data,indent=2, sort_keys=True, ensure_ascii=False))
예제 #9
0
 def set(decay_channels):
     list_decay = []
     buildWeights = Decay.buildWeights(decay_channels)
     if decay_channels != []:
         choice = Decay.weightedChoice(buildWeights[0], buildWeights[1])
         channel = decay_channels[choice][1]
         for pdgid in channel:
             list_decay.append(ParticleDataSource.getName(pdgid))
     return list_decay
예제 #10
0
 def _build_json():
     part_dict = {}
     for target in ['p+', 'n0']:
         part_dict[target]={}
         for item in ParticleDataSource.getParticleList():
             particles = InelasticFile.get_particles(item[1].name,target)
             if particles != []:
                 part_dict[target][item[1].name]=particles
     return part_dict
예제 #11
0
 def _build_quarktransformation(self):
     quark_list = self._setUnderCoverList(Inelastic2BodyFile.quarks)
     quark_transformation= {}
     for type in Inelastic2BodyFile.bosons[0]:
         quark_transformation[type]={}
         charge = ParticleDataSource.getCharge(type)
         for q in quark_list:
             newcharge = q.charge + charge
             if newcharge < 1 and newcharge > -1:
                 quark_transformation[type][q.name]=self.search_by_charge(newcharge)
     self._quarktransformation = quark_transformation
예제 #12
0
 def getParticlesfromDecay(self, decay):
     selected_particles = []
     for partchannel in self._allDecaysinDB:
         for channel in partchannel.decayChannels.getChannel(decay):
             if all([
                     set(decay) == channel.nameSet, channel.BR > 0.,
                     ParticleDataSource.getCharge(
                         partchannel.name) == channel.totalCharge,
                     partchannel.name in AllDecays.typical_particles
             ]):
                 if channel.isLeptonNeutrino():
                     if partchannel.name in ['W+', 'W-']:
                         selected_particles.append(
                             AllDecays.OriginOptions(
                                 partchannel.name, channel.BR))
                 else:
                     selected_particles.append(
                         AllDecays.OriginOptions(partchannel.name,
                                                 channel.BR))
     return selected_particles
예제 #13
0
    def _set_decay_masses(self):
        decay_masses = []
        for part in self._decay:
            decay_masses.append(ParticleDataSource.getMass(part))

        self._decay_masses = decay_masses
예제 #14
0
 def totalCharge(self):
     charge = 0.
     for name in self.names:
         charge += ParticleDataSource.getCharge(name)
     return charge
예제 #15
0
 def totalMass(self):
     mass = 0.
     for name in self.names:
         mass += ParticleDataSource.getMass(name)
     return mass
예제 #16
0
 def totalMass(particlelist):
     mass = 0.
     for name in particlelist:
         mass += ParticleDataSource.getMass(name)
     return mass
예제 #17
0
 def _set_mass(self):
     self._mass = ParticleDataSource.getMass(self._name)
예제 #18
0
 def _set_decayChannels(self):
     self._decay_channels = ParticleDataSource.getDecayChannels(self._name)
예제 #19
0
 def _set_composition(self):
     self._composition = ParticleDataSource.getComposition(self._name)
예제 #20
0
 def _set_type(self):
     self._type = ParticleDataSource.getType(self._name)
예제 #21
0
    def _buildVirtualChannels(self,decayparticles):
        '''
        0 -> o1+o2+o3; VP, virtual particles
        Create all combinations of o1 & o23
        Look for all VP -> o23
        Set de probability of the process through
         - BR1: the prob of the VP -> o23
         - Look for the BR2 of the process VP -> anti(o1) + 0
         - Set the Breit Wigner mass of the particle

        Set an array of VirtualChannels (namedtuples)
        '''
        assert len(decayparticles) == 3
        VirtualChannels = []
        for index, item in enumerate(decayparticles):
            output1 = item
            output23 = decayparticles[:index]+decayparticles[index+1:]
            virtuallist = ParticleDataToolFetcher.getOriginParticles(output23)
            #if lepton neutrino only accept W+-
            if VirtualParticleChannel.leptonnumber(output23)==0:
                for index, item in enumerate(virtuallist):
                    if item[1][0] in ['W+','W-']:
                        virtuallist = [virtuallist[index]]
                        break

            for item in virtuallist:
                BR1 = item[0]
                virtual = item[1][0]
                if BR1 != 0.0:
                    BRW = VirtualParticleChannel.breit_wigner(self._particle.name, virtual)
                    try:
                        BR2 = ParticleDataToolFetcher.getBR(virtual,[self._particle.name,ParticleDataSource.getAnti(output1)])
                        prob = BR1*BR2*BRW
                        vc = VirtualChannel(output1, virtual, output23, BR1, BR2, BRW, prob)
                        VirtualChannels.append(vc)
                    except:
                        pass
        self._virtualchannels = VirtualChannels
예제 #22
0
 def _set_charge(self):
     self._charge = ParticleDataSource.getCharge(self._name)
예제 #23
0
 def getmass(name):
     return ParticleDataSource.getMass(name)
예제 #24
0
 def _set_symbolName(self):
     self._symbolName = ParticleDataSource.getSymbolName(self._name)
예제 #25
0
class TransformationChannels(object):
    '''
    TCS class includes ALL the channels of a particular transformation
    TCS = TransformationChannels.from_decaylist([(0.5,[1,2]),(0.5,[3,4])])
    TCS = TransformationChannels.from_decaylistNames([(0.5,['e-','nu_ebar']),(0.5,['mu-','nu_mubar'])])
    TCS.all = [TC1,TC2]
    TCS.length = 2
    TCS.mostProbable: the TC with higher BR
    TCS.getChannel(1) = TC2
    TCS.getChannel(['mu-','nu_mubar']) = TC2
    TCS.lengthCut(3) -> TCs with number of output particles <= 3
    TCS.lengthSelection(3) -> TCs with number of output particles = 3
    '''
    EXCLUDED = ParticleDataSource.getExcludedParticles()
    additional = ['g', 'Omega*_c0', 'Omega_c0']
    EXCLUDED.extend(additional)
    EXCLUDEDSET = set(EXCLUDED)

    #EXCLUDED = set(['rndmflavgbar','rndmflavg','g'])

    def __init__(self, tclist):
        self._tclist = tclist

    @classmethod
    def from_decaylist(cls, decaylist, energy=0):
        '''
        We only accept 2body and 3body channels
        If we find a 1 body channel we use the decay channels of that particle
        '''
        tclist = []
        for channel in decaylist:
            TC = TransformationChannel(channel[0], channel[1])
            if all([
                    TC.length in [2, 3, 4],
                    TC.BR > 0.0,
                    TC.nameSet.intersection(
                        TransformationChannels.EXCLUDEDSET) == set([]),
                    #TC.totalMass <= energy
            ]):
                tclist.append(TC)
            elif TC.length == 1:
                oldBR = TC.BR

                newDCS = ParticleDataSource.getDecayChannels(TC.names[0])
                for newTC in TransformationChannels.from_decaylist(newDCS).all:
                    thisBR = newTC.BR
                    newTC = newTC._replace(BR=oldBR * thisBR)
                    tclist.append(newTC)
        return cls(tclist)

    @classmethod
    def from_decaylistNames(cls, decaylist):
        tclist = []
        for channel in decaylist:
            TC = TransformationChannel(
                channel[0], list(map(ParticleDataSource.getPDGId, channel[1])))
            if all([
                    TC.length in [2, 3, 4], TC.BR > 0.0,
                    TC.nameSet.intersection(
                        TransformationChannels.EXCLUDED) == set([])
            ]):
                tclist.append(TC)
        return cls(tclist)

    @property
    def all(self):
        return self._tclist

    @property
    def length(self):
        return len(self._tclist)

    @property
    def mostProbable(self):
        return sorted(self._tclist, key=lambda x: x.BR)[-1]

    def getChannel(self, *arg):
        if isinstance(arg[0], (int, long)):
            return self.getChannelfromId(arg[0])
        elif isinstance(arg[0], list):
            return self.getChannelfromParticles(arg[0])

    def getChannelfromId(self, id):
        try:
            return self.all[id]
        except:
            return []

    def getChannelfromParticles(self, particles):
        try:
            return [
                channel for channel in self.all
                if channel.nameSet == set(particles)
                and channel.length == len(particles)
            ]
        except:
            return []

    def lengthCut(self, len):
        return [channel for channel in self._tclist if channel.length <= len]

    def lengthSelection(self, len):
        return [channel for channel in self._tclist if channel.length == len]
예제 #26
0
 def getcharge(name):
     return ParticleDataSource.getCharge(name)
예제 #27
0
 def _set_pdgid(self, name):
     self._pdgid = ParticleDataSource.getPDGId(name)
예제 #28
0
 def _set_lifetime(self):
     self._lifetime = ParticleDataSource.getTau(self._name)
예제 #29
0
    def set_channel_choice(name,decay,limits):

        import xml.etree.ElementTree as ET
        import os

        base = 'C:\Users\Sergi\Anaconda2\Lib\site-packages\particletools'

        searchpaths = (base + '/ParticleData.xml', 'ParticleData.xml',
                       '../ParticleData.xml',
                       'ParticleDataTool/ParticleData.xml')
        xmlname = None
        for p in searchpaths:
            if os.path.isfile(p):
                xmlname = p
                break
        if xmlname is None:
            raise IOError('ParticleDataTool::_load_xml(): '
                          'XML file not found.')
        root = ET.parse(xmlname).getroot()


        k = ParticleDataSource.getPDGId(name)
        ids = [k]
        ids.append(ParticleDataSource.getPDGId(decay[0]))
        ids.append(ParticleDataSource.getPDGId(decay[1]))
        ids.append(ParticleDataSource.getPDGId(decay[2]))

        tags = [[str(ids[0]),str(-ids[1])],
            [str(ids[0]),str(-ids[2])],
            [str(ids[0]),str(-ids[3])],
            [str(ids[1]),str(ids[2])],
            [str(ids[1]),str(ids[3])],
            [str(ids[2]),str(ids[3])]]
        tagsR = [[str(-ids[1]),str(ids[0])],
            [str(-ids[2]),str(ids[0])],
            [str(-ids[3]),str(ids[0])],
            [str(ids[2]),str(ids[1])],
            [str(ids[3]),str(ids[1])],
            [str(ids[3]),str(ids[2])]]
        tagsbar = [[str(-ids[0]), str(ids[1])],
            [str(-ids[0]),str(ids[2])],
            [str(-ids[0]),str(ids[3])],
            [str(-ids[1]),str(-ids[2])],
            [str(-ids[1]),str(-ids[3])],
            [str(-ids[2]),str(-ids[3])]]
        tagsbarR = [[str(ids[1]), str(-ids[0])],
            [str(ids[2]),str(-ids[0])],
            [str(ids[3]),str(-ids[0])],
            [str(-ids[2]),str(-ids[1])],
            [str(-ids[3]),str(-ids[1])],
            [str(-ids[3]),str(-ids[2])]]
        combs = {'01':[], '02':[], '03':[], '12':[], '13':[], '23':[]}
        masses = {}
        mwidth = {}
        for parent in root:
            if parent.tag == 'particle':
                for channel in parent:
                    if channel.attrib['products'] == ' '.join(tags[0]) or channel.attrib['products'] == ' '.join(tagsR[0]):
                        combs['01'].append(parent.attrib['name'])
                        masses[parent.attrib['name']]=parent.attrib['m0']
                    if channel.attrib['products'] == ' '.join(tags[1]) or channel.attrib['products'] == ' '.join(tagsR[1]):
                        combs['02'].append(parent.attrib['name'])
                        masses[parent.attrib['name']]=parent.attrib['m0']
                    if channel.attrib['products'] == ' '.join(tags[2]) or channel.attrib['products'] == ' '.join(tagsR[2]):
                        combs['03'].append(parent.attrib['name'])
                        masses[parent.attrib['name']]=parent.attrib['m0']
                    if channel.attrib['products'] == ' '.join(tags[3]) or channel.attrib['products'] == ' '.join(tagsR[3]):
                        combs['12'].append(parent.attrib['name'])
                    if channel.attrib['products'] == ' '.join(tags[4]) or channel.attrib['products'] == ' '.join(tagsR[4]):
                        combs['13'].append(parent.attrib['name'])
                    if channel.attrib['products'] == ' '.join(tags[5]) or channel.attrib['products'] == ' '.join(tagsR[5]):
                        combs['23'].append(parent.attrib['name'])

                    if channel.attrib['products'] == ' '.join(tagsbar[0]) or channel.attrib['products'] == ' '.join(tagsbarR[0]):
                        combs['01'].append(parent.attrib['antiName'])
                        masses[parent.attrib['antiName']]=parent.attrib['m0']
                    if channel.attrib['products'] == ' '.join(tagsbar[1]) or channel.attrib['products'] == ' '.join(tagsbarR[1]):
                        combs['02'].append(parent.attrib['antiName'])
                        masses[parent.attrib['antiName']]=parent.attrib['m0']
                    if channel.attrib['products'] == ' '.join(tagsbar[2]) or channel.attrib['products'] == ' '.join(tagsbarR[2]):
                        combs['03'].append(parent.attrib['antiName'])
                        masses[parent.attrib['antiName']]=parent.attrib['m0']
                    if channel.attrib['products'] == ' '.join(tagsbar[3]) or channel.attrib['products'] == ' '.join(tagsbarR[3]):
                        combs['12'].append(parent.attrib['antiName'])
                    if channel.attrib['products'] == ' '.join(tagsbar[4]) or channel.attrib['products'] == ' '.join(tagsbarR[4]):
                        combs['13'].append(parent.attrib['antiName'])
                    if channel.attrib['products'] == ' '.join(tagsbar[5]) or channel.attrib['products'] == ' '.join(tagsbarR[5]):
                        combs['23'].append(parent.attrib['antiName'])

        poss1 = list(set(combs['01']).intersection(combs['23']))
        mposs1 = []
        for poss in poss1:
            mposs1.append(masses[poss])

        GeVfm = 0.19732696312541853
        fp = [] #final possibilities
        ew = []
        min1 = []
        for poss in poss1:
            if masses[poss] == min(mposs1):
                min1.append(poss)
            # We're giving total priority to these three particles and ignoring other options with this choice
            if poss in ['Z0','W+','W-']:
                min1 = [poss, masses[poss]]
                break
            if poss == poss1[-1]:
                min1.append(min(mposs1))

        # We filter out those options for which we won't be able to fetch the data
        for poss in min1[:-1]:
            try:
                ParticleDataSource.getCTau(poss)
            except:
                min1.remove(poss)
        # If we're left without options we need to remove the mass too to avoid passing unwanted checks
        if len(min1)==1:
            min1=[]

        if len(min1)>2:
            n = random.randint(0,len(min1)-2)
            a = min1[n]
            min1 = [a,min(mposs1)]

        if len(min1)>0:
            min1.append(GeVfm/ParticleDataSource.getCTau(min1[0])*1e-15*100.0)
            min1.append(1)
            fp.append(min1)
            if min1[0] in ['W-','W+','Z0']:
                ew.append(min1)

        poss2 = list(set(combs['02']).intersection(combs['13']))
        mposs2 = []
        for poss in poss2:
            mposs2.append(masses[poss])

        min2 = []
        for poss in poss2:
            if masses[poss] == min(mposs2):
                min2.append(poss)
            if poss in ['Z0','W+','W-']:
                min2 = [poss, masses[poss]]
                break
            if poss == poss1[-1]:
                min1.append(min(mposs1))

        # We filter out those options for which we won't be able to fetch the data
        for poss in min2[:-1]:
            try:
                ParticleDataSource.getCTau(poss)
            except:
                min2.remove(poss)
        # If we're left without options we need to remove the mass too to avoid passing unwanted checks
        if len(min2)==1:
            min2=[]

        if len(min2)>2:
            n = random.randint(0,len(min2)-2)
            a = min2[n]
            min2 = [a,min(mposs2)]

        if len(min2)>0:
            min2.append(GeVfm/ParticleDataSource.getCTau(min2[0])*1e-15*100.0)
            min2.append(2)
            fp.append(min2)
            if min2[0] in ['W-','W+','Z0']:
                ew.append(min2)

        poss3 = list(set(combs['03']).intersection(combs['12']))
        mposs3 = []
        for poss in poss3:
            mposs3.append(masses[poss])

        min3 = []
        for poss in poss3:
            if masses[poss] == min(mposs3):
                min3.append(poss)
            if poss in ['Z0','W+','W-']:
                min3 = [poss, masses[poss]]
                break
            if poss == poss1[-1]:
                min1.append(min(mposs1))

        # We filter out those options for which we won't be able to fetch the data
        for poss in min3[:-1]:
            try:
                ParticleDataSource.getCTau(poss)
            except:
                min3.remove(poss)
        # If we're left without options we need to remove the mass too to avoid passing unwanted checks
        if len(min3)==1:
            min3=[]

        if len(min3)>2:
            n = random.randint(0,len(min3)-2)
            a = min3[n]
            min3 = [a,min(mposs3)]

        if len(min3)>0:
            min3.append(GeVfm/ParticleDataSource.getCTau(min3[0])*1e-15*100.0)
            min3.append(3)
            fp.append(min3)
            if min3[0] in ['W-','W+','Z0']:
                ew.append(min3)

        # If we found a choice compatible with electroweak theory, that's our first option
        if len(ew)>0:
            n = random.randint(0,len(ew)-1)
            fd = ew[n]
        # Otherwise, we might have found another option that is well known (CTau defined, etc.)
        else:
            weights = VirtualDecay.set_weights(fp)
            fd = Decay.weightedChoice(fp, weights)
        # Lastly, we might not have found a viable virtual decay option so we return the original decay,
        # but this option is considered at the end to fit the format of the return

        # We put a way out of the function if nothing was found to avoid errors fetching the 'NoneType' fd
        if type(fd)!=list:
            virtualp = {'name': []}
            return virtualp

        chnum = []
        for ind in range(len(decay)):
            if ind != fd[3]-1:
                chnum.append(str(ind+1))
        channel = ''.join(chnum)
        # For this specific 3 particle case, it might be simpler to use:
        # if self._is_virtual[0] == 0:
        #     channel = '23'
        # elif self._is_virtual[1] == 0:
        #     channel = '13'
        # else:
        #     channel = '12'

        virtual_particle = fd[0]
        virtual_particle_mass = fd[1]
        virtual_particle_width = fd[2]
        virtual_channel_freepart = fd[3]

        # We must set the virtual particle name (could be empty) and then flag which masses will come from the virtual particle
        virtual_mass = VirtualDecay.set_BW_mass(virtual_particle_mass, virtual_particle_width, limits[channel])

        # We set the threshold for no virtual decay if the virtual mass is on the lower end of our distribution
        # This way, it's more probable to see a virtual particle when we're close
        virtualp = {}
        if (virtual_particle in ['W-','W+','Z0']) or virtual_mass >= (limits[channel][0]+limits[channel][1])/2.:
            virtualp['name'] = virtual_particle
            virtualp['mass'] = virtual_mass
            virtualp['realmass'] = virtual_particle_mass
            virtualp['channel'] = virtual_channel_freepart
        else:
            virtualp['name'] = []

        return virtualp