aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dc.c213
1 files changed, 120 insertions, 93 deletions
diff --git a/src/dc.c b/src/dc.c
index 5cb26b3..ae327d8 100644
--- a/src/dc.c
+++ b/src/dc.c
@@ -784,26 +784,104 @@ int is_slot_early(event *ev, int flasher_pmt_id)
return t_slot_median < t_nearby_median - 10.0;
}
-/* Returns 1 if the event is a flasher and 0 if it isn't. The definition of
- * a flasher event comes from
+static int is_flasher_channel(event *ev, int flasher_pmt_id, double *t_pc, int nhit)
+{
+ int i;
+ size_t crate, card, channel, id;
+ double flasher_pos[3];
+ double pmt_dir[3];
+ double distance;
+ int nhit_late, nhit_far;
+ double t;
+ int flasher_pc;
+
+ flasher_pc = (flasher_pmt_id/512)*64 + ((flasher_pmt_id % 512)/32)*4 + (flasher_pmt_id % 32)/8;
+
+ COPY(flasher_pos,pmts[flasher_pmt_id].pos);
+
+ /* Calculate the median time for PMT hits in the paddle card.
+ *
+ * Note: Initially this algorithm just used the time of the highest
+ * charge channel. However, in looking at events in run 10,000 I
+ * noticed two flashers which were not flagged by the cut because the
+ * flasher channel had a normal time. Therefore, we now use the median
+ * time for all channels in the paddle card. */
+ gsl_sort(t_pc,1,nhit);
+ t = gsl_stats_median_from_sorted_data(t_pc,1,nhit);
+
+ /* Check that 70% of the regular PMTs in the event which are not in the
+ * flasher slot fired more than 50 ns after the high charge channel and are
+ * more than 12 meters away from the high charge channel. */
+ nhit = 0;
+ /* Number of PMTs which fired 50 ns after the high charge channel. */
+ nhit_late = 0;
+ /* Number of PMTs which are 12 meters or more away from the high charge
+ * channel. */
+ nhit_far = 0;
+ for (i = 0; i < MAX_PMTS; i++) {
+ /* Skip PMTs which weren't hit. */
+ if (!ev->pmt_hits[i].hit) continue;
+
+ /* Only count regular PMTs without any flags. */
+ if (ev->pmt_hits[i].flags || pmts[i].pmt_type != PMT_NORMAL) continue;
+
+ crate = i/512;
+ card = (i % 512)/32;
+ channel = i % 32;
+
+ id = crate*64 + card*4 + channel/8;
+
+ /* Skip PMTs in the same card as the high charge channel. */
+ if (id/4 == flasher_pc/4) continue;
+
+ /* Require good calibrations. */
+ if (ev->pmt_hits[i].ept < -100) continue;
+
+ nhit += 1;
+
+ /* Calculate the distance from the current channel to the high charge
+ * channel. */
+ SUB(pmt_dir,pmts[i].pos,flasher_pos);
+ distance = NORM(pmt_dir);
+
+ /* If this channel is 12 meters or more away, increment nhit_far. */
+ if (distance >= 1200.0) nhit_far += 1;
+
+ /* If this channel fired more than 50 ns after the high charge channel,
+ * increment nhit_late. */
+ if (ev->pmt_hits[i].ept > t + 50.0) nhit_late += 1;
+ }
+
+ /* If at least 70% of the regular PMTs fired within 50 ns and were at
+ * least 12 meters away from the high charge channel, then it's a
+ * flasher! */
+ if (nhit_late >= 7*nhit/10 && nhit_far >= 7*nhit/10) return 1;
+
+ return 0;
+}
+
+/* Returns 1 if the event is a flasher and 0 if it isn't. This cut is based
+ * loosely on the definition of a flasher event from
* http://detector.sno.laurentian.ca/~detector/private/snoop/doc/eventIDs.html,
* with a few small changes.
*
* Here we define a flasher as an event with the following criteria:
*
- * - 31 <= nhit <= 1000
+ * - nhit >= 31
*
- * - Look for the paddle card with the most PMTs hit. This paddle card should
- * have 4 or more hits.
+ * - Loop over all paddle cards with at least 4 hits.
*
- * - If such a paddle card exists, look for one channel in the card that hosts
- * this paddle card which has either QHS or QHL values (uncalib'd) > 4000,
- * whereas the QHS and QHL values for the other channels in the card are <
- * 800. Note that QHS and QHL values below 300 are sent above 4096.
+ * - Look for one channel in this paddle card which has an uncalibrated QHS or
+ * QHL value 1000 counts above the next highest charge, or a QLX value more
+ * than 80 counts above the next highest QLX charge. Note that QHS, QHL, and
+ * QLX values below 300 are sent to 4095. If such a channel is found skip the
+ * next step.
*
- * Note: This is changed from the original definition. We look for all the
- * other channels to have a QHL and QHS below 800 instead of 700 since the
- * latter was failing to tag many obvious flashers.
+ * - If no such high charge channel exists and all the QLX values in the PC are
+ * less than 800, check to see if either there are more hits within the slot
+ * than within 4 meters or the median ECA calibrated hit time within the slot
+ * is earlier by at least 10 ns than the other PMTs within 4 meters. If
+ * neither of these is true, go to the next paddle card.
*
* - At least 70% of the (regular) pmts in the event which are not in the
* flasher slot should have fired more than 50 ns after the high charge
@@ -830,15 +908,10 @@ int is_flasher(event *ev)
size_t crate, card, channel, id;
int i, j;
size_t index[1280], index_qhs[8], index_qhl[8], index_qlx[8];
- double t;
- int flasher_pc;
- double flasher_pos[3];
- double pmt_dir[3];
- double distance;
- int nhit, nhit_late, nhit_far;
+ int nhit;
- /* Flasher event must have an nhit between 31 and 1000. */
- if (ev->nhit < 31 || ev->nhit > 1000) return 0;
+ /* Flasher event must have an nhit greater than 1000. */
+ if (ev->nhit < 31) return 0;
for (i = 0; i < MAX_PMTS; i++) {
if (!ev->pmt_hits[i].hit || pmts[i].pmt_type != PMT_NORMAL) continue;
@@ -855,15 +928,19 @@ int is_flasher(event *ev)
argsort(hits_pc, LEN(hits_pc), index);
/* The paddle card with the most hits must have >= 4 hits. */
- if (hits_pc[index[1279]] < 4) return 0;
+ if (hits_pc[index[LEN(hits_pc)-1]] < 4) return 0;
/* Loop over the most hit paddle cards in order from most hits to least
* hits. We do this because it's possible that more than one paddle card
* has the same number of channels hit, and so we need to test all of them. */
- for (j = 1279; j >= 0; j--) {
+ for (j = LEN(hits_pc)-1; j >= 0; j--) {
id = index[j];
- /* Make sure this paddle card has at least 4 hits. */
+ /* Make sure this paddle card has at least 4 hits.
+ *
+ * Note: Since we loop over the PCs in order from most to least hits,
+ * we are guaranteed that once we reach a PC with less than 4 hits,
+ * there are no more PCs with 4 or more hits. */
if (hits_pc[id] < 4) return 0;
nhit = 0;
@@ -937,90 +1014,40 @@ int is_flasher(event *ev)
argsort(qhl_pc, nhit, index_qhl);
argsort(qlx_pc, nhit, index_qlx);
- flasher_pc = index[j];
crate = index[j]/64;
card = (index[j] % 64)/4;
- channel = channel_pc[index_qhs[nhit-1]];
- /* Check if this paddle card has QHS, QHL, or QLX values > 4000, and the QHS,
- * QHL, and QLX values for the other channels in the card are less than 700.
+ /* Check if this paddle card has a QHS or QHL value which is 1000
+ * counts above the next highest QHS or QHL value, or a QLX value which
+ * is 80 counts above the next highest QLX value. These values come
+ * from the QvT cut in SNOMAN.
*
* Alternatively, if there isn't an obvious charge outlier, it's still
* possible that the flasher PMT hit is missing from the event or that
* the QHS/QHL/QLX values were just outside of the threshold. In this
* case, we look to see if the TAC for the proposed slot is early with
* respect to neighboring PMTs. */
- if ((qhs_pc[index_qhs[nhit-1]] < 4000 || qhs_pc[index_qhs[nhit-2]] > 800) &&
- (qhl_pc[index_qhl[nhit-1]] < 4000 || qhl_pc[index_qhl[nhit-2]] > 800) &&
- (qlx_pc[index_qlx[nhit-1]] < 1000 || qlx_pc[index_qlx[nhit-2]] > 800) &&
- !is_slot_early(ev, crate*512 + card*32 + channel)) continue;
-
- if (qhs_pc[index_qhs[nhit-1]] > 4000) {
+ if (qhs_pc[index_qhs[nhit-1]] > qhs_pc[index_qhs[nhit-2]] + 1000) {
channel = channel_pc[index_qhs[nhit-1]];
- } else if (qhl_pc[index_qhl[nhit-1]] > 4000) {
+ } else if (qhl_pc[index_qhl[nhit-1]] > qhl_pc[index_qhl[nhit-2]] + 1000) {
channel = channel_pc[index_qhl[nhit-1]];
- } else if (qlx_pc[index_qlx[nhit-1]] > 1000) {
+ } else if (qlx_pc[index_qlx[nhit-1]] > qlx_pc[index_qlx[nhit-2]] + 80) {
channel = channel_pc[index_qlx[nhit-1]];
- }
- COPY(flasher_pos,pmts[crate*512 + card*32 + channel].pos);
-
- /* Calculate the median time for PMT hits in the paddle card.
- *
- * Note: Initially this algorithm just used the time of the highest
- * charge channel. However, in looking at events in run 10,000 I
- * noticed two flashers which were not flagged by the cut because the
- * flasher channel had a normal time. Therefore, we now use the median
- * time for all channels in the paddle card. */
- gsl_sort(t_pc,1,nhit);
- t = gsl_stats_median_from_sorted_data(t_pc,1,nhit);
-
- /* Check that 70% of the regular PMTs in the event which are not in the
- * flasher slot fired more than 50 ns after the high charge channel and are
- * more than 12 meters away from the high charge channel. */
- nhit = 0;
- /* Number of PMTs which fired 50 ns after the high charge channel. */
- nhit_late = 0;
- /* Number of PMTs which are 12 meters or more away from the high charge
- * channel. */
- nhit_far = 0;
- for (i = 0; i < MAX_PMTS; i++) {
- /* Skip PMTs which weren't hit. */
- if (!ev->pmt_hits[i].hit) continue;
-
- /* Only count regular PMTs without any flags. */
- if (ev->pmt_hits[i].flags || pmts[i].pmt_type != PMT_NORMAL) continue;
-
- crate = i/512;
- card = (i % 512)/32;
- channel = i % 32;
-
- id = crate*64 + card*4 + channel/8;
-
- /* Skip PMTs in the same card as the high charge channel. */
- if (id/4 == flasher_pc/4) continue;
-
- /* Require good calibrations. */
- if (ev->pmt_hits[i].ept < -100) continue;
-
- nhit += 1;
-
- /* Calculate the distance from the current channel to the high charge
- * channel. */
- SUB(pmt_dir,pmts[i].pos,flasher_pos);
- distance = NORM(pmt_dir);
-
- /* If this channel is 12 meters or more away, increment nhit_far. */
- if (distance >= 1200.0) nhit_far += 1;
-
- /* If this channel fired more than 50 ns after the high charge channel,
- * increment nhit_late. */
- if (ev->pmt_hits[i].ept > t + 50.0) nhit_late += 1;
+ } else if (qlx_pc[index_qlx[nhit-1]] < 800) {
+ /* Check to see if the missing channel in the PC is the flasher. */
+ for (i = 0; i < 8; i++) {
+ channel = (id % 4)*8 + i;
+ if (!ev->pmt_hits[crate*512 + card*32 + channel].hit && \
+ is_slot_early(ev, crate*512 + card*32 + channel) && \
+ is_flasher_channel(ev,crate*512 + card*32 + channel,t_pc,nhit)) return 1;
+ }
+ continue;
+ } else {
+ /* No single high charge channel. */
+ continue;
}
- /* If at least 70% of the regular PMTs fired within 50 ns and were at
- * least 12 meters away from the high charge channel, then it's a
- * flasher! */
- if (nhit_late >= 7*nhit/10 && nhit_far >= 7*nhit/10) return 1;
+ if (is_flasher_channel(ev,crate*512 + card*32 + channel,t_pc,nhit)) return 1;
}
return 0;