@@ -160,6 +160,7 @@ void createOptionalOutputBranches() {
160160
161161 // T5 DNN branches
162162 createT5DNNBranches ();
163+ createT3DNNBranches ();
163164
164165#endif
165166}
@@ -191,6 +192,40 @@ void createT5DNNBranches() {
191192 }
192193}
193194
195+ // ________________________________________________________________________________________________________________________________
196+ void createT3DNNBranches () {
197+ // Common branches for T3 properties based on TripletsSoA fields
198+ ana.tx ->createBranch <std::vector<float >>(" t3_betaIn" );
199+ ana.tx ->createBranch <std::vector<float >>(" t3_centerX" );
200+ ana.tx ->createBranch <std::vector<float >>(" t3_centerY" );
201+ ana.tx ->createBranch <std::vector<float >>(" t3_radius" );
202+ ana.tx ->createBranch <std::vector<bool >>(" t3_partOfPT5" );
203+ ana.tx ->createBranch <std::vector<bool >>(" t3_partOfT5" );
204+ ana.tx ->createBranch <std::vector<bool >>(" t3_partOfPT3" );
205+ ana.tx ->createBranch <std::vector<float >>(" t3_pMatched" );
206+ ana.tx ->createBranch <std::vector<float >>(" t3_sim_vxy" );
207+ ana.tx ->createBranch <std::vector<float >>(" t3_sim_vz" );
208+
209+ // Hit-specific branches (T3 has 4 hits from two segments)
210+ std::vector<std::string> hitIndices = {" 0" , " 1" , " 2" , " 3" , " 4" , " 5" };
211+ std::vector<std::string> hitProperties = {" r" , " x" , " y" , " z" , " eta" , " phi" , " detId" , " layer" , " moduleType" };
212+
213+ for (const auto & idx : hitIndices) {
214+ for (const auto & prop : hitProperties) {
215+ std::string branchName = " t3_hit_" + idx + " _" + prop;
216+ if (prop == " detId" || prop == " layer" || prop == " moduleType" ) {
217+ ana.tx ->createBranch <std::vector<int >>(branchName);
218+ } else {
219+ ana.tx ->createBranch <std::vector<float >>(branchName);
220+ }
221+ }
222+ }
223+
224+ // Additional metadata branches
225+ ana.tx ->createBranch <std::vector<int >>(" t3_layer_binary" );
226+ ana.tx ->createBranch <std::vector<std::vector<int >>>(" t3_matched_simIdx" );
227+ }
228+
194229// ________________________________________________________________________________________________________________________________
195230void createGnnNtupleBranches () {
196231 // Mini Doublets
@@ -339,6 +374,7 @@ void setOptionalOutputBranches(LSTEvent* event) {
339374 setQuintupletOutputBranches (event);
340375 setPixelTripletOutputBranches (event);
341376 setOccupancyBranches (event);
377+ setT3DNNBranches (event);
342378 setT5DNNBranches (event);
343379
344380#endif
@@ -637,6 +673,42 @@ void setPixelTripletOutputBranches(LSTEvent* event) {
637673 ana.tx ->setBranch <std::vector<int >>(" pT3_isDuplicate" , pT3_isDuplicate);
638674}
639675
676+ // ________________________________________________________________________________________________________________________________
677+ void fillT3DNNBranches (LSTEvent* event, unsigned int iT3) {
678+ auto hits = event->getHits <HitsSoA>();
679+ auto modules = event->getModules <ModulesSoA>();
680+
681+ std::vector<unsigned int > hitIdx = getHitsFromT3 (event, iT3);
682+ std::vector<lst_math::Hit> hitObjects;
683+
684+ for (int i = 0 ; i < hitIdx.size (); ++i) {
685+ unsigned int hit = hitIdx[i];
686+ float x = hits.xs ()[hit];
687+ float y = hits.ys ()[hit];
688+ float z = hits.zs ()[hit];
689+ lst_math::Hit hitObj (x, y, z);
690+ hitObjects.push_back (hitObj);
691+
692+ std::string idx = std::to_string (i);
693+ ana.tx ->pushbackToBranch <float >(" t3_hit_" + idx + " _r" , sqrt (x * x + y * y));
694+ ana.tx ->pushbackToBranch <float >(" t3_hit_" + idx + " _x" , x);
695+ ana.tx ->pushbackToBranch <float >(" t3_hit_" + idx + " _y" , y);
696+ ana.tx ->pushbackToBranch <float >(" t3_hit_" + idx + " _z" , z);
697+ ana.tx ->pushbackToBranch <float >(" t3_hit_" + idx + " _eta" , hitObj.eta ());
698+ ana.tx ->pushbackToBranch <float >(" t3_hit_" + idx + " _phi" , hitObj.phi ());
699+
700+ int subdet = trk.ph2_subdet ()[hits.idxs ()[hit]];
701+ int is_endcap = subdet == 4 ;
702+ int layer = trk.ph2_layer ()[hits.idxs ()[hit]] + 6 * is_endcap;
703+ int detId = trk.ph2_detId ()[hits.idxs ()[hit]];
704+ unsigned int module = hits.moduleIndices ()[hit];
705+
706+ ana.tx ->pushbackToBranch <int >(" t3_hit_" + idx + " _detId" , detId);
707+ ana.tx ->pushbackToBranch <int >(" t3_hit_" + idx + " _layer" , layer);
708+ ana.tx ->pushbackToBranch <int >(" t3_hit_" + idx + " _moduleType" , modules.moduleType ()[module ]);
709+ }
710+ }
711+
640712// ________________________________________________________________________________________________________________________________
641713void fillT5DNNBranches (LSTEvent* event, unsigned int iT3) {
642714 auto hits = event->getHits <HitsSoA>();
@@ -687,6 +759,69 @@ void fillT5DNNBranches(LSTEvent* event, unsigned int iT3) {
687759 ana.tx ->pushbackToBranch <float >(" t5_t3_phi" , hitObjects[0 ].phi ());
688760}
689761
762+ void setT3DNNBranches (LSTEvent* event) {
763+ auto const triplets = event->getTriplets <TripletsSoA>();
764+ auto const tripletsOccupancy = event->getTriplets <TripletsOccupancySoA>();
765+ auto modules = event->getModules <ModulesSoA>();
766+ auto ranges = event->getRanges ();
767+
768+ for (unsigned int lowerModuleIdx = 0 ; lowerModuleIdx < modules.nLowerModules (); ++lowerModuleIdx) {
769+ int nTriplets = tripletsOccupancy.nTriplets ()[lowerModuleIdx];
770+ for (unsigned int idx = 0 ; idx < nTriplets; idx++) {
771+ unsigned int tripletIndex = ranges.tripletModuleIndices ()[lowerModuleIdx] + idx;
772+
773+ // Get hit indices and types
774+ std::vector<unsigned int > hit_idx = getHitsFromT3 (event, tripletIndex);
775+ std::vector<unsigned int > hit_type = getHitTypesFromT3 (event, tripletIndex);
776+ std::vector<unsigned int > module_idx = getModuleIdxsFromT3 (event, tripletIndex);
777+
778+ // Calculate layer binary representation
779+ int layer_binary = 0 ;
780+ for (size_t i = 0 ; i < module_idx.size (); i += 2 ) {
781+ layer_binary |= (1 << (modules.layers ()[module_idx[i]] + 6 * (modules.subdets ()[module_idx[i]] == 4 )));
782+ }
783+
784+ // Get matching information with percent matched
785+ float percent_matched;
786+ std::vector<int > simidx = matchedSimTrkIdxs (hit_idx, hit_type, false , &percent_matched);
787+
788+ // Fill the branches with T3-specific data
789+ ana.tx ->pushbackToBranch <float >(" t3_betaIn" , triplets.betaIn ()[tripletIndex]);
790+ ana.tx ->pushbackToBranch <float >(" t3_centerX" , triplets.centerX ()[tripletIndex]);
791+ ana.tx ->pushbackToBranch <float >(" t3_centerY" , triplets.centerY ()[tripletIndex]);
792+ ana.tx ->pushbackToBranch <float >(" t3_radius" , triplets.radius ()[tripletIndex]);
793+ ana.tx ->pushbackToBranch <bool >(" t3_partOfPT5" , triplets.partOfPT5 ()[tripletIndex]);
794+ ana.tx ->pushbackToBranch <bool >(" t3_partOfT5" , triplets.partOfT5 ()[tripletIndex]);
795+ ana.tx ->pushbackToBranch <bool >(" t3_partOfPT3" , triplets.partOfPT3 ()[tripletIndex]);
796+ ana.tx ->pushbackToBranch <int >(" t3_layer_binary" , layer_binary);
797+ ana.tx ->pushbackToBranch <std::vector<int >>(" t3_matched_simIdx" , simidx);
798+ ana.tx ->pushbackToBranch <float >(" t3_pMatched" , percent_matched);
799+
800+ // Add vertex information for matched sim tracks
801+ if (simidx.size () == 0 ) {
802+ // No matched sim track - set default values
803+ ana.tx ->pushbackToBranch <float >(" t3_sim_vxy" , 0.0 );
804+ ana.tx ->pushbackToBranch <float >(" t3_sim_vz" , 0.0 );
805+ } else {
806+ // Get vertex information from the first matched sim track
807+ int vtxidx = trk.sim_parentVtxIdx ()[simidx[0 ]];
808+ float vtx_x = trk.simvtx_x ()[vtxidx];
809+ float vtx_y = trk.simvtx_y ()[vtxidx];
810+ float vtx_z = trk.simvtx_z ()[vtxidx];
811+
812+ // Calculate transverse distance from origin
813+ float vxy = sqrt (vtx_x * vtx_x + vtx_y * vtx_y);
814+
815+ ana.tx ->pushbackToBranch <float >(" t3_sim_vxy" , vxy);
816+ ana.tx ->pushbackToBranch <float >(" t3_sim_vz" , vtx_z);
817+ }
818+
819+ // Fill hit-specific information
820+ fillT3DNNBranches (event, tripletIndex);
821+ }
822+ }
823+ }
824+
690825// ________________________________________________________________________________________________________________________________
691826void setT5DNNBranches (LSTEvent* event) {
692827 auto triplets = event->getTriplets <TripletsOccupancySoA>();
0 commit comments