aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/likelihood.c21
-rw-r--r--src/pmt_response.c108
-rw-r--r--src/pmt_response.h5
3 files changed, 72 insertions, 62 deletions
diff --git a/src/likelihood.c b/src/likelihood.c
index 379ac9a..d29be5e 100644
--- a/src/likelihood.c
+++ b/src/likelihood.c
@@ -210,7 +210,7 @@ void particle_free(particle *p)
static double get_expected_charge_shower(particle *p, double *pos, double *dir, double *pmt_pos, double *pmt_normal, double r, double *reflected, double n_d2o, double n_h2o, double l_d2o, double l_h2o, double *q_delta_ray, double *q_indirect_delta_ray)
{
- double pmt_dir[3], cos_theta, omega, f, f_reflec, cos_theta_pmt, theta_pmt, charge, constant, prob_abs, prob_sct;
+ double pmt_dir[3], cos_theta, omega, f, f_reflec, cos_theta_pmt, charge, constant, prob_abs, prob_sct;
SUB(pmt_dir,pmt_pos,pos);
@@ -230,9 +230,8 @@ static double get_expected_charge_shower(particle *p, double *pos, double *dir,
omega = get_solid_angle_fast(pos,pmt_pos,pmt_normal,r);
- theta_pmt = acos(-cos_theta_pmt);
- f_reflec = get_weighted_pmt_reflectivity(theta_pmt);
- f = get_weighted_pmt_response(theta_pmt);
+ f_reflec = get_weighted_pmt_reflectivity(-cos_theta_pmt);
+ f = get_weighted_pmt_response(-cos_theta_pmt);
prob_abs = 1.0 - get_fabs_d2o(l_d2o)*get_fabs_h2o(l_h2o)*get_fabs_acrylic(AV_THICKNESS);
prob_sct = 1.0 - get_fsct_d2o(l_d2o)*get_fsct_h2o(l_h2o);
@@ -261,7 +260,7 @@ static double get_expected_charge_shower(particle *p, double *pos, double *dir,
static double get_expected_charge(double x, double beta, double theta0, double *pos, double *dir, double *pmt_pos, double *pmt_normal, double r, double *reflected, double n_d2o, double n_h2o, double l_d2o, double l_h2o)
{
- double pmt_dir[3], cos_theta, n, omega, z, R, f, f_reflec, cos_theta_pmt, theta_pmt, charge, prob_abs, prob_sct;
+ double pmt_dir[3], cos_theta, n, omega, z, R, f, f_reflec, cos_theta_pmt, charge, prob_abs, prob_sct;
z = 1.0;
@@ -289,9 +288,8 @@ static double get_expected_charge(double x, double beta, double theta0, double *
omega = get_solid_angle_fast(pos,pmt_pos,pmt_normal,r);
- theta_pmt = acos(-cos_theta_pmt);
- f_reflec = get_weighted_pmt_reflectivity(theta_pmt);
- f = get_weighted_pmt_response(theta_pmt);
+ f_reflec = get_weighted_pmt_reflectivity(-cos_theta_pmt);
+ f = get_weighted_pmt_response(-cos_theta_pmt);
/* Probability that a photon is absorbed. We calculate this by computing:
*
@@ -545,7 +543,7 @@ static double get_total_charge_approx(double beta0, double *pos, double *dir, pa
*
* `smax` is currently calculated as the point where the particle velocity
* drops to 0.8 times the speed of light. */
- double pmt_dir[3], tmp[3], R, cos_theta, x, z, s, a, b, beta, E, mom, T, omega, sin_theta, f, cos_theta_pmt, theta_pmt, l_h2o, l_d2o, f_reflec, charge, prob, frac, prob_abs, prob_sct;
+ double pmt_dir[3], tmp[3], R, cos_theta, x, z, s, a, b, beta, E, mom, T, omega, sin_theta, f, cos_theta_pmt, l_h2o, l_d2o, f_reflec, charge, prob, frac, prob_abs, prob_sct;
/* First, we find the point along the track where the PMT is at the
* Cerenkov angle. */
@@ -642,9 +640,8 @@ static double get_total_charge_approx(double beta0, double *pos, double *dir, pa
frac = sqrt(2)*n_d2o*x*beta0*theta0;
- theta_pmt = acos(-cos_theta_pmt);
- f = get_weighted_pmt_response(theta_pmt);
- f_reflec = get_weighted_pmt_reflectivity(theta_pmt);
+ f = get_weighted_pmt_response(-cos_theta_pmt);
+ f_reflec = get_weighted_pmt_reflectivity(-cos_theta_pmt);
prob_abs = 1.0 - get_fabs_d2o(l_d2o)*get_fabs_h2o(l_h2o)*get_fabs_acrylic(AV_THICKNESS);
prob_sct = 1.0 - get_fsct_d2o(l_d2o)*get_fsct_h2o(l_h2o);
diff --git a/src/pmt_response.c b/src/pmt_response.c
index cedc341..7d42a39 100644
--- a/src/pmt_response.c
+++ b/src/pmt_response.c
@@ -28,13 +28,18 @@
static int initialized = 0;
+/* Global error string set when pmt_response_init() returns -1. */
char pmtr_err[256];
+/* 2D lookup table for the PMT response as a function of angle and wavelength. */
static gsl_spline2d *spline_resp;
static gsl_spline2d *spline_reflec;
static gsl_interp_accel *xacc;
static gsl_interp_accel *yacc;
+/* Angles (in degrees) that the PMT response lookup table is defined for.
+ * Ideally these would have been stored with the table itself, but these are
+ * hardcoded in SNOMAN. */
static double thetas[NUM_ANGLES] = {
0.0,
1.0,
@@ -128,6 +133,9 @@ static double thetas[NUM_ANGLES] = {
89.0,
};
+/* Wavelengths (in nm) that the PMT response lookup table is defined for.
+ * Ideally these would have been stored with the table itself, but these are
+ * hardcoded in SNOMAN. */
static double wavelengths[NUM_WAVELENGTHS] = {
220.0,
230.0,
@@ -183,62 +191,62 @@ static double wavelengths[NUM_WAVELENGTHS] = {
/* PMT response as a function of angle and wavelength. */
static double resp[NUM_ANGLES*NUM_WAVELENGTHS];
-/* PMT response as a function of angle weighted by the Cerenkov spectrum and
- * the quantum efficiency. */
-static double weighted_resp[NUM_ANGLES];
-
/* PMT reflectivity as a function of angle and wavelength. */
static double reflec[NUM_ANGLES*NUM_WAVELENGTHS];
-/* PMT reflectivity as a function of angle weighted by the Cerenkov spectrum
+
+#define N 1000
+
+/* Lower bound for cos(theta). */
+static double xlo = 0.0;
+/* Upper bound for cos(theta). */
+static double xhi = 1.0;
+
+/* Array holding the values of cos(theta). */
+static double cos_thetas[N];
+
+/* PMT response as a function of cos(theta) weighted by the Cerenkov spectrum
* and the quantum efficiency. */
-static double weighted_reflec[NUM_ANGLES];
+static double weighted_resp[N];
+/* PMT reflectivity as a function of cos(theta) weighted by the Cerenkov
+ * spectrum and the quantum efficiency. */
+static double weighted_reflec[N];
-double get_weighted_pmt_reflectivity(double theta)
+/* Returns the probability that a photon is reflected as a function of the
+ * cosine of the photon angle with respect to the PMT normal.
+ *
+ * Note: The angle should be relative to the negative of the PMT normal, i.e. a
+ * photon incident perpendicular to the front of the PMT should have
+ *
+ * cos(theta) = 1.
+ *
+ */
+double get_weighted_pmt_reflectivity(double cos_theta)
{
- /* Returns the probability that a photon is reflected as a function of the
- * photon angle with respect to the PMT normal. `theta` should be in
- * radians. */
- double deg;
-
if (!initialized) {
fprintf(stderr, "pmt response hasn't been initialized!\n");
exit(1);
}
- /* Convert to degrees since the PMTR table is in degrees. */
- deg = theta*180.0/M_PI;
-
- deg = fmod(deg,180.0);
-
- if (deg < 0.0)
- deg += 180.0;
-
- return interp1d(deg, thetas, weighted_reflec, NUM_ANGLES);
+ return interp1d(cos_theta, cos_thetas, weighted_reflec, LEN(cos_thetas));
}
-double get_weighted_pmt_response(double theta)
+/* Returns the probability that a photon is detected as a function of the
+ * cosine of the photon angle with respect to the PMT normal.
+ *
+ * Note: The angle should be relative to the negative of the PMT normal, i.e. a
+ * photon incident perpendicular to the front of the PMT should have
+ *
+ * cos(theta) = 1.
+ *
+ * Note: This does *not* include the PMT quantum efficiency. */
+double get_weighted_pmt_response(double cos_theta)
{
- /* Returns the probability that a photon is detected as a function of the
- * photon angle with respect to the PMT normal. `theta` should be in
- * radians.
- *
- * Note: This does *not* include the PMT quantum efficiency. */
- double deg;
-
if (!initialized) {
fprintf(stderr, "pmt response hasn't been initialized!\n");
exit(1);
}
- /* Convert to degrees since the PMTR table is in degrees. */
- deg = theta*180.0/M_PI;
-
- deg = fmod(deg,180.0);
-
- if (deg < 0.0)
- deg += 180.0;
-
- return interp1d(deg, thetas, weighted_resp, NUM_ANGLES);
+ return interp1d(cos_theta, cos_thetas, weighted_resp, LEN(cos_thetas));
}
double get_pmt_reflectivity(double wavelength, double theta)
@@ -324,13 +332,13 @@ static double gsl_pmt_reflectivity(double wavelength, void *params)
/* Returns the probability that a photon is reflected as a function of
* wavelength for a specific angle weighted by the quantum efficiency and
* the Cerenkov spectrum. */
- double qe, theta;
+ double qe, cos_theta;
- theta = ((double *) params)[0];
+ cos_theta = ((double *) params)[0];
qe = get_quantum_efficiency(wavelength);
- return qe*get_pmt_reflectivity(wavelength,theta)/pow(wavelength,2);
+ return qe*get_pmt_reflectivity(wavelength,acos(cos_theta))/pow(wavelength,2);
}
static double gsl_pmt_response(double wavelength, void *params)
@@ -338,13 +346,13 @@ static double gsl_pmt_response(double wavelength, void *params)
/* Returns the probability that a photon is detected as a function of
* wavelength for a specific angle weighted by the quantum efficiency and
* the Cerenkov spectrum. */
- double qe, theta;
+ double qe, cos_theta;
- theta = ((double *) params)[0];
+ cos_theta = ((double *) params)[0];
qe = get_quantum_efficiency(wavelength);
- return qe*get_pmt_response(wavelength,theta)/pow(wavelength,2);
+ return qe*get_pmt_response(wavelength,acos(cos_theta))/pow(wavelength,2);
}
static double gsl_cerenkov(double wavelength, void *params)
@@ -406,10 +414,14 @@ int pmt_response_init(dict *db)
exit(1);
}
+ for (i = 0; i < LEN(cos_thetas); i++) {
+ cos_thetas[i] = xlo + (xhi-xlo)*i/(LEN(cos_thetas)-1);
+ }
+
F.function = &gsl_pmt_response;
- for (i = 0; i < NUM_ANGLES; i++) {
- params[0] = thetas[i]*M_PI/180.0;
+ for (i = 0; i < LEN(cos_thetas); i++) {
+ params[0] = cos_thetas[i];
status = gsl_integration_cquad(&F, 200, 800, 0, 1e-2, w, &result, &error, &nevals);
@@ -423,8 +435,8 @@ int pmt_response_init(dict *db)
F.function = &gsl_pmt_reflectivity;
- for (i = 0; i < NUM_ANGLES; i++) {
- params[0] = thetas[i]*M_PI/180.0;
+ for (i = 0; i < LEN(cos_thetas); i++) {
+ params[0] = cos_thetas[i];
status = gsl_integration_cquad(&F, 200, 800, 0, 1e-2, w, &result, &error, &nevals);
diff --git a/src/pmt_response.h b/src/pmt_response.h
index fd23ab2..c87ce0d 100644
--- a/src/pmt_response.h
+++ b/src/pmt_response.h
@@ -19,6 +19,7 @@
#include "dict.h"
+/* Global error string set when pmt_response_init() returns -1. */
extern char pmtr_err[256];
#define NUM_ANGLES 90
@@ -31,8 +32,8 @@ extern char pmtr_err[256];
#define KPMTR_RESP 4
#define KPMTR_REFLEC 4504
-double get_weighted_pmt_reflectivity(double theta);
-double get_weighted_pmt_response(double theta);
+double get_weighted_pmt_reflectivity(double cos_theta);
+double get_weighted_pmt_response(double cos_theta);
double get_pmt_reflectivity(double wavelength, double theta);
double get_pmt_response(double wavelength, double theta);
int pmt_response_init(dict *db);