2626#include <TTree.h>
2727#include <filesystem>
2828#include <fstream>
29+ #include <regex>
30+ #include <set>
31+ #include <map>
2932#endif
3033
3134#define ENABLE_UPGRADES
@@ -76,7 +79,7 @@ struct Data {
7679
7780void CompareClustersAndDigitsOnChip (std ::string clusfile = "o2clus_its.root" ,
7881 std ::string digifile = "it3digits.root" ,
79- std ::string dictfile = "IT3dictionary.root " ,
82+ std ::string dictfile = "" ,
8083 std ::string hitfile = "o2sim_HitsIT3.root" ,
8184 std ::string inputGeom = "o2sim_geometry.root" ,
8285 bool batch = true)
@@ -109,6 +112,90 @@ void CompareClustersAndDigitsOnChip(std::string clusfile = "o2clus_its.root",
109112 o2 ::math_utils ::TransformType ::L2G )); // request cached transforms
110113 const int nChips = gman -> getNumberOfChips ();
111114
115+ LOGP (info , "Total number of chips is {} in ITS3 (IB and OB)" , nChips );
116+
117+ // Create all plots
118+ LOGP (info , "Selecting chips to be visualised" );
119+ std ::set < int > selectedChips ;
120+ std ::map < std ::string , std ::vector < int >> chipGroups ;
121+
122+ for (int chipID {0 }; chipID < nChips ; ++ chipID ) {
123+ TString tpath = gman -> getMatrixPath (chipID );
124+ std ::string path = tpath .Data ();
125+
126+ std ::vector < std ::string > tokens ;
127+ std ::istringstream iss (path );
128+ std ::string token ;
129+ while (std ::getline (iss , token , '/' )) {
130+ if (!token .empty ()) {
131+ tokens .push_back (token );
132+ }
133+ }
134+
135+ std ::string segmentName , staveName , carbonFormName ;
136+ for (const auto& t : tokens ) {
137+ if (t .find ("ITS3Segment ") != std ::string ::npos ) segmentName = t ;
138+ if (t .find ("ITSUStave" ) != std ::string ::npos ) staveName = t ;
139+ if (t .find ("ITS3CarbonForm" ) != std ::string ::npos ) carbonFormName = t ;
140+ }
141+
142+ std ::string groupKey ;
143+ if (!segmentName .empty ()) {
144+ groupKey = segmentName + "_" + carbonFormName ;
145+ } else if (!staveName .empty ()) {
146+ groupKey = staveName ;
147+ } else {
148+ continue ;
149+ }
150+
151+ chipGroups [groupKey ].push_back (chipID );
152+ }
153+
154+ LOGP (info , "From each IB Segment or OB Stave, 10 chipIDs are uniformly selected" );
155+ LOGP (info , "Selected chipID: " );
156+ for (auto & [groupName , ids ] : chipGroups ) {
157+ std ::vector < int > sampled ;
158+ if (ids .size () <= 10 ) {
159+ for (auto id : ids ) {
160+ selectedChips .insert (id );
161+ sampled .push_back (id );
162+ }
163+ } else {
164+ for (int i {0 }; i < 10 ; ++ i ) {
165+ int idx = i * (ids .size () - 1 ) / 9 ; // 9 intervals for 10 points
166+ int id = ids [idx ];
167+ if (selectedChips .insert (id ).second ) {
168+ sampled .push_back (id );
169+ }
170+ }
171+ }
172+
173+ std ::ostringstream oss ;
174+ std ::string topOrBot = "N/A" ;
175+ std ::smatch match ;
176+ std ::regex rgxSegment (R "(Segment(\d+)_(\d+)_ITS3CarbonForm\d+_(\d+))" );
177+ std ::regex rgxStave (R "(Stave(\d+)_(\d+))" );
178+ if (std ::regex_search (groupName , match , rgxSegment )) {
179+ int layer = std ::stoi (match [1 ]);
180+ int segment = std ::stoi (match [2 ]);
181+ int carbonForm = std ::stoi (match [3 ]);
182+ topOrBot = (carbonForm == 0 ? "TOP" : "BOT" );
183+ oss << topOrBot << " segment " << segment << " at layer " << layer << ": " ;
184+ } else if (std ::regex_search (groupName , match , rgxStave )) {
185+ int layer = std ::stoi (match [1 ]);
186+ int stave = std ::stoi (match [2 ]);
187+ oss << "Stave " << stave << " at layer " << layer << ": " ;
188+ } else {
189+ LOGP (error , "Cannot select the correct chipID in OB or IB" );
190+ return ;
191+ }
192+ for (auto id : sampled ) {
193+ oss << id << " " ;
194+ }
195+ LOG (info ) << oss .str ();
196+ }
197+ LOGP (info , "{} selected chips will be visualized and analyzed." , chipGroups .size ());
198+
112199 // Hits
113200 TFile fileH (hitfile .data ());
114201 auto* hitTree = dynamic_cast < TTree * > (fileH .Get ("o2sim" ));
@@ -198,12 +285,15 @@ void CompareClustersAndDigitsOnChip(std::string clusfile = "o2clus_its.root",
198285
199286 // Create all plots
200287 LOGP (info , "Creating plots" );
201- std ::vector < Data > data (nChips );
202- for (int iChip {0 }; iChip < nChips ; ++ iChip ) {
203- auto& dat = data [iChip ];
288+ std ::unordered_map < int , Data > data ;
289+ auto initData = [& ](int chipID , Data & dat ) {
290+ if (dat .pixelArray ) return ;
291+
204292 int nCol {0 }, nRow {0 };
205293 float lengthPixArr {0 }, widthPixArr {0 };
206- if (o2 ::its3 ::constants ::detID ::isDetITS3 (iChip )) {
294+ bool isIB = o2 ::its3 ::constants ::detID ::isDetITS3 (chipID );
295+ int layer = gman -> getLayer (chipID );
296+ if (isIB ) {
207297 nCol = o2 ::its3 ::SegmentationMosaix ::NCols ;
208298 nRow = o2 ::its3 ::SegmentationMosaix ::NRows ;
209299 lengthPixArr = o2 ::its3 ::constants ::pixelarray ::pixels ::mosaix ::pitchZ * nCol ;
@@ -214,44 +304,40 @@ void CompareClustersAndDigitsOnChip(std::string clusfile = "o2clus_its.root",
214304 lengthPixArr = o2 ::itsmft ::SegmentationAlpide ::PitchCol * nCol ;
215305 widthPixArr = o2 ::itsmft ::SegmentationAlpide ::PitchRow * nRow ;
216306 }
217-
218- dat .pixelArray = new TH2F (Form ("histSensor_%d" , iChip ), Form ("SensorID=%d;z(cm);x(cm)" , iChip ),
307+
308+ dat .pixelArray = new TH2F (Form ("histSensor_%d" , chipID ), Form ("SensorID=%d;z(cm);x(cm)" , chipID ),
219309 nCol , -0.5 * lengthPixArr , 0.5 * lengthPixArr ,
220310 nRow , -0.5 * widthPixArr , 0.5 * widthPixArr );
221311 dat .hitS = new TGraph ();
222312 dat .hitS -> SetMarkerStyle (kFullTriangleDown );
223313 dat .hitS -> SetMarkerColor (kGreen );
224- dat .hitS -> SetEditable (kFALSE );
225314 dat .hitM = new TGraph ();
226315 dat .hitM -> SetMarkerStyle (kFullCircle );
227316 dat .hitM -> SetMarkerColor (kGreen + 3 );
228- dat .hitM -> SetEditable (kFALSE );
229317 dat .hitE = new TGraph ();
230318 dat .hitE -> SetMarkerStyle (kFullTriangleUp );
231319 dat .hitE -> SetMarkerColor (kGreen + 5 );
232- dat .hitE -> SetEditable (kFALSE );
233- dat .clusS = new TGraph (1 );
320+ dat .clusS = new TGraph ();
234321 dat .clusS -> SetMarkerStyle (kFullSquare );
235322 dat .clusS -> SetMarkerColor (kBlue );
236- dat .clusS -> SetEditable (kFALSE );
237- dat .cog = new TGraph (1 );
323+ dat .cog = new TGraph ();
238324 dat .cog -> SetMarkerStyle (kFullDiamond );
239325 dat .cog -> SetMarkerColor (kRed );
240- dat .cog -> SetEditable (kFALSE );
241326 dat .leg = new TLegend (0.7 , 0.7 , 0.92 , 0.92 );
242327 dat .leg -> AddEntry (dat .hitS , "Hit Start" );
243328 dat .leg -> AddEntry (dat .hitM , "Hit Middle" );
244329 dat .leg -> AddEntry (dat .hitE , "Hit End" );
245330 dat .leg -> AddEntry (dat .clusS , "Cluster Start" );
246331 dat .leg -> AddEntry (dat .cog , "Cluster COG" );
247332 dat .vClusBox = new std ::vector < TBox * > ;
248- }
333+ };
249334
250335 LOGP (info , "Filling digits" );
251336 for (int iDigit {0 }; digTree -> LoadTree (iDigit ) >= 0 ; ++ iDigit ) {
252337 digTree -> GetEntry (iDigit );
253338 for (const auto& digit : * digArr ) {
254339 const auto chipID = digit .getChipIndex ();
340+ if (!selectedChips .count (chipID )) continue ;
255341 const auto layer = gman -> getLayer (chipID );
256342 bool isIB = layer < 3 ;
257343 float locDigiX {0 }, locDigiZ {0 };
@@ -260,14 +346,16 @@ void CompareClustersAndDigitsOnChip(std::string clusfile = "o2clus_its.root",
260346 } else {
261347 o2 ::itsmft ::SegmentationAlpide ::detectorToLocal (digit .getRow (), digit .getColumn (), locDigiX , locDigiZ );
262348 }
349+ auto& dat = data [chipID ];
350+ initData (chipID , dat );
263351 data [chipID ].pixelArray -> Fill (locDigiZ , locDigiX );
264352 }
265353 }
266354
267355 LOGP (info , "Building min and max MC events used by each ROF, total ROFs {}" , nROFRec );
268356 auto pattIt = patternsPtr -> cbegin ();
269357 bool isAllPattIDInvaild {true};
270- for (unsigned int irof = 0 ; irof < nROFRec ; irof ++ ) {
358+ for (unsigned int irof { 0 } ; irof < nROFRec ; irof ++ ) {
271359 const auto& rofRec = rofRecVec [irof ];
272360 // >> read and map MC events contributing to this ROF
273361 for (int im = mcEvMin [irof ]; im <= mcEvMax [irof ]; im ++ ) {
@@ -285,14 +373,39 @@ void CompareClustersAndDigitsOnChip(std::string clusfile = "o2clus_its.root",
285373 }
286374
287375 // Clusters in this ROF
288- for (int icl = 0 ; icl < rofRec .getNEntries (); icl ++ ) {
376+ for (int icl { 0 } ; icl < rofRec .getNEntries (); icl ++ ) {
289377 int clEntry = rofRec .getFirstEntry () + icl ; // entry of icl-th cluster of this ROF in the vector of clusters
290378 const auto& cluster = (* clusArr )[clEntry ];
291379 const auto chipID = cluster .getSensorID ();
380+ if (!selectedChips .count (chipID )) {
381+ // Even if not selected, advance pattIt if patternID is InvalidPatternID
382+ if (cluster .getPatternID () == o2 ::itsmft ::CompCluster ::InvalidPatternID ) {
383+ o2 ::itsmft ::ClusterPattern ::skipPattern (pattIt );
384+ }
385+ continue ;
386+ }
292387 const auto pattID = cluster .getPatternID ();
293388 const bool isIB = o2 ::its3 ::constants ::detID ::isDetITS3 (chipID );
294389 const auto layer = gman -> getLayer (chipID );
390+ auto& dat = data [chipID ];
391+ initData (chipID , dat );
295392 o2 ::itsmft ::ClusterPattern pattern ;
393+ // Pattern extraction
394+ if (cluster .getPatternID () != o2 ::itsmft ::CompCluster ::InvalidPatternID ) {
395+ isAllPattIDInvaild = false;
396+ if (!hasAvailableDict ) {
397+ LOGP (error , "Encountered pattern ID {}, which is not equal to the invalid pattern ID {}" , cluster .getPatternID (), o2 ::itsmft ::CompCluster ::InvalidPatternID );
398+ LOGP (error , "Clusters have already been generated with a dictionary which was not provided properly!" );
399+ return ;
400+ }
401+ if (dict .isGroup (cluster .getPatternID (), isIB )) {
402+ pattern .acquirePattern (pattIt );
403+ } else {
404+ pattern = dict .getPattern (cluster .getPatternID (), isIB );
405+ }
406+ } else {
407+ pattern .acquirePattern (pattIt );
408+ }
296409
297410 // Hits
298411 const auto& lab = (clusLabArr -> getLabels (clEntry ))[0 ];
@@ -332,30 +445,17 @@ void CompareClustersAndDigitsOnChip(std::string clusfile = "o2clus_its.root",
332445 }
333446 data [chipID ].clusS -> AddPoint (locCluZ , locCluX );
334447
335- // Pattern extraction
336- if (cluster .getPatternID () != o2 ::itsmft ::CompCluster ::InvalidPatternID ) {
337- isAllPattIDInvaild = false;
338- if (!hasAvailableDict ) {
339- LOGP (error , "Encountered pattern ID {}, which is not equal to the invalid pattern ID {}" , cluster .getPatternID (), o2 ::itsmft ::CompCluster ::InvalidPatternID );
340- LOGP (error , "Clusters have already been generated with a dictionary which was not provided properly!" );
341- return ;
342- }
343- if (dict .isGroup (cluster .getPatternID (), isIB )) {
344- pattern .acquirePattern (pattIt );
345- } else {
346- pattern = dict .getPattern (cluster .getPatternID (), isIB );
347- }
348- } else {
349- pattern .acquirePattern (pattIt );
350- }
351-
352448 // COG
353449 o2 ::math_utils ::Point3D < float > locCOG ;
354450 // Cluster COG using dictionary (if available)
355451 if (hasAvailableDict && (pattID != o2 ::itsmft ::CompCluster ::InvalidPatternID && !dict .isGroup (pattID , isIB ))) {
356452 locCOG = dict .getClusterCoordinates (cluster );
357453 } else {
358- locCOG = o2 ::itsmft ::TopologyDictionary ::getClusterCoordinates (cluster , pattern , false);
454+ if (isIB ) {
455+ locCOG = o2 ::its3 ::TopologyDictionary ::getClusterCoordinates (cluster , pattern , false);
456+ } else {
457+ locCOG = o2 ::itsmft ::TopologyDictionary ::getClusterCoordinates (cluster , pattern , false);
458+ }
359459 }
360460 if (isIB ) {
361461 float flatX {0 }, flatY {0 };
@@ -402,15 +502,16 @@ void CompareClustersAndDigitsOnChip(std::string clusfile = "o2clus_its.root",
402502 return ;
403503 }
404504 }
405-
505+
406506 LOGP (info , "Writing to root file" );
407507 double x1 , y1 , x2 , y2 ;
408508 auto oFileOut = TFile ::Open ("CompareClustersAndDigitsOnChip.root" , "RECREATE" );
409509 oFileOut -> cd ();
410- for (int iChip = 0 ; iChip < 4000 ; ++ iChip ) {
411- auto& dat = data [iChip ];
412- auto path = gman -> getMatrixPath (iChip );
413- const std ::string cpath {path .Data () + 39 , path .Data () + path .Length ()};
510+ for (int chipID {0 }; chipID < nChips ; chipID ++ ) {
511+ if (!selectedChips .count (chipID )) continue ;
512+ auto& dat = data [chipID ];
513+ TString tpath = gman -> getMatrixPath (chipID );
514+ const std ::string cpath {tpath .Data () + 39 , tpath .Data () + tpath .Length ()};
414515 const std ::filesystem ::path p {cpath };
415516 std ::string nestedDir = p .parent_path ().string ();
416517 TDirectory * currentDir = oFileOut ;
@@ -431,12 +532,12 @@ void CompareClustersAndDigitsOnChip(std::string clusfile = "o2clus_its.root",
431532 currentDir -> cd ();
432533 }
433534 if (!currentDir ) {
434- LOGP (error , "Failed to create nested directory for chip %d" , iChip );
535+ LOGP (error , "Failed to create nested directory for chip %d" , chipID );
435536 continue ;
436537 }
437-
438- auto canv = new TCanvas (Form ("%s_%d" , p .filename ().c_str (), iChip ));
439- canv -> SetTitle (Form ("%s_%d" , p .filename ().c_str (), iChip ));
538+
539+ auto canv = new TCanvas (Form ("%s_%d" , p .filename ().c_str (), chipID ));
540+ canv -> SetTitle (Form ("%s_%d" , p .filename ().c_str (), chipID ));
440541 canv -> cd ();
441542 gPad -> SetGrid (1 , 1 );
442543 dat .pixelArray -> Draw ("colz" );
@@ -445,7 +546,7 @@ void CompareClustersAndDigitsOnChip(std::string clusfile = "o2clus_its.root",
445546 dat .hitE -> Draw ("p;same" );
446547 auto arr = new TArrow ();
447548 arr -> SetArrowSize (0.01 );
448- for (int i = 0 ; i < dat .hitS -> GetN (); ++ i ) {
549+ for (int i { 0 } ; i < dat .hitS -> GetN (); ++ i ) {
449550 dat .hitS -> GetPoint (i , x1 , y1 );
450551 dat .hitE -> GetPoint (i , x2 , y2 );
451552 arr -> DrawArrow (x1 , y1 , x2 , y2 );
@@ -458,15 +559,15 @@ void CompareClustersAndDigitsOnChip(std::string clusfile = "o2clus_its.root",
458559 }
459560 dat .leg -> Draw ();
460561 canv -> SetEditable (false);
461-
562+
462563 currentDir -> WriteTObject (canv , canv -> GetName ());
463564 dat .clear ();
464565 delete canv ;
465566 delete arr ;
466- printf ("\rWriting chip %05d" , iChip );
567+ printf ("\rWriting chip %05d" , chipID );
467568 }
468569 printf ("\n" );
469570 oFileOut -> Write ();
470571 oFileOut -> Close ();
471- LOGP (info , "Finished! " );
572+ LOGP (info , "Finished writing selected chip visualizations. " );
472573}
0 commit comments