The Neutron Detector (sometimes called BigHand or NeutronArm) contains two thin veto planes followed by the neutron-detector planes: seven planes of converter material/scintillator. Each veto plane is composed of independent left-and-right scintillators read out on one end, with a total of 48 * 2 = 96 detectors per plane. The active region of the neutron detectors are 5 or 10cm thick scintillator bars read out on both sides, providing a horizontal position as well as precise timing information. The segmentation of the neutron detector planes permits a coarse determination of the neutron's vertical position.
The signals from each PMT were split and recorded by ADCs and TDCs. The ADCs integrated the pulses over a ~150ns time window. The time of the pulses were recorded in multi-hit TDCs: the vetos to Lecroy 1877 TDCs run in common-stop mode at 0.5ns/channel, and the neutron-detectors to F1 TDCs set to 0.1183ns/channel.
The values recorded by the 1877 TDCs had a definite and fixed offset to the time of the Common Stop pulse provided by the Trigger Supervisor and its 'Level One Accept', or L1A, signal. Due to the internal operations of the F1 TDC, there was a looser relation between the controlling pulse sent to the TDC and the L1A time, so a copy of the L1A was also put into a channel in the TDC; this is what is referred to as the "Reference Time". In the analysis software, the "Reference Time" is subtracted off such that the "time" variables are with respect to the L1A.
The BigBite detectors, most importantly the scintillator for purposes of reconstructing the neutron time-of-flight (ToF), used a DIFFERENT common signal for the TDC and ADC digitization, which we will call the BBtrig. To relate the Neutron Detector and BigBite times, a Lecroy 1875 TDC was used to record the difference (sometimes called the "raw coincidence time"), where the TDC had 50ps/channel such that:
L1A - BBtrig = 0.05*D.ctimeL1A[0] (ns)
The THaNeutronApp is the overall neutron detector apparatus, whose location in the hall is specified in the run database (db_run.dat) via :
database variable | Description |
na.distance | distance of plumb-bob from target center [meters] |
na.theta | angle of plumb-bob relative to beamline as measured at target center [degrees] |
na.theta_norm | in-plane angle of the normal of the ND projected through the ND relative to the beam line [degrees] |
na.phi_norm | out-of-plane angle of the normal of the ND projected through the ND (hopefully 0) [degrees] |
na.roll | rotation of the ND about the normal defined by na.theta_norm and na.phi_norm (hopefully 0) [degrees] |
The THaNeutronApp contains the THaNeutronDetector, the major class that drives the analysis of the neutron detector, which contains the neutron detector planes (in THaScintPlane's) and veto detectors (in THaVetoPlane, which inherits from THaScintPlane).
The geometry, channel map, calibration constants, etc. of each plane is specified in the database (db_na.nd.dat file for now), which is describe elsewhere. Each THaScintPlane contains an array of its bars as THaScintBar (or THaVetoBar) objects. The bars are readout by PMT's (THaScintPMT); in the case of the neutron detector planes both sides of a single bar are readout and can be combined, while for the veto bars each left- and right-paddle is read out independently.
The analysis of the neutron detector proceeds in the following steps:
- Decoding
- Plane-by-plane reconstruction
- Cluster-building
- Cluster-to-Veto matching
- Track construction for easier comparison to BB calculations
The first step is to take the data, generally from a CODA file, and read it into the Neutron-Detector class objects. The ADC and TDC values are stored in the following global variables, which can be written out to the ROOT-file. Since each channel is localized to a specific plane, each variable listed below is to be prefixed by the corresponding detector plane (eg: use "na.nd.n3.lthit_tdc" to access the "lthit_tdc" array for the n3 plane).
Since the TDCs are mult-hit, and to permit for tight-packing of the data in the tree, the general storage of the ADC and TDC readout is as a set of parallel arrays. These sets of parallel arrays have an array for the bar number, the raw readout value, and then the values after some corrections have been applied.
global variable | Description |
nrefhit | Number of stored reference hits (if needed) to relate the raw TDC readout of real detector channels to the L1A |
ref_bar | Reference index of the stored hit |
ref_tdc | Raw TDC value of the hit |
ref_time | Time in ns of the reference hit |
nlthit | Number of left-side TDC hits for this plane. |
The following arrays are parallel, and of dimension nlthit | |
lthit_bar | Bar number for the left-side TDC hit |
lthit_tdc | Raw TDC value for the hit (channels) |
lthit_time | Time for the time corrected for offsets (ns) |
nrthit | Number of right-side TDC hits for this plane. |
rthit_bar, rthit_tdc, rthit_time | Parallel arrays for the right-side TDC hits of dimension nrthit, following the same scheme as the lthit_* variables. |
nlahit | Number of left-side ADC hits for this plane. |
The following arrays are parallel, and of dimension nlahit | |
lahit_bar | Bar number for the left-side ADC hit |
lahit_adc | Raw ADC value for the hit (channels) |
lahit_ap | Pedestal-subtracted ADC value (channels) |
lahit_ac | Pedestal-subtracted and gain-corrected recorded energy of the hit (MeV) |
nrahit | Number of right-side ADC hits for this plane. |
rahit_bar, rahit_adc, rahit_ap, rahit_ac | Parallel arrays for the right-side ADC hits of dimension nrahit, following the same scheme as the lahit_* variables. |
In addition, there are "flat", non-packed arrays indexed on the bar number that store a subset (just the first hit) of the data present in the full arrays listed above. These are also prefixed by the detector and plane number, eg. "na.nd.n3.LT[5]" to get at the time of the first hit of bar 5 of plane N3. These are NOT used in the full analysis, and are depreciated.
global variable | Description (indexed by bar number) |
LT | Corrected time for left-PMT |
LTcounter | Number of hits in this left-PMT |
LA | Raw ADC readout of left-PMT |
LApedc | Pedestal-corrected ADC readout of left-PMTs |
LE | Corrected amplitude of left-PMT |
RT | Corrected time for right-PMT |
RTcounter | Number of hits in this right-PMT |
RA | Raw ADC readout of right-PMT |
RApedc | Pedestal-corrected ADC readout of right-PMTs |
RE | Corrected amplitude of right-PMT |
At the "CoarseProcess"-ing stage, the hits in the correlations between the ADCs and TDCs for a given bar are constructed in the THaScintPlane and THaVetoPlane classes; this is not performed at the Decode stage so the multi-hit capabilities of the TDCs can be used.
First the TDC and ADC hits are sorted by bar number and value, with the earlier and highest amplitudes listed first. To speed up the search for matching hits, temporary index arrays are used to hold the location of the hits in the lthit_* and similar arrays. The corrected times from the TDC, the same data as in the lthit_time and rthit_time variables, are selected to use only those entries with a time within a 300ns window as given in the database.
The "hits" on each bar are then constructed: for the neutron detector planes both PMTs on a bar are required to have ADC and TDC information while for the veto planes only the single attached PMT must have the complete information. The left and right times for each bar are corrected for timewalk effects using the ADC readout of the same bar:
ltime = lthit_time - C_l * pow(lahit_ap, P_l)
rtime = rthit_time - C_r * pow(rahit_ap, P_r)
where (C_l, C_r, P_l, P_r) are calibration constants from the database, with P_l and P_r between -1 and -.5.
With the corrected times the time of the hit on the bar, its the position along the bar, and energy deposition can be calculated and the complete hit is constructed. These can be accessed as the global array variables owned by the detector plane (eg: na.nd.n6.hit_tof), of dimension nhit. The hits are sorted in ascending order by bar number. Below Cn is the effective signal-propogation speed, including internal reflections, in the bar and is between 0.14 to 0.15 m/ns.
global variable | Description |
nhit | Number of hits in the plane |
hit_bar | bar number in the plane for this hit |
hit_xpos | x (vertical) position of the bar in the ND coordinate system (m) |
hit_tof | = 0.5*(rtime + ltime) : best time of the hit relative to the L1A (ns) |
hit_tdiff | = 0.5*(rtime - ltime) |
hit_ypos | = 0.5*(rtime - ltime)*Cn + bar_y : y (horizontal) position of the hit in the ND coordinate system (m) |
hit_Edep | = sqrt(lahit_ac*rahit_ac) : Total energy deposition in the bar of the hit (MeV) |
For the Veto detectors the same steps are followed, except that only one side and PMT is used, such that a mean-time is not formed. The hit_tof and hit_Edep are assigned to ltime or rtime and the lahit_ac or rahit_ac, respectively, and hit_ypos is set to the center of the (left or right) paddle.
The individual hits in seven neutron detector planes must be matched together to construct a small number of "clusters" per event. This is performed at the "FineProcess" level by the THaNeutronDetector::CreateClusters method. First, all the "hits" in the neutron detector planes constructed in the previous step are sorted through, and those which pass the loose cut
|hit_ypos - bar_y| < THaNeutronDetector
fHitLRMatch * bar_length ::are put into an array of good "single hits". The single hits are then iterated over, and those which are either neighbors vertically (ie in adjacent bars in the same plane) or in neighboring planes and at roughly the same vertical position (x), and have times matching to within a short window (given by THaNeutronDetector::fClustTimeWindow , presently set to 10 ns) are joined together into a cluster. The cluster continues to grow to collect all hits with the given criteria. The next unused "single hit" is then used as the beginning of the next cluster, and so on until all the "single hits" are members of a cluster, even if that cluster contains only one hit bar. The geometric correlation between bars is generated at initialization and stored in the THaBarArray class. Formally, the criteria for a candidate hit "C" being added to a cluster by its proximity to the already-in-the-cluster hit "I" are the loose cuts:
|hit_time_C - hit_time_I| < fClustTimeWindow, AND
|hit_xpos_C - hit_xpos_I| < 1.5*Max(bar_xsize_C, bar_xsize_I) AND
[ |hit_plane_C-hit_plane_I|<=1 OR MinDist(bar_zpos_C,bar_zpos_I) < 1.5*(bar_zsize_C+bar_zsize_I) ]
[ |hit_plane_C-hit_plane_I|<=1 OR MinDist(bar_zpos_C,bar_zpos_I) < 1.5*(bar_zsize_C+bar_zsize_I) ]
where MinDist is the minimum distance between the edges of the scintillator bar in the z-direction, and everything else has its obvious interpretation.
For each cluster, the specific time (tof), position (xpos,ypos,zpos), plane and bar number are of the hit closest to the front of the neutron detector. The energy-weighted position and moments of the hits are accumulated as:
clus_xwgt = 1/clus_Edep * Sum(hit_Edep * hit_xpos)
clus_dx2 = 1/clus_Edep * Sum( hit_Edep * (hit_xpos - clus_xwgt)**2 )
(and likewise for clus_ywgt and clus_zwgt, and clus_dy2 and clus_dz2).
The clusters are sorted in order of descending deposited energy.
To look for a matching hit in the veto counters, a ray from the front of the cluster towards the target center is used to match to the veto bars and get the matching bar, VetoInt. The index and veto bar hit in each the veto plane with the best-matching time to the cluster within +/-1 bar of VetoInt is stored with the cluster; if no match is found the veto bar is listed as VetoInt and the index is set to -1.
The variables are owned by the Neutron Detector and so have the prefix "na.nd.". The global variables available for each cluster are:
global variable | Description |
nclusters | Number of clusters for the event |
The next variables are parallel arrays of dimension nclusters, ordered inversely by energy (highest Edep is first) | |
clus_nbars | number of bars contributing to this cluster |
clus_bar | primary bar (closest to target) of the cluster |
clus_xpos | primary hit X-position (m) |
clus_ypos | primary hit Y-position (m) |
clus_zpos | primary hit Z-position (m) |
clus_tof | primary hit "time-of-flight", time relative to L1A (ns) |
clus_Edep | total energy deposited in cluster (MeV) |
clus_xwgt | cluster's Energy-weighted center in X (m) |
clus_ywgt | cluster's Energy-weighted center in Y (m) |
clus_zwgt | cluster's Energy-weighted center in Z (m) |
clus_dx2 | cluster's E-weighted dx**2 (m**2) |
clus_dy2 | cluster's E-weighted dy**2 (m**2) |
clus_dz2 | cluster's E-weighted dz**2 (m**2) |
clus_v1bar | veto bar in plane V1 matching to this cluster |
clus_v1hit | index of hit in plane V1 matching to this cluster; -1 if no hit found |
clus_v2bar | veto bar in plane V2 matching to this cluster |
clus_v2hit | index of hit in plane V2 matching to this cluster; -1 if no hit found |
The "tracks" are then generated from the clusters via THaNeutronDetector::BuildTracks, where rays from the target center to the primary hit are generated and put into the Hall Coordinate System (HCS). The pathlength from the target to the hit is calculated, as well as the direction of the momentum 3-vector, however the beta and magnitude of the momentum vector are arbitrary at this point since the time-of-flight is not fully calculated since the BigBite arm is not used. The location of the tracks' intersections at Z=0 of the neutron detector are calculated and reported, as well as their equivalent target "theta" and "phi" variables. However, it is suggested to use the "tr.px, tr.py, tr.pz" variables, divided by "tr.p" as direction cosines of the track.
The tracks arrays are completely parallel to the "cluster" arrays listed above. The final "tracks" are owned by the Neutron Apparatus, and so have the prefix "na.":
global variable | Description |
tr.n | Number of "tracks" |
tr.x | Front-face x coordinate (m) |
tr.y | Front-face y coordinate (m) |
tr.th | Tangent of track theta (out-of-plane) angle |
tr.ph | Traget of track phi (in-plane) angle |
tr.pathl | Distance from the target to the primary hit of the cluster |
tr.time | Time of the primary hit of the cluster relative to the L1A. |
tr.beta | Improper calculation of the track's beta given time and pathl, since time is relative to L1A and not the true time-of-flight. |
tr.p | Improper calculation of the track momentum (for now) given beta and assuming a nucleon (GeV/c) |
tr.px | X-component of the track momentum (use with tr.p for a direction cosine) in the HCS (GeV/c) |
tr.py | like tr.px but the HCS Y-component (GeV/c) |
tr.pz | like tr.px but the HCS Z-component (GeV/c) |
tr.vx | Target vertex x (m) = 0 |
tr.vy | Target vertex y (m) = 0 |
tr.vz | Target vertex z (m) = 0 |
To get the proper "time-of-flight" of the candidate nucleon track, the time must be calculated relative to the electron in BigBite. As an example, this can be calculated (to within and offset and ignoring the pathlength corrections for the electron) as:
na.tr.time - B.s.time[B.s.trpad[0]] + 0.05*D.ctimeL1A[0]
where
"B.s.time[B.s.trpad[0]]"
is the time of the hit in the BigBite's scintillators relative to the BBtrig accociated with the electron.