_TrueAHDCHits;
private boolean sim = false;
- private IndexedTable rawHitCutsTable;
- private IndexedTable timeOffsetsTable;
- private IndexedTable timeToDistanceWireTable;
- private IndexedTable timeOverThresholdTable;
- private IndexedTable adcGainsTable;
-
- public HitReader(DataEvent event, AlertDCDetector detector, boolean simulation,
- IndexedTable rawHitCuts,
- IndexedTable timeOffsets,
- IndexedTable timeToDistanceWire,
- IndexedTable timeOverThreshold,
- IndexedTable adcGains) {
+ /**
+ * Constructs a HitReader and eagerly populates the hit lists from the given event.
+ * After construction, retrieve the results via {@link #get_AHDCHits()} and
+ * (in simulation) {@link #get_TrueAHDCHits()}.
+ *
+ * @param event current event containing the {@code AHDC::adc} bank (and {@code MC::True} in sim)
+ * @param detector AHDC geometry used to resolve wire positions on each hit
+ * @param simulation {@code true} for Monte Carlo events; disables data-only cuts and corrections
+ * @param rawHitCutsTable per-wire acceptance cuts (time, ToT, ADC, pedestal min/max)
+ * @param timeOffsetsTable per-wire {@code t0} offsets applied to the leading-edge time
+ * @param timeToDistanceWireTable per-wire T2D calibration coefficients used to convert time to DOCA
+ * @param timeOverThresholdTable per-wire ToT correction factors (applied in data mode only)
+ * @param adcGainsTable per-wire ADC gain corrections (applied in data mode only)
+ */
+ public HitReader(DataEvent event, AlertDCDetector detector, boolean simulation, IndexedTable rawHitCutsTable, IndexedTable timeOffsetsTable,
+ IndexedTable timeToDistanceWireTable, IndexedTable timeOverThresholdTable, IndexedTable adcGainsTable) {
sim = simulation;
- fetch_AHDCHits(event, detector, rawHitCuts, timeOffsets, timeToDistanceWire, timeOverThreshold, adcGains);
+ fetch_AHDCHits(event, detector, rawHitCutsTable, timeOffsetsTable, timeToDistanceWireTable, timeOverThresholdTable, adcGainsTable);
if (simulation) fetch_TrueAHDCHits(event);
}
- public double T2Dfunction(int sector, int layer, int wire, double time){
+ /**
+ * Converts a calibrated drift time into a distance-of-closest-approach (DOCA) for a
+ * given wire, using the piecewise T2D calibration stored in {@code timeToDistanceWireTable}.
+ *
+ * The result is a blend of three 1st-order polynomials {@code p1, p2, p3} stitched
+ * together by two logistic transition functions {@code t1, t2}:
+ * {@code doca = p1·(1-t1) + t1·p2·(1-t2) + t2·p3}. The coefficients are looked up
+ * once per call via a hashed index on (sector, layer, wire).
+ *
+ *
Expected column order of the calibration row:
+ * p1_int(0), p1_slope(1), p2_int(2), p2_slope(3), p3_int(4), p3_slope(5),
+ * t1_x0(6), t1_width(7), t2_x0(8), t2_width(9), z0(10), z1(11), z2(12),
+ * extra1(13), extra2(14), chi2ndf(15).
+ *
+ * @param sector AHDC sector index
+ * @param layer packed layer index ({@code superlayer*10 + layer})
+ * @param wire wire (component) id within the layer
+ * @param time calibrated drift time in ns
+ * @param timeToDistanceWireTable per-wire T2D calibration table
+ * @return the DOCA in mm
+ */
+ private double T2Dfunction(int sector, int layer, int wire, double time, IndexedTable timeToDistanceWireTable){
long hash = timeToDistanceWireTable.getList().getIndexGenerator().hashCode(sector, layer, wire);
List t2d = timeToDistanceWireTable.getDoublesByHash(hash);
- // T2D function consists of three 1st order polynomials (p1, p2, p3) and two transition functions (t1, t2).
- // Column order: p1_int(0), p1_slope(1), p2_int(2), p2_slope(3), p3_int(4), p3_slope(5),
- // t1_x0(6), t1_width(7), t2_x0(8), t2_width(9), z0(10), z1(11), z2(12), extra1(13), extra2(14), chi2ndf(15)
-
double p1 = (t2d.get(0) + t2d.get(1)*time);
double p2 = (t2d.get(2) + t2d.get(3)*time);
double p3 = (t2d.get(4) + t2d.get(5)*time);
@@ -50,16 +78,31 @@ public double T2Dfunction(int sector, int layer, int wire, double time){
return (p1)*(1.0 - t1) + (t1)*(p2)*(1.0 - t2) + (t2)*(p3);
}
- public final void fetch_AHDCHits(DataEvent event, AlertDCDetector detector,
- IndexedTable rawHitCuts, IndexedTable timeOffsets,
- IndexedTable timeToDistanceWire, IndexedTable totCorrTable,
- IndexedTable adcGains) {
- this.rawHitCutsTable = rawHitCuts;
- this.timeOffsetsTable = timeOffsets;
- this.timeToDistanceWireTable = timeToDistanceWire;
- this.timeOverThresholdTable = totCorrTable;
- this.adcGainsTable = adcGains;
-
+ /**
+ * Reads the {@code AHDC::adc} bank, calibrates each raw row, and builds the list of
+ * reconstructed {@link Hit}s. For each row the method:
+ *
+ * - applies the per-wire time offset {@code t0} (subtracting event start time in data mode),
+ * - in data mode, corrects time-over-threshold and enforces per-wire acceptance cuts
+ * (time, ToT, ADC, pedestal, and {@code wfType <= 2}) — hits failing the cuts are dropped,
+ * - computes the DOCA from the calibrated time via {@link #T2Dfunction} (DOCA forced to 0
+ * when {@code time < 0}),
+ * - in data mode, applies the per-wire ADC gain correction,
+ * - instantiates a {@link Hit}, resolves its wire position via the geometry, and stores the
+ * calibrated ADC and ToT on it.
+ *
+ * The resulting list is stored via {@link #set_AHDCHits(ArrayList)} (empty if the bank is absent).
+ *
+ * @param event current event
+ * @param detector AHDC geometry used to set each hit's wire position
+ * @param rawHitCutsTable per-wire acceptance cuts (data mode only)
+ * @param timeOffsetsTable per-wire {@code t0}
+ * @param timeToDistanceWireTable per-wire T2D coefficients
+ * @param timeOverThresholdTable per-wire ToT correction factors (data mode only)
+ * @param adcGainsTable per-wire ADC gain corrections (data mode only)
+ */
+ private void fetch_AHDCHits(DataEvent event, AlertDCDetector detector, IndexedTable rawHitCutsTable, IndexedTable timeOffsetsTable,
+ IndexedTable timeToDistanceWireTable, IndexedTable timeOverThresholdTable, IndexedTable adcGainsTable) {
ArrayList hits = new ArrayList<>();
if (!event.hasBank("AHDC::adc")) {
@@ -92,16 +135,6 @@ public final void fetch_AHDCHits(DataEvent event, AlertDCDetector detector,
double adcOffset = bankDGTZ.getFloat("ped", i);
int wfType = bankDGTZ.getShort("wfType", i);
- // Raw hit cuts
- double t_min = rawHitCutsTable.getDoubleValue("t_min", sector, number, wire);
- double t_max = rawHitCutsTable.getDoubleValue("t_max", sector, number, wire);
- double tot_min = rawHitCutsTable.getDoubleValue("tot_min", sector, number, wire);
- double tot_max = rawHitCutsTable.getDoubleValue("tot_max", sector, number, wire);
- double adc_min = rawHitCutsTable.getDoubleValue("adc_min", sector, number, wire);
- double adc_max = rawHitCutsTable.getDoubleValue("adc_max", sector, number, wire);
- double ped_min = rawHitCutsTable.getDoubleValue("ped_min", sector, number, wire);
- double ped_max = rawHitCutsTable.getDoubleValue("ped_max", sector, number, wire);
-
// Time calibration
double t0 = timeOffsetsTable.getDoubleValue("t0", sector, number, wire);
double time = leadingEdgeTime - t0 - startTime;
@@ -111,21 +144,30 @@ public final void fetch_AHDCHits(DataEvent event, AlertDCDetector detector,
if (!sim) {
double totCorr = timeOverThresholdTable.getDoubleValue("totCorr", sector, number, wire);
if (totCorr != 0.0) totUsed = timeOverThreshold * totCorr;
- }
-
- // Hit selection (cuts)
- boolean passCuts =
- (wfType <= 2) &&
- (adcRaw >= adc_min) && (adcRaw <= adc_max) &&
- (time >= t_min) && (time <= t_max) &&
- (timeOverThreshold >= tot_min) && (timeOverThreshold <= tot_max) &&
- (adcOffset >= ped_min) && (adcOffset <= ped_max);
- if (!passCuts && !sim) continue;
+ // Hit selection (cuts) — only applied on data, bypassed in sim
+ long hash = rawHitCutsTable.getList().getIndexGenerator().hashCode(sector, number, wire);
+ double t_min = rawHitCutsTable.getDoubleValueByHash("t_min", hash);
+ double t_max = rawHitCutsTable.getDoubleValueByHash("t_max", hash);
+ double tot_min = rawHitCutsTable.getDoubleValueByHash("tot_min", hash);
+ double tot_max = rawHitCutsTable.getDoubleValueByHash("tot_max", hash);
+ double adc_min = rawHitCutsTable.getDoubleValueByHash("adc_min", hash);
+ double adc_max = rawHitCutsTable.getDoubleValueByHash("adc_max", hash);
+ double ped_min = rawHitCutsTable.getDoubleValueByHash("ped_min", hash);
+ double ped_max = rawHitCutsTable.getDoubleValueByHash("ped_max", hash);
+
+ boolean passCuts =
+ (wfType <= 2) &&
+ (adcRaw >= adc_min) && (adcRaw <= adc_max) &&
+ (time >= t_min) && (time <= t_max) &&
+ (timeOverThreshold >= tot_min) && (timeOverThreshold <= tot_max) &&
+ (adcOffset >= ped_min) && (adcOffset <= ped_max);
+
+ if (!passCuts) continue;
+ }
// DOCA from calibrated time
- double doca = T2Dfunction(sector, number, wire, time);
- if (time < 0) doca = 0.0;
+ double doca = (time < 0) ? 0.0 : T2Dfunction(sector, number, wire, time, timeToDistanceWireTable);
// ADC gain calibration
double adcCal = adcRaw;
@@ -144,7 +186,15 @@ public final void fetch_AHDCHits(DataEvent event, AlertDCDetector detector,
this.set_AHDCHits(hits);
}
- public final void fetch_TrueAHDCHits(DataEvent event) {
+ /**
+ * Reads Monte-Carlo truth information from the {@code MC::True} bank into a list of
+ * {@link TrueHit}s (particle id and average hit position/energy). Called only when
+ * the reader is constructed with {@code simulation = true}. If the bank is absent,
+ * the resulting list is empty.
+ *
+ * @param event current event
+ */
+ private void fetch_TrueAHDCHits(DataEvent event) {
ArrayList truehits = new ArrayList<>();
@@ -164,18 +214,36 @@ public final void fetch_TrueAHDCHits(DataEvent event) {
this.set_TrueAHDCHits(truehits);
}
+ /**
+ * @return the calibrated AHDC hits produced from the current event; never {@code null}
+ * (empty if the {@code AHDC::adc} bank is missing)
+ */
public ArrayList get_AHDCHits() {
return _AHDCHits;
}
+ /**
+ * Replaces the internally stored list of AHDC hits. Primarily used by {@link #fetch_AHDCHits}.
+ *
+ * @param hits the list to store
+ */
public void set_AHDCHits(ArrayList hits) {
this._AHDCHits = hits;
}
+ /**
+ * @return the MC-truth hits for the current event (populated only in simulation mode;
+ * {@code null} for data events where {@code fetch_TrueAHDCHits} was not called)
+ */
public ArrayList get_TrueAHDCHits() {
return _TrueAHDCHits;
}
+ /**
+ * Replaces the internally stored list of MC-truth hits. Primarily used by {@link #fetch_TrueAHDCHits}.
+ *
+ * @param trueHits the list to store
+ */
public void set_TrueAHDCHits(ArrayList trueHits) {
this._TrueAHDCHits = trueHits;
}
diff --git a/reconstruction/alert/src/main/java/org/jlab/rec/atof/hit/ATOFHit.java b/reconstruction/alert/src/main/java/org/jlab/rec/atof/hit/ATOFHit.java
index c04a4ad4d4..a1812a237b 100644
--- a/reconstruction/alert/src/main/java/org/jlab/rec/atof/hit/ATOFHit.java
+++ b/reconstruction/alert/src/main/java/org/jlab/rec/atof/hit/ATOFHit.java
@@ -27,7 +27,7 @@ public class ATOFHit {
private boolean isInACluster;
private int associatedClusterIndex;
int idTDC;
- private IndexedTable atofTimeOffsets;
+ private IndexedTable atofTimeOffsetsTable;
public int getSector() {
@@ -197,10 +197,10 @@ public final int convertTdcToTime() {
if(this.startTime!= null) this.time -= this.startTime;
//Time offsets
- if (atofTimeOffsets == null) return 0;
+ if (atofTimeOffsetsTable == null) return 0;
int order0 = 0;
- double t0 = atofTimeOffsets.getDoubleValue("t0", this.sector, this.layer, this.component, order0);
- double tud = atofTimeOffsets.getDoubleValue("upstream_downstream", this.sector, this.layer, this.component, order0);
+ double t0 = atofTimeOffsetsTable.getDoubleValue("t0", this.sector, this.layer, this.component, order0);
+ double tud = atofTimeOffsetsTable.getDoubleValue("upstream_downstream", this.sector, this.layer, this.component, order0);
//The rest of the constants are not used for now
/*double twb = timeOffsets[2];
double xtra1 = timeOffsets[3];
@@ -400,7 +400,7 @@ public double getPhi() {
* spatial coordinates.
*/
public ATOFHit(int sector, int layer, int component, int order, int tdc, int tot, Float startTime, Detector atof,
- IndexedTable atofTimeOffsets) {
+ IndexedTable atofTimeOffsetsTable) {
this.sector = sector;
this.layer = layer;
this.component = component;
@@ -408,7 +408,7 @@ public ATOFHit(int sector, int layer, int component, int order, int tdc, int tot
this.tdc = tdc;
this.tot = tot;
this.startTime = startTime;
- this.atofTimeOffsets = atofTimeOffsets;
+ this.atofTimeOffsetsTable = atofTimeOffsetsTable;
this.isInACluster = false;
this.makeType();
diff --git a/reconstruction/alert/src/main/java/org/jlab/rec/atof/hit/BarHit.java b/reconstruction/alert/src/main/java/org/jlab/rec/atof/hit/BarHit.java
index b60ecbdc2a..4dd8a94b12 100644
--- a/reconstruction/alert/src/main/java/org/jlab/rec/atof/hit/BarHit.java
+++ b/reconstruction/alert/src/main/java/org/jlab/rec/atof/hit/BarHit.java
@@ -106,7 +106,7 @@ public final void computeEnergy() {
this.setEnergy(Edep_up + Edep_down);
}
- public BarHit(ATOFHit hit_down, ATOFHit hit_up, IndexedTable atofEffectiveVelocity) {
+ public BarHit(ATOFHit hit_down, ATOFHit hit_up, IndexedTable atofEffectiveVelocityTable) {
boolean hits_match = hit_down.matchBar(hit_up);
if (!hits_match) {
throw new UnsupportedOperationException("Hits do not match \n");
@@ -122,7 +122,7 @@ public BarHit(ATOFHit hit_down, ATOFHit hit_up, IndexedTable atofEffectiveVeloci
this.setY(hit_up.getY());
//CCDB readout for the effective velocity
- this.vEff = atofEffectiveVelocity.getDoubleValue("veff", this.getSector(), this.getLayer(), this.getComponent());
+ this.vEff = atofEffectiveVelocityTable.getDoubleValue("veff", this.getSector(), this.getLayer(), this.getComponent());
this.computeZ();
this.computeTime();
this.computeEnergy();
diff --git a/reconstruction/alert/src/main/java/org/jlab/rec/atof/hit/HitFinder.java b/reconstruction/alert/src/main/java/org/jlab/rec/atof/hit/HitFinder.java
index 3970f11139..918cefa864 100644
--- a/reconstruction/alert/src/main/java/org/jlab/rec/atof/hit/HitFinder.java
+++ b/reconstruction/alert/src/main/java/org/jlab/rec/atof/hit/HitFinder.java
@@ -65,8 +65,8 @@ public void setWedgeHits(ArrayList wedge_hits) {
* the sector/layer/component to x/y/z.
*/
public void findHits(DataEvent event, Detector atof, Float startTime,
- IndexedTable atofTimeOffsets,
- IndexedTable atofEffectiveVelocity) {
+ IndexedTable atofTimeOffsetsTable,
+ IndexedTable atofEffectiveVelocityTable) {
//For each event a list of bar hits and a list of wedge hits are filled
this.barHits.clear();
this.wedgeHits.clear();
@@ -92,7 +92,7 @@ public void findHits(DataEvent event, Detector atof, Float startTime,
int tot = bank.getInt("ToT", i);
//Building a Hit
- ATOFHit hit = new ATOFHit(sector, layer, component, order, tdc, tot, startTime, atof, atofTimeOffsets);
+ ATOFHit hit = new ATOFHit(sector, layer, component, order, tdc, tot, startTime, atof, atofTimeOffsetsTable);
if (hit.getEnergy() < 0.01) {
continue; //energy threshold
}
@@ -127,7 +127,7 @@ public void findHits(DataEvent event, Detector atof, Float startTime,
//Matching the hits: if same module and different order, they make up a bar hit
if (this_hit_up.matchBar(this_hit_down)) {
//Bar hits are matched to ahdc tracks and listed
- BarHit this_bar_hit = new BarHit(this_hit_down, this_hit_up, atofEffectiveVelocity);
+ BarHit this_bar_hit = new BarHit(this_hit_down, this_hit_up, atofEffectiveVelocityTable);
//Only add bar hits for which the time sum is in time
if(!this_bar_hit.isInTime()) continue;
this.barHits.add(this_bar_hit);
diff --git a/reconstruction/alert/src/main/java/org/jlab/service/ahdc/AHDCEngine.java b/reconstruction/alert/src/main/java/org/jlab/service/ahdc/AHDCEngine.java
index 8d4252fd28..66b965825c 100644
--- a/reconstruction/alert/src/main/java/org/jlab/service/ahdc/AHDCEngine.java
+++ b/reconstruction/alert/src/main/java/org/jlab/service/ahdc/AHDCEngine.java
@@ -1,7 +1,6 @@
package org.jlab.service.ahdc;
import org.jlab.clas.reco.ReconstructionEngine;
-import org.jlab.clas.tracking.kalmanfilter.Material;
import org.jlab.io.base.DataBank;
import org.jlab.io.base.DataEvent;
import org.jlab.io.hipo.HipoDataSource;
@@ -17,7 +16,6 @@
import org.jlab.rec.ahdc.Hit.Hit;
import org.jlab.rec.ahdc.Hit.HitReader;
import org.jlab.rec.ahdc.HoughTransform.HoughTransform;
-import org.jlab.rec.ahdc.KalmanFilter.MaterialMap;
import org.jlab.rec.ahdc.PreCluster.PreCluster;
import org.jlab.rec.ahdc.PreCluster.PreClusterFinder;
import org.jlab.rec.ahdc.Track.Track;
@@ -43,10 +41,7 @@
public class AHDCEngine extends ReconstructionEngine {
static final Logger LOGGER = Logger.getLogger(AHDCEngine.class.getName());
- private boolean simulation;
-
- /// Material Map used by Kalman filter
- private HashMap materialMap;
+ private boolean simulation = false;
private ModelTrackFinding modelTrackFinding;
private ModeTrackFinding modeTrackFinding = ModeTrackFinding.AI_Track_Finding;
@@ -57,11 +52,11 @@ public class AHDCEngine extends ReconstructionEngine {
private ModeAHDC ahdcExtractor = new ModeAHDC();
// AHDC calibration tables (instance-level, refreshed on run change)
- private IndexedTable ahdcTimeOffsets;
- private IndexedTable ahdcTimeToDistanceWire;
- private IndexedTable ahdcRawHitCuts;
- private IndexedTable ahdcAdcGains;
- private IndexedTable ahdcTimeOverThreshold;
+ private IndexedTable ahdcTimeOffsetsTable;
+ private IndexedTable ahdcTimeToDistanceWireTable;
+ private IndexedTable ahdcRawHitCutsTable;
+ private IndexedTable ahdcAdcGainsTable;
+ private IndexedTable ahdcTimeOverThresholdTable;
int Run = -1;
@@ -76,9 +71,6 @@ public boolean init(ModeTrackFinding m) {
public boolean init() {
factory = (new AlertDCFactory()).createDetectorCLAS(new DatabaseConstantProvider());
- simulation = false;
-
- if (materialMap == null) materialMap = MaterialMap.generateMaterials();
String modeConfig = this.getEngineConfigString("Mode");
if (modeConfig != null) modeTrackFinding = ModeTrackFinding.valueOf(modeConfig);
@@ -92,10 +84,8 @@ public boolean init() {
tableMap.put("/calibration/alert/ahdc/time_over_threshold", 3);
requireConstants(tableMap);
-
- this.getConstantsManager().setVariation("default");
-
- this.registerOutputBank("AHDC::hits","AHDC::preclusters","AHDC::clusters","AHDC::track","AHDC::mc","AHDC::ai:prediction");
+ this.getConstantsManager().setVariation("default");
+ this.registerOutputBank("AHDC::hits","AHDC::preclusters","AHDC::clusters","AHDC::track","AHDC::mc","AHDC::ai:prediction","AHDC::interclusters","AHDC::docaclusters");
return true;
}
@@ -115,11 +105,11 @@ public boolean processDataEvent(DataEvent event) {
return false;
}
if(Run != newRun) {
- ahdcTimeOffsets = this.getConstantsManager().getConstants(newRun, "/calibration/alert/ahdc/time_offsets");
- ahdcTimeToDistanceWire = this.getConstantsManager().getConstants(newRun, "/calibration/alert/ahdc/time_to_distance_wire");
- ahdcRawHitCuts = this.getConstantsManager().getConstants(newRun, "/calibration/alert/ahdc/raw_hit_cuts");
- ahdcAdcGains = this.getConstantsManager().getConstants(newRun, "/calibration/alert/ahdc/gains");
- ahdcTimeOverThreshold = this.getConstantsManager().getConstants(newRun, "/calibration/alert/ahdc/time_over_threshold");
+ ahdcTimeOffsetsTable = this.getConstantsManager().getConstants(newRun, "/calibration/alert/ahdc/time_offsets");
+ ahdcTimeToDistanceWireTable = this.getConstantsManager().getConstants(newRun, "/calibration/alert/ahdc/time_to_distance_wire");
+ ahdcRawHitCutsTable = this.getConstantsManager().getConstants(newRun, "/calibration/alert/ahdc/raw_hit_cuts");
+ ahdcAdcGainsTable = this.getConstantsManager().getConstants(newRun, "/calibration/alert/ahdc/gains");
+ ahdcTimeOverThresholdTable = this.getConstantsManager().getConstants(newRun, "/calibration/alert/ahdc/time_over_threshold");
Run = newRun;
}
}
@@ -127,8 +117,8 @@ public boolean processDataEvent(DataEvent event) {
if (event.hasBank("AHDC::adc")) {
// I) Read raw hits
HitReader hitReader = new HitReader(event, factory, simulation,
- ahdcRawHitCuts, ahdcTimeOffsets, ahdcTimeToDistanceWire,
- ahdcTimeOverThreshold, ahdcAdcGains);
+ ahdcRawHitCutsTable, ahdcTimeOffsetsTable, ahdcTimeToDistanceWireTable,
+ ahdcTimeOverThresholdTable, ahdcAdcGainsTable);
ArrayList AHDC_Hits = hitReader.get_AHDCHits();
// II) Create PreClusters
@@ -147,14 +137,15 @@ public boolean processDataEvent(DataEvent event) {
// Otherwise, the conventional methods (Hough Transform or distance) use clusters.
// Safety check: if too many hits, rely on conventional track finding
+ ModeTrackFinding effectiveMode = modeTrackFinding;
if (AHDC_Hits.size() > MAX_HITS_FOR_AI) {
LOGGER.info("Too many AHDC_Hits in AHDC::adc, rely on conventional track finding for this event");
- modeTrackFinding = ModeTrackFinding.CV_Distance;
+ effectiveMode = ModeTrackFinding.CV_Distance;
}
ArrayList