Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,65 @@
import org.jlab.geom.detector.alert.AHDC.AlertDCDetector;
import org.jlab.utils.groups.IndexedTable;

/**
* Reads raw AHDC hits from the {@code AHDC::adc} bank, applies calibration corrections
* (time offsets, time-over-threshold, ADC gains), filters them against per-wire cuts in
* data mode, and builds the list of {@link Hit} objects used by downstream reconstruction.
* In simulation mode, the per-wire cuts and data-only ADC/ToT corrections are bypassed,
* and truth information is additionally read from the {@code MC::True} bank into {@link TrueHit}s.
*/
public class HitReader {

private ArrayList<Hit> _AHDCHits;
private ArrayList<TrueHit> _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}.
*
* <p>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).
*
* <p>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<Double> 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);
Expand All @@ -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:
* <ol>
* <li>applies the per-wire time offset {@code t0} (subtracting event start time in data mode),</li>
* <li>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,</li>
* <li>computes the DOCA from the calibrated time via {@link #T2Dfunction} (DOCA forced to 0
* when {@code time < 0}),</li>
* <li>in data mode, applies the per-wire ADC gain correction,</li>
* <li>instantiates a {@link Hit}, resolves its wire position via the geometry, and stores the
* calibrated ADC and ToT on it.</li>
* </ol>
* 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<Hit> hits = new ArrayList<>();

if (!event.hasBank("AHDC::adc")) {
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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<TrueHit> truehits = new ArrayList<>();

Expand All @@ -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<Hit> 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<Hit> 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<TrueHit> 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<TrueHit> trueHits) {
this._TrueAHDCHits = trueHits;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class ATOFHit {
private boolean isInACluster;
private int associatedClusterIndex;
int idTDC;
private IndexedTable atofTimeOffsets;
private IndexedTable atofTimeOffsetsTable;


public int getSector() {
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -400,15 +400,15 @@ 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;
this.order = order;
this.tdc = tdc;
this.tot = tot;
this.startTime = startTime;
this.atofTimeOffsets = atofTimeOffsets;
this.atofTimeOffsetsTable = atofTimeOffsetsTable;
this.isInACluster = false;

this.makeType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ public void setWedgeHits(ArrayList<ATOFHit> 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();
Expand All @@ -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
}
Expand Down Expand Up @@ -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);
Expand Down
Loading
Loading