aboutsummaryrefslogtreecommitdiff
path: root/src/pmt_response.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmt_response.c')
-rw-r--r--src/pmt_response.c108
1 files changed, 60 insertions, 48 deletions
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);