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
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
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
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
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)
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
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)
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))
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
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
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
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
def _set_decay_masses(self): decay_masses = [] for part in self._decay: decay_masses.append(ParticleDataSource.getMass(part)) self._decay_masses = decay_masses
def totalCharge(self): charge = 0. for name in self.names: charge += ParticleDataSource.getCharge(name) return charge
def totalMass(self): mass = 0. for name in self.names: mass += ParticleDataSource.getMass(name) return mass
def totalMass(particlelist): mass = 0. for name in particlelist: mass += ParticleDataSource.getMass(name) return mass
def _set_mass(self): self._mass = ParticleDataSource.getMass(self._name)
def _set_decayChannels(self): self._decay_channels = ParticleDataSource.getDecayChannels(self._name)
def _set_composition(self): self._composition = ParticleDataSource.getComposition(self._name)
def _set_type(self): self._type = ParticleDataSource.getType(self._name)
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
def _set_charge(self): self._charge = ParticleDataSource.getCharge(self._name)
def getmass(name): return ParticleDataSource.getMass(name)
def _set_symbolName(self): self._symbolName = ParticleDataSource.getSymbolName(self._name)
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]
def getcharge(name): return ParticleDataSource.getCharge(name)
def _set_pdgid(self, name): self._pdgid = ParticleDataSource.getPDGId(name)
def _set_lifetime(self): self._lifetime = ParticleDataSource.getTau(self._name)
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