Skip to content

Commit 3dce988

Browse files
Add Hit Reconstruction from Axial and Stereo Tracking Layers to rLDMX Tracking (#1705)
* Modified LinearSeedFinder.cxx and associated header file with code for new 3D hit reconstruction. Currently still in debug stage * Updated tracking to use the output of the 3D Hit reconstruction algorithm. Also updated uncertainty in y-positions of the 3D recoil hits to reflect the calculation we do to derive them. The performance of the 3D hit reconstruction is currently sub-optimal and will need to be improved. * Small modification to reconstruction algorithm and general code cleanup * Noticed error in LinearSeedFinder. The final x position of the reconstructed hit should be u_axial - dx, but we were not projecting properly. * Modified LinearSeedFinder.cxx and associated header file with code for new 3D hit reconstruction. Currently still in debug stage * Updated tracking to use the output of the 3D Hit reconstruction algorithm. Also updated uncertainty in y-positions of the 3D recoil hits to reflect the calculation we do to derive them. The performance of the 3D hit reconstruction is currently sub-optimal and will need to be improved. * Small modification to reconstruction algorithm and general code cleanup * Noticed error in LinearSeedFinder. The final x position of the reconstructed hit should be u_axial - dx, but we were not projecting properly. * Apply clang-format * Fixed GOLD config.py todefine the histograms in LinearSeedFinder.cxx * Removed LinearSeedFinder histogram declarations --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent e049b21 commit 3dce988

File tree

6 files changed

+397
-134
lines changed

6 files changed

+397
-134
lines changed

.github/validation_samples/reduced_ldmx/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
rSeedTracking.layer12_midpoint = layer12_mid
112112
rSeedTracking.layer23_midpoint = layer23_mid
113113
rSeedTracking.layer34_midpoint = layer34_mid
114+
rSeedTracking.recoil_uncertainty = [0.006, 0.085]
114115
rSeedTracking.ecal_distance_threshold = 15.0
115116

116117
rTracking = reducedTracking.LinearTrackFinder("LinearTrackFinder")

EventDisplay/python/rLDMX_EventDisplay.py

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ def addBranch(tree, ldmx_class, branch_name):
2727

2828
return branch
2929

30-
def trackPlotter(tree, event_number, tag, save):
30+
def trackPlotter(tree, event_number, tag, save, save_tag):
3131

3232
recoilSimHits = addBranch(tree, 'SimTrackerHit', 'RecoilSimHits_{}'.format(tag))
33+
targetSP = addBranch(tree, 'SimTrackerHit', 'TargetScoringPlaneHits_{}'.format(tag))
3334
ecalRecHit = addBranch(tree, 'EcalHit', 'EcalRecHits_{}'.format(tag))
3435
digiRecoil = addBranch(tree, 'Measurement', 'DigiRecoilSimHits_{}'.format(tag))
3536
recoilTruth = addBranch(tree, 'StraightTrack', 'LinearRecoilTruthTracks_{}'.format(tag))
@@ -61,6 +62,10 @@ def trackPlotter(tree, event_number, tag, save):
6162
ecal_end_NOISE_y = []
6263
ecal_end_NOISE_z = []
6364

65+
targetSP_x = []
66+
targetSP_y = []
67+
targetSP_z = []
68+
6469
trackParams = []
6570
truthTrackParams = []
6671

@@ -69,6 +74,12 @@ def trackPlotter(tree, event_number, tag, save):
6974
recoilSim_x.append(particle.getPosition()[0])
7075
recoilSim_y.append(particle.getPosition()[1])
7176

77+
for sp_particle in targetSP:
78+
if (sp_particle.getPosition()[2] > 0):
79+
targetSP_z.append(sp_particle.getPosition()[2])
80+
targetSP_x.append(sp_particle.getPosition()[0])
81+
targetSP_y.append(sp_particle.getPosition()[1])
82+
7283
for x_digi in digiRecoil:
7384
zpos_digi_tot.append(x_digi.getGlobalPosition()[0])
7485
xpos_digi_tot.append(x_digi.getGlobalPosition()[1])
@@ -102,14 +113,18 @@ def trackPlotter(tree, event_number, tag, save):
102113
ecalRecHits = np.column_stack((ecal_end_z, ecal_end_x, ecal_end_y))
103114
ecalRecHits_noise = np.column_stack((ecal_end_NOISE_z, ecal_end_NOISE_x, ecal_end_NOISE_y))
104115
recoilSim = np.column_stack((recoilSim_z, recoilSim_x, recoilSim_y))
116+
targetSP_hits = np.column_stack((targetSP_z, targetSP_x, targetSP_y))
105117
first_sensor_pos = np.column_stack((first_sensor_z, first_sensor_x, first_sensor_y))
106118
second_sensor_pos = np.column_stack((second_sensor_z, second_sensor_x, second_sensor_y))
107119

108120
fig = plt.figure(figsize=(8, 8))
109121
ax = fig.add_subplot(111, projection='3d')
110122

123+
#These values come from uncertainty propogation in the function that reconstructs
124+
#the 3D sensor point from the axial-stereo combo. See Tracking/LinearSeedFinder.cxx
125+
#for the function definitions
111126
x_sensor_uncertainty = 0.006 #mm
112-
y_sensor_uncertainty = 20./np.sqrt(12) # mm
127+
y_sensor_uncertainty = 0.085 # mm
113128

114129
for zi, xi, yi in zip(first_sensor_pos[:,0], first_sensor_pos[:,1], first_sensor_pos[:,2]):
115130
ax.plot([zi, zi], [xi - x_sensor_uncertainty, xi + x_sensor_uncertainty], [yi, yi], color='black',linewidth=2) # x error
@@ -122,6 +137,7 @@ def trackPlotter(tree, event_number, tag, save):
122137
ax.scatter(digiPoints[:,0], digiPoints[:,1], digiPoints[:,2], c='b', marker='o', label='DigiRecoil SimHit', s=25)
123138
ax.scatter(ecalRecHits[:, 0], ecalRecHits[:, 1], ecalRecHits[:, 2], c='purple', label='ECalRecHit', s=50, alpha=0.5)
124139
ax.scatter(recoilSim[:, 0], recoilSim[:, 1], recoilSim[:, 2], marker='o', c='gray', label='RecoilSimHits', s=100, alpha=0.25)
140+
ax.scatter(targetSP_hits[:, 0], targetSP_hits[:, 1], targetSP_hits[:, 2], marker='o', c='yellow', label='Target SP Hits', s=50, alpha=0.5)
125141
ax.scatter(first_sensor_pos[:,0], first_sensor_pos[:,1], first_sensor_pos[:,2], marker='o', c='red', label='First Sensor Point', s=30, alpha=0.75)
126142
ax.scatter(second_sensor_pos[:,0], second_sensor_pos[:,1], second_sensor_pos[:,2], marker='o', c='orange', label='Second Sensor Point', s=30, alpha=0.75)
127143

@@ -143,9 +159,9 @@ def trackPlotter(tree, event_number, tag, save):
143159
z_range = np.linspace(min(ecalRecHits[:,2]) - 5, max(ecalRecHits[:,2]) + 5, 50)
144160
Y, Z = np.meshgrid(y_range, z_range)
145161
X = np.full(Y.shape, ecalRecHits[0][0])
146-
162+
147163
plane = ax.plot_surface(X, Y, Z, color='red', alpha=0.1, edgecolor='none')
148-
164+
149165
for recHit in ecalRecHits:
150166
center_z, center_x, center_y = recHit[0], recHit[1], recHit[2]
151167
radius = 3.87
@@ -169,16 +185,16 @@ def trackPlotter(tree, event_number, tag, save):
169185

170186
ax.legend(fontsize=10)
171187

172-
plt.savefig(f'{save}/{tag}_eventDisplay_eventID_{event_number}.png')
188+
plt.savefig(f'{save}/{tag}_eventDisplay_eventID_{event_number}_{save_tag}.png')
173189

174190
# UNCOMMENT THESE LINES IF YOU WANT A ZOOMED IN PLOT (i.e. just recoil points)
175191
# ax.set_xlim(0, 50)
176192
#
177-
# x_low_lim = -10
178-
# x_up_lim = -5
179-
# y_low_lim = 14
180-
# y_up_lim = 17
181-
#
193+
# x_low_lim = -6
194+
# x_up_lim = -4
195+
# y_low_lim = -18.5
196+
# y_up_lim = -17
197+
#
182198
# x_target = 0.0
183199
# y_target_range = np.linspace(x_low_lim, x_up_lim, 50)
184200
# z_target_range = np.linspace(y_low_lim, y_up_lim, 50)
@@ -194,16 +210,19 @@ def trackPlotter(tree, event_number, tag, save):
194210

195211
def main():
196212
tree = r.TChain("LDMX_Events")
197-
tree.Add('events_5000_rLDMXV1.root')
213+
tree.Add('events_5000_rLDMX_v1_yZERO_new3Dpoints.root')
198214

199215
nentries = tree.GetEntries()
200216
print("nentries = ", nentries)
201217

202218
tag = 'rLDMX_v1'
203-
save_loc = 'event_displays/rLDMX_v1'
204-
event_number = 10
219+
save_loc = 'plots/event_displays/'
220+
event_number = 26
221+
save_tag = 'yZERO_new3Dpoints'
205222

206-
trackPlotter(tree, event_number, tag, save_loc)
223+
# random_numbers = random.sample(range(0, 101), 10)
224+
# for number in random_numbers:
225+
trackPlotter(tree, event_number, tag, save_loc, save_tag)
207226

208227
if __name__ == "__main__":
209228
main()

Tracking/include/Tracking/Event/Measurement.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class Measurement {
111111
/// Add a trackId to the internal vector
112112
void addTrackId(int trkId) { trackIds_.push_back(trkId); };
113113
/// @return the sim particle IDs that compose the measurement
114-
std::vector<unsigned int> getTrackIds() { return trackIds_; };
114+
std::vector<unsigned int> getTrackIds() const { return trackIds_; };
115115

116116
/// @return The energy deposited in the sensor where the measurement took
117117
/// place.

Tracking/include/Tracking/Reco/LinearSeedFinder.h

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,19 +69,6 @@ class LinearSeedFinder : public TrackingGeometryUser {
6969
recoil_two,
7070
const std::array<double, 3> ecal_one);
7171

72-
// Function to combine Recoil layer points into "real" sensor points
73-
std::pair<std::vector<std::tuple<std::array<double, 3>, ldmx::Measurement,
74-
std::optional<ldmx::Measurement>>>,
75-
std::vector<std::tuple<std::array<double, 3>, ldmx::Measurement,
76-
std::optional<ldmx::Measurement>>>>
77-
combineMultiGlobalHits(const std::vector<ldmx::Measurement> &hit_collection);
78-
79-
// Function to do weighted averaging when combining Recoil layer points
80-
std::vector<std::tuple<std::array<double, 3>, ldmx::Measurement,
81-
std::optional<ldmx::Measurement>>>
82-
midPointCalculation(const std::vector<ldmx::Measurement> &layer1,
83-
const std::vector<ldmx::Measurement> &layer2);
84-
8572
// Fitting function: fit a straight line in 3D using 3 points (1 degree of
8673
// freedom)
8774
std::tuple<double, double, double, double, std::vector<double>> fit3DLine(
@@ -93,6 +80,26 @@ class LinearSeedFinder : public TrackingGeometryUser {
9380
double calculateDistance(const std::array<double, 3> &point1,
9481
const std::array<double, 3> &point2);
9582

83+
// Do 3D hit reconstruction using an axial measurement and a stereo
84+
// measurement according to geometric projections
85+
Acts::Vector3 simple3DHitV2(const ldmx::Measurement &axial,
86+
const Acts::Surface &axial_surface,
87+
const ldmx::Measurement &stereo,
88+
const Acts::Surface &stereo_surface,
89+
const ldmx::SimTrackerHit &hitOnTarget,
90+
std::vector<ldmx::SimTrackerHit> pair_sim_hits);
91+
92+
// Makes all combinations of sensor measurements to use in the seeding
93+
std::vector<std::tuple<
94+
std::array<double, 3>,
95+
std::tuple<ldmx::Measurement, ldmx::SimTrackerHit, ldmx::SimTrackerHit>,
96+
std::optional<std::tuple<ldmx::Measurement, ldmx::SimTrackerHit,
97+
ldmx::SimTrackerHit>>>>
98+
processMeasurements(
99+
const std::vector<std::tuple<ldmx::Measurement, ldmx::SimTrackerHit,
100+
ldmx::SimTrackerHit>> &measurements,
101+
const geo::TrackersTrackingGeometry &tg);
102+
96103
// Calculate chi2 of the fit
97104
double globalChiSquare(const std::array<double, 3> &first_sensor,
98105
const std::array<double, 3> &second_sensor,
@@ -103,6 +110,15 @@ class LinearSeedFinder : public TrackingGeometryUser {
103110
// enough points to fit)
104111
int uniqueLayersHit(const std::vector<ldmx::Measurement> &digi_points);
105112

113+
// Helper functions:
114+
std::array<double, 3> convertToLdmxStdArray(const Acts::Vector3 &vec);
115+
std::tuple<Acts::Vector3, Acts::Vector3, Acts::Vector3> getSurfaceVectors(
116+
const Acts::Surface &surface);
117+
double dotProduct(const Acts::Vector3 &v1, const Acts::Vector3 &v2);
118+
std::array<double, 3> getPointAtZ(std::array<double, 3> target,
119+
std::array<double, 3> measurement,
120+
double z_target);
121+
106122
double processing_time_{0.};
107123
long n_events_{0};
108124
unsigned int n_seeds_{0};
@@ -125,7 +141,7 @@ class LinearSeedFinder : public TrackingGeometryUser {
125141
double layer34_midpoint_{27.5};
126142
double ecal_first_layer_z_threshold_{250.0};
127143

128-
std::vector<double> recoil_uncertainty_{0.006, 5.7735};
144+
std::vector<double> recoil_uncertainty_{0.006, 0.085};
129145

130146
// Check failures
131147
long n_missing_{0};

Tracking/python/reducedTracking.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def __init__(self, instance_name="LinearSeedFinder"):
3737
self.input_hits_collection = 'DigiRecoilSimHits'
3838
self.input_rec_hits_collection = 'EcalRecHits'
3939
self.out_seed_collection = 'LinearRecoilSeedTracks'
40-
self.recoil_uncertainty = [0.006, 20./(12**(0.5))]
40+
self.recoil_uncertainty = [0.006, 0.085]
4141
self.ecal_uncertainty = 3.87
4242
self.ecal_first_layer_z_threshold = 250.0
4343
self.ecal_distance_threshold = 15.0

0 commit comments

Comments
 (0)