// This is similar to the "sort" scripts used previously. // However, when working with single samples, we don't need to sort the file - we just need to add various bits and pieces, like the BadStrip flag, the sample time (given as an argument), the hitID etc. // Set up for source tests (simple, only one sensor) // THIS SCRIPT SHOULD BE COMPILED BEFORE USE #include #include "TTree.h" #include "TFile.h" // void sort(char rootFile[], int SampleTime) { cout << "==== LHCb input file: " << rootFile << endl; /// Code to sort our trees so that the 5 samples taken after each hit on the BAT is sorted into the right order. /// Want to modify so that it runs on all the trees in a file, which we give by name. TFile f(rootFile); //open new file to store the output Char_t outFile[100]; sprintf(outFile, "Sort_%s", rootFile); // creates an output filename TFile f2(outFile,"recreate"); cout << "==== Output file: " << outFile << endl; // Set up the information about the sensors int num_sensors=1; TString sensorName[num_sensors]; // Specify the names of the sensors here sensorName[0] = ""; // Also, set up the bad strip array. This is initialised to all zeroes. int sensor=0; // initialise variable to keep track of sensor we're working on int strip=0; // keeps track of individual noisy strip entries int num_noisystrips=7; // max no. of noisy strips on a sensor - choose this yourself int noisyStrips[num_sensors][num_noisystrips]; // Loop to initialise entries in array to zero for(sensor = 0; sensor < num_sensors ; sensor++){ for(strip = 0; strip < num_noisystrips ; strip++){ noisyStrips[sensor][strip]=0; } } // Then, we can specify specific noisy strips. Need to only choose the relevant sensor! // GLA1 - SINGLE MIP TESTING /* // Gla1 - avoid a single dubious strip near the start (bond pattern) and also last strip in each Alink (possibly shares signal with next strip) noisyStrips[0][0]=387; noisyStrips[0][1]=511; // Last strip in each Alink is dodgy too noisyStrips[0][2]=415; noisyStrips[0][3]=447; noisyStrips[0][4]=479; // On 3D sensor, finally want to avoid a strip with no proper signal, plus the adjacent one noisyStrips[0][5]=450; noisyStrips[0][6]=451; */ // Gla2 - no proper noisy strips, but due to an oddity in the pattern of unbonded strips I want to ignore strip 3. //noisyStrips[0][0]=3; //noisyStrips[0][1]=127; /* // Gla0 noisyStrips[0][0]=259; noisyStrips[0][1]=383; // Fre2 // The strips are around 1173 and 205, which are no use after re-ordering (fall between header strips) and also 1153, which is noisy. Note that 1152 is not used for finding hits anyway (edge of array). // So, block 1172-74, 1204-06, 1153 noisyStrips[0][0]=1172; noisyStrips[0][1]=1173; noisyStrips[0][2]=1174; noisyStrips[0][3]=1204; noisyStrips[0][4]=1205; noisyStrips[0][5]=1206; noisyStrips[0][6]=1153; // On Fre0, we have a few noisy strips - 1467, 1469, 1471. Also have strips falling between header strips as above - 1416, 1448. Lastly, 1460 is unbonded. // So, block 1415-7, 1447-49, 1459-61, 1467-71 noisyStrips[0][0]=1415; noisyStrips[0][1]=1416; noisyStrips[0][2]=1417; noisyStrips[0][3]=1447; noisyStrips[0][4]=1448; noisyStrips[0][5]=1449; noisyStrips[0][6]=1459; noisyStrips[0][7]=1460; noisyStrips[0][8]=1461; noisyStrips[0][9]=1467; noisyStrips[0][10]=1468; noisyStrips[0][11]=1469; noisyStrips[0][12]=1470; noisyStrips[0][13]=1471; */ // Define variables used when adding new data to output file int hitId=0; int BadStrip=0; int iHit=0; int iSens=0; int iSensOffset=0; Int_t nentriesEvent; Int_t nentriesHit; int BCntLoopEvent=0; int BCntOldEvent=0; // Used to check for consecutive values int BATTrigEvent=0; int nHitsEvent=0; int BCntLoopHit=0; int PosXHit=0; int checker=0; // The trees: TTree *treeEvent; TTree *treeHit; TTree *tsortedEvent; TTree *tsortedHit; // Strings I'll use TString pathEvent; TString pathHit; // Now, need to do the following for each sensor. Will copy and paste code. Usual syntax applies // During debugging, work with Fre2, then fix others after. // UBER-LOOP will deal with the separate LCMS and Cluster trees. LCMS is case 0, Cluster is case 1. for(checker = 0; checker < 2 ; checker++) { // First loop will loop over all the sensors, saving us from having to use new code for each sensor. sensor keeps track. for(sensor = 0; sensor < num_sensors ; sensor++) { cout << " Sensor setup at checker=" << checker << " and sensor=" << sensor << endl; //******************************* // Setup for each sensor //******************************* // Getting the relevant tree within the file. Here, I want to get the Event AND Hit trees. Need to use // Need to use different versions for LCMS and ClusterMoni checkers if(checker==0){ pathEvent = "VeloLCMSMoni/LCMSEvent" + sensorName[sensor]; // Put together the path pathHit = "VeloLCMSMoni/LCMSHit" + sensorName[sensor]; } else{ pathEvent = "VeloClusterMoni/ClusterEvent" + sensorName[sensor]; // Put together the path pathHit = "VeloClusterMoni/ClusterHit" + sensorName[sensor]; } treeEvent = (TTree*)f.Get(pathEvent); nentriesEvent = (Int_t)treeEvent->GetEntries(); treeHit = (TTree*)f.Get(pathHit); nentriesHit = (Int_t)treeHit->GetEntries(); //Create an empty clone of the original tree //I want to be able to add extra entries to this cloned tree // Copy the existing tree structure, call the tree *tsorted tsortedEvent = (TTree*)treeEvent->CloneTree(0); // Add new branches for the true ordering of events in each batch of 5 (OrderTrue), the hitId (to make sorting the hit tree easier) and the WindowDelay and SampleTime variables // Note that I'm trying to add the same info to a couple of different trees here. Have to be careful. tsortedEvent->Branch("hitId",&hitId,"hitId/I"); tsortedEvent->Branch("SampleTime",&SampleTime,"SampleTime/I"); //****** // Next, we need to do something similar for the Hit tree. //Create an empty clone of the original tree //I want to be able to add extra entries to this cloned tree // Copy the existing tree structure, call the tree *tsorted tsortedHit = (TTree*)treeHit->CloneTree(0); // Add new branches for the true ordering of events in each batch of 5 (OrderTrue), the raw timing info (TimeDiff), the calculated hit time in ns HitTime, and the noisy strip flag BadStrip tsortedHit->Branch("BadStrip",&BadStrip,"BadStrip/I"); tsortedHit->Branch("SampleTime",&SampleTime,"SampleTime/I"); //*** // Have to specify the following so that we can look at specific variables after using GetEntry. Also have to be careful when dealing with different detector trees - use different variables for different detectors. I get the BCntLoop to check that there are no errors in the file. BCntLoopEvent=0; BCntOldEvent=0; // Used to check for consecutive values BATTrigEvent=0; treeEvent->SetBranchAddress("BCntLoop",&BCntLoopEvent); treeEvent->SetBranchAddress("BATTrig",&BATTrigEvent); treeEvent->SetBranchAddress("nHits",&nHitsEvent); BCntLoopHit=0; PosXHit=0; treeHit->SetBranchAddress("BCntLoop",&BCntLoopHit); // Slight difference in data from trees - cluster tree gives positions of both start of cluster and its main strip. Use the main strip value. if(checker==0) treeHit->SetBranchAddress("PosX",&PosXHit); else treeHit->SetBranchAddress("CentrePosX",&PosXHit); //*************** // // LOOPING OVER ALL THE ENTRIES IN THE EVENT TREE // Need to use iSens to loop over the sensors. // Within this loop, we use the array of indices to grab the events in the correct order, writing them to a new tree. cout << " Start of loop at checker=" << checker << " and sensor=" << sensor << endl; iHit=0; // iterator to keep track of our position within the Hit tree for (iSens=iSensOffset;iSensGetEntry(iSens); // Read in an event. Previous statements mean BCntLoop is accessible. // Add hitId. This is iHit, if there are any hits in this event. If not, this is set to -1. if (nHitsEvent==0){hitId=-1;} else {hitId=iHit;} BCntOldEvent=BCntLoopEvent; // Update to the old bunch count value tsortedEvent->Fill(); // Fill the Event tree //****************** // Next, deal with the Hit tree. To do this, we need to use a loop to check all the Hit events which have the same BCntLoop value. We'll have to do some checking within the loop, so we'll use a break statement to get out of it (more flexible) while (iHitGetEntry(iHit); // Using iHit to keep track of indices, read in an event from the sorted Hit tree // As a test, check to see if the BCntLoop for the current hit is lower than that for event. If this is true, something has gone wrong. if (BCntLoopEvent>BCntLoopHit) cout << "Error with Hit tree ordering - missed an entry somewhere " << endl; // Check to see if the BCntLoop number in this Hit match the current event. If not, break. if (BCntLoopEvent!=BCntLoopHit) break; // Since we have not broken, this Hit must match the Event that we still have in memory. So, we want to attach the corresponding order and time info. // Note that the Hit tree also uses &OrderTrue, &TimeDiff and &HitTime as the locations where the data to be added to the tree is stored. Hopefully this means that I can just use Fill and it'll work. Note that I've read in the original Hit info. // Here, we check if the strip is noisy or not, and set the BadStrip flag appropriately. Need to check the hit position, PosXHit. We loop over all the strips for the current sensor. BadStrip=0; for(strip = 0; strip < num_noisystrips ; strip++){ if (noisyStrips[sensor][strip]==PosXHit) BadStrip=1; } tsortedHit->Fill(); // Fill the Hit tree ++iHit; // Move on to the next entry in the sorted hit tree. Note that if the BCntLoop comparison fails, then we'll stick with the same event till the next one. This should work fine, but be on the lookout for bugs! } } // write the histos once this is finished tsortedEvent->Write(); tsortedHit->Write(); if(checker==0){ cout << "LCMS trees" << endl; } else{ cout << "Cluster trees" << endl; } cout << sensorName[sensor] <<" done" << endl; } // End loop over all sensors } // End loop over both checkers // Write some output info cout << "No of entries in detector file: " << nentriesEvent << endl; }