问题
I have prepared a code in Python to do random sampling of beam structure and looking for photons. The evolution of photons with time follows a Poisson distribution. The beam structure I am simulating has 936 bins with first 900 bins having charge of 0.62 nC followed by a gap of 36 bins. Each bin is of 2 ns which means total revolution period of the beam (to complete one circle of synchrotron) is 1.872 microseconds (936 bins time 2 ns). We look for probability of getting photons in each bin. The rate parameter (probability of getting photons) is given by product of input count rate (defined as fr) and time bin size of 2ns (defined as dt). Since the product of fr*dt is very very small (around 0), most of the bins will have no photons and Poisson distribution will peak around 0. Indeed one needs to sample few thousand beam structure to get accurate results. In MATLAB, I simulated 10,000 beam structures to get meaningful results.
Below is my python code. I have defined one beam structure as y in my code. In order to repeat y several times, I have defined y1 (for repeating beam structure 5 times) or y2 (to repeat 100 times) and so on.
In Section 1 of the code, I loop over 936 bins of y and also make sure that bins having zero charge (last 36 bins) do not contribute to generation of photons. I loop over 936 bins of y and do a random sampling following a Poisson distribution with mean of fr*dt defined as spkt. Then I reshape spkt so that we get a single column matrix defined as spkt1. Then I print spkt1 which shows the bins having "True values". Finally I append the bins having "True" value in a empty matrix spks along with the bin number so that we get the timing information. The timing is stored in a separate array defined as spks_t. You can see by printing spks_t that we are storing the correct bins having "True" values.
Everything is working fine if I do it for one beam structure (y). However if I run the code replacing with y1 or y2 or y3, I am getting much larger number of bins having True values. As I said above since the mean of the distribution is very very small (fr*dt), I am expecting that most of the bins should be empty since the poisson distribution should peak at around zero. Also the processing time increases manifold if I use y2 or y3. Kindly suggest what is going wrong if I run the for loop for len(y2) or len(y3).
In Section 2, I am just extracting the timing of occurrence of photons by multiplying spks_t by dt.
In Section 3, I am rejecting the pile-up photons by rejecting those photons whose time difference with its consecutive photon is less than 80 ns.
Finally, I am extracting the Firingrate or Output Count Rate by dividing the clean photons by total simulation time.
import numpy as np
from matplotlib import pyplot as plt
import random
y = list(range(1,901))
for i in range(0,900):
y[i] = 62 * .000000001
i += 1
for i in range(900,936):
y.append(0)
y1 = np.tile(y,5)
t = [t * .000000001 for t in range(2,9362,2)]
y2 = np.tile(y,100)
t = [t * .000000001 for t in range(2,187202,2)]
y3 = np.tile(y,10000)
t = [t * .000000001 for t in range(2,18720002,2)]
fr = 10000
dt = .000000002
spks = []
spks_t = []
for i in range(len(y)):
if y[i] != 0:
spkt = np.random.rand(i+1)<fr*dt
spkt1 = np.reshape(spkt,(i+1,1))
print(spkt1[np.all(spkt1==True,axis=1),:],i+1)
if 'True' in str(spkt1[np.all(spkt1==True,axis=1),:]):
spks.append(spkt1[np.all(spkt1==True,axis=1),:])
spks_t.append(i+1)
len(spks)
print(spks_t)
spks_t1 = []
for i in range(len(spks_t)):
spks_t1.append(spks_t[i]*dt)
spks_pile=0
for i in range(len(spks)):
if (spks_t1[i]-spks_t1[i-1]< .000000080):
spks_pile += 1
i += 1
print(spks_pile-1)
Corrected_Photons = len(spks)-(spks_pile-1)
print(Corrected_Photons)
Firingrate = Corrected_Photons/(len(y2)*dt)
print(Firingrate)
回答1:
There are a few things to note:
NumPy has a
numpy.random.poisson(mean, size)
method to generate Poisson random numbers. However, note thatnumpy.random.*
functions are now legacy functions as of NumPy 1.17, in part because they use global state; NumPy 1.17 introduces a new random number generation system, where the new practice is to generate random numbers viaGenerator
objects. Example:rng = np.random.default_rng(); arr = rng.poisson(mean, size)
. See also: How to use numpy.random to generate random numbers from a certain distribution? .The sum of
n
independent Poisson(mean
) random numbers is Poisson(mean*n
) distributed (Devroye, "Non-Uniform Random Variate Generation", p. 501). For example, to generate a sum of 1000 Poisson random numbers with a mean of 1e-6, simply generate a single Poisson random number with a mean of 0.001 (because 1e-6 * 1000 = 0.001). This will save considerably on calls to the random number generator. See also: Performance for drawing numbers from Poisson distribution with low mean .
来源:https://stackoverflow.com/questions/62280517/random-number-generation-following-a-poisson-distribution