Age | Commit message (Collapse) | Author |
|
This commit updates get_event() to include OWL, LG, FECD, BUTT, and NECK tubes.
|
|
|
|
|
|
|
|
No reason to use fast_sqrt() in get_theta0_min() since the argument isn't
guaranteed to be between 0 and 1.
|
|
|
|
This commit makes a few small changes to try and reduce the number of divisions
and multiplications done in get_expected_charge() to speed up the likelihood
function.
|
|
Since we already calculate sin(theta) in get_expected_charge() there's no
reason to calculate it again in get_probability(). This *may* already be
optimized out by the compiler.
|
|
|
|
|
|
This commit updates find_peaks() to only return peaks which are at least a
certain number of degrees apart from each other. This is because I found that
for many events the first few peaks would all be essentially the same direction
and so the fit was taking a lot of time fitting essentially the same seed
points. Since I now have to only try 3 peaks in order to get my grid jobs to
run for less than a few hours it's necessary to make sure we aren't just
fitting the same three directions for the "quick" minimization.
I also updated the fit to only use a maximum of 3 seed directions.
|
|
|
|
|
|
|
|
Also, update the step size for the energy during the final minimization to 10%.
|
|
|
|
|
|
This commit changes the format specifier for the values in sprintf_yaml_list()
from %.2g -> %.2f because YAML (at least the python parser) doesn't recognize
values like 1e+03 as floats.
|
|
Also, delete a check on cos_theta_pmt which isn't necessary.
|
|
- set number of shower points to 10 for the main fit
- set step size to 10% of the energy
- set max number of evals during quick minimization phase to 1000
|
|
|
|
I probably need to spend some time to optimize this along with the algorithm
for guessing the peaks, but for now I am just lowering this from 10 -> 5
because with 10 the number of quick minimizations for 3 particles is too big
and so the fits take way too long.
|
|
When plotting the likelihood function I realized that the fast likelihood
calculation was *very* noisy due to the way I calculated the shower and delta
ray charge. Although it works well for single particles, it is not suitable for
distinguishing which seed is the best when doing multi particle fits.
Eventually I may be able to fix this, but for now we just do the normal
likelihood calculation.
I also decreased the number of shower points from 100 -> 10 to speed things up.
|
|
Based on some testing it seems that when fitting muons the likelihood ratio and
angular fits are better without a minimum theta0. I also determined during
testing that the minimum value would cause a discontinuity in the derivative of
the charge as a function of position which could cause the estimate of the
direct charge to be worse.
|
|
|
|
This commit adds a new program called zdab-cat which is kind of like fit, but
just produces the YAML output without actually fitting anything.
|
|
|
|
|
|
Since we now calculate the expected charge from shower photons for muons we
need to initialize the angular distribution and a few other things in
particle_init().
|
|
Similarly to electrons, I fit an analytic form to the ratio of the number of
photons produced via shower particles over the radiative energy loss. In this
case, I chose the functional form:
ratio = a*(1-exp(-T/b))
since the ratio seemed to reach a constant value after a certain energy. I then
simulated a 10 GeV muon and it appears that the ratio might actually decrease
after that, so for higher energies I may have to come up with a different fit
function.
|
|
gsl error
|
|
|
|
|
|
delta rays
This commit introduces a new method for integrating over the particle track to
calculate the number of shower and delta ray photons expected at each PMT. The
reason for introducing a new method was that the previous method of just using
the trapezoidal rule was both inaccurate and not stable. By inaccurate I mean
that the trapezoidal rule was not producing a very good estimate of the true
integral and by not stable I mean that small changes in the fit parameters
(like theta and phi) could produce wildly different results. This meant that
the likelihood function was very noisy and was causing the minimizers to not be
able to find the global minimum.
The new integration method works *much* better than the trapezoidal rule for
the specific functions we are dealing with. The problem is essentially to
integrate the product of two functions over some interval, one of which is very
"peaky", i.e. we want to find:
\int f(x) g(x) dx
where f(x) is peaked around some region and g(x) is relatively smooth. For our
case, f(x) represents the angular distribution of the Cerenkov light and g(x)
represents the factors like solid angle, absorption, etc.
The technique I discovered was that you can approximate this integral via a
discrete sum:
constant \sum_i g(x_i)
where the x_i are chosen to have equal spacing along the range of the integral
of f(x), i.e.
x_i = F^(-1)(i*constant)
This new method produces likelihood functions which are *much* more smooth and
accurate than previously.
In addition, there are a few other fixes in this commit:
- switch from specifying a step size for the shower integration to a number of
points, i.e. dx_shower -> number of shower points
- only integrate to the PSUP
I realized that previously we were integrating to the end of the track even
if the particle left the PSUP, and that there was no code to deal with the
fact that light emitted beyond the PSUP can't make it back to the PMTs.
- only integrate to the Cerenkov threshold
When integrating over the particle track to calculate the expected number
of direct Cerenkov photons, we now only integrate the track up to the point
where the particle's velocity is 1/index. This should hopefully make the
likelihood smoother because previously the estimate would depend on exactly
whether the points we sampled the track were above or below this point.
- add a minimum theta0 value based on the angular width of the PMT
When calculating the expected number of Cerenkov photons we assumed that
the angular distribution was constant over the whole PMT. This is a bad
assumption when the particle is very close to the PMT. Really we should
average the function over all the angles of the PMT, but that would be too
computationally expensive so instead we just calculate a minimum theta0
value which depends on the distance and angle to the PMT. This seems to
make the likelihood much smoother for particles near the PSUP.
- add a factor of sin(theta) when checking if we can skip calculating the
charge in get_expected_charge()
- fix a nan in beta_root() when the momentum is negative
- update PSUP_RADIUS from 800 cm -> 840 cm
|
|
|
|
|
|
This commit updates the test-find-peaks script to plot Cerenkov rings for each
of the peaks. It also updates the script to use quad to find the position
instead of using the MC information. Finally, I added a -n argument to the
script to specify how many peaks to draw.
|
|
|
|
|
|
|
|
This commit updates the code to calculate the number of Cerenkov photons from
secondary particles produced in an electromagnetic shower from electrons to use
an energy dependent formula I fit to data simulated with RAT-PAC.
|
|
This commit updates the charge likelihood calculation to calculate:
P(hit,q|n) = P(q|hit,n)*P(hit|n)
This has almost no effect on the fit results, but is technically correct.
|
|
This commit updates the optics code to calculate the rayleigh scattering length
using the Einstein-Smoluchowski formula instead of using the effective rayleigh
scattering lengths from the RSPR bank.
|
|
|
|
Thanks clang!
|
|
Previously I was calculating the expected number of delta ray photons when
integrating over the shower path, but since the delta rays are produced along
the particle path and not further out like the shower photons, this wasn't
correct. The normalization of the probability distribution for the photons
produced along the path was also not handled correctly.
This commit adds a new function called integrate_path_delta_ray() to compute
the expected number of photons from delta rays hitting each PMT. Currently this
means that the likelihood function for muons will be significantly slower than
previously, but hopefully I can speed it up again in the future (for example by
skipping the shower calculation which is negligible for lower energy muons).
|
|
This commit speeds up the likelihood function by integrating the charge along
the track inline instead of creating an array and then calling trapz(). It also
introduces two global variables avg_index_d2o and avg_index_h2o which are the
average indices of refraction for D2O and H2O weighted by the PMT quantum
efficiency and the Cerenkov spectrum.
|
|
This commit speeds up the likelihood calculation by eliminating most calls to
acos(). This is done by updating the PMT response lookup tables to be as a
function of the cosine of the angle between the photon and the PMT normal
instead of the angle itself.
|
|
Previously I was computing the fraction of light absorbed and scattered by
calculating an average absorption and scattering length weighted by the
Cerenkov spectrum and the PMT quantum efficiency, which isn't correct since we
should be averaging the absorption and scattering probabilities, not the
absorption and scattering lengths.
This commit fixes this by instead computing the average probability that a
photon is absorbed or scattered as a function of the distance travelled by
integrating the absorption and scattering probabilities over all wavelengths
weighted by the PMT quantum efficiency and the Cerenkov spectrum.
|
|
|