diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dc.c | 213 |
1 files changed, 120 insertions, 93 deletions
@@ -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; |