From a1990535ddf2cfd25bfbda1d8fa3acc6da8f3520 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 08:18:32 -0500 Subject: [PATCH 001/163] Update ClusterFinderConfig Narrow cluster window - typical use is 5 hits in 50ns, not 5 hits in 100ns --- configfiles/BeamClusterAnalysis/ClusterFinderConfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configfiles/BeamClusterAnalysis/ClusterFinderConfig b/configfiles/BeamClusterAnalysis/ClusterFinderConfig index 337d7fc2e..c13622045 100644 --- a/configfiles/BeamClusterAnalysis/ClusterFinderConfig +++ b/configfiles/BeamClusterAnalysis/ClusterFinderConfig @@ -3,9 +3,9 @@ verbosity 0 HitStore Hits #Either MCHits or Hits (accessed in ANNIEEvent store) OutputFile BeamRun_ClusterFinder_DefaultOutput #Output root prefix name for the current run -ClusterFindingWindow 100 # in ns, size of the window used to "clusterize" +ClusterFindingWindow 50 # in ns, size of the window used to "clusterize" AcqTimeWindow 70000 # in ns, size of the acquisition window -ClusterIntegrationWindow 100 # in ns, all hits with +/- 1/2 of this window are considered in the cluster +ClusterIntegrationWindow 50 # in ns, all hits with +/- 1/2 of this window are considered in the cluster MinHitsPerCluster 5 # group of hits are considered clusters above this amount of hits end_of_window_time_cut 0.95 # from o to 1, length of the window you want to loop over with respect to acq. window (1 for full window, 0.95 for 95% from the start) Plots2D 0 #Draw 2D charge-vs-time plots? From 1878409dbda3a68d583ec6ae55cff959b10204a8 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 08:20:27 -0500 Subject: [PATCH 002/163] Update EventSelectorConfig New timing offsets moved the PMTs "back" by an average of ~10ns. When looking for PMT/MRD coincidence, we this need to adjust this offset value. --- configfiles/BeamClusterAnalysis/EventSelectorConfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configfiles/BeamClusterAnalysis/EventSelectorConfig b/configfiles/BeamClusterAnalysis/EventSelectorConfig index 73250c81d..a711f08bf 100644 --- a/configfiles/BeamClusterAnalysis/EventSelectorConfig +++ b/configfiles/BeamClusterAnalysis/EventSelectorConfig @@ -19,7 +19,7 @@ RecoFVCut 0 NHitCut 0 NHitmin 4 #Minimum number of hit digits PMTMRDCoincCut 0 -PMTMRDOffset 745 +PMTMRDOffset 755 PromptTrigOnly 0 TriggerWord -1 SaveStatusToStore 1 From 92f04734e282ef14706d28da12203235e7aaba0f Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 08:25:25 -0500 Subject: [PATCH 003/163] Update ClusterClassifiers.cpp With new gains calibration we now have 121 active PMTs instead of 123. Adjust charge balance parameter to reflect the number of active PMTs that could capture light. In the future, will alter this to read in the channel keys so that it automatically grabs the correct number of active PMTs. --- UserTools/ClusterClassifiers/ClusterClassifiers.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/UserTools/ClusterClassifiers/ClusterClassifiers.cpp b/UserTools/ClusterClassifiers/ClusterClassifiers.cpp index 6b8fb705f..2120db005 100644 --- a/UserTools/ClusterClassifiers/ClusterClassifiers.cpp +++ b/UserTools/ClusterClassifiers/ClusterClassifiers.cpp @@ -222,8 +222,8 @@ double ClusterClassifiers::CalculateChargeBalance(std::vector cluster_hits) total_Q+= tube_charge; total_QSquared += (tube_charge * tube_charge); } - //FIXME: Need a method to have the 123 be equal to the number of operating detectors - double charge_balance = sqrt((total_QSquared)/(total_Q*total_Q) - (1./123.)); + //FIXME: Need a method to have the 1/N be equal to the number of operating detectors + double charge_balance = sqrt((total_QSquared)/(total_Q*total_Q) - (1./121.)); if(verbosity>4) std::cout << "ClusterClassifiers Tool: Calculated charge balance of " << charge_balance << std::endl; return charge_balance; } @@ -249,8 +249,8 @@ double ClusterClassifiers::CalculateChargeBalanceMC(std::vector cluster_h total_Q+= tube_charge; total_QSquared += (tube_charge * tube_charge); } - //FIXME: Need a method to have the 123 be equal to the number of operating detectors - double charge_balance = sqrt((total_QSquared)/(total_Q*total_Q) - (1./123.)); + //FIXME: Need a method to have the 1/N be equal to the number of operating detectors + double charge_balance = sqrt((total_QSquared)/(total_Q*total_Q) - (1./121.)); if(verbosity>4) std::cout << "ClusterClassifiers Tool: Calculated charge balance of " << charge_balance << std::endl; return charge_balance; } From 2d8dfd8d9e53c3513d409c8915a4f4546a5cfe56 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 09:10:37 -0500 Subject: [PATCH 004/163] Update ClusterFinder.cpp Fixed issues seen with ClusterFinder and the omission of charge for MC Hits: - Change MC hit time away from 2ns discretization, as the new data hit times are float values. - As a result, need to change for loop to not just grab integer hit times (old), but also grab float hit times. - MC Hits with times < 0 were being ignored due to a variable set to 0. Tool now keeps all hit times, even if they are negative due to time smearing. - Reduce first-photon effect by modifying how hit timing is assigned for a "pulse"/digit. Followed what the tool DigitBuilder used: median photon hit time as the "pulse" time. Also, - In Data, mandate hits need to be > 0 (there is a weird spike at 0 in cluster times that are from this and are likely unphysical) TODO: Potentially expand the MC "pulse" integration window from 10ns to something larger. Average charge per hit is lower and total number of hits slightly higher in MC than data, indicating the pulse window may be too narrow and is cutting what should be one pulse into two. Need to check with calibration to see what the average pulse window length is for ~SPE pulses. --- UserTools/ClusterFinder/ClusterFinder.cpp | 99 ++++++++++++++++++----- 1 file changed, 77 insertions(+), 22 deletions(-) diff --git a/UserTools/ClusterFinder/ClusterFinder.cpp b/UserTools/ClusterFinder/ClusterFinder.cpp index f88ca62c6..77b5aa811 100644 --- a/UserTools/ClusterFinder/ClusterFinder.cpp +++ b/UserTools/ClusterFinder/ClusterFinder.cpp @@ -211,39 +211,85 @@ bool ClusterFinder::Execute(){ std::vector datalike_hits; std::vector datalike_hits_charge; for (MCHit &ahit : ThisPMTHits){ - //std::cout <<"Key: "< 2000.) std::cout <<"Found hit later than 2us! Hit time : "< combine multiple photons if they are within a 10ns range - //hit times can only be recorded with 2ns precision --> possible times are 0ns, 2ns, 4ns, ... - hits_2ns_res.push_back(2*(int(ahit.GetTime())/2.)+(int(ahit.GetTime())%2)); + hits_2ns_res.push_back(ahit.GetTime()); hits_2ns_res_charge.push_back(ahit.GetCharge()); } } //Combine multiple MC hits to one pulse std::sort(hits_2ns_res.begin(),hits_2ns_res.end()); - for (int i_hit=0; i_hit < (int) hits_2ns_res.size(); i_hit++){ - double hit1 = hits_2ns_res.at(i_hit); - if (datalike_hits.size()==0) { - datalike_hits.push_back(hit1); - datalike_hits_charge.push_back(hits_2ns_res_charge.at(i_hit)); - } - else { + std::vector temp_times; + double temp_charges = 0.0; + double mid_time; + if (verbose > 0){ + std::cout << " " << std::endl; + std::cout << hits_2ns_res.size() << " total photon hits(s)" << std::endl; + } + + if (hits_2ns_res.size() > 0){ + for (int i_hit=0; i_hit < (int) hits_2ns_res.size(); i_hit++){ + double hit1 = hits_2ns_res.at(i_hit); + if (temp_times.size()==0) { + temp_times.push_back(hit1); + temp_charges += hits_2ns_res_charge.at(i_hit); + } + + else { bool new_pulse = false; - for (int j_hit=0; j_hit < (int) datalike_hits.size(); j_hit++){ - if (fabs(datalike_hits.at(j_hit)-hit1)<10.) { + if (fabs(temp_times[0]-hit1)<10.) { new_pulse=false; - datalike_hits_charge.at(j_hit)+=hits_2ns_res_charge.at(i_hit); - break; + temp_charges+=hits_2ns_res_charge.at(i_hit); + temp_times.push_back(hit1); } else new_pulse=true; } + if (new_pulse) { - datalike_hits.push_back(hit1); //Only count as a new pulse if it was 10ns away from every other pulse - datalike_hits_charge.push_back(hits_2ns_res_charge.at(i_hit)); + // following the DigitBuilder tool --> take median photon hit time as the hit time of the "pulse" + if (temp_times.size() % 2 == 0){ + mid_time = (temp_times.at(temp_times.size()/2 - 1) + temp_times.at(temp_times.size()/2))/2; + } else{ + mid_time = temp_times.at(temp_times.size()/2); + } + + datalike_hits.push_back(mid_time); + datalike_hits_charge.push_back(temp_charges); + temp_times.clear(); + temp_charges = 0; + temp_times.push_back(hit1); + temp_charges += hits_2ns_res_charge.at(i_hit); + } } } + if (temp_times.size() % 2 == 0){ + mid_time = (temp_times.at(temp_times.size()/2 - 1) + temp_times.at(temp_times.size()/2))/2; + } else{ + mid_time = temp_times.at(temp_times.size()/2); + } + + datalike_hits.push_back(mid_time); + datalike_hits_charge.push_back(temp_charges); + + if (verbose > 0){ + std::cout << " " << std::endl; + std::cout << datalike_hits.size() << " MC pulse(s) identified from the raw photon hit(s)" << std::endl; + std::cout << "Pulse time(s):" << std::endl; + for (int ih=0; ih < (int) datalike_hits.size(); ih++){ + double junk = datalike_hits.at(ih); + std::cout << junk << " "; + } + std::cout << " " << std::endl; + std::cout << "Pulse charge(s):" << std::endl; + for (int ih=0; ih < (int) datalike_hits_charge.size(); ih++){ + double junk2 = datalike_hits_charge.at(ih); + std::cout << junk2 << " "; + } + std::cout << " " << std::endl; + } + } + for (int i_hit = 0; i_hit < (int) datalike_hits.size(); i_hit++){ //v_hittimes.push_back(ahit.GetTime()); // fill a vector with all hit times (unsorted) v_hittimes.push_back(datalike_hits.at(i_hit)); @@ -295,7 +341,7 @@ bool ClusterFinder::Execute(){ // Now sort the hit time array, fill the highest time in a new array until the old array is empty do { - double max_time = 0; + double max_time = -9999; int i_max_time = 0; for (std::vector::iterator it = v_hittimes.begin(); it != v_hittimes.end(); ++it) { if (*it > max_time) { @@ -321,12 +367,21 @@ bool ClusterFinder::Execute(){ } thiswindow_Nhits = 0; v_mini_hits.clear(); - for (double j_time = *it; j_time < *it + ClusterFindingWindow; j_time+=2){ // loops through times in the window and check if there's a hit at this time + for (double j_time = *it; j_time < *it + ClusterFindingWindow; j_time+=1){ // loops through times in the window and check if there's a hit at this time for(std::vector::iterator it2 = v_hittimes_sorted.begin(); it2 != v_hittimes_sorted.end(); ++it2) { - if (*it2 == j_time) { - thiswindow_Nhits++; - v_mini_hits.push_back(*it2); + if(HitStoreName=="MCHits"){ + if (static_cast(j_time) == static_cast(*it2)) { // accept all hit times (some may be smeared to negative values) + thiswindow_Nhits++; + v_mini_hits.push_back(*it2); + } } + if(HitStoreName=="Hits"){ + if (*it2 > 0 && static_cast(j_time) == static_cast(*it2)) { // reject hit times in the data that are 0 + thiswindow_Nhits++; + v_mini_hits.push_back(*it2); + } + } + } } if (!v_mini_hits.empty()) { From 59aed694ff398ccce35e384aa5df09899196ec1a Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 09:15:06 -0500 Subject: [PATCH 005/163] Update ClusterFinderConfig Same as data - cluster window 50ns, looking for at least 5 hits --- configfiles/BeamClusterAnalysisMC/ClusterFinderConfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configfiles/BeamClusterAnalysisMC/ClusterFinderConfig b/configfiles/BeamClusterAnalysisMC/ClusterFinderConfig index 59ef4564a..b8c52e008 100644 --- a/configfiles/BeamClusterAnalysisMC/ClusterFinderConfig +++ b/configfiles/BeamClusterAnalysisMC/ClusterFinderConfig @@ -3,9 +3,9 @@ verbosity 0 HitStore MCHits #Either MCHits or Hits (accessed in ANNIEEvent store) OutputFile BeamRun_ClusterFinder_DefaultOutput #Output root prefix name for the current run -ClusterFindingWindow 100 # in ns, size of the window used to "clusterize" +ClusterFindingWindow 50 # in ns, size of the window used to "clusterize" AcqTimeWindow 70000 # in ns, size of the acquisition window -ClusterIntegrationWindow 100 # in ns, all hits with +/- 1/2 of this window are considered in the cluster +ClusterIntegrationWindow 50 # in ns, all hits with +/- 1/2 of this window are considered in the cluster MinHitsPerCluster 5 # group of hits are considered clusters above this amount of hits end_of_window_time_cut 0.95 # from o to 1, length of the window you want to loop over with respect to acq. window (1 for full window, 0.95 for 95% from the start) Plots2D 0 #Draw 2D charge-vs-time plots? From f930670796c4877e500d91089e2073451010dcc4 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 09:18:00 -0500 Subject: [PATCH 006/163] Update ClusterFinderConfig Dropped line pointing to an external WCSim channel key ID (not really an issue cause they are the same) --- configfiles/BeamClusterAnalysisMC/ClusterFinderConfig | 1 - 1 file changed, 1 deletion(-) diff --git a/configfiles/BeamClusterAnalysisMC/ClusterFinderConfig b/configfiles/BeamClusterAnalysisMC/ClusterFinderConfig index b8c52e008..db22be6ca 100644 --- a/configfiles/BeamClusterAnalysisMC/ClusterFinderConfig +++ b/configfiles/BeamClusterAnalysisMC/ClusterFinderConfig @@ -9,4 +9,3 @@ ClusterIntegrationWindow 50 # in ns, all hits with +/- 1/2 of this window are co MinHitsPerCluster 5 # group of hits are considered clusters above this amount of hits end_of_window_time_cut 0.95 # from o to 1, length of the window you want to loop over with respect to acq. window (1 for full window, 0.95 for 95% from the start) Plots2D 0 #Draw 2D charge-vs-time plots? -ChankeyToPMTIDMap ./configfiles/EventDisplay/Data-RecoEvent/Chankey_WCSimID.dat From a42dc1a50e148fd879ad4713097212972c886273 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 09:20:35 -0500 Subject: [PATCH 007/163] Update DeadPMTIDs_p2v7.txt Updated mask to omit additional PMT to reflect new gains data. (PMT 337, aka 6 here, no longer active in data) --- configfiles/BeamClusterAnalysisMC/DeadPMTIDs_p2v7.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/configfiles/BeamClusterAnalysisMC/DeadPMTIDs_p2v7.txt b/configfiles/BeamClusterAnalysisMC/DeadPMTIDs_p2v7.txt index a5e258dad..4ce119098 100644 --- a/configfiles/BeamClusterAnalysisMC/DeadPMTIDs_p2v7.txt +++ b/configfiles/BeamClusterAnalysisMC/DeadPMTIDs_p2v7.txt @@ -1,4 +1,5 @@ 2 +6 11 14 15 From 9ac0e3b9460ba6024154a0d36229c0ebd190a7a1 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 09:27:54 -0500 Subject: [PATCH 008/163] Update LoadWCSimConfig Added a small description on where to find collaboration WCSim samples. Also cut down on commented lines --- configfiles/BeamClusterAnalysisMC/LoadWCSimConfig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/configfiles/BeamClusterAnalysisMC/LoadWCSimConfig b/configfiles/BeamClusterAnalysisMC/LoadWCSimConfig index defd4639b..a25d47f59 100644 --- a/configfiles/BeamClusterAnalysisMC/LoadWCSimConfig +++ b/configfiles/BeamClusterAnalysisMC/LoadWCSimConfig @@ -2,12 +2,12 @@ # all variables retrieved with m_variables.Get() must be defined here! verbose 1 -#InputFile /pnfs/annie/persistent/users/moflaher/wcsim/multipmt/tankonly/wcsim_25_04_19_ANNIEp2v6_nodigit_BNB_Water_10k_22-05-17/wcsim_0.1.9.root -#InputFile /annie/app/users/mnieslon/WCSim_build/wcsim_ambe_port5_z0_5000_0.root -InputFile /pnfs/annie/persistent/users/mnieslon/wcsim/output/tankonly/wcsim_ANNIEp2v7_beam/pmt-files/wcsim_beam_gst_1079_0_0.9000.root -#InputFile /pnfs/annie/persistent/users/mnieslon/wcsim/output/tankonly/wcsim_ANNIEp2v7_beam/pmt-files/wcsim_beam_gst_1079_9_0.9009.root -#InputFile /annie/app/users/mnieslon/WCSim_build/wcsim_michel_1000_0.root -#InputFile /pnfs/annie/persistent/users/mnieslon/wcsim/output/tankonly/wcsim_ANNIEp2v7_throughgoing/wcsim_throughgoing_muon_R2614_0.0.root +# WCSim collaboration samples using GENIE (from James): +#InputFile /pnfs/annie/persistent/simulations/wcsim/G1810a0211a/standard//pmt/wcsim_0.X.Y.root +# where X = run number for the corresponding GENIE file (gntp.X.ghep.root) +# Y = offset multiple for GENIE event number + +InputFile /pnfs/annie/persistent/users/moflaher/wcsim/multipmt/tankonly/wcsim_25_04_19_ANNIEp2v6_nodigit_BNB_Water_10k_22-05-17/wcsim_0.1.9.root WCSimVersion 3 ## should reflect the WCSim version of the files being loaded HistoricTriggeroffset 0 ## time offset of digits relative to the trigger From d43b389ba5da5a7c102da80cbd221b2e0b771e26 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 09:41:01 -0500 Subject: [PATCH 009/163] Update LoadGenieEventConfig Updated tool config to read in new collaboration samples. Added description to each variable per doc 5230-v2 (LoadGenieEvent Tutorial) --- .../LoadGenieEventConfig | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/configfiles/BeamClusterAnalysisMC/LoadGenieEventConfig b/configfiles/BeamClusterAnalysisMC/LoadGenieEventConfig index 6e22a33ba..4bd3619c4 100644 --- a/configfiles/BeamClusterAnalysisMC/LoadGenieEventConfig +++ b/configfiles/BeamClusterAnalysisMC/LoadGenieEventConfig @@ -1,11 +1,24 @@ verbosity 2 -FluxVersion 0 # use 0 to load genie files based on bnb_annie_0000.root etc files - # use 1 to load files based on beammc_annie_0000.root etc files -#FileDir NA # specify "NA" for newer files: full path is saved in WCSim + +# Refers to format of flux file used to generate GENIE sample (bnb or gsimple) +FluxVersion 1 # use 0 to load genie files based on bnb_annie_0000.root etc files (bnb/redecay/dk2nu flux format) + # use 1 to load files based on beammc_annie_0000.root etc files (generated by Zarko, gsimple flux format) + # - All GENIE (and WCSim) files generated by James uses gsimple (1) format + +# Path to directory of GENIE files +#FileDir NA # special option to load path from associated WCSim (Not recommended) +#FileDir /pnfs/annie/persistent/simulations/genie3/G1810a0211a/standard/ FileDir /pnfs/annie/persistent/users/vfischer/genie_files/BNB_Water_10k_22-05-17 -#FileDir /pnfs/annie/persistent/users/moflaher/genie/BNB_World_10k_11-03-18_gsimpleflux -FilePattern gntp.197.ghep.root -#FilePattern LoadWCSimTool ## use this pattern to load corresponding genie info with the LoadWCSimTool - ## N.B: FileDir must still be specified for now! (WCSim files do not record their directory) -ManualFileMatching 0 -EventOffset 0 + +# Name of GENIE file to open +FilePattern gntp.99.ghep.root # gntp.[run_number].ghep.root +#FilePattern LoadWCSimTool # special option to load GENIE events corresponding to WCSim events + +# Option to match GENIE events to WCSim events without using file path saved in WCSim file +ManualFileMatching 1 # 0 (false) - no manual matching, 1 (true) - uses FileDir and info from WCSim file name to find GENIE files/events - strongly recommended to use (1)! (as of Aug 2023) + +# Number of events in the WCSim file (used for offsetting the GENIE file event when used in conjunction with ManualFileMatching) +FileEvents 1000 # 1000 for James' WCSim files, 500 for Marcus' files + +# Number to offset the first loaded GENIE event (for usage without ManualFileMatching) - 0 by default +EventOffset 0 From c1a66b8bc34dd00a007d08edb923568e159786b5 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 09:42:51 -0500 Subject: [PATCH 010/163] Update PhaseIITreeMakerConfig In prep for whenever we have tank reco available --- configfiles/BeamClusterAnalysisMC/PhaseIITreeMakerConfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configfiles/BeamClusterAnalysisMC/PhaseIITreeMakerConfig b/configfiles/BeamClusterAnalysisMC/PhaseIITreeMakerConfig index 29999cdee..138764f15 100644 --- a/configfiles/BeamClusterAnalysisMC/PhaseIITreeMakerConfig +++ b/configfiles/BeamClusterAnalysisMC/PhaseIITreeMakerConfig @@ -11,6 +11,7 @@ SiPMPulseInfo_fill 0 fillCleanEventsOnly 0 MCTruth_fill 1 Reco_fill 0 +TankReco_fill 0 RecoDebug_fill 0 muonTruthRecoDiff_fill 0 IsData 0 From c1556a8ceeeeb2be2a4f57ddd7dbce950654b64a Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 09:43:29 -0500 Subject: [PATCH 011/163] Update LoadGeometryConfig new gains --- configfiles/BeamClusterAnalysisMC/LoadGeometryConfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configfiles/BeamClusterAnalysisMC/LoadGeometryConfig b/configfiles/BeamClusterAnalysisMC/LoadGeometryConfig index 894092ba3..c64227136 100644 --- a/configfiles/BeamClusterAnalysisMC/LoadGeometryConfig +++ b/configfiles/BeamClusterAnalysisMC/LoadGeometryConfig @@ -4,5 +4,5 @@ FACCMRDGeoFile ./configfiles/LoadGeometry/FullMRDGeometry.csv DetectorGeoFile ./configfiles/LoadGeometry/DetectorGeometrySpecs.csv LAPPDGeoFile ./configfiles/LoadGeometry/LAPPDGeometry.csv TankPMTGeoFile ./configfiles/LoadGeometry/FullTankPMTGeometry.csv -TankPMTGainFile ./configfiles/LoadGeometry/ChannelSPEGains_BeamRun20192020.csv +TankPMTGainFile ./configfiles/LoadGeometry/ChannelSPEGains2023.csv AuxiliaryChannelFile ./configfiles/LoadGeometry/AuxChannels.csv From 7e6f6a3b3157977a06b235af6fd935f76081e79d Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 09:47:48 -0500 Subject: [PATCH 012/163] Update DeadPMTIDs_p2v7.txt Updated new inactive PMT from the gains calibration --- configfiles/LoadWCSim/DeadPMTIDs_p2v7.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/configfiles/LoadWCSim/DeadPMTIDs_p2v7.txt b/configfiles/LoadWCSim/DeadPMTIDs_p2v7.txt index a5e258dad..4ce119098 100644 --- a/configfiles/LoadWCSim/DeadPMTIDs_p2v7.txt +++ b/configfiles/LoadWCSim/DeadPMTIDs_p2v7.txt @@ -1,4 +1,5 @@ 2 +6 11 14 15 From 7c6feeb20de3a50ebc8837541acd6a28a5f1233f Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 09:48:55 -0500 Subject: [PATCH 013/163] Update LoadWCSimConfig Updated config to include paths to latest collaboration samples --- configfiles/LoadWCSim/LoadWCSimConfig | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/configfiles/LoadWCSim/LoadWCSimConfig b/configfiles/LoadWCSim/LoadWCSimConfig index c142231f6..a25d47f59 100644 --- a/configfiles/LoadWCSim/LoadWCSimConfig +++ b/configfiles/LoadWCSim/LoadWCSimConfig @@ -2,17 +2,19 @@ # all variables retrieved with m_variables.Get() must be defined here! verbose 1 -#InputFile /pnfs/annie/persistent/users/moflaher/wcsim/lappd/tankonly/wcsim_lappd_tankonly_24-09-17_BNB_Water_10k_22-05-17/wcsim_0.0.0.root -#InputFile /pnfs/annie/persistent/users/moflaher/wcsim/lappd/tankonly/wcsim_lappd_tankonly_03-05-17_rhatcher/wcsim_0.1000.root ## first of the DOE proposal files -#InputFile /pnfs/annie/persistent/users/moflaher/wcsim/multipmt/tankonly/wcsim_3-12-18_ANNIEp2v6_BNB_Water_10k_22-05-17/wcsim_0.0.0.root -#InputFile /pnfs/annie/persistent/users/moflaher/wcsim/multipmt/tankonly/wcsim_25_04_19_ANNIEp2v6_nodigit_BNB_Water_10k_22-05-17/wcsim_0.0.0.root -InputFile ./25_04_19_wcsim_0.0.0.root +# WCSim collaboration samples using GENIE (from James): +#InputFile /pnfs/annie/persistent/simulations/wcsim/G1810a0211a/standard//pmt/wcsim_0.X.Y.root +# where X = run number for the corresponding GENIE file (gntp.X.ghep.root) +# Y = offset multiple for GENIE event number + +InputFile /pnfs/annie/persistent/users/moflaher/wcsim/multipmt/tankonly/wcsim_25_04_19_ANNIEp2v6_nodigit_BNB_Water_10k_22-05-17/wcsim_0.1.9.root WCSimVersion 3 ## should reflect the WCSim version of the files being loaded HistoricTriggeroffset 0 ## time offset of digits relative to the trigger UseDigitSmearedTime 1 ## whether to use smeared digit time (T), or true time of first photon (F) -LappdNumStrips 56 ## num channels to construct from each LAPPD +LappdNumStrips 60 ## num channels to construct from each LAPPD LappdStripLength 100 ## relative x position of each LAPPD strip, for dual-sided readout [mm] LappdStripSeparation 10 ## stripline separation, for calculating relative y position of each LAPPD strip [mm] -PMTMask ./configfiles/LoadWCSim/DeadPMTIDs_p2v7.txt ## Which PMTs should be masked out? / are dead? -ChankeyToPMTIDMap ./configfiles/LoadWCSim/Chankey_WCSimID_v7.txt +PMTMask configfiles/BeamClusterAnalysisMC/DeadPMTIDs_p2v7.txt ## Which PMTs should be masked out? / are dead? +ChankeyToPMTIDMap ./configfiles/BeamClusterAnalysisMC/Chankey_WCSimID_v7.txt +SplitSubTriggers 0 # should subtriggers be loaded in separate Execute steps? From 1c749e34225c347847521ba547e40f553a7ad809 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 09:53:37 -0500 Subject: [PATCH 014/163] Add files via upload PMT timing offsets derived from Laser calibration data. These offsets should be considered precision software corrections on top of the previous firmware corrections at the ADC level to correct for the large cabling delays. --- .../LoadGeometry/TankPMTTimingOffsets.csv | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 configfiles/LoadGeometry/TankPMTTimingOffsets.csv diff --git a/configfiles/LoadGeometry/TankPMTTimingOffsets.csv b/configfiles/LoadGeometry/TankPMTTimingOffsets.csv new file mode 100644 index 000000000..cdfed43c9 --- /dev/null +++ b/configfiles/LoadGeometry/TankPMTTimingOffsets.csv @@ -0,0 +1,120 @@ +##Channel,PMT_location,offset_value(ns),offset_std(ns),notes +332,Bottom,15.25,1.31,unreliable +334,Bottom,15.55,0.57,ok +335,Bottom,8.34,1.36,unreliable +336,Bottom,15.41,1.33,unreliable +338,Bottom,10.15,1.85,unreliable +339,Bottom,8.57,0.95,ok +340,Bottom,8.66,1.29,unreliable +341,Bottom,11.51,1.95,unreliable +343,Bottom,14.24,0.33,ok (low statistics) +344,Bottom,13.41,2.11,unreliable (low statistics) +347,Bottom,10.6,1.92,unreliable +348,Bottom,7.08,2.1,unreliable +350,Bottom,3.15,1.03,ok +351,Bottom,9.16,1.05,ok +353,Top,16.13,1.14,ok (low statistics) +354,Top,10.44,1.55,unreliable +355,Top,14.27,2.08,ok +356,Top,12.88,1.48,unreliable +357,Top,8.66,2.21,ok +358,Top,8.13,1.46,ok +360,Top,8.04,2.56,ok +361,Top,14.42,1.5,unreliable +362,Top,4.88,1.88,ok +363,Top,16.96,2.24,ok +364,Top,16.22,2.83,ok +365,Top,12.43,1.53,unreliable +366,Top,11.78,1.48,ok +367,Top,14.19,2.02,ok +368,Top,10.45,1.87,ok +369,Top,18.45,1.87,ok +370,Top,18.82,2.75,ok +371,Top,16.93,1.91,ok +372,Barrel,9.13,0.9,ok +373,Barrel,7.84,0.93,ok +374,Barrel,4.81,1.21,ok +375,Barrel,1.03,1.0,ok +376,Barrel,15.7,1.27,ok +377,Barrel,16.4,0.85,ok +378,Barrel,6.5,0.87,ok +379,Barrel,9.15,0.94,ok +380,Barrel,6.97,0.9,ok +381,Barrel,4.75,1.0,ok +382,Barrel,16.09,1.32,ok +383,Barrel,11.66,1.37,ok +384,Barrel,7.84,0.98,ok +385,Barrel,5.82,1.31,ok +386,Barrel,5.99,1.29,ok +387,Barrel,5.15,0.87,ok +388,Barrel,10.01,0.92,ok +389,Barrel,7.85,1.28,ok +390,Barrel,9.93,0.95,ok +391,Barrel,11.64,1.36,ok +392,Barrel,9.64,1.02,ok +393,Barrel,3.16,1.41,ok +394,Barrel,9.26,0.97,ok +395,Barrel,11.18,1.41,ok +396,Barrel,8.17,1.37,ok +397,Barrel,6.0,0.99,ok +398,Barrel,10.38,0.89,ok +399,Barrel,14.8,1.01,ok +400,Barrel,12.03,0.97,ok +401,Barrel,13.92,0.96,ok +402,Barrel,11.0,0.9,ok +403,Barrel,11.57,1.28,ok +404,Barrel,12.36,0.9,ok +405,Barrel,6.9,1.4,ok +406,Barrel,10.33,0.83,ok +407,Barrel,16.25,0.9,ok +409,Barrel,11.86,1.25,ok +410,Barrel,9.14,1.29,ok +411,Barrel,6.38,0.85,ok +412,Barrel,6.22,0.82,ok +413,Barrel,4.1,1.27,ok +414,Barrel,16.84,1.32,ok +415,Barrel,12.67,0.97,ok +417,Barrel,7.98,1.45,ok +418,Barrel,7.96,2.28,unreliable +419,Barrel,17.9,1.92,ok +420,Barrel,6.82,1.96,ok +421,Barrel,11.13,1.96,ok +422,Barrel,11.53,2.0,ok +423,Barrel,9.71,2.84,ok +424,Barrel,8.68,1.92,ok +425,Barrel,12.89,2.32,ok +426,Barrel,10.84,2.51,ok +427,Barrel,7.92,1.37,ok +428,Barrel,10.07,2.24,ok +429,Barrel,12.23,1.01,ok +430,Barrel,7.6,2.0,ok +432,Barrel,11.94,1.57,ok +433,Barrel,12.1,1.47,ok +434,Barrel,9.58,1.85,ok +435,Barrel,12.41,1.5,ok +436,Barrel,8.17,1.43,ok +437,Barrel,4.91,1.57,ok +438,Barrel,14.03,2.01,ok +439,Barrel,10.26,1.57,ok +440,Barrel,5.55,2.54,ok +441,Barrel,9.52,2.28,ok +442,Barrel,12.17,1.58,ok +443,Barrel,16.01,2.88,ok +446,Barrel,10.01,2.45,ok +447,Barrel,12.17,1.49,ok +448,Barrel,11.31,1.55,ok +449,Barrel,13.17,1.32,ok +450,Barrel,5.7,1.88,ok +451,Barrel,6.34,1.46,ok +452,Barrel,12.1,1.42,ok +453,Barrel,0.0,1.55,ok +454,Barrel,8.29,1.04,ok +455,Barrel,17.55,1.42,ok +456,Barrel,9.53,1.53,unreliable +457,Barrel,10.18,1.6,ok +458,Barrel,10.18,1.54,ok +459,Barrel,9.69,1.99,ok +460,Barrel,5.08,1.04,ok +461,Barrel,9.32,1.59,ok +462,Barrel,17.05,2.13,ok +463,Barrel,16.18,1.44,ok From 45925e1e5fd7527eab107b60207176cc9cb4d13b Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 10:01:15 -0500 Subject: [PATCH 015/163] Update LoadGeometry.h Updated header file with PMT timing offsets --- UserTools/LoadGeometry/LoadGeometry.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/UserTools/LoadGeometry/LoadGeometry.h b/UserTools/LoadGeometry/LoadGeometry.h index 9f666ed10..9f4e2210a 100644 --- a/UserTools/LoadGeometry/LoadGeometry.h +++ b/UserTools/LoadGeometry/LoadGeometry.h @@ -36,6 +36,7 @@ class LoadGeometry: public Tool { bool ParseAuxChannelDataEntry(std::vector SpecLine, std::vector AuxChannelLegendEntries); void LoadTankPMTGains(); + void LoadTankPMTTimingOffsets(); Geometry* AnnieGeometry; @@ -49,6 +50,7 @@ class LoadGeometry: public Tool { std::string fFACCMRDGeoFile; std::string fTankPMTGeoFile; std::string fTankPMTGainFile; + std::string fTankPMTTimingOffsetFile; std::string fAuxChannelFile; std::string fLAPPDGeoFile; std::string fDetectorGeoFile; @@ -66,6 +68,7 @@ class LoadGeometry: public Tool { std::map>* ChannelNumToTankPMTCrateSpaceMap; std::map>* AuxChannelNumToCrateSpaceMap; std::map* ChannelNumToTankPMTSPEChargeMap; + std::map* ChannelNumToTankPMTTimingOffsetMap; std::map* AuxChannelNumToTypeMap; std::map,int>* LAPPDCrateSpaceToChannelNumMap; From 26f352cf21e241a88caf365fe302e8e6b63351a9 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 10:02:58 -0500 Subject: [PATCH 016/163] Update LoadGeometryConfig Path to PMT timing offset .csv file --- configfiles/LoadGeometry/LoadGeometryConfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configfiles/LoadGeometry/LoadGeometryConfig b/configfiles/LoadGeometry/LoadGeometryConfig index 693f546d2..79efc3811 100644 --- a/configfiles/LoadGeometry/LoadGeometryConfig +++ b/configfiles/LoadGeometry/LoadGeometryConfig @@ -6,4 +6,5 @@ DetectorGeoFile ./configfiles/LoadGeometry/DetectorGeometrySpecs.csv LAPPDGeoFile ./configfiles/LoadGeometry/LAPPDGeometry.csv TankPMTGeoFile ./configfiles/LoadGeometry/FullTankPMTGeometry.csv TankPMTGainFile ./configfiles/LoadGeometry/ChannelSPEGains2023.csv +TankPMTTimingOffsetFile ./configfiles/LoadGeometry/TankPMTTimingOffsets.csv AuxiliaryChannelFile ./configfiles/LoadGeometry/AuxChannels.csv From 81079fbe237299d2374a52a4ad10b34324bbaf4a Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 10:05:13 -0500 Subject: [PATCH 017/163] Update EventSelector.cpp 1. Updated default offset value (745) to 755 to account for new timing offsets of the PMTs. 2. In the new gains file, there are measurements for the 121 active PMTs. Two PMTs were deemed "inactive" and are no longer included. (Old file used to have 123 active PMTs). These PMTs were omitted as no data/hits were recorded on them during the source calibration. In principle there should only be hits in the active PMTs. However, even though there were no data/hits recorded in those tubes for the source calibration, for very energetic events occasionally one of the since "inactived" PMTs registers a hit for some reason and tries to access the map, which crashes this tool. Just added a condition that the channel must exist in the map in order to count that hit. --- UserTools/EventSelector/EventSelector.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/UserTools/EventSelector/EventSelector.cpp b/UserTools/EventSelector/EventSelector.cpp index 4563381a5..4ef5a779f 100644 --- a/UserTools/EventSelector/EventSelector.cpp +++ b/UserTools/EventSelector/EventSelector.cpp @@ -14,7 +14,7 @@ bool EventSelector::Initialise(std::string configfile, DataModel &data){ fPMTMRDOffset = false; fIsMC = true; - fPMTMRDOffset = 745; + fPMTMRDOffset = 755; fRecoPDG = -1; //Get the tool configuration variables @@ -695,8 +695,15 @@ bool EventSelector::EventSelectionByPMTMRDCoinc() { for (unsigned int i_hit = 0; i_hit < Hits.size(); i_hit++){ time_temp+=Hits.at(i_hit).GetTime(); int tube = Hits.at(i_hit).GetTubeId(); - double charge_pe = Hits.at(i_hit).GetCharge()/ChannelNumToTankPMTSPEChargeMap->at(tube); - charge_temp+=charge_pe; + // check if PMT is present in the map before accessing it + auto it = ChannelNumToTankPMTSPEChargeMap->find(tube); + if (it != ChannelNumToTankPMTSPEChargeMap->end()) { + double charge_pe = Hits.at(i_hit).GetCharge() / it->second; + charge_temp += charge_pe; + } else { + std::cerr << "PMT channel with hit not found in ChannelNumToTankPMTSPEChargeMap. Skipping this hit." << std::endl; + continue; + } } if (Hits.size()>0) time_temp/=Hits.size(); vec_pmtclusters_charge->push_back(charge_temp); From 7d0aaf5f775f3682993e0ef8bfcd98dde3ceb210 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 10:11:48 -0500 Subject: [PATCH 018/163] Update LoadGeometry.cpp Adjust LoadGeometry to include new PMT Timing offsets from .csv file, derived from the laser source calibration. --- UserTools/LoadGeometry/LoadGeometry.cpp | 32 +++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/UserTools/LoadGeometry/LoadGeometry.cpp b/UserTools/LoadGeometry/LoadGeometry.cpp index b93355c1b..de93f7e7b 100644 --- a/UserTools/LoadGeometry/LoadGeometry.cpp +++ b/UserTools/LoadGeometry/LoadGeometry.cpp @@ -20,6 +20,7 @@ bool LoadGeometry::Initialise(std::string configfile, DataModel &data){ m_variables.Get("FACCMRDGeoFile", fFACCMRDGeoFile); m_variables.Get("TankPMTGeoFile", fTankPMTGeoFile); m_variables.Get("TankPMTGainFile", fTankPMTGainFile); + m_variables.Get("TankPMTTimingOffsetFile", fTankPMTTimingOffsetFile); m_variables.Get("AuxiliaryChannelFile", fAuxChannelFile); m_variables.Get("LAPPDGeoFile", fLAPPDGeoFile); m_variables.Get("DetectorGeoFile", fDetectorGeoFile); @@ -58,6 +59,12 @@ bool LoadGeometry::Initialise(std::string configfile, DataModel &data){ return false; } + if(!this->FileExists(fTankPMTTimingOffsetFile)){ + Log("LoadGeometry Tool: File for Tank PMT Timing offsets does not exist!",v_error,verbosity); + if (verbosity > 0) std::cout << "Filepath was... " << fTankPMTTimingOffsetFile << std::endl; + return false; + } + if(!this->FileExists(fAuxChannelFile)){ Log("LoadGeometry Tool: File for Auxiliary Channels does not exist!",v_error,verbosity); if (verbosity > 0) std::cout << "Filepath was... " << fAuxChannelFile << std::endl; @@ -69,6 +76,7 @@ bool LoadGeometry::Initialise(std::string configfile, DataModel &data){ MRDChannelNumToCrateSpaceMap = new std::map>; TankPMTCrateSpaceToChannelNumMap = new std::map,int>; ChannelNumToTankPMTSPEChargeMap = new std::map; + ChannelNumToTankPMTTimingOffsetMap = new std::map; ChannelNumToTankPMTCrateSpaceMap = new std::map>; AuxCrateSpaceToChannelNumMap = new std::map,int>; AuxChannelNumToTypeMap = new std::map; @@ -87,6 +95,9 @@ bool LoadGeometry::Initialise(std::string configfile, DataModel &data){ //Load TankPMT charge to PE conversion this->LoadTankPMTGains(); + //Load TankPMT timing offsets + this->LoadTankPMTTimingOffsets(); + //Load auxiliary and spare channels this->LoadAuxiliaryChannels(); @@ -100,6 +111,7 @@ bool LoadGeometry::Initialise(std::string configfile, DataModel &data){ m_data->CStore.Set("TankPMTCrateSpaceToChannelNumMap",TankPMTCrateSpaceToChannelNumMap); m_data->CStore.Set("ChannelNumToTankPMTCrateSpaceMap",ChannelNumToTankPMTCrateSpaceMap); m_data->CStore.Set("ChannelNumToTankPMTSPEChargeMap",ChannelNumToTankPMTSPEChargeMap); + m_data->CStore.Set("ChannelNumToTankPMTTimingOffsetMap",ChannelNumToTankPMTTimingOffsetMap); m_data->CStore.Set("AuxCrateSpaceToChannelNumMap",AuxCrateSpaceToChannelNumMap); m_data->CStore.Set("AuxChannelNumToCrateSpaceMap",AuxChannelNumToCrateSpaceMap); m_data->CStore.Set("AuxChannelNumToTypeMap",AuxChannelNumToTypeMap); @@ -906,3 +918,23 @@ void LoadGeometry::LoadTankPMTGains(){ } return; } + +void LoadGeometry::LoadTankPMTTimingOffsets(){ + ifstream myfile(fTankPMTTimingOffsetFile.c_str()); + std::string line; + if (myfile.is_open()){ + //Loop over lines, collect all detector data (should only be one line here) + while(getline(myfile,line)){ + if(verbosity>3) std::cout << line << std::endl; //has our stuff; + if(line.find("#")!=std::string::npos) continue; + std::vector DataEntries; + boost::split(DataEntries,line, boost::is_any_of(","), boost::token_compress_on); + int channelkey = -9999; + double TimingOffset = -9999.; + channelkey = std::stoul(DataEntries.at(0)); + TimingOffset= std::stod(DataEntries.at(2)); + ChannelNumToTankPMTTimingOffsetMap->emplace(channelkey,TimingOffset); + } + } + return; +} From b978fd9ed08c2d35d2bf25edf083c642bbc76edd Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 10:40:23 -0500 Subject: [PATCH 019/163] Update PhaseIIADCHitFinder.cpp - Grab new PMT timing offset values from .csv file to subtract from the hit times --> added this to all methods of hit finding - Instead of grabbing the x tick with the maximum ADC value as the hit time (always binned to 2ns), assign float hit times based when the pulse crosses 50% of its maximum above threshold. Currently only implemented for the Pulse Finding Approach "Threshold" and Pulse Window Type "Dynamic" (the default, used configuration of the code). TODO: - Add this hit timing approach to all configurations of the code. - (Maybe) per Bob's recommendation, it might be better to instead assign the hit time using the following: 1. get the time at 50% between peak and threshold 2. get the time at 20% " " " " 3. Draw a straight line between these two points to extrapolate the time to zero threshold This way it would lessen the effect of time shifts between large and small pulses. --- .../PhaseIIADCHitFinder.cpp | 86 +++++++++++++++++-- 1 file changed, 80 insertions(+), 6 deletions(-) diff --git a/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp b/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp index a7a4563ca..8be738345 100755 --- a/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp +++ b/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp @@ -71,6 +71,9 @@ bool PhaseIIADCHitFinder::Initialise(std::string config_filename, DataModel& dat // Get the Auxiliary channel types; identifies which channels are SiPM channels m_data->CStore.Get("AuxChannelNumToTypeMap",AuxChannelNumToTypeMap); + // Get the timing offsets + m_data->CStore.Get("ChannelNumToTankPMTTimingOffsetMap",ChannelKeyToTimingOffsetMap); + //Recreate maps that were deleted with ANNIEEvent->Delete() ANNIEEventBuilder tool hit_map = new std::map>; aux_hit_map = new std::map>; @@ -703,11 +706,21 @@ std::vector PhaseIIADCHitFinder::find_pulses_bywindow( // Convert the pulse integral to nC charge *= NS_PER_ADC_SAMPLE / ADC_IMPEDANCE; + // PMT Timing offsets + double timing_offset=0.0; + std::map::const_iterator it = ChannelKeyToTimingOffsetMap.find(channel_key); + if(it != ChannelKeyToTimingOffsetMap.end()){ //Timing offset is available + timing_offset = ChannelKeyToTimingOffsetMap.at(channel_key); + } else { + if(verbosity>2){ + std::cout << "Didn't find Timing offset for channel " << channel_key << std::endl; + } + } // Store the freshly made pulse in the vector of found pulses pulses.emplace_back(channel_key, - ( wmin * NS_PER_SAMPLE ), - peak_sample * NS_PER_SAMPLE, + ( wmin * NS_PER_SAMPLE )-timing_offset, + (peak_sample * NS_PER_SAMPLE)-timing_offset, calibrated_minibuffer_data.GetBaseline(), calibrated_minibuffer_data.GetSigmaBaseline(), raw_area, max_ADC, calibrated_amplitude, charge); @@ -805,10 +818,21 @@ std::vector PhaseIIADCHitFinder::find_pulses_bythreshold( // Convert the pulse integral to nC charge *= NS_PER_ADC_SAMPLE / ADC_IMPEDANCE; + // PMT Timing offsets + double timing_offset=0.0; + std::map::const_iterator it = ChannelKeyToTimingOffsetMap.find(channel_key); + if(it != ChannelKeyToTimingOffsetMap.end()){ //Timing offset is available + timing_offset = ChannelKeyToTimingOffsetMap.at(channel_key); + } else { + if(verbosity>2){ + std::cout << "Didn't find Timing offset for channel " << channel_key << std::endl; + } + } + // Store the freshly made pulse in the vector of found pulses pulses.emplace_back(channel_key, - ( pulse_start_sample * NS_PER_SAMPLE ), - peak_sample * NS_PER_SAMPLE, + ( pulse_start_sample * NS_PER_SAMPLE )-timing_offset, + (peak_sample * NS_PER_SAMPLE)-timing_offset, calibrated_minibuffer_data.GetBaseline(), calibrated_minibuffer_data.GetSigmaBaseline(), raw_area, max_ADC, calibrated_amplitude, charge); @@ -868,10 +892,60 @@ std::vector PhaseIIADCHitFinder::find_pulses_bythreshold( // very close together (i.e. if the end of one is just a few samples away // from the start of another) + // PMT Timing offsets + double timing_offset=0.0; + std::map::const_iterator it = ChannelKeyToTimingOffsetMap.find(channel_key); + if(it != ChannelKeyToTimingOffsetMap.end()){ //Timing offset is available + timing_offset = ChannelKeyToTimingOffsetMap.at(channel_key); + } else { + if(verbosity>2){ + std::cout << "Didn't find Timing offset for channel " << channel_key << std::endl; + } + } + + // New approach to hit timing to avoid 2ns bins - 50% threshold above baseline + // Look for where the ADC value crosses 50% of the maximum, assign hit time + // TODO: consider using an approach recommended by Bob: get time at 50%, get time at 20%, draw straight line in between and find time to zero threshold + const double threshold_percentage = 0.5; + unsigned short threshold_value = ((max_ADC - adc_threshold) * threshold_percentage) + adc_threshold; + double hit_time = peak_sample; + bool hit_time_found = false; + + // Find the first sample where the ADC value is above 50% + for (size_t p = peak_sample; p > pulse_start_sample; --p) { + if (raw_minibuffer_data.GetSample(p) < threshold_value) { + hit_time = p; + hit_time_found = true; + break; + } + } + + // Perform simple linear interpolation to find exact crossing point + if (hit_time_found) { + if(verbosity>4) std::cout << "Interpolating hit time..." << std::endl; + if (hit_time > pulse_start_sample && hit_time < pulse_end_sample) { + double x1 = hit_time; + double x2 = hit_time + 1.0; + unsigned short y1 = raw_minibuffer_data.GetSample(static_cast(x1)); + unsigned short y2 = raw_minibuffer_data.GetSample(static_cast(x2)); + hit_time = x1 + (threshold_value - y1) * (x2 - x1) / (y2 - y1); // linear interpolation + } + } + + if(verbosity>4) std::cout << "Hit time [ns] " << hit_time * NS_PER_ADC_SAMPLE << std::endl; + + if (hit_time < 0.0) { + // If for some reason the interpolation finds a negative time value (if the pulse is extremely early in the buffer), + // default to the peak time + std::cout << "Hit time is negative! Defaulting to peak time" << std::endl; + hit_time = peak_sample; + } + + // Store the freshly made pulse in the vector of found pulses pulses.emplace_back(channel_key, - ( pulse_start_sample * NS_PER_ADC_SAMPLE ), - peak_sample * NS_PER_ADC_SAMPLE, + ( pulse_start_sample * NS_PER_ADC_SAMPLE )-timing_offset, + (peak_sample * NS_PER_ADC_SAMPLE)-timing_offset, calibrated_minibuffer_data.GetBaseline(), calibrated_minibuffer_data.GetSigmaBaseline(), raw_area, max_ADC, calibrated_amplitude, charge); From fc9081e6b8d5e52dcaa005c0f3592298b2661fb3 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 10:42:56 -0500 Subject: [PATCH 020/163] Update PhaseIIADCHitFinder.h Added offset map to header --- UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.h b/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.h index d7af819c0..b3471d58e 100755 --- a/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.h +++ b/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.h @@ -59,7 +59,8 @@ class PhaseIIADCHitFinder : public Tool { std::map channel_threshold_map; std::map>> channel_window_map; bool eventbuilding_mode; - + + std::map ChannelKeyToTimingOffsetMap; std::map* AuxChannelNumToTypeMap; From 163cfd3e15549c270a95774b9bc38b404ccd8fe7 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 11:00:39 -0500 Subject: [PATCH 021/163] Add files via upload Old tool, new toolchain: output raw waveforms of PMT and aux channels from built, processed ANNIEEvents (that contain the raw waveforms). Useful to analyze PMT waveforms, as well as look at aux channel waveforms like the BoosterRWM and BoosterRF. --- configfiles/PrintADCData/LoadANNIEEventConfig | 4 ++ .../PrintADCData/PhaseIIADCCalibratorConfig | 15 +++++ .../PrintADCData/PhaseIIADCHitFinderConfig | 10 +++ configfiles/PrintADCData/PrintADCDataConfig | 11 ++++ configfiles/PrintADCData/README.md | 64 +++++++++++++++++++ configfiles/PrintADCData/ToolChainConfig | 26 ++++++++ configfiles/PrintADCData/ToolsConfig | 5 ++ configfiles/PrintADCData/my_inputs.txt | 1 + 8 files changed, 136 insertions(+) create mode 100644 configfiles/PrintADCData/LoadANNIEEventConfig create mode 100644 configfiles/PrintADCData/PhaseIIADCCalibratorConfig create mode 100644 configfiles/PrintADCData/PhaseIIADCHitFinderConfig create mode 100644 configfiles/PrintADCData/PrintADCDataConfig create mode 100644 configfiles/PrintADCData/README.md create mode 100644 configfiles/PrintADCData/ToolChainConfig create mode 100644 configfiles/PrintADCData/ToolsConfig create mode 100644 configfiles/PrintADCData/my_inputs.txt diff --git a/configfiles/PrintADCData/LoadANNIEEventConfig b/configfiles/PrintADCData/LoadANNIEEventConfig new file mode 100644 index 000000000..de401a767 --- /dev/null +++ b/configfiles/PrintADCData/LoadANNIEEventConfig @@ -0,0 +1,4 @@ +verbose 4 +EventOffset 0 +FileForListOfInputs ./configfiles/PrintADCData/my_inputs.txt +GlobalEvNr 1 # If multiple files are present, introduce a global event number across files? diff --git a/configfiles/PrintADCData/PhaseIIADCCalibratorConfig b/configfiles/PrintADCData/PhaseIIADCCalibratorConfig new file mode 100644 index 000000000..e67bc4513 --- /dev/null +++ b/configfiles/PrintADCData/PhaseIIADCCalibratorConfig @@ -0,0 +1,15 @@ +# PhaseIIADCCalibrator config file + +verbosity 0 + +BaselineEstimationType ze3ra_multi +NumBaselineSamples 15 +NumSubWaveforms 10 + +SamplesPerBaselineEstimate 2000 +BaselineUncertaintyTolerance 2 +PCritical 0.01 +MakeCalLEDWaveforms 0 + +EventBuilding 0 +ExecutesPerBuild 10 diff --git a/configfiles/PrintADCData/PhaseIIADCHitFinderConfig b/configfiles/PrintADCData/PhaseIIADCHitFinderConfig new file mode 100644 index 000000000..473dd1dc7 --- /dev/null +++ b/configfiles/PrintADCData/PhaseIIADCHitFinderConfig @@ -0,0 +1,10 @@ +verbosity 0 + +UseLEDWaveforms 0 + +PulseFindingApproach threshold +PulseWindowType dynamic +DefaultADCThreshold 7 +DefaultThresholdType relative + +EventBuilding 0 diff --git a/configfiles/PrintADCData/PrintADCDataConfig b/configfiles/PrintADCData/PrintADCDataConfig new file mode 100644 index 000000000..817d22b20 --- /dev/null +++ b/configfiles/PrintADCData/PrintADCDataConfig @@ -0,0 +1,11 @@ +verbosity 5 + +UseLEDWaveforms 0 # specifies whether to show or save full waveforms from the DAQ or the LED waveform windows + +OutputFile test # Base filename given to both the ROOT and txt file that are output from the tool + +SaveWaveforms 1 # Determines whether or not to save raw waveforms in the output ROOT file + +WavesWithPulsesOnly 0 # Controls whether or not to save only waveforms that have a pulse in them (determined by the hit finding tools) + +MaxWaveforms 1000 # Controls the number of raw waveforms to be saved to the output ROOT file. Used to keep the ROOT file from exploding under the sheer number of raw waveforms saved diff --git a/configfiles/PrintADCData/README.md b/configfiles/PrintADCData/README.md new file mode 100644 index 000000000..e9a5e6b21 --- /dev/null +++ b/configfiles/PrintADCData/README.md @@ -0,0 +1,64 @@ +# PrintADCData toolchain + +*********************** +# Description +********************** + +The `PrintADCData` toolchain is used to analyze properties in an ANNIEEvent booststore's RecoADCHits vector (and the Aux information). The tool specifically looks at the raw and calibrated waveforms for Tank PMTs and Aux channels and outputs information including: +* Example raw waveforms for all PMTs channels, and aux channels (BoosterRWM, BoosterRF) +* The number of waveforms collected for each channel +* The number of pulses collected for each channel +* The number of waveforms with at least one pulse for each channel +* 2D histograms of the hit occupancy in y vs, phi space + +************************ +# Data +************************ + +Two files are producing after running this toolchain: +* ROOT file with raw waveforms and the 2D hit occupancy histograms +* .txt file with the waveform/pulse info described above + +************************ +# Configuration of PrintADCData tool +************************ +``` + +UseLEDWaveforms [int] +Specifies whether to show and save full waveforms from the DAQ, or +the LED waveform windows produced from running +PhaseIIADCCalibrator with MakeLEDWaveforms set at 1. +1=Show/save LED waveforms, +0= Show/save raw waveforms. + +verbosity [int] +controls the amount of print output (0- lowest, 5-highest) + +OutputFile [string] +Base filename given to both the ROOT and text file that are output from the tool. + + +SaveWaveforms [bool] +Determines whether or not to save raw waveforms in the output ROOT file. +1 = yes, 0 = no + +WavesWithPulsesOnly [bool] +Controls whether or not to save only waveforms that have a pulse in them. Whether +or not the wave has a pulse is determined by logic output by the PhaseIIADCHitFinder +tool. + +MaxWaveforms [int] +Controls the number of raw waveform examples saved to the output ROOT file. +Used to keep the ROOT file from exploding under the sheer number of raw +waveforms saved. + +LEDsUsed [string] +Log string saved in the output text file to record what LEDs were used for the +run being processed. Will eventually be automated when the DAQ can control +the LEDs. + +LEDSetpoints [string] +Log string saved in the output text file to record what LED setpoints were used + for the run being processed. Will eventually be automated when the DAQ +can control the LEDs. +``` diff --git a/configfiles/PrintADCData/ToolChainConfig b/configfiles/PrintADCData/ToolChainConfig new file mode 100644 index 000000000..552a4ccf3 --- /dev/null +++ b/configfiles/PrintADCData/ToolChainConfig @@ -0,0 +1,26 @@ +#ToolChain dynamic setup file + +##### Runtime Parameters ##### +verbose 1 ## Verbosity level of ToolChain +error_level 0 # 0= do not exit, 1= exit on unhandled errors only, 2= exit on unhandled errors and handled errors +attempt_recover 1 ## 1= will attempt to finalise if an execute fails +remote_port 24002 +IO_Threads 1 ## Number of threads for network traffic (~ 1/Gbps) + +###### Logging ##### +log_mode Interactive # Interactive=cout , Remote= remote logging system "serservice_name Remote_Logging" , Local = local file log; +log_local_path ./log +log_service LogStore + + +###### Service discovery ##### Ignore these settings for local analysis +service_publish_sec -1 +service_kick_sec -1 + +##### Tools To Add ##### +Tools_File configfiles/PrintADCData/ToolsConfig ## list of tools to run and their config files + +##### Run Type ##### +Inline -1 ## number of Execute steps in program, -1 infinite loop that is ended by user +Interactive 0 ## set to 1 if you want to run the code interactively + diff --git a/configfiles/PrintADCData/ToolsConfig b/configfiles/PrintADCData/ToolsConfig new file mode 100644 index 000000000..57c6ac4db --- /dev/null +++ b/configfiles/PrintADCData/ToolsConfig @@ -0,0 +1,5 @@ +myLoadGeometry LoadGeometry configfiles/LoadGeometry/LoadGeometryConfig +myLoadANNIEEvent LoadANNIEEvent configfiles/PrintADCData/LoadANNIEEventConfig +myPhaseIIADCCalibrator PhaseIIADCCalibrator ./configfiles/PrintADCData/PhaseIIADCCalibratorConfig +myPhaseIIADCHitFinder PhaseIIADCHitFinder ./configfiles/PrintADCData/PhaseIIADCHitFinderConfig +myPrintADCData PrintADCData configfiles/PrintADCData/PrintADCDataConfig diff --git a/configfiles/PrintADCData/my_inputs.txt b/configfiles/PrintADCData/my_inputs.txt new file mode 100644 index 000000000..c7a51732f --- /dev/null +++ b/configfiles/PrintADCData/my_inputs.txt @@ -0,0 +1 @@ +./ProcessedRawData_TankAndCTC_R4314S0p1 From 0e9c005684df5477247dee8afba9d30a519a4ba1 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 11:24:27 -0500 Subject: [PATCH 022/163] Add files via upload In case users want to eventbuild part files with raw waveforms (useful for source analysis), this toolchain complements the official event building toolchain that is used to create our processed data. Configurations for the tools to extract raw waveforms successfully from the PMTs are taken from Gian's AmBe analysis work. Currently, the event building for this toolchain has only been tested for Tank + CTC events. --- .../EventBuilderRaw/ANNIEEventBuilderConfig | 20 +++++++++++++++ .../EventBuilderRaw/DefaultTriggerMask.txt | 10 ++++++++ .../EventBuilderRaw/LoadGeometryConfig | 9 +++++++ configfiles/EventBuilderRaw/LoadRawDataConfig | 9 +++++++ .../EventBuilderRaw/PMTDataDecoderConfig | 5 ++++ .../PhaseIIADCCalibratorConfig | 15 +++++++++++ .../EventBuilderRaw/PhaseIIADCHitFinderConfig | 10 ++++++++ configfiles/EventBuilderRaw/README.md | 25 +++++++++++++++++++ configfiles/EventBuilderRaw/ToolChainConfig | 23 +++++++++++++++++ configfiles/EventBuilderRaw/ToolsConfig | 7 ++++++ .../EventBuilderRaw/TriggerDataDecoderConfig | 4 +++ configfiles/EventBuilderRaw/my_files.txt | 1 + 12 files changed, 138 insertions(+) create mode 100644 configfiles/EventBuilderRaw/ANNIEEventBuilderConfig create mode 100644 configfiles/EventBuilderRaw/DefaultTriggerMask.txt create mode 100644 configfiles/EventBuilderRaw/LoadGeometryConfig create mode 100644 configfiles/EventBuilderRaw/LoadRawDataConfig create mode 100644 configfiles/EventBuilderRaw/PMTDataDecoderConfig create mode 100644 configfiles/EventBuilderRaw/PhaseIIADCCalibratorConfig create mode 100644 configfiles/EventBuilderRaw/PhaseIIADCHitFinderConfig create mode 100644 configfiles/EventBuilderRaw/README.md create mode 100644 configfiles/EventBuilderRaw/ToolChainConfig create mode 100644 configfiles/EventBuilderRaw/ToolsConfig create mode 100644 configfiles/EventBuilderRaw/TriggerDataDecoderConfig create mode 100644 configfiles/EventBuilderRaw/my_files.txt diff --git a/configfiles/EventBuilderRaw/ANNIEEventBuilderConfig b/configfiles/EventBuilderRaw/ANNIEEventBuilderConfig new file mode 100644 index 000000000..a87912902 --- /dev/null +++ b/configfiles/EventBuilderRaw/ANNIEEventBuilderConfig @@ -0,0 +1,20 @@ +verbosity 0 + +BuildType TankAndCTC +ProcessedFilesBasename ProcessedRawData +#NumEventsPerPairing 200 +SavePath ./ + +MinNumWavesInSet 1 // 1=Just throw any waveforms into ANNIE events if you got em + +ExecutesPerBuild 10 +OrphanOldTankTimestamps 1 +OldTimestampThreshold 150 +OrphanFileBase OrphanStore +#MaxStreamMatchingTimeSeparation 60 // seconds. If one stream is ahead of the others, pause reading + +SaveRawData 1 +StoreBeamStatus 0 + +BuildStage1Data 0 +SaveSeparatePartfiles 1 diff --git a/configfiles/EventBuilderRaw/DefaultTriggerMask.txt b/configfiles/EventBuilderRaw/DefaultTriggerMask.txt new file mode 100644 index 000000000..398850355 --- /dev/null +++ b/configfiles/EventBuilderRaw/DefaultTriggerMask.txt @@ -0,0 +1,10 @@ +#Triggers are given by Jonathan; place one number per line. Values are index + 1 +#4+1: Delayed beam. 32+1: LED trigger. 34+1: AmBe and Cosmic trigger. 35+1: MRD_CR_Trigger. 30+1: LED_Start. 45+1, 46+1: Laser. 14+1: AmBe external trigger +5 +15 +36 +31 +33 +35 +46 +47 diff --git a/configfiles/EventBuilderRaw/LoadGeometryConfig b/configfiles/EventBuilderRaw/LoadGeometryConfig new file mode 100644 index 000000000..6c9e006fc --- /dev/null +++ b/configfiles/EventBuilderRaw/LoadGeometryConfig @@ -0,0 +1,9 @@ +verbosity 0 +LAPPDChannelCount 60 +FACCMRDGeoFile ./configfiles/LoadGeometry/FullMRDGeometry.csv +DetectorGeoFile ./configfiles/LoadGeometry/DetectorGeometrySpecs.csv +LAPPDGeoFile ./configfiles/LoadGeometry/LAPPDGeometry.csv +TankPMTGeoFile ./configfiles/LoadGeometry/FullTankPMTGeometry.csv +TankPMTGainFile ./configfiles/LoadGeometry/ChannelSPEGains2023.csv +TankPMTTimingOffsetFile ./configfiles/LoadGeometry/TankPMTTimingOffsets.csv +AuxiliaryChannelFile ./configfiles/LoadGeometry/AuxChannels.csv diff --git a/configfiles/EventBuilderRaw/LoadRawDataConfig b/configfiles/EventBuilderRaw/LoadRawDataConfig new file mode 100644 index 000000000..ffaf99fbd --- /dev/null +++ b/configfiles/EventBuilderRaw/LoadRawDataConfig @@ -0,0 +1,9 @@ +verbosity 0 +BuildType TankAndCTC +#BuildType CTC +Mode FileList +InputFile ./configfiles/DataDecoder/my_files.txt +DummyRunInfo 1 +StoreTrigOverlap 0 +ReadTrigOverlap 1 +StoreRawData 0 diff --git a/configfiles/EventBuilderRaw/PMTDataDecoderConfig b/configfiles/EventBuilderRaw/PMTDataDecoderConfig new file mode 100644 index 000000000..19e946601 --- /dev/null +++ b/configfiles/EventBuilderRaw/PMTDataDecoderConfig @@ -0,0 +1,5 @@ +verbosity 0 +ADCCountsToBuildWaves 0 +Mode Offline +OffsetVME03 0 +OffsetVME01 0 diff --git a/configfiles/EventBuilderRaw/PhaseIIADCCalibratorConfig b/configfiles/EventBuilderRaw/PhaseIIADCCalibratorConfig new file mode 100644 index 000000000..158dc6ed1 --- /dev/null +++ b/configfiles/EventBuilderRaw/PhaseIIADCCalibratorConfig @@ -0,0 +1,15 @@ +# PhaseIIADCCalibrator config file + +verbosity 0 + +BaselineEstimationType ze3ra_multi +NumBaselineSamples 15 +NumSubWaveforms 10 + +SamplesPerBaselineEstimate 2000 +BaselineUncertaintyTolerance 2 +PCritical 0.01 +MakeCalLEDWaveforms 0 + +EventBuilding 1 +ExecutesPerBuild 10 diff --git a/configfiles/EventBuilderRaw/PhaseIIADCHitFinderConfig b/configfiles/EventBuilderRaw/PhaseIIADCHitFinderConfig new file mode 100644 index 000000000..d183b7b27 --- /dev/null +++ b/configfiles/EventBuilderRaw/PhaseIIADCHitFinderConfig @@ -0,0 +1,10 @@ +verbosity 0 + +UseLEDWaveforms 0 + +PulseFindingApproach threshold +PulseWindowType dynamic +DefaultADCThreshold 7 +DefaultThresholdType relative + +EventBuilding 1 diff --git a/configfiles/EventBuilderRaw/README.md b/configfiles/EventBuilderRaw/README.md new file mode 100644 index 000000000..73cc63a5e --- /dev/null +++ b/configfiles/EventBuilderRaw/README.md @@ -0,0 +1,25 @@ +# EventBuilderRaw + +*********************** +## Description +********************** + +The `EventBuilderRaw` toolchain can be used to produce Processed files that contain the raw waveforms (PMTs) and store them to the ANNIEEvent booststore. This toolchain is essentially the same as the `EventBuilder` toolchain, except that raw waveforms are saved, not just the hits. + +This toolchain only builts Tank + CTC events (no MRD). Hit finding tools are typically ommitted from the toolchain but can be including to also save the hits information in parallel with the raw waveforms. + +Warning to users: When using this toolchain, enormous amounts of disk space will be used as all ~121 active PMT channels (and aux channels + CTC information) will be saved for every trigger/event. Recommended to run a part file at a time. The output Processed files will be at least x10 larger than their hits only counterparts. + +************************ +## Tools +************************ + +The toolchain typically consists of the following tools: + +``` +LoadGeometry +LoadRawData +PMTDataDecoder +TriggerDataDecoder +ANNIEEventBuilder +``` diff --git a/configfiles/EventBuilderRaw/ToolChainConfig b/configfiles/EventBuilderRaw/ToolChainConfig new file mode 100644 index 000000000..e65304c6f --- /dev/null +++ b/configfiles/EventBuilderRaw/ToolChainConfig @@ -0,0 +1,23 @@ +#ToolChain dynamic setup file + +##### Runtime Paramiters ##### +verbose 1 +error_level 0 # 0= do not exit, 1= exit on unhandeled errors only, 2= exit on unhandeled errors and handeled errors +attempt_recover 1 + +###### Logging ##### +log_mode Interactive # Interactive=cout , Remote= remote logging system "serservice_name Remote_Logging" , Local = local file log; +log_local_path ./log +log_service LogStore + +###### Service discovery ##### +service_publish_sec -1 +service_kick_sec -1 + +##### Tools To Add ##### +Tools_File ./configfiles/EventBuilderRaw/ToolsConfig + +##### Run Type ##### +Inline -1 +Interactive 0 + diff --git a/configfiles/EventBuilderRaw/ToolsConfig b/configfiles/EventBuilderRaw/ToolsConfig new file mode 100644 index 000000000..9e731b51d --- /dev/null +++ b/configfiles/EventBuilderRaw/ToolsConfig @@ -0,0 +1,7 @@ +LoadGeometry LoadGeometry ./configfiles/LoadGeometry/LoadGeometryConfig +LoadRawData LoadRawData ./configfiles/EventBuilderRaw/LoadRawDataConfig +PMTDataDecoder PMTDataDecoder ./configfiles/EventBuilderRaw/PMTDataDecoderConfig +TriggerDataDecoder TriggerDataDecoder ./configfiles/EventBuilderRaw/TriggerDataDecoderConfig +#PhaseIIADCCalibrator PhaseIIADCCalibrator ./configfiles/EventBuilderRaw/PhaseIIADCCalibratorConfig +#PhaseIIADCHitFinder PhaseIIADCHitFinder ./configfiles/EventBuilderRaw/PhaseIIADCHitFinderConfig +ANNIEEventBuilder ANNIEEventBuilder ./configfiles/EventBuilderRaw/ANNIEEventBuilderConfig diff --git a/configfiles/EventBuilderRaw/TriggerDataDecoderConfig b/configfiles/EventBuilderRaw/TriggerDataDecoderConfig new file mode 100644 index 000000000..c80c66547 --- /dev/null +++ b/configfiles/EventBuilderRaw/TriggerDataDecoderConfig @@ -0,0 +1,4 @@ +verbosity 0 +TriggerMaskFile ./configfiles/EventBuilderRaw/DefaultTriggerMask.txt +StoreTrigOverlap 0 +ReadTrigOverlap 0 diff --git a/configfiles/EventBuilderRaw/my_files.txt b/configfiles/EventBuilderRaw/my_files.txt new file mode 100644 index 000000000..de43e7839 --- /dev/null +++ b/configfiles/EventBuilderRaw/my_files.txt @@ -0,0 +1 @@ +/pnfs/annie/persistent/raw/raw/4314/RAWDataR4314S0p1 From 366ce1a01441c22518d2d23de39709f69e660b03 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 11:40:54 -0500 Subject: [PATCH 023/163] Add files via upload Added README for event building toolchain, with reference to the ANNIE wiki page on how to properly event build. --- configfiles/EventBuilder/README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 configfiles/EventBuilder/README.md diff --git a/configfiles/EventBuilder/README.md b/configfiles/EventBuilder/README.md new file mode 100644 index 000000000..ebddb16c5 --- /dev/null +++ b/configfiles/EventBuilder/README.md @@ -0,0 +1,27 @@ +# EventBuilder + +*********************** +## Description +********************** + +The `EventBuilder` toolchain should be used to eventbuild for ANNIEEvents. The toolchain read in RAWData files, time match, and creates processed ANNIEEvents with Tank, CTC, and MRD information (currently no LAPPD information is included). This toolchain consolidated efforts to create an official event building toolchain for ANNIE, and should replace the `DataDecoder` toolchain, which is now considered depreciated. + +Please consult the following ANNIE wiki page on how to event build: https://cdcvs.fnal.gov/redmine/projects/annie_experiment/wiki/Event_Building_with_ToolAnalysis + +************************ +## Tools +************************ + +The toolchain consists of the following tools: + +``` +LoadGeometry +LoadRawData +PMTDataDecoder +MRDDataDecoder +TriggerDataDecoder +PhaseIIADCCalibrator +PhaseIIADCHitFinder +SaveConfigInfo +ANNIEEventBuilder +``` From ec20c13aadea9716ad30d0772763258e81b93507 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 11:42:52 -0500 Subject: [PATCH 024/163] Update README.md small syntax fix for EventBuilder README file --- configfiles/EventBuilder/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configfiles/EventBuilder/README.md b/configfiles/EventBuilder/README.md index ebddb16c5..089e9c8a2 100644 --- a/configfiles/EventBuilder/README.md +++ b/configfiles/EventBuilder/README.md @@ -4,7 +4,7 @@ ## Description ********************** -The `EventBuilder` toolchain should be used to eventbuild for ANNIEEvents. The toolchain read in RAWData files, time match, and creates processed ANNIEEvents with Tank, CTC, and MRD information (currently no LAPPD information is included). This toolchain consolidated efforts to create an official event building toolchain for ANNIE, and should replace the `DataDecoder` toolchain, which is now considered depreciated. +The `EventBuilder` toolchain is used to event build for ANNIE. The toolchain reads in RAWData files, time match, and creates processed ANNIEEvents with Tank, CTC, and MRD information (currently no LAPPD information is included). This toolchain consolidated efforts to create an official event building toolchain, and should replace the `DataDecoder` toolchain which is now considered depreciated. Please consult the following ANNIE wiki page on how to event build: https://cdcvs.fnal.gov/redmine/projects/annie_experiment/wiki/Event_Building_with_ToolAnalysis From 1df3b7cf579f0bc15a7a211e3fcbfc8d396545d9 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 3 Apr 2024 12:45:49 -0500 Subject: [PATCH 025/163] Update ClusterFinder.cpp Missed a bracket which caused the CI build error --- UserTools/ClusterFinder/ClusterFinder.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/UserTools/ClusterFinder/ClusterFinder.cpp b/UserTools/ClusterFinder/ClusterFinder.cpp index 77b5aa811..b3f7748bc 100644 --- a/UserTools/ClusterFinder/ClusterFinder.cpp +++ b/UserTools/ClusterFinder/ClusterFinder.cpp @@ -242,7 +242,6 @@ bool ClusterFinder::Execute(){ temp_charges+=hits_2ns_res_charge.at(i_hit); temp_times.push_back(hit1); } else new_pulse=true; - } if (new_pulse) { // following the DigitBuilder tool --> take median photon hit time as the hit time of the "pulse" From 867eccddf2c66312c459e318dc9fa8e0d3b0aca1 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Tue, 9 Apr 2024 14:09:37 -0500 Subject: [PATCH 026/163] Update LoadWCSim.cpp When using the "automatic" method for loading in GENIE files in the LoadGenieEvent, this was causing that tool to crash as it couldn't find the proper path based on the WCSim file name. Removed the to_string function --- UserTools/LoadWCSim/LoadWCSim.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UserTools/LoadWCSim/LoadWCSim.cpp b/UserTools/LoadWCSim/LoadWCSim.cpp index 8e5dc24ad..584092a05 100644 --- a/UserTools/LoadWCSim/LoadWCSim.cpp +++ b/UserTools/LoadWCSim/LoadWCSim.cpp @@ -418,7 +418,7 @@ bool LoadWCSim::Execute(){ int genieentry = firsttrigt->GetHeader()->GetGenieEntryNum(); if(verbosity>1) cout<<"Genie file is "<CStore.Set("GenieFile",geniefilename); - m_data->CStore.Set("GenieEntry",std::to_string(genieentry)); + m_data->CStore.Set("GenieEntry",genieentry); for(int trigi=0; trigiwcsimrootevent->GetNumberOfEvents(); trigi++){ From a092e112c43778569d51794db33a3b29f59782c8 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Thu, 11 Apr 2024 11:34:33 -0500 Subject: [PATCH 027/163] Initial bug fix to prevent double counting and add hooks for eventbuilding. Also a default toolconfig for testing. --- BeamFetcherV2 | 1 + UserTools/BeamFetcherV2/BeamFetcherV2.cpp | 101 +++++++++++++----- UserTools/BeamFetcherV2/BeamFetcherV2.h | 7 ++ UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.h | 6 +- UserTools/BeamFetcherV2/README.md | 9 +- UserTools/BeamFetcherV2/devices.txt | 1 + configfiles/BeamFetcherV2/BeamFetcherV2Config | 8 ++ configfiles/BeamFetcherV2/DummyToolConfig | 3 + configfiles/BeamFetcherV2/LoadRawDataConfig | 9 ++ configfiles/BeamFetcherV2/README.md | 25 +++++ configfiles/BeamFetcherV2/ToolChainConfig | 26 +++++ configfiles/BeamFetcherV2/ToolsConfig | 4 + .../BeamFetcherV2/TriggerDataDecoderConfig | 4 + configfiles/BeamFetcherV2/devices.txt | 1 + configfiles/BeamFetcherV2/my_files.txt | 4 + 15 files changed, 174 insertions(+), 35 deletions(-) create mode 120000 BeamFetcherV2 create mode 100644 UserTools/BeamFetcherV2/devices.txt create mode 100644 configfiles/BeamFetcherV2/BeamFetcherV2Config create mode 100644 configfiles/BeamFetcherV2/DummyToolConfig create mode 100644 configfiles/BeamFetcherV2/LoadRawDataConfig create mode 100644 configfiles/BeamFetcherV2/README.md create mode 100644 configfiles/BeamFetcherV2/ToolChainConfig create mode 100644 configfiles/BeamFetcherV2/ToolsConfig create mode 100644 configfiles/BeamFetcherV2/TriggerDataDecoderConfig create mode 100644 configfiles/BeamFetcherV2/devices.txt create mode 100644 configfiles/BeamFetcherV2/my_files.txt diff --git a/BeamFetcherV2 b/BeamFetcherV2 new file mode 120000 index 000000000..ed84c9a56 --- /dev/null +++ b/BeamFetcherV2 @@ -0,0 +1 @@ +configfiles/BeamFetcherV2/ToolChainConfig \ No newline at end of file diff --git a/UserTools/BeamFetcherV2/BeamFetcherV2.cpp b/UserTools/BeamFetcherV2/BeamFetcherV2.cpp index 5831fb4ed..1a27828f7 100644 --- a/UserTools/BeamFetcherV2/BeamFetcherV2.cpp +++ b/UserTools/BeamFetcherV2/BeamFetcherV2.cpp @@ -24,11 +24,12 @@ bool BeamFetcherV2::Initialise(std::string config_filename, DataModel& data) m_data = &data; // Get the things - bool got_verbosity = m_variables.Get("verbose", verbosity); - bool got_bundleflag = m_variables.Get("IsBundle", fIsBundle); - bool got_devicesfile = m_variables.Get("DevicesFile", fDevicesFile); - bool got_saveroot = m_variables.Get("SaveROOT", fSaveROOT); - bool got_chunkMSec = m_variables.Get("TimeChunkStepInMilliseconds", fChunkStepMSec); + bool got_verbosity = m_variables.Get("verbose", verbosity); + bool got_bundleflag = m_variables.Get("IsBundle", fIsBundle); + bool got_devicesfile = m_variables.Get("DevicesFile", fDevicesFile); + bool got_saveroot = m_variables.Get("SaveROOT", fSaveROOT); + bool got_chunkMSec = m_variables.Get("TimeChunkStepInMilliseconds", fChunkStepMSec); + bool got_deletectcdata = m_variables.Get("DeleteCTCData", fDeleteCTCData); // Check the config parameters and set default values if necessary @@ -69,7 +70,15 @@ bool BeamFetcherV2::Initialise(std::string config_filename, DataModel& data) Log(logmessage, v_warning, verbosity); fSaveROOT = false; } - + + if (!got_deletectcdata) { + logmessage = ("Warning (BeamFetcherV2): DeleteCTCData was not set in the " + "config file. If you're not running ANNIEEventBuilder then " + "you probably want to set this to true. Using default \"false\""); + Log(logmessage, v_warning, verbosity); + fDeleteCTCData = false; + } + if (!got_chunkMSec) { logmessage = ("Warning (BeamFetcherV2): TimeChunkStepInMilliseconds was not" @@ -87,6 +96,9 @@ bool BeamFetcherV2::Initialise(std::string config_filename, DataModel& data) } if (fSaveROOT) this->SetupROOTFile(); + + // initialize the last timestamp + fLastTimestamp = 0; return true; } @@ -95,22 +107,37 @@ bool BeamFetcherV2::Initialise(std::string config_filename, DataModel& data) //------------------------------------------------------------------------------ bool BeamFetcherV2::Execute() { + m_data->CStore.Set("NewBeamDataAvailable", false); + // Do the things - bool goodFetch = this->FetchFromTrigger(); - - if (goodFetch) { - // Emplace fBeamDataToSave to CStore for other tools to use - m_data->CStore.Set("BeamData",fBeamDataToSave); - goodFetch = true; - } + bool gotNewCTCDataVar = m_data->CStore.Get("NewCTCDataAvailable", fNewCTCData); + bool goodFetch = false; + if (gotNewCTCDataVar && fNewCTCData) { + logmessage = ("Message (BeamFetcherV2): New CTC data found. Fetching. "); + Log(logmessage, v_message, verbosity); - if (fSaveROOT) this->WriteTrees(); - - // Clear for the next Fetch - fBeamDataToSave.clear(); + goodFetch = this->FetchFromTrigger(); + } else { + logmessage = ("Warning (BeamFetcherV2): No new CTC data found. Nothing to fetch. "); + Log(logmessage, v_message, verbosity); + } - return goodFetch; + // Save it out + if (goodFetch && fNewCTCData) { + logmessage = ("Debug (BeamFetcherV2): Writing out fBeamDataToSave, which has size: " + std::to_string(fBeamDataToSave.size())); + Log(logmessage, v_debug, verbosity); + + // put fBeamDataToSave in CStore for other tools to use + m_data->CStore.Set("NewBeamDataAvailable", true); + m_data->CStore.Set("BeamData",fBeamDataToSave); + if (fSaveROOT) this->WriteTrees(); + } else if (!goodFetch && fNewCTCData) { + logmessage = ("Warning (BeamFetcherV2): Bad fetch. "); + Log(logmessage, v_message, verbosity); + } + + return true; } //------------------------------------------------------------------------------ @@ -134,21 +161,31 @@ bool BeamFetcherV2::FetchFromTrigger() bool get_ok = m_data->CStore.Get("TimeToTriggerWordMap",TimeToTriggerWordMap); // Now loop over the CTC timestamps + // But start at the fLastTimeStamp to prevent double counting if the timestamp data wasn't deleted if (get_ok && TimeToTriggerWordMap) { - for (auto iterator : *TimeToTriggerWordMap) { - // We only want to get beam info for beam triggers (word 5) + for (auto iterator = TimeToTriggerWordMap->lower_bound(fLastTimestamp); + iterator != TimeToTriggerWordMap->end(); ++iterator) { + + // We only care about beam triggers here bool hasBeamTrig = false; - for (auto word : iterator.second) + for (auto word : iterator->second) if (word == 5) hasBeamTrig = true; if (!hasBeamTrig) continue; - uint64_t trigTimestamp = iterator.first; + // Grab the timestamp + uint64_t trigTimestamp = iterator->first; + fLastTimestamp = trigTimestamp; // Need to drop from ns to ms. This means that some timestamps will // already be recorded. We can skip these cases trigTimestamp = trigTimestamp/1E6; - if (fBeamDataToSave.find(trigTimestamp) != fBeamDataToSave.end()) + if (fBeamDataToSave.find(trigTimestamp) != fBeamDataToSave.end()) { + logmessage = ("Debug (BeamFetcherV2): fBeamDataToSave already has this timstamp: " + + std::to_string(trigTimestamp) + ", skipping."); + Log(logmessage, vv_debug, verbosity); + continue; + } // Check if we already have the info we need bool fetch = false; @@ -165,8 +202,7 @@ bool BeamFetcherV2::FetchFromTrigger() if (fIsBundle) { fBeamData = db.QueryBeamDBBundleSpan(fDevices[0], trigTimestamp, trigTimestamp+fChunkStepMSec); } else { - std::map > tempMap; - + std::map > tempMap; for (auto device : fDevices) { auto tempMap = db.QueryBeamDBSingleSpan(device, trigTimestamp, trigTimestamp+fChunkStepMSec); fBeamData.insert(tempMap.begin(), tempMap.end()); @@ -199,6 +235,9 @@ bool BeamFetcherV2::FetchFromTrigger() return false; } + if (fDeleteCTCData) + TimeToTriggerWordMap->clear(); + return true; } @@ -246,12 +285,16 @@ void BeamFetcherV2::SetupROOTFile() void BeamFetcherV2::WriteTrees() { // Loop over timestamps + // But start at the fLastTimeStamp to prevent double counting if the timestamp data wasn't deleted int devCounter = 0; - for (const auto iterTS : fBeamDataToSave) { - fTimestamp = iterTS.first; + uint64_t lastTimestamp = fLastTimestamp/1E6; + for (auto iterTS = fBeamDataToSave.lower_bound(lastTimestamp); + iterTS != fBeamDataToSave.end(); ++iterTS) { + + fTimestamp = iterTS->first; // Loop over devices - for (const auto iterDev : iterTS.second) { + for (const auto iterDev : iterTS->second) { std::string device = iterDev.first; std::replace( device.begin(), device.end(), ':', '_'); @@ -271,6 +314,8 @@ void BeamFetcherV2::WriteTrees() fOutTree->Fill(); }// end loop over timestamps + + } //------------------------------------------------------------------------------ diff --git a/UserTools/BeamFetcherV2/BeamFetcherV2.h b/UserTools/BeamFetcherV2/BeamFetcherV2.h index 94056ea72..e51be6715 100644 --- a/UserTools/BeamFetcherV2/BeamFetcherV2.h +++ b/UserTools/BeamFetcherV2/BeamFetcherV2.h @@ -49,6 +49,12 @@ class BeamFetcherV2: public Tool { // Holder for the devices we're going to look up std::vector fDevices; + // Keep the last timestamp around to make sure we don't double count + uint64_t fLastTimestamp; + + // Is there new data? + bool fNewCTCData; + // For ROOT file TFile *fOutFile; TTree *fOutTree; @@ -61,6 +67,7 @@ class BeamFetcherV2: public Tool { int verbosity; bool fIsBundle; bool fSaveROOT; + bool fDeleteCTCData; std::string fDevicesFile; std::string fOutFileName; uint64_t fChunkStepMSec; diff --git a/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.h b/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.h index 7ba3c6434..91835d78c 100644 --- a/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.h +++ b/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.h @@ -48,9 +48,9 @@ class IFBeamDBInterfaceV2 { /// @param t0 Starting timestamp (milliseconds since the Unix epoch) /// @param t1 Starting timestamp (milliseconds since the Unix epoch) /// @return A nested map containing the parsed data. Keys of the outer map - /// are device names, values are inner maps. Keys of the inner map are - /// timestamps (milliseconds since the Unix epoch), values are - /// BeamDataPoint structs that hold a numerical value and a unit string. + /// are timestamps (milliseconds since the Unix epoch), values are inner maps. + /// Keys of the inner map are device names , values are elements of class type + /// BeamDataPoint that hold a numerical value, a unit string, and timestamp. /// @note An easy way to get the current milliseconds since the Unix epoch /// is to use the terminal utility date like this: @verbatim date +%s%3N /// @endverbatim diff --git a/UserTools/BeamFetcherV2/README.md b/UserTools/BeamFetcherV2/README.md index 04df17154..219ec504f 100644 --- a/UserTools/BeamFetcherV2/README.md +++ b/UserTools/BeamFetcherV2/README.md @@ -20,21 +20,22 @@ FetchFromTrigger: The following objects will be put into the CStore ## Configuration -The main configuration variable for the `BeamFetcher` tool is `FetchFromTimes`, which determines whether to use the tigger timestamps or user input timestamps. The `DevicesFile`, `IsBundle`, and `TimeChunkStepInMilliseconds` variables are required regardless of the fetch mode. You can also set the `SaveROOT` bool in order to save out a TTree with the timestamp and device values as the leaves. +The main configuration variable for the `BeamFetcherV2` tool is `FetchFromTimes`, which determines whether to use the tigger timestamps or user input timestamps. The `DevicesFile`, `IsBundle`, and `TimeChunkStepInMilliseconds` variables are required regardless of the fetch mode. You can also set the `SaveROOT` bool in order to save out a TTree with the timestamp and device values as the leaves. If `FetchFromTimes == 1` then you will also need the additional config variables. The preferred timestamp format is chosen with the `TimestampMode` variable (LOCALDATE/MSEC/DB). For LOCALDATE mode you use Start/EndDate files with string formatted times (like 2023-04-11 23:03:19.163505). For MSEC mode you use the Start/EndMillisecondsSinceEpoch variables. For DB mode you must first run `LoadRunInfo` and the run timestamps will be pulled from the CStore. ``` -# BeamFetcher config file -verbose 5 +# BeamFetcherV2 config file +verbose 1 # # These three are always needed # -DevicesFile ./configfiles/BeamFetcher/devices.txt # File containing one device per line or a bundle +DevicesFile ./configfiles/BeamFetcherV2/devices.txt # File containing one device per line or a bundle IsBundle 0 # bool stating whether DevicesFile contains bundles or individual devices FetchFromTimes 0 # bool defining how to grab the data (from input times (1) or trigger(0)) TimeChunkStepInMilliseconds 3600000 # one hour SaveROOT 0 # bool, do you want to write a ROOT file with the timestamps and devices? +DeleteCTCData 0 # bool, delete viewed CTC timestamps? Helps reduce memory overhead when not running ANNIEEventBuilder. # # These parameters are only needed if FetchFromTimes == 1 # diff --git a/UserTools/BeamFetcherV2/devices.txt b/UserTools/BeamFetcherV2/devices.txt new file mode 100644 index 000000000..0bf9117bd --- /dev/null +++ b/UserTools/BeamFetcherV2/devices.txt @@ -0,0 +1 @@ +BoosterNeutrinoBeam_read diff --git a/configfiles/BeamFetcherV2/BeamFetcherV2Config b/configfiles/BeamFetcherV2/BeamFetcherV2Config new file mode 100644 index 000000000..b49564534 --- /dev/null +++ b/configfiles/BeamFetcherV2/BeamFetcherV2Config @@ -0,0 +1,8 @@ +# BeamFetcher config file +verbose 5 +DevicesFile ./configfiles/BeamFetcherV2/devices.txt # File containing one device per line or a bundle +IsBundle 1 # bool stating whether DevicesFile contains bundles or individual devices +FetchFromTimes 0 # bool defining how to grab the data (from input times (1) or trigger(0)) +TimeChunkStepInMilliseconds 3600000 # one hour +SaveROOT 1 # bool, do you want to write a ROOT file with the timestamps and devices? +DeleteCTCData 1 diff --git a/configfiles/BeamFetcherV2/DummyToolConfig b/configfiles/BeamFetcherV2/DummyToolConfig new file mode 100644 index 000000000..95cad88d2 --- /dev/null +++ b/configfiles/BeamFetcherV2/DummyToolConfig @@ -0,0 +1,3 @@ +# Dummy config file + +verbose 2 \ No newline at end of file diff --git a/configfiles/BeamFetcherV2/LoadRawDataConfig b/configfiles/BeamFetcherV2/LoadRawDataConfig new file mode 100644 index 000000000..b018c823d --- /dev/null +++ b/configfiles/BeamFetcherV2/LoadRawDataConfig @@ -0,0 +1,9 @@ +verbosity 11 +#BuildType TankAndMRDAndCTC +BuildType CTC +Mode FileList +InputFile ./configfiles/BeamFetcherV2/my_files.txt +DummyRunInfo 1 +StoreTrigOverlap 0 +ReadTrigOverlap 0 +StoreRawData 0 diff --git a/configfiles/BeamFetcherV2/README.md b/configfiles/BeamFetcherV2/README.md new file mode 100644 index 000000000..78d3e2015 --- /dev/null +++ b/configfiles/BeamFetcherV2/README.md @@ -0,0 +1,25 @@ +# Configure files + +*********************** +#Description +********************** + +Configure files are simple text files for passing variables to the Tools. + +Text files are read by the Store class (src/Store) and automatically assigned to an internal map for the relevant Tool to use. + + +************************ +#Usage +************************ + +Any line starting with a "#" will be ignored by the Store, as will blank lines. + +Variables should be stored one per line as follows: + + +Name Value #Comments + + +Note: Only one value is permitted per name and they are stored in a string stream and template cast back to the type given. + diff --git a/configfiles/BeamFetcherV2/ToolChainConfig b/configfiles/BeamFetcherV2/ToolChainConfig new file mode 100644 index 000000000..eae99b203 --- /dev/null +++ b/configfiles/BeamFetcherV2/ToolChainConfig @@ -0,0 +1,26 @@ +#ToolChain dynamic setup file + +##### Runtime Parameters ##### +verbose 1 ## Verbosity level of ToolChain +error_level 0 # 0= do not exit, 1= exit on unhandled errors only, 2= exit on unhandled errors and handled errors +attempt_recover 1 ## 1= will attempt to finalise if an execute fails +remote_port 24002 +IO_Threads 1 ## Number of threads for network traffic (~ 1/Gbps) + +###### Logging ##### +log_mode Interactive # Interactive=cout , Remote= remote logging system "serservice_name Remote_Logging" , Local = local file log; +log_local_path ./log +log_service LogStore + + +###### Service discovery ##### Ignore these settings for local analysis +service_publish_sec -1 +service_kick_sec -1 + +##### Tools To Add ##### +Tools_File configfiles/BeamFetcherV2/ToolsConfig ## list of tools to run and their config files + +##### Run Type ##### +Inline 1 ## number of Execute steps in program, -1 infinite loop that is ended by user +Interactive 0 ## set to 1 if you want to run the code interactively + diff --git a/configfiles/BeamFetcherV2/ToolsConfig b/configfiles/BeamFetcherV2/ToolsConfig new file mode 100644 index 000000000..2141e92ed --- /dev/null +++ b/configfiles/BeamFetcherV2/ToolsConfig @@ -0,0 +1,4 @@ +LoadGeometry LoadGeometry ./configfiles/LoadGeometry/LoadGeometryConfig +LoadRawData LoadRawData ./configfiles/BeamFetcherV2/LoadRawDataConfig +TriggerDataDecoder TriggerDataDecoder ./configfiles/BeamFetcherV2/TriggerDataDecoderConfig +BeamFetcherV2 BeamFetcherV2 ./configfiles/BeamFetcherV2/BeamFetcherV2Config diff --git a/configfiles/BeamFetcherV2/TriggerDataDecoderConfig b/configfiles/BeamFetcherV2/TriggerDataDecoderConfig new file mode 100644 index 000000000..0b193d920 --- /dev/null +++ b/configfiles/BeamFetcherV2/TriggerDataDecoderConfig @@ -0,0 +1,4 @@ +verbosity 0 +TriggerMaskFile ./configfiles/DataDecoder/DefaultTriggerMask.txt +StoreTrigOverlap 0 +ReadTrigOverlap 0 diff --git a/configfiles/BeamFetcherV2/devices.txt b/configfiles/BeamFetcherV2/devices.txt new file mode 100644 index 000000000..0bf9117bd --- /dev/null +++ b/configfiles/BeamFetcherV2/devices.txt @@ -0,0 +1 @@ +BoosterNeutrinoBeam_read diff --git a/configfiles/BeamFetcherV2/my_files.txt b/configfiles/BeamFetcherV2/my_files.txt new file mode 100644 index 000000000..509031822 --- /dev/null +++ b/configfiles/BeamFetcherV2/my_files.txt @@ -0,0 +1,4 @@ +/pnfs/annie/persistent/raw/raw/4774/RAWDataR4774S0p1 +/pnfs/annie/persistent/raw/raw/4774/RAWDataR4774S0p2 +/pnfs/annie/persistent/raw/raw/4774/RAWDataR4774S0p3 +/pnfs/annie/persistent/raw/raw/4774/RAWDataR4774S0p4 From 074c6888e8f677ea21bdf20bb3c1a0820ddbd71d Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Mon, 15 Apr 2024 20:32:05 -0500 Subject: [PATCH 028/163] Big commit time. New BeamQuality tool to produce BeamStatuses from the BeamFetcherV2 that ANNIEEventBuilder interfaces with. Minor changes to config files. --- UserTools/BeamFetcherV2/BeamFetcherV2.cpp | 67 +++-- UserTools/BeamFetcherV2/BeamFetcherV2.h | 5 +- UserTools/BeamQuality/BeamQuality.cpp | 256 ++++++++++++++++++ UserTools/BeamQuality/BeamQuality.h | 78 ++++++ UserTools/BeamQuality/README.md | 33 +++ UserTools/Factory/Factory.cpp | 1 + UserTools/Unity.h | 1 + configfiles/BeamFetcherV2/DummyToolConfig | 3 - configfiles/BeamFetcherV2/ToolChainConfig | 2 +- .../EventBuilder/ANNIEEventBuilderConfig | 2 +- configfiles/EventBuilder/BeamDecoderConfig | 17 -- configfiles/EventBuilder/BeamDevices.txt | 1 + configfiles/EventBuilder/BeamFetcherV2Config | 17 ++ configfiles/EventBuilder/BeamQualityConfig | 13 + configfiles/EventBuilder/ToolsConfig | 2 + 15 files changed, 444 insertions(+), 54 deletions(-) create mode 100644 UserTools/BeamQuality/BeamQuality.cpp create mode 100644 UserTools/BeamQuality/BeamQuality.h create mode 100644 UserTools/BeamQuality/README.md delete mode 100644 configfiles/BeamFetcherV2/DummyToolConfig delete mode 100644 configfiles/EventBuilder/BeamDecoderConfig create mode 100644 configfiles/EventBuilder/BeamDevices.txt create mode 100644 configfiles/EventBuilder/BeamFetcherV2Config create mode 100644 configfiles/EventBuilder/BeamQualityConfig diff --git a/UserTools/BeamFetcherV2/BeamFetcherV2.cpp b/UserTools/BeamFetcherV2/BeamFetcherV2.cpp index 1a27828f7..a25e52d05 100644 --- a/UserTools/BeamFetcherV2/BeamFetcherV2.cpp +++ b/UserTools/BeamFetcherV2/BeamFetcherV2.cpp @@ -73,8 +73,9 @@ bool BeamFetcherV2::Initialise(std::string config_filename, DataModel& data) if (!got_deletectcdata) { logmessage = ("Warning (BeamFetcherV2): DeleteCTCData was not set in the " - "config file. If you're not running ANNIEEventBuilder then " - "you probably want to set this to true. Using default \"false\""); + "config file. If you're not running downstream tools that " + "remove the CTC from the CStore then you probably want to " + " set this to true to save memory. Using default \"false\""); Log(logmessage, v_warning, verbosity); fDeleteCTCData = false; } @@ -99,6 +100,9 @@ bool BeamFetcherV2::Initialise(std::string config_filename, DataModel& data) // initialize the last timestamp fLastTimestamp = 0; + BeamDataMap = new std::map >; + + m_data->CStore.Set("NewBeamDataAvailable", false); return true; } @@ -110,9 +114,9 @@ bool BeamFetcherV2::Execute() m_data->CStore.Set("NewBeamDataAvailable", false); // Do the things - bool gotNewCTCDataVar = m_data->CStore.Get("NewCTCDataAvailable", fNewCTCData); + bool got_ctc = m_data->CStore.Get("NewCTCDataAvailable", fNewCTCData); bool goodFetch = false; - if (gotNewCTCDataVar && fNewCTCData) { + if (got_ctc && fNewCTCData) { logmessage = ("Message (BeamFetcherV2): New CTC data found. Fetching. "); Log(logmessage, v_message, verbosity); @@ -124,15 +128,15 @@ bool BeamFetcherV2::Execute() // Save it out - if (goodFetch && fNewCTCData) { - logmessage = ("Debug (BeamFetcherV2): Writing out fBeamDataToSave, which has size: " + std::to_string(fBeamDataToSave.size())); + if (goodFetch) { + logmessage = ("Debug (BeamFetcherV2): Writing out BeamDataMap, which has size: " + std::to_string(BeamDataMap->size())); Log(logmessage, v_debug, verbosity); - // put fBeamDataToSave in CStore for other tools to use + // put BeamDataMap in CStore for other tools to use m_data->CStore.Set("NewBeamDataAvailable", true); - m_data->CStore.Set("BeamData",fBeamDataToSave); + m_data->CStore.Set("BeamDataMap", BeamDataMap); if (fSaveROOT) this->WriteTrees(); - } else if (!goodFetch && fNewCTCData) { + } else if (fNewCTCData) { logmessage = ("Warning (BeamFetcherV2): Bad fetch. "); Log(logmessage, v_message, verbosity); } @@ -158,19 +162,22 @@ bool BeamFetcherV2::FetchFromTrigger() // Need to get the trigger times std::map>* TimeToTriggerWordMap=nullptr; - bool get_ok = m_data->CStore.Get("TimeToTriggerWordMap",TimeToTriggerWordMap); + bool got_triggers = m_data->CStore.Get("TimeToTriggerWordMap",TimeToTriggerWordMap); // Now loop over the CTC timestamps // But start at the fLastTimeStamp to prevent double counting if the timestamp data wasn't deleted - if (get_ok && TimeToTriggerWordMap) { + if (got_triggers && TimeToTriggerWordMap) { for (auto iterator = TimeToTriggerWordMap->lower_bound(fLastTimestamp); iterator != TimeToTriggerWordMap->end(); ++iterator) { // We only care about beam triggers here - bool hasBeamTrig = false; - for (auto word : iterator->second) - if (word == 5) hasBeamTrig = true; - if (!hasBeamTrig) continue; + if (std::find(iterator->second.begin(), iterator->second.end(), 5) == iterator->second.end()) { + continue; + } + // bool hasBeamTrig = false; + // for (auto word : iterator->second) + // if (word == 5) hasBeamTrig = true; + // if (!hasBeamTrig) continue; // Grab the timestamp uint64_t trigTimestamp = iterator->first; @@ -179,8 +186,8 @@ bool BeamFetcherV2::FetchFromTrigger() // Need to drop from ns to ms. This means that some timestamps will // already be recorded. We can skip these cases trigTimestamp = trigTimestamp/1E6; - if (fBeamDataToSave.find(trigTimestamp) != fBeamDataToSave.end()) { - logmessage = ("Debug (BeamFetcherV2): fBeamDataToSave already has this timstamp: " + if (BeamDataMap->find(trigTimestamp) != BeamDataMap->end()) { + logmessage = ("Debug (BeamFetcherV2): BeamDataMap already has this timstamp: " + std::to_string(trigTimestamp) + ", skipping."); Log(logmessage, vv_debug, verbosity); @@ -190,8 +197,8 @@ bool BeamFetcherV2::FetchFromTrigger() // Check if we already have the info we need bool fetch = false; std::map >::iterator low, prev; - low = fBeamData.lower_bound(trigTimestamp); - if (low == fBeamData.end()) { + low = BeamDataQuery.lower_bound(trigTimestamp); + if (low == BeamDataQuery.end()) { fetch = true; logmessage = ("BeamFetcherV2: I'm going to query the DB"); Log(logmessage, v_message, verbosity); @@ -200,32 +207,32 @@ bool BeamFetcherV2::FetchFromTrigger() // We'll pull fChunkStepMSec worth of data at a time to avoid rapid queries if (fetch) { if (fIsBundle) { - fBeamData = db.QueryBeamDBBundleSpan(fDevices[0], trigTimestamp, trigTimestamp+fChunkStepMSec); + BeamDataQuery = db.QueryBeamDBBundleSpan(fDevices[0], trigTimestamp, trigTimestamp+fChunkStepMSec); } else { std::map > tempMap; for (auto device : fDevices) { auto tempMap = db.QueryBeamDBSingleSpan(device, trigTimestamp, trigTimestamp+fChunkStepMSec); - fBeamData.insert(tempMap.begin(), tempMap.end()); + BeamDataQuery.insert(tempMap.begin(), tempMap.end()); } } } // Now we can match the Beam info to CTC timestamps for saving to the CStore - low = fBeamData.lower_bound(trigTimestamp); - if (low == fBeamData.end()) { + low = BeamDataQuery.lower_bound(trigTimestamp); + if (low == BeamDataQuery.end()) { logmessage = ("Error (BeamFetcherV2): We fetched the data based on the CTC" " but somehow didn't turn anything up!?"); Log(logmessage, v_error, verbosity); return false; - } else if (low == fBeamData.begin()) { - fBeamDataToSave[trigTimestamp] = low->second; + } else if (low == BeamDataQuery.begin()) { + BeamDataMap->emplace(trigTimestamp, low->second); } else { // Check the previous DB timestamp to see if it's closer in time prev = std::prev(low); if ((trigTimestamp - prev->first) < (low->first - trigTimestamp)) - fBeamDataToSave[trigTimestamp] = prev->second; + BeamDataMap->emplace(trigTimestamp, prev->second); else - fBeamDataToSave[trigTimestamp] = low->second; + BeamDataMap->emplace(trigTimestamp, low->second); } }// end loop over trigger times } else { @@ -245,7 +252,7 @@ bool BeamFetcherV2::FetchFromTrigger() bool BeamFetcherV2::SaveToFile() { BoostStore fBeamDBStore(false, BOOST_STORE_MULTIEVENT_FORMAT); - fBeamDBStore.Set("BeamData", fBeamData); + fBeamDBStore.Set("BeamData", BeamDataQuery); fBeamDBStore.Save(fOutFileName); fBeamDBStore.Delete(); @@ -288,8 +295,8 @@ void BeamFetcherV2::WriteTrees() // But start at the fLastTimeStamp to prevent double counting if the timestamp data wasn't deleted int devCounter = 0; uint64_t lastTimestamp = fLastTimestamp/1E6; - for (auto iterTS = fBeamDataToSave.lower_bound(lastTimestamp); - iterTS != fBeamDataToSave.end(); ++iterTS) { + for (auto iterTS = BeamDataMap->lower_bound(lastTimestamp); + iterTS != BeamDataMap->end(); ++iterTS) { fTimestamp = iterTS->first; diff --git a/UserTools/BeamFetcherV2/BeamFetcherV2.h b/UserTools/BeamFetcherV2/BeamFetcherV2.h index e51be6715..88c8ff0b2 100644 --- a/UserTools/BeamFetcherV2/BeamFetcherV2.h +++ b/UserTools/BeamFetcherV2/BeamFetcherV2.h @@ -16,6 +16,7 @@ // ToolAnalysis includes #include "Tool.h" +#include "BeamDataPoint.h" // ROOT includes #include "TFile.h" @@ -40,8 +41,8 @@ class BeamFetcherV2: public Tool { // Holder for the retrieved data and the stuff we'll save - std::map > fBeamData; - std::map > fBeamDataToSave; + std::map > BeamDataQuery; + std::map > *BeamDataMap; // For saving out to a file std::map > fBeamDBIdx; diff --git a/UserTools/BeamQuality/BeamQuality.cpp b/UserTools/BeamQuality/BeamQuality.cpp new file mode 100644 index 000000000..47ba19d3a --- /dev/null +++ b/UserTools/BeamQuality/BeamQuality.cpp @@ -0,0 +1,256 @@ +#include "BeamQuality.h" + +BeamQuality::BeamQuality():Tool(){} + +//------------------------------------------------------------------------------ +bool BeamQuality::Initialise(std::string configfile, DataModel &data) +{ + // Load configuration file variables + if ( !configfile.empty() ) m_variables.Initialise(configfile); + + // Assign a transient data pointer + m_data = &data; + + // Get the things + bool got_verbosity = m_variables.Get("verbose", verbosity); + bool got_potmin = m_variables.Get("POTMin", fPOTMin); + bool got_potmax = m_variables.Get("POTMax", fPOTMax); + bool got_hornmin = m_variables.Get("HornCurrentMin", fHornCurrMin); + bool got_hornmax = m_variables.Get("HornCurrentMax", fHornCurrMax); + bool got_beamloss = m_variables.Get("BeamLossTolerance", fBeamLoss); + + // Check the config parameters and set default values if necessary + if (!got_verbosity) verbosity = 1; + + if (!got_potmin) { + fPOTMin = 5e11; + + logmessage = ("Warning (BeamQuality): POTMin not " + "set in the config file. Using default: 5e11"); + Log(logmessage, v_warning, verbosity); + } + + if (!got_potmax) { + fPOTMax = 8e12; + + logmessage = ("Warning (BeamQuality): POTMax not " + "set in the config file. Using default: 8e12"); + Log(logmessage, v_warning, verbosity); + } + + if (!got_hornmin) { + fHornCurrMin = 172; + + logmessage = ("Warning (BeamQuality): HornCurrentMin not " + "set in the config file. Using default: 172"); + Log(logmessage, v_warning, verbosity); + } + + if (!got_hornmax) { + fHornCurrMax = 176; + + logmessage = ("Warning (BeamQuality): HornCurrentMax not " + "set in the config file. Using default: 176"); + Log(logmessage, v_warning, verbosity); + } + + if (!got_beamloss) { + fBeamLoss = 0.05; + + logmessage = ("Warning (BeamQuality): BeamLossTolerance not " + "set in the config file. Using default: 0.05"); + Log(logmessage, v_warning, verbosity); + } + + // Necessary initialization + m_data->CStore.Set("NewBeamStatusAvailable", false); + fLastTimestamp = 0; + BeamStatusMap = new std::map; + + return true; +} + +//------------------------------------------------------------------------------ +bool BeamQuality::Execute() +{ + m_data->CStore.Set("NewBeamStatusAvailable", false); + + // Check for CTC timestamps and beam DB info + bool got_ctc = m_data->CStore.Get("NewCTCDataAvailable", fNewCTCData); + bool got_beamdb = m_data->CStore.Get("NewBeamDataAvailable", fNewBeamData); + + // Make sure we have the info we need + if (!got_ctc) { + logmessage = ("Error (BeamQuality): Did not find NewCTCDataAvailable " + "entry in the CStore. Aborting."); + Log(logmessage, v_error, verbosity); + + return false; + } + + if (!got_beamdb) { + logmessage = ("Error (BeamQuality): Did not find NewBeamDataAvailable " + "entry in the CStore. Make sure to run BeamFetcherV2 in " + "your tool chain. Aborting."); + Log(logmessage, v_error, verbosity); + + return false; + } + + + // Start doing the things + if (!fNewCTCData) { + logmessage = ("Message (BeamQuality): No new CTC data is available. " + "Nothing to do for now"); + Log(logmessage, v_message, verbosity); + + return true; + } + + // Need to get the trigger times and loop over them + bool got_triggers = m_data->CStore.Get("TimeToTriggerWordMap", TimeToTriggerWordMap); + bool got_beamdata = m_data->CStore.Get("BeamDataMap", BeamDataMap); + + // Keep track of which timestamps we've seen so we can clear out the BeamDataMap + std::set completed_timestamps; + + // But start from the fLastTimestamp to save time + for (auto iterator = TimeToTriggerWordMap->lower_bound(fLastTimestamp); + iterator != TimeToTriggerWordMap->end(); ++iterator) { + + // Grab the timestamp and check the trigger words + uint64_t timestamp = iterator->first; + uint64_t timestamp_ms = timestamp/1E6; + fLastTimestamp = timestamp; + completed_timestamps.insert(timestamp); + + // Check for trigger word 5 (beam) + // If it's not there then it isn't a beam trigger and there's nothing more to do + if (std::find(iterator->second.begin(), iterator->second.end(), 5) == iterator->second.end()) { + BeamStatus tempStatus(TimeClass(timestamp), 0., BeamCondition::NonBeamMinibuffer); + BeamStatusMap->emplace(timestamp, tempStatus); + continue; + } + + // Have we already saved this timestamp? If so then continue to the next one + if (BeamStatusMap->find(timestamp) != BeamStatusMap->end()) + continue; + + // Check for the existence of beam DB info + if (!fNewBeamData) { + logmessage = ("Warning (BeamQuality): No new Beam DB data is available. " + "Setting it to \"Missing\". "); + Log(logmessage, v_warning, verbosity); + + BeamStatus tempStatus(TimeClass(timestamp), 0., BeamCondition::Missing); + BeamStatusMap->emplace(timestamp, tempStatus); + } + + // Check for beam DB info associated with the timestamp + if (BeamDataMap->find(timestamp_ms) != BeamDataMap->end()) { + // Got the goods, now use it + BeamStatus tempStatus = assess_beam_quality(timestamp); + BeamStatusMap->emplace(timestamp, tempStatus); + + } else { + logmessage = ("Warning (BeamQuality): No Beam DB info found for timestamp: " + + std::to_string(timestamp_ms) + ". Setting it to \"Missing\". "); + Log(logmessage, v_warning, verbosity); + + BeamStatus tempStatus(TimeClass(timestamp), 0., BeamCondition::Missing); + BeamStatusMap->emplace(timestamp, tempStatus); + } // end if found timestamp in BeamDataMap + } // end loop over TimeToTriggerWordMap + + // Clear out the BeamDataMap to free up memory + for (auto ts : completed_timestamps) + BeamDataMap->erase(ts/1E6); + + // Save the status + m_data->CStore.Set("BeamStatusMap", BeamStatusMap); + + logmessage = ("Message (BeamQuality): BeamStatusMap size: " + + std::to_string(BeamStatusMap->size())); + Log(logmessage, v_message, verbosity); + + + return true; +} + +//------------------------------------------------------------------------------ +bool BeamQuality::Finalise() +{ + + return true; +} + +//------------------------------------------------------------------------------ +BeamStatus BeamQuality::assess_beam_quality(uint64_t timestamp) +{ + // initialize the beamstatus that we'll return + BeamStatus retStatus; + retStatus.set_time(TimeClass(timestamp)); + + + // Check for and grab the quatities we want from the BeamDataMap + uint64_t timestamp_ms = timestamp/1E6; + auto BeamDataPointMap = BeamDataMap->at(timestamp_ms); + + std::string device_name = ""; + + // POT downstream toroid + device_name = "E:TOR875"; + double pot_ds_toroid = 0; + if (BeamDataPointMap.find(device_name) != BeamDataPointMap.end()) { + auto bdp = BeamDataPointMap[device_name]; + retStatus.add_measurement(device_name, timestamp_ms, bdp); + retStatus.set_pot(bdp.value); + pot_ds_toroid = bdp.value; + } + + // POT upstream toroid + device_name = "E:TOR860"; + double pot_us_toroid = 0; + if (BeamDataPointMap.find(device_name) != BeamDataPointMap.end()) { + auto bdp = BeamDataPointMap[device_name]; + retStatus.add_measurement(device_name, timestamp_ms, bdp); + pot_us_toroid = bdp.value; + } + + // Horn current + device_name = "E:THCURR"; + double horn_current = 0; + if (BeamDataPointMap.find(device_name) != BeamDataPointMap.end()) { + auto bdp = BeamDataPointMap[device_name]; + retStatus.add_measurement(device_name, timestamp_ms, bdp); + horn_current = bdp.value; + } + + + // Perform the cuts + retStatus.add_cut("POT in range", + (retStatus.pot() >= fPOTMin && retStatus.pot() <= fPOTMax)); + + retStatus.add_cut("Horn current in range", + (horn_current >= fHornCurrMin && horn_current <= fHornCurrMax)); + + double beam_loss_frac = std::abs(pot_ds_toroid - pot_us_toroid) / (pot_ds_toroid + pot_us_toroid); + retStatus.add_cut("Beam loss acceptable", + (beam_loss_frac < fBeamLoss)); + + + // Finish up the beam status + if (retStatus.passed_all_cuts()) { + retStatus.set_condition(BeamCondition::Ok); + } else { + logmessage = ("Message (BeamQuality): Bad beam spill at trigger timestamp " + + std::to_string(timestamp)); + Log(logmessage, v_message, verbosity); + if (verbosity >=v_debug) + retStatus.Print(); + + retStatus.set_condition(BeamCondition::Bad); + } + + return retStatus; +} diff --git a/UserTools/BeamQuality/BeamQuality.h b/UserTools/BeamQuality/BeamQuality.h new file mode 100644 index 000000000..deb37b314 --- /dev/null +++ b/UserTools/BeamQuality/BeamQuality.h @@ -0,0 +1,78 @@ +#ifndef BeamQuality_H +#define BeamQuality_H + +#include +#include +#include +#include +#include +#include + +#include "Tool.h" +#include "BeamStatus.h" +#include "MinibufferLabel.h" +#include "ANNIEconstants.h" +#include "BeamDataPoint.h" +#include "TimeClass.h" + +#include "Tool.h" + + +/** +* \class BeamQuality +* +* Tool to apply quality cuts to the results of BeamFetcherV2 +* +* $Author: A.Sutton $ +* $Date: 2024/04/1 $ +*/ +class BeamQuality: public Tool { + + + public: + + BeamQuality(); ///< Simple constructor + bool Initialise(std::string configfile,DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + + protected: + BeamStatus assess_beam_quality(uint64_t timestamp); + + + private: + + // Config variables + int verbosity; + + // Cut values from config + // Extend this for additional cuts + double fPOTMin; + double fPOTMax; + double fHornCurrMin; + double fHornCurrMax; + double fBeamLoss; + + + // CStore things + bool fNewCTCData; + bool fNewBeamData; + std::map> *TimeToTriggerWordMap; ///< Trigger information + std::map> *BeamDataMap; ///< BeamDB information + std::map *BeamStatusMap; ///< Map containing the beam status information that will be saved to the CStore + + // Keep the last timestamp around to make sure we don't double process things + uint64_t fLastTimestamp; + + + // Verbosity things + int v_error = 0; + int v_warning = 1; + int v_message = 2; + int v_debug = 3; + int vv_debug = 4; + std::string logmessage; +}; + + +#endif diff --git a/UserTools/BeamQuality/README.md b/UserTools/BeamQuality/README.md new file mode 100644 index 000000000..cd3ed350b --- /dev/null +++ b/UserTools/BeamQuality/README.md @@ -0,0 +1,33 @@ +# BeamQuality + +The `BeamQuality` tool is part of the Event Building chain in ANNIE and forwards information about the Beam Status to the `ANNIEEventBuilder` tool. It uses information that was previously retrieved from the beam database with the `BeamFetcherV2` tool. This mimic the `BeamQuality` tool that is used for the original `BeamFetcher`. + +The information is saved in the form of the `BeamStatus` class. This class contains some basic information like the POT for the timestamp in question and some more detailed information about the horn currents. It is possible to already choose some beam quality cuts for the timestamp tolerance, horn currents, and POT values. However, some beam information will be stored in the object, so it will be possible to use slightly different cuts when analyzing the data later. + +## Data + +The Beam Status information is stored in the `BeamStatusMap` object and put in the CStore. The `ANNIEEventBuilder` tool can access the object in the CStore and write the information to the ANNIEEvent BoostStore. + +The `BeamQuality` tool goes through the decoded trigger timestamps and searches for the beam status at each of these trigger timestamps (in case there was a beam trigger). The properties of the beam are then saved in the BeamStatus object and put into the `BeamStatusMap`. It then deletes the used BeamData to free up memory. + +**BeamStatusMap** `map` +* Beam status for the trigger timestamps + +The `BeamStatusMap` is stored in the form of a pointer, and the `ANNIEEventBuilder` will delete already built entries from the map to free up memory. + +## Configuration + +BeamQuality has the following configuration variables: + +``` +# BeamQuality config file +verbose 1 +# POT window for "good" beam +POTMin 5e11 +POTMax 8e12 +# Horn current window for "good" beam (in kA) +HornCurrentMin 172 +HornCurrentMax 176 +# Fractional difference between the upstream and downstream POT measurements +BeamLossTolerance 0.05 +``` diff --git a/UserTools/Factory/Factory.cpp b/UserTools/Factory/Factory.cpp index c932574cd..8fa8c1d5b 100644 --- a/UserTools/Factory/Factory.cpp +++ b/UserTools/Factory/Factory.cpp @@ -167,5 +167,6 @@ if (tool=="NeutronMultiplicity") ret=new NeutronMultiplicity; if (tool=="PlotsTrackLengthAndEnergy") ret=new PlotsTrackLengthAndEnergy; if (tool=="SaveConfigInfo") ret=new SaveConfigInfo; if (tool=="ReadConfigInfo") ret=new ReadConfigInfo; +if (tool=="BeamQuality") ret=new BeamQuality; return ret; } diff --git a/UserTools/Unity.h b/UserTools/Unity.h index 9e00352b5..043287e2a 100644 --- a/UserTools/Unity.h +++ b/UserTools/Unity.h @@ -175,3 +175,4 @@ #include "PlotsTrackLengthAndEnergy.h" #include "SaveConfigInfo.h" #include "ReadConfigInfo.h" +#include "BeamQuality.h" diff --git a/configfiles/BeamFetcherV2/DummyToolConfig b/configfiles/BeamFetcherV2/DummyToolConfig deleted file mode 100644 index 95cad88d2..000000000 --- a/configfiles/BeamFetcherV2/DummyToolConfig +++ /dev/null @@ -1,3 +0,0 @@ -# Dummy config file - -verbose 2 \ No newline at end of file diff --git a/configfiles/BeamFetcherV2/ToolChainConfig b/configfiles/BeamFetcherV2/ToolChainConfig index eae99b203..32618da66 100644 --- a/configfiles/BeamFetcherV2/ToolChainConfig +++ b/configfiles/BeamFetcherV2/ToolChainConfig @@ -21,6 +21,6 @@ service_kick_sec -1 Tools_File configfiles/BeamFetcherV2/ToolsConfig ## list of tools to run and their config files ##### Run Type ##### -Inline 1 ## number of Execute steps in program, -1 infinite loop that is ended by user +Inline -1 ## number of Execute steps in program, -1 infinite loop that is ended by user Interactive 0 ## set to 1 if you want to run the code interactively diff --git a/configfiles/EventBuilder/ANNIEEventBuilderConfig b/configfiles/EventBuilder/ANNIEEventBuilderConfig index 6d59474bf..2e2c65aec 100644 --- a/configfiles/EventBuilder/ANNIEEventBuilderConfig +++ b/configfiles/EventBuilder/ANNIEEventBuilderConfig @@ -14,7 +14,7 @@ OrphanFileBase OrphanStore MaxStreamMatchingTimeSeparation 60 # seconds. If one stream is ahead of the others, pause reading SaveRawData 0 -StoreBeamStatus 0 +StoreBeamStatus 1 BuildStage1Data 0 SaveSeparatePartfiles 1 diff --git a/configfiles/EventBuilder/BeamDecoderConfig b/configfiles/EventBuilder/BeamDecoderConfig deleted file mode 100644 index 3866c2b30..000000000 --- a/configfiles/EventBuilder/BeamDecoderConfig +++ /dev/null @@ -1,17 +0,0 @@ -# BeamDecoder config file -verbosity 0 -# Names of devices needed for beam quality cuts -HornCurrentDevice E:THCURR -# The "first" toroid is the one farther upstream from the target -FirstToroid E:TOR860 -SecondToroid E:TOR875 -# POT window -CutPOTMin 5e11 -CutPOTMax 8e12 -# Peak horn current window (in kA) -CutPeakHornCurrentMin 172 -CutPeakHornCurrentMax 176 -# Toroid agreement tolerance (fractional error) -CutToroidAgreement 0.05 -# DB vs DAQ timestamp agreement tolerance (ms) -CutTimestampAgreement 100 diff --git a/configfiles/EventBuilder/BeamDevices.txt b/configfiles/EventBuilder/BeamDevices.txt new file mode 100644 index 000000000..0bf9117bd --- /dev/null +++ b/configfiles/EventBuilder/BeamDevices.txt @@ -0,0 +1 @@ +BoosterNeutrinoBeam_read diff --git a/configfiles/EventBuilder/BeamFetcherV2Config b/configfiles/EventBuilder/BeamFetcherV2Config new file mode 100644 index 000000000..8a0bb9e7b --- /dev/null +++ b/configfiles/EventBuilder/BeamFetcherV2Config @@ -0,0 +1,17 @@ +# BeamFetcher config file +verbose 0 +# +# File containing one device per line or a bundle +DevicesFile ./configfiles/EventBuilder/BeamDevices.txt +# +# bool stating whether DevicesFile contains bundles or individual devices +IsBundle 1 +# +# bool defining how to grab the data (from input times (1) or trigger(0)) +FetchFromTimes 0 +# +# How much data to pull in one query (set to 1 hr) +TimeChunkStepInMilliseconds 3600000 +# +# bool, do you want to write a ROOT file with the timestamps and devices? +SaveROOT 0 \ No newline at end of file diff --git a/configfiles/EventBuilder/BeamQualityConfig b/configfiles/EventBuilder/BeamQualityConfig new file mode 100644 index 000000000..f478a3b2b --- /dev/null +++ b/configfiles/EventBuilder/BeamQualityConfig @@ -0,0 +1,13 @@ +# BeamQuality config file +verbose 0 +# +# POT window for "good" beam +POTMin 5e11 +POTMax 8e12 +# +# Horn current window for "good" beam (in kA) +HornCurrentMin 172 +HornCurrentMax 176 +# +# Fractional difference between the upstream and downstream POT measurements +BeamLossTolerance 0.05 \ No newline at end of file diff --git a/configfiles/EventBuilder/ToolsConfig b/configfiles/EventBuilder/ToolsConfig index 95cc19f24..9d62fd3c6 100644 --- a/configfiles/EventBuilder/ToolsConfig +++ b/configfiles/EventBuilder/ToolsConfig @@ -3,6 +3,8 @@ LoadRawData LoadRawData ./configfiles/EventBuilder/LoadRawDataConfig PMTDataDecoder PMTDataDecoder ./configfiles/EventBuilder/PMTDataDecoderConfig MRDDataDecoder MRDDataDecoder ./configfiles/EventBuilder/MRDDataDecoderConfig TriggerDataDecoder TriggerDataDecoder ./configfiles/EventBuilder/TriggerDataDecoderConfig +BeamFetcherV2 BeamFetcherV2 ./configfiles/EventBuilder/BeamFetcherV2Config +BeamQuality BeamQuality ./configfiles/EventBuilder/BeamQualityConfig PhaseIIADCCalibrator PhaseIIADCCalibrator ./configfiles/EventBuilder/PhaseIIADCCalibratorConfig PhaseIIADCHitFinder PhaseIIADCHitFinder ./configfiles/EventBuilder/PhaseIIADCHitFinderConfig SaveConfigInfo SaveConfigInfo ./configfiles/EventBuilder/SaveConfigInfoConfig From dc89b1cc8828370137ccd8839e435a9303fb8449 Mon Sep 17 00:00:00 2001 From: Feng Yue Date: Mon, 22 Apr 2024 17:04:47 -0500 Subject: [PATCH 029/163] Add new tools for LAPPD toolchain v1 Add LAPPDLoadStore, load the LAPPD PsecData from multiple store format Add LAPPDStoreReorder Add LAPPDPlots for plotting functions Add LAPPDThresReco for a threshold based pulse finder and hit finder Add LAPPDTreeMaker Change some verbosity related print in TriggerDataDecoder --- DataModel/LAPPDHit.h | 10 + UserTools/Factory/Factory.cpp | 7 + UserTools/LAPPDBaseline/LAPPDBaseline.cpp | 195 +++ UserTools/LAPPDBaseline/LAPPDBaseline.h | 44 + UserTools/LAPPDBaseline/README.md | 20 + UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp | 1168 +++++++++++++++++ UserTools/LAPPDLoadStore/LAPPDLoadStore.h | 128 ++ UserTools/LAPPDLoadStore/README.md | 20 + UserTools/LAPPDPlots/LAPPDPlots.cpp | 325 +++++ UserTools/LAPPDPlots/LAPPDPlots.h | 105 ++ UserTools/LAPPDPlots/README.md | 20 + .../LAPPDStoreReorder/LAPPDStoreReorder.cpp | 299 +++++ .../LAPPDStoreReorder/LAPPDStoreReorder.h | 73 ++ UserTools/LAPPDStoreReorder/README.md | 20 + UserTools/LAPPDThresReco/LAPPDThresReco.cpp | 855 ++++++++++++ UserTools/LAPPDThresReco/LAPPDThresReco.h | 127 ++ UserTools/LAPPDThresReco/README.md | 20 + .../LAPPDTimeAlignment/LAPPDTimeAlignment.cpp | 248 ++++ .../LAPPDTimeAlignment/LAPPDTimeAlignment.h | 52 + UserTools/LAPPDTimeAlignment/README.md | 20 + UserTools/LAPPDTreeMaker/LAPPDTreeMaker.cpp | 790 +++++++++++ UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h | 155 +++ UserTools/LAPPDTreeMaker/README.md | 20 + .../TriggerDataDecoder/TriggerDataDecoder.cpp | 4 +- UserTools/Unity.h | 7 + 25 files changed, 4730 insertions(+), 2 deletions(-) create mode 100644 UserTools/LAPPDBaseline/LAPPDBaseline.cpp create mode 100644 UserTools/LAPPDBaseline/LAPPDBaseline.h create mode 100644 UserTools/LAPPDBaseline/README.md create mode 100644 UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp create mode 100644 UserTools/LAPPDLoadStore/LAPPDLoadStore.h create mode 100644 UserTools/LAPPDLoadStore/README.md create mode 100644 UserTools/LAPPDPlots/LAPPDPlots.cpp create mode 100644 UserTools/LAPPDPlots/LAPPDPlots.h create mode 100644 UserTools/LAPPDPlots/README.md create mode 100644 UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp create mode 100644 UserTools/LAPPDStoreReorder/LAPPDStoreReorder.h create mode 100644 UserTools/LAPPDStoreReorder/README.md create mode 100644 UserTools/LAPPDThresReco/LAPPDThresReco.cpp create mode 100644 UserTools/LAPPDThresReco/LAPPDThresReco.h create mode 100644 UserTools/LAPPDThresReco/README.md create mode 100644 UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.cpp create mode 100644 UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.h create mode 100644 UserTools/LAPPDTimeAlignment/README.md create mode 100644 UserTools/LAPPDTreeMaker/LAPPDTreeMaker.cpp create mode 100644 UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h create mode 100644 UserTools/LAPPDTreeMaker/README.md diff --git a/DataModel/LAPPDHit.h b/DataModel/LAPPDHit.h index d125bc46f..5dd752126 100755 --- a/DataModel/LAPPDHit.h +++ b/DataModel/LAPPDHit.h @@ -15,12 +15,18 @@ class LAPPDHit : public Hit{ public: LAPPDHit() : Hit(), Position(0), LocalPosition(0) {serialise=true;} LAPPDHit(int thetubeid, double thetime, double thecharge, std::vector theposition, std::vector thelocalposition) : Hit(thetubeid,thetime,thecharge), Position(theposition), LocalPosition(thelocalposition) {serialise=true;} + LAPPDHit(int thetubeid, double thetime, double thecharge, std::vector theposition, std::vector thelocalposition, double pulse1LastTime, double pulse2LastTime, double pulse1StartTime, double pulse2StartTime) : Hit(thetubeid,thetime,thecharge), Position(theposition), LocalPosition(thelocalposition) {serialise=true; Pulse1LastTime = pulse1LastTime; Pulse2LastTime = pulse2LastTime; Pulse1StartTime = pulse1StartTime; Pulse2StartTime = pulse2StartTime;} + virtual ~LAPPDHit(){}; inline std::vector GetPosition() const {return Position;} inline std::vector GetLocalPosition() const {return LocalPosition;} inline void SetPosition(std::vector pos){Position=pos;} inline void SetLocalPosition(std::vector locpos){LocalPosition=locpos;} + inline double GetPulse1LastTime() const {return Pulse1LastTime;} + inline double GetPulse2LastTime() const {return Pulse2LastTime;} + inline double GetPulse1StartTime() const {return Pulse1StartTime;} + inline double GetPulse2StartTime() const {return Pulse2StartTime;} bool Print() { cout<<"TubeId : "< Position; std::vector LocalPosition; + double Pulse1LastTime; + double Pulse2LastTime; + double Pulse1StartTime; + double Pulse2StartTime; template void serialize(Archive & ar, const unsigned int version){ if(serialise){ diff --git a/UserTools/Factory/Factory.cpp b/UserTools/Factory/Factory.cpp index c932574cd..a766d2a90 100644 --- a/UserTools/Factory/Factory.cpp +++ b/UserTools/Factory/Factory.cpp @@ -167,5 +167,12 @@ if (tool=="NeutronMultiplicity") ret=new NeutronMultiplicity; if (tool=="PlotsTrackLengthAndEnergy") ret=new PlotsTrackLengthAndEnergy; if (tool=="SaveConfigInfo") ret=new SaveConfigInfo; if (tool=="ReadConfigInfo") ret=new ReadConfigInfo; +if (tool=="LAPPDLoadStore") ret=new LAPPDLoadStore; +if (tool=="LAPPDTreeMaker") ret=new LAPPDTreeMaker; +if (tool=="LAPPDPlots") ret=new LAPPDPlots; +if (tool=="LAPPDThresReco") ret=new LAPPDThresReco; +if (tool=="LAPPDTimeAlignment") ret=new LAPPDTimeAlignment; +if (tool=="LAPPDBaseline") ret=new LAPPDBaseline; +if (tool=="LAPPDStoreReorder") ret=new LAPPDStoreReorder; return ret; } diff --git a/UserTools/LAPPDBaseline/LAPPDBaseline.cpp b/UserTools/LAPPDBaseline/LAPPDBaseline.cpp new file mode 100644 index 000000000..7b9353470 --- /dev/null +++ b/UserTools/LAPPDBaseline/LAPPDBaseline.cpp @@ -0,0 +1,195 @@ +#include "LAPPDBaseline.h" + +LAPPDBaseline::LAPPDBaseline() : Tool() {} + +bool LAPPDBaseline::Initialise(std::string configfile, DataModel &data) +{ + /////////////////// Usefull header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + // bool isBLsub = true; + // m_data->Stores["ANNIEEvent"]->Header->Set("isBLsubtracted",isBLsub); + + m_variables.Get("Nsamples", DimSize); + m_variables.Get("SampleSize", Deltat); + m_variables.Get("TrigChannel", TrigChannel); + m_variables.Get("LowBLfitrange", LowBLfitrange); + m_variables.Get("HiBLfitrange", HiBLfitrange); + m_variables.Get("TrigLowBLfitrange", TrigLowBLfitrange); + m_variables.Get("TrigHiBLfitrange", TrigHiBLfitrange); + m_variables.Get("BLSInputWavLabel", BLSInputWavLabel); + m_variables.Get("BLSOutputWavLabel", BLSOutputWavLabel); + m_variables.Get("BaselineSubstractVerbosityLevel", BLSVerbosityLevel); + m_variables.Get("LAPPDchannelOffset", LAPPDchannelOffset); + execludeAmpDifference = 100; + m_variables.Get("execludeAmpDifference", execludeAmpDifference); + + return true; +} + +bool LAPPDBaseline::Execute() +{ + + bool LAPPDana = false; + + m_data->CStore.Get("LAPPDana", LAPPDana); + if (!LAPPDana) + { + return true; + } + else + { + if (BLSVerbosityLevel > 1) + cout << "YES LAPPD Data found in baselinesub" << endl; + } + + bool isBLsub = true; + m_data->Stores["ANNIEEvent"]->Set("isBLsubtracted", isBLsub); + if (BLSVerbosityLevel > 2) + cout << "Made it to here " << BLSInputWavLabel << " is read in." << endl; + Waveform bwav; + + std::map>> lappddata; + m_data->Stores["ANNIEEvent"]->Get(BLSInputWavLabel, lappddata); + if (BLSVerbosityLevel > 2) + cout << "And data is loaded" << endl; + // the filtered Waveform + std::map>> blsublappddata; + + map>>::iterator itr; + for (itr = lappddata.begin(); itr != lappddata.end(); ++itr) + { + int channelno = itr->first; + channelno = channelno%1000 + 1000; + vector> Vwavs = itr->second; + vector> Vfwavs; + int bi = (int)(channelno - LAPPDchannelOffset) / 30; + + // loop over all Waveforms + for (int i = 0; i < Vwavs.size(); i++) + { + + Waveform bwav = Vwavs.at(i); + + // This is from back when we had a sinusoidal pedestal + // Waveform blswav = SubtractSine(bwav); + + // Loop over first N samples and get average value + if (LowBLfitrange > DimSize || HiBLfitrange > DimSize) + { + cout << "BASELINE FITRANGE IS WRONG!!! " << LowBLfitrange << " " << HiBLfitrange << endl; + LowBLfitrange = 0; + HiBLfitrange = 1; + } + + if (TrigLowBLfitrange > DimSize || TrigHiBLfitrange > DimSize) + { + cout << "BASELINE FITRANGE IS WRONG!!! " << TrigLowBLfitrange << " " << TrigHiBLfitrange << endl; + TrigLowBLfitrange = 0; + TrigHiBLfitrange = 1; + } + + double BLval = 0; + int execuldedBins = 0; + + if (channelno == (LAPPDchannelOffset + (30 * bi) + TrigChannel)) + { + for (int j = TrigLowBLfitrange; j < TrigHiBLfitrange; j++) + { + if (j > 0) + { + if (abs(bwav.GetSamples()->at(j) - bwav.GetSamples()->at(j - 1)) < execludeAmpDifference) + BLval += bwav.GetSamples()->at(j); + else + execuldedBins++; + } + else + { + BLval += bwav.GetSamples()->at(j); + } + } + } + else + { + for (int j = LowBLfitrange; j < HiBLfitrange; j++) + { + if (j > 0) + { + if (abs(bwav.GetSamples()->at(j) - bwav.GetSamples()->at(j - 1)) < execludeAmpDifference) + BLval += bwav.GetSamples()->at(j); + else + execuldedBins++; + } + else + { + BLval += bwav.GetSamples()->at(j); + } + } + } + + double AvgBL = BLval / ((double)(HiBLfitrange - LowBLfitrange - execuldedBins)); + + Waveform blswav; + for (int k = 0; k < bwav.GetSamples()->size(); k++) + { + blswav.PushSample((bwav.GetSamples()->at(k)) - AvgBL); + } + + Vfwavs.push_back(blswav); + } + + blsublappddata.insert(pair>>(channelno, Vfwavs)); + } + + if (BLSVerbosityLevel > 2) + cout << "Baseline substraction is done in " << BLSOutputWavLabel << endl; + m_data->Stores["ANNIEEvent"]->Set(BLSOutputWavLabel, blsublappddata); + + return true; +} + +Waveform LAPPDBaseline::SubtractSine(Waveform iwav) +{ + Waveform subWav; + + int nbins = iwav.GetSamples()->size(); + double starttime = 0.; + double endtime = starttime + ((double)nbins) * 100.; + TH1D *hwav_raw = new TH1D("hwav_raw", "hwav_raw", nbins, starttime, endtime); + + for (int i = 0; i < nbins; i++) + { + hwav_raw->SetBinContent(i + 1, iwav.GetSample(i)); + hwav_raw->SetBinError(i + 1, 0.1); + } + + TF1 *sinit = new TF1("sinit", "([0]*sin([2]*x+[1]))", 0, DimSize * Deltat); + sinit->SetParameter(0, 0.4); + sinit->SetParameter(1, 0.0); + sinit->SetParameter(2, 0.0); + sinit->SetParameter(2, 0.00055); + sinit->SetParLimits(2, 0.0003, 0.0008); + sinit->SetParLimits(0, 0., 1.0); + + hwav_raw->Fit("sinit", "QNO", "", LowBLfitrange, HiBLfitrange); + // cout<<"Parameters: "<< sinit->GetParameter(3)<<" "<GetBinContent(j + 1)) - (sinit->Eval(hwav_raw->GetBinCenter(j + 1)))); + } + + delete hwav_raw; + delete sinit; + return subWav; +} + +bool LAPPDBaseline::Finalise() +{ + return true; +} diff --git a/UserTools/LAPPDBaseline/LAPPDBaseline.h b/UserTools/LAPPDBaseline/LAPPDBaseline.h new file mode 100644 index 000000000..34ac201d7 --- /dev/null +++ b/UserTools/LAPPDBaseline/LAPPDBaseline.h @@ -0,0 +1,44 @@ +#ifndef LAPPDBaseline_H +#define LAPPDBaseline_H + + +#include +#include + +#include "TH1.h" +#include "TF1.h" +#include "Tool.h" + +class LAPPDBaseline: public Tool { + + + public: + + LAPPDBaseline(); + bool Initialise(std::string configfile,DataModel &data); + bool Execute(); + bool Finalise(); + + + private: + + Waveform SubtractSine(Waveform iwav); + int LAPPDchannelOffset; + int BLSVerbosityLevel; + bool isSim; + int DimSize; + int TrigChannel; + double Deltat; + double LowBLfitrange; + double HiBLfitrange; + double TrigLowBLfitrange; + double TrigHiBLfitrange; + string BLSInputWavLabel; + string BLSOutputWavLabel; + + double execludeAmpDifference; + +}; + + +#endif diff --git a/UserTools/LAPPDBaseline/README.md b/UserTools/LAPPDBaseline/README.md new file mode 100644 index 000000000..2b28737d8 --- /dev/null +++ b/UserTools/LAPPDBaseline/README.md @@ -0,0 +1,20 @@ +# LAPPDBaseline + +LAPPDBaseline + +## Data + +Describe any data formats LAPPDBaseline creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for LAPPDBaseline. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp new file mode 100644 index 000000000..76794db28 --- /dev/null +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp @@ -0,0 +1,1168 @@ +#include "LAPPDLoadStore.h" + +LAPPDLoadStore::LAPPDLoadStore() : Tool() {} + +bool LAPPDLoadStore::Initialise(std::string configfile, DataModel &data) +{ + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + // Control variables + // Control variables used in this tool + retval = 0; + eventNo = 0; + CLOCK_to_NSEC = 3.125; // 3.125 ns per clock cycle + errorEventsNumber = 0; + // Control variables that you get from the config file, for this tool + m_variables.Get("ReadStore", ReadStore); + m_variables.Get("Nboards", Nboards); + m_variables.Get("StorePedinputfile", PedFileName); + m_variables.Get("PedinputfileTXT", PedFileNameTXT); + m_variables.Get("DoPedSubtraction", DoPedSubtract); + m_variables.Get("LAPPDStoreReadInVerbosity", LAPPDStoreReadInVerbosity); + m_variables.Get("num_vector_data", num_vector_data); + m_variables.Get("num_vector_pps", num_vector_pps); + m_variables.Get("SelectSingleLAPPD", SelectSingleLAPPD); + m_variables.Get("SelectedLAPPD", SelectedLAPPD); + mergingModeReadIn = false; + m_variables.Get("mergingModeReadIn", mergingModeReadIn); + ReadStorePdeFile = false; + m_variables.Get("ReadStorePdeFile", ReadStorePdeFile); + MultiLAPPDMap = false; + m_variables.Get("MultiLAPPDMap", MultiLAPPDMap); + loadPSEC = true; + m_variables.Get("loadPSEC", loadPSEC); + loadPPS = false; + m_variables.Get("loadPPS", loadPPS); + loadOffsets = false; + m_variables.Get("loadOffsets", loadOffsets); + // Control variables in this tool, initialized in this tool + NonEmptyEvents = 0; + PPSnumber = 0; + isFiltered = false; + isBLsub = false; + isCFD = false; + // Global Control variables that you get from the config file + m_variables.Get("stopEntries", stopEntries); + m_variables.Get("PsecReceiveMode", PsecReceiveMode); + m_variables.Get("RawDataOutputWavLabel", OutputWavLabel); + m_variables.Get("RawDataInputWavLabel", InputWavLabel); + m_variables.Get("NChannels", NChannels); + m_variables.Get("Nsamples", Nsamples); + m_variables.Get("TrigChannel", TrigChannel); + m_variables.Get("SampleSize", SampleSize); + m_variables.Get("LAPPDchannelOffset", LAPPDchannelOffset); + // Data variables + // Data variables you get from other tools (it not initialized in execute) + // Data variables you use in this tool + m_variables.Get("PSECinputfile", NewFileName); + // Verbosity + // Details on channels, samples and max vector sizes and trigger channel + m_variables.Get("Nsamples", Nsamples); + m_variables.Get("TrigChannel", TrigChannel); + + runNumber = 0; + subRunNumber = 0; + partFileNumber = 0; + eventNumberInPF = 0; + + // get data file + if (ReadStore == 1) + { + // get data from a StoreFile in ANNIEEvent format + m_data->Stores["ANNIEEvent"] = new BoostStore(false, 2); + m_data->Stores["ANNIEEvent"]->Initialise(NewFileName); + cout << "LAPPDStoreReadIn Reading new ANNIEevent from " << NewFileName << endl; + } + else if (ReadStore == 0) + { // get data from previous chain, or m_data + cout << "LAPPDStoreReadIn Using ANNIEevent or CStore" << endl; + } + // Grab all pedestal files and prepare the map channel|pedestal-vector for substraction + if (DoPedSubtract == 1) + { + PedestalValues = new std::map>; + if (ReadStorePdeFile) + { + m_data->Stores["PedestalFile"] = new BoostStore(false, 2); + bool ret = false; + if (FILE *file = fopen(PedFileName.c_str(), "r")) + { + fclose(file); + ret = true; + cout << "Using Store Pedestal File" << endl; + } + if (ret) + { + m_data->Stores["PedestalFile"]->Initialise(PedFileName); + long Pedentries; + m_data->Stores["PedestalFile"]->Header->Get("TotalEntries", Pedentries); + if (LAPPDStoreReadInVerbosity > 0) + cout << PedFileName << " got " << Pedentries << endl; + m_data->Stores["PedestalFile"]->Get("PedestalMap", PedestalValues); + } + } + else + { + for (int i = 0; i < Nboards; i++) + { + if (LAPPDStoreReadInVerbosity > 0) + cout << "Reading Pedestal File " << PedFileNameTXT << " " << i << endl; + ReadPedestals(i); + } + } + if (LAPPDStoreReadInVerbosity > 0) + cout << "PEDSIZES: " << PedestalValues->size() << " " << PedestalValues->at(0).size() << " " << PedestalValues->at(4).at(5) << endl; + } + + // set some control variables for later tools + m_data->CStore.Set("SelectSingleLAPPD", SelectSingleLAPPD); + m_data->Stores["ANNIEEvent"]->Set("Nsamples", Nsamples); + m_data->Stores["ANNIEEvent"]->Set("NChannels", NChannels); + m_data->Stores["ANNIEEvent"]->Set("TrigChannel", TrigChannel); + m_data->Stores["ANNIEEvent"]->Set("LAPPDchannelOffset", LAPPDchannelOffset); + m_data->Stores["ANNIEEvent"]->Set("SampleSize", SampleSize); + m_data->Stores["ANNIEEvent"]->Set("isFiltered", isFiltered); + m_data->Stores["ANNIEEvent"]->Set("isBLsubtracted", isBLsub); + m_data->Stores["ANNIEEvent"]->Set("isCFD", isCFD); + + if (loadOffsets) + LoadOffsetsAndCorrections(); + debugStoreReadIn.open("debugStoreReadIn.txt"); + + return true; +} + +void LAPPDLoadStore::CleanDataObjects() +{ + LAPPD_ID = -9999; + Raw_buffer.clear(); + Parse_buffer.clear(); + ReadBoards.clear(); + data.clear(); + meta.clear(); + pps.clear(); + LAPPDWaveforms.clear(); + EventType = -9999; + LAPPDana = false; + ParaBoards.clear(); + meta.clear(); + LAPPDWaveforms.clear(); + data.clear(); + Parse_buffer.clear(); + LAPPDDataMap.clear(); + runInfoLoaded = false; +} + +bool LAPPDLoadStore::Execute() +{ + // 1. clean data variables + // 2. decide loading data or not, load the data from PsecData dat to tool + // 3. parse and pass data to later tools + + CleanDataObjects(); + m_data->CStore.Set("LAPPD_new_event", false); + + // decide loading data or not, set to LAPPDana for later tools + LAPPDana = LoadData(); + m_data->CStore.Set("LAPPDana", LAPPDana); + if (!LAPPDana) + { + // not loading data, return + return true; + } + + if (!MultiLAPPDMap) + { + // parse and pass data to later tools + int frametype = static_cast(Raw_buffer.size() / ReadBoards.size()); + if (frametype != num_vector_data && frametype != num_vector_pps) + { + cout << "Problem identifying the frametype, size of raw vector was " << Raw_buffer.size() << endl; + cout << "It was expected to be either " << num_vector_data * ReadBoards.size() << " or " << num_vector_pps * ReadBoards.size() << endl; + cout << "Please check manually!" << endl; + LAPPDana = false; + m_data->CStore.Set("LAPPDana", LAPPDana); + m_data->CStore.Set("LAPPDPPShere", LAPPDana); + return true; + } + + if (frametype == num_vector_pps && loadPPS) + { + // if it's PPS, don't to anything relate to merging + m_data->CStore.Set("LAPPDanaData", false); + // set LAPPDana to false + LAPPDana = false; + m_data->CStore.Set("LAPPDana", LAPPDana); + ParsePPSData(); + m_data->CStore.Set("LAPPD_ID", LAPPD_ID); + m_data->Stores["ANNIEEvent"]->Set("LAPPD_ID", LAPPD_ID); + m_data->CStore.Set("LoadingPPS", true); + if (LAPPDStoreReadInVerbosity > 0) + cout << "LAPPDStoreReadIn: PPS data loaded, LAPPDanaData is false, set LAPPDana to false" << endl; + return true; + } + + if (frametype == num_vector_data && loadPSEC) + { + m_data->CStore.Set("LAPPDanaData", true); + bool parsData = ParsePSECData(); + LoadRunInfo(); + runInfoLoaded = true; + LAPPDana = parsData; + m_data->CStore.Set("LAPPDana", LAPPDana); + m_data->CStore.Set("LoadingPPS", false); + + if (!parsData) + { + cout << "LAPPDStoreReadIn: PSEC data parsing failed, set LAPPDana to false and return" << endl; + + return true; + } + } + + // parsing finished, do pedestal subtraction + DoPedestalSubtract(); + // save some timestamps relate to this event, for later using + SaveTimeStamps(); + + if (LAPPDStoreReadInVerbosity > 0) + cout << "*************************END LAPPDStoreReadIn************************************" << endl; + m_data->CStore.Set("LAPPD_ID", LAPPD_ID); + m_data->Stores["ANNIEEvent"]->Set("LAPPD_ID", LAPPD_ID); + m_data->Stores["ANNIEEvent"]->Set("RawLAPPDData", LAPPDWaveforms); // leave this only for the merger tool + m_data->Stores["ANNIEEvent"]->Set("MergeLAPPDPsec", LAPPDWaveforms); + m_data->Stores["ANNIEEvent"]->Set("ACDCmetadata", meta); + m_data->Stores["ANNIEEvent"]->Set("ACDCboards", ReadBoards); + m_data->Stores["ANNIEEvent"]->Set("SortedBoards", ParaBoards); + m_data->Stores["ANNIEEvent"]->Set("TriggerChannelBase", TrigChannel); + + m_data->CStore.Set("NewLAPPDDataAvailable",true); + debugStoreReadIn<< " Set NewLAPPDDataAvailable to true"< 2) + { + cout << "Finish LAPPDStoreReadIn, Printing the ANNIEEvent" << endl; + m_data->Stores["ANNIEEvent"]->Print(false); + } + } + else + { + // if we are reading multiple LAPPD data from one ANNIEEvent + // assume we only have PSEC data in ANNIEEvent, no PPS event. + // loop the map, for each PSEC data, do the same loading and parsing. + // load the waveform by using LAPPD_ID * board_number * channel_number as the key + if (LAPPDStoreReadInVerbosity > 0) + cout << "LAPPDStoreReadIn: LAPPDDataMap has " << LAPPDDataMap.size() << " LAPPD PSEC data " << endl; + bool ValidDataLoaded = false; + std::map::iterator it; + for (it = LAPPDDataMap.begin(); it != LAPPDDataMap.end(); it++) + { + unsigned long time = it->first; + PsecData dat = it->second; + + ReadBoards = dat.BoardIndex; + Raw_buffer = dat.RawWaveform; + LAPPD_ID = dat.LAPPD_ID; + if (LAPPD_ID != SelectedLAPPD && SelectSingleLAPPD) + continue; + + int frametype = static_cast(Raw_buffer.size() / ReadBoards.size()); + if (frametype != num_vector_data) + { + cout << "LAPPDStoreReadIn: For LAPPD_ID " << LAPPD_ID << " frametype is not num_vector_data, skip this LAPPD" << endl; + continue; + } + m_data->CStore.Set("LAPPDanaData", true); + bool parsData = ParsePSECData(); // TODO: now assuming all boards just has 30 channels. Need to be changed for gen 2 + if (parsData) + ValidDataLoaded = true; + } + LAPPDana = ValidDataLoaded; + m_data->CStore.Set("LAPPDana", LAPPDana); + DoPedestalSubtract(); + + m_data->Stores["ANNIEEvent"]->Set("RawLAPPDData", LAPPDWaveforms); // leave this only for the merger tool + // TODO: save other timestamps, variables and metadata for later use + } + + return true; +} + +bool LAPPDLoadStore::Finalise() +{ + cout << "Got pps event in total: " << PPSnumber << endl; + cout << "Got error events in total: " << errorEventsNumber << endl; + cout << "Got non empty events in total: " << NonEmptyEvents << endl; + cout << "Got event in total: " << eventNo << endl; + return true; +} + +bool LAPPDLoadStore::ReadPedestals(int boardNo) +{ + + if (LAPPDStoreReadInVerbosity > 0) + cout << "Getting Pedestals " << boardNo << endl; + + std::string LoadName = PedFileNameTXT; + string nextLine; // temp line to parse + double finalsampleNo; + std::string ext = std::to_string(boardNo); + ext += ".txt"; + LoadName += ext; + PedFile.open(LoadName); // final name: PedFileNameTXT + boardNo + .txt + if (!PedFile.is_open()) + { + cout << "Failed to open " << LoadName << "!" << endl; + return false; + } + if (LAPPDStoreReadInVerbosity > 0) + cout << "Opened file: " << LoadName << endl; + + int sampleNo = 0; // sample number + while (getline(PedFile, nextLine)) + { + istringstream iss(nextLine); // copies the current line in the file + int location = -1; // counts the current perameter in the line + string stempValue; // current string in the line + int tempValue; // current int in the line + unsigned long channelNo = boardNo * 30; // channel number + // cout<<"NEW BOARD "<> stempValue) + { + location++; + int tempValue = stoi(stempValue, 0, 10); + if (sampleNo == 0) + { + vector tempPed; + tempPed.push_back(tempValue); + // cout<<"First time: "<insert(pair>(channelNo, tempPed)); + if (LAPPDStoreReadInVerbosity > 0) + cout << "Inserting pedestal at channelNo " << channelNo << endl; + // newboard=false; + } + else + { + // cout<<"Following time: "<count(channelNo)<find(channelNo))->second)).push_back(tempValue); + } + + channelNo++; + } + sampleNo++; + } + if (LAPPDStoreReadInVerbosity > 0) + cout << "FINAL SAMPLE NUMBER: " << PedestalValues->size() << " " << (((PedestalValues->find(0))->second)).size() << endl; + PedFile.close(); + return true; +} + +bool LAPPDLoadStore::MakePedestals() +{ + + // Empty for now... + // should be moved to ASCII readin? + + return true; +} + +int LAPPDLoadStore::getParsedMeta(std::vector buffer, int BoardId) +{ + // Catch empty buffers + if (buffer.size() == 0) + { + std::cout << "You tried to parse ACDC data without pulling/setting an ACDC buffer" << std::endl; + return -1; + } + + // Prepare the Metadata vector + // meta.clear(); + + // Helpers + int chip_count = 0; + + // Indicator words for the start/end of the metadata + const unsigned short startword = 0xBA11; + unsigned short endword = 0xFACE; + unsigned short endoffile = 0x4321; + + // Empty metadata map for each Psec chip + map> PsecInfo; + + // Empty trigger metadata map for each Psec chip + map> PsecTriggerInfo; + unsigned short CombinedTriggerRateCount; + + // Empty vector with positions of aboves startword + vector start_indices = + { + 1539, 3091, 4643, 6195, 7747}; + + // Fill the psec info map + vector::iterator bit; + for (int i : start_indices) + { + // Write the first word after the startword + bit = buffer.begin() + (i + 1); + + // As long as the endword isn't reached copy metadata words into a vector and add to map + vector InfoWord; + while (*bit != endword && *bit != endoffile && InfoWord.size() < 14) + { + InfoWord.push_back(*bit); + ++bit; + } + PsecInfo.insert(pair>(chip_count, InfoWord)); + chip_count++; + } + + // Fill the psec trigger info map + for (int chip = 0; chip < NUM_PSEC; chip++) + { + for (int ch = 0; ch < NUM_CH / NUM_PSEC; ch++) + { + if (LAPPDStoreReadInVerbosity > 10) + cout << "parsing meta step1-1" << endl; + // Find the trigger data at begin + last_metadata_start + 13_info_words + 1_end_word + 1 + bit = buffer.begin() + start_indices[4] + 13 + 1 + 1 + ch + (chip * (NUM_CH / NUM_PSEC)); + if (LAPPDStoreReadInVerbosity > 10) + cout << "parsing meta step1-2" << endl; + PsecTriggerInfo[chip].push_back(*bit); + } + } + + if (LAPPDStoreReadInVerbosity > 10) + cout << "parsing meta step1.5" << endl; + // Fill the combined trigger + CombinedTriggerRateCount = buffer[7792]; + + //---------------------------------------------------------- + // Start the metadata parsing + + meta.push_back(BoardId); + for (int CHIP = 0; CHIP < NUM_PSEC; CHIP++) + { + meta.push_back((0xDCB0 | CHIP)); + // cout<<"size of info word is "< 10) + cout << "parsing meta step2-1 infoword " << INFOWORD << endl; + if (PsecInfo[CHIP].size() < 13) + { + NonEmptyEvents = NonEmptyEvents - 1; + cout << "meta data parsing wrong! PsecInfo[CHIP].size() < 13" << endl; + m_data->CStore.Set("LAPPDana", false); + return 1; + } + + try + { + meta.push_back(PsecInfo[CHIP][INFOWORD]); + } + catch (...) + { + NonEmptyEvents = NonEmptyEvents - 1; + cout << "meta data parsing wrong! meta.push_back(PsecInfo[CHIP][INFOWORD]);" << endl; + m_data->CStore.Set("LAPPDana", false); + return 1; + } + } + for (int TRIGGERWORD = 0; TRIGGERWORD < 6; TRIGGERWORD++) + { + if (LAPPDStoreReadInVerbosity > 10) + cout << "parsing meta step2-2 trigger word" << endl; + + if (PsecTriggerInfo[CHIP].size() < 6) + { + NonEmptyEvents = NonEmptyEvents - 1; + cout << "meta data parsing wrong! PsecTriggerInfo[CHIP].size() < 6" << endl; + m_data->CStore.Set("LAPPDana", false); + return 1; + } + + try + { + meta.push_back(PsecTriggerInfo[CHIP][TRIGGERWORD]); + } + catch (...) + { + NonEmptyEvents = NonEmptyEvents - 1; + cout << "meta data parsing wrong! meta.push_back(PsecTriggerInfo[CHIP][TRIGGERWORD]);" << endl; + m_data->CStore.Set("LAPPDana", false); + return 1; + } + } + } + + meta.push_back(CombinedTriggerRateCount); + meta.push_back(0xeeee); + return 0; +} + +int LAPPDLoadStore::getParsedData(std::vector buffer, int ch_start) +{ + // Catch empty buffers + if (buffer.size() == 0) + { + std::cout << "You tried to parse ACDC data without pulling/setting an ACDC buffer" << std::endl; + return -1; + } + + // Helpers + int DistanceFromZero; + int channel_count = 0; + + // Indicator words for the start/end of the metadata + const unsigned short startword = 0xF005; + unsigned short endword = 0xBA11; + unsigned short endoffile = 0x4321; + + // Empty vector with positions of aboves startword + vector start_indices = + { + 2, 1554, 3106, 4658, 6210}; + + // Fill data map + vector::iterator bit; + for (int i : start_indices) + { + // Write the first word after the startword + bit = buffer.begin() + (i + 1); + + // As long as the endword isn't reached copy metadata words into a vector and add to map + vector InfoWord; + while (*bit != endword && *bit != endoffile) + { + InfoWord.push_back((unsigned short)*bit); + if (InfoWord.size() == NUM_SAMP) + { + data.insert(pair>(ch_start + channel_count, InfoWord)); + InfoWord.clear(); + channel_count++; + } + ++bit; + } + } + + return 0; +} + +bool LAPPDLoadStore::LoadData() +{ + // TODO: when looping in Stores["ANNIEEvent"], the multiple PSEC data will be saved in std::map LAPPDDatas; + // so we need to loop the map to get all data and waveforms, using the LAPPD_ID, board number, channel number to form a global channel-waveform map + // then loop all waveforms based on channel number + + m_data->Stores["ANNIEEvent"]->GetEntry(eventNo); + if (LAPPDStoreReadInVerbosity > 2) + cout << "Got eventNo " << eventNo << endl; + + // if loaded enough events, stop the loop and return false + if (NonEmptyEvents == stopEntries) + { + if (LAPPDStoreReadInVerbosity > 0) + cout << "LAPPDStoreReadIn: NonEmptyEvents is " << NonEmptyEvents << ", stopEntries is " << stopEntries << ", stop the loop" << endl; + m_data->vars.Set("StopLoop", 1); + return false; + } + + std::map DataStreams; + m_data->Stores["ANNIEEvent"]->Get("DataStreams", DataStreams); + if (mergedEvent) + DataStreams["LAPPD"] = true; + + if (loadPSEC || loadPPS) + { // if load any kind of data + // if there is no LAPPD data in event store, and not getting data from CStore, return false, don't load + if (!DataStreams["LAPPD"] && PsecReceiveMode == 0) + { + return false; + } + else if (PsecReceiveMode == 1) // no LAPPD data in event store, but load from CStore (for merging LAPPD to ANNIEEvent) + { // only get PSEC data from CStore, no PPS + // if loading from raw data, and the loading was set to pause, return false + bool LAPPDRawLoadingPaused = false; + m_data->CStore.Get("PauseLAPPDDecoding", LAPPDRawLoadingPaused); + if (LAPPDRawLoadingPaused){ + m_data->CStore.Set("NewLAPPDDataAvailable",false); + return false; + } + + + PsecData dat; + bool getData = m_data->CStore.Get("LAPPDData", dat); + if(getData){ + m_data->CStore.Set("StoreLoadedLAPPDData",dat); + } + if (LAPPDStoreReadInVerbosity > 0) + cout << "LAPPDStoreReadIn: getting LAPPDData from CStore" << endl; + bool mergingLoad; + // if in merging mode, but no LAPPD data in CStore, return false, don't load + m_data->CStore.Get("LAPPDanaData", mergingLoad); + if (!mergingLoad && mergingModeReadIn) + { + if (LAPPDStoreReadInVerbosity > 0) + cout << "LAPPDStoreReadIn: mergingMode is true but LAPPDanaData is false, set LAPPDana to false" << endl; + return false; + } + if (getData) + { + vector errorcodes = dat.errorcodes; + if (errorcodes.size() == 1 && errorcodes[0] == 0x00000000) + { + if (LAPPDStoreReadInVerbosity > 1) + printf("No errorcodes found all good: 0x%08x\n", errorcodes[0]); + } + else + { + printf("When Loading PPS: Errorcodes found: %li\n", errorcodes.size()); + for (unsigned int k = 0; k < errorcodes.size(); k++) + { + printf("Errorcode: 0x%08x\n", errorcodes[k]); + } + errorEventsNumber++; + return false; + } + ReadBoards = dat.BoardIndex; + Raw_buffer = dat.RawWaveform; + LAPPD_ID = dat.LAPPD_ID; + if (LAPPD_ID != SelectedLAPPD && SelectSingleLAPPD) + return false; + m_data->CStore.Set("PsecTimestamp", dat.Timestamp); + if (LAPPDStoreReadInVerbosity > 2) + { + cout << " Got Data " << endl; + dat.Print(); + } + int frameType = static_cast(Raw_buffer.size() / ReadBoards.size()); + if (LAPPDStoreReadInVerbosity > 0) + cout << "LAPPDStoreReadIn: got Data from CStore, frame type is " << frameType << endl; + if (loadPSEC) + { + if (frameType == num_vector_data) + { + m_data->CStore.Set("LoadingPPS", false); + return true; + } + } + if (loadPPS) + { + if (frameType == num_vector_pps) + { + m_data->CStore.Set("LoadingPPS", true); + return true; + } + } + return false; + } + else + { + return false; + } + } + else if (DataStreams["LAPPD"] && PsecReceiveMode == 0) + { + PsecData dat; + m_data->Stores["ANNIEEvent"]->Get("LAPPDData", dat); + ReadBoards = dat.BoardIndex; + Raw_buffer = dat.RawWaveform; + LAPPD_ID = dat.LAPPD_ID; + if (LAPPD_ID != SelectedLAPPD && SelectSingleLAPPD) + return false; + m_data->CStore.Set("PsecTimestamp", dat.Timestamp); + + if (Raw_buffer.size() != 0 || ReadBoards.size() != 0) + { + if (LAPPDStoreReadInVerbosity > 0) + { + cout << "Getting data length format" << static_cast(Raw_buffer.size() / ReadBoards.size()) << ", psec timestamp is " << dat.Timestamp << endl; + cout << "ReadBoards size " << ReadBoards.size() << " Raw_buffer size " << Raw_buffer.size() << " LAPPD_ID " << LAPPD_ID << endl; + } + } + else + { + cout << "LAPPDStoreReadIn: loading data with raw buffer size 0 or ReadBoards size 0, skip loading" << endl; + cout << "ReadBoards size " << ReadBoards.size() << " Raw_buffer size " << Raw_buffer.size() << " LAPPD_ID " << LAPPD_ID << endl; + + return false; + } + return true; + } + else if (DataStreams["LAPPD"] && MultiLAPPDMap) + { + bool getMap = m_data->Stores["ANNIEEvent"]->Get("LAPPDDataMap", LAPPDDataMap); + if (LAPPDStoreReadInVerbosity > 0) + cout << "LAPPDStoreReadIn: getting LAPPDDataMap from ANNIEEvent" << endl; + if (getMap) + return true; + } + } + return false; // if not any of the above, return false +} + +void LAPPDLoadStore::ParsePPSData() +{ + if (LAPPDStoreReadInVerbosity > 0) + cout << "Loading PPS frame size " << pps.size() << endl; + std::vector pps = Raw_buffer; + std::vector pps_vector; + std::vector pps_count_vector; + + unsigned long pps_timestamp = 0; + unsigned long ppscount = 0; + for (int s = 0; s < ReadBoards.size(); s++) + { + unsigned short pps_63_48 = pps.at(2 + 16 * s); + unsigned short pps_47_32 = pps.at(3 + 16 * s); + unsigned short pps_31_16 = pps.at(4 + 16 * s); + unsigned short pps_15_0 = pps.at(5 + 16 * s); + std::bitset<16> bits_pps_63_48(pps_63_48); + std::bitset<16> bits_pps_47_32(pps_47_32); + std::bitset<16> bits_pps_31_16(pps_31_16); + std::bitset<16> bits_pps_15_0(pps_15_0); + unsigned long pps_63_0 = (static_cast(pps_63_48) << 48) + (static_cast(pps_47_32) << 32) + (static_cast(pps_31_16) << 16) + (static_cast(pps_15_0)); + if (LAPPDStoreReadInVerbosity > 0) + std::cout << "pps combined: " << pps_63_0 << std::endl; + std::bitset<64> bits_pps_63_0(pps_63_0); + // pps_timestamp = pps_63_0 * (CLOCK_to_NSEC); // NOTE: Don't do convert to ns because of the precision, do this in later tools + pps_timestamp = pps_63_0; + // LAPPDPPS->push_back(pps_timestamp); + if (LAPPDStoreReadInVerbosity > 0) + std::cout << "Adding timestamp " << pps_timestamp << " to LAPPDPPS" << std::endl; + pps_vector.push_back(pps_timestamp); + + unsigned short ppscount_31_16 = pps.at(8 + 16 * s); + unsigned short ppscount_15_0 = pps.at(9 + 16 * s); + std::bitset<16> bits_ppscount_31_16(ppscount_31_16); + std::bitset<16> bits_ppscount_15_0(ppscount_15_0); + unsigned long ppscount_31_0 = (static_cast(ppscount_31_16) << 16) + (static_cast(ppscount_15_0)); + if (LAPPDStoreReadInVerbosity > 0) + std::cout << "pps count combined: " << ppscount_31_0 << std::endl; + std::bitset<32> bits_ppscount_31_0(ppscount_31_0); + ppscount = ppscount_31_0; + pps_count_vector.push_back(ppscount); + + if (LAPPDStoreReadInVerbosity > 8) + { + // Print the bitsets + cout << "******************************" << endl; + std::cout << "printing ACDC " << s << ": " << endl; + std::cout << "bits_pps_63_48: " << bits_pps_63_48 << std::endl; + std::cout << "bits_pps_47_32: " << bits_pps_47_32 << std::endl; + std::cout << "bits_pps_31_16: " << bits_pps_31_16 << std::endl; + std::cout << "bits_pps_15_0: " << bits_pps_15_0 << std::endl; + // Print the unsigned shorts + std::cout << "pps_63_48: " << pps_63_48 << std::endl; + std::cout << "pps_47_32: " << pps_47_32 << std::endl; + std::cout << "pps_31_16: " << pps_31_16 << std::endl; + std::cout << "pps_15_0: " << pps_15_0 << std::endl; + std::cout << "pps_63_0: " << pps_63_0 << std::endl; + std::cout << "pps_63_0 after conversion in double: " << pps_timestamp << endl; + + for (int x = 0; x < 16; x++) + { + std::bitset<16> bit_pps_here(pps.at(x + 16 * s)); + cout << "unsigned short at " << x << " : " << pps.at(x + 16 * s) << ", bit at " << x << " is: " << bit_pps_here << endl; + ; + } + } + } + + // double ppsDiff = static_cast(pps_vector.at(0)) - static_cast(pps_vector.at(1)); + unsigned long ppsDiff = pps_vector.at(0) - pps_vector.at(1); + m_data->CStore.Set("LAPPDPPScount0", pps_count_vector.at(0)); + m_data->CStore.Set("LAPPDPPScount1", pps_count_vector.at(1)); + m_data->CStore.Set("LAPPDPPScount", pps_count_vector); + m_data->CStore.Set("LAPPDPPSDiff0to1", ppsDiff); + m_data->CStore.Set("LAPPDPPSVector", pps_vector); + + m_data->CStore.Set("LAPPDPPStimestamp0", pps_vector.at(0)); + m_data->CStore.Set("LAPPDPPStimestamp1", pps_vector.at(1)); + m_data->CStore.Set("LAPPDPPShere", true); + m_data->CStore.Set("LAPPD_ID", LAPPD_ID); + + PPSnumber++; +} + +bool LAPPDLoadStore::ParsePSECData() +{ + if (LAPPDStoreReadInVerbosity > 0) + std::cout << "PSEC Data Frame was read! Starting the parsing!" << std::endl; + + // while loading single PsecData Object, parse the data by LAPPDID and number of boards on each LAPPD and channel on each board + // Create a vector of paraphrased board indices + // the board indices goes with LAPPD ID. For example, LAPPD ID = 2, we will have board = 4,5 + // this need to be converted to 0,1 + int nbi = ReadBoards.size(); + if (LAPPDStoreReadInVerbosity > 0 && nbi != 2) + cout << "Number of board is " << nbi << endl; + if (nbi == 0) + { + cout << "LAPPDStoreReadIn: error here! number of board is 0" << endl; + errorEventsNumber++; + return false; + } + if (nbi % 2 != 0) + { + errorEventsNumber++; + cout << "LAPPDStoreReadIn: uneven number of boards in this event" << endl; + if (nbi == 1) + { + ParaBoards.push_back(ReadBoards[0]); + } + else + { + return false; + } + } + else + { + for (int cbi = 0; cbi < nbi; cbi++) + { + ParaBoards.push_back(cbi); + if (LAPPDStoreReadInVerbosity > 2) + cout << "Board " << cbi << " is added to the list of boards to be parsed!" << endl; + } + } + // loop all boards, 0, 1 + for (int bi : ParaBoards) + { + Parse_buffer.clear(); + if (LAPPDStoreReadInVerbosity > 2) + std::cout << "Starting with board " << ReadBoards[bi] << std::endl; + // Go over all ACDC board data frames by seperating them + int frametype = static_cast(Raw_buffer.size() / ReadBoards.size()); + for (int c = bi * frametype; c < (bi + 1) * frametype; c++) + { + Parse_buffer.push_back(Raw_buffer[c]); + } + if (LAPPDStoreReadInVerbosity > 2) + std::cout << "Data for board " << ReadBoards[bi] << " was grabbed!" << std::endl; + + // Grab the parsed data and give it to a global variable 'data' + // insert the data start with channel number 30*ReadBoards[bi] + // for instance, when bi=0 , LAPPD ID = 2, ReadBoards[bi] = 4, insert to channel number start with 120, to 150 + retval = getParsedData(Parse_buffer, ReadBoards[bi] * NUM_CH); //(because there are only 2 boards, so it's 0*30 or 1*30). Inserting the channel number start from this then ++ to 30 + if (retval == 0) + { + if (LAPPDStoreReadInVerbosity > 2) + std::cout << "Data for board " << ReadBoards[bi] << " was parsed!" << std::endl; + // Grab the parsed metadata and give it to a global variable 'meta' + retval = getParsedMeta(Parse_buffer, ReadBoards[bi]); + if (retval != 0) + { + std::cout << "Meta parsing went wrong! " << retval << endl; + return false; + } + else + { + if (LAPPDStoreReadInVerbosity > 2) + std::cout << "Meta for board " << ReadBoards[bi] << " was parsed!" << std::endl; + } + } + else + { + std::cout << "Parsing went wrong! " << retval << endl; + return false; + } + } + + return true; +} + +bool LAPPDLoadStore::DoPedestalSubtract() +{ + Waveform tmpWave; + vector> VecTmpWave; + int pedval, val; + // Loop over data stream + for (std::map>::iterator it = data.begin(); it != data.end(); ++it) // looping over the data map by channel number, from 0 to 60 + { + int wrongPedChannel = 0; + for (int kvec = 0; kvec < it->second.size(); kvec++) + { // loop all data point in this channel + if (DoPedSubtract == 1) + { + auto iter = PedestalValues->find((it->first)); + if (iter != PedestalValues->end() && iter->second.size() > kvec) + { + pedval = iter->second.at(kvec); + } + else + { + pedval = 0; + wrongPedChannel = (it->first); + } + } + else + { + pedval = 0; + } + val = it->second.at(kvec); + tmpWave.PushSample(0.3 * (double)(val - pedval)); + } + if (wrongPedChannel != 0) + cout << "Pedestal value not found for channel " << wrongPedChannel << "with it->first channel" << it->first << ", LAPPD channel shift " << LAPPD_ID * 60 << endl; + + VecTmpWave.push_back(tmpWave); + + unsigned long pushChannelNo = (unsigned long)it->first; + LAPPDWaveforms.insert(pair>>(pushChannelNo, VecTmpWave)); + + tmpWave.ClearSamples(); + VecTmpWave.clear(); + } + return true; +} + +void LAPPDLoadStore::SaveTimeStamps() +{ + unsigned short beamgate_63_48 = meta.at(7); + unsigned short beamgate_47_32 = meta.at(27); + unsigned short beamgate_31_16 = meta.at(47); + unsigned short beamgate_15_0 = meta.at(67); + std::bitset<16> bits_beamgate_63_48(beamgate_63_48); + std::bitset<16> bits_beamgate_47_32(beamgate_47_32); + std::bitset<16> bits_beamgate_31_16(beamgate_31_16); + std::bitset<16> bits_beamgate_15_0(beamgate_15_0); + unsigned long beamgate_63_0 = (static_cast(beamgate_63_48) << 48) + (static_cast(beamgate_47_32) << 32) + (static_cast(beamgate_31_16) << 16) + (static_cast(beamgate_15_0)); + std::bitset<64> bits_beamgate_63_0(beamgate_63_0); + unsigned long beamgate_timestamp = beamgate_63_0 * (CLOCK_to_NSEC); + m_data->CStore.Set("LAPPDbeamgate", beamgate_timestamp); + m_data->CStore.Set("LAPPDBeamgate_Raw", beamgate_63_0); + + unsigned long BGTruncation = beamgate_63_0 % 8; + unsigned long BGTruncated = beamgate_63_0 - BGTruncation; + unsigned long BGInt = BGTruncated / 8 * 25; + unsigned long BGIntTruncation = BGTruncation * 3; + // save these two to CStore + double BGFloat = BGTruncation * 0.125; + unsigned long BGIntCombined = BGInt + BGIntTruncation; + m_data->CStore.Set("LAPPDBGIntCombined", BGIntCombined); + m_data->CStore.Set("LAPPDBGFloat", BGFloat); + + unsigned short timestamp_63_48 = meta.at(70); + unsigned short timestamp_47_32 = meta.at(50); + unsigned short timestamp_31_16 = meta.at(30); + unsigned short timestamp_15_0 = meta.at(10); + std::bitset<16> bits_timestamp_63_48(timestamp_63_48); + std::bitset<16> bits_timestamp_47_32(timestamp_47_32); + std::bitset<16> bits_timestamp_31_16(timestamp_31_16); + std::bitset<16> bits_timestamp_15_0(timestamp_15_0); + unsigned long timestamp_63_0 = (static_cast(timestamp_63_48) << 48) + (static_cast(timestamp_47_32) << 32) + (static_cast(timestamp_31_16) << 16) + (static_cast(timestamp_15_0)); + unsigned long lappd_timestamp = timestamp_63_0 * (CLOCK_to_NSEC); + m_data->CStore.Set("LAPPDtimestamp", lappd_timestamp); + m_data->CStore.Set("LAPPDTimestamp_Raw", timestamp_63_0); + + unsigned long TSTruncation = timestamp_63_0 % 8; + unsigned long TSTruncated = timestamp_63_0 - TSTruncation; + unsigned long TSInt = TSTruncated / 8 * 25; + unsigned long TSIntTruncation = TSTruncation * 3; + // save these two to CStore + double TSFloat = TSTruncation * 0.125; + unsigned long TSIntCombined = TSInt + TSIntTruncation; + m_data->CStore.Set("LAPPDTSIntCombined", TSIntCombined); + m_data->CStore.Set("LAPPDTSFloat", TSFloat); + + m_data->Stores["ANNIEEvent"]->Set("LAPPDbeamgate", beamgate_timestamp); // in ns + m_data->Stores["ANNIEEvent"]->Set("LAPPDtimestamp", lappd_timestamp); // in ns + m_data->Stores["ANNIEEvent"]->Set("LAPPDBeamgate_Raw", beamgate_63_0); + m_data->Stores["ANNIEEvent"]->Set("LAPPDTimestamp_Raw", timestamp_63_0); + +debugStoreReadIn<CStore.Set("LAPPD_new_event", true); +} + +void LAPPDLoadStore::SaveOffsets() +{ + + std::string key = std::to_string(runNumber) + "_" + std::to_string(subRunNumber) + "_" + std::to_string(partFileNumber) + "_" + std::to_string(LAPPD_ID); + + int LAPPDBGCorrection = 0; + int LAPPDTSCorrection = 0; + int LAPPDOffset_minus_ps = 0; + uint64_t LAPPDOffset = 0; + + // Check if the key exists and the index is within range for BGCorrections + if (BGCorrections.find(key) != BGCorrections.end() && eventNumberInPF < BGCorrections[key].size()) + { + LAPPDBGCorrection = BGCorrections[key][eventNumberInPF]; + } + else + { + if (BGCorrections.find(key) == BGCorrections.end()) + { + std::cerr << "Error: Key not found in BGCorrections: " << key << std::endl; + } + else + { + std::cerr << "Error: eventNumberInPF out of range for BGCorrections with key: " << key << std::endl; + } + } + + // Repeat the checks for TSCorrections, Offsets_minus_ps, and Offsets + if (TSCorrections.find(key) != TSCorrections.end() && eventNumberInPF < TSCorrections[key].size()) + { + LAPPDTSCorrection = TSCorrections[key][eventNumberInPF]; + } + else + { + if (TSCorrections.find(key) == TSCorrections.end()) + { + std::cerr << "Error: Key not found in TSCorrections: " << key << std::endl; + } + else + { + std::cerr << "Error: eventNumberInPF out of range for TSCorrections with key: " << key << std::endl; + } + } + + if (Offsets_minus_ps.find(key) != Offsets_minus_ps.end() && eventNumberInPF < Offsets_minus_ps[key].size()) + { + LAPPDOffset_minus_ps = Offsets_minus_ps[key][eventNumberInPF]; + } + else + { + if (Offsets_minus_ps.find(key) == Offsets_minus_ps.end()) + { + std::cerr << "Error: Key not found in Offsets_minus_ps: " << key << std::endl; + } + else + { + std::cerr << "Error: eventNumberInPF out of range for Offsets_minus_ps with key: " << key << std::endl; + } + } + + if (Offsets.find(key) != Offsets.end() && eventNumberInPF < Offsets[key].size()) + { + LAPPDOffset = Offsets[key][eventNumberInPF]; + } + else + { + if (Offsets.find(key) == Offsets.end()) + { + std::cerr << "Error: Key not found in Offsets: " << key << std::endl; + } + else + { + std::cerr << "Error: eventNumberInPF out of range for Offsets with key: " << key << std::endl; + } + } + + // start to fill data + m_data->CStore.Set("LAPPDBGCorrection", LAPPDBGCorrection); + m_data->CStore.Set("LAPPDTSCorrection", LAPPDTSCorrection); + m_data->CStore.Set("LAPPDOffset", LAPPDOffset); + m_data->CStore.Set("LAPPDOffset_minus_ps", LAPPDOffset_minus_ps); + + cout<<"LAPPDStoreReadIn, Saving offsets and corrections, key: "<> Offsets; //Loaded offset, use string = run number + sub run number + partfile number as key. + std::map> Offsets_minus_ps; //offset in ps, use offset - this/1e3 as the real offset + std::map> BGCorrections; //Loaded BGcorrections, same key as Offsets, but offset saved on event by event basis in that part file, in unit of ticks + std::map> TSCorrections; //TS corrections, in unit of ticks + */ + + TFile *file = new TFile("offsetFitResult.root", "READ"); + TTree *tree; + file->GetObject("Events", tree); + + if (!tree) + { + std::cerr << "LAPPDStoreReadIn Loading offsets, Tree not found!" << std::endl; + return; + } + + int runNumber, subRunNumber, partFileNumber, LAPPD_ID; + ULong64_t final_offset_ns_0, final_offset_ps_negative_0, EventIndex; + ULong64_t BGCorrection_tick, TSCorrection_tick; + tree->SetBranchAddress("runNumber", &runNumber); + tree->SetBranchAddress("subRunNumber", &subRunNumber); + tree->SetBranchAddress("partFileNumber", &partFileNumber); + tree->SetBranchAddress("LAPPD_ID", &LAPPD_ID); + tree->SetBranchAddress("EventIndex", &EventIndex); + tree->SetBranchAddress("final_offset_ns_0", &final_offset_ns_0); + tree->SetBranchAddress("final_offset_ps_negative_0", &final_offset_ps_negative_0); + tree->SetBranchAddress("BGCorrection_tick", &BGCorrection_tick); + tree->SetBranchAddress("TSCorrection_tick", &TSCorrection_tick); + + Long64_t nentries = tree->GetEntries(); + cout<<"LAPPDStoreReadIn Loading offsets and corrections, total entries: "<GetEntry(i); + + std::string key = std::to_string(runNumber) + "_" + std::to_string(subRunNumber) + "_" + std::to_string(partFileNumber) + "_" + std::to_string(LAPPD_ID); + + // Prepare the vector sizes for each map + if (Offsets[key].size() <= EventIndex) + { + Offsets[key].resize(EventIndex + 1); + Offsets_minus_ps[key].resize(EventIndex + 1); + BGCorrections[key].resize(EventIndex + 1); + TSCorrections[key].resize(EventIndex + 1); + } + + // Now using EventIndex to place each event correctly + Offsets[key][EventIndex] = final_offset_ns_0; + Offsets_minus_ps[key][EventIndex] = static_cast(final_offset_ps_negative_0); + BGCorrections[key][EventIndex] = static_cast(BGCorrection_tick) - 1000; + TSCorrections[key][EventIndex] = static_cast(TSCorrection_tick) - 1000; + + if(i%(static_cast(nentries/10))==0) + {cout<<"LAPPDStoreReadIn Loading offsets and corrections, "<Close(); + delete file; + + // The data structures are now correctly filled and can be used as needed. +} + +void LAPPDLoadStore::LoadRunInfo() +{ + if(LAPPDStoreReadInVerbosity>0) + cout<<"LAPPDStoreReadIn, Loading run info"<CStore.Get("rawFileNumber", partFileNumber); + m_data->CStore.Get("runNumber", runNumber); + m_data->CStore.Get("subrunNumber", subRunNumber); + + if (partFileNumber != PFNumberBeforeGet) + { + eventNumberInPF = 0; + } + else + { + eventNumberInPF++; + } + if(LAPPDStoreReadInVerbosity>0) + cout<<"LAPPDStoreReadIn, Loaded run info, runNumber: "< +#include +#include +#include +#include +#include "Tool.h" +#include "PsecData.h" +#include "TFile.h" +#include "TTree.h" + +#define NUM_CH 30 +#define NUM_PSEC 5 +#define NUM_SAMP 256 + +using namespace std; +/** + * \class LAPPDLoadStore + * + * Load LAPPD PSEC data and PPS data from BoostStore. + * + */ +class LAPPDLoadStore : public Tool +{ + +public: + LAPPDLoadStore(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + bool ReadPedestals(int boardNo); ///< Read in the Pedestal Files + bool MakePedestals(); ///< Make a Pedestal File + + int getParsedData(vector buffer, int ch_start); + int getParsedMeta(vector buffer, int BoardId); + + void CleanDataObjects(); + bool LoadData(); + bool ParsePSECData(); + void ParsePPSData(); + bool DoPedestalSubtract(); + void SaveTimeStamps(); // save some timestamps relate to this event + void LoadOffsetsAndCorrections(); + void LoadRunInfo(); + void SaveOffsets(); + +private: + // This tool, control variables (only used in this tool, every thing that is not an data object) + // Variables that you get from the config file + int ReadStore; // read data from a StoreFile (tool chain start with this tool rather than LoadANNIEEvent) + int Nboards; // total number of boards to load pedestal file, LAPPD number * 2 + string PedFileName; // store format pedestal file name + string PedFileNameTXT; // txt format pedestal file name + int DoPedSubtract; // 1: do pedestal subtraction, 0: don't do pedestal subtraction + int LAPPDStoreReadInVerbosity; + int num_vector_data; + int num_vector_pps; + bool SelectSingleLAPPD; + int SelectedLAPPD; + bool mergingModeReadIn; + bool ReadStorePdeFile; + bool MultiLAPPDMap; // loading map of multiple LAPPDs from ANNIEEvent + bool loadOffsets; + // Variables that you need in the tool + int retval; // track the data parsing and meta parsing status + int eventNo; + double CLOCK_to_NSEC; + int errorEventsNumber; + bool runInfoLoaded; + + + // LAPPD tool chain, control variables (Will be shared in multiple LAPPD tools to show the state of the tool chain in each loop) + // Variables that you get from the config file + int stopEntries; // stop tool chain after loading this number of PSEC data events + int NonEmptyEvents; // count how many non empty data events were loaded + bool PsecReceiveMode; // Get PSEC data from CStore or Stores["ANNIEEvent"]. 1: CStore, 0: Stores["ANNIEEvent"] + string OutputWavLabel; + string InputWavLabel; + int NChannels; + int Nsamples; + int TrigChannel; + double SampleSize; + int LAPPDchannelOffset; + int PPSnumber; + bool loadPPS; + bool loadPSEC; + bool mergedEvent; // in some merged Event, the LAPPD events was merged to ANNIEEvent, but the data stream was not changed to be true. use this = 1 to read it + bool LAPPDana; // run other LAPPD tools + // Variables that you need in the tool + bool isCFD; + bool isBLsub; + bool isFiltered; + int EventType; // 0: PSEC, 1: PPS + // LAPPD tool chain, data variables. (Will be used in multiple LAPPD tools) + // everything you get or set to Store, which means it may be used in other tools or it's from other tools + int LAPPD_ID; + vector ParaBoards; // save the board index for this PsecData + std::map>> LAPPDWaveforms; + + // This tool, data variables (only used in this tool, every thing that is an data object) + ifstream PedFile; // stream for reading in the Pedestal Files + string NewFileName; // name of the new Data File + std::map> *PedestalValues; + std::vector Raw_buffer; + std::vector Parse_buffer; + std::vector ReadBoards; + std::map> data; + vector meta; + vector pps; + vector LAPPD_ID_Channel; // for each LAPPD, how many channels on it's each board + vector LAPPD_ID_BoardNumber; // for each LAPPD, how many boards with it + std::map LAPPDDataMap; + + // data variables don't need to be cleared in each loop + std::map> Offsets; // Loaded offset, use string = run number + sub run number + partfile number as key. + std::map> Offsets_minus_ps; // offset in ps, use offset - this/1e3 as the real offset + std::map> BGCorrections; // Loaded BGcorrections, same key as Offsets, but offset saved on event by event basis in that part file, in unit of ticks + std::map> TSCorrections; // TS corrections, in unit of ticks + int runNumber; + int subRunNumber; + int partFileNumber; + int eventNumberInPF; + std::ofstream debugStoreReadIn; +}; + +#endif diff --git a/UserTools/LAPPDLoadStore/README.md b/UserTools/LAPPDLoadStore/README.md new file mode 100644 index 000000000..ec08cbc11 --- /dev/null +++ b/UserTools/LAPPDLoadStore/README.md @@ -0,0 +1,20 @@ +# LAPPDLoadStore + +LAPPDLoadStore + +## Data + +Describe any data formats LAPPDLoadStore creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for LAPPDLoadStore. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/LAPPDPlots/LAPPDPlots.cpp b/UserTools/LAPPDPlots/LAPPDPlots.cpp new file mode 100644 index 000000000..d48882daa --- /dev/null +++ b/UserTools/LAPPDPlots/LAPPDPlots.cpp @@ -0,0 +1,325 @@ +#include "LAPPDPlots.h" + +LAPPDPlots::LAPPDPlots() : Tool() {} + +bool LAPPDPlots::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + m_data->Stores["ANNIEEvent"]->Header->Get("AnnieGeometry", _geom); + + m_variables.Get("LAPPDPlotInputWaveLabel", LAPPDPlotInputWaveLabel); + LAPPDPlotsVerbosity = 0; + m_variables.Get("LAPPDPlotsVerbosity", LAPPDPlotsVerbosity); + CanvasXSubPlotNumber = 2; + m_variables.Get("CanvasXSubPlotNumber", CanvasXSubPlotNumber); + CanvasYSubPlotNumber = 3; + m_variables.Get("CanvasYSubPlotNumber", CanvasYSubPlotNumber); + CanvasTotalSubPlotNumber = CanvasXSubPlotNumber * CanvasYSubPlotNumber; + Side0EventWaveformDrawPosition = 1; + m_variables.Get("Side0EventWaveformDrawPosition", Side0EventWaveformDrawPosition); + Side1EventWaveformDrawPosition = 2; + m_variables.Get("Side1EventWaveformDrawPosition", Side1EventWaveformDrawPosition); + drawTriggerChannel = true; + m_variables.Get("drawTriggerChannel", drawTriggerChannel); + drawHighThreshold = 50; + m_variables.Get("drawHighThreshold", drawHighThreshold); + drawLowThreshold = -20; + m_variables.Get("drawLowThreshold", drawLowThreshold); + titleSize = 0.05; + m_variables.Get("titleSize", titleSize); + canvasTitleOffset = 1.05; + m_variables.Get("canvasTitleOffset", canvasTitleOffset); + canvasMargin = 0.15; + m_variables.Get("canvasMargin", canvasMargin); + CanvasWidth = 800; + m_variables.Get("CanvasWidth", CanvasWidth); + CanvasHeight = 1200; + m_variables.Get("CanvasHeight", CanvasHeight); + maxDrawEventNumber = 20; + m_variables.Get("maxDrawEventNumber", maxDrawEventNumber); + colorPalette = 112; + m_variables.Get("colorPalette", colorPalette); + DrawEventWaveform = true; + m_variables.Get("DrawEventWaveform", DrawEventWaveform); + OnlyDrawInBeamWindow = false; + m_variables.Get("OnlyDrawInBeamWindow", OnlyDrawInBeamWindow); + BeamWindowStart = 8000; + m_variables.Get("BeamWindowStart", BeamWindowStart); + BeamWindowEnd = 10000; + m_variables.Get("BeamWindowEnd", BeamWindowEnd); + Side0BinDrawPosition = 3; + m_variables.Get("Side0BinDrawPosition", Side0BinDrawPosition); + Side1BinDrawPosition = 4; + m_variables.Get("Side1BinDrawPosition", Side1BinDrawPosition); + DrawBinHist = true; + m_variables.Get("DrawBinHist", DrawBinHist); + BinHistMin = -20; + m_variables.Get("BinHistMin", BinHistMin); + BinHistMax = 50; + m_variables.Get("BinHistMax", BinHistMax); + BinHistNumber = 100; + m_variables.Get("BinHistNumber", BinHistNumber); + + eventNumber = 0; + + f = new TFile("LAPPDPlots.root", "RECREATE"); + c = new TCanvas("c", "c", CanvasWidth, CanvasHeight); + + return true; +} + +bool LAPPDPlots::Execute() +{ + m_data->CStore.Get("LAPPDana", LAPPDana); + if (!LAPPDana) + return true; + if (eventNumber > maxDrawEventNumber) + return true; + + inBeamWindow = CheckInBeamgateWindow(); + if (OnlyDrawInBeamWindow && (inBeamWindow == 0 || inBeamWindow == -1)) + return true; + + c->Clear(); + c->Divide(CanvasXSubPlotNumber, CanvasYSubPlotNumber); + + if (LAPPDPlotsVerbosity > 0) + cout << "Divide canvas into " << CanvasXSubPlotNumber << "x" << CanvasYSubPlotNumber << " subplots" << endl; + c->SetTitle("Event " + TString::Itoa(eventNumber, 10)); + c->SetName("Event" + TString::Itoa(eventNumber, 10)); + // c->cd(1); + gStyle->SetPalette(colorPalette); + + bool gotdata = m_data->Stores["ANNIEEvent"]->Get(LAPPDPlotInputWaveLabel, lappddata); + m_data->Stores["ANNIEEvent"]->Get("ACDCboards", ReadBoards); + m_data->CStore.Get("LAPPD_ID", LAPPD_ID); + + if (LAPPDPlotsVerbosity > 0) + cout << "LAPPDPlots execute with data " << LAPPDPlotInputWaveLabel << ", got data " << gotdata << ", data size " << lappddata.size() << ", Boards number" << ReadBoards.size() << ", ID " << LAPPD_ID << endl; + + if (DrawEventWaveform) + { + vector DrawPosition = {Side0EventWaveformDrawPosition, Side1EventWaveformDrawPosition}; + for (int i = 0; i < ReadBoards.size(); i++) + { + const int drawPosition = DrawPosition[i]; + TPad *p = (TPad *)c->cd(drawPosition); + // c->cd(drawPosition); + p->cd(); + p->SetRightMargin(canvasMargin); + p->SetLeftMargin(canvasMargin); + p->SetTopMargin(canvasMargin); + p->SetBottomMargin(canvasMargin); + if (LAPPDPlotsVerbosity > 0) + cout << "Drawing board " << ReadBoards[i] << " at position " << DrawPosition[i] << " start" << endl; + std::map>> boarddata = GetDataForBoard(ReadBoards[i]); + TString HistoName = "Event" + TString::Itoa(eventNumber, 10) + "_B" + ReadBoards[i] + "_ID" + LAPPD_ID; + // convert BGTiming to string and add to HistoName + // if (OnlyDrawInBeamWindow) + HistoName += "_BG" + TString::Itoa(BGTiming, 10); + + // DrawEventWaveform(c, DrawPosition[i], HistoName, boarddata); + // TH2D h = DrawEventWaveform(HistoName, boarddata); + + int nstrips = 30; + if (!drawTriggerChannel) + nstrips = 28; + TH2D *h = new TH2D(HistoName, HistoName, 256, 0, 256, nstrips, 0 - 0.5, nstrips - 0.5); + if (LAPPDPlotsVerbosity > 3) + cout << "Start Drawing event waveform with data size = " << boarddata.size() << endl; + std::map>>::iterator it; + for (it = boarddata.begin(); it != boarddata.end(); it++) + { + unsigned long channelNo = it->first; + Waveform w = it->second[0]; + Channel *ch = _geom->GetChannel(channelNo); + int stripNo = ch->GetStripNum(); + if (LAPPDPlotsVerbosity > 3) + cout << "Drawing channel " << channelNo << " strip " << stripNo << ", with sample size " << w.GetSamples()->size() << endl; + if (!drawTriggerChannel) + if ((channelNo % 1000) % 30 == 5) + continue; + + for (int i = 0; i < w.GetSamples()->size(); i++) + { + h->SetBinContent(i, stripNo + 1, -w.GetSamples()->at(i)); + } + } + if (LAPPDPlotsVerbosity > 3) + cout << "Finish Drawing event waveform" << endl; + + h->SetMaximum(drawHighThreshold); + h->SetMinimum(drawLowThreshold); + h->SetStats(0); + h->GetXaxis()->SetTitle("Time (ns)"); + h->GetXaxis()->SetTitleSize(titleSize); + h->GetXaxis()->SetTitleOffset(canvasTitleOffset); + h->GetYaxis()->SetTitle("Strip Number"); + h->GetYaxis()->SetTitleSize(titleSize); + h->GetYaxis()->SetTitleOffset(canvasTitleOffset); + h->GetZaxis()->SetTitle("Amplitude (mV)"); + + h->Draw("colz"); + f->cd(); + h->Write(); + if (LAPPDPlotsVerbosity > 0) + cout << "Drawing board " << ReadBoards[i] << " finished for Draw Event waveform" << endl; + } + } + + if (DrawBinHist) + { + + vector DrawPositionBinHist = {Side0BinDrawPosition, Side1BinDrawPosition}; + for (int i = 0; i < ReadBoards.size(); i++) + { + const int drawPosition = DrawPositionBinHist[i]; + TPad *p = (TPad *)c->cd(drawPosition); + // c->cd(drawPosition); + p->cd(); + p->SetRightMargin(canvasMargin); + p->SetLeftMargin(canvasMargin); + p->SetTopMargin(canvasMargin); + p->SetBottomMargin(canvasMargin); + if (LAPPDPlotsVerbosity > 0) + cout << "Drawing board " << ReadBoards[i] << " at position " << DrawPositionBinHist[i] << " start" << endl; + std::map>> boarddata = GetDataForBoard(ReadBoards[i]); + TString HistoName = "Event" + TString::Itoa(eventNumber, 10) + "_Bin_B" + ReadBoards[i] + "_ID" + LAPPD_ID; + // convert BGTiming to string and add to HistoName + // if (OnlyDrawInBeamWindow) + HistoName += "_BG" + TString::Itoa(BGTiming, 10); + + int nstrips = 30; + if (!drawTriggerChannel) + nstrips = 28; + const double BinHistMinConst = BinHistMin; + const double BinHistMaxConst = BinHistMax; + const int BinHistNumberConst = BinHistNumber; + TH2D *h = new TH2D(HistoName, HistoName, BinHistNumberConst, BinHistMinConst, BinHistMaxConst, nstrips, 0 - 0.5, nstrips - 0.5); + if (LAPPDPlotsVerbosity > 3) + cout << "Start Drawing event waveform with data size = " << boarddata.size() << endl; + std::map>>::iterator it; + for (it = boarddata.begin(); it != boarddata.end(); it++) + { + unsigned long channelNo = it->first; + Waveform w = it->second[0]; + Channel *ch = _geom->GetChannel(channelNo); + int stripNo = ch->GetStripNum(); + if (LAPPDPlotsVerbosity > 3) + cout << "Drawing channel " << channelNo << " strip " << stripNo << ", with sample size " << w.GetSamples()->size() << endl; + if (!drawTriggerChannel) + if ((channelNo % 1000) % 30 == 5) + continue; + + for (int i = 0; i < w.GetSamples()->size(); i++) + { + h->Fill(-w.GetSamples()->at(i), stripNo + 1); + } + } + if (LAPPDPlotsVerbosity > 3) + cout << "Finish Drawing event waveform" << endl; + + h->SetStats(0); + h->GetXaxis()->SetTitle("Amplitude (mV)"); + h->GetXaxis()->SetTitleSize(titleSize); + h->GetXaxis()->SetTitleOffset(canvasTitleOffset); + h->GetYaxis()->SetTitle("Strip Number"); + h->GetYaxis()->SetTitleSize(titleSize); + h->GetYaxis()->SetTitleOffset(canvasTitleOffset); + h->GetZaxis()->SetTitle("Entries"); + h->Draw("colz"); + + f->cd(); + h->Write(); + if (LAPPDPlotsVerbosity > 0) + cout << "Drawing board " << ReadBoards[i] << ", i=" << i << " in " << ReadBoards.size() << " finished for Draw Bin Hist" << endl; + } + } + + c->Modified(); + c->Update(); + + if (eventNumber == 0) + c->Print("LAPPDPlots.pdf("); + else if (eventNumber == maxDrawEventNumber) + c->Print("LAPPDPlots.pdf)"); + else if (eventNumber < maxDrawEventNumber) + c->Print("LAPPDPlots.pdf"); + + eventNumber++; + return true; +} + +bool LAPPDPlots::Finalise() +{ + if (eventNumber < maxDrawEventNumber) + c->Print("LAPPDPlots.pdf)"); + c->Clear(); + c->Close(); + delete c; + + f->cd(); + f->Close(); + delete f; + return true; +} + +std::map>> LAPPDPlots::GetDataForBoard(int boardID) +{ + + std::map>> boarddata; + for (auto &it : lappddata) + { + unsigned long channelNo = it.first; + + Channel *ch = _geom->GetChannel(channelNo); + int stripSide = ch->GetStripSide(); + if (LAPPDPlotsVerbosity > 4) + cout << "GetData, channelNo: " << channelNo << ", side number" << stripSide << ", boardID " << boardID << endl; + if (static_cast((channelNo % 1000) / 60) == static_cast(boardID / 2) * 2 && stripSide == boardID % 2) + { + boarddata[channelNo] = it.second; + if (LAPPDPlotsVerbosity > 4) + cout << "insearting data for channel " << channelNo << endl; + } + } + + return boarddata; +} + +void LAPPDPlots::CleanObjects() +{ + lappddata.clear(); + ReadBoards.clear(); + LAPPD_ID = -1; + inBeamWindow = -1; + BGTiming = -1; +} + +int LAPPDPlots::CheckInBeamgateWindow() +{ + unsigned long LAPPDDataBeamgateUL; + unsigned long LAPPDDataTimeStampUL; + bool got = m_data->CStore.Get("LAPPDBeamgate_Raw", LAPPDDataBeamgateUL); + got = m_data->CStore.Get("LAPPDTimestamp_Raw", LAPPDDataTimeStampUL); + + if (got) + { + unsigned long Timing = (LAPPDDataTimeStampUL - LAPPDDataBeamgateUL) * 3.125; + BGTiming = Timing; + if (Timing > BeamWindowStart && Timing < BeamWindowEnd) + return 1; + else + return 0; + } + else + return -1; +} \ No newline at end of file diff --git a/UserTools/LAPPDPlots/LAPPDPlots.h b/UserTools/LAPPDPlots/LAPPDPlots.h new file mode 100644 index 000000000..fe2b0332c --- /dev/null +++ b/UserTools/LAPPDPlots/LAPPDPlots.h @@ -0,0 +1,105 @@ +#ifndef LAPPDPlots_H +#define LAPPDPlots_H + +#include +#include + +#include "Tool.h" + +#include "TFile.h" +#include "TH1D.h" +#include "TH2D.h" +#include "TString.h" +#include "TTree.h" +#include "LAPPDHit.h" +#include "LAPPDPulse.h" +#include "TCanvas.h" +#include "TStyle.h" +#include "TColor.h" +#include "TLegend.h" +#include "TMath.h" +#include "Detector.h" +#include "Geometry.h" + +/** + * \class LAPPDPlots + * + * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. + * + * $Author: B.Richards $ + * $Date: 2019/05/28 10:44:00 $ + * Contact: b.richards@qmul.ac.uk + */ +class LAPPDPlots : public Tool +{ + +public: + LAPPDPlots(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + std::map>> GetDataForBoard(int boardID); + int CheckInBeamgateWindow(); + void CleanObjects(); + +private: + //**************************** This tool, control variables *************************************************** + // (only used in this tool, every thing that is not an data object) + // Variables that you get from the config file + int CanvasXSubPlotNumber; + int CanvasYSubPlotNumber; // c->Divide(x, y); + int CanvasWidth; + int CanvasHeight; + int maxDrawEventNumber; + string LAPPDPlotInputWaveLabel; + int LAPPDPlotsVerbosity; + // draw event waveform + int Side0EventWaveformDrawPosition; + int Side1EventWaveformDrawPosition; + bool drawTriggerChannel; + double drawHighThreshold; + double drawLowThreshold; + double titleSize; + double canvasTitleOffset; + double canvasMargin; + int colorPalette; + bool DrawEventWaveform; + bool OnlyDrawInBeamWindow; + int BeamWindowStart; + int BeamWindowEnd; + bool DrawBinHist; + int Side0BinDrawPosition; + int Side1BinDrawPosition; + double BinHistMin; + double BinHistMax; + int BinHistNumber; + + + // Variables that you need in the tool + int CanvasTotalSubPlotNumber; + int inBeamWindow; + double BGTiming; + //**************************** LAPPD tool chain, control variables *************************************************** + //(Will be shared in multiple LAPPD tools to show the state of the tool chain in each loop) + // Variables that you get from the config file + + // Variables that you need in the tool + bool LAPPDana; + + //**************************** LAPPD tool chain, data variables *************************************************** + // (Will be used in multiple LAPPD tools) + // everything you get or set to Store, which means it may be used in other tools or it's from other tools + Geometry *_geom; + std::map>> lappddata; + std::vector ReadBoards; + int LAPPD_ID; + + //**************************** This tool, data variables *************************************************** + // (only used in this tool, every thing that is an data object) + // data variables don't need to be cleared in each loop + TCanvas *c; + TFile *f; + int eventNumber; +}; + +#endif diff --git a/UserTools/LAPPDPlots/README.md b/UserTools/LAPPDPlots/README.md new file mode 100644 index 000000000..e00a11b82 --- /dev/null +++ b/UserTools/LAPPDPlots/README.md @@ -0,0 +1,20 @@ +# LAPPDPlots + +LAPPDPlots + +## Data + +Describe any data formats LAPPDPlots creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for LAPPDPlots. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp b/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp new file mode 100644 index 000000000..2d1ad1b2b --- /dev/null +++ b/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp @@ -0,0 +1,299 @@ +#include "LAPPDStoreReorder.h" + +LAPPDStoreReorder::LAPPDStoreReorder() : Tool() {} + +bool LAPPDStoreReorder::Initialise(std::string configfile, DataModel &data) +{ + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + m_variables.Get("ReorderInputWavLabel", InputWavLabel); + m_variables.Get("ReorderOutputWavLabel", OutputWavLabel); + m_variables.Get("DelayOffset", delayoffset); + m_variables.Get("GlobalShift", GlobalShift); + m_variables.Get("LAPPDReorderVerbosityLevel", LAPPDReorderVerbosityLevel); + m_variables.Get("NUM_VECTOR_METADATA", NUM_VECTOR_METADATA); + m_variables.Get("LAPPDchannelOffset", LAPPDchannelOffset); + bool gotGeomerty = m_data->Stores["ANNIEEvent"]->Header->Get("AnnieGeometry", _geom); + if (!gotGeomerty) + { + Log("Error: LAPPDStoreReorder: Failed to get ANNIEGeometry from the ANNIEEvent store", 0, LAPPDReorderVerbosityLevel); + return false; + } + + return true; +} + +bool LAPPDStoreReorder::Execute() +{ + CleanDataObjects(); + if (LAPPDReorderVerbosityLevel > 3) + cout << "LAPPDStoreReorder::Execute()" << endl; + m_data->CStore.Get("LAPPDana", LAPPDana); + if (!LAPPDana) + { + if (LAPPDReorderVerbosityLevel > 3) + cout << "LAPPDStoreReorder::Execute() LAPPDana is false, returning" << endl; + return true; + } + + m_data->Stores["ANNIEEvent"]->Get("ACDCmetadata", acdcmetadata); + m_data->Stores["ANNIEEvent"]->Get(InputWavLabel, lappddata); + m_data->Stores["ANNIEEvent"]->Get("ACDCboards", NReadBoards); + + // Loop over waveforms, reorder data + DoReorder(); + // this reorder will change the channel number by adding an channel offset. + + m_data->Stores["ANNIEEvent"]->Set("TimingCounters", tcounters); + m_data->Stores["ANNIEEvent"]->Set(OutputWavLabel, reordereddata); + + if (LAPPDReorderVerbosityLevel > 1) + { + cout<<"LAPPDStoreReorder, reordered data size is "< 3) + cout << "LAPPDStoreReorder::Execute() done" << endl; + + return true; +} + +bool LAPPDStoreReorder::Finalise() +{ + return true; +} + +void LAPPDStoreReorder::CleanDataObjects() +{ + reordereddata.clear(); + lappddata.clear(); + acdcmetadata.clear(); + NReadBoards.clear(); + tcounters.clear(); +} + +bool LAPPDStoreReorder::DoReorder() +{ + // For 30 channels change to 10 + vector Smeta26; + for (int meta26 = 0; meta26 < NReadBoards.size(); meta26++) + { + Smeta26.push_back(acdcmetadata.at((meta26 * NUM_VECTOR_METADATA) + 10)); + if (LAPPDReorderVerbosityLevel > 1) + cout << "Metaword entry " << meta26 << " is " << Smeta26[meta26] << endl; + } + if (LAPPDReorderVerbosityLevel > 2) + cout << "REORDER TIME!!!! " << acdcmetadata.size() << " " << acdcmetadata.at(10) << " " << acdcmetadata.at(102) << "lappd data size is " << lappddata.size() << ", reordereddata size is " << reordereddata.size() << endl; + map>>::iterator itr; + for (itr = lappddata.begin(); itr != lappddata.end(); ++itr) + { + if (LAPPDReorderVerbosityLevel > 1) + cout << "reordering channelno= " << itr->first << endl; + unsigned long channelno = itr->first; + int channelHere = channelno; + channelHere = channelHere % 1000 + 1000; // hmmm the offset in geometry is 1000 + Channel *chan = _geom->GetChannel(channelHere); + int stripno = chan->GetStripNum(); + vector> Vwavs = itr->second; + if (LAPPDReorderVerbosityLevel > 1) + { + cout << "this channel has " << Vwavs.size() << " waveforms" << endl; + if (Vwavs.size() > 0) + cout << "The first waveform has " << Vwavs.at(0).GetSamples()->size() << " samples" << endl; + } + int switchbit = 0; + // Get the current board and the respective meta word + int bi = (int)channelno / 30; + unsigned short switchword = Smeta26[std::distance(NReadBoards.begin(), std::find(NReadBoards.begin(), NReadBoards.end(), bi))]; + // Smeta26, 0 or 1, so switchword is the first timestmap or the second + // Set the switchbit + switchbit = (switchword & 0x7) * 32; + // insert the stripno and switchbit into the map + + // take the last 3 bits of PSEC0 timestamp (10 in meta words), then times 2^5, shift left by 5 + switchbit += delayoffset; + + vector> Vrwav; + // loop over all Waveforms + for (int i = 0; i < Vwavs.size(); i++) + { + + Waveform bwav = Vwavs.at(i); + Waveform rwav; + Waveform rwavCorr; + + for (int j = 0; j < bwav.GetSamples()->size(); j++) + { + + if (switchbit > 255 || switchbit < 0) + switchbit = 0; + double nsamp = bwav.GetSamples()->at(switchbit); + rwav.PushSample(nsamp); + switchbit++; + } + for (int j = 0; j < rwav.GetSamples()->size(); j++) + { + int ibin = j + GlobalShift; + if (ibin > 255) + ibin = ibin - 255; + double nsamp = rwav.GetSamples()->at(ibin); + rwavCorr.PushSample(nsamp); + } + + Vrwav.push_back(rwavCorr); + } + + reordereddata.insert(pair>>(LAPPDchannelOffset + channelno, Vrwav)); + if(LAPPDReorderVerbosityLevel>2) + cout<<"inserted channelno: "<1) + { + cout<<"LAPPDStoreReorder, reordered data size is "< bits_beamgate_63_48(beamgate_63_48); + std::bitset<16> bits_beamgate_47_32(beamgate_47_32); + std::bitset<16> bits_beamgate_31_16(beamgate_31_16); + std::bitset<16> bits_beamgate_15_0(beamgate_15_0); + + // cout statements + + if (LAPPDReorderVerbosityLevel > 2) + std::cout << "bits_beamgate_63_48: " << bits_beamgate_63_48 << std::endl; + if (LAPPDReorderVerbosityLevel > 2) + std::cout << "bits_beamgate_47_32: " << bits_beamgate_47_32 << std::endl; + if (LAPPDReorderVerbosityLevel > 2) + std::cout << "bits_beamgate_31_16: " << bits_beamgate_31_16 << std::endl; + if (LAPPDReorderVerbosityLevel > 2) + std::cout << "bits_beamgate_15_0: " << bits_beamgate_15_0 << std::endl; + // construct the full 64-bit counter number + unsigned long beamgate_63_0 = (static_cast(beamgate_63_48) << 48) + (static_cast(beamgate_47_32) << 32) + (static_cast(beamgate_31_16) << 16) + (static_cast(beamgate_15_0)); + // cout statement + if (LAPPDReorderVerbosityLevel > 2) + std::cout << "beamgate combined: " << beamgate_63_0 << std::endl; + // binary digit + std::bitset<64> bits_beamgate_63_0(beamgate_63_0); + // cout the binary + if (LAPPDReorderVerbosityLevel > 2) + std::cout << "bits_beamgate_63_0: " << bits_beamgate_63_0 << std::endl; + + // hex manipulations + std::stringstream str_beamgate_15_0; + str_beamgate_15_0 << std::hex << (beamgate_15_0); + std::stringstream str_beamgate_31_16; + str_beamgate_31_16 << std::hex << (beamgate_31_16); + std::stringstream str_beamgate_47_32; + str_beamgate_47_32 << std::hex << (beamgate_47_32); + std::stringstream str_beamgate_63_48; + str_beamgate_63_48 << std::hex << (beamgate_63_48); + const char *hexstring = str_beamgate_63_48.str().c_str(); + unsigned int meta7_1 = (unsigned int)strtol(hexstring, NULL, 16); + hexstring = str_beamgate_47_32.str().c_str(); + unsigned int meta27_1 = (unsigned int)strtol(hexstring, NULL, 16); + hexstring = str_beamgate_31_16.str().c_str(); + unsigned int meta47_1 = (unsigned int)strtol(hexstring, NULL, 16); + hexstring = str_beamgate_15_0.str().c_str(); + unsigned int meta67_1 = (unsigned int)strtol(hexstring, NULL, 16); + meta7_1 = meta7_1 << 16; + meta47_1 = meta47_1 << 16; + + // my two beam counter values + unsigned int beamcounter = meta47_1 + meta67_1; + unsigned int beamcounterL = meta7_1 + meta27_1; + // as doubles + double largetime = (double)beamcounterL * 13.1; + double smalltime = ((double)beamcounter / 1E9) * 3.125; + + // bunch of couts + if (LAPPDReorderVerbosityLevel > 2) + { + std::cout << "meta7_1: " << meta7_1 << std::endl; + std::cout << "meta27_1: " << meta27_1 << std::endl; + std::cout << "meta47_1: " << meta47_1 << std::endl; + std::cout << "meta67_1: " << meta67_1 << std::endl; + std::cout << "beamcounter: " << beamcounter << std::endl; + std::cout << "beamcounterL: " << beamcounterL << std::endl; + std::cout << "largetime: " << largetime << std::endl; + std::cout << "smalltime: " << smalltime << std::endl; + std::cout << "eventtime: " << (largetime + smalltime) << std::endl; + std::cout << "beamgate old: " << ((beamgate_63_0 / 1E9) * 3.125) << std::endl; + } + + // Build data timestamp + unsigned short timestamp_63_48 = acdcmetadata.at(70); + unsigned short timestamp_47_32 = acdcmetadata.at(50); + unsigned short timestamp_31_16 = acdcmetadata.at(30); + unsigned short timestamp_15_0 = acdcmetadata.at(10); + std::bitset<16> bits_timestamp_63_48(timestamp_63_48); + std::bitset<16> bits_timestamp_47_32(timestamp_47_32); + std::bitset<16> bits_timestamp_31_16(timestamp_31_16); + std::bitset<16> bits_timestamp_15_0(timestamp_15_0); + if (LAPPDReorderVerbosityLevel > 2) + std::cout << "bits_timestamp_63_48: " << bits_timestamp_63_48 << std::endl; + if (LAPPDReorderVerbosityLevel > 2) + std::cout << "bits_timestamp_47_32: " << bits_timestamp_47_32 << std::endl; + if (LAPPDReorderVerbosityLevel > 2) + std::cout << "bits_timestamp_31_16: " << bits_timestamp_31_16 << std::endl; + if (LAPPDReorderVerbosityLevel > 2) + std::cout << "bits_timestamp_15_0: " << bits_timestamp_15_0 << std::endl; + // construct the full 64-bit counter number + unsigned long timestamp_63_0 = (static_cast(timestamp_63_48) << 48) + (static_cast(timestamp_47_32) << 32) + (static_cast(timestamp_31_16) << 16) + (static_cast(timestamp_15_0)); + // cout statement + if (LAPPDReorderVerbosityLevel > 2) + std::cout << "timestamp combined: " << timestamp_63_0 << std::endl; + std::bitset<64> bits_timestamp_63_0(timestamp_63_0); + // cout the binary + if (LAPPDReorderVerbosityLevel > 2) + std::cout << "bits_timestamp_63_0: " << bits_timestamp_63_0 << std::endl; + + // hex manipulations + std::stringstream str_timestamp_63_48; + str_timestamp_63_48 << std::hex << (timestamp_63_48); + std::stringstream str_timestamp_47_32; + str_timestamp_47_32 << std::hex << (timestamp_47_32); + std::stringstream str_timestamp_31_16; + str_timestamp_31_16 << std::hex << (timestamp_31_16); + std::stringstream str_timestamp_15_0; + str_timestamp_15_0 << std::hex << (timestamp_15_0); + + hexstring = str_timestamp_63_48.str().c_str(); + unsigned int meta70_1 = (unsigned int)strtol(hexstring, NULL, 16); + hexstring = str_timestamp_47_32.str().c_str(); + unsigned int meta50_1 = (unsigned int)strtol(hexstring, NULL, 16); + hexstring = str_timestamp_31_16.str().c_str(); + unsigned int meta30_1 = (unsigned int)strtol(hexstring, NULL, 16); + hexstring = str_timestamp_15_0.str().c_str(); + unsigned int meta10_1 = (unsigned int)strtol(hexstring, NULL, 16); + meta70_1 = meta70_1 << 16; + meta30_1 = meta30_1 << 16; + + // my two beam counter values + unsigned int trigcounter = meta30_1 + meta10_1; + unsigned int trigcounterL = meta50_1 + meta70_1; + // as doubles + + tcounters.push_back(beamcounter); + tcounters.push_back(beamcounterL); + tcounters.push_back(trigcounter); + tcounters.push_back(trigcounterL); + + return true; +} diff --git a/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.h b/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.h new file mode 100644 index 000000000..696a79491 --- /dev/null +++ b/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.h @@ -0,0 +1,73 @@ +#ifndef LAPPDStoreReorder_H +#define LAPPDStoreReorder_H + +#include +#include + +#include "Tool.h" +#include +#include "Geometry.h" + + +using namespace std; +/** +* \class LAPPDStoreReorder +* +* Do LAPPD data read in from BoostStore +* +* $Author: $ +* $Date: $ +* Contact: +*/ +class LAPPDStoreReorder: public Tool { + + + public: + + LAPPDStoreReorder(); ///< Simple constructor + bool Initialise(std::string configfile,DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + +void CleanDataObjects(); +bool DoReorder(); +bool ConstructTimestampsFromMeta(); + private: + + //**************************** This tool, control variables *************************************************** + // (only used in this tool, every thing that is not an data object) + // Variables that you get from the config file + int LAPPDReorderVerbosityLevel; + int NUM_VECTOR_METADATA; + int delayoffset; + int GlobalShift; + // Variables that you need in the tool + + //**************************** LAPPD tool chain, control variables *************************************************** + //(Will be shared in multiple LAPPD tools to show the state of the tool chain in each loop) + // Variables that you get from the config file + int LAPPDchannelOffset; + string InputWavLabel; + string OutputWavLabel; + + // Variables that you need in the tool + bool LAPPDana; + + //**************************** LAPPD tool chain, data variables *************************************************** + // (Will be used in multiple LAPPD tools) + // everything you get or set to Store, which means it may be used in other tools or it's from other tools + std::map>> reordereddata; + std::map>> lappddata; + vector acdcmetadata; + vector NReadBoards; + vector tcounters; + + //**************************** This tool, data variables *************************************************** + // (only used in this tool, every thing that is an data object) + // data variables don't need to be cleared in each loop + Geometry* _geom; + +}; + + +#endif diff --git a/UserTools/LAPPDStoreReorder/README.md b/UserTools/LAPPDStoreReorder/README.md new file mode 100644 index 000000000..2e088501d --- /dev/null +++ b/UserTools/LAPPDStoreReorder/README.md @@ -0,0 +1,20 @@ +# LAPPDStoreReorder + +LAPPDStoreReorder + +## Data + +Describe any data formats LAPPDStoreReorder creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for LAPPDStoreReorder. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/LAPPDThresReco/LAPPDThresReco.cpp b/UserTools/LAPPDThresReco/LAPPDThresReco.cpp new file mode 100644 index 000000000..ce561198e --- /dev/null +++ b/UserTools/LAPPDThresReco/LAPPDThresReco.cpp @@ -0,0 +1,855 @@ +#include "LAPPDThresReco.h" + +LAPPDThresReco::LAPPDThresReco() : Tool() {} + +bool LAPPDThresReco::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + // Control variables + // Control variables used in this tool + // Control variables that you get from the config file, for this tool + LAPPDThresRecoVerbosity = 0; + m_variables.Get("LAPPDThresRecoVerbosity", LAPPDThresRecoVerbosity); + threshold = 15; + m_variables.Get("threshold", threshold); + minPulseWidth = 3; // number of bins require for a pulse + m_variables.Get("minPulseWidth", minPulseWidth); + printHitsTXT = 1; // 1 print hit information to a txt file + m_variables.Get("printHitsTXT", printHitsTXT); + useMaxTime = true; // use the max amplitude time of the pulse as the time of the hit + m_variables.Get("useMaxTime", useMaxTime); + signalSpeedOnStrip = 0.567; // speed of the signal on the strip in fraction of speed of light, 0.567 was previous measured data + m_variables.Get("signalSpeedOnStrip", signalSpeedOnStrip); + triggerBoardDelay = 0; // arbitrary added to include the electronic delay between two ACDC boards + m_variables.Get("triggerBoardDelay", triggerBoardDelay); + savePositionOnStrip = true; // save the position of the hit on the strip, for event display purpose + m_variables.Get("savePositionOnStrip", savePositionOnStrip); + useRange = -1; // use the pulse time for hit time, rather than the reconstructed hit time. -1 averaged peak time, 0 low range, 1 high range + m_variables.Get("useRange", useRange); + loadPrintMRDinfo = true; // print MRD track information + m_variables.Get("loadPrintMRDinfo", loadPrintMRDinfo); + // Control variables in this tool, initialized in this tool + eventNumber = 0; + + // Global Control variables that you get from the config file + ThresRecoInputWaveLabel = "LAPPDWave"; + m_variables.Get("ThresRecoInputWaveLabel", ThresRecoInputWaveLabel); + ThresRecoOutputPulseLabel = "LAPPDPulse"; + m_variables.Get("ThresRecoOutputPulseLabel", ThresRecoOutputPulseLabel); + ThresRecoOutputHitLabel = "LAPPDHit"; + m_variables.Get("ThresRecoOutputHitLabel", ThresRecoOutputHitLabel); + // Global control variables/objects that you get from other tools + m_data->Stores["ANNIEEvent"]->Header->Get("AnnieGeometry", _geom); + if (LAPPDThresRecoVerbosity > 0) + cout << "LAPPDThresReco: Geometry loaded as AnnieGeometry from Store [ANNIEEvent]" << endl; + + // Data variables + // Data variables you get from other tools (it not initialized in execute) + + // Data variables you use in this tool + if (printHitsTXT) + { + // recreate myfile + myfile.open("LAPPDThresRecoHits.txt"); + myfile << "eventNumber" + << "\t" + << "thisEventHitNumber" + << "\t" + << "stripno" + << "\t" + << "ParallelToStripPos" + << "\t" + << "TransverseToStripPos" + << "\t" + << "HitArivTime" + << "\t" + << "HitAmp" + << "\t" + << "Pulse1LastTime" + << "\t" + << "Pulse2LastTime" + << "\t" + << "Pulse1StartTime" + << "\t" + << "Pulse2StartTime" << endl; + } + if (loadPrintMRDinfo) + { + mrdfile.open("LAPPDThresRecoMRDinfo.txt"); + mrdfile << "eventNumber" + << "\t" + << "trackNumber" + << "\t" + << "trackAngle" + << "\t" + << "trackAngleError" + << "\t" + << "penetrationDepth" + << "\t" + << "trackLength" + << "\t" + << "entryPointRadius" + << "\t" + << "energyLoss" + << "\t" + << "energyLossError" + << "\t" + << "trackStartX" + << "\t" + << "trackStartY" + << "\t" + << "trackStartZ" + << "\t" + << "trackStopX" + << "\t" + << "trackStopY" + << "\t" + << "trackStopZ" + << "\t" + << "trackSide" + << "\t" + << "trackStop" + << "\t" + << "trackThrough" + << "\t" + << "fHtrackFitChi2" + << "\t" + << "fHtrackFitCov" + << "\t" + << "fVtrackFitChi2" + << "\t" + << "fVtrackFitCov" + << "\t" + << "fHtrackOrigin" + << "\t" + << "fHtrackOriginError" + << "\t" + << "fHtrackGradient" + << "\t" + << "fHtrackGradientError" + << "\t" + << "fVtrackOrigin" + << "\t" + << "fVtrackOriginError" + << "\t" + << "fVtrackGradient" + << "\t" + << "fVtrackGradientError" + << "\t" + << "particlePID" << endl; + } + + return true; +} + +bool LAPPDThresReco::Execute() +{ + CleanDataObjects(); + + m_data->CStore.Get("LAPPDana", LAPPDana); + if (!LAPPDana) + return true; + + // get the input LAPPD Data waveform; + m_data->Stores["ANNIEEvent"]->Get(ThresRecoInputWaveLabel, lappdData); + // get current LAPPD_ID + m_data->CStore.Get("LAPPD_ID", LAPPD_ID); + + if(LAPPDThresRecoVerbosity>0) + cout<<"Start WaveformMaximaFinding"<0) + cout<<"Start FillLAPPDPulse"<0) + cout<<"Start FillLAPPDHit"<0) + cout<<"Reco Finished, start filling"<Stores["ANNIEEvent"]->Set(ThresRecoOutputPulseLabel, lappdPulses); + m_data->Stores["ANNIEEvent"]->Set(ThresRecoOutputHitLabel, lappdHits); + m_data->Stores["ANNIEEvent"]->Set("waveformMax",waveformMax); + m_data->Stores["ANNIEEvent"]->Set("waveformRMS",waveformRMS); + m_data->Stores["ANNIEEvent"]->Set("waveformMaxLast",waveformMaxLast); + m_data->Stores["ANNIEEvent"]->Set("waveformMaxNearing",waveformMaxNearing); + m_data->Stores["ANNIEEvent"]->Set("waveformMaxTimeBin",waveformMaxTimeBin); + eventNumber++; // operation in this loop finished, increase the event number + + if(LAPPDThresRecoVerbosity>0) + cout<<"Filling finished, printing to txt"<CStore.Get("MrdTimeClusters", MrdTimeClusters); + if (gotMRDdata) + PrintMRDinfoToTXT(); + } + + return true; +} + +void LAPPDThresReco::CleanDataObjects() +{ + + lappdData.clear(); + lappdPulses.clear(); + lappdHits.clear(); + MrdTimeClusters.clear(); + waveformRMS.clear(); + waveformMax.clear(); + waveformMaxLast.clear(); + waveformMaxNearing.clear(); + + LAPPD_ID = -9999; + LAPPDana = false; +} + +void LAPPDThresReco::FillLAPPDPulse() +{ + + // loop over the data and fine pulses + std::map>>::iterator it; + for (it = lappdData.begin(); it != lappdData.end(); it++) + { + + // get the waveforms from channel number + unsigned long channel = it->first; + channel = channel%1000 + 1000; + if ((channel % 1000)%30 == 5) + continue; + Waveform waveforms = it->second.at(0); + vector wav = *waveforms.GetSamples(); + vector wave = wav; + if(wave.size() != 256) { + cout<<"FillLAPPDPulse: Found a bug waveform at channel "<2) + cout<<"FillLAPPDPulse: Found waveform at channel "< pulses = FindPulses(wave, LAPPD_ID, channel); + + Channel *chan = _geom->GetChannel(channel); + int stripno = chan->GetStripNum(); + int stripSide = chan->GetStripSide(); + + // check, in lappdPulses, is there an element with the strip no, if not, create one vector with lenth 2, set the pulses to element with index stripSide + if (lappdPulses.find(stripno) == lappdPulses.end()) + { + vector> stripPulses; + stripPulses.resize(2); + stripPulses.at(stripSide) = pulses; + lappdPulses[stripno] = stripPulses; + } + else + { + lappdPulses[stripno].at(stripSide) = pulses; + } + } +} + +void LAPPDThresReco::FillLAPPDHit() +{ + int numberOfHits = 0; + std::map>>::iterator it2; + for (it2 = lappdPulses.begin(); it2 != lappdPulses.end(); it2++) + { + unsigned long stripno = it2->first; + vector> pulses = it2->second; + vector lHits = FindHit(pulses); + lappdHits[stripno] = lHits; + numberOfHits += lHits.size(); + } + if (LAPPDThresRecoVerbosity > 0) + cout << "LAPPDThresReco found hits: " << numberOfHits << endl; +} + +void LAPPDThresReco::PrintHitsToTXT() +{ + int thisEventHitNumber = 0; + + // print all hits in this event to a txt file, column was separated by tab + // print: event number, hit number, hit strip number, hit loacl parallel position x, hit local transverse position y, hit time, hit amplitude + std::map>::iterator it3; + for (it3 = lappdHits.begin(); it3 != lappdHits.end(); it3++) + { + unsigned long stripno = it3->first; + vector lHits = it3->second; + for (int i = 0; i < lHits.size(); i++) + { + LAPPDHit hit = lHits.at(i); + vector positionOnLAPPD = hit.GetLocalPosition(); + double pulse1StartTime = hit.GetPulse1StartTime(); + double pulse2StartTime = hit.GetPulse2StartTime(); + double pulse1LastTime = hit.GetPulse1LastTime(); + double pulse2LastTime = hit.GetPulse2LastTime(); + // print the data in this order:myfile<LoadMRDTrackReco(i); + if (LAPPDThresRecoVerbosity > 0) + cout << "LAPPDThresReco found MRD tracks: " << fNumClusterTracks << endl; + for (int i = 0; i < fMRDTrackAngle.size(); i++) + { + mrdfile << eventNumber << "\t" << i << "\t" << fMRDTrackAngle.at(i) << "\t" << fMRDTrackAngleError.at(i) << "\t" << fMRDPenetrationDepth.at(i) << "\t" << fMRDTrackLength.at(i) << "\t" << fMRDEntryPointRadius.at(i) << "\t" << fMRDEnergyLoss.at(i) << "\t" << fMRDEnergyLossError.at(i) << "\t" << fMRDTrackStartX.at(i) << "\t" << fMRDTrackStartY.at(i) << "\t" << fMRDTrackStartZ.at(i) << "\t" << fMRDTrackStopX.at(i) << "\t" << fMRDTrackStopY.at(i) << "\t" << fMRDTrackStopZ.at(i) << "\t" << fMRDSide.at(i) << "\t" << fMRDStop.at(i) << "\t" << fMRDThrough.at(i) << "\t" << fHtrackFitChi2.at(i) << "\t" << fHtrackFitCov.at(i) << "\t" << fVtrackFitChi2.at(i) << "\t" << fVtrackFitCov.at(i) << "\t" << fHtrackOrigin.at(i) << "\t" << fHtrackOriginError.at(i) << "\t" << fHtrackGradient.at(i) << "\t" << fHtrackGradientError.at(i) << "\t" << fVtrackOrigin.at(i) << "\t" << fVtrackOriginError.at(i) << "\t" << fVtrackGradient.at(i) << "\t" << fVtrackGradientError.at(i) << "\t" << fparticlePID.at(i) << endl; + } +} + +bool LAPPDThresReco::Finalise() +{ + + // close txt file + myfile.close(); + mrdfile.close(); + + return true; +} + +vector LAPPDThresReco::FindPulses(vector wave, int LAPPD_ID, int channel) +{ + // the wave pass to here must be all positive, not the default negative signals + std::vector pulses; + + // loop the waveform, find the pulses with amplitude larger than threshold and last for bin number > minPulseWidth + bool inPulse = false; + double currentSig = threshold; + + int pulseStart = 0; + int pulseSize = 0; // number of bins of the pulse + double peakBin = 0; // which bin is the peak + double peakAmp = 0; // the peak amplitude + double Q = 0; + + vector binNumbers; + vector amplitudes; + + for (int i = 0; i < wave.size(); i++) + { + currentSig = wave.at(i); + if (wave.at(i) > threshold) + { // if the signal is larger than threshold + if (!inPulse) + { + inPulse = true; + pulseStart = i; + pulseSize = 1; + peakBin = i; + peakAmp = currentSig; + Q = currentSig / 50000. * (1e-10); // same as LAPPDFindPeak + } + else + { + if (inPulse) + { + pulseSize++; + if (currentSig > peakAmp) + { + peakAmp = currentSig; + peakBin = i; + } + Q += currentSig / 50000. * (1e-10); + } + } + binNumbers.push_back(static_cast(i)); + amplitudes.push_back(currentSig); + } + else + { // if the signal is smaller than threshold + if (inPulse) + { + inPulse = false; // exit the pulse + if (pulseSize > minPulseWidth) + { // if the pulse is long enough + double peakBinGaus = GaussianFit(binNumbers, amplitudes); + + if (LAPPDThresRecoVerbosity > 1) + cout << "inserting pulse at time: " << peakBin * (25. / 256.) << "(" << peakBinGaus << ") with peakAmp: " << peakAmp << " from " << pulseStart << " to " << pulseStart + pulseSize << endl; + if (useMaxTime) + { + LAPPDPulse thisPulse(LAPPD_ID, channel, peakBin * (25. / 256.), Q, peakAmp, pulseStart, pulseStart + pulseSize); + pulses.push_back(thisPulse); + } + else + { + LAPPDPulse thisPulse(LAPPD_ID, channel, peakBinGaus * (25. / 256.), Q, peakAmp, pulseStart, pulseStart + pulseSize); + pulses.push_back(thisPulse); + } + // tube ID: LAPPD_ID + // channel: this channel + // peakBin: the bin number of the peak in the 256 bins (use 256 bins for 25 ns, might be wrong) + // Q: charge of the pulse + // peakAmp: the peak amplitude + // pulseStart: the bin number of the start of the pulse + // pulseStart+pulseSize: the bin number of the end of the pulse + + // clean the bin numbers and amplitudes vectors + binNumbers.clear(); + amplitudes.clear(); + } + else + { + pulseStart = 0; + pulseSize = 0; + peakAmp = currentSig; + Q = 0; + } + } + } + } + return pulses; +} + +vector LAPPDThresReco::FindHit(vector> pulses) +{ + vector lHits; + + // loop the pulses, find the pairs of pulses with the same strip number and different side, then do the reco + vector side0 = pulses.at(0); + vector side1 = pulses.at(1); + if (side0.size() == 0 || side1.size() == 0) + return lHits; + + // use the vector with less number of pulse to do reco, incase some noise pulses are inserted + if (side0.size() < side1.size()) + { // if side 0 has fewer pulses + for (int i = 0; i < side0.size(); i++) + { + if (side1.size() == 0) + break; + LAPPDPulse pulse0; + LAPPDPulse pulse1; + pulse0 = side0.at(i); + int bestMatchIndex = -1; + double prob = 0; + for (int j = 0; j < side1.size(); j++) + { + pulse1 = side1.at(j); + // if the higher pulse peak amplitude is larger than 50% of the lower one, don't match + if ((pulse0.GetPeak() < pulse1.GetPeak() * 0.5) || (pulse0.GetPeak() * 0.5 > pulse1.GetPeak())) + continue; + + // if the peak time of the pulse is 2ns away from the peak time of the other pulse, don't match + if (abs(pulse1.GetTime() - pulse0.GetTime()) > 20) + continue; + + // just use a simple inverse product as the prob, the pulse finding is very rough anyway + double thisProb = 1 / (abs(pulse1.GetTime() - pulse0.GetTime()) * abs(pulse1.GetPeak() - pulse0.GetPeak())); + if (thisProb > prob) + { + prob = thisProb; + bestMatchIndex = j; + } + } + // if found the bestMatch, pair to make a hit, if not, skip + if (bestMatchIndex != -1) + { + pulse1 = side1.at(bestMatchIndex); + pulse0 = side0.at(i); + LAPPDHit hit = MakeHit(pulse0, pulse1); + lHits.push_back(hit); + side1.erase(side1.begin() + bestMatchIndex); + } + } + } + else + { // if side 1 has fewer pulses + for (int i = 0; i < side1.size(); i++) + { + if (side0.size() == 0) + break; + LAPPDPulse pulse0; + LAPPDPulse pulse1; + pulse1 = side1.at(i); + int bestMatchIndex = -1; + double prob = 0; + for (int j = 0; j < side0.size(); j++) + { + pulse0 = side0.at(j); + // if the higher pulse peak amplitude is larger than 50% of the lower one, don't match + if ((pulse0.GetPeak() < pulse1.GetPeak() * 0.5) || (pulse0.GetPeak() * 0.5 > pulse1.GetPeak())) + continue; + + // if the peak time of the pulse is 2ns away from the peak time of the other pulse, don't match + if (abs(pulse1.GetTime() - pulse0.GetTime()) > 20) + continue; + + // just use a simple inverse product as the prob, the pulse finding is very rough anyway + double thisProb = 1 / (abs(pulse1.GetTime() - pulse0.GetTime()) * abs(pulse1.GetPeak() - pulse0.GetPeak())); + if (thisProb > prob) + { + prob = thisProb; + bestMatchIndex = j; + } + } + // if found the bestMatch, pair to make a hit, if not, skip + if (bestMatchIndex != -1) + { + pulse0 = side0.at(bestMatchIndex); + pulse1 = side1.at(i); + LAPPDHit hit = MakeHit(pulse0, pulse1); + lHits.push_back(hit); + side0.erase(side0.begin() + bestMatchIndex); + } + } + } + + return lHits; +} + +LAPPDHit LAPPDThresReco::MakeHit(LAPPDPulse pulse0, LAPPDPulse pulse1) +{ + // Always use pulse1 - pulse0 + double deltaT = pulse1.GetTime() - pulse0.GetTime(); + double averageAmp = (pulse1.GetPeak() + pulse0.GetPeak()) / 2; + double averageQ = (pulse1.GetCharge() + pulse0.GetCharge()) / 2; + + if (LAPPDThresRecoVerbosity > 0) + { + cout << "Making Hit: " << endl; + cout << "Pulse0: " << endl; + cout << "Channel = " << pulse0.GetChannelID() << endl; + pulse0.Print(); + cout << "Pulse1: " << endl; + cout << "Channel = " << pulse1.GetChannelID() << endl; + pulse1.Print(); + cout << "DeltaT: " << deltaT << endl; + cout << "AverageAmp: " << averageAmp << endl; + cout << "AverageQ: " << averageQ << endl; + } + Channel *chan0 = _geom->GetChannel(pulse0.GetChannelID()); + int stripno0 = chan0->GetStripNum(); + Channel *chan1 = _geom->GetChannel(pulse1.GetChannelID()); + int stripno1 = chan1->GetStripNum(); + if (stripno0 != stripno1) + { + if (LAPPDThresRecoVerbosity > 0) + cout << "Error: the two pulses are not on the same strip!" << endl; + LAPPDHit hit; + return hit; + } + else + { + // double stripWidth = 4.62+2.29; //mm + // double LAPPDEdgeWidth = 14.40s; //mm + // double transversePos = LAPPDEdgeWidth + stripWidth*(stripno0-0.5); + + double stripWidth = 4.62 + 2.29; // mm + double LAPPDEdgeWidth = 14.40 + 4.62 / 2; // mm + double transversePos = LAPPDEdgeWidth + stripWidth * (stripno0); + + // use the center position of the strip in mm + if (LAPPDThresRecoVerbosity > 0) + { + cout << "making hit from pulse0 on channel " << pulse0.GetChannelID() << ", strip " << stripno0 << endl; + cout << "making hit from pulse1 on channel " << pulse1.GetChannelID() << ", strip " << stripno1 << endl; + cout << "transversePos: " << transversePos << endl; + } + double t0 = pulse0.GetTime() + triggerBoardDelay / 169.982; + double t1 = pulse1.GetTime(); + + // double parallelPos = (t0 - t1 + 1.14555)*0.5 *signalSpeedOnStrip * 100; + double parallelPos = (t0 - t1 + 1.37724) * 0.5 * signalSpeedOnStrip * 100; + // position from the edge of the start of pulse0 (side 0) in mm + + double averageTime = (t0 + t1) * 0.5; + double averageTimeLow = (pulse0.GetLowRange() + pulse1.GetLowRange()) * 0.5; + double averageTimeHi = (pulse0.GetHiRange() + pulse1.GetHiRange()) * 0.5; + + double arrivalTime = t0 - (t0 - t1 + 1) * 0.5; + + if (LAPPDThresRecoVerbosity > 0) + cout << "Position on LAPPD: " << parallelPos << " " << transversePos << endl; + + vector positionOnLAPPD = {parallelPos, transversePos}; + vector positionInTank = {0 + transversePos / 1000 - 0.1, -0.2255, 2.951}; // need to get this from the geometry + if (savePositionOnStrip) + { + if (parallelPos < 100 && parallelPos > -100) + positionInTank[1] = -0.2255 + parallelPos / 1000; + } + + int tubeID = pulse0.GetTubeId(); + double pulse1LastTime = pulse0.GetHiRange() - pulse0.GetLowRange(); + double pulse2LastTime = pulse1.GetHiRange() - pulse1.GetLowRange(); + double pulse1StartTime = pulse0.GetLowRange(); + double pulse2StartTime = pulse1.GetLowRange(); + // print tubeID + if (LAPPDThresRecoVerbosity > 0) + { + cout << "TubeID: " << tubeID << endl; + cout << "average charge is " << averageQ << ", q/amplitude is " << averageQ / averageAmp << endl; + cout << "average amplitude is " << averageAmp << ", amplitude/7 is " << averageAmp / 7 << endl; + } + if (useRange == -1) + { + LAPPDHit hit(tubeID, averageTime, averageAmp, positionInTank, positionOnLAPPD, pulse1LastTime, pulse2LastTime, pulse1StartTime, pulse2StartTime); + return hit; + } + else if (useRange == 0) + { + LAPPDHit hit(tubeID, averageTimeLow, averageAmp, positionInTank, positionOnLAPPD, pulse1LastTime, pulse2LastTime, pulse1StartTime, pulse2StartTime); + return hit; + } + else if (useRange == 1) + { + LAPPDHit hit(tubeID, averageTimeHi, averageAmp, positionInTank, positionOnLAPPD, pulse1LastTime, pulse2LastTime, pulse1StartTime, pulse2StartTime); + return hit; + } + else + { + cout << "Error: useRange should be -1, 0 or 1" << endl; + return LAPPDHit(); + } + + //********************* + // NOTE: we are actually using the average AMPLITUDE here, rather than the charge + //********************* + + // return hit; + } +} + +double LAPPDThresReco::GaussianFit(const vector &xData, const vector &yData) +{ + TGraph graph(xData.size(), &xData[0], &yData[0]); + TF1 f("gaus", "gaus", xData.front(), xData.back()); + graph.Fit(&f, "Q"); // "Q" for quiet mode, no output + return f.GetParameter(1); // 返回高斯拟åˆçš„峰值ä½ç½® +} + +void LAPPDThresReco::CleanMRDRecoInfo() +{ + fMRDTrackAngle.clear(); + fMRDTrackAngleError.clear(); + fMRDPenetrationDepth.clear(); + fMRDTrackLength.clear(); + fMRDEntryPointRadius.clear(); + fMRDEnergyLoss.clear(); + fMRDEnergyLossError.clear(); + fMRDTrackStartX.clear(); + fMRDTrackStartY.clear(); + fMRDTrackStartZ.clear(); + fMRDTrackStopX.clear(); + fMRDTrackStopY.clear(); + fMRDTrackStopZ.clear(); + fMRDSide.clear(); + fMRDStop.clear(); + fMRDThrough.clear(); + fHtrackFitChi2.clear(); + fHtrackFitCov.clear(); + fVtrackFitChi2.clear(); + fVtrackFitCov.clear(); + fHtrackOrigin.clear(); + fHtrackOriginError.clear(); + fHtrackGradient.clear(); + fHtrackGradientError.clear(); + fVtrackOrigin.clear(); + fVtrackOriginError.clear(); + fVtrackGradient.clear(); + fVtrackGradientError.clear(); + fparticlePID.clear(); +} + +int LAPPDThresReco::LoadMRDTrackReco(int SubEventID) +{ + + // Check for valid track criteria + m_data->Stores["MRDTracks"]->Get("MRDTracks", theMrdTracks); + m_data->Stores["MRDTracks"]->Get("NumMrdTracks", numtracksinev); + // Loop over reconstructed tracks + + Position StartVertex; + Position StopVertex; + double TrackLength = -9999; + double TrackAngle = -9999; + double TrackAngleError = -9999; + double PenetrationDepth = -9999; + Position MrdEntryPoint; + double EnergyLoss = -9999; // in MeV + double EnergyLossError = -9999; + double EntryPointRadius = -9999; + bool IsMrdPenetrating; + bool IsMrdStopped; + bool IsMrdSideExit; + double HtrackFitChi2 = -9999; + double HtrackFitCov = -9999; + double VtrackFitChi2 = -9999; + double VtrackFitCov = -9999; + double HtrackOrigin = -9999; + double HtrackOriginError = -9999; + double HtrackGradient = -9999; + double HtrackGradientError = -9999; + double VtrackOrigin = -9999; + double VtrackOriginError = -9999; + double VtrackGradient = -9999; + double VtrackGradientError = -9999; + int particlePID = -9999; + + int NumClusterTracks = 0; + for (int tracki = 0; tracki < numtracksinev; tracki++) + { + BoostStore *thisTrackAsBoostStore = &(theMrdTracks->at(tracki)); + int TrackEventID = -1; + // get track properties that are needed for the through-going muon selection + thisTrackAsBoostStore->Get("MrdSubEventID", TrackEventID); + if (TrackEventID != SubEventID) + continue; + + // If we're here, this track is associated with this cluster + thisTrackAsBoostStore->Get("StartVertex", StartVertex); + thisTrackAsBoostStore->Get("StopVertex", StopVertex); + thisTrackAsBoostStore->Get("TrackAngle", TrackAngle); + thisTrackAsBoostStore->Get("TrackAngleError", TrackAngleError); + thisTrackAsBoostStore->Get("PenetrationDepth", PenetrationDepth); + thisTrackAsBoostStore->Get("MrdEntryPoint", MrdEntryPoint); + thisTrackAsBoostStore->Get("EnergyLoss", EnergyLoss); + thisTrackAsBoostStore->Get("EnergyLossError", EnergyLossError); + thisTrackAsBoostStore->Get("IsMrdPenetrating", IsMrdPenetrating); // bool + thisTrackAsBoostStore->Get("IsMrdStopped", IsMrdStopped); // bool + thisTrackAsBoostStore->Get("IsMrdSideExit", IsMrdSideExit); + thisTrackAsBoostStore->Get("HtrackFitChi2", HtrackFitChi2); + thisTrackAsBoostStore->Get("HtrackFitCov", HtrackFitCov); + thisTrackAsBoostStore->Get("VtrackFitChi2", VtrackFitChi2); + thisTrackAsBoostStore->Get("VtrackFitCov", VtrackFitCov); + TrackLength = sqrt(pow((StopVertex.X() - StartVertex.X()), 2) + pow(StopVertex.Y() - StartVertex.Y(), 2) + pow(StopVertex.Z() - StartVertex.Z(), 2)) * 100.0; + EntryPointRadius = sqrt(pow(MrdEntryPoint.X(), 2) + pow(MrdEntryPoint.Y(), 2)) * 100.0; // convert to cm + PenetrationDepth = PenetrationDepth * 100.0; + thisTrackAsBoostStore->Get("HtrackOrigin", HtrackOrigin); + thisTrackAsBoostStore->Get("HtrackOriginError", HtrackOriginError); + thisTrackAsBoostStore->Get("HtrackGradient", HtrackGradient); + thisTrackAsBoostStore->Get("HtrackGradientError", HtrackGradientError); + thisTrackAsBoostStore->Get("VtrackOrigin", VtrackOrigin); + thisTrackAsBoostStore->Get("VtrackOriginError", VtrackOriginError); + thisTrackAsBoostStore->Get("VtrackGradient", VtrackGradient); + thisTrackAsBoostStore->Get("VtrackGradientError", VtrackGradientError); + thisTrackAsBoostStore->Get("particlePID", particlePID); + + // Push back some properties + fMRDTrackAngle.push_back(TrackAngle); + fMRDTrackAngleError.push_back(TrackAngleError); + fMRDTrackLength.push_back(TrackLength); + fMRDPenetrationDepth.push_back(PenetrationDepth); + fMRDEntryPointRadius.push_back(EntryPointRadius); + fMRDEnergyLoss.push_back(EnergyLoss); + fMRDEnergyLossError.push_back(EnergyLossError); + fMRDTrackStartX.push_back(StartVertex.X()); + fMRDTrackStartY.push_back(StartVertex.Y()); + fMRDTrackStartZ.push_back(StartVertex.Z()); + fMRDTrackStopX.push_back(StopVertex.X()); + fMRDTrackStopY.push_back(StopVertex.Y()); + fMRDTrackStopZ.push_back(StopVertex.Z()); + fMRDStop.push_back(IsMrdStopped); + fMRDSide.push_back(IsMrdSideExit); + fMRDThrough.push_back(IsMrdPenetrating); + fHtrackFitChi2.push_back(HtrackFitChi2); + fHtrackFitCov.push_back(HtrackFitCov); + fVtrackFitChi2.push_back(VtrackFitChi2); + fVtrackFitCov.push_back(VtrackFitCov); + fHtrackOrigin.push_back(HtrackOrigin); + fHtrackOriginError.push_back(HtrackOriginError); + fHtrackGradient.push_back(HtrackGradient); + fHtrackGradientError.push_back(HtrackGradientError); + fVtrackOrigin.push_back(VtrackOrigin); + fVtrackOriginError.push_back(VtrackOriginError); + fVtrackGradient.push_back(VtrackGradient); + fVtrackGradientError.push_back(VtrackGradientError); + fparticlePID.push_back(particlePID); + NumClusterTracks += 1; + } + return NumClusterTracks; +} + + + +void LAPPDThresReco::WaveformMaximaFinding(){ + //loop the lappdData map, for each value, find the maxima and RMS, and put them into waveformMax and waveformRMS + //use the strip number + 30* strip side as the key + if(LAPPDThresRecoVerbosity>0 ) cout<<"WaveformMaximaFinding: Start finding maxima and RMS of the waveforms"<>>::iterator it; + for(it = lappdData.begin(); it!= lappdData.end(); it++){ + unsigned long channel = it->first; + channel = channel%1000 + 1000; + if(channel == 1005 || channel == 1035) continue; + Channel* chan = _geom->GetChannel(channel); + int stripno = chan->GetStripNum(); + int stripSide = chan->GetStripSide(); + Waveform waveforms = it->second.at(0); + vector wav = *waveforms.GetSamples(); + + vector wave = wav; + if(wave.size() != 256) { + cout<<"WaveformMaximaFinding: Found a bug waveform at channel "<2) + cout<<"WaveformMaximaFinding: Found a waveform at channel "<max) { + if(wave.at(i+1)>0.8*wave.at(i) && wave.at(i-1)>0.8*wave.at(i)){ + max = wave.at(i); + maxIsLast = 1; + binOfMax = i; + + } + if(wave.at(i+1)>wave.at(i-1)){ + nearingMin = wave.at(i-1); + }else{ + nearingMin = wave.at(i+1); + } + } + + rms += (wave.at(i))*(wave.at(i)); + } + + rms = sqrt(rms/wave.size()); + int key = stripno + 30*stripSide; + if(waveformMax[stripno].size() == 0){ + waveformMax[stripno].resize(2); + waveformRMS[stripno].resize(2); + waveformMaxLast[stripno].resize(2); + waveformMaxNearing[stripno].resize(2); + waveformMaxTimeBin[stripno].resize(2); + } + waveformMax[stripno].at(stripSide) = max; + waveformRMS[stripno].at(stripSide) = rms; + waveformMaxLast[stripno].at(stripSide) = maxIsLast; + waveformMaxNearing[stripno].at(stripSide) = nearingMin; + waveformMaxTimeBin[stripno].at(stripSide) = binOfMax; + } + +} + diff --git a/UserTools/LAPPDThresReco/LAPPDThresReco.h b/UserTools/LAPPDThresReco/LAPPDThresReco.h new file mode 100644 index 000000000..e73af72d1 --- /dev/null +++ b/UserTools/LAPPDThresReco/LAPPDThresReco.h @@ -0,0 +1,127 @@ +#ifndef LAPPDThresReco_H +#define LAPPDThresReco_H + +#include +#include + +#include "Tool.h" +#include "LAPPDPulse.h" +#include "LAPPDHit.h" +#include "Geometry.h" +#include "TGraph.h" +#include "TF1.h" +#include "Position.h" + +/** + * \class LAPPDThresReco + * + * Use an input std::map>> lappdData and a threshold to find pulses and construct hits. + * Output a std::map> lappdHits. + * Also generate txt files for hits and muon tracks. (need the muon track tools in the tool chain) + * + * $Author: Yue Feng $ + * $Date: 2024/01/29 $ + * Contact: yuef@iastate.edu + */ + +class LAPPDThresReco : public Tool +{ + +public: + LAPPDThresReco(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + + vector FindPulses(vector wave, int LAPPD_ID, int channel); + vector FindHit(vector> pulses); + LAPPDHit MakeHit(LAPPDPulse pulse0, LAPPDPulse pulse1); + double GaussianFit(const vector &xData, const vector &yData); + int LoadMRDTrackReco(int SubEventID); + void CleanMRDRecoInfo(); + void CleanDataObjects(); + void FillLAPPDPulse(); + void FillLAPPDHit(); + void PrintHitsToTXT(); + void PrintMRDinfoToTXT(); + void WaveformMaximaFinding(); + +private: + // This tool, control variables (only used in this tool, every thing that is not an data object) + // Variables that you get from the config file + int LAPPDThresRecoVerbosity; + double threshold; + int minPulseWidth; + int printHitsTXT; + bool useMaxTime; + double signalSpeedOnStrip; + double triggerBoardDelay; + bool savePositionOnStrip; + int useRange; //-1 averaged peak time, 0 low, 1 high + bool loadPrintMRDinfo; + // Variables that you need in the tool + int eventNumber; + + // LAPPD tool chain, control variables (Will be shared in multiple LAPPD tools to show the state of the tool chain in each loop) + // Variables that you get from the config file + string ThresRecoInputWaveLabel; + string ThresRecoOutputPulseLabel; + string ThresRecoOutputHitLabel; + // Variables that you need in the tool + Geometry *_geom; + bool LAPPDana; + + // LAPPD tool chain, data variables. (Will be used in multiple LAPPD tools) + // everything you get or set to Store, which means it may be used in other tools or it's from other tools + std::vector *theMrdTracks; // the reconstructed tracks + int numtracksinev; + std::map channelnoToSwitchbit; + std::map> waveformMax; + std::map> waveformRMS; + std::map> waveformMaxLast; + std::map> waveformMaxNearing; + std::map> waveformMaxTimeBin; + + // This tool, data variables (only used in this tool, every thing that is an data object) + std::map>> lappdData; // waveform data + std::map>> lappdPulses; // save threshold based method found lappd pulses + std::map> lappdHits; + std::vector> MrdTimeClusters; + int LAPPD_ID; + std::vector fMRDTrackAngle; + std::vector fMRDTrackAngleError; + std::vector fMRDPenetrationDepth; + std::vector fMRDTrackLength; + std::vector fMRDEntryPointRadius; + std::vector fMRDEnergyLoss; + std::vector fMRDEnergyLossError; + std::vector fMRDTrackStartX; + std::vector fMRDTrackStartY; + std::vector fMRDTrackStartZ; + std::vector fMRDTrackStopX; + std::vector fMRDTrackStopY; + std::vector fMRDTrackStopZ; + std::vector fHtrackFitChi2; + std::vector fHtrackFitCov; + std::vector fVtrackFitChi2; + std::vector fVtrackFitCov; + std::vector fMRDSide; + std::vector fMRDStop; + std::vector fMRDThrough; + std::vector fHtrackOrigin; + std::vector fHtrackOriginError; + std::vector fHtrackGradient; + std::vector fHtrackGradientError; + std::vector fVtrackOrigin; + std::vector fVtrackOriginError; + std::vector fVtrackGradient; + std::vector fVtrackGradientError; + std::vector fparticlePID; + + // data variables don't need to be cleared in each loop + ofstream myfile; + ofstream mrdfile; + +}; + +#endif diff --git a/UserTools/LAPPDThresReco/README.md b/UserTools/LAPPDThresReco/README.md new file mode 100644 index 000000000..ed43861cc --- /dev/null +++ b/UserTools/LAPPDThresReco/README.md @@ -0,0 +1,20 @@ +# LAPPDThresReco + +LAPPDThresReco + +## Data + +Describe any data formats LAPPDThresReco creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for LAPPDThresReco. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.cpp b/UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.cpp new file mode 100644 index 000000000..1e9192719 --- /dev/null +++ b/UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.cpp @@ -0,0 +1,248 @@ +#include "LAPPDTimeAlignment.h" +#include "TGraph.h" + +LAPPDTimeAlignment::LAPPDTimeAlignment():Tool(){} + + +bool LAPPDTimeAlignment::Initialise(std::string configfile, DataModel &data) +{ + /////////////////// Useful header /////////////////////// + if(configfile!="") m_variables.Initialise(configfile); // loading config file + //m_variables.Print(); + + m_data= &data; //assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + m_variables.Get("FindT0InputWavLabel",InputWavLabel); + m_variables.Get("FindT0OutputWavLabel",OutputWavLabel); + + m_variables.Get("FindT0Verbosity",FindT0VerbosityLevel); + + m_variables.Get("TrigEarlyCut",trigearlycut); + m_variables.Get("TrigLateCut",triglatecut); + + m_variables.Get("T0signalmax",T0signalmax); + m_variables.Get("T0signalthreshold",T0signalthreshold); + + m_variables.Get("T0signalmaxOld",T0signalmaxOld); + m_variables.Get("T0signalthresholdOld",T0signalthresholdOld); + + m_variables.Get("T0offset",T0offset); + m_variables.Get("GlobalShiftT0",globalshiftT0); + + m_data->Stores["ANNIEEvent"]->Get("TrigChannel",TrigChannel); + m_data->Stores["ANNIEEvent"]->Get("LAPPDchannelOffset",LAPPDchannelOffset); + + return true; +} + + +bool LAPPDTimeAlignment::Execute(){ + + oldLaser = 0; + m_data->Stores["ANNIEEvent"]->Get("oldLaser", oldLaser); + if(oldLaser == 1){T0signalmax=T0signalmaxOld; T0signalthreshold=T0signalthresholdOld;} + + if(FindT0VerbosityLevel>0) cout<<"OLD LASER? "<>> lappddata; + m_data->Stores["ANNIEEvent"]->Get(InputWavLabel,lappddata); + vector NReadBoards; + m_data->Stores["ANNIEEvent"]->Get("ACDCboards",NReadBoards); + std::map>> reordereddata; + bool T0signalInWindow = false; + double deltaT; + + + map >> :: iterator itr_bi; + for(int bi: NReadBoards) + { + T0channelNo = LAPPDchannelOffset+(30*bi)+TrigChannel; + + if(FindT0VerbosityLevel>0) cout<<"For board "<0) cout<<"In LAPPDTimeAlignment, T0 channel:"<< T0channelNo<<" , InputWavlabel: "< bwav = (itr_bi->second).at(0); + + double thetime = Tfit(bwav.GetSamples()); + int switchbit = (int)(thetime/100.); + deltaT = thetime - (100.*(double)switchbit); + int Qvar=0; + if( (switchbit>=trigearlycut) && (switchbit<=triglatecut) ) T0signalInWindow = true; + + //vector transcribe + vec_deltaT.push_back(deltaT); + vec_T0signalInWindow.push_back(T0signalInWindow); + vec_T0Bin.push_back(switchbit); + + if(FindT0VerbosityLevel>0) cout<<"Done finding the time, switchbit:" << switchbit << " , deltaT: "<1) cout<<"ready to loop"<>> :: iterator itr; + for (itr = lappddata.begin(); itr != lappddata.end(); ++itr) + { + unsigned long channelno = itr->first; + if(FindT0VerbosityLevel>2) + cout<<"Found channelno: "<first; + vector> Vwavs = itr->second; + vector> Vrwav; + int bi = (int)(channelno-LAPPDchannelOffset)/30%2; //TODO: fix this, why loading data with board 2 and 3 have channel from 0 to 120? + int countnumber = (channelno%1000)%60; + if(FindT0VerbosityLevel>2)cout <<"Looping with channelno: "<2 && i ==0) cout<<"Looping waveform at"< bwav = Vwavs.at(i); + Waveform rwav; + Waveform rwavShift; + + int sb = vec_T0Bin[bi] + T0offset + AnalogBoardShift[countnumber]; + + countnumber++; + + + if(sb<0) sb+=255; + + for(int j=0; j< bwav.GetSamples()->size(); j++) + { + if(sb>255) sb=0; + double nsamp = bwav.GetSamples()->at(sb); + rwav.PushSample(nsamp); + sb++; + } + + for(int j=0; j< rwav.GetSamples()->size(); j++) + { + int ibin = j + globalshiftT0; + if(ibin > 255) ibin = ibin - 255; + double nsamp = rwav.GetSamples()->at(ibin); + rwavShift.PushSample(nsamp); + } + Vrwav.push_back(rwavShift); + } + reordereddata.insert(pair>>(channelno,Vrwav)); + } + + if(FindT0VerbosityLevel>0) cout<<"End of LAPPDTimeAlignment..."<Stores["ANNIEEvent"]->Set(OutputWavLabel,reordereddata); + m_data->Stores["ANNIEEvent"]->Set("deltaT",vec_deltaT); + m_data->Stores["ANNIEEvent"]->Set("T0signalInWindow",T0signalInWindow); + m_data->Stores["ANNIEEvent"]->Set("T0Bin",vec_T0Bin); + vec_deltaT.clear(); + vec_T0signalInWindow.clear(); + vec_T0Bin.clear(); + + return true; +} + + +bool LAPPDTimeAlignment::Finalise() +{ + return true; +} + + + +double LAPPDTimeAlignment::Tfit(std::vector* wf) +{ + int nbin = wf->size(); + + double ppre=0.0; + double pvol=0.0; + + + bool firstcross=true; + double ttime=0; + + for(int i=0;iat(i)); + if(i>1) ppre = (wf->at(i-1)); + + if(FindT0VerbosityLevel>2) cout< T0signalmax && ppre < T0signalmax && i>5 && i<250){ //trigger up to +200 2020 data + if(FindT0VerbosityLevel>1) cout<<"Old t0 bin: "<SetPoint(j+7,(i+j)*100.,(wf->at(i+j))); //select 7 points + } + bool firstthreshcross=true; + for(int k=(i-7)*100; k<(i+1)*100; k+=10){ + if(FindT0VerbosityLevel==3) cout<Eval((double)k, 0, "S"))<Eval((double)k, 0, "S"))2) cout<<"time: "< T0signalmax && i>7 && i<249){ + + if(FindT0VerbosityLevel>1) cout<<"New t0 bin: "<SetPoint(j+7,(i+j)*100.,(wf->at(i+j))); + } + + bool firstthreshcross=true; + for(int k=(i-7)*100; k<(i+1)*100; k+=10){ + + if(FindT0VerbosityLevel==3) cout<Eval((double)k, 0, "S"))<Eval((double)k, 0, "S"))2) cout<<"time: "<0) cout<<"Done Finding T0"< +#include + +#include "Tool.h" + + +/** + * \class LAPPDTimeAlignment + * + * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. +* +* $Author: B.Richards $ +* $Date: 2019/05/28 10:44:00 $ +* Contact: b.richards@qmul.ac.uk +*/ +class LAPPDTimeAlignment: public Tool { + + + public: + + LAPPDTimeAlignment(); ///< Simple constructor + bool Initialise(std::string configfile,DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + double Tfit(std::vector* wf); + + private: + + //vector for save + vector vec_T0signalInWindow; + vector vec_deltaT; + vector vec_T0Bin; + + int LAPPDchannelOffset; + int TrigChannel; + int T0offset; + double T0signalmax,T0signalthreshold; + double T0signalmaxOld,T0signalthresholdOld; + int T0channelNo; + int FindT0VerbosityLevel; + int globalshiftT0; + string InputWavLabel; + string OutputWavLabel; + int trigearlycut,triglatecut; + int oldLaser; +}; + + +#endif diff --git a/UserTools/LAPPDTimeAlignment/README.md b/UserTools/LAPPDTimeAlignment/README.md new file mode 100644 index 000000000..7690759f1 --- /dev/null +++ b/UserTools/LAPPDTimeAlignment/README.md @@ -0,0 +1,20 @@ +# LAPPDTimeAlignment + +LAPPDTimeAlignment + +## Data + +Describe any data formats LAPPDTimeAlignment creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for LAPPDTimeAlignment. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.cpp b/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.cpp new file mode 100644 index 000000000..b491b2dd2 --- /dev/null +++ b/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.cpp @@ -0,0 +1,790 @@ +#include "LAPPDTreeMaker.h" + +LAPPDTreeMaker::LAPPDTreeMaker() : Tool() {} + +bool LAPPDTreeMaker::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + m_variables.Get("treeMakerVerbosity", treeMakerVerbosity); + m_variables.Get("treeMakerInputPulseLabel", treeMakerInputPulseLabel); + m_variables.Get("treeMakerInputHitLabel", treeMakerInputHitLabel); + treeMakerOutputFileName = "LAPPDTree.root"; + m_variables.Get("treeMakerOutputFileName", treeMakerOutputFileName); + + LoadPulse = false; + m_variables.Get("LoadPulse", LoadPulse); + LoadHit = false; + m_variables.Get("LoadHit", LoadHit); + LoadWaveform = false; + m_variables.Get("LoadWaveform", LoadWaveform); + LoadLAPPDDataTimeStamp = false; + m_variables.Get("LoadLAPPDDataTimeStamp", LoadLAPPDDataTimeStamp); + LoadPPSTimestamp = false; + m_variables.Get("LoadPPSTimestamp", LoadPPSTimestamp); + LoadRunInfoRaw = false; + m_variables.Get("LoadRunInfoRaw", LoadRunInfoRaw); + LoadRunInfoANNIEEvent = false; + m_variables.Get("LoadRunInfoANNIEEvent", LoadRunInfoANNIEEvent); + LoadTriggerInfo = false; + m_variables.Get("LoadTriggerInfo", LoadTriggerInfo); + LoadGroupedTriggerInfo = false; + m_variables.Get("LoadGroupedTriggerInfo", LoadGroupedTriggerInfo); + if (!LoadTriggerInfo) + LoadGroupedTriggerInfo = false; // if not loading trigger, don't fill grouped trigger + LoadGroupOption = "beam"; + m_variables.Get("LoadGroupOption", LoadGroupOption); + + TString filename = treeMakerOutputFileName; + file = new TFile(filename, "RECREATE"); + fPulse = new TTree("Pulse", "Pulse"); + fHit = new TTree("Hit", "Hit"); + fWaveform = new TTree("Waveform", "Waveform"); + fTimeStamp = new TTree("TimeStamp", "TimeStamp"); + fTrigger = new TTree("Trig", "Trig"); + fGroupedTrigger = new TTree("GTrig", "GTrig"); + + fPulse->Branch("RunNumber", &RunNumber, "RunNumber/I"); + fPulse->Branch("SubRunNumber", &SubRunNumber, "SubRunNumber/I"); + fPulse->Branch("PartFileNumber", &PartFileNumber, "PartFileNumber/I"); + fPulse->Branch("EventNumber", &EventNumber, "EventNumber/I"); + fPulse->Branch("LAPPD_ID", &LAPPD_ID, "LAPPD_ID/I"); + fPulse->Branch("LAPPDDataTimeStampUL", &LAPPDDataTimeStampUL, "LAPPDDataTimeStampUL/l"); + fPulse->Branch("LAPPDDataBeamgateUL", &LAPPDDataBeamgateUL, "LAPPDDataBeamgateUL/l"); + fPulse->Branch("ChannelID", &ChannelID, "ChannelID/I"); + fPulse->Branch("StripNumber", &StripNumber, "StripNumber/I"); + fPulse->Branch("PeakTime", &PeakTime, "PeakTime/D"); + fPulse->Branch("Charge", &Charge, "Charge/D"); + fPulse->Branch("PeakAmp", &PeakAmp, "PeakAmp/D"); + fPulse->Branch("PulseStart", &PulseStart, "PulseStart/D"); + fPulse->Branch("PulseEnd", &PulseEnd, "PulseEnd/D"); + fPulse->Branch("PulseSize", &PulseSize, "PulseSize/D"); + fPulse->Branch("PulseSide", &PulseSide, "PulseSide/I"); + fPulse->Branch("PulseThreshold", &PulseThreshold, "PulseThreshold/D"); + fPulse->Branch("PulseBaseline", &PulseBaseline, "PulseBaseline/D"); + + fHit->Branch("RunNumber", &RunNumber, "RunNumber/I"); + fHit->Branch("SubRunNumber", &SubRunNumber, "SubRunNumber/I"); + fHit->Branch("PartFileNumber", &PartFileNumber, "PartFileNumber/I"); + fHit->Branch("EventNumber", &EventNumber, "EventNumber/I"); + fHit->Branch("LAPPD_ID", &LAPPD_ID, "LAPPD_ID/I"); + fHit->Branch("LAPPDDataTimeStampUL", &LAPPDDataTimeStampUL, "LAPPDDataTimeStampUL/l"); + fHit->Branch("LAPPDDataBeamgateUL", &LAPPDDataBeamgateUL, "LAPPDDataBeamgateUL/l"); + fHit->Branch("StripNumber", &StripNumber, "StripNumber/I"); + fHit->Branch("HitTime", &HitTime, "HitTime/D"); + fHit->Branch("HitAmp", &HitAmp, "HitAmp/D"); + fHit->Branch("XPosTank", &XPosTank, "XPosTank/D"); + fHit->Branch("YPosTank", &YPosTank, "YPosTank/D"); + fHit->Branch("ZPosTank", &ZPosTank, "ZPosTank/D"); + fHit->Branch("ParallelPos", &ParallelPos, "ParallelPos/D"); + fHit->Branch("TransversePos", &TransversePos, "TransversePos/D"); + fHit->Branch("Pulse1StartTime", &Pulse1StartTime, "Pulse1StartTime/D"); + fHit->Branch("Pulse2StartTime", &Pulse2StartTime, "Pulse2StartTime/D"); + fHit->Branch("Pulse1LastTime", &Pulse1LastTime, "Pulse1LastTime/D"); + fHit->Branch("Pulse2LastTime", &Pulse2LastTime, "Pulse2LastTime/D"); + + fWaveform->Branch("RunNumber", &RunNumber, "RunNumber/I"); + fWaveform->Branch("SubRunNumber", &SubRunNumber, "SubRunNumber/I"); + fWaveform->Branch("PartFileNumber", &PartFileNumber, "PartFileNumber/I"); + fWaveform->Branch("EventNumber", &EventNumber, "EventNumber/I"); + fWaveform->Branch("LAPPD_ID", &LAPPD_ID, "LAPPD_ID/I"); + fWaveform->Branch("LAPPDDataTimeStampUL", &LAPPDDataTimeStampUL, "LAPPDDataTimeStampUL/l"); + fWaveform->Branch("LAPPDDataBeamgateUL", &LAPPDDataBeamgateUL, "LAPPDDataBeamgateUL/l"); + fWaveform->Branch("StripNumber", &StripNumber, "StripNumber/I"); + fWaveform->Branch("PulseSide", &PulseSide, "PulseSide/I"); + fWaveform->Branch("WaveformMax", &waveformMaxValue, "WaveformMax/D"); + fWaveform->Branch("WaveformRMS", &waveformRMSValue, "WaveformRMS/D"); + fWaveform->Branch("WaveformMaxTimeBin", &waveformMaxTimeBinValue, "WaveformMaxTimeBin/I"); + fWaveform->Branch("waveformMaxFoundNear", &waveformMaxFoundNear, "waveformMaxFoundNear/O"); // O is boolean + fWaveform->Branch("WaveformMaxNearing", &waveformMaxNearingValue, "WaveformMaxNearing/D"); + + fTimeStamp->Branch("RunNumber", &RunNumber, "RunNumber/I"); + fTimeStamp->Branch("SubRunNumber", &SubRunNumber, "SubRunNumber/I"); + fTimeStamp->Branch("PartFileNumber", &PartFileNumber, "PartFileNumber/I"); + fTimeStamp->Branch("EventNumber", &EventNumber, "EventNumber/I"); + fTimeStamp->Branch("LAPPD_ID", &LAPPD_ID, "LAPPD_ID/I"); + fTimeStamp->Branch("LAPPDDataTimeStampUL", &LAPPDDataTimeStampUL, "LAPPDDataTimeStampUL/l"); + fTimeStamp->Branch("LAPPDDataBeamgateUL", &LAPPDDataBeamgateUL, "LAPPDDataBeamgateUL/l"); + fTimeStamp->Branch("LAPPDDataTimestamp", &LAPPDDataTimestampPart1, "LAPPDDataTimestamp/l"); + fTimeStamp->Branch("LAPPDDataBeamgate", &LAPPDDataBeamgatePart1, "LAPPDDataBeamgate/l"); + fTimeStamp->Branch("LAPPDDataTimestampFloat", &LAPPDDataTimestampPart2, "LAPPDDataTimestampFloat/D"); + fTimeStamp->Branch("LAPPDDataBeamgateFloat", &LAPPDDataBeamgatePart2, "LAPPDDataBeamgateFloat/D"); + fTimeStamp->Branch("ppsDiff", &ppsDiff, "ppsDiff/L"); + fTimeStamp->Branch("ppsCount0", &ppsCount0, "ppsCount0/l"); + fTimeStamp->Branch("ppsCount1", &ppsCount1, "ppsCount1/l"); + fTimeStamp->Branch("ppsTime0", &ppsTime0, "ppsTime0/l"); + fTimeStamp->Branch("ppsTime1", &ppsTime1, "ppsTime1/l"); + + // trigger trees have no related to LAPPD data or PPS, so don't need event number + fTrigger->Branch("RunNumber", &RunNumber, "RunNumber/I"); + fTrigger->Branch("SubRunNumber", &SubRunNumber, "SubRunNumber/I"); + fTrigger->Branch("PartFileNumber", &PartFileNumber, "PartFileNumber/I"); + fTrigger->Branch("CTCTimeStamp", &CTCTimeStamp, "CTCTimeStamp/l"); + fTrigger->Branch("CTCTriggerWord", &CTCTriggerWord); + fTrigger->Branch("trigNumInMap", &trigNumInThisMap, "trigNumInMap/I"); + fTrigger->Branch("trigIndexInMap", &trigIndexInThisMap, "trigNumInMap/I"); + + fGroupedTrigger->Branch("RunNumber", &RunNumber, "RunNumber/I"); + fGroupedTrigger->Branch("SubRunNumber", &SubRunNumber, "SubRunNumber/I"); + fGroupedTrigger->Branch("PartFileNumber", &PartFileNumber, "PartFileNumber/I"); + fGroupedTrigger->Branch("gTrigWord", &groupedTriggerWords); + fGroupedTrigger->Branch("gTrigTime", &groupedTriggerTimestamps); + fGroupedTrigger->Branch("gTrigType", &groupedTriggerType, "gTrigType/I"); + fGroupedTrigger->Branch("gTrigNum", &TriggerGroupNumInThisEvent, "gTrigNum/I"); + + TriggerWordMap = new std::map>; + m_data->Stores["ANNIEEvent"]->Header->Get("AnnieGeometry", _geom); + EventNumber = 0; + + return true; +} + +bool LAPPDTreeMaker::Execute() +{ + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::Execute()" << endl; + CleanVariables(); + + m_data->CStore.Get("LoadingPPS", LoadingPPS); + if (treeMakerVerbosity > 0) + cout << "LoadingPPS: " << LoadingPPS << endl; + + m_data->CStore.Get("LAPPDana", LAPPDana); + if (treeMakerVerbosity > 0) + cout << "LAPPDana: " << LAPPDana << endl; + + if (LoadRunInfoRaw) + LoadRunInfoFromRaw(); + + if (LoadRunInfoANNIEEvent) + LoadRunInfoFromANNIEEvent(); + + bool loadTriggerPaused = false; + m_data->CStore.Get("PauseCTCDecoding", loadTriggerPaused); + if (treeMakerVerbosity > 0) + cout << "loadTriggerPaused: " << loadTriggerPaused << endl; + if (!loadTriggerPaused) + { + if (LoadTriggerInfo) + { + bool getTrig = m_data->CStore.Get("TimeToTriggerWordMap", TriggerWordMap); + if (!getTrig) + cout << "Error in getting trigger word map" << endl; + if (getTrig) + { + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker:: TimeToTriggerWordMap size: " << TriggerWordMap->size() << endl; + FillTriggerTree(); + } + } + } + + if (LoadGroupedTriggerInfo) + FillGroupedTriggerTree(); + + if (LoadPPSTimestamp && LoadingPPS) + { + bool gotPPSTimestamp = m_data->CStore.Get("LAPPDPPSVector", pps_vector); + bool gotPPSCounter = m_data->CStore.Get("LAPPDPPScount", pps_count_vector); + if (!gotPPSTimestamp) + cout << "Error in getting PPS timestamp" << endl; + if (!gotPPSCounter) + cout << "Error in getting PPS counter" << endl; + if (gotPPSTimestamp && gotPPSCounter) + FillPPSTimestamp(); + } + + if (LoadLAPPDDataTimeStamp && !LoadingPPS) + { + bool newDataEvent; + m_data->CStore.Get("LAPPD_new_event", newDataEvent); + if (newDataEvent) + FillLAPPDDataTimeStamp(); + m_data->CStore.Set("LAPPD_new_event", true); + } + + if (LoadPulse && LAPPDana) + { + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::Execute() LoadPulse" << endl; + bool gotPulse = m_data->Stores["ANNIEEvent"]->Get(treeMakerInputPulseLabel, lappdPulses); + if (!gotPulse) + cout << "Error in getting LAPPD pulses" << endl; + if (gotPulse) + FillPulseTree(); + } + + if (LoadHit && LAPPDana) + { + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::Execute() LoadHit" << endl; + bool gotHit = m_data->Stores["ANNIEEvent"]->Get(treeMakerInputHitLabel, lappdHits); + if (!gotHit) + cout << "Error in getting LAPPD hits" << endl; + if (gotHit) + FillHitTree(); + } + + if (LoadWaveform && LAPPDana) + { + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::Execute() LoadWaveform" << endl; + bool gotWaveformMax = m_data->Stores["ANNIEEvent"]->Get("waveformMax", waveformMax); + if (!gotWaveformMax) + cout << "Error in getting waveform max" << endl; + bool gotWaveformRMS = m_data->Stores["ANNIEEvent"]->Get("waveformRMS", waveformRMS); + if (!gotWaveformRMS) + cout << "Error in getting waveform RMS" << endl; + bool gotWaveformMaxLast = m_data->Stores["ANNIEEvent"]->Get("waveformMaxLast", waveformMaxLast); + if (!gotWaveformMaxLast) + cout << "Error in getting waveform max last" << endl; + bool gotWaveformMaxNearing = m_data->Stores["ANNIEEvent"]->Get("waveformMaxNearing", waveformMaxNearing); + if (!gotWaveformMaxNearing) + cout << "Error in getting waveform max nearing" << endl; + bool gotWaveformMaxTimeBin = m_data->Stores["ANNIEEvent"]->Get("waveformMaxTimeBin", waveformMaxTimeBin); + if (!gotWaveformMaxTimeBin) + cout << "Error in getting waveform max time bin" << endl; + + if (gotWaveformMax && gotWaveformRMS && gotWaveformMaxLast && gotWaveformMaxNearing && gotWaveformMaxTimeBin) + FillWaveformTree(); + } + + if (LAPPDana) + EventNumber++; + + if (TriggerWordMap != nullptr) + TriggerWordMap->clear(); + + return true; +} + +bool LAPPDTreeMaker::Finalise() +{ + file->cd(); + fPulse->Write(); + fHit->Write(); + fWaveform->Write(); + fTimeStamp->Write(); + fTrigger->Write(); + fGroupedTrigger->Write(); + file->Close(); + return true; +} + +void LAPPDTreeMaker::CleanVariables() +{ + LAPPDana = false; + + RunNumber = -9999; + SubRunNumber = -9999; + PartFileNumber = -9999; + + lappdPulses.clear(); + lappdHits.clear(); + lappdData.clear(); + waveformMax.clear(); + waveformRMS.clear(); + waveformMaxLast.clear(); + waveformMaxNearing.clear(); + waveformMaxTimeBin.clear(); + pps_vector.clear(); + pps_count_vector.clear(); + + LAPPD_ID = -9999; + ChannelID = -9999; + PeakTime = -9999; + Charge = -9999; + PeakAmp = -9999; + PulseStart = -9999; + PulseEnd = -9999; + PulseSize = -9999; + PulseSide = -9999; + PulseThreshold = -9999; + PulseBaseline = -9999; + + HitTime = -9999; + HitAmp = -9999; + XPosTank = -9999; + YPosTank = -9999; + ZPosTank = -9999; + ParallelPos = -9999; + TransversePos = -9999; + Pulse1StartTime = -9999; + Pulse2StartTime = -9999; + Pulse1LastTime = -9999; + Pulse2LastTime = -9999; + + LAPPDDataTimeStampUL = 0; + LAPPDDataBeamgateUL = 0; + LAPPDDataTimestampPart1 = 0; + LAPPDDataBeamgatePart1 = 0; + LAPPDDataTimestampPart2 = -9999; + LAPPDDataBeamgatePart2 = -9999; + + ppsDiff = -9999; + ppsCount0 = 0; + ppsCount1 = 0; + ppsTime0 = 0; + ppsTime1 = 0; + + CTCTimeStamp = 0; + CTCTriggerWord.clear(); + trigNumInThisMap = -9999; + trigIndexInThisMap = 0; + + groupedTriggerWordsVector.clear(); + groupedTriggerTimestampsVector.clear(); + groupedTriggerWords.clear(); + groupedTriggerTimestamps.clear(); + groupedTriggerByType.clear(); + groupedTriggerType = -9999; + TriggerGroupNumInThisEvent = 0; // start from 0 + groupedTriggerType = -9999; +} + +bool LAPPDTreeMaker::LoadRunInfoFromRaw() +{ + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::LoadRunInfoFromRaw" << endl; + m_data->CStore.Get("runNumber", RunNumber); + m_data->CStore.Get("rawFileNumber", PartFileNumber); + m_data->CStore.Get("subrunNumber", SubRunNumber); + return true; +} + +bool LAPPDTreeMaker::LoadRunInfoFromANNIEEvent() +{ + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::LoadRunInfoFromANNIEEvent" << endl; + m_data->Stores["ANNIEEvent"]->Header->Get("RunNumber", RunNumber); + m_data->Stores["ANNIEEvent"]->Header->Get("SubRunNumber", SubRunNumber); + m_data->Stores["ANNIEEvent"]->Header->Get("PartFileNumber", PartFileNumber); + if (treeMakerVerbosity > 0) + cout << "RunNumber: " << RunNumber << ", SubRunNumber: " << SubRunNumber << ", PartFileNumber: " << PartFileNumber << endl; + return true; +} + +bool LAPPDTreeMaker::FillPulseTree() +{ + // LAPPDPulse thisPulse(LAPPD_ID, channel, peakBin*(25./256.), Q, peakAmp, pulseStart, pulseStart+pulseSize); + std::map>>::iterator it; + int foundPulseNum = 0; + if (lappdPulses.size() == 0) + { + if (treeMakerVerbosity > 0) + cout << "No pulses found" << endl; + return true; + } + for (it = lappdPulses.begin(); it != lappdPulses.end(); it++) + { + int stripno = it->first; + vector> stripPulses = it->second; + vector pulse0 = stripPulses.at(0); + vector pulse1 = stripPulses.at(1); + for (int i = 0; i < pulse0.size(); i++) + { + PulseSide = 0; + LAPPDPulse thisPulse = pulse0.at(i); + LAPPD_ID = thisPulse.GetTubeId(); + ChannelID = thisPulse.GetChannelID(); + StripNumber = stripno; + PeakTime = thisPulse.GetTime(); + Charge = thisPulse.GetCharge(); + PeakAmp = thisPulse.GetPeak(); + PulseStart = thisPulse.GetLowRange(); + PulseEnd = thisPulse.GetHiRange(); + PulseSize = PulseEnd - PulseStart; + // TODO save threshold and baseline + fPulse->Fill(); + foundPulseNum++; + } + for (int i = 0; i < pulse1.size(); i++) + { + PulseSide = 1; + LAPPDPulse thisPulse = pulse1.at(i); + LAPPD_ID = thisPulse.GetTubeId(); + ChannelID = thisPulse.GetChannelID(); + StripNumber = stripno; + PeakTime = thisPulse.GetTime(); + Charge = thisPulse.GetCharge(); + PeakAmp = thisPulse.GetPeak(); + PulseStart = thisPulse.GetLowRange(); + PulseEnd = thisPulse.GetHiRange(); + PulseSize = PulseEnd - PulseStart; + // TODO save threshold and baseline + fPulse->Fill(); + foundPulseNum++; + } + } + if (treeMakerVerbosity > 0) + cout << "Found and saved " << foundPulseNum << " pulses" << endl; + return true; +} + +bool LAPPDTreeMaker::FillHitTree() +{ + // LAPPDHit hit(tubeID, averageTimeLow, averageAmp, positionInTank, positionOnLAPPD, pulse1LastTime, pulse2LastTime, pulse1StartTime, pulse2StartTime); + int foundHitNum = 0; + if (lappdHits.size() == 0) + { + if (treeMakerVerbosity > 0) + cout << "No hits found" << endl; + return true; + } + std::map>::iterator it; + for (it = lappdHits.begin(); it != lappdHits.end(); it++) + { + int stripno = it->first; + vector stripHits = it->second; + for (int i = 0; i < stripHits.size(); i++) + { + LAPPDHit thisHit = stripHits.at(i); + LAPPD_ID = thisHit.GetTubeId(); + StripNumber = stripno; + HitTime = thisHit.GetTime(); + HitAmp = thisHit.GetCharge(); + vector position = thisHit.GetPosition(); + XPosTank = position.at(0); + YPosTank = position.at(1); + ZPosTank = position.at(2); + vector localPosition = thisHit.GetLocalPosition(); + ParallelPos = localPosition.at(0); + TransversePos = localPosition.at(1); + Pulse1StartTime = thisHit.GetPulse1StartTime(); + Pulse2StartTime = thisHit.GetPulse2StartTime(); + Pulse1LastTime = thisHit.GetPulse1LastTime(); + Pulse2LastTime = thisHit.GetPulse2LastTime(); + fHit->Fill(); + foundHitNum++; + } + } + if (treeMakerVerbosity > 0) + cout << "Found and saved " << foundHitNum << " hits" << endl; + return true; +} + +bool LAPPDTreeMaker::FillWaveformTree() +{ + if (waveformMax.size() == 0) + { + if (treeMakerVerbosity > 0) + cout << "No waveforms found" << endl; + return true; + } + std::map>::iterator it; + for (it = waveformMax.begin(); it != waveformMax.end(); it++) + { + StripNumber = it->first; + for (int side = 0; side < 2; side++) + { + PulseSide = side; + LAPPD_ID = 0; + waveformMaxValue = waveformMax.at(StripNumber).at(side); + waveformRMSValue = waveformRMS.at(StripNumber).at(side); + waveformMaxFoundNear = waveformMaxLast.at(StripNumber).at(side); + waveformMaxNearingValue = waveformMaxNearing.at(StripNumber).at(side); + waveformMaxTimeBinValue = waveformMaxTimeBin.at(StripNumber).at(side); + fWaveform->Fill(); + } + } + if (treeMakerVerbosity > 0) + cout << "Found and saved " << waveformMax.size() << " waveforms" << endl; + return true; +} + +bool LAPPDTreeMaker::FillPPSTimestamp() +{ + ppsTime0 = pps_vector.at(0); + ppsTime1 = pps_vector.at(1); + ppsCount0 = pps_count_vector.at(0); + ppsCount1 = pps_count_vector.at(1); + ppsDiff = ppsTime1 - ppsTime0; + m_data->CStore.Get("LAPPD_ID", LAPPD_ID); + if (treeMakerVerbosity > 0) + cout << "LAPPD_ID: " << LAPPD_ID << ", ppsDiff: " << ppsDiff << ", ppsTime0: " << ppsTime0 << ", ppsTime1: " << ppsTime1 << ", ppsCount0: " << ppsCount0 << ", ppsCount1: " << ppsCount1 << endl; + fTimeStamp->Fill(); + return true; +} + +bool LAPPDTreeMaker::FillLAPPDDataTimeStamp() +{ + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::FillLAPPDDataTimeStamp. Before fill: LAPPDDataTimeStampUL: " << LAPPDDataTimeStampUL << ", LAPPDDataBeamgateUL: " << LAPPDDataBeamgateUL << ", LAPPDDataTimestampPart1: " << LAPPDDataTimestampPart1 << ", LAPPDDataBeamgatePart1: " << LAPPDDataBeamgatePart1 << ", LAPPDDataTimestampPart2: " << LAPPDDataTimestampPart2 << ", LAPPDDataBeamgatePart2: " << LAPPDDataBeamgatePart2 << endl; + m_data->CStore.Get("LAPPDBeamgate_Raw", LAPPDDataBeamgateUL); + m_data->CStore.Get("LAPPDTimestamp_Raw", LAPPDDataTimeStampUL); + m_data->CStore.Get("LAPPDBGIntCombined", LAPPDDataBeamgatePart1); + m_data->CStore.Get("LAPPDBGFloat", LAPPDDataBeamgatePart2); + m_data->CStore.Get("LAPPDTSIntCombined", LAPPDDataTimestampPart1); + m_data->CStore.Get("LAPPDTSFloat", LAPPDDataTimestampPart2); + m_data->CStore.Get("LAPPD_ID", LAPPD_ID); + fTimeStamp->Fill(); + if (treeMakerVerbosity > 0) + cout << "LAPPDDataTimeStampUL: " << LAPPDDataTimeStampUL << ", LAPPDDataBeamgateUL: " << LAPPDDataBeamgateUL << ", LAPPDDataTimestampPart1: " << LAPPDDataTimestampPart1 << ", LAPPDDataBeamgatePart1: " << LAPPDDataBeamgatePart1 << ", LAPPDDataTimestampPart2: " << LAPPDDataTimestampPart2 << ", LAPPDDataBeamgatePart2: " << LAPPDDataBeamgatePart2 << endl; + return true; +} + +bool LAPPDTreeMaker::FillTriggerTree() +{ + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::FillTriggerTree" << endl; + + trigNumInThisMap = TriggerWordMap->size(); + for (const auto &item : *TriggerWordMap) + { + CTCTimeStamp = item.first; + CTCTriggerWord = item.second; + fTrigger->Fill(); + trigIndexInThisMap++; + } + if (treeMakerVerbosity > 0) + cout << "FillTriggerTree: " << trigNumInThisMap << " triggers filled" << endl; + + return true; +} + +bool LAPPDTreeMaker::FillGroupedTriggerTree() +{ + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::FillGroupedTriggerTree" << endl; + + // fill new triggers from the map to ungrouped trigger buffer + for (const auto &item : *TriggerWordMap) + { + CTCTimeStamp = item.first; + CTCTriggerWord = item.second; + + for (const auto &trigw : CTCTriggerWord) + { + unGroupedTriggerTimestamps.push_back(CTCTimeStamp); + unGroupedTriggerWords.push_back(trigw); + } + } + + if (LoadGroupOption == "beam") + GroupTriggerByBeam(); + else if (LoadGroupOption == "laser") + GroupTriggerByLaser(); + + GroupPPSTrigger(); + + for (int i = 0; i < groupedTriggerWordsVector.size(); i++) + { + groupedTriggerWords = groupedTriggerWordsVector.at(i); + groupedTriggerTimestamps = groupedTriggerTimestampsVector.at(i); + groupedTriggerType = groupedTriggerByType.at(i); + fGroupedTrigger->Fill(); + TriggerGroupNumInThisEvent += 1; + } + + CleanTriggers(); + + return true; +} + +bool LAPPDTreeMaker::GroupTriggerByBeam() +{ + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::GroupTriggerByBeam" << endl; + + vector removeIndex; + bool beamNow = false; + bool trigger2ed = false; + bool trigger14ed = false; + bool trigger1ed = false; + int beamConfirm = 0; + vector thisTGroup; + vector thisTTimestamp; + bool ppsNow = false; + + for (int i = 0; i < unGroupedTriggerWords.size(); i++) + { + uint32_t tWord = unGroupedTriggerWords.at(i); + unsigned long tTime = unGroupedTriggerTimestamps.at(i); + bool pushedToBuffer = false; + if (!beamNow) + { + // not in a beam group + if (tWord == 3) + { + beamNow = true; + beamConfirm = 0; + thisTGroup.push_back(tWord); + thisTTimestamp.push_back(tTime); + pushedToBuffer = true; + trigger2ed = false; + trigger14ed = false; + trigger1ed = false; + } + } + else + { // while in a group + if (beamConfirm <= 2 && tWord == 3) + { + // in grouping mode, meet a new start, but haven't got enough trigger 14 and 2 + // clear buffer, restart the grouping from this t 3 + thisTGroup.clear(); + thisTTimestamp.clear(); + beamNow = true; + thisTGroup.push_back(tWord); + thisTTimestamp.push_back(tTime); + pushedToBuffer = true; + trigger2ed = false; + trigger14ed = false; + trigger1ed = false; + } + + if (beamConfirm > 2 && tWord == 10) + { + // if beam confirmed and meet a trigger 10, save the grouped triggers + // 10 always come with 8, which is delayed trigger to MRD + thisTGroup.push_back(tWord); + thisTTimestamp.push_back(tTime); + pushedToBuffer = true; + // if found trigger 14 and 2, save the grouped triggers + if ((std::find(thisTGroup.begin(), thisTGroup.end(), 14) != thisTGroup.end()) && (std::find(thisTGroup.begin(), thisTGroup.end(), 2) != thisTGroup.end())) + { + groupedTriggerWordsVector.push_back(thisTGroup); + groupedTriggerTimestampsVector.push_back(thisTTimestamp); + groupedTriggerByType.push_back(14); + } + thisTGroup.clear(); + thisTTimestamp.clear(); + beamNow = false; + trigger14ed = false; + trigger2ed = false; + trigger1ed = false; + beamConfirm = 0; + } + + if (!pushedToBuffer && tWord != 32 && tWord != 34 && tWord != 36) + { + if (tWord == 2) + { + trigger2ed = true; + beamConfirm++; + } + + if (tWord != 14) + { + thisTGroup.push_back(tWord); + thisTTimestamp.push_back(tTime); + } + else if (!trigger14ed) + { + thisTGroup.push_back(tWord); + thisTTimestamp.push_back(tTime); + trigger14ed = true; + beamConfirm++; + } + pushedToBuffer = true; + } + } + + if (pushedToBuffer) + { + removeIndex.push_back(i); + } + } + + vector unRemovedTriggerWords; + vector unRemovedTriggerTimestamps; + for (int i = 0; i < unGroupedTriggerWords.size(); i++) + { + if (std::find(removeIndex.begin(), removeIndex.end(), i) == removeIndex.end()) + { + unRemovedTriggerWords.push_back(unGroupedTriggerWords.at(i)); + unRemovedTriggerTimestamps.push_back(unGroupedTriggerTimestamps.at(i)); + } + } + unGroupedTriggerTimestamps = unRemovedTriggerTimestamps; + unGroupedTriggerWords = unRemovedTriggerWords; + + return true; +} + +bool LAPPDTreeMaker::GroupPPSTrigger() +{ + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::GroupPPSTrigger" << endl; + + vector removeIndex; + vector thisTGroup; + vector thisTTimestamp; + bool ppsNow = false; + for (int i = 0; i < unGroupedTriggerWords.size(); i++) + { + uint32_t tWord = unGroupedTriggerWords.at(i); + unsigned long tTime = unGroupedTriggerTimestamps.at(i); + bool pushedToBuffer = false; + if (!ppsNow) + { + if (tWord == 32) + { + ppsNow = true; + thisTGroup.push_back(tWord); + thisTTimestamp.push_back(tTime); + pushedToBuffer = true; + } + } + else + { + if (tWord == 34) + { + thisTGroup.push_back(tWord); + thisTTimestamp.push_back(tTime); + pushedToBuffer = true; + groupedTriggerWordsVector.push_back(thisTGroup); + groupedTriggerTimestampsVector.push_back(thisTTimestamp); + groupedTriggerByType.push_back(32); + thisTGroup.clear(); + thisTTimestamp.clear(); + ppsNow = false; + } + } + + if (pushedToBuffer) + { + removeIndex.push_back(i); + } + } + + vector unRemovedTriggerWords; + vector unRemovedTriggerTimestamps; + for (int i = 0; i < unGroupedTriggerWords.size(); i++) + { + if (std::find(removeIndex.begin(), removeIndex.end(), i) == removeIndex.end()) + { + unRemovedTriggerWords.push_back(unGroupedTriggerWords.at(i)); + unRemovedTriggerTimestamps.push_back(unGroupedTriggerTimestamps.at(i)); + } + } + unGroupedTriggerTimestamps = unRemovedTriggerTimestamps; + unGroupedTriggerWords = unRemovedTriggerWords; + return true; +} + +bool LAPPDTreeMaker::GroupTriggerByLaser() +{ + // waiting for implementation + return true; +} + +void LAPPDTreeMaker::CleanTriggers() +{ + // only keep the last 1000 triggers + // create new vector to store the last 1000 triggers + if (unGroupedTriggerWords.size() > 1000) + { + std::vector lastTrigWords(unGroupedTriggerWords.end() - 1000, unGroupedTriggerWords.end()); + unGroupedTriggerWords = lastTrigWords; + std::vector lastTrigTimestamps(unGroupedTriggerTimestamps.end() - 1000, unGroupedTriggerTimestamps.end()); + unGroupedTriggerTimestamps = lastTrigTimestamps; + } +} \ No newline at end of file diff --git a/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h b/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h new file mode 100644 index 000000000..c95e69c86 --- /dev/null +++ b/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h @@ -0,0 +1,155 @@ +#ifndef LAPPDTreeMaker_H +#define LAPPDTreeMaker_H + +#include +#include + +#include "Tool.h" +#include "TTree.h" +#include "TFile.h" +#include "TString.h" +#include "LAPPDPulse.h" +#include "LAPPDHit.h" +#include "Geometry.h" +#include "Position.h" + +/** + * \class LAPPDTreeMaker + * + * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. + * + * $Author: Yue Feng $ + * $Date: 2024/02/03 16:10:00 $ + * Contact: yuef@iastate.edu + */ +class LAPPDTreeMaker : public Tool +{ + +public: + LAPPDTreeMaker(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + void CleanVariables(); + bool FillPulseTree(); + bool FillHitTree(); + bool FillWaveformTree(); + bool FillPPSTimestamp(); + bool FillLAPPDDataTimeStamp(); + bool LoadRunInfoFromRaw(); + bool LoadRunInfoFromANNIEEvent(); + bool GroupTriggerByBeam(); + bool GroupTriggerByLaser(); + bool GroupPPSTrigger(); + bool FillTriggerTree(); + bool FillGroupedTriggerTree(); + void CleanTriggers(); + +private: + TFile *file; + TTree *fPulse; + TTree *fHit; + TTree *fWaveform; + TTree *fTimeStamp; + TTree *fTrigger; + TTree *fGroupedTrigger; + + int treeMakerVerbosity; + bool LAPPDana; + bool LoadingPPS; + + bool LoadPulse; + bool LoadHit; + bool LoadWaveform; + bool LoadLAPPDDataTimeStamp; + bool LoadPPSTimestamp; + bool LoadRunInfoRaw; + bool LoadRunInfoANNIEEvent; + bool LoadTriggerInfo; + bool LoadGroupedTriggerInfo; + string LoadGroupOption; // using beam, or laser, or other. + + std::map>> lappdData; + std::map> waveformMax; // strip number+30*side, value + std::map> waveformRMS; + std::map> waveformMaxLast; + std::map> waveformMaxNearing; + std::map> waveformMaxTimeBin; + + map> *TriggerWordMap; + unsigned long CTCTimeStamp; + std::vector CTCTriggerWord; + int trigNumInThisMap; + int trigIndexInThisMap; + int TriggerGroupNumInThisEvent; + int groupedTriggerType; + + vector unGroupedTriggerWords; + vector unGroupedTriggerTimestamps; + vector> groupedTriggerWordsVector; + vector> groupedTriggerTimestampsVector; + vector groupedTriggerByType; + vector groupedTriggerWords; + vector groupedTriggerTimestamps; + + double waveformMaxValue; + double waveformRMSValue; + bool waveformMaxFoundNear; + double waveformMaxNearingValue; + int waveformMaxTimeBinValue; + + std::map>> lappdPulses; + std::map> lappdHits; + Geometry *_geom; + string treeMakerInputPulseLabel; + string treeMakerInputHitLabel; + string treeMakerOutputFileName; + + int EventNumber; // this is for LAPPD relate event number, data or PPS, not trigger!! + int StripNumber; + + int LAPPD_ID; + int ChannelID; + double PeakTime; + double Charge; + double PeakAmp; + double PulseStart; + double PulseEnd; + double PulseSize; + int PulseSide; + double PulseThreshold; + double PulseBaseline; + + double HitTime; + double HitAmp; + double XPosTank; + double YPosTank; + double ZPosTank; + double ParallelPos; + double TransversePos; + double Pulse1StartTime; + double Pulse2StartTime; + double Pulse1LastTime; + double Pulse2LastTime; + + unsigned long LAPPDDataTimeStampUL; + unsigned long LAPPDDataBeamgateUL; + unsigned long LAPPDDataTimestampPart1; + unsigned long LAPPDDataBeamgatePart1; + double LAPPDDataTimestampPart2; + double LAPPDDataBeamgatePart2; + + vector pps_vector; + vector pps_count_vector; + Long64_t ppsDiff; + unsigned long ppsCount0; + unsigned long ppsCount1; + unsigned long ppsTime0; // in clock tick, without 3.125ns + unsigned long ppsTime1; // in clock tick, without 3.125ns + + int RunNumber; + int SubRunNumber; + int PartFileNumber; +}; + +#endif diff --git a/UserTools/LAPPDTreeMaker/README.md b/UserTools/LAPPDTreeMaker/README.md new file mode 100644 index 000000000..23363ae82 --- /dev/null +++ b/UserTools/LAPPDTreeMaker/README.md @@ -0,0 +1,20 @@ +# LAPPDTreeMaker + +LAPPDTreeMaker + +## Data + +Describe any data formats LAPPDTreeMaker creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for LAPPDTreeMaker. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp b/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp index 56dae396a..e6a08cf0a 100644 --- a/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp +++ b/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp @@ -63,7 +63,7 @@ bool TriggerDataDecoder::Execute(){ m_data->CStore.Set("NewCTCDataAvailable",false); bool PauseCTCDecoding = false; m_data->CStore.Get("PauseCTCDecoding",PauseCTCDecoding); - if (PauseCTCDecoding){ + if (PauseCTCDecoding && verbosity > 0){ std::cout << "TriggerDataDecoder tool: Pausing trigger decoding to let Tank and MRD data catch up..." << std::endl; return true; } @@ -98,7 +98,7 @@ bool TriggerDataDecoder::Execute(){ } bool new_ts_available = false; std::vector aTimeStampData = Tdata->TimeStampData; - std::cout <<"aTimeStampData.size(): "<0) std::cout <<"aTimeStampData.size(): "<v_debug) std::cout<<"TriggerDataDecoder Tool: Loading next TrigData from entry's index " << i <AddWord(aTimeStampData.at(i)); diff --git a/UserTools/Unity.h b/UserTools/Unity.h index 9e00352b5..636f2bf14 100644 --- a/UserTools/Unity.h +++ b/UserTools/Unity.h @@ -175,3 +175,10 @@ #include "PlotsTrackLengthAndEnergy.h" #include "SaveConfigInfo.h" #include "ReadConfigInfo.h" +#include "LAPPDLoadStore.h" +#include "LAPPDTreeMaker.h" +#include "LAPPDPlots.h" +#include "LAPPDThresReco.h" +#include "LAPPDTimeAlignment.h" +#include "LAPPDBaseline.h" +#include "LAPPDStoreReorder.h" From 4ae243d2c8195640d4ce1c91e87d7796b4ccad8e Mon Sep 17 00:00:00 2001 From: Yue Date: Mon, 22 Apr 2024 23:52:43 -0500 Subject: [PATCH 030/163] Add LAPPD_EB tool chain for generating timestamp tree. Add LAPPDRaw tool for generating lappd analysis tree --- UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp | 9 +- UserTools/LoadRawData/LoadRawData.cpp | 135 ++++++++++++++---- UserTools/LoadRawData/LoadRawData.h | 1 + configfiles/LAPPDRaw/ConfigGeo | 11 ++ configfiles/LAPPDRaw/ConfigPlot | 129 +++++++++++++++++ configfiles/LAPPDRaw/ConfigPreProcess | 65 +++++++++ configfiles/LAPPDRaw/ConfigStoreReadIn | 43 ++++++ configfiles/LAPPDRaw/Configs | 69 +++++++++ configfiles/LAPPDRaw/DefaultTriggerMask.txt | 7 + configfiles/LAPPDRaw/LoadRawDataConfig | 12 ++ configfiles/LAPPDRaw/ToolChainConfig | 24 ++++ configfiles/LAPPDRaw/ToolsConfig | 18 +++ configfiles/LAPPDRaw/TriggerDataDecoderConfig | 4 + configfiles/LAPPDRaw/list.txt | 3 + configfiles/LAPPD_EB/ConfigGeo | 11 ++ configfiles/LAPPD_EB/Configs | 56 ++++++++ configfiles/LAPPD_EB/LoadRawDataConfig | 12 ++ configfiles/LAPPD_EB/ToolChainConfig | 24 ++++ configfiles/LAPPD_EB/ToolsConfig | 11 ++ configfiles/LAPPD_EB/TriggerDataDecoderConfig | 4 + configfiles/LAPPD_EB/list.txt | 8 ++ 21 files changed, 622 insertions(+), 34 deletions(-) create mode 100644 configfiles/LAPPDRaw/ConfigGeo create mode 100755 configfiles/LAPPDRaw/ConfigPlot create mode 100755 configfiles/LAPPDRaw/ConfigPreProcess create mode 100755 configfiles/LAPPDRaw/ConfigStoreReadIn create mode 100644 configfiles/LAPPDRaw/Configs create mode 100644 configfiles/LAPPDRaw/DefaultTriggerMask.txt create mode 100644 configfiles/LAPPDRaw/LoadRawDataConfig create mode 100644 configfiles/LAPPDRaw/ToolChainConfig create mode 100644 configfiles/LAPPDRaw/ToolsConfig create mode 100644 configfiles/LAPPDRaw/TriggerDataDecoderConfig create mode 100644 configfiles/LAPPDRaw/list.txt create mode 100644 configfiles/LAPPD_EB/ConfigGeo create mode 100644 configfiles/LAPPD_EB/Configs create mode 100644 configfiles/LAPPD_EB/LoadRawDataConfig create mode 100644 configfiles/LAPPD_EB/ToolChainConfig create mode 100644 configfiles/LAPPD_EB/ToolsConfig create mode 100644 configfiles/LAPPD_EB/TriggerDataDecoderConfig create mode 100644 configfiles/LAPPD_EB/list.txt diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp index 76794db28..779a106d2 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp @@ -133,7 +133,7 @@ bool LAPPDLoadStore::Initialise(std::string configfile, DataModel &data) if (loadOffsets) LoadOffsetsAndCorrections(); - debugStoreReadIn.open("debugStoreReadIn.txt"); + if(LAPPDStoreReadInVerbosity>11) debugStoreReadIn.open("debugStoreReadIn.txt"); return true; } @@ -171,6 +171,7 @@ bool LAPPDLoadStore::Execute() // decide loading data or not, set to LAPPDana for later tools LAPPDana = LoadData(); m_data->CStore.Set("LAPPDana", LAPPDana); + if(LAPPDStoreReadInVerbosity>0) cout<<"LAPPDana for loading was set to "<Stores["ANNIEEvent"]->Set("TriggerChannelBase", TrigChannel); m_data->CStore.Set("NewLAPPDDataAvailable",true); - debugStoreReadIn<< " Set NewLAPPDDataAvailable to true"<11) debugStoreReadIn<< " Set NewLAPPDDataAvailable to true"<Stores["ANNIEEvent"]->Set("LAPPDBeamgate_Raw", beamgate_63_0); m_data->Stores["ANNIEEvent"]->Set("LAPPDTimestamp_Raw", timestamp_63_0); -debugStoreReadIn<11) debugStoreReadIn<11) debugStoreReadIn<CStore.Set("FileProcessingComplete",false); @@ -78,7 +78,7 @@ bool LoadRawData::Execute(){ //Check if we've reached the end of our file list or single file bool ProcessingComplete = false; if(FileCompleted) ProcessingComplete = this->InitializeNewFile(); - if(ProcessingComplete) { + if(BuildType != "LAPPDMerging" && ProcessingComplete) { Log("LoadRawData Tool: All files have been processed.",v_message,verbosity); m_data->CStore.Set("FileProcessingComplete",true); return true; @@ -113,6 +113,9 @@ bool LoadRawData::Execute(){ std::cout << "LoadRawData tool ERROR: no files in file list to parse! Stopping toolchain" << std::endl; m_data->vars.Set("StopLoop",1); return false; + if(BuildType == "LAPPDMerging" && FileCompleted){ + return true; + } } if(FileCompleted || CurrentFile=="NONE"){ Log("LoadRawData tool: Moving to next file.",v_message,verbosity); @@ -127,10 +130,63 @@ bool LoadRawData::Execute(){ this->LoadPMTMRDData(); this->LoadTriggerData(); this->LoadLAPPDData(); + + { + // extract run number and file number from filename + std::regex runNumber_regex("RAWDataR(\\d{4})"); + std::regex subrunNUmber_regex("S(\\d{1,4})p"); + std::regex rawFileNumber_regex("p(\\d{1,4})"); + std::smatch match; + if (std::regex_search(CurrentFile, match, runNumber_regex) && match.size() > 1) + { + int runNumber = std::stoi(match.str(1)); + if(verbosity > 0) std::cout << "runNumber: " << runNumber << std::endl; + m_data->CStore.Set("runNumber", runNumber); + } + else + { + std::cout << "runNumber not found" << std::endl; + m_data->CStore.Set("rawFileNumber", -9999); + } + + if (std::regex_search(CurrentFile, match, subrunNUmber_regex) && match.size() > 1) + { + int subrunNumber = std::stoi(match.str(1)); + if(verbosity > 0) std::cout << "subrunNumber: " << subrunNumber << std::endl; + m_data->CStore.Set("subrunNumber", subrunNumber); + } + else + { + std::cout << "subrunNumber not found" << std::endl; + m_data->CStore.Set("subrunNumber", -9999); + } + + if (std::regex_search(CurrentFile, match, rawFileNumber_regex) && match.size() > 1) + { + int rawFileNumber = std::stoi(match.str(1)); + if(verbosity > 0) std::cout << "rawFileNumber: " << rawFileNumber << std::endl; + m_data->CStore.Set("rawFileNumber", rawFileNumber); + } + else + { + std::cout << "rawFileNumber not found" << std::endl; + m_data->CStore.Set("runNumber", -9999); + } + } + } else { if(verbosity>v_message) std::cout << "LoadRawDataTool: continuing file " << OrganizedFileList.at(FileNum) << std::endl; } FileCompleted = false; + if (JumpBecauseLAPPD){ + //something the LAPPD data in raw data file may have a very large entry number seems like because of overflow + //then the whole loader will be stuck in the loop, so we need to jump to the next file + //only set while loading with LAPPD, won't affect others + FileCompleted = true; + JumpBecauseLAPPD = false; + cout<<"LoadRawData: Jumping to next file because there is something wrong about LAPPD data"<CStore.Set("PauseTankDecoding",TankPaused); @@ -281,6 +336,10 @@ bool LoadRawData::Execute(){ //Set if the raw data file has been completed if (TankEntriesCompleted && BuildType == "Tank") FileCompleted = true; if (MRDEntriesCompleted && BuildType == "MRD") FileCompleted = true; + if (LAPPDEntriesCompleted && BuildType == "LAPPD") FileCompleted = true; + if ((LAPPDEntriesCompleted && TrigEntriesCompleted) && (BuildType == "LAPPDAndCTC" || BuildType == "CTCAndLAPPD")) FileCompleted = true; + if (lappdtotalentries == 0 && (BuildType == "LAPPD" || BuildType == "LAPPDMerging" || BuildType == "LAPPDAndCTC" || BuildType == "CTCAndLAPPD")) FileCompleted = true; + if (LAPPDEntriesCompleted && BuildType == "LAPPDMerging") FileCompleted = true; if ((TankEntriesCompleted && MRDEntriesCompleted) && (BuildType == "TankAndMRD")) FileCompleted = true; if ((TrigEntriesCompleted && TankEntriesCompleted) && (BuildType == "TankAndCTC")) FileCompleted = true; if ((TrigEntriesCompleted && MRDEntriesCompleted) && (BuildType == "MRDAndCTC")) FileCompleted = true; @@ -396,12 +455,28 @@ void LoadRawData::LoadTriggerData(){ void LoadRawData::LoadLAPPDData(){ Log("LoadRawData Tool: Accessing LAPPD Data in raw data",v_message,verbosity); - if((BuildType == "TankAndMRDAndCTCAndLAPPD")){ + if(BuildType == "TankAndMRDAndCTCAndLAPPD" || BuildType == "LAPPD" || BuildType == "LAPPDMerging" || BuildType == "LAPPDAndCTC" || BuildType == "CTCAndLAPPD"){ Log("LoadRawData Tool: Accessing LAPPD Data in raw data",v_message,verbosity); try{ RawData->Get("LAPPDData",*LAPPDData); LAPPDData->Header->Get("TotalEntries",lappdtotalentries); - if(verbosity>3) LAPPDData->Print(false); + if(verbosity>3) { + Log("LoadRawData Tool: LAPPDData printing",v_message,verbosity); + LAPPDData->Print(false); + Log("LoadRawData Tool: LAPPDData Header printing",v_message,verbosity); + LAPPDData->Header->Print(false); + } + if(lappdtotalentries < 0){ //some time the lappd broken data can give negative value + lappdtotalentries = 0; + LAPPDEntriesCompleted = true; + }else{ + Log("LoadRawData Tool: in loading, LAPPDData has "+std::to_string(lappdtotalentries)+" entries",v_message,verbosity); + if(lappdtotalentries > 100000){ + Log("LoadRawData Tool: LAPPDData has "+std::to_string(lappdtotalentries)+" entries. This is a large wrong number of entries. May be a corrupted file.",v_warning,verbosity); + JumpBecauseLAPPD = true; //if loading LAPPD data and the LAPPD data in this file was broken, jump to next file + return; + } + } } catch (...) { Log("LoadRawData: Did not find LAPPDData in raw data file! (Maybe corrupted!!!) Don't process LAPPDData",0,0); lappdtotalentries=0; @@ -516,8 +591,16 @@ TrigData->Close(); TrigData->Delete(); delete TrigData; TrigData = new BoostStor EndOfProcessing = true; } if(Mode == "FileList" && FileNum == int(OrganizedFileList.size())){ + //In Merging LAPPD with event building data, loading LAPPD from raw data will be finished before finishing merging + //so set the FileNum == to >=, and minus 1 to not disturb other code relate to FileNum Log("LoadRawData Tool: Full file list parsed. Ending toolchain after this loop.",v_message, verbosity); - m_data->vars.Set("StopLoop",1); + m_data->CStore.Set("LAPPDanaData",false); //while use loading raw data to merge LAPPD data with other data, after reading all LAPPD data, set later LAPPDReadIn to stop. + if(BuildType != "LAPPDMerging"){ + m_data->vars.Set("StopLoop",1); + }else{ + Log("LoadRawData Tool: in LAPPD Merging mode, do not stop tool chain",v_message, verbosity); + FileNum -= 1; + } EndOfProcessing = true; } //No need to stop the loop in continous mode @@ -529,7 +612,7 @@ TrigData->Close(); TrigData->Delete(); delete TrigData; TrigData = new BoostStor } void LoadRawData::GetNextDataEntries(){ - std::cout <<"BuildType: "<0) std::cout <<"BuildType: "<GetEntry(LAPPDEntryNum); - LAPPDData->Get("LAPPDData",*Ldata); - m_data->CStore.Set("LAPPDData",Ldata,true); - LAPPDEntryNum+=1; - } - } - //Get next TrigData Entry - if((BuildType == "TankAndMRDAndCTC" || BuildType == "TankAndCTC" || BuildType == "MRDAndCTC" || BuildType == "CTC" || BuildType == "TankAndMRDAndCTCAndLAPPD") && !TrigEntriesCompleted && !CTCPaused){ + if((BuildType == "TankAndMRDAndCTC" || BuildType == "TankAndCTC" || BuildType == "MRDAndCTC" || BuildType == "CTC" || BuildType == "TankAndMRDAndCTCAndLAPPD" || BuildType == "CTCAndLAPPD" || BuildType == "LAPPDAndCTC") && !TrigEntriesCompleted && !CTCPaused){ Log("LoadRawData Tool: Procesing TrigData Entry "+to_string(TrigEntryNum)+"/"+to_string(trigtotalentries),v_debug, verbosity); if (storetrigoverlap && TrigEntryNum == 0 && extract_part != 0){ TrigData->GetEntry(TrigEntryNum); @@ -613,12 +685,15 @@ void LoadRawData::GetNextDataEntries(){ } //Get next LAPPDData Entry - if(BuildType == "LAPPD" || BuildType == "TankAndLAPPD" || BuildType == "MRDAndLAPPD" || BuildType == "TankAndMRDAndLAPPD" || BuildType == "TankAndMRDAndLAPPDAndCTC"){ - Log("LoadRawData Tool: Processing LAPPDData Entry "+to_string(LAPPDEntryNum)+"/"+to_string(lappdtotalentries),v_debug,verbosity); - LAPPDData->GetEntry(LAPPDEntryNum); - LAPPDData->Get("LAPPDData", *Ldata); - m_data->CStore.Set("LAPPDData", Ldata); - LAPPDEntryNum+=1; + if(BuildType == "LAPPD" || BuildType == "TankAndLAPPD" || BuildType == "MRDAndLAPPD" || BuildType == "TankAndMRDAndLAPPD" || BuildType == "TankAndMRDAndCTCAndLAPPD" || BuildType == "CTCAndLAPPD" || BuildType == "LAPPDMerging" || BuildType == "LAPPDAndCTC" ){ + if(!LAPPDPaused && !LAPPDEntriesCompleted){ + Log("LoadRawData Tool: Processing LAPPDData Entry "+to_string(LAPPDEntryNum)+"/"+to_string(lappdtotalentries),v_debug,verbosity); + LAPPDData->GetEntry(LAPPDEntryNum); + LAPPDData->Get("LAPPDData", *Ldata); + m_data->CStore.Set("LAPPDData", Ldata); + m_data->CStore.Set("LAPPDanaData",true); + LAPPDEntryNum+=1; + } } return; } diff --git a/UserTools/LoadRawData/LoadRawData.h b/UserTools/LoadRawData/LoadRawData.h index 95204fed2..54308c5e0 100644 --- a/UserTools/LoadRawData/LoadRawData.h +++ b/UserTools/LoadRawData/LoadRawData.h @@ -63,6 +63,7 @@ class LoadRawData: public Tool { bool TrigEntriesCompleted; bool LAPPDEntriesCompleted; bool FileCompleted; + bool JumpBecauseLAPPD; int TankEntryNum = 0; int MRDEntryNum = 0; int TrigEntryNum = 0; diff --git a/configfiles/LAPPDRaw/ConfigGeo b/configfiles/LAPPDRaw/ConfigGeo new file mode 100644 index 000000000..ffe0ca918 --- /dev/null +++ b/configfiles/LAPPDRaw/ConfigGeo @@ -0,0 +1,11 @@ +#LoadGeometry +verbosity 0 +LAPPDChannelCount 60 +FACCMRDGeoFile ./configfiles/LoadGeometry/FullMRDGeometry.csv +DetectorGeoFile ./configfiles/LoadGeometry/DetectorGeometrySpecs.csv +LAPPDGeoFile ./configfiles/LAPPDana/LAPPDGeometry.csv +TankPMTGeoFile ./configfiles/LoadGeometry/FullTankPMTGeometry.csv +TankPMTGainFile ./configfiles/LoadGeometry/ChannelSPEGains_BeamRun20192020.csv +AuxiliaryChannelFile ./configfiles/LoadGeometry/AuxChannels.csv +LAPPDMerging 0 + diff --git a/configfiles/LAPPDRaw/ConfigPlot b/configfiles/LAPPDRaw/ConfigPlot new file mode 100755 index 000000000..2e1fa034f --- /dev/null +++ b/configfiles/LAPPDRaw/ConfigPlot @@ -0,0 +1,129 @@ +oldLaser 0 #1 for old data, 0 for new trigger boards + +#LAPPDBaselineSubtract +BLSInputWavLabel AlignedLAPPDData +BaselineSubstractVerbosityLevel 0 +TrigChannel 5 #Specified channel the trigger signal will be on +LAPPDchannelOffset 1000 +LowBLfitrange 25; +HiBLfitrange 60; +TrigLowBLfitrange 30 +TrigHiBLfitrange 100 +BLSOutputWavLabel ABLSLAPPDData +oldLaserTrigAmpRange 40 + +#LAPPDFindPeak +FindPeakVerbosity 0 +FiltPeakInputWavLabel FiltLAPPDData +RawPeakInputWavLabel LAPPDWaveforms +BLSPeakInputWavLabel ABLSLAPPDData +FindPeakOutLabel SimpleRecoLAPPDPulses +TotThreshold 15. +MinimumTot 900. +Deltat 100. + +# General Parameters +Nsamples 256 +SampleSize 100 +NChannels 60 + +#LAPPDPlotWaveForms +requireT0signal 0 +SaveByChannel 1 +#PlotWavLabel RawLAPPDData +#PlotWavLabel LAPPDWaveforms +PlotWavLabel BLsubtractedLAPPDData +#PlotWavLabel AlignedLAPPDData +switchBit 0 + +outfile WaveForms_ablsub.root +NHistos 200 +SaveSingleStrip 0 +SingleStripNo 9 +plotLow -10 +plotHigh 20 + +#LAPPDPlotWaveForms2D +outfile2D RawDataWaveForms_2D.root +plot2DrecoPulseInputLabel thresRecoLAPPDPulses +plot2DrecoHitInputLabel thresRecoLAPPDHits +includeRecoPulses 1 +includeRecoHits 1 +plotAdditionalPart 1 +titleSize 0.04 +canvasMargin 0.15 +canvasTitleOffset 1 +#LAPPDSelectPlot2D +LAPPDSelectPlotWaveform2DLabel LAPPDWaveforms +SelectOutfile2D LAPPDSelectPlot.root +MRDTrackExistSelection 0 +verbosityPlot2D 10 +colorContour 255 +useDefaultPalette 1 +colorPalette 112 + + + +#LAPPDThresReco +LAPPDThresRecoVerbosity 0 +verbosity 0 +printHitsTXT 0 +threshold 10 +minPulseWidth 10 +#thresRecoInputWaveLabel AlignedLAPPDData +ThresRecoInputWaveLabel BLsubtractedLAPPDData +#thresRecoInputWaveLabel LAPPDWaveforms + +ThresRecoOutputPulseLabel LAPPDPulses +ThresRecoOutputHitLabel LAPPDHits +useMaxTime 1 +#signalSpeedOnStrip 0.6667 +signalSpeedOnStrip 0.567 #1.69982/2.99792 +triggerBoardDelay 0 +loadPrintMRDinfo 1 +useRange -1 #set this to 0 for using pulse start time as the saved pulse time, 1 for high, -1 for using peak time +plusClockBit 0 + +savePositionOnStrip 1 + + +#LAPPDStackStrip +verbosityStackStrip 0 +StackOutputFileName stacked.root +#StackInputWaveLabel BLsubtractedLAPPDData +StackInputWaveLabel RawLAPPDData +#StackInputWaveLabel LAPPDWaveforms +StackStripNumber 1 +StackStripSide 0 + +#LAPPDPlotWaveForms +NHistos 200 +SaveByChannel 0 +SaveSingleStrip 0 +SingleStripNo 1 +requireT0signal 0 + + +#LAPPDTreeMaker +treeMakerVerbosity 0 +treeMakerInputPulseLabel LAPPDPulses +treeMakerInputHitLabel LAPPDHits +treeMakerOutputFileName LAPPDTree.root + + + +#LAPPDPlots +LAPPDPlotInputWaveLabel BLsubtractedLAPPDData +LAPPDPlotsVerbosity 0 +CanvasXSubPlotNumber 2 +CanvasYSubPlotNumber 2 +canvasMargin 0.1 +drawHighThreshold 50 +drawLowThreshold -20 + +CanvasWidth 1000 +CanvasHeight 500 + +maxDrawEventNumber 50 + +DrawBinHist 1 diff --git a/configfiles/LAPPDRaw/ConfigPreProcess b/configfiles/LAPPDRaw/ConfigPreProcess new file mode 100755 index 000000000..ee2a71e11 --- /dev/null +++ b/configfiles/LAPPDRaw/ConfigPreProcess @@ -0,0 +1,65 @@ +# General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +LAPPDchannelOffset 1000 +Folder ../Data/3655/ +#Folder ../Data/2022-06-10/ + +#LAPPDBaselineSubtract +BaselineSubstractVerbosityLevel 0 +TrigChannel1 1005 +TrigChannel2 1035 +#BLSInputWavLabel LAPPDWaveforms #LAPPDWaveforms +BLSInputWavLabel AlignedLAPPDData +#BLSInputWavLabel RawLAPPDData + +LowBLfitrange 0 +HiBLfitrange 60 +TrigLowBLfitrange 110 +TrigHiBLfitrange 160 +BLSOutputWavLabel BLsubtractedLAPPDData +oldLaserTrigAmpRange 40 + +#LAPPDFindT0 +FindT0Verbosity 0 +#FindT0InputWavLabel BLsubtractedLAPPDData +#FindT0InputWavLabel RawLAPPDData +FindT0InputWavLabel LAPPDWaveforms +OneBoardShift 0 +OneBoardShiftValue 16 + + +TrigEarlyCut 20 +TrigLateCut 200 +T0channelNo 1005 +T0channelNo1 1005 +T0channelNo2 1005 +T0signalmax -100. +T0signalthreshold -50. +T0signalmaxOld 50. #Older data uses a positive going signal +T0signalthresholdOld 80. #Older data uses a positive going signal +T0offset 0 +FindT0OutputWavLabel AlignedLAPPDData +GlobalShiftT0 0 +#Added by Marc +Triggerdefault 5 +LAPPDOffset 1000 + +#LAPPDPlotWaveForms +requireT0signal 0 +SaveByChannel 1 +PlotWavLabel BLsubtractedLAPPDData +#PlotWavLabel LAPPDWaveforms +outfile WaveForms_rawblsub.root +NHistos 400 +SaveSingleStrip 0 +SingleStripNo 9 + + + + + + + + diff --git a/configfiles/LAPPDRaw/ConfigStoreReadIn b/configfiles/LAPPDRaw/ConfigStoreReadIn new file mode 100755 index 000000000..d4b3b4e5f --- /dev/null +++ b/configfiles/LAPPDRaw/ConfigStoreReadIn @@ -0,0 +1,43 @@ +# General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +NUM_VECTOR_PPS 16 #Fixed PPS vector size +NUM_VECTOR_DATA 7795 #Fixed DATA vector size +NUM_VECTOR_METADATA 103 #Fixed META vector size +LAPPDchannelOffset 1000 +NChannels 30 +#StoreInputFile /pnfs/annie/persistent/users/redwards/data/filtered_lappd/R3649-R3844/LAPPDEventsBeamgateMRDTrack/FilteredEvents_LAPPDEventsBeamgateMRDTrack_R3649-R3844 + +LAPPDStoreReadInVerbosity 0 + +RawDataInputWavLabel RawWaveform +RawDataOutputWavLabel RawLAPPDData +BoardIndexLabel BoardIndex #Label of the vector of read out boards + +PsecReceiveMode 1 +stopEntries 10000000000 + +DoPedSubtraction 1 +Nboards 6 #Number of pedestal files to be read in +PedinputfileTXT ../Pedestals/swapLAPPD/Pedestal +#PedinputfileTXT ../Pedestals/change/Pedestal + +Pedinputfile1 ../Pedestals/PEDS_ACDC_board0.txt +Pedinputfile2 ../Pedestals/PEDS_ACDC_board1.txt + +#LAPPDReorderData +LAPPDReorderVerbosityLevel 0 +ReorderVerbosityLevel 0 +ReorderInputWavLabel RawLAPPDData +ReorderOutputWavLabel LAPPDWaveforms +DelayOffset 0 +GlobalShift 150 + +ReadStore 0 +NUM_VECTOR_DATA 7795 +NUM_VECTOR_PPS 16 +OutputWavLabel RawLAPPDData +SelectSingleLAPPD false +SelectedLAPPD 0 + diff --git a/configfiles/LAPPDRaw/Configs b/configfiles/LAPPDRaw/Configs new file mode 100644 index 000000000..00e70fe0a --- /dev/null +++ b/configfiles/LAPPDRaw/Configs @@ -0,0 +1,69 @@ + General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +NUM_VECTOR_PPS 16 #Fixed PPS vector size +NUM_VECTOR_DATA 7795 #Fixed DATA vector size +NUM_VECTOR_METADATA 103 #Fixed META vector size +LAPPDchannelOffset 1000 +NChannels 30 + +LAPPDStoreReadInVerbosity 0 + +mergingModeReadIn 0 +RawDataInputWavLabel RawWaveform +RawDataOutputWavLabel RawLAPPDData +BoardIndexLabel BoardIndex #Label of the vector of read out boards + +PsecReceiveMode 1 +stopEntries 10000000000 + +DoPedSubtraction 0 +Nboards 6 #Number of pedestal files to be read in +#PedinputfileTXT ../Pedestals/swapLAPPD/Pedestal +#PedinputfileTXT ../Pedestals/run3xxx/Pedestal +#Laser 2024 Feb +PedinputfileTXT ../Pedestals/Laser2024Feb/P +PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 + + +Pedinputfile1 ../Pedestals/PEDS_ACDC_board0.txt +Pedinputfile2 ../Pedestals/PEDS_ACDC_board1.txt + +#LAPPDReorderData +ReorderVerbosityLevel 0 +#ReorderInputWavLabel RawLAPPDData +ReorderInputWavLabel AlignedLAPPDData +ReorderOutputWavLabel LAPPDWaveforms +DelayOffset 0 +GlobalShift 180 + +ReadStore 0 +NUM_VECTOR_DATA 7795 +NUM_VECTOR_PPS 16 +OutputWavLabel RawLAPPDData +SelectSingleLAPPD false +SelectedLAPPD 0 +loadPSEC 1 +loadPPS 1 +loadOffsets 0 +num_vector_data 7795 +num_vector_pps 16 + +#LAPPDTreeMaker +LoadPulse 1 +LoadHit 1 +LoadWaveform 1 +LoadLAPPDDataTimeStamp 1 +LoadPPSTimestamp 1 +LoadRunInfoRaw 1 +LoadRunInfoANNIEEvent 0 + +treeMakerVerbosity 0 + +treeMakerInputPulseLabel LAPPDPulses +treeMakerInputHitLabel LAPPDHits +treeMakerOutputFileName LAPPDTree.root +LoadTriggerInfo 0 +LoadGroupOption beam +LoadGroupedTriggerInfo 1 diff --git a/configfiles/LAPPDRaw/DefaultTriggerMask.txt b/configfiles/LAPPDRaw/DefaultTriggerMask.txt new file mode 100644 index 000000000..002014f0f --- /dev/null +++ b/configfiles/LAPPDRaw/DefaultTriggerMask.txt @@ -0,0 +1,7 @@ +#Triggers are given by Jonathan; place one number per line. Values are index + 1 +#4+1: Delayed beam. 32+1: LED trigger. 34+1: AmBe and Cosmic trigger. 35+1: MRD_CR_Trigger. 30+1: LED_Start +3 +5 +8 +14 +32 diff --git a/configfiles/LAPPDRaw/LoadRawDataConfig b/configfiles/LAPPDRaw/LoadRawDataConfig new file mode 100644 index 000000000..0caf97dbc --- /dev/null +++ b/configfiles/LAPPDRaw/LoadRawDataConfig @@ -0,0 +1,12 @@ +verbosity 0 +BuildType LAPPDAndCTC +Mode FileList + + +InputFile ./configfiles/LAPPDRaw/list.txt + + +DummyRunInfo 1 +StoreTrigOverlap 0 +ReadTrigOverlap 0 +StoreRawData 0 diff --git a/configfiles/LAPPDRaw/ToolChainConfig b/configfiles/LAPPDRaw/ToolChainConfig new file mode 100644 index 000000000..6bccc8861 --- /dev/null +++ b/configfiles/LAPPDRaw/ToolChainConfig @@ -0,0 +1,24 @@ + +#ToollChain dynamic setup file + +##### Runtime Paramiters ##### +verbose 1 ## Verbosity level of ToolChain +error_level 0 # 0= do not exit, 1= exit on unhandeled errors only, 2= exit on unhandeled errors and handeled errors +attempt_recover 1 ## 1= will attempt to finalise if an execute fails + +###### Logging ##### +log_mode Interactive # Interactive=cout , Remote= remote logging system "serservice_name Remote_Logging" , Local = local file log; +log_local_path ./log +log_service LogStore + +###### Service discovery ##### Ignore these settings for local analysis +service_publish_sec -1 +service_kick_sec -1 + +##### Tools To Add ##### +Tools_File configfiles/LAPPDRaw/ToolsConfig ## list of tools to run and their config files + +##### Run Type ##### +Inline -1 ## number of Execute steps in program, -1 infinite loop that is ended by user +Interactive 0 ## set to 1 if you want to run the code interactively + diff --git a/configfiles/LAPPDRaw/ToolsConfig b/configfiles/LAPPDRaw/ToolsConfig new file mode 100644 index 000000000..1bae5453d --- /dev/null +++ b/configfiles/LAPPDRaw/ToolsConfig @@ -0,0 +1,18 @@ +LoadGeometry LoadGeometry configfiles/LAPPDRaw/ConfigGeo +LoadRawData LoadRawData configfiles/LAPPDRaw/LoadRawDataConfig + +#TriggerDataDecoder TriggerDataDecoder configfiles/LAPPDRaw/TriggerDataDecoderConfig + +LAPPDLoadStore LAPPDLoadStore configfiles/LAPPDRaw/Configs +LAPPDStoreReorder LAPPDStoreReorder configfiles/LAPPDRaw/ConfigStoreReadIn + +LAPPDTimeAlignment LAPPDTimeAlignment configfiles/LAPPDRaw/ConfigPreProcess +LAPPDBaseline LAPPDBaseline configfiles/LAPPDRaw/ConfigPreProcess +LAPPDPlots LAPPDPlots configfiles/LAPPDRaw/ConfigPlot + +LAPPDThresReco LAPPDThresReco configfiles/LAPPDRaw/ConfigPlot + +LAPPDTreeMaker LAPPDTreeMaker configfiles/LAPPDRaw/Configs + + + diff --git a/configfiles/LAPPDRaw/TriggerDataDecoderConfig b/configfiles/LAPPDRaw/TriggerDataDecoderConfig new file mode 100644 index 000000000..22aa89a31 --- /dev/null +++ b/configfiles/LAPPDRaw/TriggerDataDecoderConfig @@ -0,0 +1,4 @@ +verbosity 0 +#TriggerMaskFile ./configfiles/LAPPDBeamAnalysis/LAPPDRaw/DefaultTriggerMask.txt +StoreTrigOverlap 0 +ReadTrigOverlap 0 diff --git a/configfiles/LAPPDRaw/list.txt b/configfiles/LAPPDRaw/list.txt new file mode 100644 index 000000000..000620da4 --- /dev/null +++ b/configfiles/LAPPDRaw/list.txt @@ -0,0 +1,3 @@ +/pnfs/annie/scratch/users/yuefeng/rawData/4796/RAWDataR4796S0p14 +/pnfs/annie/scratch/users/yuefeng/rawData/4796/RAWDataR4796S0p15 +/pnfs/annie/scratch/users/yuefeng/rawData/4796/RAWDataR4796S0p16 diff --git a/configfiles/LAPPD_EB/ConfigGeo b/configfiles/LAPPD_EB/ConfigGeo new file mode 100644 index 000000000..ffe0ca918 --- /dev/null +++ b/configfiles/LAPPD_EB/ConfigGeo @@ -0,0 +1,11 @@ +#LoadGeometry +verbosity 0 +LAPPDChannelCount 60 +FACCMRDGeoFile ./configfiles/LoadGeometry/FullMRDGeometry.csv +DetectorGeoFile ./configfiles/LoadGeometry/DetectorGeometrySpecs.csv +LAPPDGeoFile ./configfiles/LAPPDana/LAPPDGeometry.csv +TankPMTGeoFile ./configfiles/LoadGeometry/FullTankPMTGeometry.csv +TankPMTGainFile ./configfiles/LoadGeometry/ChannelSPEGains_BeamRun20192020.csv +AuxiliaryChannelFile ./configfiles/LoadGeometry/AuxChannels.csv +LAPPDMerging 0 + diff --git a/configfiles/LAPPD_EB/Configs b/configfiles/LAPPD_EB/Configs new file mode 100644 index 000000000..0975b4615 --- /dev/null +++ b/configfiles/LAPPD_EB/Configs @@ -0,0 +1,56 @@ + General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +num_vector_pps 16 #Fixed PPS vector size +num_vector_data 7795 #Fixed DATA vector size +NUM_VECTOR_METADATA 103 #Fixed META vector size +LAPPDchannelOffset 1000 +NChannels 30 + +LAPPDStoreReadInVerbosity 0 + +mergingModeReadIn 0 +RawDataInputWavLabel RawWaveform +RawDataOutputWavLabel RawLAPPDData +BoardIndexLabel BoardIndex #Label of the vector of read out boards + +PsecReceiveMode 1 +stopEntries 10000000000 + +DoPedSubtraction 0 +Nboards 6 #Number of pedestal files to be read in +PedinputfileTXT ../Pedestals/Laser2024Feb/P +PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 + + +Pedinputfile1 ../Pedestals/PEDS_ACDC_board0.txt +Pedinputfile2 ../Pedestals/PEDS_ACDC_board1.txt + + +ReadStore 0 +OutputWavLabel RawLAPPDData +SelectSingleLAPPD false +SelectedLAPPD 0 +loadPSEC 1 +loadPPS 1 +loadOffsets 0 + + +#LAPPDTreeMaker +LoadPulse 0 +LoadHit 0 +LoadWaveform 0 +LoadLAPPDDataTimeStamp 1 +LoadPPSTimestamp 1 +LoadRunInfoRaw 1 +LoadRunInfoANNIEEvent 0 + +treeMakerVerbosity 0 + +treeMakerInputPulseLabel LAPPDPulses +treeMakerInputHitLabel LAPPDHits +treeMakerOutputFileName LAPPDTree.root +LoadTriggerInfo 1 +LoadGroupOption beam +LoadGroupedTriggerInfo 1 diff --git a/configfiles/LAPPD_EB/LoadRawDataConfig b/configfiles/LAPPD_EB/LoadRawDataConfig new file mode 100644 index 000000000..3b9a2ea0a --- /dev/null +++ b/configfiles/LAPPD_EB/LoadRawDataConfig @@ -0,0 +1,12 @@ +verbosity 0 +BuildType LAPPDAndCTC +Mode FileList + + +InputFile ./configfiles/LAPPD_EB/list.txt + + +DummyRunInfo 1 +StoreTrigOverlap 0 +ReadTrigOverlap 0 +StoreRawData 0 diff --git a/configfiles/LAPPD_EB/ToolChainConfig b/configfiles/LAPPD_EB/ToolChainConfig new file mode 100644 index 000000000..fe4ab0be2 --- /dev/null +++ b/configfiles/LAPPD_EB/ToolChainConfig @@ -0,0 +1,24 @@ + +#ToollChain dynamic setup file + +##### Runtime Paramiters ##### +verbose 1 ## Verbosity level of ToolChain +error_level 0 # 0= do not exit, 1= exit on unhandeled errors only, 2= exit on unhandeled errors and handeled errors +attempt_recover 1 ## 1= will attempt to finalise if an execute fails + +###### Logging ##### +log_mode Interactive # Interactive=cout , Remote= remote logging system "serservice_name Remote_Logging" , Local = local file log; +log_local_path ./log +log_service LogStore + +###### Service discovery ##### Ignore these settings for local analysis +service_publish_sec -1 +service_kick_sec -1 + +##### Tools To Add ##### +Tools_File configfiles/LAPPD_EB/ToolsConfig ## list of tools to run and their config files + +##### Run Type ##### +Inline -1 ## number of Execute steps in program, -1 infinite loop that is ended by user +Interactive 0 ## set to 1 if you want to run the code interactively + diff --git a/configfiles/LAPPD_EB/ToolsConfig b/configfiles/LAPPD_EB/ToolsConfig new file mode 100644 index 000000000..ea786fae4 --- /dev/null +++ b/configfiles/LAPPD_EB/ToolsConfig @@ -0,0 +1,11 @@ +LoadGeometry LoadGeometry configfiles/LAPPD_EB/ConfigGeo +LoadRawData LoadRawData configfiles/LAPPD_EB/LoadRawDataConfig + +TriggerDataDecoder TriggerDataDecoder configfiles/LAPPD_EB/TriggerDataDecoderConfig + +LAPPDLoadStore LAPPDLoadStore configfiles/LAPPD_EB/Configs + +LAPPDTreeMaker LAPPDTreeMaker configfiles/LAPPD_EB/Configs + + + diff --git a/configfiles/LAPPD_EB/TriggerDataDecoderConfig b/configfiles/LAPPD_EB/TriggerDataDecoderConfig new file mode 100644 index 000000000..d3e32f7f8 --- /dev/null +++ b/configfiles/LAPPD_EB/TriggerDataDecoderConfig @@ -0,0 +1,4 @@ +verbosity 0 +#TriggerMaskFile ./configfiles/LAPPDBeamAnalysis/LAPPDRawData/DefaultTriggerMask.txt +StoreTrigOverlap 0 +ReadTrigOverlap 0 diff --git a/configfiles/LAPPD_EB/list.txt b/configfiles/LAPPD_EB/list.txt new file mode 100644 index 000000000..f9adb18ca --- /dev/null +++ b/configfiles/LAPPD_EB/list.txt @@ -0,0 +1,8 @@ +/pnfs/annie/persistent/raw/raw/4765/RAWDataR4765S0p12 +/pnfs/annie/persistent/raw/raw/4765/RAWDataR4765S0p13 +/pnfs/annie/persistent/raw/raw/4765/RAWDataR4765S0p14 +/pnfs/annie/persistent/raw/raw/4765/RAWDataR4765S0p15 +/pnfs/annie/persistent/raw/raw/4765/RAWDataR4765S0p16 +/pnfs/annie/persistent/raw/raw/4765/RAWDataR4765S0p17 +/pnfs/annie/persistent/raw/raw/4765/RAWDataR4765S0p18 +/pnfs/annie/persistent/raw/raw/4765/RAWDataR4765S0p19 From e668884f90d3756c43e252f2334b42323aa6bf22 Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Fri, 24 May 2024 12:32:10 -0500 Subject: [PATCH 031/163] Fixing a bug wherein not all timestamps were being saved to the ROOT file correctly --- UserTools/BeamFetcherV2/BeamFetcherV2.cpp | 19 +++++++++++-------- UserTools/BeamFetcherV2/BeamFetcherV2.h | 3 ++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/UserTools/BeamFetcherV2/BeamFetcherV2.cpp b/UserTools/BeamFetcherV2/BeamFetcherV2.cpp index a25e52d05..2d7cba2d9 100644 --- a/UserTools/BeamFetcherV2/BeamFetcherV2.cpp +++ b/UserTools/BeamFetcherV2/BeamFetcherV2.cpp @@ -99,7 +99,8 @@ bool BeamFetcherV2::Initialise(std::string config_filename, DataModel& data) if (fSaveROOT) this->SetupROOTFile(); // initialize the last timestamp - fLastTimestamp = 0; + fLastTimestampFetched = 0; + fLastTimestampSaved = 0; BeamDataMap = new std::map >; m_data->CStore.Set("NewBeamDataAvailable", false); @@ -165,9 +166,9 @@ bool BeamFetcherV2::FetchFromTrigger() bool got_triggers = m_data->CStore.Get("TimeToTriggerWordMap",TimeToTriggerWordMap); // Now loop over the CTC timestamps - // But start at the fLastTimeStamp to prevent double counting if the timestamp data wasn't deleted + // But start at the fLastTimeStampFetched to prevent double counting if the timestamp data wasn't deleted if (got_triggers && TimeToTriggerWordMap) { - for (auto iterator = TimeToTriggerWordMap->lower_bound(fLastTimestamp); + for (auto iterator = TimeToTriggerWordMap->lower_bound(fLastTimestampFetched+1); iterator != TimeToTriggerWordMap->end(); ++iterator) { // We only care about beam triggers here @@ -181,7 +182,7 @@ bool BeamFetcherV2::FetchFromTrigger() // Grab the timestamp uint64_t trigTimestamp = iterator->first; - fLastTimestamp = trigTimestamp; + fLastTimestampFetched = trigTimestamp; // Need to drop from ns to ms. This means that some timestamps will // already be recorded. We can skip these cases @@ -292,13 +293,15 @@ void BeamFetcherV2::SetupROOTFile() void BeamFetcherV2::WriteTrees() { // Loop over timestamps - // But start at the fLastTimeStamp to prevent double counting if the timestamp data wasn't deleted - int devCounter = 0; - uint64_t lastTimestamp = fLastTimestamp/1E6; - for (auto iterTS = BeamDataMap->lower_bound(lastTimestamp); + // But start at the fLastTimeStampSaved to prevent double counting if the timestamp data wasn't deleted + int devCounter = 0; + for (auto iterTS = BeamDataMap->lower_bound(fLastTimestampSaved+1); iterTS != BeamDataMap->end(); ++iterTS) { fTimestamp = iterTS->first; + fLastTimestampSaved = fTimestamp; + + std::cout << "Timestamp: " << fTimestamp << std::endl; // Loop over devices for (const auto iterDev : iterTS->second) { diff --git a/UserTools/BeamFetcherV2/BeamFetcherV2.h b/UserTools/BeamFetcherV2/BeamFetcherV2.h index 88c8ff0b2..6aac55bc2 100644 --- a/UserTools/BeamFetcherV2/BeamFetcherV2.h +++ b/UserTools/BeamFetcherV2/BeamFetcherV2.h @@ -51,7 +51,8 @@ class BeamFetcherV2: public Tool { std::vector fDevices; // Keep the last timestamp around to make sure we don't double count - uint64_t fLastTimestamp; + uint64_t fLastTimestampFetched; + uint64_t fLastTimestampSaved; // Is there new data? bool fNewCTCData; From 786a194a3982a3884b62290720c81b6325c72e7c Mon Sep 17 00:00:00 2001 From: Yue Date: Sat, 1 Jun 2024 12:45:03 -0500 Subject: [PATCH 032/163] New event builder Added tools: EBLoadRaw : Load RawData EBTriggerGrouper : group trigger for event building EBPMT : Load PMT hits, build with the grouped triggers EBMRD : Load MRD events, build with the grouped triggers EBLAPPD : Load LAPPD info, build with the grouped triggers EBSaver : use the pairing information, save the build events to boost store Modified tools: PhaseIITreeMaker: include loading LAPPD timing information, and grouped triggers Added file: offsetFit_MultipleLAPPD.cpp : use for LAPPD offset fitting Added tool chains: EventBuildingV2 : new event building tool chain LAPPD_EB: generate LAPPD timing information with trigger information, used for LAPPD offset fit On branch Application Your branch is up to date with 'origin/Application'. Changes to be committed: new file: UserTools/EBLAPPD/EBLAPPD.cpp new file: UserTools/EBLAPPD/EBLAPPD.h new file: UserTools/EBLAPPD/README.md new file: UserTools/EBLoadRaw/EBLoadRaw.cpp new file: UserTools/EBLoadRaw/EBLoadRaw.h new file: UserTools/EBLoadRaw/README.md new file: UserTools/EBMRD/EBMRD.cpp new file: UserTools/EBMRD/EBMRD.h new file: UserTools/EBMRD/README.md new file: UserTools/EBPMT/EBPMT.cpp new file: UserTools/EBPMT/EBPMT.h new file: UserTools/EBPMT/README.md new file: UserTools/EBSaver/EBSaver.cpp new file: UserTools/EBSaver/EBSaver.h new file: UserTools/EBSaver/README.md new file: UserTools/EBTriggerGrouper/EBTriggerGrouper.cpp new file: UserTools/EBTriggerGrouper/EBTriggerGrouper.h new file: UserTools/EBTriggerGrouper/README.md modified: UserTools/Factory/Factory.cpp modified: UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp modified: UserTools/PhaseIITreeMaker/PhaseIITreeMaker.h modified: UserTools/Unity.h modified: configfiles/BeamClusterAnalysis/PhaseIITreeMakerConfig new file: configfiles/EventBuilderV2/DefaultTriggerMask.txt new file: configfiles/EventBuilderV2/EBLAPPDConfig new file: configfiles/EventBuilderV2/EBLoadRawConfig new file: configfiles/EventBuilderV2/EBMRDConfig new file: configfiles/EventBuilderV2/EBPMTConfig new file: configfiles/EventBuilderV2/EBSaverConfig new file: configfiles/EventBuilderV2/EBTriggerGrouperConfig new file: configfiles/EventBuilderV2/LAPPDLoadStoreConfig new file: configfiles/EventBuilderV2/MRDDataDecoderConfig new file: configfiles/EventBuilderV2/PMTDataDecoderConfig new file: configfiles/EventBuilderV2/PhaseIIADCCalibratorConfig new file: configfiles/EventBuilderV2/PhaseIIADCHitFinderConfig new file: configfiles/EventBuilderV2/ToolChainConfig new file: configfiles/EventBuilderV2/ToolsConfig new file: configfiles/EventBuilderV2/TriggerDataDecoderConfig new file: configfiles/EventBuilderV2/list.txt modified: configfiles/LAPPDRaw/Configs modified: configfiles/LAPPDRaw/list.txt modified: configfiles/LAPPD_EB/list.txt new file: offsetFit_MultipleLAPPD.cpp --- UserTools/EBLAPPD/EBLAPPD.cpp | 314 +++++ UserTools/EBLAPPD/EBLAPPD.h | 79 ++ UserTools/EBLAPPD/README.md | 20 + UserTools/EBLoadRaw/EBLoadRaw.cpp | 645 +++++++++ UserTools/EBLoadRaw/EBLoadRaw.h | 113 ++ UserTools/EBLoadRaw/README.md | 20 + UserTools/EBMRD/EBMRD.cpp | 225 ++++ UserTools/EBMRD/EBMRD.h | 65 + UserTools/EBMRD/README.md | 20 + UserTools/EBPMT/EBPMT.cpp | 425 ++++++ UserTools/EBPMT/EBPMT.h | 73 ++ UserTools/EBPMT/README.md | 20 + UserTools/EBSaver/EBSaver.cpp | 1150 +++++++++++++++++ UserTools/EBSaver/EBSaver.h | 167 +++ UserTools/EBSaver/README.md | 20 + .../EBTriggerGrouper/EBTriggerGrouper.cpp | 723 +++++++++++ UserTools/EBTriggerGrouper/EBTriggerGrouper.h | 119 ++ UserTools/EBTriggerGrouper/README.md | 20 + UserTools/Factory/Factory.cpp | 6 + .../PhaseIITreeMaker/PhaseIITreeMaker.cpp | 147 +++ UserTools/PhaseIITreeMaker/PhaseIITreeMaker.h | 32 + UserTools/Unity.h | 6 + .../PhaseIITreeMakerConfig | 8 +- .../EventBuilderV2/DefaultTriggerMask.txt | 10 + configfiles/EventBuilderV2/EBLAPPDConfig | 7 + configfiles/EventBuilderV2/EBLoadRawConfig | 10 + configfiles/EventBuilderV2/EBMRDConfig | 4 + configfiles/EventBuilderV2/EBPMTConfig | 4 + configfiles/EventBuilderV2/EBSaverConfig | 10 + .../EventBuilderV2/EBTriggerGrouperConfig | 23 + .../EventBuilderV2/LAPPDLoadStoreConfig | 39 + .../EventBuilderV2/MRDDataDecoderConfig | 2 + .../EventBuilderV2/PMTDataDecoderConfig | 5 + .../EventBuilderV2/PhaseIIADCCalibratorConfig | 15 + .../EventBuilderV2/PhaseIIADCHitFinderConfig | 10 + configfiles/EventBuilderV2/ToolChainConfig | 23 + configfiles/EventBuilderV2/ToolsConfig | 21 + .../EventBuilderV2/TriggerDataDecoderConfig | 3 + configfiles/EventBuilderV2/list.txt | 3 + configfiles/LAPPDRaw/Configs | 5 +- configfiles/LAPPDRaw/list.txt | 713 +++++++++- configfiles/LAPPD_EB/list.txt | 58 +- offsetFit_MultipleLAPPD.cpp | 1076 +++++++++++++++ 43 files changed, 6441 insertions(+), 17 deletions(-) create mode 100644 UserTools/EBLAPPD/EBLAPPD.cpp create mode 100644 UserTools/EBLAPPD/EBLAPPD.h create mode 100644 UserTools/EBLAPPD/README.md create mode 100644 UserTools/EBLoadRaw/EBLoadRaw.cpp create mode 100644 UserTools/EBLoadRaw/EBLoadRaw.h create mode 100644 UserTools/EBLoadRaw/README.md create mode 100644 UserTools/EBMRD/EBMRD.cpp create mode 100644 UserTools/EBMRD/EBMRD.h create mode 100644 UserTools/EBMRD/README.md create mode 100644 UserTools/EBPMT/EBPMT.cpp create mode 100644 UserTools/EBPMT/EBPMT.h create mode 100644 UserTools/EBPMT/README.md create mode 100644 UserTools/EBSaver/EBSaver.cpp create mode 100644 UserTools/EBSaver/EBSaver.h create mode 100644 UserTools/EBSaver/README.md create mode 100644 UserTools/EBTriggerGrouper/EBTriggerGrouper.cpp create mode 100644 UserTools/EBTriggerGrouper/EBTriggerGrouper.h create mode 100644 UserTools/EBTriggerGrouper/README.md create mode 100644 configfiles/EventBuilderV2/DefaultTriggerMask.txt create mode 100644 configfiles/EventBuilderV2/EBLAPPDConfig create mode 100644 configfiles/EventBuilderV2/EBLoadRawConfig create mode 100644 configfiles/EventBuilderV2/EBMRDConfig create mode 100644 configfiles/EventBuilderV2/EBPMTConfig create mode 100644 configfiles/EventBuilderV2/EBSaverConfig create mode 100644 configfiles/EventBuilderV2/EBTriggerGrouperConfig create mode 100644 configfiles/EventBuilderV2/LAPPDLoadStoreConfig create mode 100644 configfiles/EventBuilderV2/MRDDataDecoderConfig create mode 100644 configfiles/EventBuilderV2/PMTDataDecoderConfig create mode 100644 configfiles/EventBuilderV2/PhaseIIADCCalibratorConfig create mode 100644 configfiles/EventBuilderV2/PhaseIIADCHitFinderConfig create mode 100644 configfiles/EventBuilderV2/ToolChainConfig create mode 100644 configfiles/EventBuilderV2/ToolsConfig create mode 100644 configfiles/EventBuilderV2/TriggerDataDecoderConfig create mode 100644 configfiles/EventBuilderV2/list.txt create mode 100644 offsetFit_MultipleLAPPD.cpp diff --git a/UserTools/EBLAPPD/EBLAPPD.cpp b/UserTools/EBLAPPD/EBLAPPD.cpp new file mode 100644 index 000000000..bc8147794 --- /dev/null +++ b/UserTools/EBLAPPD/EBLAPPD.cpp @@ -0,0 +1,314 @@ +#include "EBLAPPD.h" + +EBLAPPD::EBLAPPD() : Tool() {} + +bool EBLAPPD::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + m_variables.Get("verbosityEBLAPPD", verbosityEBLAPPD); + matchTargetTrigger = 14; + m_variables.Get("matchTargetTrigger", matchTargetTrigger); + matchTolerance_ns = 400000; // default 400us + m_variables.Get("matchTolerance_ns", matchTolerance_ns); + matchToAllTriggers = false; + m_variables.Get("matchToAllTriggers", matchToAllTriggers); + exePerMatch = 500; + m_variables.Get("exePerMatch", exePerMatch); + + return true; +} + +bool EBLAPPD::Execute() +{ + m_data->CStore.Get("PairedLAPPDTriggerTimestamp", PairedCTCTimeStamps); + m_data->CStore.Get("PairedLAPPDTimeStamps", PairedLAPPDTimeStamps); + m_data->CStore.Get("PairedLAPPD_TriggerIndex", PairedLAPPD_TriggerIndex); + m_data->CStore.Get("Buffer_LAPPDData", Buffer_LAPPDData); + m_data->CStore.Get("Buffer_LAPPDTimestamp_ns", Buffer_LAPPDTimestamp_ns); + m_data->CStore.Get("Buffer_LAPPDBeamgate_ns", Buffer_LAPPDBeamgate_ns); + m_data->CStore.Get("Buffer_LAPPDOffset", Buffer_LAPPDOffset); + m_data->CStore.Get("Buffer_LAPPDBeamgate_Raw", Buffer_LAPPDBeamgate_Raw); + m_data->CStore.Get("Buffer_LAPPDTimestamp_Raw", Buffer_LAPPDTimestamp_Raw); + m_data->CStore.Get("Buffer_LAPPDBGCorrection", Buffer_LAPPDBGCorrection); + m_data->CStore.Get("Buffer_LAPPDTSCorrection", Buffer_LAPPDTSCorrection); + m_data->CStore.Get("Buffer_LAPPDOffset_minus_ps", Buffer_LAPPDOffset_minus_ps); + m_data->CStore.Get("Buffer_LAPPDRunCode", Buffer_RunCode); + + Log("EBLAPPD: Got pairing information from CStore, PairedLAPPDTimeStamps[14] size = " + std::to_string(PairedLAPPDTimeStamps[14].size()), v_message, verbosityEBLAPPD); + + CleanData(); + m_data->CStore.Get("RunCode", currentRunCode); + + bool IsNewLAPPDData = false; + m_data->CStore.Get("NewLAPPDDataAvailable", IsNewLAPPDData); + Log("EBLAPPD: NewLAPPDDataAvailable = " + std::to_string(IsNewLAPPDData), v_message, verbosityEBLAPPD); + bool LoadingPPS = false; + m_data->CStore.Get("LoadingPPS", LoadingPPS); + + if (IsNewLAPPDData && !LoadingPPS) + LoadLAPPDData(); + + Log("EBLAPPD: Finished Loading LAPPD data to buffer, Buffer_LAPPDData size is now " + std::to_string(Buffer_LAPPDData.size()), v_message, verbosityEBLAPPD); + + string storeFileName; + m_data->CStore.Get("SaveToFileName", storeFileName); + + bool stopLoop = false; + m_data->vars.Get("StopLoop", stopLoop); + int runNum = thisRunNum; + m_data->vars.Get("RunNumber", thisRunNum); + if (stopLoop || runNum != thisRunNum || exeNum % exePerMatch == 0) + { + Log("EBLAPPD: exeNum = " + std::to_string(exeNum) + ". Doing matching", v_message, verbosityEBLAPPD); + if (matchToAllTriggers) + { + Matching(0, 0); + } + else + { + bool BeamTriggerGroupped = false; + m_data->CStore.Get("BeamTriggerGroupped", BeamTriggerGroupped); + if (BeamTriggerGroupped) + Matching(14, 14); + else + Log("EBLAPPD: BeamTriggerGroupped is false, no beam trigger groupped in the grouper, stop matching", v_message, verbosityEBLAPPD); + + bool LaserTriggerGroupped = false; + m_data->CStore.Get("LaserTriggerGroupped", LaserTriggerGroupped); + if (LaserTriggerGroupped) + Matching(47, 46); + else + Log("EBLAPPD: LaserTriggerGroupped is false, no laser trigger groupped in the grouper, stop matching", v_message, verbosityEBLAPPD); + + bool CosmicTriggerGroupped = false; + m_data->CStore.Get("CosmicTriggerGroupped", CosmicTriggerGroupped); + if (CosmicTriggerGroupped) + Matching(44, 46); + else + Log("EBLAPPD: CosmicTriggerGroupped is false, no cosmic trigger groupped in the grouper, stop matching", v_message, verbosityEBLAPPD); + + bool LEDTriggerGroupped = false; + m_data->CStore.Get("LEDTriggerGroupped", LEDTriggerGroupped); + if (LEDTriggerGroupped) + Matching(31, 46); + else + Log("EBLAPPD: LEDTriggerGroupped is false, no LED trigger groupped in the grouper, stop matching", v_message, verbosityEBLAPPD); + } + } + + // Set all matching info to CStore + m_data->CStore.Set("PairedLAPPDTriggerTimestamp", PairedCTCTimeStamps); + m_data->CStore.Set("PairedLAPPDTimeStamps", PairedLAPPDTimeStamps); + m_data->CStore.Set("PairedLAPPD_TriggerIndex", PairedLAPPD_TriggerIndex); + Log("EBLAPPD: Set pairing information to CStore, PairedLAPPDTimeStamps[14] size = " + std::to_string(PairedLAPPDTimeStamps[14].size()), v_message, verbosityEBLAPPD); + + // Set the indexing of buffer + m_data->CStore.Set("Buffer_LAPPDTimestamp_ns", Buffer_LAPPDTimestamp_ns); + + // Also set all buffers to CStore + m_data->CStore.Set("Buffer_LAPPDData", Buffer_LAPPDData); + m_data->CStore.Set("Buffer_LAPPDBeamgate_ns", Buffer_LAPPDBeamgate_ns); + m_data->CStore.Set("Buffer_LAPPDOffset", Buffer_LAPPDOffset); + m_data->CStore.Set("Buffer_LAPPDBeamgate_Raw", Buffer_LAPPDBeamgate_Raw); + m_data->CStore.Set("Buffer_LAPPDTimestamp_Raw", Buffer_LAPPDTimestamp_Raw); + m_data->CStore.Set("Buffer_LAPPDBGCorrection", Buffer_LAPPDBGCorrection); + m_data->CStore.Set("Buffer_LAPPDTSCorrection", Buffer_LAPPDTSCorrection); + m_data->CStore.Set("Buffer_LAPPDOffset_minus_ps", Buffer_LAPPDOffset_minus_ps); + m_data->CStore.Set("Buffer_LAPPDRunCode", Buffer_RunCode); + + exeNum++; + + return true; +} + +bool EBLAPPD::Finalise() +{ + Log("\033[1;34mEBLAPPD: Finalising\033[0m", v_message, verbosityEBLAPPD); + Log("EBLAPPD: Matched LAPPD number = " + std::to_string(matchedLAPPDNumber), v_message, verbosityEBLAPPD); + Log("EBLAPPD: Unmatched LAPPD number = " + std::to_string(MatchBuffer_LAPPDTimestamp_ns.size()), v_message, verbosityEBLAPPD); + return true; +} + +bool EBLAPPD::CleanData() +{ + LAPPDBeamgate_ns = 0; + LAPPDTimestamp_ns = 0; + LAPPDOffset = 0; + LAPPDBeamgate_Raw = 0; + LAPPDTimestamp_Raw = 0; + LAPPDBGCorrection = 0; + LAPPDTSCorrection = 0; + LAPPDOffset_minus_ps = 0; + + return true; +} + +bool EBLAPPD::LoadLAPPDData() +{ + // get the LAPPD beamgate + LAPPDBeamgate_Raw = 0; + LAPPDTimestamp_Raw = 0; + m_data->CStore.Get("LAPPDBeamgate_Raw", LAPPDBeamgate_Raw); + m_data->CStore.Get("LAPPDTimestamp_Raw", LAPPDTimestamp_Raw); + + LAPPDBeamgate_ns = LAPPDBeamgate_Raw * 3.125; + LAPPDTimestamp_ns = LAPPDTimestamp_Raw * 3.125; + + LAPPDBGCorrection = 0; + LAPPDTSCorrection = 0; + LAPPDOffset_minus_ps = 0; + m_data->CStore.Get("LAPPDBGCorrection", LAPPDBGCorrection); + m_data->CStore.Get("LAPPDTSCorrection", LAPPDTSCorrection); + m_data->CStore.Get("LAPPDOffset_minus_ps", LAPPDOffset_minus_ps); + LAPPDOffset = 0; + m_data->CStore.Get("LAPPDOffset", LAPPDOffset); + + LAPPDBeamgate_ns = LAPPDBeamgate_ns + LAPPDBGCorrection + LAPPDOffset; + LAPPDTimestamp_ns = LAPPDTimestamp_ns + LAPPDTSCorrection + LAPPDOffset; + + if (verbosityEBLAPPD > 1) + { + cout << "Processing new LAPPD data from store" << endl; + cout << "Got info: LAPPDBeamgate_Raw: " << LAPPDBeamgate_Raw << ", LAPPDTimestamp_Raw: " << LAPPDTimestamp_Raw << ", LAPPDBGCorrection: " << LAPPDBGCorrection << ", LAPPDTSCorrection: " << LAPPDTSCorrection << ", LAPPDOffset: " << LAPPDOffset << ", LAPPDOffset_minus_ps: " << LAPPDOffset_minus_ps << endl; + cout << "LAPPDBeamgate_ns: " << LAPPDBeamgate_ns << endl; + cout << "LAPPDTimestamp_ns: " << LAPPDTimestamp_ns << endl; + } + + bool gotdata = m_data->CStore.Get("StoreLoadedLAPPDData", dat); + + if (gotdata) + { + Buffer_LAPPDTimestamp_ns.push_back(LAPPDTimestamp_ns); + + Buffer_LAPPDData.push_back(dat); + Buffer_LAPPDBeamgate_ns.push_back(LAPPDBeamgate_ns); + Buffer_LAPPDOffset.push_back(LAPPDOffset); + Buffer_LAPPDBeamgate_Raw.push_back(LAPPDBeamgate_Raw); + Buffer_LAPPDTimestamp_Raw.push_back(LAPPDTimestamp_Raw); + Buffer_LAPPDBGCorrection.push_back(LAPPDBGCorrection); + Buffer_LAPPDTSCorrection.push_back(LAPPDTSCorrection); + Buffer_LAPPDOffset_minus_ps.push_back(LAPPDOffset_minus_ps); + Buffer_RunCode.push_back(currentRunCode); + + MatchBuffer_LAPPDTimestamp_ns.push_back(LAPPDTimestamp_ns); + + Log("EBLAPPD: Loaded LAPPD data to buffer, Buffer_LAPPDData size after this load is now " + std::to_string(Buffer_LAPPDData.size()), v_message, verbosityEBLAPPD); + } + + return true; +} + +bool EBLAPPD::Matching(int targetTrigger, int matchToTrack) +{ + cout << "\033[1;34m******* EBLAPPD : Matching *******\033[0m" << endl; + + std::map>> GroupedTriggersInTotal; // each map is a group of triggers, with the key is the target trigger word + m_data->CStore.Get("GroupedTriggersInTotal", GroupedTriggersInTotal); + //print how many trigger groups in each track + + vector matchedLAPPDTimes; + vector indexToRemove; + std::map matchedNumberInTrack; + + // loop the LAPPDDataBuffer keys, and loop all the grouped triggers + // in each group of trigger, find the target trigger word and it's time + // fine the minimum time difference, if smaller than matchTolerance_ns, then save the time to PairedCTCTimeStamps and PairedLAPPDTimeStamps + for (int i = 0; i < MatchBuffer_LAPPDTimestamp_ns.size(); i++) + { + uint64_t LAPPDtime = MatchBuffer_LAPPDTimestamp_ns.at(i); + // if found LAPPDtime at PairedLAPPDTimeStamps, skip //shouldn't happen + if (std::find(PairedLAPPDTimeStamps[matchToTrack].begin(), PairedLAPPDTimeStamps[matchToTrack].end(), LAPPDtime) != PairedLAPPDTimeStamps[matchToTrack].end()) + { + Log("EBLAPPD: Buffer " + std::to_string(i) + " with time " + std::to_string(Buffer_LAPPDTimestamp_ns.at(i)) + ": Found a match already", v_message, verbosityEBLAPPD); + continue; + } + + // set minDT to 5 min + uint64_t minDT = 5 * 60 * 1e9; + uint64_t minDTTrigger = 0; + uint64_t dt = 0; + uint32_t matchedTrigWord = 0; + int matchedTrack = 0; + int matchedIndex = 0; + + for (std::pair>> pair : GroupedTriggersInTotal) + { + int TrackTriggerWord = pair.first; + if(matchedNumberInTrack.find(TrackTriggerWord) == matchedNumberInTrack.end()) + matchedNumberInTrack.emplace(TrackTriggerWord, 0); + if (TrackTriggerWord != matchToTrack && !matchToAllTriggers) + { + Log("EBLAPPD: Skipping TrackTriggerWord " + std::to_string(TrackTriggerWord), v_debug, verbosityEBLAPPD); + continue; + } + vector> GroupedTriggers = pair.second; + + for (int j = 0; j < GroupedTriggers.size(); j++) + { + map groupedTrigger = GroupedTriggers.at(j); + // itearte over all the grouped triggers, if the value is target trigger, then calculate the time difference + for (std::pair p : groupedTrigger) + { + if (matchToAllTriggers || p.second == targetTrigger) + { + + if (LAPPDtime > p.first) + { + dt = LAPPDtime - p.first; + } + else + { + dt = p.first - LAPPDtime; + } + if (dt < minDT) + { + minDT = dt; + minDTTrigger = p.first; + matchedTrigWord = p.second; + matchedTrack = TrackTriggerWord; + matchedIndex = j; + } + } + } + } + } + + Log("EBLAPPD: at buffer " + std::to_string(i) + " with time " + std::to_string(Buffer_LAPPDTimestamp_ns.at(i)) + ", minDT: " + std::to_string(minDT), v_debug, verbosityEBLAPPD); + if (minDT < matchTolerance_ns) + { + PairedCTCTimeStamps[matchedTrack].push_back(minDTTrigger); + PairedLAPPDTimeStamps[matchedTrack].push_back(LAPPDtime); + PairedLAPPD_TriggerIndex[matchedTrack].push_back(matchedIndex); + + matchedLAPPDTimes.push_back(LAPPDtime); + indexToRemove.push_back(i); + matchedLAPPDNumber++; + matchedNumberInTrack[matchedTrack]++; + Log("EBLAPPD: Buffer " + std::to_string(i) + " with time " + std::to_string(Buffer_LAPPDTimestamp_ns.at(i)) + ": Found a match for LAPPD data at " + std::to_string(LAPPDtime) + " with target trigger at " + std::to_string(minDTTrigger) + " with minDT " + std::to_string(minDT), v_message, verbosityEBLAPPD); + } + } + Log("EBLAPPD: Finished matching LAPPD data with target triggers, " + std::to_string(matchedLAPPDTimes.size()) + " new matched found, total matchedLAPPDNumber = " + std::to_string(matchedLAPPDNumber) + " in buffer size = " + std::to_string(MatchBuffer_LAPPDTimestamp_ns.size()), v_message, verbosityEBLAPPD); + + for (int i = indexToRemove.size() - 1; i >= 0; i--) + { + MatchBuffer_LAPPDTimestamp_ns.erase(MatchBuffer_LAPPDTimestamp_ns.begin() + indexToRemove.at(i)); + } + + Log("EBLAPPD: Finished removing paired LAPPD data from match buffer, MatchBuffer_LAPPDTimestamp_ns size is now " + std::to_string(MatchBuffer_LAPPDTimestamp_ns.size()), v_message, verbosityEBLAPPD); + //print all elements in matchedNumberInTrack with key and value + for(std::pair pair : matchedNumberInTrack) + { + Log("EBLAPPD: Match finished, matched number in Track " + std::to_string(pair.first) + " is = " + std::to_string(pair.second), v_message, verbosityEBLAPPD); + } + + + return true; +} \ No newline at end of file diff --git a/UserTools/EBLAPPD/EBLAPPD.h b/UserTools/EBLAPPD/EBLAPPD.h new file mode 100644 index 000000000..fa5326200 --- /dev/null +++ b/UserTools/EBLAPPD/EBLAPPD.h @@ -0,0 +1,79 @@ +#ifndef EBLAPPD_H +#define EBLAPPD_H + +#include +#include + +#include "Tool.h" +#include "PsecData.h" +#include "BoostStore.h" + +/** + * \class EBLAPPD + * + * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. + * + * $Author: B.Richards $ + * $Date: 2019/05/28 10:44:00 $ + * Contact: b.richards@qmul.ac.uk + */ +class EBLAPPD : public Tool +{ + +public: + EBLAPPD(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + bool LoadLAPPDData(); + bool CleanData(); + bool Matching(int targetTrigger, int matchToTrack); + +private: + int thisRunNum; + bool matchToAllTriggers; + int exePerMatch; + + PsecData dat; + uint64_t LAPPDBeamgate_ns; + uint64_t LAPPDTimestamp_ns; + uint64_t LAPPDOffset; + unsigned long LAPPDBeamgate_Raw; + unsigned long LAPPDTimestamp_Raw; + int LAPPDBGCorrection; + int LAPPDTSCorrection; + int LAPPDOffset_minus_ps; + + vector MatchBuffer_LAPPDTimestamp_ns; // used to indexing data for unmatched + + // TODO, maybe make a new "LAPPDBuildData" class? + vector Buffer_LAPPDTimestamp_ns; // used to indexing the data + vector Buffer_LAPPDData; + vector Buffer_LAPPDBeamgate_ns; + vector Buffer_LAPPDOffset; + vector Buffer_LAPPDBeamgate_Raw; + vector Buffer_LAPPDTimestamp_Raw; + vector Buffer_LAPPDBGCorrection; + vector Buffer_LAPPDTSCorrection; + vector Buffer_LAPPDOffset_minus_ps; + vector Buffer_RunCode; + + std::map> PairedCTCTimeStamps; + std::map> PairedLAPPD_TriggerIndex; + std::map> PairedLAPPDTimeStamps; + + int matchTargetTrigger; + uint64_t matchTolerance_ns; + int verbosityEBLAPPD; + + int matchedLAPPDNumber = 0; + int exeNum = 0; + int currentRunCode; + + int v_message = 1; + int v_warning = 2; + int v_error = 3; + int v_debug = 4; +}; + +#endif diff --git a/UserTools/EBLAPPD/README.md b/UserTools/EBLAPPD/README.md new file mode 100644 index 000000000..b8d0bb8d0 --- /dev/null +++ b/UserTools/EBLAPPD/README.md @@ -0,0 +1,20 @@ +# EBLAPPD + +EBLAPPD + +## Data + +Describe any data formats EBLAPPD creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for EBLAPPD. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/EBLoadRaw/EBLoadRaw.cpp b/UserTools/EBLoadRaw/EBLoadRaw.cpp new file mode 100644 index 000000000..ef04f56c3 --- /dev/null +++ b/UserTools/EBLoadRaw/EBLoadRaw.cpp @@ -0,0 +1,645 @@ +#include "EBLoadRaw.h" + +EBLoadRaw::EBLoadRaw() : Tool() {} + +bool EBLoadRaw::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + m_variables.Get("verbosityEBLoadRaw", verbosityEBLoadRaw); + + ReadTriggerOverlap = false; + m_variables.Get("ReadTriggerOverlap", ReadTriggerOverlap); + m_variables.Get("InputFile", InputFile); + OrganizedFileList = OrganizeRunParts(InputFile); + + LoadCTC = false; + m_variables.Get("LoadCTC", LoadCTC); + LoadPMT = false; + m_variables.Get("LoadPMT", LoadPMT); + LoadMRD = false; + m_variables.Get("LoadMRD", LoadMRD); + LoadLAPPD = false; + m_variables.Get("LoadLAPPD", LoadLAPPD); + + FileCompleted = false; + JumpBecauseLAPPD = false; + ProcessingComplete = false; + PMTPaused = false; + MRDPaused = false; + LAPPDPaused = false; + CTCPaused = false; + usingTriggerOverlap = false; + LoadingFileNumber = 0; + + RunNumber = 0; + SubRunNumber = 0; + PartFileNumber = 0; + + CTCEntryNum = 0; + PMTEntryNum = 0; + MRDEntryNum = 0; + LAPPDEntryNum = 0; + + PMTTotalEntries = 0; + MRDTotalEntries = 0; + LAPPDTotalEntries = 0; + CTCTotalEntries = 0; + PMTEntriesCompleted = false; + MRDEntriesCompleted = false; + LAPPDEntriesCompleted = false; + CTCEntriesCompleted = false; + LoadedPMTTotalEntries = 0; + LoadedMRDTotalEntries = 0; + LoadedLAPPDTotalEntries = 0; + LoadedCTCTotalEntries = 0; + + RawData = new BoostStore(false, 0); + PMTData = new BoostStore(false, 2); + MRDData = new BoostStore(false, 2); + LAPPDData = new BoostStore(false, 2); + CTCData = new BoostStore(false, 2); + CData = new std::vector; + TData = new TriggerData; + MData = new MRDOut; + LData = new PsecData; + + m_data->CStore.Set("FileProcessingComplete", false); + RunCodeToSave = 0; + + return true; +} + +bool EBLoadRaw::Execute() +{ + m_data->CStore.Set("NewRawDataEntryAccessed", false); + m_data->CStore.Set("NewRawDataFileAccessed", false); + m_data->CStore.Set("SaveProcessedFile", false); + + ProcessingComplete = false; + if (FileCompleted) + { + if (CurrentFile != "NONE") + { + RunCodeToSave = RunCode(CurrentFile); + m_data->CStore.Set("RunCodeToSave", RunCodeToSave); + m_data->CStore.Set("SaveProcessedFile", true); + Log("EBLoadRaw: File completed, saving file " + CurrentFile + " with RunCode: " + std::to_string(RunCodeToSave), v_message, verbosityEBLoadRaw); + } + ProcessingComplete = LoadNewFile(); + } + + if (ProcessingComplete) + { + RunCodeToSave = RunCode(CurrentFile); + m_data->CStore.Set("RunCodeToSave", RunCodeToSave); + m_data->CStore.Set("SaveProcessedFile", true); + m_data->CStore.Set("SaveEverything", true); + Log("EBLoadRaw: File completed, saving file " + CurrentFile + " with RunCode: " + std::to_string(RunCodeToSave), v_message, verbosityEBLoadRaw); + + m_data->CStore.Set("FileProcessingComplete", true); + m_data->vars.Set("StopLoop", 1); + Log("EBLoadRaw: All files have been processed, set pause flags, PMT: " + std::to_string(PMTPaused) + ", MRD: " + std::to_string(MRDPaused) + ", CTC: " + std::to_string(CTCPaused) + ", LAPPD: " + std::to_string(LAPPDPaused), v_message, verbosityEBLoadRaw); + return true; + } + + m_data->CStore.Get("PauseTankDecoding", PMTPaused); + m_data->CStore.Get("PauseMRDDecoding", MRDPaused); + m_data->CStore.Get("PauseCTCDecoding", CTCPaused); + m_data->CStore.Get("PauseLAPPDDecoding", LAPPDPaused); + + if (OrganizedFileList.size() == 0) + { + Log("EBLoadRaw: No files to process.", v_warning, verbosityEBLoadRaw); + m_data->vars.Set("StopLoop", 1); + return true; + } + if (FileCompleted || CurrentFile == "NONE") + { + Log("EBLoadRaw: Loading new file. " + OrganizedFileList.at(LoadingFileNumber), v_message, verbosityEBLoadRaw); + CurrentFile = OrganizedFileList.at(LoadingFileNumber); + RawData->Initialise(CurrentFile.c_str()); + Log("EBLoadRaw: File loaded.", v_message, verbosityEBLoadRaw); + m_data->CStore.Set("NewRawDataFileAccessed", true); + if (verbosityEBLoadRaw > 4) + RawData->Print(false); + LoadRunInfo(); + LoadPMTData(); + LoadMRDData(); + LoadCTCData(); + LoadLAPPDData(); + } + else + { + Log("EBLoadRaw: Loading next entry of current file " + CurrentFile, v_message, verbosityEBLoadRaw); + } + + FileCompleted = false; + if (JumpBecauseLAPPD) + { + FileCompleted = true; + JumpBecauseLAPPD = false; + Log("EBLoadRaw: Jumping to next file due to LAPPD data.", v_message, verbosityEBLoadRaw); + return true; + } + + // if more MRD events than VME PMT events, jump to next file + if (MRDTotalEntries > PMTTotalEntries) + { + FileCompleted = true; + Log("EBLoadRaw: Jumping to next file due to MRD entry is more than PMT entry.", v_message, verbosityEBLoadRaw); + return true; + } + + if (LoadPMT && PMTEntryNum == PMTTotalEntries) + { + Log("EBLoadRaw: ALL PMT entries Loaded.", v_message, verbosityEBLoadRaw); + PMTEntriesCompleted = true; + PMTPaused = true; + } + if (LoadMRD && MRDEntryNum == MRDTotalEntries) + { + Log("EBLoadRaw: ALL MRD entries Loaded.", v_message, verbosityEBLoadRaw); + MRDEntriesCompleted = true; + MRDPaused = true; + } + if (LoadCTC && CTCEntryNum == CTCTotalEntries) + { + Log("EBLoadRaw: ALL CTC entries Loaded.", v_message, verbosityEBLoadRaw); + CTCEntriesCompleted = true; + CTCPaused = true; + } + if (LoadLAPPD && LAPPDEntryNum == LAPPDTotalEntries) + { + Log("EBLoadRaw: ALL LAPPD entries Loaded.", v_message, verbosityEBLoadRaw); + LAPPDEntriesCompleted = true; + LAPPDPaused = true; + } + + if (LoadLAPPD && LAPPDTotalEntries < 0) + LAPPDEntriesCompleted = true; + + m_data->CStore.Set("PauseTankDecoding", PMTPaused); + m_data->CStore.Set("PauseMRDDecoding", MRDPaused); + m_data->CStore.Set("PauseCTCDecoding", CTCPaused); + m_data->CStore.Set("PauseLAPPDDecoding", LAPPDPaused); + + Log("EBLoadRaw: Set pause flags, PMT: " + std::to_string(PMTPaused) + ", MRD: " + std::to_string(MRDPaused) + ", CTC: " + std::to_string(CTCPaused) + ", LAPPD: " + std::to_string(LAPPDPaused), v_message, verbosityEBLoadRaw); + + if (LoadPMT && !PMTPaused && !PMTEntriesCompleted) + LoadNextPMTData(); + if (LoadMRD && !MRDPaused && !MRDEntriesCompleted) + LoadNextMRDData(); + if (LoadCTC && !CTCPaused && !CTCEntriesCompleted) + LoadNextCTCData(); + if (LoadLAPPD && !LAPPDPaused && !LAPPDEntriesCompleted) + LoadNextLAPPDData(); + + // if all required data is loaded, set filecompleted flag to true + if ((!LoadPMT || PMTEntriesCompleted) && (!LoadMRD || MRDEntriesCompleted) && (!LoadCTC || CTCEntriesCompleted) && (!LoadLAPPD || LAPPDEntriesCompleted)) + { + FileCompleted = true; + Log("EBLoadRaw: All data loaded.", v_message, verbosityEBLoadRaw); + } + + if (verbosityEBLoadRaw > v_message) + { + std::cout << "**************************************************EBLoadRaw: Current progress after execute: " << std::endl; + std::cout << "EBLoadRaw: Current file: " << CurrentFile << std::endl; + if (LoadPMT) + std::cout << "EBLoadRaw: PMT entries: " << PMTEntryNum << " / " << PMTTotalEntries << " = " << static_cast(PMTEntryNum) / static_cast(PMTTotalEntries) * 100 << "%" << std::endl; + if (LoadMRD) + std::cout << "EBLoadRaw: MRD entries: " << MRDEntryNum << " / " << MRDTotalEntries << " = " << static_cast(MRDEntryNum) / static_cast(MRDTotalEntries) * 100 << "%" << std::endl; + if (LoadCTC) + std::cout << "EBLoadRaw: CTC entries: " << CTCEntryNum << " / " << CTCTotalEntries << " = " << static_cast(CTCEntryNum) / static_cast(CTCTotalEntries) * 100 << "%" << std::endl; + if (LoadLAPPD) + std::cout << "EBLoadRaw: LAPPD entries: " << LAPPDEntryNum << " / " << LAPPDTotalEntries << " = " << static_cast(LAPPDEntryNum) / static_cast(LAPPDTotalEntries) * 100 << "%" << std::endl; + std::cout << "**********************************************************************************************" << std::endl; + } + + m_data->CStore.Set("MRDEntriesCompleted", MRDEntriesCompleted); + m_data->CStore.Set("PMTEntriesCompleted", PMTEntriesCompleted); + m_data->CStore.Set("CTCEntriesCompleted", CTCEntriesCompleted); + m_data->CStore.Set("LAPPDEntriesCompleted", LAPPDEntriesCompleted); + Log("EBLoadRaw: Set entries completed flags, PMT: " + std::to_string(PMTEntriesCompleted) + ", MRD: " + std::to_string(MRDEntriesCompleted) + ", CTC: " + std::to_string(CTCEntriesCompleted) + ", LAPPD: " + std::to_string(LAPPDEntriesCompleted), v_message, verbosityEBLoadRaw); + + m_data->CStore.Set("NewRawDataEntryAccessed", true); + m_data->CStore.Set("FileCompleted", FileCompleted); + + Log("EBLoadRaw: Finished execution loop.", v_message, verbosityEBLoadRaw); + return true; +} + +bool EBLoadRaw::Finalise() +{ + RawData->Close(); + RawData->Delete(); + delete RawData; + if (LoadPMT) + { + PMTData->Close(); + PMTData->Delete(); + delete PMTData; + } + if (LoadMRD) + { + MRDData->Close(); + MRDData->Delete(); + delete MRDData; + } + if (LoadLAPPD) + { + LAPPDData->Close(); + LAPPDData->Delete(); + delete LAPPDData; + } + if (LoadCTC) + { + CTCData->Close(); + CTCData->Delete(); + delete CTCData; + } + + std::cout << "\033[1;34mEBLoadRaw: Finalising EBLoadRaw\033[0m" << std::endl; + std::cout << "EBLoadRaw: Loaded " << OrganizedFileList.size() << " files " + << " from " << OrganizedFileList.at(0) << " to " << OrganizedFileList.at(OrganizedFileList.size() - 1) << std::endl; + std::cout << "EBLoadRaw: Loaded " << LoadedPMTTotalEntries << " PMT entries. " << std::endl; + std::cout << "EBLoadRaw: Loaded " << LoadedMRDTotalEntries << " MRD entries. " << std::endl; + std::cout << "EBLoadRaw: Loaded " << LoadedCTCTotalEntries << " CTC entries. " << std::endl; + std::cout << "EBLoadRaw: Loaded " << LoadedLAPPDTotalEntries << " LAPPD entries. " << std::endl; + + return true; +} + +std::vector EBLoadRaw::OrganizeRunParts(std::string FileList) +{ + std::vector OrganizedFiles; + std::vector UnorganizedFileList; + std::vector RunCodes; + int ThisRunCode; + // First, parse the lines and get all files. + std::string line; + ifstream myfile(FileList.c_str()); + if (myfile.is_open()) + { + std::cout << "Lines in FileList being printed" << std::endl; // has our stuff; + while (getline(myfile, line)) + { + if (line.find("#") != std::string::npos) + continue; + std::string filename = line; + int RunCodeNumber = RunCode(filename); + + if (RunCodeNumber != -9999) + { + UnorganizedFileList.push_back(filename); + RunCodes.push_back(RunCodeNumber); + } + + } // End parsing each line in file + + // Now, organize files based on the part number array + std::vector> SortingVector; + for (int i = 0; i < (int)UnorganizedFileList.size(); i++) + { + SortingVector.push_back(std::make_pair(RunCodes.at(i), UnorganizedFileList.at(i))); + } + std::sort(SortingVector.begin(), SortingVector.end()); + for (int j = 0; j < (int)SortingVector.size(); j++) + { + OrganizedFiles.push_back(SortingVector.at(j).second); + } + } + // print the OrganizedFiles + for (int i = 0; i < (int)OrganizedFiles.size(); i++) + { + std::cout << OrganizedFiles.at(i) << std::endl; + } + + return OrganizedFiles; +} + +int EBLoadRaw::RunCode(string fileName) +{ + // extract run number and file number from filename + std::regex runNumber_regex("RAWDataR(\\d{4})"); + std::regex subrunNumber_regex("S(\\d{1,4})p"); + std::regex rawFileNumber_regex("p(\\d{1,4})$"); + std::smatch match; + int runNumber = -9999; + int subrunNumber = -9999; + int rawFileNumber = -9999; + bool allmatched = false; + if (std::regex_search(fileName, match, runNumber_regex) && match.size() > 1) + { + runNumber = std::stoi(match.str(1)); + if (verbosityEBLoadRaw > 0) + std::cout << "runNumber: " << runNumber << std::endl; + m_data->CStore.Set("runNumber", runNumber); + allmatched = true; + } + else + { + std::cout << "runNumber not found" << std::endl; + m_data->CStore.Set("rawFileNumber", -9999); + } + + if (std::regex_search(fileName, match, subrunNumber_regex) && match.size() > 1) + { + subrunNumber = std::stoi(match.str(1)); + if (verbosityEBLoadRaw > 0) + std::cout << "subrunNumber: " << subrunNumber << std::endl; + m_data->CStore.Set("subrunNumber", subrunNumber); + allmatched = true; + } + else + { + std::cout << "subrunNumber not found" << std::endl; + m_data->CStore.Set("subrunNumber", -9999); + } + + if (std::regex_search(fileName, match, rawFileNumber_regex) && match.size() > 1) + { + rawFileNumber = std::stoi(match.str(1)); + if (verbosityEBLoadRaw > 0) + std::cout << "rawFileNumber: " << rawFileNumber << std::endl; + m_data->CStore.Set("rawFileNumber", rawFileNumber); + allmatched = true; + } + else + { + std::cout << "rawFileNumber not found" << std::endl; + m_data->CStore.Set("runNumber", -9999); + } + + if (allmatched == true) + { + int runcode = runNumber * 100000 + ((subrunNumber + 1) * 10000) + rawFileNumber; + cout << "EBLoadRaw: RunCode: " << runcode << endl; + return runcode; + } + else + { + return -9999; + } +} + +bool EBLoadRaw::LoadRunInfo() +{ + int runCode = RunCode(CurrentFile); + Log("EBLoadRaw: Loading run information, RunCode: " + std::to_string(runCode), v_message, verbosityEBLoadRaw); + + RunNumber = runCode / 100000; + SubRunNumber = (runCode % 100000) / 10000 - 1; + PartFileNumber = runCode % 10000; + + Store Postgress; + + std::cout << "EBLoadRaw: loading run information, RunNumber: " << RunNumber << ", SubRunNumber: " << SubRunNumber << ", PartFileNumber: " << PartFileNumber << std::endl; + + Postgress.Set("RunNumber", RunNumber); + Postgress.Set("SubRunNumber", SubRunNumber); + Postgress.Set("PartFileNumber", PartFileNumber); + Postgress.Set("RunType", -1); + Postgress.Set("StartTime", -1); + + m_data->CStore.Set("RunInfoPostgress", Postgress); + + m_data->CStore.Set("RunNumber", RunNumber); + m_data->CStore.Set("SubRunNumber", SubRunNumber); + m_data->CStore.Set("PartFileNumber", PartFileNumber); + m_data->CStore.Set("RunCode", runCode); + + return true; +} + +// load new file and it's related boost store +bool EBLoadRaw::LoadNewFile() +{ + bool EndOfProcessing = false; + LoadingFileNumber++; + + RawData->Close(); + RawData->Delete(); + delete RawData; + RawData = new BoostStore(false, 0); + PMTData->Close(); + PMTData->Delete(); + delete PMTData; + PMTData = new BoostStore(false, 2); + MRDData->Close(); + MRDData->Delete(); + delete MRDData; + MRDData = new BoostStore(false, 2); + LAPPDData->Close(); + LAPPDData->Delete(); + delete LAPPDData; + LAPPDData = new BoostStore(false, 2); + CTCData->Close(); + CTCData->Delete(); + delete CTCData; + CTCData = new BoostStore(false, 2); + + PMTEntryNum = 0; + MRDEntryNum = 0; + LAPPDEntryNum = 0; + CTCEntryNum = 0; + + PMTEntriesCompleted = false; + MRDEntriesCompleted = false; + LAPPDEntriesCompleted = false; + CTCEntriesCompleted = false; + + m_data->CStore.Set("PauseTankDecoding", false); + m_data->CStore.Set("PauseMRDDecoding", false); + m_data->CStore.Set("PauseCTCDecoding", false); + m_data->CStore.Set("PauseLAPPDDecoding", false); + + if (LoadingFileNumber == OrganizedFileList.size()) + { + EndOfProcessing = true; + m_data->CStore.Set("PauseTankDecoding", true); + m_data->CStore.Set("PauseMRDDecoding", true); + m_data->CStore.Set("PauseCTCDecoding", true); + m_data->CStore.Set("PauseLAPPDDecoding", true); + } + + return EndOfProcessing; +} + +bool EBLoadRaw::LoadPMTData() +{ + Log("EBLoadRaw: Loading PMTData.", v_message, verbosityEBLoadRaw); + RawData->Get("PMTData", *PMTData); + PMTData->Header->Get("TotalEntries", PMTTotalEntries); + LoadedPMTTotalEntries += PMTTotalEntries; + Log("EBLoadRaw: PMTData loaded, TotalEntries: " + std::to_string(PMTTotalEntries), v_message, verbosityEBLoadRaw); + + if (verbosityEBLoadRaw > 3) + PMTData->Print(false); + if (verbosityEBLoadRaw > 3) + PMTData->Header->Print(false); + return true; +} + +bool EBLoadRaw::LoadMRDData() +{ + Log("EBLoadRaw: Loading MRDData.", v_message, verbosityEBLoadRaw); + RawData->Get("CCData", *MRDData); + MRDData->Header->Get("TotalEntries", MRDTotalEntries); + LoadedMRDTotalEntries += MRDTotalEntries; + Log("EBLoadRaw: MRDData loaded, TotalEntries: " + std::to_string(MRDTotalEntries), v_message, verbosityEBLoadRaw); + if (verbosityEBLoadRaw > 3) + MRDData->Print(false); + return true; +} + +bool EBLoadRaw::LoadCTCData() +{ + Log("EBLoadRaw: Loading CTCData.", v_message, verbosityEBLoadRaw); + RawData->Get("TrigData", *CTCData); + if (verbosityEBLoadRaw > 3) + CTCData->Print(false); + CTCData->Header->Get("TotalEntries", CTCTotalEntries); + LoadedCTCTotalEntries += CTCTotalEntries; + if (verbosityEBLoadRaw > 3) + CTCData->Header->Print(false); + if (ReadTriggerOverlap) + { + std::stringstream ss_trigoverlap; + ss_trigoverlap << "TrigOverlap_R" << RunNumber << "S" << SubRunNumber << "p" << PartFileNumber; + std::cout << "EBLoadRaw: Loading Trigger Overlap data: " << ss_trigoverlap.str() << std::endl; + BoostStore TrigOverlapStore; + bool store_exist = TrigOverlapStore.Initialise(ss_trigoverlap.str().c_str()); + std::cout << "EBLoadRaw: Trigger Overlap store exist: " << store_exist << std::endl; + if (store_exist) + { + CTCTotalEntries++; + std::cout << "EBLoadRaw: total trigger entry with overlap is: " << CTCTotalEntries << std::endl; + } + } + return true; +} + +bool EBLoadRaw::LoadLAPPDData() +{ + Log("EBLoadRaw: Loading LAPPDData.", v_message, verbosityEBLoadRaw); + try + { + RawData->Get("LAPPDData", *LAPPDData); + LAPPDData->Header->Get("TotalEntries", LAPPDTotalEntries); + Log("EBLoadRaw: LAPPDData loaded, TotalEntries: " + std::to_string(LAPPDTotalEntries), v_message, verbosityEBLoadRaw); + if (verbosityEBLoadRaw > 3) + { + LAPPDData->Print(false); + LAPPDData->Header->Print(false); + } + if (LAPPDTotalEntries < 0) + { + + cout << "EBLoadRaw: LAPPDData entry < 0, found " << LAPPDTotalEntries << ", set to 0" << endl; + LAPPDTotalEntries = 0; + LAPPDEntriesCompleted = true; + } + else if (LAPPDTotalEntries > 100000) + { + cout << "EBLoadRaw: LAPPDData entry very large, found " << LAPPDTotalEntries << ", return and set jump because LAPPD = true" << endl; + JumpBecauseLAPPD = true; + return true; + } + LoadedLAPPDTotalEntries += LAPPDTotalEntries; + } + catch (std::exception &e) + { + std::cout << "EBLoadRaw: LAPPDData not found in file." << std::endl; + LAPPDTotalEntries = 0; + LAPPDEntriesCompleted = true; + } + Log("EBLoadRaw: LAPPDData has " + std::to_string(LAPPDTotalEntries) + " entries.", v_message, verbosityEBLoadRaw); + return true; +} + +// load next entry of the current file +bool EBLoadRaw::LoadNextPMTData() +{ + Log("EBLoadRaw: Loading next PMTData entry " + std::to_string(PMTEntryNum) + " of " + std::to_string(PMTTotalEntries), v_warning, verbosityEBLoadRaw); + PMTData->GetEntry(PMTEntryNum); + Log("EBLoadRaw: Getting the PMT card data entry", v_warning, verbosityEBLoadRaw); + PMTData->Get("CardData", *CData); + Log("EBLoadRaw: Setting into CStore", v_warning, verbosityEBLoadRaw); + m_data->CStore.Set("CardData", CData); + Log("EBLoadRaw: Setting PMT entry num to CStore", v_warning, verbosityEBLoadRaw); + m_data->CStore.Set("TankEntryNum", PMTEntryNum); + PMTEntryNum++; + + return true; +} + +bool EBLoadRaw::LoadNextMRDData() +{ + Log("EBLoadRaw: Loading next MRDData entry " + std::to_string(MRDEntryNum) + " of " + std::to_string(MRDTotalEntries), v_warning, verbosityEBLoadRaw); + MRDData->GetEntry(MRDEntryNum); + MRDData->Get("Data", *MData); + m_data->CStore.Set("MRDData", MData, true); + m_data->CStore.Set("MRDEntryNum", MRDEntryNum); + MRDEntryNum++; + return true; +} + +bool EBLoadRaw::LoadNextLAPPDData() +{ + Log("EBLoadRaw: Loading next LAPPDData entry " + std::to_string(LAPPDEntryNum) + " of " + std::to_string(LAPPDTotalEntries), v_warning, verbosityEBLoadRaw); + LAPPDData->GetEntry(LAPPDEntryNum); + LAPPDData->Get("LAPPDData", *LData); + m_data->CStore.Set("LAPPDData", LData); + m_data->CStore.Set("LAPPDEntryNum", LAPPDEntryNum); + m_data->CStore.Set("LAPPDanaData", true); + LAPPDEntryNum++; + return true; +} + +bool EBLoadRaw::LoadNextCTCData() +{ + Log("EBLoadRaw: Loading next CTCData entry " + std::to_string(CTCEntryNum) + " of " + std::to_string(CTCTotalEntries), v_warning, verbosityEBLoadRaw); + if (!ReadTriggerOverlap) + { + CTCData->GetEntry(CTCEntryNum); + CTCData->Get("TrigData", *TData); + Log("EBLoadRaw: Loaded CTCData entry " + std::to_string(CTCEntryNum), v_warning, verbosityEBLoadRaw); + } + else + { + if (CTCEntryNum != CTCTotalEntries - 1) + { + CTCData->GetEntry(CTCEntryNum); + CTCData->Get("TrigData", *TData); + m_data->CStore.Set("usingTriggerOverlap", false); + Log("EBLoadRaw: Loaded CTCData entry " + std::to_string(CTCEntryNum), v_warning, verbosityEBLoadRaw); + } + else + { + BoostStore TrigOverlapStore; + std::stringstream ss_trigoverlap; + ss_trigoverlap << "TrigOverlap_R" << RunNumber << "S" << SubRunNumber << "p" << PartFileNumber; + bool got_trig_o = TrigOverlapStore.Initialise(ss_trigoverlap.str().c_str()); + if (got_trig_o) + { + TrigOverlapStore.Get("TrigData", *TData); + m_data->CStore.Set("usingTriggerOverlap", true); + } + else + std::cout << "EBLoadRaw: Trigger Overlap data not found while loading" << std::endl; + } + m_data->CStore.Set("TrigData", TData); + + Log("EBLoadRaw: Loaded CTCData entry " + std::to_string(CTCEntryNum), v_warning, verbosityEBLoadRaw); + CTCEntryNum++; + } + return true; +} diff --git a/UserTools/EBLoadRaw/EBLoadRaw.h b/UserTools/EBLoadRaw/EBLoadRaw.h new file mode 100644 index 000000000..296e697da --- /dev/null +++ b/UserTools/EBLoadRaw/EBLoadRaw.h @@ -0,0 +1,113 @@ +#ifndef EBLoadRaw_H +#define EBLoadRaw_H + +#include +#include + +#include "Tool.h" +#include "CardData.h" +#include "TriggerData.h" +#include "PsecData.h" +#include "BoostStore.h" +#include "Store.h" + +/** + * \class EBLoadRaw + * + * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. + * + * $Author: B.Richards $ + * $Date: 2019/05/28 10:44:00 $ + * Contact: b.richards@qmul.ac.uk + */ +class EBLoadRaw : public Tool +{ + +public: + EBLoadRaw(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + + bool LoadPMTData(); + bool LoadMRDData(); + bool LoadLAPPDData(); + bool LoadCTCData(); + bool LoadRunInfo(); + + bool LoadNextPMTData(); + bool LoadNextMRDData(); + bool LoadNextLAPPDData(); + bool LoadNextCTCData(); + + bool LoadNewFile(); + int RunCode(string fileName); + std::vector OrganizeRunParts(std::string FileList); + +private: + std::string CurrentFile = "NONE"; + std::string InputFile; + std::vector OrganizedFileList; + bool ReadTriggerOverlap; + int RunCodeToSave; + + bool LoadCTC; + bool LoadPMT; + bool LoadMRD; + bool LoadLAPPD; + + int PMTTotalEntries; + int MRDTotalEntries; + int LAPPDTotalEntries; + int CTCTotalEntries; + + int LoadedPMTTotalEntries; + int LoadedMRDTotalEntries; + int LoadedLAPPDTotalEntries; + int LoadedCTCTotalEntries; + + bool ProcessingComplete; + bool FileCompleted; + bool JumpBecauseLAPPD; + bool PMTEntriesCompleted; + bool MRDEntriesCompleted; + bool LAPPDEntriesCompleted; + bool CTCEntriesCompleted; + bool usingTriggerOverlap; + + + int CTCEntryNum; + int PMTEntryNum; + int MRDEntryNum; + int LAPPDEntryNum; + int LoadingFileNumber; + + int RunNumber; + int SubRunNumber; + int PartFileNumber; + + bool PMTPaused; + bool MRDPaused; + bool LAPPDPaused; + bool CTCPaused; + + BoostStore *RawData = nullptr; + BoostStore *PMTData = nullptr; + BoostStore *MRDData = nullptr; + BoostStore *LAPPDData = nullptr; + BoostStore *CTCData = nullptr; + + std::vector *CData = nullptr; + TriggerData *TData = nullptr; + MRDOut *MData = nullptr; + PsecData *LData = nullptr; + + int verbosityEBLoadRaw; + + int v_message = 1; + int v_warning = 2; + int v_error = 3; + int v_debug = 4; +}; + +#endif diff --git a/UserTools/EBLoadRaw/README.md b/UserTools/EBLoadRaw/README.md new file mode 100644 index 000000000..12f285dc2 --- /dev/null +++ b/UserTools/EBLoadRaw/README.md @@ -0,0 +1,20 @@ +# EBLoadRaw + +EBLoadRaw + +## Data + +Describe any data formats EBLoadRaw creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for EBLoadRaw. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/EBMRD/EBMRD.cpp b/UserTools/EBMRD/EBMRD.cpp new file mode 100644 index 000000000..9fb27e9f3 --- /dev/null +++ b/UserTools/EBMRD/EBMRD.cpp @@ -0,0 +1,225 @@ +#include "EBMRD.h" + +EBMRD::EBMRD() : Tool() {} + +bool EBMRD::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + m_variables.Get("verbosityEBMRD", verbosityEBMRD); + matchTargetTrigger = 8; + m_variables.Get("matchTargetTrigger", matchTargetTrigger); + matchTolerance_ns = 2000000; // default 2ms + m_variables.Get("matchTolerance_ns", matchTolerance_ns); + exePerMatch = 500; + m_variables.Get("exePerMatch", exePerMatch); + matchToAllTriggers = 0; + m_variables.Get("matchToAllTriggers", matchToAllTriggers); + + matchedMRDNumber = 0; + + return true; +} + +bool EBMRD::Execute() +{ + m_data->CStore.Get("RunCode", currentRunCode); + + m_data->CStore.Get("MRDEvents", MRDEvents); + m_data->CStore.Get("MRDEventTriggerTypes", MRDEventTriggerTypes); + m_data->CStore.Get("MRDBeamLoopback", MRDBeamLoopback); + m_data->CStore.Get("MRDCosmicLoopback", MRDCosmicLoopback); + m_data->CStore.Get("NewMRDDataAvailable", NewMRDDataAvailable); + + m_data->CStore.Get("PairedMRDTriggerTimestamp", PairedCTCTimeStamps); + m_data->CStore.Get("PairedMRDTimeStamps", PairedMRDTimeStamps); + + Log("EBMRD: NewMRDDataAvailable = " + std::to_string(NewMRDDataAvailable) + ", Current loaded MRDEvents size is " + std::to_string(MRDEvents.size()), v_message, verbosityEBMRD); + Log("EBMRD: Current buffer size is " + std::to_string(MRDEventsBuffer.size()), v_message, verbosityEBMRD); + // loop the MRDEvents, save every event to MRDEventsBuffer if it's not already in the buffer + int newLoadedEvents = 0; + for (std::pair>> p : MRDEvents) + { + uint64_t MTCtime = p.first; + std::vector> WaveMap = p.second; + //if find the MTCtime in the PairedMRDTimeStamps, then skip + if (PairedMRDTimeStamps.size() > 0) + { + bool skip = false; + for (std::pair> pair : PairedMRDTimeStamps) + { + for (uint64_t t : pair.second) + { + if (t == MTCtime) + { + skip = true; + break; + } + } + if (skip) + break; + } + if (skip) + continue; + } + if (MRDEventsBuffer.find(MTCtime) == MRDEventsBuffer.end()) + { + MRDEventsBuffer.emplace(MTCtime, WaveMap); + newLoadedEvents++; + } + } + Log("EBMRD: Finished loading MRDEvents to buffer, Buffer_MRDEvents size is now " + std::to_string(MRDEventsBuffer.size()) + " new loaded events = " + std::to_string(newLoadedEvents), v_message, verbosityEBMRD); + + bool stopLoop = false; + m_data->vars.Get("StopLoop", stopLoop); + int runNum = thisRunNum; + m_data->vars.Get("RunNumber", thisRunNum); + + if (exeNum % exePerMatch == 0 || runNum != thisRunNum || stopLoop) + { + Log("EBMRD: exeNum = " + std::to_string(exeNum) + ". Doing matching now", v_message, verbosityEBMRD); + if (matchToAllTriggers) + { + Matching(0, 0); + } + else + { + bool BeamTriggerGroupped = false; + m_data->CStore.Get("BeamTriggerGroupped", BeamTriggerGroupped); + bool CosmicTriggerGroupped = false; + m_data->CStore.Get("CosmicTriggerGroupped", CosmicTriggerGroupped); + if (BeamTriggerGroupped) + Matching(matchTargetTrigger, 14); + else if (CosmicTriggerGroupped) + Matching(36, 36); + else + Log("EBMRD: BeamTriggerGroupped and CosmicTriggerGroupped are false, no beam trigger groupped in the grouper, stop matching", v_message, verbosityEBMRD); + } + } + + m_data->CStore.Set("PairedMRDTriggerTimestamp", PairedCTCTimeStamps); + m_data->CStore.Set("PairedMRDTimeStamps", PairedMRDTimeStamps); + m_data->CStore.Set("PairedMRD_TriggerIndex", PairedMRD_TriggerIndex); + m_data->CStore.Set("MRDHitMapRunCode", MRDHitMapRunCode); + + exeNum++; + return true; +} + +bool EBMRD::Finalise() +{ + Log("\033[1;34mEBMRD: Finalising\033[0m", v_message, verbosityEBMRD); + Log("EBMRD: Matched MRD number = " + std::to_string(matchedMRDNumber), v_message, verbosityEBMRD); + Log("EBMRD: Unmatched MRD number = " + std::to_string(MRDEventsBuffer.size()), v_message, verbosityEBMRD); + return true; +} + +bool EBMRD::Matching(int targetTrigger, int matchToTrack) +{ + cout << "\033[1;34m******* EBMRD : Matching *******\033[0m" << endl; + std::map>> GroupedTriggersInTotal; // each map is a group of triggers, with the key is the target trigger word + m_data->CStore.Get("GroupedTriggersInTotal", GroupedTriggersInTotal); + + Log("EBMRD: Got GroupedTriggersInTotal[14] size: " + std::to_string(GroupedTriggersInTotal[14].size()), v_message, verbosityEBMRD); + + vector matchedMRDTimes; + std::map matchedNumberInTrack; + + // loop the MRDEventsBuffer keys, and loop all the grouped triggers + // in each group of trigger, find the target trigger word and it's time + // fine the minimum time difference, if smaller than matchTolerance_ns, then save the time to PairedCTCTimeStamps and PairedMRDTimeStamps + int loopNum = 0; + for (std::pair>> mrdpair : MRDEventsBuffer) + { + if (verbosityEBMRD > 11) + cout << "******************EBMRD: new MRD event: " << loopNum << endl; + uint64_t MTCtime = mrdpair.first; + std::vector> WaveMap = mrdpair.second; + // set minDT to 5 min + uint64_t minDT = 5 * 60 * 1e9; + uint64_t minDTTrigger = 0; + uint64_t dt = 0; + uint32_t matchedTrigWord = 0; + int matchedTrack = 0; + int matchedIndex = 0; + for (std::pair>> pair : GroupedTriggersInTotal) + { + int TrackTriggerWord = pair.first; + if (TrackTriggerWord != matchToTrack && !matchToAllTriggers) + { + Log("EBMRD: Skipping TrackTriggerWord " + std::to_string(TrackTriggerWord), v_debug, verbosityEBMRD); + continue; + } + if(matchedNumberInTrack.find(TrackTriggerWord) == matchedNumberInTrack.end()) + matchedNumberInTrack.emplace(TrackTriggerWord, 0); + + vector> groupedTriggers = pair.second; + + for (int i = 0; i < groupedTriggers.size(); i++) + { + map groupedTrigger = groupedTriggers.at(i); + // itearte over all the grouped triggers, if the value is target trigger, then calculate the time difference + for (std::pair p : groupedTrigger) + { + if (matchToAllTriggers || p.second == targetTrigger) + { + if (MTCtime > p.first) + { + dt = MTCtime - p.first; + } + else + { + dt = p.first - MTCtime; + } + if (dt < minDT) + { + minDT = dt; + minDTTrigger = p.first; + matchedTrigWord = p.second; + matchedIndex = p.second; + matchedTrack = TrackTriggerWord; + + // if(verbosityEBMRD > 11) cout<<"EBMRD: dt: "< pair : matchedNumberInTrack) + { + Log("EBMRD: Match finished, matched number in Track " + std::to_string(pair.first) + " is " + std::to_string(pair.second), v_message, verbosityEBMRD); + } + + return true; +} \ No newline at end of file diff --git a/UserTools/EBMRD/EBMRD.h b/UserTools/EBMRD/EBMRD.h new file mode 100644 index 000000000..aa53269ab --- /dev/null +++ b/UserTools/EBMRD/EBMRD.h @@ -0,0 +1,65 @@ +#ifndef EBMRD_H +#define EBMRD_H + +#include +#include + +#include "Tool.h" + +/** + * \class EBMRD + * + * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. + * + * $Author: B.Richards $ + * $Date: 2019/05/28 10:44:00 $ + * Contact: b.richards@qmul.ac.uk + */ +class EBMRD : public Tool +{ + +public: + EBMRD(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + bool Matching(int targetTrigger, int matchToTrack); + +private: + int verbosityEBMRD; + int matchTargetTrigger; + uint64_t matchTolerance_ns; + + int currentRunCode; + + int v_message = 1; + int v_warning = 2; + int v_error = 3; + int v_debug = 4; + + int matchedMRDNumber = 0; + int exeNum = 0; + + std::map>> MRDEvents; // Key: {MTCTime}, value: "WaveMap" with key (CardID,ChannelID), value FinishedWaveform + std::map MRDEventTriggerTypes; // Key: {MTCTime}, value: string noting what type of trigger occured for the event + std::map MRDBeamLoopback; // Key: {MTCTime}, value: string noting what type of trigger occured for the event + std::map MRDCosmicLoopback; // KEY: {MTCTime}, value: Cosmic loopback TDC value + + std::map>> MRDEventsBuffer; + + bool NewMRDDataAvailable; + + std::map> PairedCTCTimeStamps; + std::map> PairedMRD_TriggerIndex; + std::map> PairedMRDTimeStamps; + std::map MRDHitMapRunCode; // Key: {MTCTime}, value: RunCode + + + + bool matchToAllTriggers; + + int thisRunNum; + int exePerMatch; +}; + +#endif diff --git a/UserTools/EBMRD/README.md b/UserTools/EBMRD/README.md new file mode 100644 index 000000000..693dd242f --- /dev/null +++ b/UserTools/EBMRD/README.md @@ -0,0 +1,20 @@ +# EBMRD + +EBMRD + +## Data + +Describe any data formats EBMRD creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for EBMRD. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/EBPMT/EBPMT.cpp b/UserTools/EBPMT/EBPMT.cpp new file mode 100644 index 000000000..b0cd4dd53 --- /dev/null +++ b/UserTools/EBPMT/EBPMT.cpp @@ -0,0 +1,425 @@ +#include "EBPMT.h" + +EBPMT::EBPMT() : Tool() {} + +bool EBPMT::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + m_variables.Get("verbosityEBPMT", verbosityEBPMT); + matchTargetTrigger = 5; + m_variables.Get("matchTargetTrigger", matchTargetTrigger); + matchTolerance_ns = 200; // default 200ns + m_variables.Get("matchTolerance_ns", matchTolerance_ns); + exePerMatch = 500; + m_variables.Get("exePerMatch", exePerMatch); + matchToAllTriggers = false; + m_variables.Get("matchToAllTriggers", matchToAllTriggers); + + NumWavesInCompleteSet = 140; + + FinishedHits = new std::map> *>(); + + return true; +} + +bool EBPMT::Execute() +{ + m_data->CStore.Get("RunCode", currentRunCode); + bool gotHits = m_data->CStore.Get("InProgressHits", InProgressHits); + bool gotChkey = m_data->CStore.Get("InProgressChkey", InProgressChkey); + + if (exeNum % 80 == 0 && exeNum!=0) + { + //80 is arbitrary, because 6*80 = 480 around, close, and smaller than the pairing exe number, exePerMatch default 500 + Log("EBPMT: exeNum: " + std::to_string(exeNum) + " Before loading, apply a VMEOffset correction", v_message, verbosityEBPMT); + Log("EBPMT: before apply the VME offset correction, the size of FinishedHits is " + std::to_string(FinishedHits->size()), v_message, verbosityEBPMT); + m_data->CStore.Get("InProgressHitsAux", InProgressHitsAux); + m_data->CStore.Get("InProgressRecoADCHits", InProgressRecoADCHits); + m_data->CStore.Get("InProgressRecoADCHitsAux", InProgressRecoADCHitsAux); + CorrectVMEOffset(); + m_data->CStore.Set("InProgressHits", InProgressHits); + m_data->CStore.Set("InProgressChkey", InProgressChkey); + m_data->CStore.Set("InProgressHitsAux", InProgressHitsAux); + m_data->CStore.Set("InProgressRecoADCHits", InProgressRecoADCHits); + m_data->CStore.Set("InProgressRecoADCHitsAux", InProgressRecoADCHitsAux); + } + + m_data->CStore.Get("PairedPMTTriggerTimestamp", PairedCTCTimeStamps); + m_data->CStore.Get("PairedPMTTimeStamps", PairedPMTTimeStamps); + Log("EBPMT: Got PairedPMTTimeStamps size: " + std::to_string(PairedPMTTimeStamps.size()), v_message, verbosityEBPMT); + Log("EBPMT: Got PairedPMTTriggerTimestamp size: " + std::to_string(PairedCTCTimeStamps.size()), v_message, verbosityEBPMT); + + Log("EBPMT: gotHits = " + std::to_string(gotHits) + " gotChkey = " + std::to_string(gotChkey), v_message, verbosityEBPMT); + if (!gotHits || !gotChkey) + { + Log("EBPMT: No InProgressHits or InProgressChkey found", v_message, verbosityEBPMT); + return true; + } + + Log("EBPMT: got inprogress hits and chkey with size " + std::to_string(InProgressHits->size()) + " and " + std::to_string(InProgressChkey->size()), v_message, verbosityEBPMT); + + vector PMTEmplacedHitTimes; + + for (std::pair> *> p : *InProgressHits) + { + uint64_t PMTCounterTimeNs = p.first; + std::map> *hitMap = p.second; + vector ChannelKey = InProgressChkey->at(PMTCounterTimeNs); + + Log("EBPMT: PMTCounterTimeNs: " + std::to_string(PMTCounterTimeNs), v_debug, verbosityEBPMT); + Log("EBPMT: hitMap size: " + std::to_string(hitMap->size()), v_debug, verbosityEBPMT); + Log("EBPMT: ChannelKey vector size: " + std::to_string(ChannelKey.size()), v_debug, verbosityEBPMT); + Log("EBPMT: Current unfinished InProgressHits size: " + std::to_string(InProgressHits->size()), v_debug, verbosityEBPMT); + + if (static_cast(ChannelKey.size()) > MaxObservedNumWaves) + MaxObservedNumWaves = ChannelKey.size(); + if (InProgressHits->size() > 500 && MaxObservedNumWaves < NumWavesInCompleteSet && !max_waves_adapted && MaxObservedNumWaves >= 130) + { + NumWavesInCompleteSet = MaxObservedNumWaves; + max_waves_adapted = true; + Log("EBPMT: MaxObservedNumWaves = " + std::to_string(MaxObservedNumWaves), v_message, verbosityEBPMT); + Log("EBPMT: NumWavesInCompleteSet = " + std::to_string(NumWavesInCompleteSet), v_message, verbosityEBPMT); + } + + if (MaxObservedNumWaves > NumWavesInCompleteSet) + NumWavesInCompleteSet = MaxObservedNumWaves; + + if (ChannelKey.size() == (NumWavesInCompleteSet - 1)) + { + Log("EBPMT: ChannelKey.size() = " + std::to_string(ChannelKey.size()) + " == NumWavesInCompleteSet - 1 = " + std::to_string(NumWavesInCompleteSet - 1), v_debug, verbosityEBPMT); + if (AlmostCompleteWaveforms.find(PMTCounterTimeNs) != AlmostCompleteWaveforms.end()) + { + Log("EBPMT: AlmostCompleteWaveforms size = " + std::to_string(AlmostCompleteWaveforms.size()), v_debug, verbosityEBPMT); + AlmostCompleteWaveforms[PMTCounterTimeNs]++; + } + else + AlmostCompleteWaveforms.emplace(PMTCounterTimeNs, 0); + Log("EBPMT: AlmostCompleteWaveforms adding PMTCounterTimeNs = " + std::to_string(PMTCounterTimeNs) + " to " + std::to_string(AlmostCompleteWaveforms[PMTCounterTimeNs]), v_debug, verbosityEBPMT); + } + + Log("EBPMT: ChannelKey.size() = " + std::to_string(ChannelKey.size()) + " >= NumWavesInCompleteSet = " + std::to_string(NumWavesInCompleteSet) + " or AlmostCompleteWaveforms.at(PMTCounterTimeNs) = " + std::to_string(AlmostCompleteWaveforms[PMTCounterTimeNs] >= 5), v_debug, verbosityEBPMT); + + if (ChannelKey.size() >= NumWavesInCompleteSet || ((ChannelKey.size() == NumWavesInCompleteSet - 1) && (AlmostCompleteWaveforms[PMTCounterTimeNs] >= 5))) + { + Log("EBPMT: Emplace hit map to FinishedHits, ChannelKey.size() = " + std::to_string(ChannelKey.size()) + " >= NumWavesInCompleteSet = " + std::to_string(NumWavesInCompleteSet) + " or AlmostCompleteWaveforms.at(PMTCounterTimeNs) = " + std::to_string(AlmostCompleteWaveforms.at(PMTCounterTimeNs) >= 5), v_debug, verbosityEBPMT); + + // check if the PMTCounterTimeNs is already in the FinishedHits, if not then add it + + if (FinishedHits->find(PMTCounterTimeNs) != FinishedHits->end()) + { + Log("EBPMT: PMTCounterTimeNs: " + std::to_string(PMTCounterTimeNs) + " already in FinishedHits", v_debug, verbosityEBPMT); + continue; + } + // if find PMTCounterTimeNs in PairedPMTTimeStamps, then skip this hit + if (PairedPMTTimeStamps.size() > 0) + { + bool skip = false; + for (std::pair> p : PairedPMTTimeStamps) + { + vector PMTTimeStamps = p.second; + for (uint64_t PMTTimeStamp : PMTTimeStamps) + { + if (PMTCounterTimeNs == PMTTimeStamp) + { + skip = true; + break; + } + } + if (skip) + break; + } + if (skip) + continue; + } + FinishedHits->emplace(PMTCounterTimeNs, hitMap); + + PMTEmplacedHitTimes.push_back(PMTCounterTimeNs); + + std::map, int> aWaveMapSampleSize; + + // Put PMT timestamp into the timestamp set for this run. + Log("EBPMT: waveset has clock counter: " + std::to_string(PMTCounterTimeNs), v_debug, verbosityEBPMT); + } + + if ((ChannelKey.size() == NumWavesInCompleteSet - 1)) + { + if (AlmostCompleteWaveforms.at(PMTCounterTimeNs) >= 5) + AlmostCompleteWaveforms.erase(PMTCounterTimeNs); + } + } + + Log("EBPMT: InProgressHits size: " + std::to_string(InProgressHits->size()) + " InProgressChkey size: " + std::to_string(InProgressChkey->size()), v_message, verbosityEBPMT); + Log("EBPMT: PMTEmplacedHitTimes size: " + std::to_string(PMTEmplacedHitTimes.size()), v_message, verbosityEBPMT); + /*for (uint64_t PMTCounterTimeNs : PMTEmplacedHitTimes) + { + InProgressHits->erase(PMTCounterTimeNs); + InProgressChkey->erase(PMTCounterTimeNs); + }*/ + Log("EBPMT: InProgressHits size: " + std::to_string(InProgressHits->size()) + " InProgressChkey size: " + std::to_string(InProgressChkey->size()), v_message, verbosityEBPMT); + + // If this InProgressTankEvent is too old, clear it + Log("EBPMT: Current number of unfinished hitmaps in InProgressHits: " + std::to_string(InProgressHits->size()), v_debug, verbosityEBPMT); + + Log("EBPMT: All finished, left size are, matchedHitNumber: " + std::to_string(matchedHitNumber) + " InProgressHits: " + std::to_string(InProgressHits->size()) + " FinishedHits: " + std::to_string(FinishedHits->size()), v_message, verbosityEBPMT); + + if (exeNum % 80 == 0) + { + Log("EBPMT: after apply the VME offset correction and loading, the size of FinishedHits is " + std::to_string(FinishedHits->size()), v_message, verbosityEBPMT); + } + + + exeNum++; + + if (exeNum % 50 == 0) + { + Log("EBPMT: exeNum: " + std::to_string(exeNum), v_message, verbosityEBPMT); + } + + bool stopLoop = false; + m_data->vars.Get("StopLoop", stopLoop); + int runNum = thisRunNum; + m_data->vars.Get("RunNumber", thisRunNum); + if (exeNum % exePerMatch == 0 || runNum != thisRunNum || stopLoop) + { + Log("EBPMT: exeNum: " + std::to_string(exeNum) + " Doing Matching", v_message, verbosityEBPMT); + if (matchToAllTriggers) + { + Matching(0, 0); + } + else + { + bool BeamTriggerGroupped = false; + m_data->CStore.Get("BeamTriggerGroupped", BeamTriggerGroupped); + if (BeamTriggerGroupped) + Matching(5, 14); + else + Log("EBPMT: BeamTriggerGroupped is false, no beam trigger groupped in the grouper, stop matching", v_message, verbosityEBPMT); + } + } + + m_data->CStore.Set("PairedPMTTriggerTimestamp", PairedCTCTimeStamps); + m_data->CStore.Set("PairedPMTTimeStamps", PairedPMTTimeStamps); + m_data->CStore.Set("PairedPMT_TriggerIndex", PairedPMT_TriggerIndex); + m_data->CStore.Set("PMTHitmapRunCode", PMTHitmapRunCode); + // everytime change the trigger group, also update the trigger index. + Log("EBPMT: Set PairedPMTTimeStamps size: " + std::to_string(PairedPMTTimeStamps.size()), v_message, verbosityEBPMT); + Log("EBPMT: Set PairedPMTTriggerTimestamp size: " + std::to_string(PairedCTCTimeStamps.size()), v_message, verbosityEBPMT); + + return true; +} + +bool EBPMT::Finalise() +{ + + Log("\033[1;34mEBPMT: Finalising\033[0m", v_message, verbosityEBPMT); + Log("EBPMT: Matched Hit Map Entry Number: " + std::to_string(matchedHitNumber), v_message, verbosityEBPMT); + Log("EBPMT: Unmatched Hit Map Entry Number left: " + std::to_string(FinishedHits->size()), v_message, verbosityEBPMT); + + return true; +} + +bool EBPMT::Matching(int targetTrigger, int matchToTrack) +{ + cout << "\033[1;34m******* EBPMT : Matching *******\033[0m" << endl; + std::map>> GroupedTriggersInTotal; // each map is a group of triggers, with the key is the target trigger word + m_data->CStore.Get("GroupedTriggersInTotal", GroupedTriggersInTotal); + + vector matchedHitTimes; + // loop over all the Hits, for each FinishedHits, loop all grouped triggers, if the time differencs<100 for trigger 5, + // matchedHitNumber ++, then remove the hit from the map + int loopNum = 0; + for (std::pair> *> pmtpair : *FinishedHits) + { + if (verbosityEBPMT > 11) + cout << "******************EBPMT: new hit" << endl; + uint64_t PMTCounterTimeNs = pmtpair.first; + std::map> *hitMap = pmtpair.second; + // set minDT to 5 min + uint64_t minDT = 5 * 60 * 1e9; + uint64_t minDTTrigger = 0; + uint64_t dt = 0; + uint32_t matchedTrigWord = 0; + int matchedTrack = 0; + int matchedIndex = 0; + // loop all tracks of GroupedTriggersInTotal + for (std::pair>> pair : GroupedTriggersInTotal) + { + int TrackTriggerWord = pair.first; + if (TrackTriggerWord != matchToTrack && !matchToAllTriggers) + continue; + + vector> groupedTriggers = pair.second; + + // loop all the grouped triggers, if the value is target trigger, then calculate the time difference + for (int i = 0; i < groupedTriggers.size(); i++) + { + map groupedTrigger = groupedTriggers.at(i); + // itearte over all the grouped triggers, if the value is target trigger, then calculate the time difference + for (std::pair p : groupedTrigger) + { + if (matchToAllTriggers || p.second == targetTrigger) + { + if (PMTCounterTimeNs > p.first) + { + dt = PMTCounterTimeNs - p.first; + } + else + { + dt = p.first - PMTCounterTimeNs; + } + if (dt < minDT) + { + minDT = dt; + minDTTrigger = p.first; + matchedTrigWord = p.second; + matchedTrack = TrackTriggerWord; + matchedIndex = i; + } + } + } + } + } + + Log("EBPMT: looping hit " + std::to_string(loopNum) + ", minDT: " + std::to_string(minDT) + ", minDTTrigger time: " + std::to_string(minDTTrigger) + " with word " + std::to_string(matchedTrigWord) + ", in trigger track " + std::to_string(matchedTrack), v_warning, verbosityEBPMT); + if (minDT < matchTolerance_ns) + { + PairedCTCTimeStamps[matchedTrack].push_back(minDTTrigger); + PairedPMTTimeStamps[matchedTrack].push_back(PMTCounterTimeNs); + PairedPMT_TriggerIndex[matchedTrack].push_back(matchedIndex); + + // the pmt hit map with timestmap PMTCounterTimeNs, match to trigger with timestamp minDTTrigger + // the matched trigger is at matchedIndex of that trigger track + + matchedHitNumber++; + matchedHitTimes.push_back(PMTCounterTimeNs); + // FinishedHits->erase(PMTCounterTimeNs); + Log("EBPMT: Matched Hit to trigger " + std::to_string(matchedTrigWord) + " at PMTCounterTimeNs: " + std::to_string(PMTCounterTimeNs) + " to TriggerTime: " + std::to_string(minDTTrigger) + " with minDT: " + std::to_string(minDT) + ", in trigger track " + std::to_string(matchedTrack) + ", in trigger index " + std::to_string(matchedIndex), v_message, verbosityEBPMT); + } + else + { + Log("EBPMT: Match failed, found min diff Hit to trigger " + std::to_string(matchedTrigWord) + " at PMTCounterTimeNs: " + std::to_string(PMTCounterTimeNs) + " to TriggerTime: " + std::to_string(minDTTrigger) + " with minDT: " + std::to_string(minDT) + ", in trigger track " + std::to_string(matchedTrack) + ", in trigger index " + std::to_string(matchedIndex), v_message, verbosityEBPMT); + } + loopNum++; + } + Log("EBPMT: total matchedHitNumber: " + std::to_string(matchedHitNumber), v_message, verbosityEBPMT); + Log("EBPMT: Current number of unfinished hitmaps after match in InProgressHits: " + std::to_string(InProgressHits->size()), v_message, verbosityEBPMT); + + Log("EBPMT: Found matched hits: " + std::to_string(matchedHitTimes.size()), v_message, verbosityEBPMT); + Log("EBPMT: before erase, left number of unfinished hitmaps in FinishedHits: " + std::to_string(FinishedHits->size()), v_message, verbosityEBPMT); + for (uint64_t PMTCounterTimeNs : matchedHitTimes) + { + FinishedHits->erase(PMTCounterTimeNs); + } + Log("EBPMT: after erase, left number of unfinished hitmaps in FinishedHits: " + std::to_string(FinishedHits->size()), v_message, verbosityEBPMT); + + return true; +} + +void EBPMT::CorrectVMEOffset() +{ + Log("EBPMT: Correcting VME Offset", v_message, verbosityEBPMT); + vector timestamps; // all current timestamps + std::map timestamps_to_shift; // timestamps need to be shifted + + //if InProgressHits size is 0, return + if (InProgressHits->size() == 0) + { + Log("EBPMT: InProgressHits size is 0, return", v_message, verbosityEBPMT); + return; + } + + //insert the key of std::map> *> *InProgressHits; to timestamps + for (std::pair> *> p : *InProgressHits) + { + timestamps.push_back(p.first); + } + + Log("EBPMT: Found " + std::to_string(timestamps.size()) + " timestamps", v_message, verbosityEBPMT); + + // loop timestamps,对于æ¯ä¸€ä¸ªæ—¶é—´æˆ³ï¼Œæ£€æŸ¥å®ƒä¸Žå®ƒä¹‹å‰çš„æ—¶é—´æˆ³çš„å·®å€¼æ˜¯å¦æ˜¯8或者16 + // 如果是,获得InProgressHits在这两个时间戳上的mapçš„size + // 在timestamps_to_shift中记录pair,第一个时间戳是size较å°çš„那个,第二个是较大的那个 + for (int i = 1; i < timestamps.size(); i++) + { + uint64_t dt = (timestamps[i] > timestamps[i - 1]) ? (timestamps[i] - timestamps[i - 1]) : (timestamps[i - 1] - timestamps[i]); + Log("EBPMT: Found two timestamps with difference = " + std::to_string(dt) + "ns", v_message, verbosityEBPMT); + Log("EBPMT: timestamps[i - 1] = " + std::to_string(timestamps[i - 1]) + " timestamps[i] = " + std::to_string(timestamps[i]), v_message, verbosityEBPMT); + if (dt == 8 || dt == 16) + { + uint64_t FirstMapSize = InProgressHits->at(timestamps[i - 1])->size(); + uint64_t SecondMapSize = InProgressHits->at(timestamps[i])->size(); + Log("EBPMT: Found two timestamps with 8 or 16ns difference, FirstMapSize: " + std::to_string(FirstMapSize) + " SecondMapSize: " + std::to_string(SecondMapSize), v_message, verbosityEBPMT); + if (FirstMapSize < SecondMapSize) + { + timestamps_to_shift.emplace(timestamps[i - 1], timestamps[i]); + } + else + { + timestamps_to_shift.emplace(timestamps[i], timestamps[i - 1]); + } + } + else if (dt < 1600) + { + Log("EBPMT: Found two timestamps with difference = " + std::to_string(dt) + "ns", v_message, verbosityEBPMT); + continue; + } + } + + int correctionApplied = 0; + Log("EBPMT: Found " + std::to_string(timestamps_to_shift.size()) + " timestamps to shift", v_message, verbosityEBPMT); + // go through timestamps_to_shift, for each pair, shift the hit map in the first smaller timestamp to the second larger timestamp + // apply on InProgressHits, InProgressHitsAux, InProgressChkey, InProgressRecoADCHits, InProgressRecoADCHitsAux + if (InProgressHitsAux != NULL && InProgressRecoADCHitsAux != NULL) + { // InProgressHitsAux,InProgressRecoADCHitsAux may not exist yet + for (std::map::iterator it = timestamps_to_shift.begin(); it != timestamps_to_shift.end(); it++) + { + uint64_t SmallerMapTS = it->first; + uint64_t LargerMapTS = it->second; + Log("EBPMT::CorrectVMEOffset: Map Timestamp " + std::to_string(SmallerMapTS) + " to timestamp " + std::to_string(LargerMapTS), v_debug, verbosityEBPMT); + if (InProgressHits->count(SmallerMapTS) == 0 || InProgressHits->count(LargerMapTS) == 0) + { // map object at FirstTS, SecondTS may not exist yet + Log("EBPMT::CorrectVMEOffset: InProgressHits->count(FirstTS) == " + std::to_string(InProgressHits->count(SmallerMapTS)) + ", InProgressHits->count(SecondTS) == " + std::to_string(InProgressHits->count(LargerMapTS)), v_debug, verbosityEBPMT); + break; + } + // Get InProgress* {Hits, Chkey, and RecoADCHits} objects + std::map> *FirstTankHits = InProgressHits->at(SmallerMapTS); + std::map> *SecondTankHits = InProgressHits->at(LargerMapTS); + std::vector FirstChankey = InProgressChkey->at(SmallerMapTS); + std::vector SecondChankey = InProgressChkey->at(LargerMapTS); + std::map> *FirstTankHitsAux = InProgressHitsAux->at(SmallerMapTS); + std::map> *SecondTankHitsAux = InProgressHitsAux->at(LargerMapTS); + std::map>> FirstRecoADCHits = InProgressRecoADCHits->at(SmallerMapTS); + std::map>> SecondRecoADCHits = InProgressRecoADCHits->at(LargerMapTS); + std::map>> FirstRecoADCHitsAux = InProgressRecoADCHitsAux->at(SmallerMapTS); + std::map>> SecondRecoADCHitsAux = InProgressRecoADCHitsAux->at(LargerMapTS); + + SecondTankHits->insert(FirstTankHits->begin(), FirstTankHits->end()); + SecondChankey.insert(SecondChankey.end(), FirstChankey.begin(), FirstChankey.end()); + SecondTankHitsAux->insert(FirstTankHitsAux->begin(), FirstTankHitsAux->end()); + SecondRecoADCHits.insert(FirstRecoADCHits.begin(), FirstRecoADCHits.end()); + SecondRecoADCHitsAux.insert(FirstRecoADCHitsAux.begin(), FirstRecoADCHitsAux.end()); + + (*InProgressHits)[LargerMapTS] = SecondTankHits; + InProgressHits->erase(SmallerMapTS); + (*InProgressChkey)[LargerMapTS] = SecondChankey; + InProgressChkey->erase(SmallerMapTS); + (*InProgressHitsAux)[LargerMapTS] = SecondTankHitsAux; + InProgressHitsAux->erase(SmallerMapTS); + (*InProgressRecoADCHits)[LargerMapTS] = SecondRecoADCHits; + InProgressRecoADCHits->erase(SmallerMapTS); + (*InProgressRecoADCHitsAux)[LargerMapTS] = SecondRecoADCHitsAux; + InProgressRecoADCHitsAux->erase(SmallerMapTS); + + correctionApplied++; + } + } + Log("EBPMT: Corrected VME Offset for " + std::to_string(correctionApplied) + " timestamps", v_message, verbosityEBPMT); +} \ No newline at end of file diff --git a/UserTools/EBPMT/EBPMT.h b/UserTools/EBPMT/EBPMT.h new file mode 100644 index 000000000..0a6242f7a --- /dev/null +++ b/UserTools/EBPMT/EBPMT.h @@ -0,0 +1,73 @@ +#ifndef EBPMT_H +#define EBPMT_H + +#include +#include + +#include "Tool.h" +#include "Hit.h" +#include "ADCPulse.h" + +/** + * \class EBPMT + * + * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. + * + * $Author: B.Richards $ + * $Date: 2019/05/28 10:44:00 $ + * Contact: b.richards@qmul.ac.uk + */ +class EBPMT : public Tool +{ + +public: + EBPMT(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + bool Matching(int targetTrigger, int matchToTrack); + void CorrectVMEOffset(); + +private: + int verbosityEBPMT; + int matchTargetTrigger; + uint64_t matchTolerance_ns; + + int currentRunCode; + + std::map>*> *FinishedHits; //Key: {MTCTime}, value: map of Hit distributions + + std::map AlmostCompleteWaveforms; + + std::map> *> *InProgressHits; // Key: {MTCTime}, value: map of Hit distributions + std::map> *InProgressChkey; // Key: {MTCTime}, value: vector of in progress chankeys + + //only used for VME offset correction + std::map> *> *InProgressHitsAux; // Key: {MTCTime}, value: map of Hit distributions + std::map>>> *InProgressRecoADCHits; // Key: {MTCTime}, value: map of found pulses + std::map>>> *InProgressRecoADCHitsAux; // Key: {MTCTime}, value: map of found pulses + + + std::map> PairedCTCTimeStamps; + std::map> PairedPMT_TriggerIndex; + std::map> PairedPMTTimeStamps; + std::map PMTHitmapRunCode; // Key: {MTCTime}, value: RunCode + + + int v_message = 1; + int v_warning = 2; + int v_error = 3; + int v_debug = 4; + + int MaxObservedNumWaves = 0; + int NumWavesInCompleteSet = 140; + bool max_waves_adapted = false; + + int matchedHitNumber = 0; + int exeNum = 0; + int thisRunNum; + int exePerMatch = 500; + bool matchToAllTriggers; +}; + +#endif diff --git a/UserTools/EBPMT/README.md b/UserTools/EBPMT/README.md new file mode 100644 index 000000000..131118613 --- /dev/null +++ b/UserTools/EBPMT/README.md @@ -0,0 +1,20 @@ +# EBPMT + +EBPMT + +## Data + +Describe any data formats EBPMT creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for EBPMT. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/EBSaver/EBSaver.cpp b/UserTools/EBSaver/EBSaver.cpp new file mode 100644 index 000000000..ad029ef07 --- /dev/null +++ b/UserTools/EBSaver/EBSaver.cpp @@ -0,0 +1,1150 @@ +#include "EBSaver.h" + +EBSaver::EBSaver() : Tool() {} + +bool EBSaver::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + m_variables.Get("verbosityEBSaver", verbosityEBSaver); + savePath = ""; + m_variables.Get("savePath", savePath); + saveName = "ProcessedData_"; + m_variables.Get("saveName", saveName); + + saveTriggerGroups = true; + savePMT = true; + + saveAllTriggers = false; + m_variables.Get("saveAllTriggers", saveAllTriggers); + saveMRD = true; + m_variables.Get("saveMRD", saveMRD); + saveLAPPD = true; + m_variables.Get("saveLAPPD", saveLAPPD); + saveOrphan = true; + m_variables.Get("saveOrphan", saveOrphan); + + ANNIEEvent = new BoostStore(false, 2); + + exeNumber = 0; + savedTriggerGroupNumber = 0; + savedPMTHitMapNumber = 0; + savedMRDNumber = 0; + savedLAPPDNumber = 0; + + savePerExe = 2000; + + if (savePMT) + saveName += "PMT"; + if (saveMRD) + saveName += "MRD"; + if (saveLAPPD) + saveName += "LAPPD"; + + m_data->CStore.Get("BeamTriggerMain", BeamTriggerMain); + m_data->CStore.Get("LaserTriggerMain", LaserTriggerMain); + m_data->CStore.Get("CosmicTriggerMain", CosmicTriggerMain); + m_data->CStore.Get("LEDTriggerMain", LEDTriggerMain); + m_data->CStore.Get("AmBeTriggerMain", AmBeTriggerMain); + m_data->CStore.Get("PPSMain", PPSMain); + + InProgressHits = new std::map> *>; + InProgressChkey = new std::map>; + InProgressRecoADCHits = new std::map>>>; + InProgressRecoADCHitsAux = new std::map>>>; + InProgressHitsAux = new std::map> *>; + FinishedRawAcqSize = new std::map>>; + + return true; +} + +bool EBSaver::Execute() +{ + + bool saveProcessedFile = false; + bool saveEverything = false; + m_data->CStore.Get("SaveProcessedFile", saveProcessedFile); + m_data->CStore.Get("SaveEverything", saveEverything); + if (!saveProcessedFile && !saveEverything) + { + Log("EBSaver: Not saving data in this exe", v_message, verbosityEBSaver); + return true; + } + cout << "\033[1;34m******* EBSaver : Start execute *******\033[0m" << endl; + + m_data->CStore.Get("RunCodeToSave", savingRunCode); + GotAllDataFromOriginalBuffer(); + + Log("EBSaver: Start saving data for run code " + std::to_string(savingRunCode), v_message, verbosityEBSaver); + + // clean the to remove buffer + GroupedTriggerIndexToRemove.clear(); + PMTRunCodeToRemove.clear(); + MRDRunCodeToRemove.clear(); + LAPPDRunCodeToRemove.clear(); + + PMTPairInfoToRemoveTime.clear(); + MRDPairInfoToRemoveTime.clear(); + LAPPDPairInfoToRemoveTime.clear(); + + // get the grouped trigger, save the grouped triggers with the same runcode + cout << "\033[1;34m******* EBSaver : Saving *******\033[0m" << endl; + m_data->CStore.Get("GroupedTriggersInTotal", GroupedTriggersInTotal); + m_data->CStore.Get("RunCodeInTotal", RunCodeInTotal); + + // get the pmt data, runcode buffer, and match information + + // get the pmt buffer, save the data, and remove the saved data from data buffer + + // loop each track in the RunCodeInTotal; + for (auto const &track : RunCodeInTotal) + { + int triggerTrack = track.first; + std::vector RunCodeVector = track.second; + // check if the RunCodeInTotal[tragetTrigWord] has the same size with GroupedTriggersInTotal[tragetTrigWord] + Log("EBSaver: Looping trigger track " + std::to_string(triggerTrack) + " with RunCodeInTotal size " + std::to_string(RunCodeVector.size()) + " and GroupedTriggersInTotal size " + std::to_string(GroupedTriggersInTotal[triggerTrack].size()), v_message, verbosityEBSaver); + + if (RunCodeVector.size() != GroupedTriggersInTotal[triggerTrack].size()) + { + Log("EBSaver: RunCodeInTotal and GroupedTriggersInTotal size not match, RunCodeVector size " + std::to_string(RunCodeVector.size()) + " and GroupedTriggersInTotal size " + std::to_string(GroupedTriggersInTotal[triggerTrack].size()), v_warning, verbosityEBSaver); + continue; + } + // GroupedTriggersInTotal and RunCodeInTotal have the same size + // same index is the cooresponding data + for (int i = 0; i < RunCodeVector.size(); i++) + { + int runCode = RunCodeVector[i]; + // saving + // if save Everything, in case there might be some mis aligned events not saved to that processed part file correctly and left in buffer, save them to corresponding part file + if (runCode == savingRunCode) + { + Log("\033[1;34m ****EBSaver: Saving a new event \033[0m", v_message, verbosityEBSaver); + + std::string saveFileName = savePath + saveName + "_R" + to_string(runCode / 100000) + "S" + to_string((runCode % 100000) / 10000 - 1) + "p" + to_string(runCode % 10000); + Log("EBSaver: Saving to " + saveFileName + " with run code " + std::to_string(runCode) + " at index " + std::to_string(i), v_message, verbosityEBSaver); + + // if in last exe, the runcode for that group of trigger equals to the saving RunCode, save to ANNIEEvent Processed File + SaveToANNIEEvent(saveFileName, runCode, triggerTrack, i); + } + } + } + + // remove the paired trigger and data timestamp at PairInfoToRemoveIndex from the buffer like PairedLAPPDTimeStamps + for (auto const &track : GroupedTriggerIndexToRemove) + { + int triggerTrack = track.first; + int groupIndex = track.second; + GroupedTriggersInTotal[triggerTrack].erase(GroupedTriggersInTotal[triggerTrack].begin() + groupIndex); + RunCodeInTotal[triggerTrack].erase(RunCodeInTotal[triggerTrack].begin() + groupIndex); + } + int PMTToRemove = 0; + int MRDToRemove = 0; + int LAPPDToRemove = 0; + for (auto const &track : PMTPairInfoToRemoveTime) + { + int triggerTrack = track.first; + std::vector times = track.second; + PMTToRemove += times.size(); + // print the size of times, and all elements in times + Log("EBSaver: PMT PairInfoToRemoveTime at track " + std::to_string(triggerTrack) + " size " + std::to_string(times.size()), v_message, verbosityEBSaver); + for (int i = 0; i < times.size(); i++) + cout << i << ": " << times[i] << ", "; + } + cout << endl; + for (auto const &track : MRDPairInfoToRemoveTime) + { + int triggerTrack = track.first; + std::vector times = track.second; + MRDToRemove += times.size(); + Log("EBSaver: MRD PairInfoToRemoveTime at track " + std::to_string(triggerTrack) + " size " + std::to_string(times.size()), v_message, verbosityEBSaver); + for (int i = 0; i < times.size(); i++) + cout << i << ": " << times[i] << ", "; + } + cout << endl; + for (auto const &track : LAPPDPairInfoToRemoveTime) + { + int triggerTrack = track.first; + std::vector times = track.second; + LAPPDToRemove += times.size(); + Log("EBSaver: LAPPD PairInfoToRemoveTime at track " + std::to_string(triggerTrack) + " size " + std::to_string(times.size()), v_message, verbosityEBSaver); + for (int i = 0; i < times.size(); i++) + cout << i << ": " << times[i] << ", "; + } + cout << endl; + + Log("EBSaver: before remove from pair info buffer, going to remove PMT " + std::to_string(PMTToRemove) + ", MRD " + std::to_string(MRDToRemove) + ", LAPPD " + std::to_string(LAPPDToRemove), v_message, verbosityEBSaver); + + // print everything in PairedLAPPDTimeStamps for debug + for (auto const &track : PairedLAPPDTimeStamps) + { + int triggerTrack = track.first; + std::vector times = track.second; + Log("EBSaver: PairedLAPPDTimeStamps at track " + std::to_string(triggerTrack) + " size " + std::to_string(times.size()), v_message, verbosityEBSaver); + for (int i = 0; i < times.size(); i++) + cout << i << ": " << times[i] << ", "; + } + // print everything in Buffer_LAPPDTimestamp_ns for debug + Log("EBSaver: Buffer_LAPPDTimestamp_ns size " + std::to_string(Buffer_LAPPDTimestamp_ns.size()), v_message, verbosityEBSaver); + for (int i = 0; i < Buffer_LAPPDTimestamp_ns.size(); i++) + cout << i << ": " << Buffer_LAPPDTimestamp_ns[i] << ", "; + cout << endl; + + // 删除 LAPPD 相关时间戳 + int removedLAPPD = 0; + for (auto const &track : LAPPDPairInfoToRemoveTime) + { + int triggerTrack = track.first; + std::vector indexes = track.second; + for (int i = 0; i < indexes.size(); i++) + { + int foundIndex = -1; + for (int j = 0; j < PairedLAPPDTimeStamps[triggerTrack].size(); j++) + { + if (PairedLAPPDTimeStamps[triggerTrack][j] == indexes[i]) + { + foundIndex = j; + break; + } + } + if (foundIndex != -1) + { + removedLAPPD++; + Log("EBSaver: Remove LAPPD data with LAPPDTime " + std::to_string(indexes[i]) + " at index " + std::to_string(foundIndex), v_message, verbosityEBSaver); + PairedLAPPDTimeStamps[triggerTrack].erase(PairedLAPPDTimeStamps[triggerTrack].begin() + foundIndex); + PairedLAPPDTriggerTimestamp[triggerTrack].erase(PairedLAPPDTriggerTimestamp[triggerTrack].begin() + foundIndex); + } + } + } + + // 删除 PMT 相关时间戳 + + for (auto const &track : PMTPairInfoToRemoveTime) + { + int triggerTrack = track.first; + std::vector indexes = track.second; + for (int i = 0; i < indexes.size(); i++) + { + int foundIndex = -1; + for (int j = 0; j < PairedPMTTimeStamps[triggerTrack].size(); j++) + { + if (PairedPMTTimeStamps[triggerTrack][j] == indexes[i]) + { + foundIndex = j; + break; + } + } + if (foundIndex != -1) + { + PairedPMTTimeStamps[triggerTrack].erase(PairedPMTTimeStamps[triggerTrack].begin() + foundIndex); + PairedPMTTriggerTimestamp[triggerTrack].erase(PairedPMTTriggerTimestamp[triggerTrack].begin() + foundIndex); + } + } + } + + // 删除 MRD 相关时间戳 + for (auto const &track : MRDPairInfoToRemoveTime) + { + int triggerTrack = track.first; + std::vector indexes = track.second; + for (int i = 0; i < indexes.size(); i++) + { + int foundIndex = -1; + for (int j = 0; j < PairedMRDTimeStamps[triggerTrack].size(); j++) + { + if (PairedMRDTimeStamps[triggerTrack][j] == indexes[i]) + { + foundIndex = j; + break; + } + } + if (foundIndex != -1) + { + PairedMRDTimeStamps[triggerTrack].erase(PairedMRDTimeStamps[triggerTrack].begin() + foundIndex); + PairedMRDTriggerTimestamp[triggerTrack].erase(PairedMRDTriggerTimestamp[triggerTrack].begin() + foundIndex); + } + } + } + + ANNIEEvent->Close(); + ANNIEEvent->Delete(); + delete ANNIEEvent; + ANNIEEvent = new BoostStore(false, 2); + + if (saveEverything) + { + Log("EBSaver: Save everything", v_message, verbosityEBSaver); + } + + // now save other data left in the data buffer to orphan + // loop the runcode buffer of each data store, find which run code we need to save + // then loop the run code vector, for each run code, loop all data buffers, save the left data with the save run code + + m_data->CStore.Set("GroupedTriggersInTotal", GroupedTriggersInTotal); + m_data->CStore.Set("RunCodeInTotal", RunCodeInTotal); + m_data->CStore.Set("PairedLAPPDTriggerTimestamp", PairedLAPPDTriggerTimestamp); + m_data->CStore.Set("PairedLAPPDTimeStamps", PairedLAPPDTimeStamps); + m_data->CStore.Set("PairedPMTTriggerTimestamp", PairedPMTTriggerTimestamp); + m_data->CStore.Set("PairedPMTTimeStamps", PairedPMTTimeStamps); + m_data->CStore.Set("PairedMRDTriggerTimestamp", PairedMRDTriggerTimestamp); + m_data->CStore.Set("PairedMRDTimeStamps", PairedMRDTimeStamps); + + Log("EBSaver: Execute finished, saved PMT " + std::to_string(savedPMTHitMapNumber) + ", MRD " + std::to_string(savedMRDNumber) + ", LAPPD " + std::to_string(savedLAPPDNumber) + ", trigger group " + std::to_string(savedTriggerGroupNumber), v_message, verbosityEBSaver); + + Log("EBSaver: Set PMT pairing information buffer PairedPMTTimeStamps size " + std::to_string(PairedPMTTimeStamps.size()), v_message, verbosityEBSaver); + // print size of each track + for (auto const &track : PairedPMTTimeStamps) + Log("EBSaver: track " + std::to_string(track.first) + " size " + std::to_string(track.second.size()), v_message, verbosityEBSaver); + Log("EBSaver: Set MRD pairing information buffer PairedMRDTimeStamps size " + std::to_string(PairedMRDTimeStamps.size()), v_message, verbosityEBSaver); + for (auto const &track : PairedMRDTimeStamps) + Log("EBSaver: track " + std::to_string(track.first) + " size " + std::to_string(track.second.size()), v_message, verbosityEBSaver); + Log("EBSaver: Set LAPPD pairing information buffer PairedLAPPDTimeStamps size " + std::to_string(PairedLAPPDTimeStamps.size()), v_message, verbosityEBSaver); + for (auto const &track : PairedLAPPDTimeStamps) + Log("EBSaver: track " + std::to_string(track.first) + " size " + std::to_string(track.second.size()), v_message, verbosityEBSaver); + + SetDataObjects(); + cout << "\033[1;34m******* EBSaver : Finished *******\033[0m" << endl; + + return true; +} + +bool EBSaver::Finalise() +{ + Log("\033[1;34mEBSaver: Finalising\033[0m", v_message, verbosityEBSaver); + ANNIEEvent->Close(); + ANNIEEvent->Delete(); + delete ANNIEEvent; + + Log("EBSaver: Finished built " + std::to_string(TotalBuiltEventsNumber) + " events", v_message, verbosityEBSaver); + Log("EBSaver: Finished built " + std::to_string(savedTriggerGroupNumber) + " trigger groups", v_message, verbosityEBSaver); + Log("EBSaver: Finished built " + std::to_string(savedPMTHitMapNumber) + " PMT hit maps", v_message, verbosityEBSaver); + Log("EBSaver: Finished built " + std::to_string(savedMRDNumber) + " MRD events", v_message, verbosityEBSaver); + Log("EBSaver: Finished built " + std::to_string(savedLAPPDNumber) + " LAPPD events", v_message, verbosityEBSaver); + Log("EBSaver: matched but not built event number: ***********", v_message, verbosityEBSaver); + Log("\033[1;34mEBSaver: left PMT events in pairing info buffer " + std::to_string(PairedPMTTimeStamps.size()) + " \033[0m", v_message, verbosityEBSaver); + // also print the size of each track with track word + + for (auto const &track : PairedPMTTimeStamps) + { + Log("EBSaver: track " + std::to_string(track.first) + ", total left trigger number " + std::to_string(track.second.size()), v_message, verbosityEBSaver); + if (verbosityEBSaver > 9) + { + // count how many events not built for each trigger word + std::map unbuiltEvents; + for (int i = 0; i < track.second.size(); i++) + { + if (PairedPMTTimeStamps[track.first][i] != 0) + unbuiltEvents[PairedPMTTimeStamps[track.first][i]]++; + } + for (auto const &event : unbuiltEvents) + Log("EBSaver: track " + std::to_string(track.first) + ", left trigger " + std::to_string(event.first) + " number " + std::to_string(event.second), v_message, verbosityEBSaver); + } + } + Log("\033[1;34mEBSaver: left MRD events in pairing info buffer " + std::to_string(PairedMRDTimeStamps.size()) + " \033[0m", v_message, verbosityEBSaver); + for (auto const &track : PairedMRDTimeStamps) + { + Log("EBSaver: track " + std::to_string(track.first) + ", left trigger number " + std::to_string(track.second.size()), v_message, verbosityEBSaver); + if (verbosityEBSaver > 9) + { + // count how many events not built for each trigger word + std::map unbuiltEvents; + for (int i = 0; i < track.second.size(); i++) + { + if (PairedMRDTimeStamps[track.first][i] != 0) + unbuiltEvents[PairedMRDTimeStamps[track.first][i]]++; + } + for (auto const &event : unbuiltEvents) + Log("EBSaver: track " + std::to_string(track.first) + ", left trigger " + std::to_string(event.first) + " number " + std::to_string(event.second), v_message, verbosityEBSaver); + } + } + Log("\033[1;34mEBSaver: left LAPPD events in pairing info buffer " + std::to_string(PairedLAPPDTimeStamps.size()) + " \033[0m", v_message, verbosityEBSaver); + for (auto const &track : PairedLAPPDTimeStamps) + { + Log("EBSaver: track " + std::to_string(track.first) + ", left trigger number " + std::to_string(track.second.size()), v_message, verbosityEBSaver); + // count how many events not built for each trigger word + if (verbosityEBSaver > 9) + { + std::map unbuiltEvents; + for (int i = 0; i < track.second.size(); i++) + { + if (PairedLAPPDTimeStamps[track.first][i] != 0) + unbuiltEvents[PairedLAPPDTimeStamps[track.first][i]]++; + } + for (auto const &event : unbuiltEvents) + Log("EBSaver: track " + std::to_string(track.first) + ", left trigger " + std::to_string(event.first) + " number " + std::to_string(event.second), v_message, verbosityEBSaver); + } + } + Log("EBSaver: left event number: ***********", v_message, verbosityEBSaver); + Log("EBSaver: left PMT events in original data buffer " + std::to_string(InProgressHits->size()), v_message, verbosityEBSaver); + Log("EBSaver: left MRD events in original data buffer " + std::to_string(MRDEvents.size()), v_message, verbosityEBSaver); + Log("EBSaver: left LAPPD events in original data buffer " + std::to_string(Buffer_LAPPDTimestamp_ns.size()), v_message, verbosityEBSaver); + // print the size of each track of + + // add debug print for the left MRD, print TriggerTimeWithoutMRD and PairedMRDTimeStamps to two txt file + std::ofstream TriggerTimeWithoutMRDFile; + TriggerTimeWithoutMRDFile.open("EBdebug_TriggerTimeWithoutMRD.txt"); + for (auto const &track : TriggerTimeWithoutMRD) + { + TriggerTimeWithoutMRDFile << track.first << " " << track.second << endl; + } + TriggerTimeWithoutMRDFile.close(); + std::ofstream PairedMRDTimeStampsFile; + PairedMRDTimeStampsFile.open("EBdebug_PairedMRDTimeStamps.txt"); + for (auto const &track : PairedMRDTimeStamps) + { + for (int i = 0; i < track.second.size(); i++) + { + PairedMRDTimeStampsFile << track.first << " " << track.second[i] << endl; + } + } + + return true; +} + +bool EBSaver::SaveToANNIEEvent(string saveFileName, int runCode, int triggerTrack, int trackIndex) +{ + SaveRunInfo(runCode); + std::map DataStreams; + DataStreams.emplace("Tank", 0); + DataStreams.emplace("MRD", 0); + DataStreams.emplace("CTC", 1); + DataStreams.emplace("LAPPD", 0); + + SaveGroupedTriggers(triggerTrack, trackIndex); + + bool PMTSaved = false; // incase of multiple 14 found in one group + bool MRDSaved = false; + bool LAPPDSaved = false; + + std::map GroupedTrigger = GroupedTriggersInTotal[triggerTrack][trackIndex]; + // For each element in GroupedTrigger, find is it appear in PairedPMTTriggerTimestamp[triggerTrack], + // if yes, got the index, access the same index at PairedPMTTimeStamps[triggerTrack], that uint64_t is the PMTTime + for (auto &trigger : GroupedTrigger) + { + uint64_t triggerTime = trigger.first; + uint32_t triggerType = trigger.second; + if (triggerType == 14) + Log("EBSaver: Found undelayed beam trigger with time " + std::to_string(triggerTime) + " in GroupedTrigger", v_debug, verbosityEBSaver); + + if (PairedPMTTriggerTimestamp.find(triggerTrack) != PairedPMTTriggerTimestamp.end()) + { + for (int i = 0; i < PairedPMTTriggerTimestamp.at(triggerTrack).size(); i++) + { + if (PairedPMTTriggerTimestamp.at(triggerTrack).at(i) == triggerTime) + { + uint64_t PMTTime = PairedPMTTimeStamps.at(triggerTrack).at(i); + Log("EBSaver: Found trigger with time " + std::to_string(triggerTime) + " in PairedPMTTriggerTimestamp " + std::to_string(i) + " match with PMTTime " + std::to_string(PMTTime), v_debug, verbosityEBSaver); + + bool saved = SavePMTData(PMTTime); + PMTSaved = saved; + DataStreams["Tank"] = 1; + if (saved) + PMTPairInfoToRemoveTime[triggerTrack].push_back(PMTTime); + Log("EBSaver: Saved " + std::to_string(savedPMTHitMapNumber) + " PMT data with PMTTime " + std::to_string(PMTTime), v_debug, verbosityEBSaver); + // break; + } + } + } + + // check if PairedMRDTriggerTimestamp has element with key = triggerTrack + if(!MRDSaved){ + Log("Finding trigger track = " + std::to_string(triggerTrack) + " in PairedMRDTriggerTimestamp", v_debug, verbosityEBSaver); + //print PairedMRDTriggerTimestamp with track number and size + for (auto const &track : PairedMRDTriggerTimestamp) + { + Log("EBSaver: in PairedMRDTriggerTimestamp track " + std::to_string(track.first) + ", left trigger number " + std::to_string(track.second.size()), v_message, verbosityEBSaver); + } + for (auto const &track : PairedMRDTimeStamps) + { + Log("EBSaver: in PairedMRDTimeStamps track " + std::to_string(track.first) + ", left trigger number " + std::to_string(track.second.size()), v_message, verbosityEBSaver); + } + if (PairedMRDTriggerTimestamp.find(triggerTrack) != PairedMRDTriggerTimestamp.end()) + { + uint64_t minDiff = 100*60*1e9; + Log("Found trigger track = " + std::to_string(triggerTrack) + " in PairedMRDTriggerTimestamp", v_debug, verbosityEBSaver); + //print the size of PairedMRDTriggerTimestamp.at(triggerTrack), print the first and the last timestamp + Log("EBSaver: PairedMRDTriggerTimestamp size " + std::to_string(PairedMRDTriggerTimestamp.at(triggerTrack).size()), v_debug, verbosityEBSaver); + if(PairedMRDTriggerTimestamp.at(triggerTrack).size()>0) + Log("EBSaver: PairedMRDTriggerTimestamp first " + std::to_string(PairedMRDTriggerTimestamp.at(triggerTrack).at(0)) + ", last " + std::to_string(PairedMRDTriggerTimestamp.at(triggerTrack).at(PairedMRDTriggerTimestamp.at(triggerTrack).size()-1)), v_debug, verbosityEBSaver); + + for (int i = 0; i < PairedMRDTriggerTimestamp.at(triggerTrack).size(); i++) + { + uint64_t diff = (PairedMRDTriggerTimestamp.at(triggerTrack).at(i) > triggerTime) ? PairedMRDTriggerTimestamp.at(triggerTrack).at(i) - triggerTime : triggerTime - PairedMRDTriggerTimestamp.at(triggerTrack).at(i); + if(diff < minDiff) + minDiff = diff; + + if (PairedMRDTriggerTimestamp.at(triggerTrack).at(i) == triggerTime || (diff<1e6)) + { + if(diff<1e6) + {Log("EBSaver: diff<1e6, is " + std::to_string(diff), v_debug, verbosityEBSaver); + TriggerTimeWithoutMRD.emplace(PairedMRDTriggerTimestamp.at(triggerTrack).at(i), static_cast(diff)); + } + uint64_t MRDTime = PairedMRDTimeStamps.at(triggerTrack).at(i); + bool saved = SaveMRDData(MRDTime); + MRDSaved = saved; + DataStreams["MRD"] = 1; + if (MRDSaved) + MRDPairInfoToRemoveTime[triggerTrack].push_back(MRDTime); + Log("EBSaver: Saved " + std::to_string(savedMRDNumber) + " MRD data with MRDTime " + std::to_string(MRDTime), v_debug, verbosityEBSaver); + Log("EBSaver: Found trigger with time " + std::to_string(triggerTime) + " in PairedMRDTriggerTimestamp " + std::to_string(i) + " match with MRDTime " + std::to_string(MRDTime), v_debug, verbosityEBSaver); + // break; + } + } + // Log("EBSaver: MRDData saved", 8, verbosityEBSaver); + Log("EBSaver: While saving MRD data, use trigger time " + std::to_string(triggerTime) + " with minDiff " + std::to_string(minDiff), v_debug, verbosityEBSaver); + } + } + + if (PairedLAPPDTriggerTimestamp.find(triggerTrack) != PairedLAPPDTriggerTimestamp.end()) + { + for (int i = 0; i < PairedLAPPDTriggerTimestamp.at(triggerTrack).size(); i++) + { + if (PairedLAPPDTriggerTimestamp.at(triggerTrack).at(i) == triggerTime) + { + uint64_t LAPPDTime = PairedLAPPDTimeStamps.at(triggerTrack).at(i); + bool saved = SaveLAPPDData(LAPPDTime); + LAPPDSaved = saved; + DataStreams["LAPPD"] = 1; + if (LAPPDSaved) + LAPPDPairInfoToRemoveTime[triggerTrack].push_back(LAPPDTime); + Log("EBSaver: Saved " + std::to_string(savedLAPPDNumber) + " LAPPD data with LAPPDTime " + std::to_string(LAPPDTime), v_debug, verbosityEBSaver); + Log("EBSaver: Found trigger with time " + std::to_string(triggerTime) + " in PairedLAPPDTriggerTimestamp " + std::to_string(i) + " match with LAPPDTime " + std::to_string(LAPPDTime), v_debug, verbosityEBSaver); + // break; + } + } + // Log("EBSaver: LAPPDData saved", 8, verbosityEBSaver); + } + } + + ANNIEEvent->Set("DataStreams", DataStreams); + + // if Datastream is not built, save a default empty data for that into the event + if (DataStreams["Tank"] == 0) + BuildEmptyPMTData(); + if (DataStreams["MRD"] == 0) + { + BuildEmptyMRDData(); + if (triggerTrack == 14) + { + // find the time of trigger 8 in current group + uint64_t triggerTime = 0; + for (auto &trigger : GroupedTrigger) + { + if (trigger.second == 8) + { + triggerTime = trigger.first; + break; + } + } + TriggerTimeWithoutMRD.emplace(triggerTime, triggerTrack); + } + else if (triggerTrack == 36) + { + // find the time of trigger 8 in current group + uint64_t triggerTime = 0; + for (auto &trigger : GroupedTrigger) + { + if (trigger.second == 36) + { + triggerTime = trigger.first; + break; + } + } + TriggerTimeWithoutMRD.emplace(triggerTime, triggerTrack); + } + } + + if (DataStreams["LAPPD"] == 0) + BuildEmptyLAPPDData(); + + Log("EBSaver: Print ANNIEEvent, Saving to " + saveFileName, v_debug, verbosityEBSaver); + if (verbosityEBSaver > 8) + ANNIEEvent->Print(false); + ANNIEEvent->Save(saveFileName); + TotalBuiltEventsNumber++; + ANNIEEvent->Delete(); + + return true; +} + +bool EBSaver::SaveRunInfo(int runCode) +{ + int RunNumber = runCode / 100000; + int SubRunNumber = (runCode % 100000) / 10000 - 1; + int PartFileNumber = runCode % 10000; + + ANNIEEvent->Set("RunNumber", RunNumber); + ANNIEEvent->Set("SubRunNumber", SubRunNumber); + ANNIEEvent->Set("PartNumber", PartFileNumber); + Log("EBSaver: Saving run info with RunNumber " + std::to_string(RunNumber) + " SubRunNumber " + std::to_string(SubRunNumber) + " PartFileNumber " + std::to_string(PartFileNumber), v_debug, verbosityEBSaver); + return true; +} + +bool EBSaver::SaveGroupedTriggers(int triggerTrack, int groupIndex) +{ + Log("EBSaver: Saving grouped triggers for trigger track " + std::to_string(triggerTrack) + " with group index " + std::to_string(groupIndex), v_debug, verbosityEBSaver); + std::map GroupedTrigger = GroupedTriggersInTotal[triggerTrack][groupIndex]; + GroupedTriggerIndexToRemove.emplace(triggerTrack, groupIndex); + + ANNIEEvent->Set("GroupedTrigger", GroupedTrigger); + int matchTriggerType = triggerTrack; + ANNIEEvent->Set("PrimaryTriggerWord", matchTriggerType); + ANNIEEvent->Set("TriggerWord", matchTriggerType); + + // find the triggertrack trigger time in GroupedTrigger + uint64_t primaryTrigTime = 0; + for (auto &trigger : GroupedTrigger) + { + if (trigger.second == triggerTrack) + { + primaryTrigTime = trigger.first; + break; + } + } + + ANNIEEvent->Set("PrimaryTriggerTime", primaryTrigTime); + ANNIEEvent->Set("CTCTimestamp", primaryTrigTime); + + bool NCExtended = false; + bool CCExtended = false; + std::string TriggerType = ""; + int CTCWordExtended = 0; + uint64_t ExtendedTriggerTime = 0; + + if (triggerTrack == BeamTriggerMain) + { + TriggerType = "Beam"; + // if found 40 in values of GroupedTrigger, set NCExtended to true + // put the data at that index to ExtendedTriggerTime + for (auto &trigger : GroupedTrigger) + { + if (trigger.second == 41) + { + NCExtended = true; + ExtendedTriggerTime = trigger.first; + CTCWordExtended = 1; + break; + } + } + for (auto &trigger : GroupedTrigger) + { + if (trigger.second == 40) + { + CCExtended = true; + ExtendedTriggerTime = trigger.first; + CTCWordExtended = 2; + break; + } + } + } + else if (triggerTrack == LaserTriggerMain) + TriggerType = "Laser"; + else if (triggerTrack == CosmicTriggerMain) + TriggerType = "Cosmic"; + else if (triggerTrack == LEDTriggerMain) + TriggerType = "LED"; + else if (triggerTrack == AmBeTriggerMain) + TriggerType = "AmBe"; + else if (triggerTrack == PPSMain) + TriggerType = "PPS"; + + ANNIEEvent->Set("NCExtended", NCExtended); + ANNIEEvent->Set("CCExtended", CCExtended); + ANNIEEvent->Set("TriggerType", TriggerType); + ANNIEEvent->Set("TriggerExtended", CTCWordExtended); // 0: normal, 1: NC extended, 2: CC extended + // Notice, in the V1 eventbuilder, there is a requirement that the matched trigger time - extended trigger time <5000, if not the extended will be 0 + // we don't have it here because the PMT was not matched to a single trigger, but a group. + // you may need to select the events based on the time difference in the grouped trigger + + TimeClass TriggerTime(primaryTrigTime); + TriggerClass TriggerData(TriggerType, matchTriggerType, CTCWordExtended, true, TriggerTime); + ANNIEEvent->Set("TriggerData", TriggerData); + + savedTriggerGroupNumber++; + Log("EBSaver: Saved trigger group with trigger type " + TriggerType + " and trigger time " + std::to_string(primaryTrigTime), v_debug, verbosityEBSaver); + return true; +} + +bool EBSaver::SavePMTData(uint64_t PMTTime) +{ + Log("EBSaver: Saving PMT data with PMTTime " + std::to_string(PMTTime), v_debug, verbosityEBSaver); + // find PMTTime in InProgressHits, if not found, return false + if (InProgressHits->find(PMTTime) == InProgressHits->end()) + { + Log("EBSaver: PMT data with PMTTime " + std::to_string(PMTTime) + " not found in InProgressHits", v_debug, verbosityEBSaver); + return false; + } + ANNIEEvent->Set("EventTimeTank", PMTTime); + + std::map> *PMTHits = InProgressHits->at(PMTTime); + std::map>> PMTRecoADCHits = InProgressRecoADCHits->at(PMTTime); + std::map> *PMTHitsAux = InProgressHitsAux->at(PMTTime); + std::map>> PMTRecoADCHitsAux = InProgressRecoADCHitsAux->at(PMTTime); + std::map> PMTRawAcqSize = FinishedRawAcqSize->at(PMTTime); + + Log("EBSaver: Got PMT data, saving", v_debug, verbosityEBSaver); + + //check does the ANNIEEvent already have the key "Hits", if yes, print the size of the vector of each key + //also print the size of the vector of each key in new PMTHits + //Then Merger the two maps + std::map> *OldPMTHits = new std::map>; + bool gotHits = ANNIEEvent->Get("Hits", OldPMTHits); + if(gotHits){ + Log("EBSaver: ANNIEEvent already has key Hits, size " + std::to_string(OldPMTHits->size()), v_debug, verbosityEBSaver); + for (auto const &time : *OldPMTHits) + Log("EBSaver: OldPMTHits old time " + std::to_string(time.first) + " size " + std::to_string(time.second.size()), v_debug, verbosityEBSaver); + for (auto const &time : *PMTHits) + Log("EBSaver: PMTHits new time " + std::to_string(time.first) + " size " + std::to_string(time.second.size()), v_debug, verbosityEBSaver); + for (auto const &time : *OldPMTHits) + { + if (PMTHits->count(time.first) == 0) + { + PMTHits->emplace(time.first, time.second); + } + else + { + for (auto const &hit : time.second) + { + PMTHits->at(time.first).push_back(hit); + } + } + } + Log("EBSaver: Merged PMT data, PMTHits size " + std::to_string(PMTHits->size()), v_debug, verbosityEBSaver); + } + + + ANNIEEvent->Set("Hits", PMTHits, true); + ANNIEEvent->Set("RecoADCData", PMTRecoADCHits); + ANNIEEvent->Set("AuxHits", PMTHitsAux, true); + ANNIEEvent->Set("RecoAuxADCData", PMTRecoADCHitsAux); + ANNIEEvent->Set("RawAcqSize", PMTRawAcqSize); + + savedPMTHitMapNumber++; + + // erase the built data from original data buffer + InProgressHits->erase(PMTTime); + InProgressRecoADCHits->erase(PMTTime); + InProgressHitsAux->erase(PMTTime); + InProgressRecoADCHitsAux->erase(PMTTime); + FinishedRawAcqSize->erase(PMTTime); + + Log("EBSaver: Saved PMT data with PMTTime " + std::to_string(PMTTime), v_debug, verbosityEBSaver); + return true; +} + +bool EBSaver::SaveMRDData(uint64_t MRDTime) +{ + Log("EBSaver: Saving MRD data with MRDTime " + std::to_string(MRDTime), v_debug, verbosityEBSaver); + // find MRDTime in MRDEvents, if not found, return false + if (MRDEvents.find(MRDTime) == MRDEvents.end()) + { + Log("EBSaver: not found MRD data with MRDTime " + std::to_string(MRDTime) + " in MRDEvents", v_debug, verbosityEBSaver); + return false; + } + + // find the index of the MRDTime in PairedMRDTimeStamps + std::vector> MRDHits = MRDEvents.at(MRDTime); + std::string MRDTriggerType = MRDEventTriggerTypes.at(MRDTime); + int beam_tdc = MRDBeamLoopback.at(MRDTime); + int cosmic_tdc = MRDCosmicLoopback.at(MRDTime); + + std::map> *TDCData = new std::map>; + + for (unsigned int i_value = 0; i_value < MRDHits.size(); i_value++) + { + unsigned long channelkey = MRDHits.at(i_value).first; + int hitTimeADC = MRDHits.at(i_value).second; + double hitTime = 4000. - 4. * static_cast(hitTimeADC); + + if (TDCData->count(channelkey) == 0) + { + std::vector newhitvector; + newhitvector.push_back(Hit(0, hitTime, 1.)); + TDCData->emplace(channelkey, newhitvector); + } + else + { + TDCData->at(channelkey).push_back(Hit(0, hitTime, 1.)); + } + } + + std::map mrd_loopback_tdc; + mrd_loopback_tdc.emplace("BeamLoopbackTDC", beam_tdc); + mrd_loopback_tdc.emplace("CosmicLoopbackTDC", cosmic_tdc); + + Log("EBSaver: TDCdata size: " + std::to_string(TDCData->size()), v_warning, verbosityEBSaver); + + ANNIEEvent->Set("TDCData", TDCData, true); + TimeClass t(MRDTime); + ANNIEEvent->Set("EventTimeMRD", t); + ANNIEEvent->Set("MRDTriggerType", MRDTriggerType); + ANNIEEvent->Set("MRDLoopbackTDC", mrd_loopback_tdc); + + savedMRDNumber++; + + // erase the built data from original data buffer + MRDEvents.erase(MRDTime); + MRDEventTriggerTypes.erase(MRDTime); + MRDBeamLoopback.erase(MRDTime); + MRDCosmicLoopback.erase(MRDTime); + + Log("EBSaver: Saved MRD data with MRDTime " + std::to_string(MRDTime), v_debug, verbosityEBSaver); + return true; +} + +bool EBSaver::SaveLAPPDData(uint64_t LAPPDTime) +{ + Log("EBSaver: Saving LAPPD data with LAPPDTime " + std::to_string(LAPPDTime), v_debug, verbosityEBSaver); + // find LAPPDTime in Buffer_LAPPDTimestamp_ns, if not found, return false + if (std::find(Buffer_LAPPDTimestamp_ns.begin(), Buffer_LAPPDTimestamp_ns.end(), LAPPDTime) == Buffer_LAPPDTimestamp_ns.end()) + { + Log("EBSaver: LAPPD data with LAPPDTime " + std::to_string(LAPPDTime) + " not found in Buffer_LAPPDTimestamp_ns", v_debug, verbosityEBSaver); + return false; + } + + // find the index of the LAPPDTime in PairedLAPPDTimeStamps + int index = -1; + for (int i = 0; i < Buffer_LAPPDTimestamp_ns.size(); i++) + { + if (Buffer_LAPPDTimestamp_ns.at(i) == LAPPDTime) + { + index = i; + break; + } + } + + // save the data at index i to ANNIE event, then remove that index from buffer + if (index != -1) + { + std::map LAPPDDataMap; + std::map LAPPDBeamgate_ns; + std::map LAPPDTimeStamps_ns; // data and key are the same + std::map LAPPDTimeStampsRaw; + std::map LAPPDBeamgatesRaw; + std::map LAPPDOffsets; + std::map LAPPDTSCorrection; + std::map LAPPDBGCorrection; + std::map LAPPDOSInMinusPS; + + bool gotMap = ANNIEEvent->Get("LAPPDDataMap", LAPPDDataMap); + bool gotBeamgates_ns = ANNIEEvent->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + bool gotTimeStamps_ns = ANNIEEvent->Get("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); + bool gotTimeStampsRaw = ANNIEEvent->Get("LAPPDTimeStampsRaw", LAPPDTimeStampsRaw); + bool gotBeamgatesRaw = ANNIEEvent->Get("LAPPDBeamgatesRaw", LAPPDBeamgatesRaw); + bool gotOffsets = ANNIEEvent->Get("LAPPDOffsets", LAPPDOffsets); + bool gotTSCorrection = ANNIEEvent->Get("LAPPDTSCorrection", LAPPDTSCorrection); + bool gotDBGCorrection = ANNIEEvent->Get("LAPPDBGCorrection", LAPPDBGCorrection); + bool gotOSInMinusPS = ANNIEEvent->Get("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + + LAPPDDataMap.emplace(LAPPDTime, Buffer_LAPPDData.at(index)); + LAPPDBeamgate_ns.emplace(LAPPDTime, Buffer_LAPPDBeamgate_ns.at(index)); + LAPPDTimeStamps_ns.emplace(LAPPDTime, Buffer_LAPPDTimestamp_ns.at(index)); + LAPPDTimeStampsRaw.emplace(LAPPDTime, Buffer_LAPPDTimestamp_Raw.at(index)); + LAPPDBeamgatesRaw.emplace(LAPPDTime, Buffer_LAPPDBeamgate_Raw.at(index)); + LAPPDOffsets.emplace(LAPPDTime, Buffer_LAPPDOffset.at(index)); + LAPPDTSCorrection.emplace(LAPPDTime, Buffer_LAPPDTSCorrection.at(index)); + LAPPDBGCorrection.emplace(LAPPDTime, Buffer_LAPPDBGCorrection.at(index)); + LAPPDOSInMinusPS.emplace(LAPPDTime, Buffer_LAPPDOffset_minus_ps.at(index)); + + ANNIEEvent->Set("LAPPDDataMap", LAPPDDataMap); + ANNIEEvent->Set("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + ANNIEEvent->Set("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); + ANNIEEvent->Set("LAPPDTimeStampsRaw", LAPPDTimeStampsRaw); + ANNIEEvent->Set("LAPPDBeamgatesRaw", LAPPDBeamgatesRaw); + ANNIEEvent->Set("LAPPDOffsets", LAPPDOffsets); + ANNIEEvent->Set("LAPPDTSCorrection", LAPPDTSCorrection); + ANNIEEvent->Set("LAPPDBGCorrection", LAPPDBGCorrection); + ANNIEEvent->Set("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + + savedLAPPDNumber++; + + // erase the built data from original data buffer + Buffer_LAPPDData.erase(Buffer_LAPPDData.begin() + index); + Buffer_LAPPDBeamgate_ns.erase(Buffer_LAPPDBeamgate_ns.begin() + index); + Buffer_LAPPDTimestamp_ns.erase(Buffer_LAPPDTimestamp_ns.begin() + index); + Buffer_LAPPDTimestamp_Raw.erase(Buffer_LAPPDTimestamp_Raw.begin() + index); + Buffer_LAPPDBeamgate_Raw.erase(Buffer_LAPPDBeamgate_Raw.begin() + index); + Buffer_LAPPDOffset.erase(Buffer_LAPPDOffset.begin() + index); + Buffer_LAPPDTSCorrection.erase(Buffer_LAPPDTSCorrection.begin() + index); + Buffer_LAPPDBGCorrection.erase(Buffer_LAPPDBGCorrection.begin() + index); + Buffer_LAPPDOffset_minus_ps.erase(Buffer_LAPPDOffset_minus_ps.begin() + index); + + Log("EBSaver: Saved LAPPD data with LAPPDTime " + std::to_string(LAPPDTime), v_debug, verbosityEBSaver); + return true; + } + else + { + Log("EBSaver: Failed to find LAPPD data with LAPPDTime " + std::to_string(LAPPDTime), v_debug, verbosityEBSaver); + + return false; + } +} + +bool EBSaver::SaveOrphan(int runCode) +{ + // loop everything in the data buffer, save + SaveOrphanPMT(runCode); + SaveOrphanMRD(runCode); + SaveOrphanLAPPD(runCode); + SaveOrphanCTC(runCode); + return true; +} + +bool EBSaver::SaveOrphanPMT(int runCode) +{ + + return true; +} + +bool EBSaver::SaveOrphanMRD(int runCode) +{ + + return true; +} + +bool EBSaver::SaveOrphanCTC(int runCode) +{ + + return true; +} + +bool EBSaver::SaveOrphanLAPPD(int runCode) +{ + + return true; +} + +bool EBSaver::GotAllDataFromOriginalBuffer() +{ + // got PMT data + bool gotPMTHits = m_data->CStore.Get("InProgressHits", InProgressHits); + bool gotPMTChkey = m_data->CStore.Get("InProgressChkey", InProgressChkey); + bool gotIPRecoADCHits = m_data->CStore.Get("InProgressRecoADCHits", InProgressRecoADCHits); + bool gotIPHitsAux = m_data->CStore.Get("InProgressHitsAux", InProgressHitsAux); + bool gotIPRADCH = m_data->CStore.Get("InProgressRecoADCHitsAux", InProgressRecoADCHitsAux); + bool gotFRAS = m_data->CStore.Get("FinishedRawAcqSize", FinishedRawAcqSize); // Filled in PhaseIIADCCalibrator + + if (!gotPMTHits || !gotPMTChkey || !gotIPRecoADCHits || !gotIPHitsAux || !gotIPRADCH || !gotFRAS) + { + Log("EBSaver: Failed to get some PMT data from buffer", v_message, verbosityEBSaver); + // print which one was failed + if (!gotPMTHits) + Log("EBSaver: Failed to get PMT hits from buffer", v_message, verbosityEBSaver); + if (!gotPMTChkey) + Log("EBSaver: Failed to get PMT chkey from buffer", v_message, verbosityEBSaver); + if (!gotIPRecoADCHits) + Log("EBSaver: Failed to get PMT recoADCHits from buffer", v_message, verbosityEBSaver); + if (!gotIPHitsAux) + Log("EBSaver: Failed to get PMT hits aux from buffer", v_message, verbosityEBSaver); + if (!gotIPRADCH) + Log("EBSaver: Failed to get PMT recoADCHits aux from buffer", v_message, verbosityEBSaver); + if (!gotFRAS) + Log("EBSaver: Failed to get PMT raw acq size from buffer", v_message, verbosityEBSaver); + } + // got PMT match info + bool gotPairedPMTTriggerTimestamp = m_data->CStore.Get("PairedPMTTriggerTimestamp", PairedPMTTriggerTimestamp); + bool gotPairedPMTTimeStamps = m_data->CStore.Get("PairedPMTTimeStamps", PairedPMTTimeStamps); + bool gotPairedPMT_TriggerIndex = m_data->CStore.Get("PairedPMT_TriggerIndex", PairedPMT_TriggerIndex); + bool gotPMTHitmapRunCode = m_data->CStore.Get("PMTHitmapRunCode", PMTHitmapRunCode); + if (!gotPairedPMTTriggerTimestamp || !gotPairedPMTTimeStamps || !gotPairedPMT_TriggerIndex || !gotPMTHitmapRunCode) + { + Log("EBSaver: Failed to get PMT match info from buffer", v_message, verbosityEBSaver); + // print which one was failed + if (!gotPairedPMTTriggerTimestamp) + Log("EBSaver: Failed to get PairedPMTTriggerTimestamp", v_message, verbosityEBSaver); + if (!gotPairedPMTTimeStamps) + Log("EBSaver: Failed to get PairedPMTTimeStamps", v_message, verbosityEBSaver); + if (!gotPairedPMT_TriggerIndex) + Log("EBSaver: Failed to get PairedPMT_TriggerIndex", v_message, verbosityEBSaver); + if (!gotPMTHitmapRunCode) + Log("EBSaver: Failed to get PMTHitmapRunCode", v_message, verbosityEBSaver); + } + // + // got MRD data + bool gotMRDEvents = m_data->CStore.Get("MRDEvents", MRDEvents); + bool gotMRDEventTriggerTypes = m_data->CStore.Get("MRDEventTriggerTypes", MRDEventTriggerTypes); + bool gotMRDBeamLoopback = m_data->CStore.Get("MRDBeamLoopback", MRDBeamLoopback); + bool gotMRDCosmicLoopback = m_data->CStore.Get("MRDCosmicLoopback", MRDCosmicLoopback); + if (!gotMRDEvents || !gotMRDEventTriggerTypes || !gotMRDBeamLoopback || !gotMRDCosmicLoopback) + Log("EBSaver: Failed to get some MRD data from buffer", v_message, verbosityEBSaver); + // got MRD match info + bool gotPairedMRDTriggerTimestamp = m_data->CStore.Get("PairedMRDTriggerTimestamp", PairedMRDTriggerTimestamp); + bool gotPairedMRDTimeStamps = m_data->CStore.Get("PairedMRDTimeStamps", PairedMRDTimeStamps); + bool gotPairedMRD_TriggerIndex = m_data->CStore.Get("PairedMRD_TriggerIndex", PairedMRD_TriggerIndex); + bool gotMRDHitMapRunCode = m_data->CStore.Get("MRDHitMapRunCode", MRDHitMapRunCode); + if (!gotPairedMRDTriggerTimestamp || !gotPairedMRDTimeStamps || !gotPairedMRD_TriggerIndex || !gotMRDHitMapRunCode) + Log("EBSaver: Failed to get MRD match info from buffer", v_message, verbosityEBSaver); + // + // got LAPPD data + bool gotBuffer_LAPPDTimestamp_ns = m_data->CStore.Get("Buffer_LAPPDTimestamp_ns", Buffer_LAPPDTimestamp_ns); + bool gotBuffer_LAPPDData = m_data->CStore.Get("Buffer_LAPPDData", Buffer_LAPPDData); + bool gotBuffer_LAPPDBeamgate_ns = m_data->CStore.Get("Buffer_LAPPDBeamgate_ns", Buffer_LAPPDBeamgate_ns); + bool gotBuffer_LAPPDOffset = m_data->CStore.Get("Buffer_LAPPDOffset", Buffer_LAPPDOffset); + bool gotBuffer_LAPPDBeamgate_Raw = m_data->CStore.Get("Buffer_LAPPDBeamgate_Raw", Buffer_LAPPDBeamgate_Raw); + bool gotBuffer_LAPPDTimestamp_Raw = m_data->CStore.Get("Buffer_LAPPDTimestamp_Raw", Buffer_LAPPDTimestamp_Raw); + bool gotBuffer_LAPPDBGCorrection = m_data->CStore.Get("Buffer_LAPPDBGCorrection", Buffer_LAPPDBGCorrection); + bool gotBuffer_LAPPDTSCorrection = m_data->CStore.Get("Buffer_LAPPDTSCorrection", Buffer_LAPPDTSCorrection); + bool gotBuffer_LAPPDOffset_minus_ps = m_data->CStore.Get("Buffer_LAPPDOffset_minus_ps", Buffer_LAPPDOffset_minus_ps); + if (!gotBuffer_LAPPDTimestamp_ns || !gotBuffer_LAPPDData || !gotBuffer_LAPPDBeamgate_ns || !gotBuffer_LAPPDOffset || !gotBuffer_LAPPDBeamgate_Raw || !gotBuffer_LAPPDTimestamp_Raw || !gotBuffer_LAPPDBGCorrection || !gotBuffer_LAPPDTSCorrection || !gotBuffer_LAPPDOffset_minus_ps) + Log("EBSaver: Failed to get some LAPPD data from buffer", v_message, verbosityEBSaver); + // got LAPPD match info + bool gotPairedLAPPDTriggerTimestamp = m_data->CStore.Get("PairedLAPPDTriggerTimestamp", PairedLAPPDTriggerTimestamp); + bool gotPairedLAPPDTimeStamps = m_data->CStore.Get("PairedLAPPDTimeStamps", PairedLAPPDTimeStamps); + bool gotPairedLAPPD_TriggerIndex = m_data->CStore.Get("PairedLAPPD_TriggerIndex", PairedLAPPD_TriggerIndex); + bool gotLAPPDRunCode = m_data->CStore.Get("Buffer_LAPPDRunCode", Buffer_LAPPDRunCode); + if (!gotPairedLAPPDTriggerTimestamp || !gotPairedLAPPDTimeStamps || !gotPairedLAPPD_TriggerIndex || !gotLAPPDRunCode) + { + Log("EBSaver: Failed to get LAPPD match info from buffer", v_message, verbosityEBSaver); + // print which one was failed + if (!gotPairedLAPPDTriggerTimestamp) + Log("EBSaver: Failed to get PairedLAPPDTriggerTimestamp", v_message, verbosityEBSaver); + if (!gotPairedLAPPDTimeStamps) + Log("EBSaver: Failed to get PairedLAPPDTimeStamps", v_message, verbosityEBSaver); + if (!gotPairedLAPPD_TriggerIndex) + Log("EBSaver: Failed to get PairedLAPPD_TriggerIndex", v_message, verbosityEBSaver); + if (!gotLAPPDRunCode) + Log("EBSaver: Failed to get LAPPDRunCode", v_message, verbosityEBSaver); + } + + Log("EBSaver: got PMT pairing information buffer PairedPMTTimeStamps size " + std::to_string(PairedPMTTimeStamps.size()), v_message, verbosityEBSaver); + Log("EBSaver: got MRD pairing information buffer PairedMRDTimeStamps size " + std::to_string(PairedMRDTimeStamps.size()), v_message, verbosityEBSaver); + for (auto const &track : PairedMRDTimeStamps) + { + int triggerTrack = track.first; + std::vector times = track.second; + Log("EBSaver: PairedMRDTimeStamps at track " + std::to_string(triggerTrack) + " size " + std::to_string(times.size()), v_message, verbosityEBSaver); + for (int i = 0; i < times.size(); i++) + cout << i << ": " << times[i] << ", "; + } + cout << endl; + + Log("EBSaver: got LAPPD pairing information buffer PairedLAPPDTimeStamps size " + std::to_string(PairedLAPPDTimeStamps.size()), v_message, verbosityEBSaver); + for (auto const &track : PairedLAPPDTimeStamps) + { + int triggerTrack = track.first; + std::vector times = track.second; + Log("EBSaver: PairedLAPPDTimeStamps at track " + std::to_string(triggerTrack) + " size " + std::to_string(times.size()), v_message, verbosityEBSaver); + for (int i = 0; i < times.size(); i++) + cout << i << ": " << times[i] << ", "; + } + cout << endl; + + // print PairedLAPPD_TriggerIndex + Log("EBSaver: got LAPPD pairing information buffer PairedLAPPD_TriggerIndex size " + std::to_string(PairedLAPPD_TriggerIndex.size()), v_message, verbosityEBSaver); + for (auto const &track : PairedLAPPD_TriggerIndex) + { + int triggerTrack = track.first; + std::vector indexes = track.second; + Log("EBSaver: PairedLAPPD_TriggerIndex at track " + std::to_string(triggerTrack) + " size " + std::to_string(indexes.size()), v_message, verbosityEBSaver); + for (int i = 0; i < indexes.size(); i++) + cout << i << ": " << indexes[i] << ", "; + } + cout << endl; + + // print Buffer_LAPPDBeamgate_ns + Log("EBSaver: got LAPPD pairing information buffer Buffer_LAPPDBeamgate_ns size " + std::to_string(Buffer_LAPPDBeamgate_ns.size()), v_message, verbosityEBSaver); + for (int i = 0; i < Buffer_LAPPDBeamgate_ns.size(); i++) + cout << i << ": " << Buffer_LAPPDBeamgate_ns[i] << ", "; + cout << endl; + + return true; +} + +void EBSaver::SetDataObjects() +{ + // after erase those data, set them back to CStore + // set PMT data + m_data->CStore.Set("InProgressHits", InProgressHits); + m_data->CStore.Set("InProgressChkey", InProgressChkey); + m_data->CStore.Set("InProgressRecoADCHits", InProgressRecoADCHits); + m_data->CStore.Set("InProgressHitsAux", InProgressHitsAux); + m_data->CStore.Set("InProgressRecoADCHitsAux", InProgressRecoADCHitsAux); + m_data->CStore.Set("FinishedRawAcqSize", FinishedRawAcqSize); + // set PMT match info + m_data->CStore.Set("PairedPMTTriggerTimestamp", PairedPMTTriggerTimestamp); + m_data->CStore.Set("PairedPMTTimeStamps", PairedPMTTimeStamps); + m_data->CStore.Set("PairedPMT_TriggerIndex", PairedPMT_TriggerIndex); + m_data->CStore.Set("PMTHitmapRunCode", PMTHitmapRunCode); + // set MRD data + m_data->CStore.Set("MRDEvents", MRDEvents); + m_data->CStore.Set("MRDEventTriggerTypes", MRDEventTriggerTypes); + m_data->CStore.Set("MRDBeamLoopback", MRDBeamLoopback); + m_data->CStore.Set("MRDCosmicLoopback", MRDCosmicLoopback); + // set MRD match info + m_data->CStore.Set("PairedMRDTriggerTimestamp", PairedMRDTriggerTimestamp); + m_data->CStore.Set("PairedMRDTimeStamps", PairedMRDTimeStamps); + m_data->CStore.Set("PairedMRD_TriggerIndex", PairedMRD_TriggerIndex); + m_data->CStore.Set("MRDHitMapRunCode", MRDHitMapRunCode); + // set LAPPD data + m_data->CStore.Set("Buffer_LAPPDTimestamp_ns", Buffer_LAPPDTimestamp_ns); + m_data->CStore.Set("Buffer_LAPPDData", Buffer_LAPPDData); + m_data->CStore.Set("Buffer_LAPPDBeamgate_ns", Buffer_LAPPDBeamgate_ns); + m_data->CStore.Set("Buffer_LAPPDOffset", Buffer_LAPPDOffset); + m_data->CStore.Set("Buffer_LAPPDBeamgate_Raw", Buffer_LAPPDBeamgate_Raw); + m_data->CStore.Set("Buffer_LAPPDTimestamp_Raw", Buffer_LAPPDTimestamp_Raw); + m_data->CStore.Set("Buffer_LAPPDBGCorrection", Buffer_LAPPDBGCorrection); + m_data->CStore.Set("Buffer_LAPPDTSCorrection", Buffer_LAPPDTSCorrection); + m_data->CStore.Set("Buffer_LAPPDOffset_minus_ps", Buffer_LAPPDOffset_minus_ps); + // set LAPPD match info + m_data->CStore.Set("PairedLAPPDTriggerTimestamp", PairedLAPPDTriggerTimestamp); + m_data->CStore.Set("PairedLAPPDTimeStamps", PairedLAPPDTimeStamps); + m_data->CStore.Set("PairedLAPPD_TriggerIndex", PairedLAPPD_TriggerIndex); + m_data->CStore.Set("Buffer_LAPPDRunCode", Buffer_LAPPDRunCode); +} + +void EBSaver::BuildEmptyPMTData() +{ + std::map> *PMTHits = new std::map>; + std::map>> PMTRecoADCHits; + std::map> *PMTHitsAux = new std::map>; + std::map>> PMTRecoADCHitsAux; + std::map> PMTRawAcqSize; + + ANNIEEvent->Set("Hits", PMTHits, true); + ANNIEEvent->Set("RecoADCData", PMTRecoADCHits); + ANNIEEvent->Set("AuxHits", PMTHitsAux, true); + ANNIEEvent->Set("RecoAuxADCData", PMTRecoADCHitsAux); + ANNIEEvent->Set("RawAcqSize", PMTRawAcqSize); +} + +void EBSaver::BuildEmptyMRDData() +{ + std::map> *TDCData = new std::map>; + std::string MRDTriggerType = ""; + std::map mrd_loopback_tdc; + + ANNIEEvent->Set("TDCData", TDCData, true); + TimeClass t(0); + ANNIEEvent->Set("EventTimeMRD", t); + ANNIEEvent->Set("MRDTriggerType", MRDTriggerType); + ANNIEEvent->Set("MRDLoopbackTDC", mrd_loopback_tdc); +} + +void EBSaver::BuildEmptyLAPPDData() +{ + std::map LAPPDDataMap; + std::map LAPPDBeamgate_ns; + std::map LAPPDTimeStamps_ns; // data and key are the same + std::map LAPPDTimeStampsRaw; + std::map LAPPDBeamgatesRaw; + std::map LAPPDOffsets; + std::map LAPPDTSCorrection; + std::map LAPPDBGCorrection; + std::map LAPPDOSInMinusPS; + + ANNIEEvent->Set("LAPPDDataMap", LAPPDDataMap); + ANNIEEvent->Set("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + ANNIEEvent->Set("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); + ANNIEEvent->Set("LAPPDTimeStampsRaw", LAPPDTimeStampsRaw); + ANNIEEvent->Set("LAPPDBeamgatesRaw", LAPPDBeamgatesRaw); + ANNIEEvent->Set("LAPPDOffsets", LAPPDOffsets); + ANNIEEvent->Set("LAPPDTSCorrection", LAPPDTSCorrection); + ANNIEEvent->Set("LAPPDBGCorrection", LAPPDBGCorrection); + ANNIEEvent->Set("LAPPDOSInMinusPS", LAPPDOSInMinusPS); +} \ No newline at end of file diff --git a/UserTools/EBSaver/EBSaver.h b/UserTools/EBSaver/EBSaver.h new file mode 100644 index 000000000..1388b07dd --- /dev/null +++ b/UserTools/EBSaver/EBSaver.h @@ -0,0 +1,167 @@ +#ifndef EBSaver_H +#define EBSaver_H + +#include +#include + +#include "Tool.h" +#include "BoostStore.h" +#include "PsecData.h" +#include "TimeClass.h" +#include "TriggerClass.h" +#include "Waveform.h" +#include "ANNIEalgorithms.h" +#include "ADCPulse.h" +#include "CalibratedADCWaveform.h" +#include "BeamStatus.h" + +/** + * \class EBSaver + * + * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. + * + * $Author: B.Richards $ + * $Date: 2019/05/28 10:44:00 $ + * Contact: b.richards@qmul.ac.uk + */ +class EBSaver : public Tool +{ + +public: + EBSaver(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + + bool GotAllDataFromOriginalBuffer(); + void SetDataObjects(); + + bool SaveToANNIEEvent(string saveFileName, int runCode, int triggerTrack, int trackIndex); // save the data to the ANNIEEvent, include all other saving functions. + bool SaveRunInfo(int runCode); // get run numbers from the RunCode in trigger grouper + bool SaveGroupedTriggers(int triggerTrack, int groupIndex); + // use the targetTrigWord to get the trigger track, use the groupIndex to get the group of triggers in that track + // save triggers from std::map>> GroupedTriggersInTotal; //each map is a group of triggers, with the key is the target trigger word + + bool SavePMTData(uint64_t PMTTime); + bool SaveMRDData(uint64_t MRDTime); + bool SaveLAPPDData(uint64_t LAPPDTime); + + bool SaveOrphan(int runCode); + bool SaveOrphanPMT(int runCode); + bool SaveOrphanMRD(int runCode); + bool SaveOrphanCTC(int runCode); + bool SaveOrphanLAPPD(int runCode); + + void BuildEmptyPMTData(); + void BuildEmptyMRDData(); + void BuildEmptyLAPPDData(); + +private: + int saveRunNumber; + int saveSubrunNumber; + int savePartFileNumber; + int savingRunCode; + + bool saveTriggerGroups = true; + bool saveAllTriggers; + bool savePMT = true; + bool saveMRD; + bool saveLAPPD; + bool saveOrphan; + + string savePath; + string saveName; + + int verbosityEBSaver; + int v_message = 1; + int v_warning = 2; + int v_error = 3; + int v_debug = 4; + + BoostStore *ANNIEEvent; + + int exeNumber; + int savedTriggerGroupNumber; + int savedPMTHitMapNumber; + int savedMRDNumber; + int savedLAPPDNumber; + + std::map TriggerTimeWithoutMRD; //trigger time, 8 or 36 + + int thisRunNum; + int thisSubrunNum; + int thisPartFileNum; + + int savePerExe; + + int TotalBuiltEventsNumber; + int TotalBuiltPMTNumber; + int TotalBuiltMRDNumber; + int TotalBuiltLAPPDNumber; + int TotalBuiltTriggerGroupNumber; + + std::map PMTRunCodeToRemove; + std::map MRDRunCodeToRemove; + std::map LAPPDRunCodeToRemove; + std::map GroupedTriggerIndexToRemove; + + std::map> PMTPairInfoToRemoveTime; + std::map> MRDPairInfoToRemoveTime; + std::map> LAPPDPairInfoToRemoveTime; + + + std::map>> GroupedTriggersInTotal; // each map is a group of triggers, with the key is the target trigger word + std::map> RunCodeInTotal; + + int BeamTriggerMain; + int LaserTriggerMain; + int CosmicTriggerMain; + int LEDTriggerMain; + int AmBeTriggerMain; + int PPSMain; + + // PMT related data object + std::map> *> *InProgressHits; // Key: {MTCTime}, value: map of Hit distributions + std::map> *InProgressChkey; // Key: {MTCTime}, value: vector of in progress chankeys + std::map>>> *InProgressRecoADCHits; // Key: {MTCTime}, value: map of found pulses + std::map>>> *InProgressRecoADCHitsAux; // Key: {MTCTime}, value: map of found pulses + std::map> *> *InProgressHitsAux; // Key: {MTCTime}, value: map of Hit distributions + std::map>> *FinishedRawAcqSize; // Key: {MTCTime}, value: map of acquisition time window sizes + + std::map> PairedPMTTriggerTimestamp; + std::map> PairedPMT_TriggerIndex; + std::map> PairedPMTTimeStamps; + std::map PMTHitmapRunCode; // Key: {MTCTime}, value: RunCode + + // MRD related data object + std::map>> MRDEvents; // Key: {MTCTime}, value: "WaveMap" with key (CardID,ChannelID), value FinishedWaveform + std::map MRDEventTriggerTypes; // Key: {MTCTime}, value: string noting what type of trigger occured for the event + std::map MRDBeamLoopback; // Key: {MTCTime}, value: string noting what type of trigger occured for the event + std::map MRDCosmicLoopback; // KEY: {MTCTime}, value: Cosmic loopback TDC value + + std::map> PairedMRDTriggerTimestamp; + std::map> PairedMRD_TriggerIndex; + std::map> PairedMRDTimeStamps; + std::map MRDHitMapRunCode; // Key: {MTCTime}, value: RunCode + + // LAPPD related data object + vector Buffer_IndexOfData; // index of unpaired data + vector Buffer_LAPPDTimestamp_ns; // used to match + + vector Buffer_LAPPDData; + vector Buffer_LAPPDBeamgate_ns; + vector Buffer_LAPPDOffset; + vector Buffer_LAPPDBeamgate_Raw; + vector Buffer_LAPPDTimestamp_Raw; + vector Buffer_LAPPDBGCorrection; + vector Buffer_LAPPDTSCorrection; + vector Buffer_LAPPDOffset_minus_ps; + + vector Buffer_LAPPDRunCode; + + std::map> PairedLAPPDTriggerTimestamp; + std::map> PairedLAPPD_TriggerIndex; + std::map> PairedLAPPDTimeStamps; +}; + +#endif diff --git a/UserTools/EBSaver/README.md b/UserTools/EBSaver/README.md new file mode 100644 index 000000000..a96d57ce3 --- /dev/null +++ b/UserTools/EBSaver/README.md @@ -0,0 +1,20 @@ +# EBSaver + +EBSaver + +## Data + +Describe any data formats EBSaver creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for EBSaver. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/EBTriggerGrouper/EBTriggerGrouper.cpp b/UserTools/EBTriggerGrouper/EBTriggerGrouper.cpp new file mode 100644 index 000000000..b35dffbe9 --- /dev/null +++ b/UserTools/EBTriggerGrouper/EBTriggerGrouper.cpp @@ -0,0 +1,723 @@ +#include "EBTriggerGrouper.h" + +EBTriggerGrouper::EBTriggerGrouper() : Tool() {} + +bool EBTriggerGrouper::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + m_variables.Get("verbosityEBTG", verbosityEBTG); + savePath = ""; + m_variables.Get("savePath", savePath); + m_variables.Get("GroupMode", GroupMode); + m_variables.Get("GroupTolerance", GroupTolerance); + m_variables.Get("GroupTrigWord", GroupTrigWord); + + TimeToTriggerWordMap = new std::map>; + TimeToTriggerWordMapComplete = new std::map>; + + groupBeam = true; + m_variables.Get("groupBeam", groupBeam); + groupCosmic = false; + m_variables.Get("groupCosmic", groupCosmic); + groupLaser = true; + m_variables.Get("groupLaser", groupLaser); + groupLED = false; + m_variables.Get("groupLED", groupLED); + groupAmBe = false; + m_variables.Get("groupAmBe", groupAmBe); + groupPPS = false; + m_variables.Get("groupPPS", groupPPS); + + BeamTriggerMain = 14; + BeamTolerance = 3000000; // use 3 ms here, the spill time difference is 66ms + m_variables.Get("BeamTolerance", BeamTolerance); + BeamTriggers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 14, 37, 38, 40, 41, 46}; + m_data->CStore.Set("BeamTriggersUsedForGroupping", BeamTriggers); + m_data->CStore.Set("BeamTriggerMain", BeamTriggerMain); + + LaserTriggerMain = 47; + m_variables.Get("LaserTriggerMain", LaserTriggerMain); + LaserTolerance = 1000; // 1us + m_variables.Get("LaserTolerance", LaserTolerance); + LaserTriggers = {47, 46}; // 47 first, then 46, (~232ns in run 4692 data) + m_data->CStore.Set("LaserTriggersUsedForGroupping", LaserTriggers); + + PPSTriggerMain = 32; + PPSTolerance = 30000; // 30 us + m_variables.Get("PPSTolerance", PPSTolerance); + PPSTriggers = {32, 34}; // 32 first, then 34, (~20us in run 4802 data) + m_data->CStore.Set("PPSTriggersUsedForGroupping", PPSTriggers); + + CosmicTriggerMain = 44; // TODO need to check + m_variables.Get("CosmicTriggerMain", CosmicTriggerMain); + CosmicTolerance = 330000; // 330000ns, TODO + m_variables.Get("CosmicTolerance", CosmicTolerance); + CosmicTriggers = {44, 45, 36, 27, 28, 29, 30, 46}; // TODO: check the trigger words in cosmic run + m_data->CStore.Set("CosmicTriggersUsedForGroupping", CosmicTriggers); + + LEDTriggerMain = 31; // need to check + m_variables.Get("LEDTriggerMain", LEDTriggerMain); + LEDTolerance = 1000; // 1ms 440ns in LED run 4792 + m_variables.Get("LEDTolerance", LEDTolerance); + LEDTriggers = {33, 22, 31, 43, 46}; // in run 4792 [[22, 33], [4160001224, 4160001664]] + m_data->CStore.Set("LEDTriggersUsedForGroupping", LEDTriggers); + + AmBeTriggerMain = 19; // TODO: need to check + m_variables.Get("AmBeTriggerMain", AmBeTriggerMain); + AmBeTolerance = 5000; // 2336 in Ambe run 4707 + m_variables.Get("AmBeTolerance", AmBeTolerance); + AmBeTriggers = {11, 12, 15, 19}; // in run 4707 [[19, 12, 15, 11], [21275647928, 21275647936, 21275647952, 21275650264]] + m_data->CStore.Set("AmBeTriggersUsedForGroupping", AmBeTriggers); + + StoreTotalEntry = 0; + + maxNumAllowedInBuffer = 10000; + m_variables.Get("maxNumAllowedInBuffer", maxNumAllowedInBuffer); + Log("EBTG: maxNumAllowedInBuffer = " + std::to_string(maxNumAllowedInBuffer), v_message, verbosityEBTG); + + return true; +} + +bool EBTriggerGrouper::Execute() +{ + bool NewCTCDataAvailable = false; + m_data->CStore.Get("NewCTCDataAvailable", NewCTCDataAvailable); + Log("EBTG: NewCTCDataAvailable = " + std::to_string(NewCTCDataAvailable), v_message, verbosityEBTG); + bool FileProcessingComplete = false; + m_data->CStore.Get("FileProcessingComplete", FileProcessingComplete); + if (FileProcessingComplete) + { + Log("EBTG: FileProcessingComplete = " + std::to_string(FileProcessingComplete), v_message, verbosityEBTG); + return true; + } + if (!NewCTCDataAvailable) + { + Log("EBTG: No new CTC data avaliable", v_message, verbosityEBTG); + return true; + } + Log("EBTG: Get Run information", v_message, verbosityEBTG); + m_data->CStore.Get("RunNumber", CurrentRunNum); + m_data->CStore.Get("SubRunNumber", CurrentSubrunNum); + int CurrentUsingPartNum = CurrentPartNum; + m_data->CStore.Get("PartFileNumber", CurrentPartNum); + m_data->CStore.Get("RunCode", currentRunCode); + + m_data->CStore.Get("usingTriggerOverlap", usingTriggerOverlap); + if (usingTriggerOverlap) + { + CurrentPartNum -= 1; + Log("EBTG: usingTriggerOverlap, CurrentPartNum was minused 1 to be " + std::to_string(CurrentPartNum), v_message, verbosityEBTG); + } + + /* + if (CurrentPartNum != CurrentUsingPartNum) + { + Log("EBTG: PartFileNumber changed from " + std::to_string(CurrentUsingPartNum) + " to " + std::to_string(CurrentPartNum) + " Clear buffer with size " + std::to_string(TrigTimeForGroup.size()), v_message, verbosityEBTG); + TrigTimeForGroup.clear(); + TrigWordForGroup.clear(); + }*/ + + Log("EBTG: Accessing new Trigger data in CStore", v_message, verbosityEBTG); + m_data->CStore.Get("TimeToTriggerWordMap", TimeToTriggerWordMap); + m_data->CStore.Get("TimeToTriggerWordMapComplete", TimeToTriggerWordMapComplete); + + // do grouping in the TimeToTriggerWordMap, remove the groupped triggers from both of them + // 1. load the trigger from TimeToTriggerWordMap to local buffer TrigTimeForGroup and TrigWordForGroup, clean it + // 2. group the triggers in buffer, save to GroupedTriggers, and remove grouped trigger from buffer + // 2.1 group trigger based on trigger word selection or time Tolerance relative to the target trigger + // 2.2 for left triggers, pair them with the grouped trigger using the same Tolerance fo cover triggers before the target trigger + // 2.3 run for different trigger tracks. like pps + + // Finally we should have: + // 1. GroupedTriggers: mutiple grouped trigger tracks + // 2. buffer: left triggers in buffer, not grouped + + vector TriggerToRemove; + for (auto it = TimeToTriggerWordMap->begin(); it != TimeToTriggerWordMap->end(); ++it) + { + uint64_t timestamp = it->first; + std::vector triggers = it->second; + bool stopLoading = false; + + // if found the target trigger in the trigger vector, stop loading to buffer. + if (usingTriggerOverlap) + { + for (auto trig = triggers.begin(); trig != triggers.end(); ++trig) + { + if (*trig == GroupTrigWord) + stopLoading = true; + Log("EBTG: when using TriggerOverlap, met the new target trigger " + std::to_string(GroupTrigWord) + ", stop loading to buffer", v_message, verbosityEBTG); + } + } + if (stopLoading) + break; + + for (auto trig = triggers.begin(); trig != triggers.end(); ++trig) + { + TrigTimeForGroup.push_back(timestamp); + TrigWordForGroup.push_back(*trig); + TriggerToRemove.push_back(timestamp); + StoreTotalEntry++; + if (verbosityEBTG > 11) + cout << "EBTG: TrigTimeForGroup: " << timestamp << " TrigWordForGroup: " << *trig << endl; + } + } + Log("EBTG: finish loading trigger from TimeToTriggerWordMap, buffer TrigTimeForGroup size = " + std::to_string(TrigTimeForGroup.size()) + ", loaded TimeToTriggerWordMap size = " + std::to_string(TimeToTriggerWordMap->size()), v_message, verbosityEBTG); + Log("EBTG: Start erase triggers from TimeToTriggerWordMap and TimeToTriggerWordMapComplete, TimeToTriggerWordMap and TimeToTriggerWordMapComplete size = " + std::to_string(TimeToTriggerWordMap->size()) + ", " + std::to_string(TimeToTriggerWordMapComplete->size()), v_message, verbosityEBTG); + for (int i = 0; i < TriggerToRemove.size(); i++) + { + TimeToTriggerWordMap->erase(TriggerToRemove[i]); + TimeToTriggerWordMapComplete->erase(TriggerToRemove[i]); + } + Log("EBTG: Finish erase triggers from TimeToTriggerWordMap and TimeToTriggerWordMapComplete, TimeToTriggerWordMap and TimeToTriggerWordMapComplete size = " + std::to_string(TimeToTriggerWordMap->size()) + ", " + std::to_string(TimeToTriggerWordMapComplete->size()), v_message, verbosityEBTG); + + /*{ + //TODO: this should be removed after later changes was made + Log("EBTG: Start grouping based on trigger word " + std::to_string(GroupTrigWord), v_message, verbosityEBTG); + + GroupByTolerance(); // remove grouped trigger in the function + FillByTolerance(); + //CleanBuffer(); + + Log("EBTG: grouping and filling finishes, buffer size is " + std::to_string(TrigTimeForGroup.size()) + ", now save to CStore", v_message, verbosityEBTG); + + m_data->CStore.Set("GroupedTriggers", GroupedTriggers); + }*/ + + m_data->CStore.Set("TrigTimeForGroup", TrigTimeForGroup); + m_data->CStore.Set("TrigWordForGroup", TrigWordForGroup); + + Log("EBTG: Start grouping for different trigger tracks", v_message, verbosityEBTG); + if (groupBeam) + { + Log("EBTG: Grouping Beam Triggers", v_message, verbosityEBTG); + int groupNum = GroupByTrigWord(BeamTriggerMain, BeamTriggers, BeamTolerance); + int fillNum = FillByTrigWord(BeamTriggerMain, BeamTriggers, BeamTolerance); + Log("EBTG: Found Beam Trigger group: " + std::to_string(groupNum) + ". Fill additional triggers to group: " + std::to_string(fillNum), v_message, verbosityEBTG); + m_data->CStore.Set("BeamTriggerGroupped", true); + } + else + { + m_data->CStore.Set("BeamTriggerGroupped", false); + } + + if (groupCosmic) + { + Log("EBTG: Grouping Cosmic Triggers", v_message, verbosityEBTG); + int groupNum = GroupByTrigWord(CosmicTriggerMain, CosmicTriggers, CosmicTolerance); + int fillNum = FillByTrigWord(CosmicTriggerMain, CosmicTriggers, CosmicTolerance); + Log("EBTG: Found Cosmic Trigger group: " + std::to_string(groupNum) + ". Fill additional triggers to group: " + std::to_string(fillNum), v_message, verbosityEBTG); + m_data->CStore.Set("CosmicTriggerGroupped", true); + } + else + { + m_data->CStore.Set("CosmicTriggerGroupped", false); + } + + if (groupLaser) + { + Log("EBTG: Grouping Laser Triggers", v_message, verbosityEBTG); + int groupNum = GroupByTrigWord(LaserTriggerMain, LaserTriggers, LaserTolerance); + int fillNum = FillByTrigWord(LaserTriggerMain, LaserTriggers, LaserTolerance); + Log("EBTG: Found Laser Trigger group: " + std::to_string(groupNum) + ". Fill additional triggers to group: " + std::to_string(fillNum), v_message, verbosityEBTG); + m_data->CStore.Set("LaserTriggerGroupped", true); + } + else + { + m_data->CStore.Set("LaserTriggerGroupped", false); + } + + if (groupLED) + { + Log("EBTG: Grouping LED Triggers", v_message, verbosityEBTG); + int groupNum = GroupByTrigWord(LEDTriggerMain, LEDTriggers, LEDTolerance); + int fillNum = FillByTrigWord(LEDTriggerMain, LEDTriggers, LEDTolerance); + Log("EBTG: Found LED Trigger group: " + std::to_string(groupNum) + ". Fill additional triggers to group: " + std::to_string(fillNum), v_message, verbosityEBTG); + m_data->CStore.Set("LEDTriggerGroupped", true); + } + else + { + m_data->CStore.Set("LEDTriggerGroupped", false); + } + + if (groupAmBe) + { + Log("EBTG: Grouping AmBe Triggers", v_message, verbosityEBTG); + int groupNum = GroupByTrigWord(AmBeTriggerMain, AmBeTriggers, AmBeTolerance); + int fillNum = FillByTrigWord(AmBeTriggerMain, AmBeTriggers, AmBeTolerance); + Log("EBTG: Found AmBe Trigger group: " + std::to_string(groupNum) + ". Fill additional triggers to group: " + std::to_string(fillNum), v_message, verbosityEBTG); + m_data->CStore.Set("AmBeTriggerGroupped", true); + } + else + { + m_data->CStore.Set("AmBeTriggerGroupped", false); + } + + if (groupPPS) + { + Log("EBTG: Grouping PPS Triggers", v_message, verbosityEBTG); + int groupNum = GroupByTrigWord(PPSTriggerMain, PPSTriggers, PPSTolerance); + int fillNum = FillByTrigWord(PPSTriggerMain, PPSTriggers, PPSTolerance); + Log("EBTG: Found PPS Trigger group: " + std::to_string(groupNum) + ". Fill additional triggers to group: " + std::to_string(fillNum), v_message, verbosityEBTG); + m_data->CStore.Set("PPSTriggerGroupped", true); + } + else + { + m_data->CStore.Set("PPSTriggerGroupped", false); + } + + Log("EBTG: Grouping for different trigger tracks finishes, save to CStore", v_message, verbosityEBTG); + m_data->CStore.Set("GroupedTriggersInTotal", GroupedTriggersInTotal); + m_data->CStore.Set("RunCodeInTotal", RunCodeInTotal); + + int removedTriggerNumber = CleanTriggerBuffer(); + Log("EBTG: CleanTriggerBuffer finishes, removed " + std::to_string(removedTriggerNumber) + " triggers from buffer, buffer size = " + std::to_string(TrigTimeForGroup.size()), v_message, verbosityEBTG); + + return true; +} + +bool EBTriggerGrouper::Finalise() +{ + Log("\033[1;34mEBTG: Finalising\033[0m", v_message, verbosityEBTG); + Log("EBTG: GroupedTriggersInTotal track number = " + std::to_string(GroupedTriggersInTotal.size()), v_message, verbosityEBTG); + for (auto it = GroupedTriggersInTotal.begin(); it != GroupedTriggersInTotal.end(); ++it) + { + Log("EBTG: GroupedTriggersInTotal track " + std::to_string(it->first) + " size = " + std::to_string(it->second.size()), v_message, verbosityEBTG); + } + Log("EBTG: In configfile, set left trigger number = " + std::to_string(maxNumAllowedInBuffer), v_message, verbosityEBTG); + Log("EBTG: Left Total loaded trigger number to buffer = " + std::to_string(StoreTotalEntry), v_message, verbosityEBTG); + Log("EBTG: Ungrouped triggers in buffer size = " + std::to_string(TrigTimeForGroup.size()), v_message, verbosityEBTG); + // calculate which trigger word left in TrigWordForGroup, and print them + std::map triggerWordCount; + for (int i = 0; i < TrigWordForGroup.size(); i++) + { + triggerWordCount[TrigWordForGroup[i]]++; + } + for (auto it = triggerWordCount.begin(); it != triggerWordCount.end(); ++it) + { + Log("EBTG: Trigger word " + std::to_string(it->first) + " left in buffer " + std::to_string(it->second) + " times", v_message, verbosityEBTG); + } + Log("EBTG: Ungrouped triggers in TimeToTriggerWordMap size = " + std::to_string(TimeToTriggerWordMap->size()), v_message, verbosityEBTG); + Log("EBTG: Ungrouped triggers in TimeToTriggerWordMapComplete size = " + std::to_string(TimeToTriggerWordMapComplete->size()), v_message, verbosityEBTG); + + // print first 10000 triggers to a txt for debug + Log("EBTG: Save first 2000 triggers in each track of GroupedTriggersInTotal to TrigDebugGrouped.txt", v_message, verbosityEBTG); + ofstream trigDebugGrouped; + trigDebugGrouped.open("TrigDebugGrouped.txt"); + trigDebugGrouped << "trackTargetTrigger groupIndex triggerTime triggerWord" << endl; + for (auto it = GroupedTriggersInTotal.begin(); it != GroupedTriggersInTotal.end(); ++it) + { + int i = 0; + for (int j = 0; j < it->second.size(); j++) + { + for (auto trig = it->second[j].begin(); trig != it->second[j].end(); ++trig) + { + if (i > 2000) + break; + trigDebugGrouped << it->first << " " << j << " " << trig->first << " " << trig->second << endl; + i++; + } + if (i > 2000) + break; + } + } + trigDebugGrouped.close(); + Log("EBTG: Save first 10000 triggers in TrigTimeForGroup to TrigDebugBufferLeft.txt", v_message, verbosityEBTG); + ofstream trigDebugBufferLeft; + trigDebugBufferLeft.open("TrigDebugBufferLeft.txt"); + for (int i = 0; i < TrigTimeForGroup.size(); i++) + { + if (i > 10000) + break; + trigDebugBufferLeft << i << " " << TrigTimeForGroup[i] << " " << TrigWordForGroup[i] << endl; + } + Log("EBTG: Save first 2000 triggers in TimeToTriggerWordMap to TrigDebug.txt", v_message, verbosityEBTG); + ofstream trigDebug; + trigDebug.open("TrigDebug.txt"); + int i = 0; + for (auto it = TimeToTriggerWordMap->begin(); it != TimeToTriggerWordMap->end(); ++it) + { + if (i > 2000) + break; + trigDebug << it->first << " "; + for (auto trig = it->second.begin(); trig != it->second.end(); ++trig) + { + trigDebug << *trig << " "; + } + trigDebug << endl; + i++; + } + trigDebug.close(); + + Log("EBTG: Printing SkippedDuplicateTriggers", v_message, verbosityEBTG); + int totalSkipped = 0; + for (auto it = SkippedDuplicateTriggers.begin(); it != SkippedDuplicateTriggers.end(); ++it) + { + Log("EBTG: Skipped " + std::to_string(it->second) + " groups of triggers for trigger track " + std::to_string(it->first), v_message, verbosityEBTG); + totalSkipped += it->second; + } + Log("EBTG: Total skipped groups of triggers = " + std::to_string(totalSkipped), v_message, verbosityEBTG); + + return true; +} + +bool EBTriggerGrouper::GroupByTolerance() +{ + Log("EBTG: GroupByTolerance()", v_warning, verbosityEBTG); + Log("EBTG: Grouping by Tolerance: " + std::to_string(GroupTolerance), v_warning, verbosityEBTG); + Log("EBTG: size of time buffer before grouping is " + std::to_string(TrigTimeForGroup.size()) + ", size of word buffer is " + std::to_string(TrigWordForGroup.size()), v_warning, verbosityEBTG); + bool found = false; + uint64_t prev_target_time = 0; + std::map ThisGroup; + vector toRemove; + int totalGroupedTriggerNumber = 0; + for (int i = 0; i < TrigTimeForGroup.size(); i++) + { + uint64_t dt = 0; + if (TrigTimeForGroup[i] > prev_target_time) + dt = TrigTimeForGroup[i] - prev_target_time; + else if (TrigTimeForGroup[i] < prev_target_time) + dt = prev_target_time - TrigTimeForGroup[i]; + else if (TrigTimeForGroup[i] == prev_target_time) + dt = 0; + + if (!found && TrigWordForGroup[i] == GroupTrigWord) + { + found = true; + ThisGroup.clear(); + prev_target_time = TrigTimeForGroup[i]; + ThisGroup.insert(std::pair(TrigTimeForGroup[i], TrigWordForGroup[i])); + toRemove.push_back(i); + } + else if (found && dt < GroupTolerance) + { + + ThisGroup.insert(std::pair(TrigTimeForGroup[i], TrigWordForGroup[i])); + toRemove.push_back(i); + if (TrigWordForGroup[i] == 10 || TrigWordForGroup[i] == 40 || TrigWordForGroup[i] == 41) + { + ThisGroup.insert(std::pair(TrigTimeForGroup[i] + 1, TrigWordForGroup[i])); + } + ///!!! attention, the trigger word 10 always come with 8 with the same time, so it won't be inserted to the map + // Therefore we add another 1ns to it, but it's not real + } + else if (found && dt > GroupTolerance) + { + if (verbosityEBTG > 9) + { + // print all triggers in this group + cout << "EBTG: GroupByTolerance: ThisGroup size = " << ThisGroup.size() << endl; + for (auto it = ThisGroup.begin(); it != ThisGroup.end(); ++it) + { + cout << it->first << " - " << it->second << ", "; + } + cout << endl; + } + GroupedTriggers.push_back(ThisGroup); + totalGroupedTriggerNumber += ThisGroup.size(); + ThisGroup.clear(); + found = false; + } + } + int totalToRemoveTriggerNumber = toRemove.size(); + // from end to beginning, remove the triggers in buffer based on toRemove index + for (int i = toRemove.size() - 1; i >= 0; i--) + { + TrigTimeForGroup.erase(TrigTimeForGroup.begin() + toRemove[i]); + TrigWordForGroup.erase(TrigWordForGroup.begin() + toRemove[i]); + } + Log("EBTG: GroupByTolerance Finished, accumulated saved " + std::to_string(GroupedTriggers.size()) + " group of triggers", v_warning, verbosityEBTG); + Log("EBTG: buffer TriggersForGroup after grouping size = " + std::to_string(TrigTimeForGroup.size()), v_warning, verbosityEBTG); + Log("EBTG: totalGroupedTriggerNumber in this grouping step is: " + std::to_string(totalGroupedTriggerNumber) + ", totalToRemoveTriggerNumber = " + std::to_string(totalToRemoveTriggerNumber), v_warning, verbosityEBTG); + + return true; +} + +bool EBTriggerGrouper::FillByTolerance() +{ + Log("EBTG: FillByTolerance()", v_warning, verbosityEBTG); + Log("EBTG: Fill by Tolerance: " + std::to_string(GroupTolerance), v_warning, verbosityEBTG); + Log("EBTG: size of time buffer before refilling is " + std::to_string(TrigTimeForGroup.size()) + ", size of word buffer is " + std::to_string(TrigWordForGroup.size()), v_warning, verbosityEBTG); + + int addedTriggerNumber = 0; + + for (int i = TrigTimeForGroup.size() - 1; i >= 0; i--) + { + for (int j = 0; j < GroupedTriggers.size(); j++) + { + + for (auto it = GroupedTriggers[j].begin(); it != GroupedTriggers[j].end(); ++it) + { + if (it->second == GroupTrigWord) + { + uint64_t dt = (TrigTimeForGroup[i] > it->first) ? (TrigTimeForGroup[i] - it->first) : (it->first - TrigTimeForGroup[i]); + if (dt < GroupTolerance) + { + GroupedTriggers[j].insert(std::make_pair(TrigTimeForGroup[i], TrigWordForGroup[i])); + TrigTimeForGroup.erase(TrigTimeForGroup.begin() + i); + TrigWordForGroup.erase(TrigWordForGroup.begin() + i); + addedTriggerNumber++; + break; + } + } + } + } + } + + Log("EBTG: FillByTolerance Finished, addedTriggerNumber = " + std::to_string(addedTriggerNumber), v_warning, verbosityEBTG); + Log("EBTG: buffer TriggersForGroup after refilling size = " + std::to_string(TrigTimeForGroup.size()), v_warning, verbosityEBTG); + + return true; +} + +bool EBTriggerGrouper::CleanBuffer() +{ + Log("EBTG: CleanBuffer()", v_warning, verbosityEBTG); + Log("EBTG: size of time buffer before cleaning is " + std::to_string(TrigTimeForGroup.size()) + ", size of word buffer is " + std::to_string(TrigWordForGroup.size()), v_warning, verbosityEBTG); + // check is there any target trigger word in the buffer + // if yes, print a warning message + // only leave the last 100 triggers in the buffer + int numberOfTargetTriggers = 0; + for (int i = 0; i < TrigWordForGroup.size(); i++) + { + if (TrigWordForGroup[i] == GroupTrigWord) + { + numberOfTargetTriggers++; + } + } + if (numberOfTargetTriggers > 0) + { + Log("EBTG: CleanBuffer: Warning: there are " + std::to_string(numberOfTargetTriggers) + " target trigger words in the buffer", v_warning, verbosityEBTG); + } + else + { + Log("EBTG: CleanBuffer: no target trigger words left in the buffer.", v_warning, verbosityEBTG); + } + if (TrigTimeForGroup.size() > 100) + { + TrigTimeForGroup.erase(TrigTimeForGroup.begin(), TrigTimeForGroup.end() - 100); + TrigWordForGroup.erase(TrigWordForGroup.begin(), TrigWordForGroup.end() - 100); + } + Log("EBTG: CleanBuffer Finished, buffer size = " + std::to_string(TrigTimeForGroup.size()), v_warning, verbosityEBTG); + return true; +} + +int EBTriggerGrouper::GroupByTrigWord(uint32_t mainTrigWord, vector TrigWords, int tolerance) +{ + Log("EBTG: GroupByTrigWord()", v_warning, verbosityEBTG); + Log("EBTG: Grouping by TrigWord: " + std::to_string(mainTrigWord), v_warning, verbosityEBTG); + Log("EBTG: size of time buffer before grouping is " + std::to_string(TrigTimeForGroup.size()) + ", size of word buffer is " + std::to_string(TrigWordForGroup.size()), v_warning, verbosityEBTG); + bool found = false; + uint64_t prev_target_time = 0; + std::map ThisGroup; + vector toRemove; + int totalGroupedTriggerNumber = 0; + uint64_t trackTriggerTime = 0; + uint32_t trackTriggerWord = 0; + + for (int i = 0; i < TrigTimeForGroup.size(); i++) + { + uint64_t dt = 0; + if (TrigTimeForGroup[i] > prev_target_time) + dt = TrigTimeForGroup[i] - prev_target_time; + else if (TrigTimeForGroup[i] < prev_target_time) + dt = prev_target_time - TrigTimeForGroup[i]; + else if (TrigTimeForGroup[i] == prev_target_time) + dt = 0; + + if (!found && TrigWordForGroup[i] == mainTrigWord) + { + found = true; + ThisGroup.clear(); + prev_target_time = TrigTimeForGroup[i]; + ThisGroup.insert(std::pair(TrigTimeForGroup[i], TrigWordForGroup[i])); + trackTriggerTime = TrigTimeForGroup[i]; + trackTriggerWord = TrigWordForGroup[i]; + toRemove.push_back(i); + } + else if (found && dt < tolerance) + { + // if found TrigWordForGroup in TrigWords, insert to ThisGroup + if (std::find(TrigWords.begin(), TrigWords.end(), TrigWordForGroup[i]) != TrigWords.end()) + { + ThisGroup.insert(std::pair(TrigTimeForGroup[i], TrigWordForGroup[i])); + toRemove.push_back(i); + if (mainTrigWord == 14 && (TrigWordForGroup[i] == 10 || TrigWordForGroup[i] == 40 || TrigWordForGroup[i] == 41)) + { + ThisGroup.insert(std::pair(TrigTimeForGroup[i] + 1, TrigWordForGroup[i])); + } + ///!!! attention, the trigger word 10 always come with 8 with the same time, so it won't be inserted to the map + // Therefore we add another 1ns to it, but it's not real + } + } + else if (found && dt > tolerance) + { + if (verbosityEBTG > 9) + { + // print all triggers in this group + cout << "EBTG: GroupByTrigWord: ThisGroup size = " << ThisGroup.size() << endl; + for (auto it = ThisGroup.begin(); it != ThisGroup.end(); ++it) + { + cout << it->first << " - " << it->second << ", "; + } + cout << endl; + } + // check is the current track trigger already exist in GroupedTriggersInTotal, if so, don't add it + // find trackTriggerTime in each element in GroupedTriggersInTotal[mainTrigWord] + bool trackTriggerExist = false; + for (int j = 0; j < GroupedTriggersInTotal[mainTrigWord].size(); j++) + { + for (auto it = GroupedTriggersInTotal[mainTrigWord][j].begin(); it != GroupedTriggersInTotal[mainTrigWord][j].end(); ++it) + { + if (it->first == trackTriggerTime && it->second == trackTriggerWord) + { + trackTriggerExist = true; + break; + } + } + } + if (!trackTriggerExist) + { + GroupedTriggersInTotal[mainTrigWord].push_back(ThisGroup); + } + else + { + // in it's track of SkippedDuplicateTriggers, plus one. if found it, ++, if not, emplace 1 + if (SkippedDuplicateTriggers.find(mainTrigWord) != SkippedDuplicateTriggers.end()) + { + SkippedDuplicateTriggers[mainTrigWord]++; + } + else + { + SkippedDuplicateTriggers.emplace(mainTrigWord, 1); + } + + Log("EBTG: Found a duplicated main trigger with word " + std::to_string(mainTrigWord) + " and time " + std::to_string(trackTriggerTime), v_message, verbosityEBTG); + } + + if (verbosityEBTG > 9) + cout << "EBTG: saving grouped trigger with currentRunCode = " << currentRunCode << endl; + if (!trackTriggerExist) + RunCodeInTotal[mainTrigWord].push_back(currentRunCode); + else + Log("EBTG: Found a duplicated main trigger with word " + std::to_string(mainTrigWord) + " and time " + std::to_string(trackTriggerTime) + ", so skip adding run code vector", v_message, verbosityEBTG); + totalGroupedTriggerNumber += ThisGroup.size(); + ThisGroup.clear(); + found = false; + } + } + int totalToRemoveTriggerNumber = toRemove.size(); + // from end to beginning, remove the triggers in buffer based on toRemove index + for (int i = toRemove.size() - 1; i >= 0; i--) + { + TrigTimeForGroup.erase(TrigTimeForGroup.begin() + toRemove[i]); + TrigWordForGroup.erase(TrigWordForGroup.begin() + toRemove[i]); + } + Log("EBTG: GroupByTrigWord Finished, accumulated saved " + std::to_string(GroupedTriggers.size()) + " group of triggers", v_warning, verbosityEBTG); + Log("EBTG: buffer TriggersForGroup after grouping size = " + std::to_string(TrigTimeForGroup.size()), v_warning, verbosityEBTG); + Log("EBTG: totalGroupedTriggerNumber in this grouping step is: " + std::to_string(totalGroupedTriggerNumber) + ", totalToRemoveTriggerNumber = " + std::to_string(totalToRemoveTriggerNumber), v_warning, verbosityEBTG); + + return totalToRemoveTriggerNumber; +} + +int EBTriggerGrouper::FillByTrigWord(uint32_t mainTrigWord, vector TrigWords, int tolerance) +{ + // Fill the trigger maps at GroupedTriggersInTotal[mainTrigWord] + // for all triggers in the buffer, if the trigger word is in the vector, and in the range of main TrigWord - the tolerance + // push the trigger into the map + + Log("EBTG: FillByTrigWord()", v_warning, verbosityEBTG); + Log("EBTG: Fill by TrigWord: " + std::to_string(mainTrigWord), v_warning, verbosityEBTG); + Log("EBTG: size of time buffer before refilling is " + std::to_string(TrigTimeForGroup.size()) + ", size of word buffer is " + std::to_string(TrigWordForGroup.size()), v_warning, verbosityEBTG); + + int addedTriggerNumber = 0; + vector indexToRemove; + + for (int i = TrigTimeForGroup.size() - 1; i >= 0; i--) + { + if (verbosityEBTG > 11) + cout << "EBTG: FillByTrigWord: mainTrigWord = " << mainTrigWord << ", TrigWordForGroup[i] = " << TrigWordForGroup[i] << ", TrigTimeForGroup[i] = " << TrigTimeForGroup[i] << ", tolerance = " << tolerance << endl; + // check is current trigger word in TrigWords + if (std::find(TrigWords.begin(), TrigWords.end(), TrigWordForGroup[i]) == TrigWords.end()) + continue; + bool triggerToAdd = false; + int insertTrack = 0; + int insertGroupIndex = 0; + uint64_t insertedDT = tolerance; + for (int j = 0; j < GroupedTriggersInTotal[mainTrigWord].size(); j++) + { + for (auto it = GroupedTriggersInTotal[mainTrigWord][j].begin(); it != GroupedTriggersInTotal[mainTrigWord][j].end(); ++it) + { + if (it->second == mainTrigWord) + { + uint64_t dt = (TrigTimeForGroup[i] > it->first) ? (TrigTimeForGroup[i] - it->first) : (it->first - TrigTimeForGroup[i]); + if (dt < tolerance && dt < insertedDT) + { + insertedDT = dt; + insertTrack = mainTrigWord; + insertGroupIndex = j; + triggerToAdd = true; + Log("EBTG: FillByTrigWord: Found trigger to add, insertTrack = " + std::to_string(insertTrack) + ", insertGroupIndex = " + std::to_string(insertGroupIndex) + ", insert DT = " + std::to_string(insertedDT), 9, verbosityEBTG); + break; + } + } + } + } + if (triggerToAdd) + { + GroupedTriggersInTotal[mainTrigWord][insertGroupIndex].insert(std::make_pair(TrigTimeForGroup[i], TrigWordForGroup[i])); + indexToRemove.push_back(i); + if (verbosityEBTG > 11) + cout << "EBTG: FillByTrigWord: add this trigger: " << TrigTimeForGroup[i] << " - " << TrigWordForGroup[i] << endl; + addedTriggerNumber++; + } + } + Log("EBTG: FillByTrigWord Finished, addedTriggerNumber = " + std::to_string(addedTriggerNumber), v_warning, verbosityEBTG); + Log("EBTG: indexToRemove size = " + std::to_string(indexToRemove.size()) + ", buffer size before remove is " + std::to_string(TrigTimeForGroup.size()), v_warning, verbosityEBTG); + + // sort indexToRemove from large to small, then remove the triggers in buffer based on toRemove index + std::sort(indexToRemove.begin(), indexToRemove.end(), std::greater()); + + if (verbosityEBTG > 11) + { + // print all index to remove + cout << "EBTG: FillByTrigWord: indexToRemove: "; + for (int i = 0; i < indexToRemove.size(); i++) + { + cout << indexToRemove[i] << ", "; + } + } + + for (int i = 0; i < indexToRemove.size(); i++) + { + TrigTimeForGroup.erase(TrigTimeForGroup.begin() + indexToRemove[i]); + TrigWordForGroup.erase(TrigWordForGroup.begin() + indexToRemove[i]); + } + Log("EBTG: buffer TriggersForGroup after refilling and removing size = " + std::to_string(TrigTimeForGroup.size()), v_warning, verbosityEBTG); + + return addedTriggerNumber; +} + +int EBTriggerGrouper::CleanTriggerBuffer() +{ + //remove very early trigger in TrigTimeForGroup and TrigWordForGroup + //only leave the latest maxNumAllowedInBuffer elements + int removedNumber = 0; + if (TrigTimeForGroup.size() > maxNumAllowedInBuffer) + { + removedNumber = TrigTimeForGroup.size() - maxNumAllowedInBuffer; + removedTriggerInBuffer += removedNumber; + Log("EBTG: CleanTriggerBuffer, will remove the earliest " + std::to_string(TrigTimeForGroup.size() - maxNumAllowedInBuffer) + " triggers in buffer", v_message, verbosityEBTG); + TrigTimeForGroup.erase(TrigTimeForGroup.begin(), TrigTimeForGroup.end() - maxNumAllowedInBuffer); + TrigWordForGroup.erase(TrigWordForGroup.begin(), TrigWordForGroup.end() - maxNumAllowedInBuffer); + } + return removedNumber; +} \ No newline at end of file diff --git a/UserTools/EBTriggerGrouper/EBTriggerGrouper.h b/UserTools/EBTriggerGrouper/EBTriggerGrouper.h new file mode 100644 index 000000000..0146c67fe --- /dev/null +++ b/UserTools/EBTriggerGrouper/EBTriggerGrouper.h @@ -0,0 +1,119 @@ +#ifndef EBTriggerGrouper_H +#define EBTriggerGrouper_H + +#include +#include + +#include "Tool.h" + +/** + * \class EBTriggerGrouper + * + * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. + * + * $Author: B.Richards $ + * $Date: 2019/05/28 10:44:00 $ + * Contact: b.richards@qmul.ac.uk + */ +class EBTriggerGrouper : public Tool +{ + +public: + EBTriggerGrouper(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + + bool GroupByTolerance(); + bool FillByTolerance(); + bool SaveGroupedTriggers(); + bool CleanBuffer(); + + int GroupByTrigWord(uint32_t mainTrigWord, vector TrigWords, int tolerance); + // group and save triggers to GroupedTriggersInTotal and RunCodeInTotal + // input a vector of trigger words in that combination, and a tolerance + // during grouping, select based on the main TrigWord + the tolerance + // in that range, if the trigger word is in the vector, group them together + // push the grouped trigger map into the vector at GroupedTriggersInTotal[mainTrigWord] + + int FillByTrigWord(uint32_t mainTrigWord, vector TrigWords, int tolerance); + // Fill the trigger maps at GroupedTriggersInTotal[mainTrigWord] + // for all triggers in the buffer, if the trigger word is in the vector, and in the range of main TrigWord - the tolerance + // push the trigger into the map + + int CleanTriggerBuffer(); //remove very early trigger in TrigTimeForGroup and TrigWordForGroup + //only leave the latest maxNumAllowedInBuffer elements + +private: + string savePath; + string GroupMode; // beam, Tolerance + double GroupTolerance; + int GroupTrigWord; + + std::map> *TimeToTriggerWordMap; + std::map> *TimeToTriggerWordMapComplete; // Info about all triggerwords + + vector TrigTimeForGroup; + vector TrigWordForGroup; + vector RunCodeBuffer; + + std::vector> GroupedTriggers; // each map is a group of triggers, for the main target trigger + vector RunCode; //!! RunCode goes with each group, always modify them together + + std::map>> GroupedTriggersInTotal; // each map is a group of triggers, with the key is the target trigger word + std::map> RunCodeInTotal; //!! RunCode goes with each group, always modify them together + + std::map SkippedDuplicateTriggers; //if the trigger was duplicated in multiple entries, skip it. this record the skipped number of groups + + int verbosityEBTG; + + int v_message = 1; + int v_warning = 2; + int v_error = 3; + int v_debug = 4; + + int ANNIEEventNum; + int CurrentRunNum; + int CurrentSubrunNum; + int CurrentPartNum; + int currentRunCode; + bool usingTriggerOverlap; + + int StoreTotalEntry; + + int maxNumAllowedInBuffer; + int removedTriggerInBuffer; + + bool groupBeam; + bool groupCosmic; + bool groupLaser; + bool groupLED; + bool groupAmBe; + bool groupPPS; + + int BeamTriggerMain; + double BeamTolerance; + vector BeamTriggers; + + int CosmicTriggerMain; + double CosmicTolerance; + vector CosmicTriggers; + + int LaserTriggerMain; + double LaserTolerance; + vector LaserTriggers; + + int LEDTriggerMain; + double LEDTolerance; + vector LEDTriggers; + + int AmBeTriggerMain; + double AmBeTolerance; + vector AmBeTriggers; + + int PPSTriggerMain; + double PPSTolerance; + vector PPSTriggers; +}; + +#endif diff --git a/UserTools/EBTriggerGrouper/README.md b/UserTools/EBTriggerGrouper/README.md new file mode 100644 index 000000000..417e352e7 --- /dev/null +++ b/UserTools/EBTriggerGrouper/README.md @@ -0,0 +1,20 @@ +# EBTriggerGrouper + +EBTriggerGrouper + +## Data + +Describe any data formats EBTriggerGrouper creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for EBTriggerGrouper. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/Factory/Factory.cpp b/UserTools/Factory/Factory.cpp index a766d2a90..c062d6343 100644 --- a/UserTools/Factory/Factory.cpp +++ b/UserTools/Factory/Factory.cpp @@ -174,5 +174,11 @@ if (tool=="LAPPDThresReco") ret=new LAPPDThresReco; if (tool=="LAPPDTimeAlignment") ret=new LAPPDTimeAlignment; if (tool=="LAPPDBaseline") ret=new LAPPDBaseline; if (tool=="LAPPDStoreReorder") ret=new LAPPDStoreReorder; +if (tool=="EBLoadRaw") ret=new EBLoadRaw; +if (tool=="EBTriggerGrouper") ret=new EBTriggerGrouper; +if (tool=="EBLAPPD") ret=new EBLAPPD; +if (tool=="EBPMT") ret=new EBPMT; +if (tool=="EBMRD") ret=new EBMRD; +if (tool=="EBSaver") ret=new EBSaver; return ret; } diff --git a/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp b/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp index 8022719e9..f820cb3f7 100644 --- a/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp +++ b/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp @@ -25,6 +25,7 @@ bool PhaseIITreeMaker::Initialise(std::string configfile, DataModel &data){ m_variables.Get("TankReco_fill", TankReco_fill); m_variables.Get("RecoDebug_fill", RecoDebug_fill); m_variables.Get("muonTruthRecoDiff_fill", muonTruthRecoDiff_fill); + m_variables.Get("LAPPDData_fill", LAPPDData_fill); m_variables.Get("SiPMPulseInfo_fill",SiPMPulseInfo_fill); m_variables.Get("TankClusterProcessing",TankClusterProcessing); @@ -101,6 +102,21 @@ bool PhaseIITreeMaker::Initialise(std::string configfile, DataModel &data){ fPhaseIITankClusterTree->Branch("SiPM1NPulses",&fSiPM1NPulses,"SiPM1NPulses/I"); fPhaseIITankClusterTree->Branch("SiPM2NPulses",&fSiPM2NPulses,"SiPM2NPulses/I"); } + if(LAPPDData_fill) + { + fPhaseIITankClusterTree->Branch("LAPPD_ID",&fLAPPD_ID); + fPhaseIITankClusterTree->Branch("LAPPD_Beamgate_ns",&fLAPPD_Beamgate_ns); + fPhaseIITankClusterTree->Branch("LAPPD_Timestamp_ns",&fLAPPD_Timestamp_ns); + fPhaseIITankClusterTree->Branch("LAPPD_Beamgate_Raw",&fLAPPD_Beamgate_Raw); + fPhaseIITankClusterTree->Branch("LAPPD_Timestamp_Raw",&fLAPPD_Timestamp_Raw); + fPhaseIITankClusterTree->Branch("LAPPD_Offset",&fLAPPD_Offset); + fPhaseIITankClusterTree->Branch("LAPPD_TSCorrection",&fLAPPD_TSCorrection); + fPhaseIITankClusterTree->Branch("LAPPD_BGCorrection",&fLAPPD_BGCorrection); + fPhaseIITankClusterTree->Branch("LAPPD_OSInMinusPS",&fLAPPD_OSInMinusPS); + + fPhaseIITankClusterTree->Branch("fGroupedTriggerTime",&fGroupedTriggerTime); + fPhaseIITankClusterTree->Branch("fGroupedTriggerWord",&fGroupedTriggerWord); + } } if(MRDClusterProcessing){ @@ -156,6 +172,23 @@ bool PhaseIITreeMaker::Initialise(std::string configfile, DataModel &data){ fPhaseIIMRDClusterTree->Branch("MRDStop",&fMRDStop); fPhaseIIMRDClusterTree->Branch("MRDThrough",&fMRDThrough); } + + if(LAPPDData_fill) + { + fPhaseIIMRDClusterTree->Branch("LAPPD_ID",&fLAPPD_ID); + fPhaseIIMRDClusterTree->Branch("LAPPD_Beamgate_ns",&fLAPPD_Beamgate_ns); + fPhaseIIMRDClusterTree->Branch("LAPPD_Timestamp_ns",&fLAPPD_Timestamp_ns); + fPhaseIIMRDClusterTree->Branch("LAPPD_Beamgate_Raw",&fLAPPD_Beamgate_Raw); + fPhaseIIMRDClusterTree->Branch("LAPPD_Timestamp_Raw",&fLAPPD_Timestamp_Raw); + fPhaseIIMRDClusterTree->Branch("LAPPD_Offset",&fLAPPD_Offset); + fPhaseIIMRDClusterTree->Branch("LAPPD_TSCorrection",&fLAPPD_TSCorrection); + fPhaseIIMRDClusterTree->Branch("LAPPD_BGCorrection",&fLAPPD_BGCorrection); + fPhaseIIMRDClusterTree->Branch("LAPPD_OSInMinusPS",&fLAPPD_OSInMinusPS); + + fPhaseIIMRDClusterTree->Branch("fGroupedTriggerTime",&fGroupedTriggerTime); + fPhaseIIMRDClusterTree->Branch("fGroupedTriggerWord",&fGroupedTriggerWord); + } + } if(TriggerProcessing){ @@ -390,6 +423,22 @@ bool PhaseIITreeMaker::Initialise(std::string configfile, DataModel &data){ fPhaseIITrigTree->Branch("deltaAzimuth",&fDeltaAzimuth,"deltaAzimuth/D"); fPhaseIITrigTree->Branch("deltaZenith",&fDeltaZenith,"deltaZenith/D"); fPhaseIITrigTree->Branch("deltaAngle",&fDeltaAngle,"deltaAngle/D"); + } + + if(LAPPDData_fill) + { + fPhaseIITrigTree->Branch("LAPPD_ID",&fLAPPD_ID); + fPhaseIITrigTree->Branch("LAPPD_Beamgate_ns",&fLAPPD_Beamgate_ns); + fPhaseIITrigTree->Branch("LAPPD_Timestamp_ns",&fLAPPD_Timestamp_ns); + fPhaseIITrigTree->Branch("LAPPD_Beamgate_Raw",&fLAPPD_Beamgate_Raw); + fPhaseIITrigTree->Branch("LAPPD_Timestamp_Raw",&fLAPPD_Timestamp_Raw); + fPhaseIITrigTree->Branch("LAPPD_Offset",&fLAPPD_Offset); + fPhaseIITrigTree->Branch("LAPPD_TSCorrection",&fLAPPD_TSCorrection); + fPhaseIITrigTree->Branch("LAPPD_BGCorrection",&fLAPPD_BGCorrection); + fPhaseIITrigTree->Branch("LAPPD_OSInMinusPS",&fLAPPD_OSInMinusPS); + + fPhaseIITrigTree->Branch("fGroupedTriggerTime",&fGroupedTriggerTime); + fPhaseIITrigTree->Branch("fGroupedTriggerWord",&fGroupedTriggerWord); } } return true; @@ -399,10 +448,32 @@ bool PhaseIITreeMaker::Execute(){ Log("===========================================================================================",v_debug,verbosity); Log("PhaseIITreeMaker Tool: Executing",v_debug,verbosity); +/* + std::map checkDataStreams; + m_data->Stores.at("ANNIEEvent")->Get("DataStreams",checkDataStreams); + //print out the data streams + if(checkDataStreams["LAPPD"]==1){ + m_data->Stores.at("ANNIEEvent")->Get("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); + m_data->Stores.at("ANNIEEvent")->Get("LAPPDOffsets", LAPPDOffsets); + //check they have the same size, if not print in log + if(LAPPDTimeStamps_ns.size() != LAPPDOffsets.size()){ + Log("PhaseIITreeMaker Tool: LAPPD Time Stamps and Offsets are not the same size!",v_message,verbosity); + }else{ + cout<<"LAPPDTimeStamps_ns size is: "<ResetVariables(); + if (LAPPDData_fill) this->LoadLAPPDData(); + fClusterNumber = cluster_num; //Standard run level information @@ -710,6 +783,7 @@ bool PhaseIITreeMaker::Execute(){ fNumClusterTracks = this->LoadMRDTrackReco(i); //Get the track info } + if (LAPPDData_fill) this->LoadLAPPDData(); fPhaseIIMRDClusterTree->Fill(); cluster_num += 1; @@ -794,6 +868,8 @@ bool PhaseIITreeMaker::Execute(){ // FIll tree with all reconstruction information if (RecoDebug_fill) this->FillRecoDebugInfo(); + if (LAPPDData_fill) this->LoadLAPPDData(); + fPhaseIITrigTree->Fill(); } return true; @@ -1023,6 +1099,34 @@ void PhaseIITreeMaker::ResetVariables() { fDeltaZenith = -9999; fDeltaAngle = -9999; } + + if(LAPPDData_fill){ + LAPPDDataMap.clear(); + LAPPDBeamgate_ns.clear(); + LAPPDTimeStamps_ns.clear(); + LAPPDTimeStampsRaw.clear(); + LAPPDBeamgatesRaw.clear(); + LAPPDOffsets.clear(); + LAPPDTSCorrection.clear(); + LAPPDBGCorrection.clear(); + LAPPDOSInMinusPS.clear(); + + fLAPPD_ID.clear(); + fLAPPD_Beamgate_ns.clear(); + fLAPPD_Timestamp_ns.clear(); + fLAPPD_Beamgate_Raw.clear(); + fLAPPD_Timestamp_Raw.clear(); + fLAPPD_Offset.clear(); + fLAPPD_TSCorrection.clear(); + fLAPPD_BGCorrection.clear(); + fLAPPD_OSInMinusPS.clear(); + + GroupedTrigger.clear(); + + fGroupedTriggerTime.clear(); + fGroupedTriggerWord.clear(); + } + } bool PhaseIITreeMaker::LoadTankClusterClassifiers(double cluster_time){ @@ -1805,3 +1909,46 @@ void PhaseIITreeMaker::RecoSummary() { std::cout << " RecoStatus = " << fRecoStatus <::iterator it = LAPPDDataMap.begin(); it != LAPPDDataMap.end(); ++it) { + uint64_t key = it->first; + PsecData psecData = it->second; + + fLAPPD_ID.push_back(psecData.LAPPD_ID); + + fLAPPD_Beamgate_ns.push_back(LAPPDBeamgate_ns[key]); + fLAPPD_Timestamp_ns.push_back(LAPPDTimeStamps_ns[key]); + fLAPPD_Beamgate_Raw.push_back(LAPPDBeamgatesRaw[key]); + fLAPPD_Timestamp_Raw.push_back(LAPPDTimeStampsRaw[key]); + fLAPPD_Offset.push_back(LAPPDOffsets[key]); + fLAPPD_TSCorrection.push_back(LAPPDTSCorrection[key]); + fLAPPD_BGCorrection.push_back(LAPPDBGCorrection[key]); + fLAPPD_OSInMinusPS.push_back(LAPPDOSInMinusPS[key]); + } + + for(std::map::iterator it = GroupedTrigger.begin(); it != GroupedTrigger.end(); ++it) { + uint64_t key = it->first; + uint32_t value = it->second; + + fGroupedTriggerTime.push_back(key); + fGroupedTriggerWord.push_back(value); + } + +} + +void PhaseIITreeMaker::LoadLAPPDData() +{ + m_data->Stores["ANNIEEvent"]->Get("LAPPDDataMap", LAPPDDataMap); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStampsRaw", LAPPDTimeStampsRaw); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgatesRaw", LAPPDBeamgatesRaw); + m_data->Stores["ANNIEEvent"]->Get("LAPPDOffsets", LAPPDOffsets); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTSCorrection", LAPPDTSCorrection); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBGCorrection", LAPPDBGCorrection); + m_data->Stores["ANNIEEvent"]->Get("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + if(LAPPDDataMap.size() != 0) + FillLAPPDData(); +} \ No newline at end of file diff --git a/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.h b/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.h index 1bb0f9789..bffe7e497 100644 --- a/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.h +++ b/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.h @@ -21,6 +21,7 @@ #include "ANNIEalgorithms.h" #include "TimeClass.h" #include "BeamStatus.h" +#include "PsecData.h" class PhaseIITreeMaker: public Tool { @@ -50,6 +51,8 @@ class PhaseIITreeMaker: public Tool { bool LoadTankClusterClassifiers(double cluster_time); void LoadAllTankHits(bool IsData); void LoadSiPMHits(); + void LoadLAPPDData(); + void FillLAPPDData(); private: @@ -355,6 +358,35 @@ class PhaseIITreeMaker: public Tool { bool RecoDebug_fill = 0; //Outputs results of Reconstruction at each step (best fits, FOMs, etc.) bool muonTruthRecoDiff_fill = 0; //Output difference in tmuonruth and reconstructed values bool SiPMPulseInfo_fill = 0; + + // LAPPD data variables + bool LAPPDData_fill = 0; + int gotLAPPDNumber; + std::map LAPPDDataMap; + std::map LAPPDBeamgate_ns; + std::map LAPPDTimeStamps_ns; // data and key are the same + std::map LAPPDTimeStampsRaw; + std::map LAPPDBeamgatesRaw; + std::map LAPPDOffsets; + std::map LAPPDTSCorrection; + std::map LAPPDBGCorrection; + std::map LAPPDOSInMinusPS; + + vector fLAPPD_ID; + vector fLAPPD_Beamgate_ns; + vector fLAPPD_Timestamp_ns; + vector fLAPPD_Beamgate_Raw; + vector fLAPPD_Timestamp_Raw; + vector fLAPPD_Offset; + vector fLAPPD_TSCorrection; + vector fLAPPD_BGCorrection; + vector fLAPPD_OSInMinusPS; + + std::map GroupedTrigger; + + vector fGroupedTriggerTime; + vector fGroupedTriggerWord; + }; diff --git a/UserTools/Unity.h b/UserTools/Unity.h index 636f2bf14..574d41e82 100644 --- a/UserTools/Unity.h +++ b/UserTools/Unity.h @@ -182,3 +182,9 @@ #include "LAPPDTimeAlignment.h" #include "LAPPDBaseline.h" #include "LAPPDStoreReorder.h" +#include "EBLoadRaw.h" +#include "EBTriggerGrouper.h" +#include "EBLAPPD.h" +#include "EBPMT.h" +#include "EBMRD.h" +#include "EBSaver.h" diff --git a/configfiles/BeamClusterAnalysis/PhaseIITreeMakerConfig b/configfiles/BeamClusterAnalysis/PhaseIITreeMakerConfig index eee2e9cb4..acb3ea7ff 100644 --- a/configfiles/BeamClusterAnalysis/PhaseIITreeMakerConfig +++ b/configfiles/BeamClusterAnalysis/PhaseIITreeMakerConfig @@ -1,6 +1,6 @@ verbose 0 -OutputFile BeamRun_R2573_AllTriggers.ntuple.root +OutputFile BeamRunClusterTest_newEB.root TankClusterProcessing 1 MRDClusterProcessing 1 TriggerProcessing 1 @@ -8,10 +8,12 @@ TankHitInfo_fill 1 MRDHitInfo_fill 1 MRDReco_fill 1 SiPMPulseInfo_fill 0 -fillCleanEventsOnly 1 +fillCleanEventsOnly 0 MCTruth_fill 0 -Reco_fill 0 +Reco_fill 1 RecoDebug_fill 0 muonTruthRecoDiff_fill 0 IsData 1 HasGenie 0 + +LAPPDData_fill 1 diff --git a/configfiles/EventBuilderV2/DefaultTriggerMask.txt b/configfiles/EventBuilderV2/DefaultTriggerMask.txt new file mode 100644 index 000000000..398850355 --- /dev/null +++ b/configfiles/EventBuilderV2/DefaultTriggerMask.txt @@ -0,0 +1,10 @@ +#Triggers are given by Jonathan; place one number per line. Values are index + 1 +#4+1: Delayed beam. 32+1: LED trigger. 34+1: AmBe and Cosmic trigger. 35+1: MRD_CR_Trigger. 30+1: LED_Start. 45+1, 46+1: Laser. 14+1: AmBe external trigger +5 +15 +36 +31 +33 +35 +46 +47 diff --git a/configfiles/EventBuilderV2/EBLAPPDConfig b/configfiles/EventBuilderV2/EBLAPPDConfig new file mode 100644 index 000000000..b6981cdec --- /dev/null +++ b/configfiles/EventBuilderV2/EBLAPPDConfig @@ -0,0 +1,7 @@ +verbosityEBLAPPD 5 +matchTargetTrigger 14 +matchTolerance_ns 400000 +#matchTolerance_ns 10000 +exePerMatch 500 + +matchToAllTriggers 0 diff --git a/configfiles/EventBuilderV2/EBLoadRawConfig b/configfiles/EventBuilderV2/EBLoadRawConfig new file mode 100644 index 000000000..bae579561 --- /dev/null +++ b/configfiles/EventBuilderV2/EBLoadRawConfig @@ -0,0 +1,10 @@ +verbosityEBLoadRaw 5 +ReadTriggerOverlap 1 + +InputFile ./configfiles/EventBuilderV2/list.txt + +LoadPMT 1 +LoadMRD 1 +LoadCTC 1 +LoadLAPPD 1 + diff --git a/configfiles/EventBuilderV2/EBMRDConfig b/configfiles/EventBuilderV2/EBMRDConfig new file mode 100644 index 000000000..1914f4cc9 --- /dev/null +++ b/configfiles/EventBuilderV2/EBMRDConfig @@ -0,0 +1,4 @@ +verbosityEBMRD 5 +matchTargetTrigger 8 +matchTolerance_ns 3000000 +matchToAllTriggers 0 diff --git a/configfiles/EventBuilderV2/EBPMTConfig b/configfiles/EventBuilderV2/EBPMTConfig new file mode 100644 index 000000000..06d278434 --- /dev/null +++ b/configfiles/EventBuilderV2/EBPMTConfig @@ -0,0 +1,4 @@ +verbosityEBPMT 3 +matchTargetTrigger 5 +matchTolerance_ns 2000 +matchToAllTriggers 1 diff --git a/configfiles/EventBuilderV2/EBSaverConfig b/configfiles/EventBuilderV2/EBSaverConfig new file mode 100644 index 000000000..922c6714c --- /dev/null +++ b/configfiles/EventBuilderV2/EBSaverConfig @@ -0,0 +1,10 @@ +verbosityEBSaver 5 + +savePMT 1 +saveMRD 1 +saveCTC 1 +saveLAPPD 1 +saveRunInfo 1 +saveBeamInfo 1 + + diff --git a/configfiles/EventBuilderV2/EBTriggerGrouperConfig b/configfiles/EventBuilderV2/EBTriggerGrouperConfig new file mode 100644 index 000000000..02d5ec658 --- /dev/null +++ b/configfiles/EventBuilderV2/EBTriggerGrouperConfig @@ -0,0 +1,23 @@ +verbosityEBTG 5 +GroupMode beam +GroupTolerance 3000000 +GroupTrigWord 14 //undelayed beam + +groupBeam 1 +BeamTolerance 25000000 + +groupCosmic 1 + +groupLaser 1 +#LaserTolerance 10000 + +groupLED 1 +#LEDTriggerMain 31 +#LEDTolerance 10000 + +groupAmBe 0 + +groupPPS 0 + + + diff --git a/configfiles/EventBuilderV2/LAPPDLoadStoreConfig b/configfiles/EventBuilderV2/LAPPDLoadStoreConfig new file mode 100644 index 000000000..daa420ebe --- /dev/null +++ b/configfiles/EventBuilderV2/LAPPDLoadStoreConfig @@ -0,0 +1,39 @@ + General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +NUM_VECTOR_METADATA 103 #Fixed META vector size +LAPPDchannelOffset 1000 +NChannels 30 + +LAPPDStoreReadInVerbosity 0 + +mergingModeReadIn 0 +RawDataInputWavLabel RawWaveform +RawDataOutputWavLabel RawLAPPDData +BoardIndexLabel BoardIndex #Label of the vector of read out boards + +PsecReceiveMode 1 +stopEntries 10000000000 + +DoPedSubtraction 0 +Nboards 6 #Number of pedestal files to be read in +PedinputfileTXT ../Pedestals/Laser2024Feb/P +PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 + + +Pedinputfile1 ../Pedestals/PEDS_ACDC_board0.txt +Pedinputfile2 ../Pedestals/PEDS_ACDC_board1.txt + + +ReadStore 0 +num_vector_data 7795 +num_vector_pps 16 +OutputWavLabel RawLAPPDData +SelectSingleLAPPD false +SelectedLAPPD 0 +loadPSEC 1 +loadPPS 1 +loadOffsets 1 + + diff --git a/configfiles/EventBuilderV2/MRDDataDecoderConfig b/configfiles/EventBuilderV2/MRDDataDecoderConfig new file mode 100644 index 000000000..d9937ca9a --- /dev/null +++ b/configfiles/EventBuilderV2/MRDDataDecoderConfig @@ -0,0 +1,2 @@ +verbosity 0 +DaylightSavingsSpring 1 diff --git a/configfiles/EventBuilderV2/PMTDataDecoderConfig b/configfiles/EventBuilderV2/PMTDataDecoderConfig new file mode 100644 index 000000000..cca7bb6b5 --- /dev/null +++ b/configfiles/EventBuilderV2/PMTDataDecoderConfig @@ -0,0 +1,5 @@ +verbosity 1 +ADCCountsToBuildWaves 0 +Mode Offline +OffsetVME03 0 +OffsetVME01 0 diff --git a/configfiles/EventBuilderV2/PhaseIIADCCalibratorConfig b/configfiles/EventBuilderV2/PhaseIIADCCalibratorConfig new file mode 100644 index 000000000..158dc6ed1 --- /dev/null +++ b/configfiles/EventBuilderV2/PhaseIIADCCalibratorConfig @@ -0,0 +1,15 @@ +# PhaseIIADCCalibrator config file + +verbosity 0 + +BaselineEstimationType ze3ra_multi +NumBaselineSamples 15 +NumSubWaveforms 10 + +SamplesPerBaselineEstimate 2000 +BaselineUncertaintyTolerance 2 +PCritical 0.01 +MakeCalLEDWaveforms 0 + +EventBuilding 1 +ExecutesPerBuild 10 diff --git a/configfiles/EventBuilderV2/PhaseIIADCHitFinderConfig b/configfiles/EventBuilderV2/PhaseIIADCHitFinderConfig new file mode 100644 index 000000000..d183b7b27 --- /dev/null +++ b/configfiles/EventBuilderV2/PhaseIIADCHitFinderConfig @@ -0,0 +1,10 @@ +verbosity 0 + +UseLEDWaveforms 0 + +PulseFindingApproach threshold +PulseWindowType dynamic +DefaultADCThreshold 7 +DefaultThresholdType relative + +EventBuilding 1 diff --git a/configfiles/EventBuilderV2/ToolChainConfig b/configfiles/EventBuilderV2/ToolChainConfig new file mode 100644 index 000000000..b661e1dfd --- /dev/null +++ b/configfiles/EventBuilderV2/ToolChainConfig @@ -0,0 +1,23 @@ +#ToolChain dynamic setup file + +##### Runtime Paramiters ##### +verbose 1 +error_level 0 # 0= do not exit, 1= exit on unhandeled errors only, 2= exit on unhandeled errors and handeled errors +attempt_recover 1 + +###### Logging ##### +log_mode Interactive # Interactive=cout , Remote= remote logging system "serservice_name Remote_Logging" , Local = local file log; +log_local_path ./log +log_service LogStore + +###### Service discovery ##### +service_publish_sec -1 +service_kick_sec -1 + +##### Tools To Add ##### +Tools_File ./configfiles/EventBuilderV2/ToolsConfig + +##### Run Type ##### +Inline -1 +Interactive 0 + diff --git a/configfiles/EventBuilderV2/ToolsConfig b/configfiles/EventBuilderV2/ToolsConfig new file mode 100644 index 000000000..e6fcaa2bf --- /dev/null +++ b/configfiles/EventBuilderV2/ToolsConfig @@ -0,0 +1,21 @@ +LoadGeometry LoadGeometry ./configfiles/LoadGeometry/LoadGeometryConfig +EBLoadRaw EBLoadRaw ./configfiles/EventBuilderV2/EBLoadRawConfig + + +PMTDataDecoder PMTDataDecoder ./configfiles/EventBuilderV2/PMTDataDecoderConfig +MRDDataDecoder MRDDataDecoder ./configfiles/EventBuilderV2/MRDDataDecoderConfig +TriggerDataDecoder TriggerDataDecoder ./configfiles/EventBuilderV2/TriggerDataDecoderConfig +LAPPDLoadStore LAPPDLoadStore ./configfiles/EventBuilderV2/LAPPDLoadStoreConfig + + +PhaseIIADCCalibrator PhaseIIADCCalibrator ./configfiles/EventBuilderV2/PhaseIIADCCalibratorConfig +PhaseIIADCHitFinder PhaseIIADCHitFinder ./configfiles/EventBuilderV2/PhaseIIADCHitFinderConfig + + +EBTriggerGrouper EBTriggerGrouper ./configfiles/EventBuilderV2/EBTriggerGrouperConfig +EBPMT EBPMT ./configfiles/EventBuilderV2/EBPMTConfig +EBMRD EBMRD ./configfiles/EventBuilderV2/EBMRDConfig +EBLAPPD EBLAPPD ./configfiles/EventBuilderV2/EBLAPPDConfig +EBSaver EBSaver ./configfiles/EventBuilderV2/EBSaverConfig + + diff --git a/configfiles/EventBuilderV2/TriggerDataDecoderConfig b/configfiles/EventBuilderV2/TriggerDataDecoderConfig new file mode 100644 index 000000000..7cff259ea --- /dev/null +++ b/configfiles/EventBuilderV2/TriggerDataDecoderConfig @@ -0,0 +1,3 @@ +verbosity 1 +StoreTrigOverlap 0 +ReadTrigOverlap 0 diff --git a/configfiles/EventBuilderV2/list.txt b/configfiles/EventBuilderV2/list.txt new file mode 100644 index 000000000..178f6b1cb --- /dev/null +++ b/configfiles/EventBuilderV2/list.txt @@ -0,0 +1,3 @@ +/pnfs/annie/persistent/raw/raw/4877/RAWDataR4877S0p104 +/pnfs/annie/persistent/raw/raw/4877/RAWDataR4877S0p105 +/pnfs/annie/persistent/raw/raw/4877/RAWDataR4877S0p106 diff --git a/configfiles/LAPPDRaw/Configs b/configfiles/LAPPDRaw/Configs index 00e70fe0a..d160269fa 100644 --- a/configfiles/LAPPDRaw/Configs +++ b/configfiles/LAPPDRaw/Configs @@ -18,12 +18,11 @@ BoardIndexLabel BoardIndex #Label of the vector of read out boards PsecReceiveMode 1 stopEntries 10000000000 -DoPedSubtraction 0 +DoPedSubtraction 1 Nboards 6 #Number of pedestal files to be read in #PedinputfileTXT ../Pedestals/swapLAPPD/Pedestal #PedinputfileTXT ../Pedestals/run3xxx/Pedestal -#Laser 2024 Feb -PedinputfileTXT ../Pedestals/Laser2024Feb/P +PedinputfileTXT ../Pedestals/LAPPD640392/P PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 diff --git a/configfiles/LAPPDRaw/list.txt b/configfiles/LAPPDRaw/list.txt index 000620da4..9e8c65863 100644 --- a/configfiles/LAPPDRaw/list.txt +++ b/configfiles/LAPPDRaw/list.txt @@ -1,3 +1,710 @@ -/pnfs/annie/scratch/users/yuefeng/rawData/4796/RAWDataR4796S0p14 -/pnfs/annie/scratch/users/yuefeng/rawData/4796/RAWDataR4796S0p15 -/pnfs/annie/scratch/users/yuefeng/rawData/4796/RAWDataR4796S0p16 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p0 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p1 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p2 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p3 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p4 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p5 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p6 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p7 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p8 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p9 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p10 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p11 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p12 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p13 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p14 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p15 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p16 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p17 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p18 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p19 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p20 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p21 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p22 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p23 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p24 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p25 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p26 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p27 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p28 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p29 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p30 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p31 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p32 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p33 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p34 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p35 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p36 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p37 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p38 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p39 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p40 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p41 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p42 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p43 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p44 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p45 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p46 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p47 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p48 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p49 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p50 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p51 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p52 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p53 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p54 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p55 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p56 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p57 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p58 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p59 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p60 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p61 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p62 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p63 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p64 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p65 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p66 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p67 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p68 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p69 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p70 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p71 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p72 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p73 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p74 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p75 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p76 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p77 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p78 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p79 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p80 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p81 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p82 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p83 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p84 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p85 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p86 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p87 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p88 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p89 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p90 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p91 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p92 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p93 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p94 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p95 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p96 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p97 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p98 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p99 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p100 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p101 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p102 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p103 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p104 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p105 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p106 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p107 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p108 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p109 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p110 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p111 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p112 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p113 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p114 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p115 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p116 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p117 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p118 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p119 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p120 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p121 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p122 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p123 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p124 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p125 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p126 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p127 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p128 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p129 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p130 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p131 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p132 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p133 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p134 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p135 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p136 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p137 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p138 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p139 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p140 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p141 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p142 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p143 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p144 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p145 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p146 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p147 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p148 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p149 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p150 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p151 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p152 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p153 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p154 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p155 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p156 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p157 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p158 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p159 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p160 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p161 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p162 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p163 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p164 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p165 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p166 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p167 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p168 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p169 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p170 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p171 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p172 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p173 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p174 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p175 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p176 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p177 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p178 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p179 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p180 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p181 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p182 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p183 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p184 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p185 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p186 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p187 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p188 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p189 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p190 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p191 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p192 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p193 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p194 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p195 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p196 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p197 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p198 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p199 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p200 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p201 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p202 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p203 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p204 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p205 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p206 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p207 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p208 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p209 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p210 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p211 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p212 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p213 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p214 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p215 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p216 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p217 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p218 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p219 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p220 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p221 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p222 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p223 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p224 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p225 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p226 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p227 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p228 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p229 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p230 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p231 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p232 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p233 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p234 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p235 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p236 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p237 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p238 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p239 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p240 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p241 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p242 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p243 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p244 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p245 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p246 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p247 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p248 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p249 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p250 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p251 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p252 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p253 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p254 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p255 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p256 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p257 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p258 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p259 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p260 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p261 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p262 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p263 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p264 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p265 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p266 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p267 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p268 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p269 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p270 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p271 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p272 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p273 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p274 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p275 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p276 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p277 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p278 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p279 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p280 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p281 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p282 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p283 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p284 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p285 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p286 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p287 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p288 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p289 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p290 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p291 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p292 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p293 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p294 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p295 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p296 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p297 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p298 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p299 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p300 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p301 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p302 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p303 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p304 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p305 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p306 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p307 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p308 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p309 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p310 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p311 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p312 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p313 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p314 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p315 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p316 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p317 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p318 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p319 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p320 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p321 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p322 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p323 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p324 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p325 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p326 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p327 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p328 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p329 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p330 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p331 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p332 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p333 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p334 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p335 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p336 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p337 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p338 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p339 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p340 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p341 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p342 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p343 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p344 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p345 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p346 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p347 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p348 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p349 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p350 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p351 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p352 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p353 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p354 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p355 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p356 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p357 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p358 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p359 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p360 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p361 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p362 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p363 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p364 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p365 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p366 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p367 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p368 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p369 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p370 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p371 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p372 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p373 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p374 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p375 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p376 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p377 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p378 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p379 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p380 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p381 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p382 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p383 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p384 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p385 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p386 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p387 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p388 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p389 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p390 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p391 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p392 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p393 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p394 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p395 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p396 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p397 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p398 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p399 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p400 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p401 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p402 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p403 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p404 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p405 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p406 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p407 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p408 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p409 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p410 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p411 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p412 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p413 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p414 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p415 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p416 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p417 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p418 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p419 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p420 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p421 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p422 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p423 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p424 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p425 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p426 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p427 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p428 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p429 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p430 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p431 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p432 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p433 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p434 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p435 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p436 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p437 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p438 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p439 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p440 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p441 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p442 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p443 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p444 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p445 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p446 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p447 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p448 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p449 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p450 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p451 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p452 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p453 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p454 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p455 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p456 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p457 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p458 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p459 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p460 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p461 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p462 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p463 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p464 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p465 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p466 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p467 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p468 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p469 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p470 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p471 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p472 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p473 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p474 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p475 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p476 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p477 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p478 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p479 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p480 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p481 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p482 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p483 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p484 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p485 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p486 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p487 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p488 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p489 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p490 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p491 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p492 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p493 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p494 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p495 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p496 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p497 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p498 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p499 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p500 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p501 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p502 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p503 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p504 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p505 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p506 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p507 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p508 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p509 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p510 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p511 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p512 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p513 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p514 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p515 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p516 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p517 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p518 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p519 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p520 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p521 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p522 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p523 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p524 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p525 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p526 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p527 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p528 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p529 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p530 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p531 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p532 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p533 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p534 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p535 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p536 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p537 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p538 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p539 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p540 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p541 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p542 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p543 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p544 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p545 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p546 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p547 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p548 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p549 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p550 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p551 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p552 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p553 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p554 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p555 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p556 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p557 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p558 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p559 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p560 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p561 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p562 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p563 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p564 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p565 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p566 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p567 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p568 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p569 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p570 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p571 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p572 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p573 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p574 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p575 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p576 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p577 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p578 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p579 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p580 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p581 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p582 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p583 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p584 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p585 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p586 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p587 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p588 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p589 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p590 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p591 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p592 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p593 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p594 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p595 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p596 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p597 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p598 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p599 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p600 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p601 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p602 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p603 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p604 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p605 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p606 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p607 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p608 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p609 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p610 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p611 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p612 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p613 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p614 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p615 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p616 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p617 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p618 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p619 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p620 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p621 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p622 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p623 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p624 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p625 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p626 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p627 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p628 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p629 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p630 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p631 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p632 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p633 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p634 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p635 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p636 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p637 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p638 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p639 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p640 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p641 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p642 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p643 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p644 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p645 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p646 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p647 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p648 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p649 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p650 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p651 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p652 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p653 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p654 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p655 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p656 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p657 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p658 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p659 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p660 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p661 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p662 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p663 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p664 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p665 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p666 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p667 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p668 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p669 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p670 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p671 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p672 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p673 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p674 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p675 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p676 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p677 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p678 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p679 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p680 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p681 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p682 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p683 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p684 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p685 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p686 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p687 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p688 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p689 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p690 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p691 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p692 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p693 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p694 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p695 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p696 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p697 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p698 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p699 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p700 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p701 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p702 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p703 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p704 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p705 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p706 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p707 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p708 +/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p709 diff --git a/configfiles/LAPPD_EB/list.txt b/configfiles/LAPPD_EB/list.txt index f9adb18ca..d047a0162 100644 --- a/configfiles/LAPPD_EB/list.txt +++ b/configfiles/LAPPD_EB/list.txt @@ -1,8 +1,50 @@ -/pnfs/annie/persistent/raw/raw/4765/RAWDataR4765S0p12 -/pnfs/annie/persistent/raw/raw/4765/RAWDataR4765S0p13 -/pnfs/annie/persistent/raw/raw/4765/RAWDataR4765S0p14 -/pnfs/annie/persistent/raw/raw/4765/RAWDataR4765S0p15 -/pnfs/annie/persistent/raw/raw/4765/RAWDataR4765S0p16 -/pnfs/annie/persistent/raw/raw/4765/RAWDataR4765S0p17 -/pnfs/annie/persistent/raw/raw/4765/RAWDataR4765S0p18 -/pnfs/annie/persistent/raw/raw/4765/RAWDataR4765S0p19 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p0 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p1 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p2 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p3 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p4 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p5 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p6 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p7 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p8 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p9 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p10 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p11 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p12 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p13 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p14 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p15 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p16 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p17 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p18 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p19 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p20 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p21 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p22 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p23 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p24 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p25 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p26 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p27 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p28 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p29 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p30 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p31 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p32 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p33 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p34 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p35 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p36 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p37 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p38 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p39 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p40 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p41 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p42 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p43 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p44 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p45 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p46 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p47 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p48 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p49 diff --git a/offsetFit_MultipleLAPPD.cpp b/offsetFit_MultipleLAPPD.cpp new file mode 100644 index 000000000..72ff663ed --- /dev/null +++ b/offsetFit_MultipleLAPPD.cpp @@ -0,0 +1,1076 @@ +// This is a script for offset fitting, use it on the output LAPPDTree.root +// This script require all LAPPD events appear in sequence, and all CTC events appear in sequence +/* procedure: + 1. load LAPPDTree.root (TODO: or use LAPPDTree_runNumber.root) + 2. load TimeStamp tree, get run number and part file number + 3. for each unique run number and part file number, do fit: + 4. in this file, for each LAPPD ID: + 5. loop TimeStamp tree + load data timestamp + load data beamgate + load PPS for board 0 and board 1 + 6. loop Trig (or GTrig) tree + load CTC PPS (word = 32) + load target trigger word + + 7. Find the number of resets in LAPPD PPS: + There must be at least one event in each reset. + Based on the event index order, only fit before the reset which doesn't have data event. + Save the data event and PPS index order. + + 8. Use the target trigger word, fit the offset + 9. save the offset for this LAPPD ID, run number, part file number, index, reset number. + 10. Print info to txt file + +Laser trigger word: 47 +Undelayed beam trigger word: 14 + +root -l -q 'offsetFit_MultipleLAPPD.cpp("LAPPDTree.root", 14, 1, 10, 0)' +root -l -q 'offsetFit_MultipleLAPPD.cpp("LAPPDTree.root", 47, 0, 10, 0)' +*/ +#include +#include +#include +#include +#include +#include +#include "TFile.h" +#include "TTree.h" +#include "TH2D.h" +#include "TH1D.h" +#include "TString.h" + +vector> fitInThisReset( + const std::vector &LAPPDDataTimeStampUL, + const std::vector &LAPPDDataBeamgateUL, + const std::vector &LAPPD_PPS, + const int fitTargetTriggerWord, + const std::vector &CTCTrigger, + const std::vector &CTCPPS, + const ULong64_t PPSDeltaT) +{ + cout << "***************************************" << endl; + cout << "Fitting in this reset with:" << endl; + cout << "LAPPDDataTimeStampUL size: " << LAPPDDataTimeStampUL.size() << endl; + cout << "LAPPDDataBeamgateUL size: " << LAPPDDataBeamgateUL.size() << endl; + cout << "LAPPD_PPS size: " << LAPPD_PPS.size() << endl; + cout << "CTCTrigger size: " << CTCTrigger.size() << endl; + cout << "CTCPPS size: " << CTCPPS.size() << endl; + cout << "PPSDeltaT: " << PPSDeltaT << endl; + // for this input PPS, fit an offset + // return the offset and other information in order + // precedure: + // 1. check drift + // 2. shift the timestmap and beamgate based on drift + // 3. fit the offset + + std::vector PPSInterval_ACDC; + + for (int i = 1; i < LAPPD_PPS.size(); i++) + { + + double diff = static_cast(LAPPD_PPS[i] - LAPPD_PPS[i - 1]); + // cout << "LAPPD_PPS[" << i << "]: " << LAPPD_PPS[i] / 1E9 / 1000 << ", diff is " << diff / 1E9 / 1000 << endl; + // cout << "diff: " << diff/1E9 << ", 0.9*deltaT = " << 0.9 * PPSDeltaT/1E9 << ", 1.1*deltaT = " << 1.1 * PPSDeltaT/1E9 << endl; + // only save the time interval that is close to the deltaT, to avoid the clock tick level miss and the whole PPS pulse was missed. + if (diff > 0.9 * PPSDeltaT && diff < 1.1 * PPSDeltaT) + PPSInterval_ACDC.push_back((PPSDeltaT - diff) / 1000 / 1000); + // cout << "Diff of Interval to deltaT in s is " << (PPSDeltaT - diff) / 1000 / 1E9 << endl; + } + int totalPPS = LAPPD_PPS.size(); + int driftedPPS = 0; + + TH1D *h = new TH1D("h", "h", 1000, 0, 1E3); + for (int i = 0; i < PPSInterval_ACDC.size(); i++) + { + // only fill the drift histogram if there is a drift > 2 microseconds + if (PPSInterval_ACDC[i] / 1000 / 1000 > 2) + { + h->Fill(PPSInterval_ACDC[i] / 1000 / 1000); // fill in microseconds + // cout << "Fill histogram: PPSInterval_ACDC[" << i << "]: " << PPSInterval_ACDC[i] / 1000 / 1000 << endl; + } + } + + TF1 *gausf = new TF1("gausf", "gaus", 0, 1E3); + h->Fit(gausf, "Q"); // Q for quiet mode + ULong64_t drift = static_cast(gausf->GetParameter(1) * 1E3 * 1E3); // drift in ps + ULong64_t trueInterval = PPSDeltaT - drift; + std::cout << "Gaussian Drift in ps is " << drift << std::endl; + std::cout << "True PPS interval in ps is " << trueInterval << std::endl; + delete gausf; + delete h; + + // initialize variables need for fitting + int orphanCount = 0; // count the number that how many data event timestamp doesn't matched to a target trigger within an interval. + + std::map>> DerivationMap; + for (int i = 0; i < LAPPD_PPS.size(); i++) + { + if (i % static_cast(LAPPD_PPS.size() / 5) == 0) + cout << "Fitting PPS " << i << " of " << LAPPD_PPS.size() << endl; + + ULong64_t LAPPD_PPS_ns = LAPPD_PPS.at(i) / 1000; + ULong64_t LAPPD_PPS_truncated_ps = LAPPD_PPS.at(i) % 1000; + + for (int j = 0; j < CTCPPS.size(); j++) + { + vector diffSum; + ULong64_t offsetNow_ns = 0; + if (drift == 0) + { + offsetNow_ns = CTCPPS.at(j) - LAPPD_PPS_ns; + } + else + { + double driftScaling = LAPPD_PPS_ns / trueInterval / 1000; + ULong64_t totalDriftedClock = static_cast(drift * driftScaling / 1000); + offsetNow_ns = CTCPPS.at(j) - (LAPPD_PPS_ns + totalDriftedClock); + } + + if (i < 3 && j < 3) + cout << "In ns: CTCPPS.at(" << j << "): " << CTCPPS.at(j) << ", LAPPD_PPS.at(" << i << "): " << LAPPD_PPS.at(i) << ", use LAPPD_PPS_ns: " << LAPPD_PPS_ns << ", offsetNow_ns: " << offsetNow_ns << endl; + + // now, we have offset in ns. + // We do fit in ns level, then save the previse information in ps level. + + orphanCount = 0; + vector notOrphanIndex; + vector ctcPairedIndex; + vector ctcOrphanPairedIndex; + + for (int lappdb = 0; lappdb < LAPPDDataBeamgateUL.size(); lappdb++) + { + ULong64_t TS_ns = LAPPDDataTimeStampUL.at(lappdb) / 1000; + ULong64_t TS_truncated_ps = LAPPDDataTimeStampUL.at(lappdb) % 1000; + // if fit for the undelayed beam trigger, use BG + if (fitTargetTriggerWord == 14) + { + TS_ns = LAPPDDataBeamgateUL.at(lappdb) / 1000; + TS_truncated_ps = LAPPDDataBeamgateUL.at(lappdb) % 1000; + } + + ULong64_t driftCorrectionForTS = 0; + if (drift != 0) + { + double driftScaling = TS_ns / trueInterval / 1000; + driftCorrectionForTS = static_cast(drift * driftScaling / 1000); + } + + // this is the TS we use for matching + ULong64_t DriftCorrectedTS_ns = TS_ns + offsetNow_ns + driftCorrectionForTS; + + // initialise other matching variables + ULong64_t minMatchDiff = std::numeric_limits::max(); + bool useThisValue = true; + int minPairIndex = 0; + string reason = "none"; + Long64_t first_derivation = 0; + int minIndex = 0; + double useValue = true; + + // find the best match of target trigger to this TS, in ns level. + for (int ctcb = 0; ctcb < CTCTrigger.size(); ctcb++) + { + ULong64_t CTCTrigger_ns = CTCTrigger.at(ctcb); + Long64_t diff = CTCTrigger_ns - DriftCorrectedTS_ns; + if (diff < 0) + diff = -diff; + + if (diff < minMatchDiff) + { + minMatchDiff = diff; + minPairIndex = ctcb; + } + + Long64_t LastBound = diff - minMatchDiff; + if (LastBound < 0) + LastBound = -LastBound; + Long64_t FirstBound = diff - first_derivation; + if (FirstBound < 0) + FirstBound = -FirstBound; + + // save the dt for the first matching to determin the matching position in range. + if (ctcb == 0) + first_derivation = diff; + + if (ctcb == CTCTrigger.size() - 1 && LastBound / 1E9 < 0.01) + { + useValue = false; + reason = "When matching the last TS, this diff is too close to (or even is) the minMatchDiff at index " + std::to_string(minPairIndex) + " in " + std::to_string(CTCTrigger.size()) + ". All LAPPD TS is out of the end of CTC trigger range"; + } + if (ctcb == CTCTrigger.size() - 1 && FirstBound / 1E9 < 0.01) + { + useValue = false; + reason = "When matching the last TS, this diff is too close to (or even is) the first_derivation at index " + std::to_string(minPairIndex) + " in " + std::to_string(CTCTrigger.size()) + ". All LAPPD TS is out of the beginning of CTC trigger range"; + } + } + + if (useValue) + { + diffSum.push_back(minMatchDiff); + double minAllowedDiff = 0; + double maxAllowedDiff = 100E3; + if (fitTargetTriggerWord == 14) + { + minAllowedDiff = 322E3; + maxAllowedDiff = 326E3; + } + if (minMatchDiff > maxAllowedDiff || minMatchDiff < minAllowedDiff) + { + // TODO: adjust the limit for laser. + orphanCount += 1; + ctcOrphanPairedIndex.push_back(minPairIndex); + } + else + { + notOrphanIndex.push_back(lappdb); + ctcPairedIndex.push_back(minPairIndex); + } + } + else + { + orphanCount += 1; + } + } + + double mean_dev = 0; + for (int k = 0; k < diffSum.size(); k++) + { + mean_dev += diffSum[k]; + } + if (diffSum.size() > 0) + mean_dev = mean_dev / diffSum.size(); + + double mean_dev_noOrphan = 0; + for (int k = 0; k < notOrphanIndex.size(); k++) + { + if (fitTargetTriggerWord == 14) + { + if (diffSum.at(k) > 322E3 && diffSum.at(k) < 326E3) + mean_dev_noOrphan += diffSum[notOrphanIndex[k]]; + } + else + { + mean_dev_noOrphan += diffSum[notOrphanIndex[k]]; + } + } + if ((diffSum.size() - orphanCount) != 0) + { + mean_dev_noOrphan = mean_dev_noOrphan / (diffSum.size() - orphanCount); + } + else + { + mean_dev_noOrphan = -1; // if all timestamps are out of the range, set it to -1 + } + + bool increMean_dev = false; + int maxAttempts = 1000; + int attemptCount = 0; + + if (mean_dev > 0) + { + int increament_dev = 0; + while (true) + { + // TODO + auto iter = DerivationMap.find(mean_dev); + if (iter == DerivationMap.end() || iter->second.empty()) + { + vector Info = {i, j, orphanCount, static_cast(mean_dev_noOrphan * 1000), increament_dev}; + DerivationMap[mean_dev].push_back(Info); + DerivationMap[mean_dev].push_back(notOrphanIndex); + DerivationMap[mean_dev].push_back(ctcPairedIndex); + DerivationMap[mean_dev].push_back(ctcOrphanPairedIndex); + break; + } + else + { + increament_dev += 1; + mean_dev += 0.001; // if the mean_dev is already in the map, increase it by 1ps + attemptCount += 1; + if (attemptCount > maxAttempts) + break; + } + } + } + } + } + + // finish matching, found the minimum mean_dev in the map, extract the matching information + double min_mean_dev = std::numeric_limits::max(); + int final_i = 0; + int final_j = 0; + int gotOrphanCount = 0; + double gotMin_mean_dev_noOrphan = 0; + double increament_times = 0; + vector final_notOrphanIndex; + vector final_ctcPairedIndex; + vector final_ctcOrphanIndex; + + for (const auto &minIter : DerivationMap) + { + if (minIter.first > 10 && minIter.first < min_mean_dev) + { + min_mean_dev = minIter.first; + final_i = minIter.second[0][0]; + final_j = minIter.second[0][1]; + gotOrphanCount = minIter.second[0][2]; + gotMin_mean_dev_noOrphan = static_cast(minIter.second[0][3] / 1000); + increament_times = minIter.second[0][4]; + final_notOrphanIndex = minIter.second[1]; + final_ctcPairedIndex = minIter.second[2]; + final_ctcOrphanIndex = minIter.second[3]; + } + } + + ULong64_t final_offset_ns = 0; + ULong64_t final_offset_ps_negative = 0; + if (drift == 0) + { + final_offset_ns = CTCPPS.at(final_j) - (LAPPD_PPS.at(final_i) / 1000); + final_offset_ps_negative = LAPPD_PPS.at(final_i) % 1000; + } + else + { + ULong64_t LAPPD_PPS_ns = LAPPD_PPS.at(final_i) / 1000; + ULong64_t LAPPD_PPS_truncated_ps = LAPPD_PPS.at(final_i) % 1000; + double driftScaling = LAPPD_PPS_ns / trueInterval / 1000; // this is the same drift scaling as in the matching loop + ULong64_t totalDriftedClock = static_cast(drift * driftScaling / 1000); + final_offset_ns = CTCPPS.at(final_j) - (LAPPD_PPS_ns + totalDriftedClock); + final_offset_ps_negative = LAPPD_PPS_truncated_ps; // this is useless if there is a drift though. + } + /* + cout << "******* Fit Finished *******" << endl; + cout << "*** Final offset in is " << final_offset_ns << " ns minus " << final_offset_ps_negative << " ps" << endl; + cout << "*** Final orphan count is " << gotOrphanCount << endl; + cout << "*** Final mean_dev_noOrphan is " << gotMin_mean_dev_noOrphan << " ps" << endl; + cout << "*** Final increament times in this result is " << increament_times << endl; + cout << "*** Final mean deviation is " << min_mean_dev << " ps" << endl; + cout << "*** Final PPS index is " << final_i << ", in total of " << LAPPD_PPS.size() << endl; + cout << "*** Final CTC PPS index is " << final_j << ", in total of " << CTCPPS.size() << endl; + cout << "***************************" << endl; + cout << "******* Saving *************" << endl; + */ + + cout << "\033[1;34m******* Fit Finished *******\033[0m" << endl; + + cout << "\033[1;34m*** Final offset in is \033[1;31m" << final_offset_ns << "\033[1;34m ns minus \033[1;31m" << final_offset_ps_negative << "\033[1;34m ps\033[0m" << endl; + cout << "\033[1;34m*** Final orphan count is \033[1;31m" << gotOrphanCount << "\033[0m" << endl; + cout << "\033[1;34m*** Final mean_dev_noOrphan is \033[1;31m" << gotMin_mean_dev_noOrphan << "\033[1;34m ns\033[0m" << endl; + cout << "\033[1;34m*** Final increament times in this result is \033[1;31m" << increament_times << "\033[0m" << endl; + cout << "\033[1;34m*** Final mean deviation is \033[1;31m" << min_mean_dev << "\033[1;34m ns\033[0m" << endl; + cout << "\033[1;34m*** Final PPS index is \033[1;31m" << final_i << "\033[1;34m, in total of \033[1;31m" << LAPPD_PPS.size() << "\033[0m" << endl; + cout << "\033[1;34m*** Final CTC PPS index is \033[1;31m" << final_j << "\033[1;34m, in total of \033[1;31m" << CTCPPS.size() << "\033[0m" << endl; + cout << "\033[1;34m***************************\033[0m" << endl; + cout << "\033[1;34m******* Saving *************\033[0m" << endl; + + // now, based on this offset, calculate the event time for each event, and save to result. + vector TimeStampRaw; + vector BeamGateRaw; + vector TimeStamp_ns; + vector BeamGate_ns; + vector TimeStamp_ps; + vector BeamGate_ps; + vector EventIndex; + vector EventDeviation_ns; + vector CTCTriggerIndex; + vector CTCTriggerTimeStamp_ns; + vector BeamGate_correction_tick; + vector TimeStamp_correction_tick; + vector PPS_tick_correction; // if timestamp falls in between of PPS i and i+1, corrected timestamp = timestamp + PPS_tick_correction[i] + vector LAPPD_PPS_missing_ticks; + vector LAPPD_PPS_interval_ticks; + + // calculate the missing ticks for each LAPPD PPS + PPS_tick_correction.push_back(0); + LAPPD_PPS_missing_ticks.push_back(0); + LAPPD_PPS_interval_ticks.push_back(0); + ULong64_t intervalTicks = 320000000 * (PPSDeltaT / 1000 / 1E9); + for (int i = 1; i < LAPPD_PPS.size(); i++) + { + ULong64_t thisPPS = LAPPD_PPS.at(i) / 3125; + ULong64_t prevPPS = LAPPD_PPS.at(i - 1) / 3125; + long long thisInterval = thisPPS - prevPPS; + long long thisMissingTicks = intervalTicks - thisInterval; + LAPPD_PPS_interval_ticks.push_back(thisInterval); + + // if the difference between this PPS and previous PPS is > intervalTicks-20 and < intervalTicks+5, + // the missed value is thisInterval - intervalTicks + // push this value plus the sum of previous missing ticks to the vector + // else just push the sum of previous missing ticks + long long sumOfPreviousMissingTicks = 0; + for (int j = 0; j < LAPPD_PPS_missing_ticks.size(); j++) + { + sumOfPreviousMissingTicks += LAPPD_PPS_missing_ticks.at(j); + } + + if (thisMissingTicks > -20 && thisMissingTicks < 20) + { + LAPPD_PPS_missing_ticks.push_back(thisMissingTicks); + PPS_tick_correction.push_back(thisMissingTicks + sumOfPreviousMissingTicks); + } + else + { + // some time one pps might be wired, but the combination of two is ok. + bool combined = false; + // if there are missing PPS, interval is like 22399999990 % 3200000000 = 3199999990 + long long pInterval = thisInterval % intervalTicks; + long long missingPTicks = 0; + if (intervalTicks - pInterval < 30) + missingPTicks = intervalTicks - pInterval; + else if (pInterval < 30) + missingPTicks = -pInterval; +////// + if(missingPTicks == 1 || missingPTicks == -1){ + cout<<"Found missing tick is "< -30 && combinedMissingTicks < 30) + { + LAPPD_PPS_missing_ticks.push_back(combinedMissingTicks); + PPS_tick_correction.push_back(combinedMissingTicks + sumOfPreviousMissingTicks); + combined = true; + cout << "Pushing PPS correction " << i << ", this PPS interval tick is " << thisInterval << ", missing ticks: " << thisMissingTicks << ", push missing " << LAPPD_PPS_missing_ticks.at(i) << ", push correction " << PPS_tick_correction.at(i) << endl; + continue; + } + } + + if (!combined) + { + LAPPD_PPS_missing_ticks.push_back(0); + PPS_tick_correction.push_back(sumOfPreviousMissingTicks); + } + } + cout << "Pushing PPS correction " << i << ", this PPS interval tick is " << thisInterval << ", missing ticks: " << thisMissingTicks << ", push missing " << LAPPD_PPS_missing_ticks.at(i) << ", push correction " << PPS_tick_correction.at(i) << endl; + } + + // loop all data events, plus the offset, save the event time and beamgate time + // fing the closest CTC trigger, also save all information + for (int l = 0; l < LAPPDDataTimeStampUL.size(); l++) + { + ULong64_t TS_ns = LAPPDDataTimeStampUL.at(l) / 1000; + ULong64_t TS_truncated_ps = LAPPDDataTimeStampUL.at(l) % 1000; + ULong64_t BG_ns = LAPPDDataBeamgateUL.at(l) / 1000; + ULong64_t BG_truncated_ps = LAPPDDataBeamgateUL.at(l) % 1000; + ULong64_t driftCorrectionForTS = 0; + ULong64_t driftCorrectionForBG = 0; + if (drift != 0) + { + double driftScaling = TS_ns / trueInterval / 1000; + driftCorrectionForTS = static_cast(drift * driftScaling / 1000); + double driftScalingBG = BG_ns / trueInterval / 1000; + driftCorrectionForBG = static_cast(drift * driftScalingBG / 1000); + } + ULong64_t DriftCorrectedTS_ns = TS_ns + final_offset_ns + driftCorrectionForTS; + ULong64_t DriftCorrectedBG_ns = BG_ns + final_offset_ns + driftCorrectionForBG; + ULong64_t min_mean_dev_match = std::numeric_limits::max(); + int matchedIndex = 0; + for (int c = 0; c < CTCTrigger.size(); c++) + { + ULong64_t CTCTrigger_ns = CTCTrigger.at(c); + Long64_t diff = CTCTrigger_ns - DriftCorrectedTS_ns; + if (diff < 0) + diff = -diff; + if (diff < min_mean_dev_match) + { + matchedIndex = c; + min_mean_dev_match = diff; + } + } + + // check the position of beamgate and timestamp raw fall into which pps interval; + bool TSFound = false; + bool BGFound = false; + for (int i = 0; i < LAPPD_PPS.size() - 1; i++) + { + if (LAPPD_PPS.at(i) / 3125 < LAPPDDataTimeStampUL.at(l) / 3125 && LAPPD_PPS.at(i + 1) / 3125 > LAPPDDataTimeStampUL.at(l) / 3125) + { + TimeStamp_correction_tick.push_back(PPS_tick_correction.at(i)+1000); + TSFound = true; + break; + } + } + if (!TSFound && LAPPDDataTimeStampUL.at(l) / 3125 > LAPPD_PPS.at(LAPPD_PPS.size() - 1) / 3125) + { + TimeStamp_correction_tick.push_back(PPS_tick_correction.at(LAPPD_PPS.size() - 1)+1000); + TSFound = true; + } + if (!TSFound && LAPPDDataTimeStampUL.at(l) / 3125 < LAPPD_PPS.at(0) / 3125) + { + TimeStamp_correction_tick.push_back(0+1000); + TSFound = true; + } + + for (int i = 0; i < LAPPD_PPS.size() - 1; i++) + { + if (LAPPD_PPS.at(i) / 3125 < LAPPDDataBeamgateUL.at(l) / 3125 && LAPPD_PPS.at(i + 1) / 3125 > LAPPDDataBeamgateUL.at(l) / 3125) + { + BeamGate_correction_tick.push_back(PPS_tick_correction.at(i)+1000); + BGFound = true; + cout << "Normal push: BGraw = " << LAPPDDataBeamgateUL.at(l) / 3125 << ", pps = " << LAPPD_PPS.at(i) << ", pps/3125 = " << LAPPD_PPS.at(i) / 3125 << endl; + if(LAPPD_PPS_interval_ticks.at(i) != intervalTicks) + { + cout << "Warning: PPS interval is not " << intervalTicks << " at index " << i << ", it is " << LAPPD_PPS_interval_ticks.at(i) << endl; + } + break; + } + } + if (!BGFound && LAPPDDataBeamgateUL.at(l) / 3125 > LAPPD_PPS.at(LAPPD_PPS.size() - 1) / 3125) + { + BeamGate_correction_tick.push_back(PPS_tick_correction.at(LAPPD_PPS.size() - 1)+1000); + cout << "BGraw = " << LAPPDDataBeamgateUL.at(l) / 3125 << ", pps = " << LAPPD_PPS.at(LAPPD_PPS.size() - 1) << ", pps/3125 = " << LAPPD_PPS.at(LAPPD_PPS.size() - 1) / 3125 << endl; + BGFound = true; + } + if (!BGFound && LAPPDDataBeamgateUL.at(l) / 3125 < LAPPD_PPS.at(0) / 3125) + { + BeamGate_correction_tick.push_back(0+1000); + cout << "BGraw less than pps0" << endl; + BGFound = true; + } + if (!TSFound || !BGFound) + { + cout << "Error: PPS not found for event " << l << ", TSFound: " << TSFound << ", BGFound: " << BGFound << endl; + } + /* + cout << "******Found result:" << endl; + cout << "LAPPDDataTimeStampUL.at(" << l << "): " << LAPPDDataTimeStampUL.at(l)/3125 << endl; + cout << "LAPPDDataBeamgateUL.at(" << l << "): " << LAPPDDataBeamgateUL.at(l)/3125 << endl; + cout << "TS_ns: " << TS_ns << endl; + cout << "BG_ns: " << BG_ns << endl; + cout << "final_offset_ns: " << final_offset_ns << endl; + cout << "drift: " << drift << endl; + cout << "TS driftscaling: " << TS_ns / trueInterval / 1000 << endl; + cout << "DriftCorrectedTS_ns: " << DriftCorrectedTS_ns << endl; + cout << "TS_truncated_ps: " << TS_truncated_ps << endl; + cout << "DriftCorrectedBG_ns: " << DriftCorrectedBG_ns << endl; + cout << "BG_truncated_ps: " << BG_truncated_ps << endl; + cout << "Found min_mean_dev_match: " << min_mean_dev_match << endl; + cout << "MatchedIndex: " << matchedIndex << endl; + cout << "CTCTrigger.at(" << matchedIndex << "): " << CTCTrigger.at(matchedIndex) << endl; + cout << "BeamGate_correction_tick at " << l << ": " << BeamGate_correction_tick.at(l) << endl; + cout << "TimeStamp_correction_tick at " << l << ": " << TimeStamp_correction_tick.at(l) << endl; + */ + + TimeStampRaw.push_back(LAPPDDataTimeStampUL.at(l) / 3125); + BeamGateRaw.push_back(LAPPDDataBeamgateUL.at(l) / 3125); + TimeStamp_ns.push_back(DriftCorrectedTS_ns); + BeamGate_ns.push_back(DriftCorrectedBG_ns); + TimeStamp_ps.push_back(TS_truncated_ps); + BeamGate_ps.push_back(BG_truncated_ps); + EventIndex.push_back(l); + EventDeviation_ns.push_back(min_mean_dev_match); + // to get ps, should minus the TS_truncated_ps + CTCTriggerIndex.push_back(matchedIndex); + CTCTriggerTimeStamp_ns.push_back(CTCTrigger.at(matchedIndex)); + } + ULong64_t totalEventNumber = LAPPDDataTimeStampUL.size(); + ULong64_t gotOrphanCount_out = gotOrphanCount; + ULong64_t gotMin_mean_dev_noOrphan_out = gotMin_mean_dev_noOrphan; + ULong64_t increament_times_out = increament_times; + ULong64_t min_mean_dev_out = min_mean_dev; + ULong64_t final_i_out = final_i; + ULong64_t final_j_out = final_j; + ULong64_t drift_out = drift; + + vector FitInfo = {final_offset_ns, final_offset_ps_negative, gotOrphanCount_out, gotMin_mean_dev_noOrphan_out, increament_times_out, min_mean_dev_out, final_i_out, final_j_out, totalEventNumber, drift_out}; + + vector> Result = {FitInfo, TimeStampRaw, BeamGateRaw, TimeStamp_ns, BeamGate_ns, TimeStamp_ps, BeamGate_ps, EventIndex, EventDeviation_ns, CTCTriggerIndex, CTCTriggerTimeStamp_ns, BeamGate_correction_tick, TimeStamp_correction_tick, LAPPD_PPS_interval_ticks}; + return Result; +} + +vector> fitInPartFile(TTree *lappdTree, TTree *triggerTree, int runNumber, int subRunNumber, int partFileNumber, int LAPPD_ID, int fitTargetTriggerWord, bool triggerGrouped, int intervalInSecond) +{ + cout << "***************************************" << endl; + cout << "Fitting in run " << runNumber << ", sub run " << subRunNumber << ", part file " << partFileNumber << " for LAPPD ID " << LAPPD_ID << endl; + + vector LAPPD_PPS0; + vector LAPPD_PPS1; + vector LAPPDDataTimeStampUL; + vector LAPPDDataBeamgateUL; + + vector CTCTargetTimeStamp; + vector CTCPPSTimeStamp; + + int LAPPD_ID_inTree; + int runNumber_inTree; + int subRunNumber_inTree; + int partFileNumber_inTree; + + ULong64_t ppsTime0; + ULong64_t ppsTime1; + ULong64_t LAPPDTimeStampUL; + ULong64_t LAPPDBeamgateUL; + ULong64_t LAPPDDataTimestamp; + ULong64_t LAPPDDataBeamgate; + double LAPPDDataTimestampFloat; + double LAPPDDataBeamgateFloat; + + vector *CTCTriggerWord = nullptr; + ULong64_t CTCTimeStamp; + vector *groupedTriggerWords = nullptr; + vector *groupedTriggerTimestamps = nullptr; + + lappdTree->SetBranchAddress("RunNumber", &runNumber_inTree); + lappdTree->SetBranchAddress("SubRunNumber", &subRunNumber_inTree); + lappdTree->SetBranchAddress("PartFileNumber", &partFileNumber_inTree); + lappdTree->SetBranchAddress("LAPPD_ID", &LAPPD_ID_inTree); + lappdTree->SetBranchAddress("LAPPDDataTimeStampUL", &LAPPDTimeStampUL); + lappdTree->SetBranchAddress("LAPPDDataBeamgateUL", &LAPPDBeamgateUL); + lappdTree->SetBranchAddress("LAPPDDataTimestamp", &LAPPDDataTimestamp); + lappdTree->SetBranchAddress("LAPPDDataBeamgate", &LAPPDDataBeamgate); + lappdTree->SetBranchAddress("LAPPDDataTimestampFloat", &LAPPDDataTimestampFloat); + lappdTree->SetBranchAddress("LAPPDDataBeamgateFloat", &LAPPDDataBeamgateFloat); + lappdTree->SetBranchAddress("ppsTime0", &ppsTime0); + lappdTree->SetBranchAddress("ppsTime1", &ppsTime1); + + // triggerTree->Print(); + triggerTree->SetBranchAddress("RunNumber", &runNumber_inTree); + triggerTree->SetBranchAddress("SubRunNumber", &subRunNumber_inTree); + triggerTree->SetBranchAddress("PartFileNumber", &partFileNumber_inTree); + if (triggerGrouped) + { + triggerTree->SetBranchAddress("gTrigWord", &groupedTriggerWords); + triggerTree->SetBranchAddress("gTrigTime", &groupedTriggerTimestamps); + } + else + { + triggerTree->SetBranchAddress("CTCTriggerWord", &CTCTriggerWord); + triggerTree->SetBranchAddress("CTCTimeStamp", &CTCTimeStamp); + } + + int l_nEntries = lappdTree->GetEntries(); + int t_nEntries = triggerTree->GetEntries(); + int repeatedPPSNumber0 = -1; + int repeatedPPSNumber1 = -1; + + // 5. loop TimeStamp tree + for (int i = 0; i < l_nEntries; i++) + { + lappdTree->GetEntry(i); + // if(i<100) + // cout<<"LAPPD_ID_inTree: "<(LAPPDTimeStampUL * 1000 / 8 * 25) / 1E9 / 1000 << ", Beamgate: " << static_cast(LAPPDBeamgateUL * 1000 / 8 * 25) / 1E9 / 1000 << endl; + LAPPDDataTimeStampUL.push_back(LAPPDTimeStampUL * 1000 / 8 * 25); + LAPPDDataBeamgateUL.push_back(LAPPDBeamgateUL * 1000 / 8 * 25); + /* + cout << "LAPPDDataTimestamp: " << LAPPDDataTimestamp << ", LAPPDDataBeamgate: " << LAPPDDataBeamgate << endl; + cout << "LAPPDDataTimestampFloat: " << LAPPDDataTimestampFloat << ", LAPPDDataBeamgateFloat: " << LAPPDDataBeamgateFloat << endl; + ULong64_t ULTS = LAPPDTimeStampUL*1000/8*25; + double DTS = static_cast(LAPPDDataTimestamp); + double plusDTS = DTS + LAPPDDataTimestampFloat; + ULong64_t ULBG = LAPPDBeamgateUL*1000/8*25; + double DBG = static_cast(LAPPDDataBeamgate); + double plusDBG = DBG + LAPPDDataBeamgateFloat; + cout << std::fixed << " ULTS: " << ULTS << ", DTS: " << DTS << ", plusDTS: " << plusDTS << endl; + cout << std::fixed << " ULBG: " << ULBG << ", DBG: " << DBG << ", plusDBG: " << plusDBG << endl; + cout << endl; + */ + } + else if (LAPPDTimeStampUL == 0) + { + // cout << "ppsTime0: " << ppsTime0 << ", ppsTime1: " << ppsTime1 << endl; + if (LAPPD_PPS0.size() == 0) + LAPPD_PPS0.push_back(ppsTime0 * 1000 / 8 * 25); + if (LAPPD_PPS1.size() == 0) + LAPPD_PPS1.push_back(ppsTime1 * 1000 / 8 * 25); + if (LAPPD_PPS0.size() > 0 && ppsTime0 * 1000 / 8 * 25 != LAPPD_PPS0.at(LAPPD_PPS0.size() - 1)) + LAPPD_PPS0.push_back(ppsTime0 * 1000 / 8 * 25); + else + repeatedPPSNumber0 += 1; + if (LAPPD_PPS1.size() > 0 && ppsTime1 * 1000 / 8 * 25 != LAPPD_PPS1.at(LAPPD_PPS1.size() - 1)) + LAPPD_PPS1.push_back(ppsTime1 * 1000 / 8 * 25); + else + repeatedPPSNumber1 += 1; + } + } + } + cout << "repeatedPPSNumber0: " << repeatedPPSNumber0 << ", loaded PPS0 size: " << LAPPD_PPS0.size() << endl; + cout << "repeatedPPSNumber1: " << repeatedPPSNumber1 << ", loaded PPS1 size: " << LAPPD_PPS1.size() << endl; + + // 6. loop Trig (or GTrig) tree + for (int i = 0; i < t_nEntries; i++) + { + triggerTree->GetEntry(i); + if (runNumber_inTree == runNumber && subRunNumber_inTree == subRunNumber && partFileNumber_inTree == partFileNumber) + { + // cout<<"triggerGrouped: "<size(); j++) + { + // cout<<"At j = "<at(j)<<", fitTargetTriggerWord: "<at(j) == fitTargetTriggerWord) + CTCTargetTimeStamp.push_back(groupedTriggerTimestamps->at(j)); + if (groupedTriggerWords->at(j) == 32) + CTCPPSTimeStamp.push_back(groupedTriggerTimestamps->at(j)); + } + } + else + { + for (int j = 0; j < CTCTriggerWord->size(); j++) + { + if (CTCTriggerWord->at(j) == fitTargetTriggerWord) + CTCTargetTimeStamp.push_back(CTCTimeStamp); + if (CTCTriggerWord->at(j) == 32) + CTCPPSTimeStamp.push_back(CTCTimeStamp); + } + } + } + } + cout << "Vector for partfile " << partFileNumber << " for LAPPD ID " << LAPPD_ID << " loaded." << endl; + cout << "LAPPDDataTimeStampUL in ps size: " << LAPPDDataTimeStampUL.size() << endl; + cout << "LAPPDDataBeamgateUL in ps size: " << LAPPDDataBeamgateUL.size() << endl; + cout << "LAPPD_PPS0 size: " << LAPPD_PPS0.size() << endl; + cout << "LAPPD_PPS1 size: " << LAPPD_PPS1.size() << endl; + cout << "CTCTargetTimeStamp size: " << CTCTargetTimeStamp.size() << endl; + cout << "CTCPPSTimeStamp size: " << CTCPPSTimeStamp.size() << endl; + // 7. Find the number of resets in LAPPD PPS: + int LAPPDDataFitStopIndex = 0; + int resetNumber = 0; + // first check is there a reset, if no, set the LAPPDDataFitStopIndex to the size of LAPPDDataTimeStampUL + // if all PPS in this part file was increamented, then there is no reset + for (int i = 1; i < LAPPD_PPS0.size(); i++) + { + if (LAPPD_PPS0[i] < LAPPD_PPS0[i - 1]) + { + resetNumber += 1; + cout << "For LAPPD ID " << LAPPD_ID << ", run number " << runNumber << ", sub run number " << subRunNumber << ", part file number " << partFileNumber << ", reset " + << " found at PPS_ACDC0 index " << i << endl; + break; + } + } + for (int i = 1; i < LAPPD_PPS1.size(); i++) + { + if (LAPPD_PPS1[i] < LAPPD_PPS1[i - 1]) + { + resetNumber += 1; + cout << "For LAPPD ID " << LAPPD_ID << ", run number " << runNumber << ", sub run number " << subRunNumber << ", part file number " << partFileNumber << ", reset " + << " found at PPS_ACDC1 index " << i << endl; + break; + } + } + if (resetNumber == 0) + cout << "For LAPPD ID " << LAPPD_ID << ", run number " << runNumber << ", sub run number " << subRunNumber << ", part file number " << partFileNumber << ", no reset found." << endl; + + // if reset found, loop the timestamp in order to find the LAPPDDataFitStopIndex + // + if (resetNumber != 0) + { + for (int i = 1; i < LAPPDDataTimeStampUL.size(); i++) + { + if (LAPPDDataTimeStampUL[i] < LAPPDDataTimeStampUL[i - 1]) + { + LAPPDDataFitStopIndex = i - 1; + break; + } + } + // TODO: extend this to later offsets + } + // 8. Use the target trigger word, fit the offset + // TODO: fit for each reset + vector> ResultTotal; + if (LAPPDDataTimeStampUL.size() == LAPPDDataBeamgateUL.size()) + { + vector> ResultACDC0 = fitInThisReset(LAPPDDataTimeStampUL, LAPPDDataBeamgateUL, LAPPD_PPS0, fitTargetTriggerWord, CTCTargetTimeStamp, CTCPPSTimeStamp, intervalInSecond * 1E9 * 1000); + vector> ResultACDC1 = fitInThisReset(LAPPDDataTimeStampUL, LAPPDDataBeamgateUL, LAPPD_PPS1, fitTargetTriggerWord, CTCTargetTimeStamp, CTCPPSTimeStamp, intervalInSecond * 1E9 * 1000); + + // 9. save the offset for this LAPPD ID, run number, part file number, index, reset number. + + cout << "Fitting in part file " << partFileNumber << " for LAPPD ID " << LAPPD_ID << " done." << endl; + + // Combine ResultACDC0 and ResultACDC1 to ResultTotal + for (int i = 0; i < ResultACDC0.size(); i++) + { + ResultTotal.push_back(ResultACDC0[i]); + } + for (int i = 0; i < ResultACDC1.size(); i++) + { + ResultTotal.push_back(ResultACDC1[i]); + } + } + return ResultTotal; +} + +void offsetFit_MultipleLAPPD(string fileName, int fitTargetTriggerWord, bool triggerGrouped, int intervalInSecond, int processPFNumber) +{ + // 1. load LAPPDTree.root + const string file = fileName; + TFile *f = new TFile(file.c_str(), "READ"); + if (!f->IsOpen()) + { + std::cerr << "Error: cannot open file " << file << std::endl; + return; + } + + std::cout << "Opened file " << file << std::endl; + + std::ofstream outputOffset("offset.txt"); + + outputOffset << "runNumber" + << "\t" + << "subRunNumber" + << "\t" + << "partFileNumber" + << "\t" + << "resetNumber" + << "\t" + << "LAPPD_ID" + << "\t" + << "offset_ACDC0_ns" + << "\t" + << "offset_ACDC1_ns" + << "\t" + << "offset_ACDC0_ps_negative" + << "\t" + << "offset_ACDC1_ps_negative" + << "\t" + << "gotOrphanCount_ACDC0" + << "\t" + << "gotOrphanCount_ACDC1" + << "\t" + << "EventNumInThisPartFile" + << "\t" + << "min_mean_dev_noOrphan_ACDC0" + << "\t" + << "min_mean_dev_noOrphan_ACDC1" + << "\t" + << "increament_times_ACDC0" + << "\t" + << "increament_times_ACDC1" + << "\t" + << "min_mean_dev_ACDC0" + << "\t" + << "min_mean_dev_ACDC1" + << std::endl; + + // 2. load TimeStamp tree, get run number and part file number + TTree *TSTree = (TTree *)f->Get("TimeStamp"); + TTree *CTCTree = (TTree *)f->Get("Trig"); + TTree *GCTCTree = (TTree *)f->Get("GTrig"); + int runNumber; + int subRunNumber; + int partFileNumber; + int LAPPD_ID; + ULong64_t ppsCount0; + TSTree->SetBranchAddress("RunNumber", &runNumber); + TSTree->SetBranchAddress("SubRunNumber", &subRunNumber); + TSTree->SetBranchAddress("PartFileNumber", &partFileNumber); + TSTree->SetBranchAddress("LAPPD_ID", &LAPPD_ID); + TSTree->SetBranchAddress("ppsCount0", &ppsCount0); + std::vector> loopInfo; + int nEntries = TSTree->GetEntries(); + for (int i = 0; i < nEntries; i++) + { + TSTree->GetEntry(i); + // if this entry is PPS event, continue. + if (ppsCount0 != 0) + continue; + vector info = {runNumber, subRunNumber, partFileNumber, LAPPD_ID}; + // find if this info is already in loopInfo + bool found = std::find_if(loopInfo.begin(), loopInfo.end(), [&info](const std::vector &vec) + { + return vec == info; // compare vec and info + }) != loopInfo.end(); // if find_if doesn't return end,found + + if (!found) + loopInfo.push_back(info); + } + + // 3. for each unique run number and part file number + // 4. in this file, for each LAPPD ID + // do fit: + std::map>> ResultMap; + std::vector>::iterator it; + int pfNumber = 0; + for (it = loopInfo.begin(); it != loopInfo.end(); it++) + { + int runNumber = (*it)[0]; + int subRunNumber = (*it)[1]; + int partFileNumber = (*it)[2]; + int LAPPD_ID = (*it)[3]; + if (processPFNumber != 0) + { + if (pfNumber >= processPFNumber) + break; + } + + vector> Result; + if (!triggerGrouped) + { // cout<<"trigger not grouped"<> Result = {FitInfo, TimeStampRaw, BeamGateRaw, TimeStamp_ns, BeamGate_ns, TimeStamp_ps, BeamGate_ps, EventIndex, EventDeviation_ns, CTCTriggerIndex, CTCTriggerTimeStamp_ns,BeamGate_correction_tick,TimeStamp_correction_tick}; + vector FitInfo = {final_offset_ns, final_offset_ps_negative, gotOrphanCount, gotMin_mean_dev_noOrphan, increament_times, min_mean_dev, final_i, final_j, totalEventNumber}; + vector TimeStampRaw; + vector BeamGateRaw; + vector TimeStamp_ns; + vector BeamGate_ns; + vector TimeStamp_ps; + vector BeamGate_ps; + vector EventIndex; + vector EventDeviation_ns; + vector CTCTriggerIndex; + vector CTCTriggerTimeStamp_ns; + vector BeamGate_correction_tick; + vector TimeStamp_correction_tick; + */ + // Loop the ResultMap, save the result to a root tree in a root file + cout << "Start saving the result to root file and txt file..." << endl; + TFile *fOut = new TFile("offsetFitResult.root", "RECREATE"); + TTree *tOut = new TTree("Events", "Events"); + int runNumber_out; + int subRunNumber_out; + int partFileNumber_out; + int LAPPD_ID_out; + ULong64_t EventIndex; + ULong64_t EventNumberInThisPartFile; + ULong64_t final_offset_ns_0; + ULong64_t final_offset_ns_1; + ULong64_t final_offset_ps_negative_0; + ULong64_t final_offset_ps_negative_1; + ULong64_t gotOrphanCount_0; + ULong64_t gotOrphanCount_1; + ULong64_t gotMin_mean_dev_noOrphan_0; + ULong64_t gotMin_mean_dev_noOrphan_1; + ULong64_t increament_times_0; + ULong64_t increament_times_1; + ULong64_t min_mean_dev_0; + ULong64_t min_mean_dev_1; + ULong64_t TimeStampRaw; + ULong64_t BeamGateRaw; + ULong64_t TimeStamp_ns; + ULong64_t BeamGate_ns; + ULong64_t TimeStamp_ps; + ULong64_t BeamGate_ps; + ULong64_t EventDeviation_ns_0; + ULong64_t EventDeviation_ns_1; + ULong64_t CTCTriggerIndex; + ULong64_t CTCTriggerTimeStamp_ns; + long long BGMinusTrigger_ns; + long long BGCorrection_tick; + long long TSCorrection_tick; + ULong64_t LAPPD_PPS_interval_ticks; + tOut->Branch("runNumber", &runNumber_out, "runNumber/I"); + tOut->Branch("subRunNumber", &subRunNumber_out, "subRunNumber/I"); + tOut->Branch("partFileNumber", &partFileNumber_out, "partFileNumber/I"); + tOut->Branch("LAPPD_ID", &LAPPD_ID_out, "LAPPD_ID/I"); + tOut->Branch("EventIndex", &EventIndex, "EventIndex/l"); + tOut->Branch("EventNumInThisPF", &EventNumberInThisPartFile, "EventNumInThisPF/l"); + tOut->Branch("final_offset_ns_0", &final_offset_ns_0, "final_offset_ns_0/l"); + tOut->Branch("final_offset_ns_1", &final_offset_ns_1, "final_offset_ns_1/l"); + tOut->Branch("final_offset_ps_negative_0", &final_offset_ps_negative_0, "final_offset_ps_negative_0/l"); + tOut->Branch("final_offset_ps_negative_1", &final_offset_ps_negative_1, "final_offset_ps_negative_1/l"); + tOut->Branch("gotOrphanCount_0", &gotOrphanCount_0, "gotOrphanCount_0/l"); + tOut->Branch("gotOrphanCount_1", &gotOrphanCount_1, "gotOrphanCount_1/l"); + tOut->Branch("gotMin_mean_dev_noOrphan_0", &gotMin_mean_dev_noOrphan_0, "gotMin_mean_dev_noOrphan_0/l"); + tOut->Branch("gotMin_mean_dev_noOrphan_1", &gotMin_mean_dev_noOrphan_1, "gotMin_mean_dev_noOrphan_1/l"); + tOut->Branch("increament_times_0", &increament_times_0, "increament_times_0/l"); + tOut->Branch("increament_times_1", &increament_times_1, "increament_times_1/l"); + tOut->Branch("min_mean_dev_0", &min_mean_dev_0, "min_mean_dev_0/l"); + tOut->Branch("min_mean_dev_1", &min_mean_dev_1, "min_mean_dev_1/l"); + tOut->Branch("TimeStampRaw", &TimeStampRaw, "TimeStampRaw/l"); + tOut->Branch("BeamGateRaw", &BeamGateRaw, "BeamGateRaw/l"); + tOut->Branch("TimeStamp_ns", &TimeStamp_ns, "TimeStamp_ns/l"); + tOut->Branch("BeamGate_ns", &BeamGate_ns, "BeamGate_ns/l"); + tOut->Branch("TimeStamp_ps", &TimeStamp_ps, "TimeStamp_ps/l"); + tOut->Branch("BeamGate_ps", &BeamGate_ps, "BeamGate_ps/l"); + tOut->Branch("EventDeviation_ns_0", &EventDeviation_ns_0, "EventDeviation_ns_0/l"); + tOut->Branch("EventDeviation_ns_1", &EventDeviation_ns_1, "EventDeviation_ns_1/l"); + tOut->Branch("CTCTriggerIndex", &CTCTriggerIndex, "CTCTriggerIndex/l"); + tOut->Branch("CTCTriggerTimeStamp_ns", &CTCTriggerTimeStamp_ns, "CTCTriggerTimeStamp_ns/l"); + tOut->Branch("BGMinusTrigger_ns", &BGMinusTrigger_ns, "BGMinusTrigger_ns/L"); + tOut->Branch("BGCorrection_tick", &BGCorrection_tick, "BGCorrection_tick/l"); + tOut->Branch("TSCorrection_tick", &TSCorrection_tick, "TSCorrection_tick/l"); + tOut->Branch("LAPPD_PPS_interval_ticks", &LAPPD_PPS_interval_ticks, "LAPPD_PPS_interval_ticks/l"); + std::ofstream outputEvents("outputEvents.txt"); + for (auto it = ResultMap.begin(); it != ResultMap.end(); it++) + { + string key = it->first; + vector> Result = it->second; + + runNumber_out = std::stoi(key.substr(0, key.find("_"))); + subRunNumber_out = std::stoi(key.substr(key.find("_") + 1, key.find("_", key.find("_") + 1) - key.find("_") - 1)); + partFileNumber_out = std::stoi(key.substr(key.find("_", key.find("_") + 1) + 1, key.find("_", key.find("_", key.find("_") + 1) + 1) - key.find("_", key.find("_") + 1) - 1)); + LAPPD_ID_out = std::stoi(key.substr(key.find("_", key.find("_", key.find("_") + 1) + 1) + 1, key.size() - key.find("_", key.find("_", key.find("_") + 1) + 1) - 1)); + final_offset_ns_0 = Result[0][0]; + final_offset_ns_1 = Result[14][0]; + final_offset_ps_negative_0 = Result[0][1]; + final_offset_ps_negative_1 = Result[14][1]; + gotOrphanCount_0 = Result[0][2]; + gotOrphanCount_1 = Result[14][2]; + gotMin_mean_dev_noOrphan_0 = Result[0][3]; + gotMin_mean_dev_noOrphan_1 = Result[14][3]; + increament_times_0 = Result[0][4]; + increament_times_1 = Result[14][4]; + min_mean_dev_0 = Result[0][5]; + min_mean_dev_1 = Result[14][5]; + EventNumberInThisPartFile = Result[0][8]; + + for (int j = 0; j < Result[1].size(); j++) + { + long long BGTdiff = Result[4][j] - Result[10][j] - 325250; + // cout<<"BGTDiff: "<Fill(); + } + outputOffset << runNumber_out << "\t" << subRunNumber_out << "\t" << partFileNumber_out << "\t" << 0 << "\t" << LAPPD_ID_out << "\t" << final_offset_ns_0 << "\t" << final_offset_ns_1 << "\t" << final_offset_ps_negative_0 << "\t" << final_offset_ps_negative_1 << "\t" << gotOrphanCount_0 << "\t" << gotOrphanCount_1 << "\t" << EventNumberInThisPartFile << "\t" << gotMin_mean_dev_noOrphan_0 << "\t" << gotMin_mean_dev_noOrphan_1 << "\t" << increament_times_0 << "\t" << increament_times_1 << "\t" << min_mean_dev_0 << "\t" << min_mean_dev_1 << std::endl; + } + outputOffset.close(); + fOut->cd(); + tOut->Write(); + fOut->Close(); + cout << "Result saved." << endl; +} From c5bcf3218f52cc25275d0872dcdc8052f0ea2c56 Mon Sep 17 00:00:00 2001 From: Yue Date: Sat, 1 Jun 2024 12:54:32 -0500 Subject: [PATCH 033/163] Changes to be committed: modified: UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp modified: configfiles/LoadGeometry/ChannelSPEGains2023.csv --- UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp | 8 ++++---- configfiles/LoadGeometry/ChannelSPEGains2023.csv | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp index 779a106d2..f067f4461 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp @@ -299,10 +299,10 @@ bool LAPPDLoadStore::Execute() bool LAPPDLoadStore::Finalise() { - cout << "Got pps event in total: " << PPSnumber << endl; - cout << "Got error events in total: " << errorEventsNumber << endl; - cout << "Got non empty events in total: " << NonEmptyEvents << endl; - cout << "Got event in total: " << eventNo << endl; + cout << "LAPPDLoadStore: Got pps event in total: " << PPSnumber << endl; + cout << "LAPPDLoadStore: Got error events in total: " << errorEventsNumber << endl; + cout << "LAPPDLoadStore: Got non empty events in total: " << NonEmptyEvents << endl; + cout << "LAPPDLoadStore: Got event in total: " << eventNo << endl; return true; } diff --git a/configfiles/LoadGeometry/ChannelSPEGains2023.csv b/configfiles/LoadGeometry/ChannelSPEGains2023.csv index a54a43f7b..e0dcfa7cf 100644 --- a/configfiles/LoadGeometry/ChannelSPEGains2023.csv +++ b/configfiles/LoadGeometry/ChannelSPEGains2023.csv @@ -79,6 +79,7 @@ 413,0.001499 414,0.001488 415,0.001217 +416,0.0 417,0.001468 418,0.001457 419,0.001248 From 4cfb254d8e847091852a08c9b93633d06abe03b8 Mon Sep 17 00:00:00 2001 From: Yue Date: Wed, 5 Jun 2024 14:32:42 -0500 Subject: [PATCH 034/163] Add more pairing oprion to EBLAPPD, EBMRD, add muni trigger to EBTriggerGrouper Changes to be committed: modified: UserTools/ClusterFinder/ClusterFinder.cpp modified: UserTools/EBLAPPD/EBLAPPD.cpp modified: UserTools/EBMRD/EBMRD.cpp modified: UserTools/EBTriggerGrouper/EBTriggerGrouper.cpp modified: UserTools/EBTriggerGrouper/EBTriggerGrouper.h modified: UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp modified: configfiles/BeamClusterAnalysis/ClusterClassifiersConfig modified: configfiles/BeamClusterAnalysis/ClusterFinderConfig new file: configfiles/BeamClusterAnalysis/ClusterFinderConfig_default modified: configfiles/BeamClusterAnalysis/EventSelectorConfig modified: configfiles/BeamClusterAnalysis/PhaseIITreeMakerConfig modified: configfiles/BeamClusterAnalysis/my_inputs.txt modified: configfiles/EventBuilder/ANNIEEventBuilderConfig modified: configfiles/EventBuilder/LoadRawDataConfig modified: configfiles/EventBuilder/MRDDataDecoderConfig modified: configfiles/EventBuilder/my_files.txt --- UserTools/ClusterFinder/ClusterFinder.cpp | 100 +++++-- UserTools/EBLAPPD/EBLAPPD.cpp | 9 +- UserTools/EBMRD/EBMRD.cpp | 46 ++-- .../EBTriggerGrouper/EBTriggerGrouper.cpp | 28 +- UserTools/EBTriggerGrouper/EBTriggerGrouper.h | 5 + .../TriggerDataDecoder/TriggerDataDecoder.cpp | 20 ++ .../ClusterClassifiersConfig | 2 +- .../BeamClusterAnalysis/ClusterFinderConfig | 4 +- .../ClusterFinderConfig_default | 12 + .../BeamClusterAnalysis/EventSelectorConfig | 2 +- .../PhaseIITreeMakerConfig | 4 +- configfiles/BeamClusterAnalysis/my_inputs.txt | 257 ++++++------------ .../EventBuilder/ANNIEEventBuilderConfig | 2 +- configfiles/EventBuilder/LoadRawDataConfig | 2 +- configfiles/EventBuilder/MRDDataDecoderConfig | 2 +- configfiles/EventBuilder/my_files.txt | 22 +- 16 files changed, 288 insertions(+), 229 deletions(-) create mode 100644 configfiles/BeamClusterAnalysis/ClusterFinderConfig_default diff --git a/UserTools/ClusterFinder/ClusterFinder.cpp b/UserTools/ClusterFinder/ClusterFinder.cpp index f88ca62c6..b3f7748bc 100644 --- a/UserTools/ClusterFinder/ClusterFinder.cpp +++ b/UserTools/ClusterFinder/ClusterFinder.cpp @@ -211,39 +211,84 @@ bool ClusterFinder::Execute(){ std::vector datalike_hits; std::vector datalike_hits_charge; for (MCHit &ahit : ThisPMTHits){ - //std::cout <<"Key: "< 2000.) std::cout <<"Found hit later than 2us! Hit time : "< combine multiple photons if they are within a 10ns range - //hit times can only be recorded with 2ns precision --> possible times are 0ns, 2ns, 4ns, ... - hits_2ns_res.push_back(2*(int(ahit.GetTime())/2.)+(int(ahit.GetTime())%2)); + hits_2ns_res.push_back(ahit.GetTime()); hits_2ns_res_charge.push_back(ahit.GetCharge()); } } //Combine multiple MC hits to one pulse std::sort(hits_2ns_res.begin(),hits_2ns_res.end()); - for (int i_hit=0; i_hit < (int) hits_2ns_res.size(); i_hit++){ - double hit1 = hits_2ns_res.at(i_hit); - if (datalike_hits.size()==0) { - datalike_hits.push_back(hit1); - datalike_hits_charge.push_back(hits_2ns_res_charge.at(i_hit)); - } - else { + std::vector temp_times; + double temp_charges = 0.0; + double mid_time; + if (verbose > 0){ + std::cout << " " << std::endl; + std::cout << hits_2ns_res.size() << " total photon hits(s)" << std::endl; + } + + if (hits_2ns_res.size() > 0){ + for (int i_hit=0; i_hit < (int) hits_2ns_res.size(); i_hit++){ + double hit1 = hits_2ns_res.at(i_hit); + if (temp_times.size()==0) { + temp_times.push_back(hit1); + temp_charges += hits_2ns_res_charge.at(i_hit); + } + + else { bool new_pulse = false; - for (int j_hit=0; j_hit < (int) datalike_hits.size(); j_hit++){ - if (fabs(datalike_hits.at(j_hit)-hit1)<10.) { + if (fabs(temp_times[0]-hit1)<10.) { new_pulse=false; - datalike_hits_charge.at(j_hit)+=hits_2ns_res_charge.at(i_hit); - break; + temp_charges+=hits_2ns_res_charge.at(i_hit); + temp_times.push_back(hit1); } else new_pulse=true; - } + if (new_pulse) { - datalike_hits.push_back(hit1); //Only count as a new pulse if it was 10ns away from every other pulse - datalike_hits_charge.push_back(hits_2ns_res_charge.at(i_hit)); + // following the DigitBuilder tool --> take median photon hit time as the hit time of the "pulse" + if (temp_times.size() % 2 == 0){ + mid_time = (temp_times.at(temp_times.size()/2 - 1) + temp_times.at(temp_times.size()/2))/2; + } else{ + mid_time = temp_times.at(temp_times.size()/2); + } + + datalike_hits.push_back(mid_time); + datalike_hits_charge.push_back(temp_charges); + temp_times.clear(); + temp_charges = 0; + temp_times.push_back(hit1); + temp_charges += hits_2ns_res_charge.at(i_hit); + } } } + if (temp_times.size() % 2 == 0){ + mid_time = (temp_times.at(temp_times.size()/2 - 1) + temp_times.at(temp_times.size()/2))/2; + } else{ + mid_time = temp_times.at(temp_times.size()/2); + } + + datalike_hits.push_back(mid_time); + datalike_hits_charge.push_back(temp_charges); + + if (verbose > 0){ + std::cout << " " << std::endl; + std::cout << datalike_hits.size() << " MC pulse(s) identified from the raw photon hit(s)" << std::endl; + std::cout << "Pulse time(s):" << std::endl; + for (int ih=0; ih < (int) datalike_hits.size(); ih++){ + double junk = datalike_hits.at(ih); + std::cout << junk << " "; + } + std::cout << " " << std::endl; + std::cout << "Pulse charge(s):" << std::endl; + for (int ih=0; ih < (int) datalike_hits_charge.size(); ih++){ + double junk2 = datalike_hits_charge.at(ih); + std::cout << junk2 << " "; + } + std::cout << " " << std::endl; + } + } + for (int i_hit = 0; i_hit < (int) datalike_hits.size(); i_hit++){ //v_hittimes.push_back(ahit.GetTime()); // fill a vector with all hit times (unsorted) v_hittimes.push_back(datalike_hits.at(i_hit)); @@ -295,7 +340,7 @@ bool ClusterFinder::Execute(){ // Now sort the hit time array, fill the highest time in a new array until the old array is empty do { - double max_time = 0; + double max_time = -9999; int i_max_time = 0; for (std::vector::iterator it = v_hittimes.begin(); it != v_hittimes.end(); ++it) { if (*it > max_time) { @@ -321,12 +366,21 @@ bool ClusterFinder::Execute(){ } thiswindow_Nhits = 0; v_mini_hits.clear(); - for (double j_time = *it; j_time < *it + ClusterFindingWindow; j_time+=2){ // loops through times in the window and check if there's a hit at this time + for (double j_time = *it; j_time < *it + ClusterFindingWindow; j_time+=1){ // loops through times in the window and check if there's a hit at this time for(std::vector::iterator it2 = v_hittimes_sorted.begin(); it2 != v_hittimes_sorted.end(); ++it2) { - if (*it2 == j_time) { - thiswindow_Nhits++; - v_mini_hits.push_back(*it2); + if(HitStoreName=="MCHits"){ + if (static_cast(j_time) == static_cast(*it2)) { // accept all hit times (some may be smeared to negative values) + thiswindow_Nhits++; + v_mini_hits.push_back(*it2); + } } + if(HitStoreName=="Hits"){ + if (*it2 > 0 && static_cast(j_time) == static_cast(*it2)) { // reject hit times in the data that are 0 + thiswindow_Nhits++; + v_mini_hits.push_back(*it2); + } + } + } } if (!v_mini_hits.empty()) { diff --git a/UserTools/EBLAPPD/EBLAPPD.cpp b/UserTools/EBLAPPD/EBLAPPD.cpp index bc8147794..a7ee2e6b2 100644 --- a/UserTools/EBLAPPD/EBLAPPD.cpp +++ b/UserTools/EBLAPPD/EBLAPPD.cpp @@ -91,7 +91,7 @@ bool EBLAPPD::Execute() bool CosmicTriggerGroupped = false; m_data->CStore.Get("CosmicTriggerGroupped", CosmicTriggerGroupped); if (CosmicTriggerGroupped) - Matching(44, 46); + Matching(45, 46); else Log("EBLAPPD: CosmicTriggerGroupped is false, no cosmic trigger groupped in the grouper, stop matching", v_message, verbosityEBLAPPD); @@ -101,6 +101,13 @@ bool EBLAPPD::Execute() Matching(31, 46); else Log("EBLAPPD: LEDTriggerGroupped is false, no LED trigger groupped in the grouper, stop matching", v_message, verbosityEBLAPPD); + + bool NuMITriggerGroupped = false; + m_data->CStore.Get("NuMITriggerGroupped", NuMITriggerGroupped); + if (NuMITriggerGroupped) + Matching(42, 46); + else + Log("EBLAPPD: NuMITriggerGroupped is false, no NuMI trigger groupped in the grouper, stop matching", v_message, verbosityEBLAPPD); } } diff --git a/UserTools/EBMRD/EBMRD.cpp b/UserTools/EBMRD/EBMRD.cpp index 9fb27e9f3..373533102 100644 --- a/UserTools/EBMRD/EBMRD.cpp +++ b/UserTools/EBMRD/EBMRD.cpp @@ -49,26 +49,26 @@ bool EBMRD::Execute() { uint64_t MTCtime = p.first; std::vector> WaveMap = p.second; - //if find the MTCtime in the PairedMRDTimeStamps, then skip - if (PairedMRDTimeStamps.size() > 0) + // if find the MTCtime in the PairedMRDTimeStamps, then skip + if (PairedMRDTimeStamps.size() > 0) + { + bool skip = false; + for (std::pair> pair : PairedMRDTimeStamps) { - bool skip = false; - for (std::pair> pair : PairedMRDTimeStamps) + for (uint64_t t : pair.second) { - for (uint64_t t : pair.second) + if (t == MTCtime) { - if (t == MTCtime) - { - skip = true; - break; - } - } - if (skip) + skip = true; break; + } } if (skip) - continue; + break; } + if (skip) + continue; + } if (MRDEventsBuffer.find(MTCtime) == MRDEventsBuffer.end()) { MRDEventsBuffer.emplace(MTCtime, WaveMap); @@ -95,11 +95,21 @@ bool EBMRD::Execute() m_data->CStore.Get("BeamTriggerGroupped", BeamTriggerGroupped); bool CosmicTriggerGroupped = false; m_data->CStore.Get("CosmicTriggerGroupped", CosmicTriggerGroupped); + bool NuMITriggerGroupped = false; + m_data->CStore.Get("NuMITriggerGroupped", NuMITriggerGroupped); + + if (BeamTriggerGroupped) Matching(matchTargetTrigger, 14); - else if (CosmicTriggerGroupped) + if (CosmicTriggerGroupped) + { Matching(36, 36); - else + Matching(45, 46); + } + if(NuMITriggerGroupped) + Matching(42, 46); + + if(!BeamTriggerGroupped && !CosmicTriggerGroupped && !NuMITriggerGroupped) Log("EBMRD: BeamTriggerGroupped and CosmicTriggerGroupped are false, no beam trigger groupped in the grouper, stop matching", v_message, verbosityEBMRD); } } @@ -157,7 +167,7 @@ bool EBMRD::Matching(int targetTrigger, int matchToTrack) Log("EBMRD: Skipping TrackTriggerWord " + std::to_string(TrackTriggerWord), v_debug, verbosityEBMRD); continue; } - if(matchedNumberInTrack.find(TrackTriggerWord) == matchedNumberInTrack.end()) + if (matchedNumberInTrack.find(TrackTriggerWord) == matchedNumberInTrack.end()) matchedNumberInTrack.emplace(TrackTriggerWord, 0); vector> groupedTriggers = pair.second; @@ -185,7 +195,7 @@ bool EBMRD::Matching(int targetTrigger, int matchToTrack) matchedTrigWord = p.second; matchedIndex = p.second; matchedTrack = TrackTriggerWord; - + // if(verbosityEBMRD > 11) cout<<"EBMRD: dt: "< pair : matchedNumberInTrack) { Log("EBMRD: Match finished, matched number in Track " + std::to_string(pair.first) + " is " + std::to_string(pair.second), v_message, verbosityEBMRD); diff --git a/UserTools/EBTriggerGrouper/EBTriggerGrouper.cpp b/UserTools/EBTriggerGrouper/EBTriggerGrouper.cpp index b35dffbe9..755c1cacf 100644 --- a/UserTools/EBTriggerGrouper/EBTriggerGrouper.cpp +++ b/UserTools/EBTriggerGrouper/EBTriggerGrouper.cpp @@ -35,6 +35,8 @@ bool EBTriggerGrouper::Initialise(std::string configfile, DataModel &data) m_variables.Get("groupAmBe", groupAmBe); groupPPS = false; m_variables.Get("groupPPS", groupPPS); + groupNuMI = true; + m_variables.Get("groupNuMI", groupNuMI); BeamTriggerMain = 14; BeamTolerance = 3000000; // use 3 ms here, the spill time difference is 66ms @@ -56,9 +58,9 @@ bool EBTriggerGrouper::Initialise(std::string configfile, DataModel &data) PPSTriggers = {32, 34}; // 32 first, then 34, (~20us in run 4802 data) m_data->CStore.Set("PPSTriggersUsedForGroupping", PPSTriggers); - CosmicTriggerMain = 44; // TODO need to check + CosmicTriggerMain = 45; // TODO need to check m_variables.Get("CosmicTriggerMain", CosmicTriggerMain); - CosmicTolerance = 330000; // 330000ns, TODO + CosmicTolerance = 100; // 330000ns, TODO m_variables.Get("CosmicTolerance", CosmicTolerance); CosmicTriggers = {44, 45, 36, 27, 28, 29, 30, 46}; // TODO: check the trigger words in cosmic run m_data->CStore.Set("CosmicTriggersUsedForGroupping", CosmicTriggers); @@ -70,13 +72,20 @@ bool EBTriggerGrouper::Initialise(std::string configfile, DataModel &data) LEDTriggers = {33, 22, 31, 43, 46}; // in run 4792 [[22, 33], [4160001224, 4160001664]] m_data->CStore.Set("LEDTriggersUsedForGroupping", LEDTriggers); - AmBeTriggerMain = 19; // TODO: need to check + AmBeTriggerMain = 15; // TODO: need to check m_variables.Get("AmBeTriggerMain", AmBeTriggerMain); AmBeTolerance = 5000; // 2336 in Ambe run 4707 m_variables.Get("AmBeTolerance", AmBeTolerance); AmBeTriggers = {11, 12, 15, 19}; // in run 4707 [[19, 12, 15, 11], [21275647928, 21275647936, 21275647952, 21275650264]] m_data->CStore.Set("AmBeTriggersUsedForGroupping", AmBeTriggers); + NuMITriggerMain = 42; + m_variables.Get("NuMITriggerMain", NuMITriggerMain); + NuMITolerance = 100; // 100ns + m_variables.Get("NuMITolerance", NuMITolerance); + NuMITriggers = {42, 46}; // + m_data->CStore.Set("NuMITriggersUsedForGroupping", NuMITriggers); + StoreTotalEntry = 0; maxNumAllowedInBuffer = 10000; @@ -274,6 +283,19 @@ bool EBTriggerGrouper::Execute() m_data->CStore.Set("PPSTriggerGroupped", false); } + if (groupNuMI) + { + Log("EBTG: Grouping NuMI Triggers", v_message, verbosityEBTG); + int groupNum = GroupByTrigWord(NuMITriggerMain, NuMITriggers, NuMITolerance); + int fillNum = FillByTrigWord(NuMITriggerMain, NuMITriggers, NuMITolerance); + Log("EBTG: Found NuMI Trigger group: " + std::to_string(groupNum) + ". Fill additional triggers to group: " + std::to_string(fillNum), v_message, verbosityEBTG); + m_data->CStore.Set("NuMITriggerGroupped", true); + } + else + { + m_data->CStore.Set("NuMITriggerGroupped", false); + } + Log("EBTG: Grouping for different trigger tracks finishes, save to CStore", v_message, verbosityEBTG); m_data->CStore.Set("GroupedTriggersInTotal", GroupedTriggersInTotal); m_data->CStore.Set("RunCodeInTotal", RunCodeInTotal); diff --git a/UserTools/EBTriggerGrouper/EBTriggerGrouper.h b/UserTools/EBTriggerGrouper/EBTriggerGrouper.h index 0146c67fe..b98cba127 100644 --- a/UserTools/EBTriggerGrouper/EBTriggerGrouper.h +++ b/UserTools/EBTriggerGrouper/EBTriggerGrouper.h @@ -90,6 +90,7 @@ class EBTriggerGrouper : public Tool bool groupLED; bool groupAmBe; bool groupPPS; + bool groupNuMI; int BeamTriggerMain; double BeamTolerance; @@ -114,6 +115,10 @@ class EBTriggerGrouper : public Tool int PPSTriggerMain; double PPSTolerance; vector PPSTriggers; + + int NuMITriggerMain; + double NuMITolerance; + vector NuMITriggers; }; #endif diff --git a/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp b/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp index e6a08cf0a..c6391c11c 100644 --- a/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp +++ b/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp @@ -60,6 +60,10 @@ bool TriggerDataDecoder::Initialise(std::string configfile, DataModel &data){ bool TriggerDataDecoder::Execute(){ if (mode == "EventBuilding"){ + +processed_sources.clear(); +processed_ns.clear(); + m_data->CStore.Set("NewCTCDataAvailable",false); bool PauseCTCDecoding = false; m_data->CStore.Get("PauseCTCDecoding",PauseCTCDecoding); @@ -208,6 +212,22 @@ bool TriggerDataDecoder::Finalise(){ StoreC1C2.Set("c2",c2); StoreC1C2.Save(storec1c2.c_str()); }*/ + ofstream trigDebug; + trigDebug.open("TrigDecoderDebug.txt"); + int i = 0; + for (auto it = TimeToTriggerWordMapComplete->begin(); it != TimeToTriggerWordMapComplete->end(); ++it) + { + if (i > 10000) + break; + trigDebug << it->first << " "; + for (auto trig = it->second.begin(); trig != it->second.end(); ++trig) + { + trigDebug << *trig << " "; + } + trigDebug << endl; + i++; + } + trigDebug.close(); return true; } diff --git a/configfiles/BeamClusterAnalysis/ClusterClassifiersConfig b/configfiles/BeamClusterAnalysis/ClusterClassifiersConfig index 199d3866f..752200268 100644 --- a/configfiles/BeamClusterAnalysis/ClusterClassifiersConfig +++ b/configfiles/BeamClusterAnalysis/ClusterClassifiersConfig @@ -1 +1 @@ -verbosity 2 +verbosity 0 diff --git a/configfiles/BeamClusterAnalysis/ClusterFinderConfig b/configfiles/BeamClusterAnalysis/ClusterFinderConfig index 337d7fc2e..c13622045 100644 --- a/configfiles/BeamClusterAnalysis/ClusterFinderConfig +++ b/configfiles/BeamClusterAnalysis/ClusterFinderConfig @@ -3,9 +3,9 @@ verbosity 0 HitStore Hits #Either MCHits or Hits (accessed in ANNIEEvent store) OutputFile BeamRun_ClusterFinder_DefaultOutput #Output root prefix name for the current run -ClusterFindingWindow 100 # in ns, size of the window used to "clusterize" +ClusterFindingWindow 50 # in ns, size of the window used to "clusterize" AcqTimeWindow 70000 # in ns, size of the acquisition window -ClusterIntegrationWindow 100 # in ns, all hits with +/- 1/2 of this window are considered in the cluster +ClusterIntegrationWindow 50 # in ns, all hits with +/- 1/2 of this window are considered in the cluster MinHitsPerCluster 5 # group of hits are considered clusters above this amount of hits end_of_window_time_cut 0.95 # from o to 1, length of the window you want to loop over with respect to acq. window (1 for full window, 0.95 for 95% from the start) Plots2D 0 #Draw 2D charge-vs-time plots? diff --git a/configfiles/BeamClusterAnalysis/ClusterFinderConfig_default b/configfiles/BeamClusterAnalysis/ClusterFinderConfig_default new file mode 100644 index 000000000..337d7fc2e --- /dev/null +++ b/configfiles/BeamClusterAnalysis/ClusterFinderConfig_default @@ -0,0 +1,12 @@ +# ClusterFinder Config File + +verbosity 0 +HitStore Hits #Either MCHits or Hits (accessed in ANNIEEvent store) +OutputFile BeamRun_ClusterFinder_DefaultOutput #Output root prefix name for the current run +ClusterFindingWindow 100 # in ns, size of the window used to "clusterize" +AcqTimeWindow 70000 # in ns, size of the acquisition window +ClusterIntegrationWindow 100 # in ns, all hits with +/- 1/2 of this window are considered in the cluster +MinHitsPerCluster 5 # group of hits are considered clusters above this amount of hits +end_of_window_time_cut 0.95 # from o to 1, length of the window you want to loop over with respect to acq. window (1 for full window, 0.95 for 95% from the start) +Plots2D 0 #Draw 2D charge-vs-time plots? +ChankeyToPMTIDMap ./configfiles/EventDisplay/Data-RecoEvent/Chankey_WCSimID.dat diff --git a/configfiles/BeamClusterAnalysis/EventSelectorConfig b/configfiles/BeamClusterAnalysis/EventSelectorConfig index 73250c81d..a711f08bf 100644 --- a/configfiles/BeamClusterAnalysis/EventSelectorConfig +++ b/configfiles/BeamClusterAnalysis/EventSelectorConfig @@ -19,7 +19,7 @@ RecoFVCut 0 NHitCut 0 NHitmin 4 #Minimum number of hit digits PMTMRDCoincCut 0 -PMTMRDOffset 745 +PMTMRDOffset 755 PromptTrigOnly 0 TriggerWord -1 SaveStatusToStore 1 diff --git a/configfiles/BeamClusterAnalysis/PhaseIITreeMakerConfig b/configfiles/BeamClusterAnalysis/PhaseIITreeMakerConfig index acb3ea7ff..5afabc7ea 100644 --- a/configfiles/BeamClusterAnalysis/PhaseIITreeMakerConfig +++ b/configfiles/BeamClusterAnalysis/PhaseIITreeMakerConfig @@ -1,6 +1,6 @@ verbose 0 -OutputFile BeamRunClusterTest_newEB.root +OutputFile BeamRunTree.root TankClusterProcessing 1 MRDClusterProcessing 1 TriggerProcessing 1 @@ -8,7 +8,7 @@ TankHitInfo_fill 1 MRDHitInfo_fill 1 MRDReco_fill 1 SiPMPulseInfo_fill 0 -fillCleanEventsOnly 0 +fillCleanEventsOnly 1 MCTruth_fill 0 Reco_fill 1 RecoDebug_fill 0 diff --git a/configfiles/BeamClusterAnalysis/my_inputs.txt b/configfiles/BeamClusterAnalysis/my_inputs.txt index e58972378..030e62e88 100644 --- a/configfiles/BeamClusterAnalysis/my_inputs.txt +++ b/configfiles/BeamClusterAnalysis/my_inputs.txt @@ -1,173 +1,84 @@ -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p0 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p1 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p2 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p3 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p4 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p5 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p6 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p7 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p8 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p9 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p10 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p11 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p12 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p13 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p14 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p15 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p16 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p17 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p18 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p19 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p20 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p21 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p22 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p23 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p24 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p25 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p26 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p27 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p28 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p29 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p30 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p31 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p32 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p33 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p34 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p35 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p36 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p37 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p38 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p39 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p40 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p41 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p42 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p43 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p44 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p45 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p46 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p47 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p48 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p49 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p50 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p51 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p52 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p53 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p54 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p55 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p56 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p57 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p58 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p59 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p60 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p61 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p62 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p63 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p64 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p65 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p66 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p67 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p68 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p69 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p70 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p71 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p72 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p73 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p74 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p75 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p76 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p77 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p78 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p79 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p80 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p81 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p82 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p83 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p84 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p85 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p86 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p87 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p88 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p89 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p90 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p91 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p92 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p93 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p94 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p95 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p96 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p97 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p98 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p99 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p100 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p101 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p102 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p103 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p104 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p105 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p106 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p107 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p108 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p109 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p110 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p111 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p112 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p113 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p114 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p115 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p116 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p117 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p118 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p119 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p120 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p121 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p122 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p123 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p124 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p125 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p126 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p127 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p128 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p129 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p130 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p131 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p132 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p133 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p134 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p135 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p136 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p137 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p138 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p139 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p140 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p141 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p142 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p143 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p144 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p145 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p146 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p147 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p148 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p149 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p150 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p151 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p152 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p153 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p154 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p155 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p156 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p157 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p158 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p159 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p160 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p161 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p162 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p163 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p164 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p165 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p166 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p167 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p168 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p169 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p170 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p171 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2573/ProcessedRawData_TankAndMRDAndCTC_R2573S0p172 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p4 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p5 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p6 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p7 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p8 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p9 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p10 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p11 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p12 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p13 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p14 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p15 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p29 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p30 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p31 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p32 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p33 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p34 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p35 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p39 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p40 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p41 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p42 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p43 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p44 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p45 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p74 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p75 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p76 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p77 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p78 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p79 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p80 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p224 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p225 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p226 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p227 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p349 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p350 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p351 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p352 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p353 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p354 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p355 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p369 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p370 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p371 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p372 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p373 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p374 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p375 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p434 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p435 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p436 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p437 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p438 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p439 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p440 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p441 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p442 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p443 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p444 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p445 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p474 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p475 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p476 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p477 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p478 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p479 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p480 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p599 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p600 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p601 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p602 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p603 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p604 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p605 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p624 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p625 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p626 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p627 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p628 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p629 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p630 diff --git a/configfiles/EventBuilder/ANNIEEventBuilderConfig b/configfiles/EventBuilder/ANNIEEventBuilderConfig index 6d59474bf..29a47f79a 100644 --- a/configfiles/EventBuilder/ANNIEEventBuilderConfig +++ b/configfiles/EventBuilder/ANNIEEventBuilderConfig @@ -1,4 +1,4 @@ -verbosity 0 +verbosity 1 BuildType TankAndMRDAndCTC ProcessedFilesBasename ProcessedRawData diff --git a/configfiles/EventBuilder/LoadRawDataConfig b/configfiles/EventBuilder/LoadRawDataConfig index 658744545..3ebf29085 100644 --- a/configfiles/EventBuilder/LoadRawDataConfig +++ b/configfiles/EventBuilder/LoadRawDataConfig @@ -1,4 +1,4 @@ -verbosity 0 +verbosity 1 BuildType TankAndMRDAndCTC #BuildType CTC Mode FileList diff --git a/configfiles/EventBuilder/MRDDataDecoderConfig b/configfiles/EventBuilder/MRDDataDecoderConfig index 4f4260f01..d9937ca9a 100644 --- a/configfiles/EventBuilder/MRDDataDecoderConfig +++ b/configfiles/EventBuilder/MRDDataDecoderConfig @@ -1,2 +1,2 @@ -verbosity 2 +verbosity 0 DaylightSavingsSpring 1 diff --git a/configfiles/EventBuilder/my_files.txt b/configfiles/EventBuilder/my_files.txt index 8c8399ef2..2dce56d16 100644 --- a/configfiles/EventBuilder/my_files.txt +++ b/configfiles/EventBuilder/my_files.txt @@ -1,2 +1,20 @@ -/pnfs/annie/persistent/raw/raw/4314/RAWDataR4314S0p0 -/pnfs/annie/persistent/raw/raw/4314/RAWDataR4314S0p1 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p0 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p1 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p2 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p3 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p4 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p5 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p6 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p7 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p8 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p9 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p10 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p11 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p12 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p13 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p14 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p15 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p16 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p17 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p18 +/pnfs/annie/persistent/raw/raw/4795/RAWDataR4795S0p19 From 7ace76d53dff2c1ab69ff8695a15ddcf34cfe957 Mon Sep 17 00:00:00 2001 From: Yue Date: Wed, 5 Jun 2024 14:34:07 -0500 Subject: [PATCH 035/163] Changes to be committed: modified: UserTools/EventSelector/EventSelector.cpp --- UserTools/EventSelector/EventSelector.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/UserTools/EventSelector/EventSelector.cpp b/UserTools/EventSelector/EventSelector.cpp index 4563381a5..4ef5a779f 100644 --- a/UserTools/EventSelector/EventSelector.cpp +++ b/UserTools/EventSelector/EventSelector.cpp @@ -14,7 +14,7 @@ bool EventSelector::Initialise(std::string configfile, DataModel &data){ fPMTMRDOffset = false; fIsMC = true; - fPMTMRDOffset = 745; + fPMTMRDOffset = 755; fRecoPDG = -1; //Get the tool configuration variables @@ -695,8 +695,15 @@ bool EventSelector::EventSelectionByPMTMRDCoinc() { for (unsigned int i_hit = 0; i_hit < Hits.size(); i_hit++){ time_temp+=Hits.at(i_hit).GetTime(); int tube = Hits.at(i_hit).GetTubeId(); - double charge_pe = Hits.at(i_hit).GetCharge()/ChannelNumToTankPMTSPEChargeMap->at(tube); - charge_temp+=charge_pe; + // check if PMT is present in the map before accessing it + auto it = ChannelNumToTankPMTSPEChargeMap->find(tube); + if (it != ChannelNumToTankPMTSPEChargeMap->end()) { + double charge_pe = Hits.at(i_hit).GetCharge() / it->second; + charge_temp += charge_pe; + } else { + std::cerr << "PMT channel with hit not found in ChannelNumToTankPMTSPEChargeMap. Skipping this hit." << std::endl; + continue; + } } if (Hits.size()>0) time_temp/=Hits.size(); vec_pmtclusters_charge->push_back(charge_temp); From 49c2b2f4d494edc66ac58730c132a9c6904d78ec Mon Sep 17 00:00:00 2001 From: Yue Date: Thu, 6 Jun 2024 10:14:37 -0500 Subject: [PATCH 036/163] add waveform print function to LAPPDPlots add LAPPDProcessedAna tool chain, to use new LAPPD tools to load processed data Changes to be committed: modified: UserTools/LAPPDPlots/LAPPDPlots.cpp modified: UserTools/LAPPDPlots/LAPPDPlots.h modified: configfiles/EventBuilderV2/EBPMTConfig modified: configfiles/EventBuilderV2/EBTriggerGrouperConfig modified: configfiles/EventBuilderV2/list.txt new file: configfiles/LAPPDProcessedAna/ConfigGeo new file: configfiles/LAPPDProcessedAna/ConfigPlot new file: configfiles/LAPPDProcessedAna/ConfigPreProcess new file: configfiles/LAPPDProcessedAna/ConfigStoreReadIn new file: configfiles/LAPPDProcessedAna/Configs new file: configfiles/LAPPDProcessedAna/FindMrdTracksConfig new file: configfiles/LAPPDProcessedAna/LoadANNIEEventConfig new file: configfiles/LAPPDProcessedAna/TimeClusteringConfig new file: configfiles/LAPPDProcessedAna/ToolChainConfig new file: configfiles/LAPPDProcessedAna/ToolsConfig new file: configfiles/LAPPDProcessedAna/list.txt --- UserTools/LAPPDPlots/LAPPDPlots.cpp | 136 ++++++++++++++++++ UserTools/LAPPDPlots/LAPPDPlots.h | 9 ++ configfiles/EventBuilderV2/EBPMTConfig | 2 +- .../EventBuilderV2/EBTriggerGrouperConfig | 4 +- configfiles/EventBuilderV2/list.txt | 8 +- configfiles/LAPPDProcessedAna/ConfigGeo | 11 ++ configfiles/LAPPDProcessedAna/ConfigPlot | 135 +++++++++++++++++ .../LAPPDProcessedAna/ConfigPreProcess | 65 +++++++++ .../LAPPDProcessedAna/ConfigStoreReadIn | 43 ++++++ configfiles/LAPPDProcessedAna/Configs | 68 +++++++++ .../LAPPDProcessedAna/FindMrdTracksConfig | 12 ++ .../LAPPDProcessedAna/LoadANNIEEventConfig | 6 + .../LAPPDProcessedAna/TimeClusteringConfig | 13 ++ configfiles/LAPPDProcessedAna/ToolChainConfig | 24 ++++ configfiles/LAPPDProcessedAna/ToolsConfig | 16 +++ configfiles/LAPPDProcessedAna/list.txt | 1 + 16 files changed, 548 insertions(+), 5 deletions(-) create mode 100644 configfiles/LAPPDProcessedAna/ConfigGeo create mode 100755 configfiles/LAPPDProcessedAna/ConfigPlot create mode 100755 configfiles/LAPPDProcessedAna/ConfigPreProcess create mode 100755 configfiles/LAPPDProcessedAna/ConfigStoreReadIn create mode 100644 configfiles/LAPPDProcessedAna/Configs create mode 100644 configfiles/LAPPDProcessedAna/FindMrdTracksConfig create mode 100644 configfiles/LAPPDProcessedAna/LoadANNIEEventConfig create mode 100644 configfiles/LAPPDProcessedAna/TimeClusteringConfig create mode 100644 configfiles/LAPPDProcessedAna/ToolChainConfig create mode 100644 configfiles/LAPPDProcessedAna/ToolsConfig create mode 100644 configfiles/LAPPDProcessedAna/list.txt diff --git a/UserTools/LAPPDPlots/LAPPDPlots.cpp b/UserTools/LAPPDPlots/LAPPDPlots.cpp index d48882daa..aca3cc758 100644 --- a/UserTools/LAPPDPlots/LAPPDPlots.cpp +++ b/UserTools/LAPPDPlots/LAPPDPlots.cpp @@ -68,6 +68,13 @@ bool LAPPDPlots::Initialise(std::string configfile, DataModel &data) BinHistNumber = 100; m_variables.Get("BinHistNumber", BinHistNumber); + printEventWaveform = 0; + m_variables.Get("printEventWaveform", printEventWaveform); + printLAPPDNumber = 2; + m_variables.Get("printLAPPDNumber", printLAPPDNumber); + printEventNumber = 10; + m_variables.Get("printEventNumber", printEventNumber); + eventNumber = 0; f = new TFile("LAPPDPlots.root", "RECREATE"); @@ -254,6 +261,81 @@ bool LAPPDPlots::Execute() else if (eventNumber < maxDrawEventNumber) c->Print("LAPPDPlots.pdf"); + // if printEventNumber was set to be zero, print all events + if (printEventWaveform && (eventNumber < printEventNumber || printEventNumber == 0)) + { + vector>> LAPPDOnSide0; + vector>> LAPPDOnSide1; + LAPPDOnSide0.resize(printLAPPDNumber); + LAPPDOnSide1.resize(printLAPPDNumber); + + vector savedBoard; + for (int i = 0; i < printLAPPDNumber * 2; i++) + { + savedBoard.push_back(0); + } + + for (int i = 0; i < ReadBoards.size(); i++) + { + // data on board i, in key as channel number + std::map>> boarddata = GetDataForBoard(ReadBoards[i]); + std::map>>::iterator it; + for (it = boarddata.begin(); it != boarddata.end(); it++) + { + unsigned long channelNo = it->first; + Waveform w = it->second[0]; + Channel *ch = _geom->GetChannel(channelNo); + int stripSide = ch->GetStripSide(); + int stripNo = ch->GetStripNum(); + int lappd_id = static_cast((channelNo - 1000) / 60); + if (lappd_id < printLAPPDNumber) + { + vector printW; + + for (int i = 0; i < w.GetSamples()->size(); i++) + { + printW.push_back(-w.GetSamples()->at(i)); + } + if (LAPPDPlotsVerbosity > 0) + cout << "LAPPD ID " << lappd_id << ", strip number " << stripNo << ", waveform size " << printW.size() << endl; + if (stripSide == 0) + LAPPDOnSide0[lappd_id][stripNo] = printW; + else if (stripSide == 1) + LAPPDOnSide1[lappd_id][stripNo] = printW; + if (LAPPDPlotsVerbosity > 0) + cout << "Saved waveform " << endl; + + savedBoard[ReadBoards[i]] = 1; + } + } + } + + // loop savedBoard, if the board was not saved, add empty vector with 256 0 in it. + for (int i = 0; i < savedBoard.size(); i++) + { + if (savedBoard[i] == 0) + { + int id = static_cast(i / 2); + + vector printW; + for (int k = 0; k < 256; k++) + { + printW.push_back(0); + } + if (i % 2 == 0) + LAPPDOnSide0[id][i] = printW; + else + LAPPDOnSide1[id][i] = printW; + } + } + + WaveformToPringSide0.push_back(LAPPDOnSide0); + WaveformToPringSide1.push_back(LAPPDOnSide1); + } + + if (printEventWaveform && printEventNumber != 0 && eventNumber == printEventNumber) + PrintWaveformToTxt(); + eventNumber++; return true; } @@ -269,6 +351,10 @@ bool LAPPDPlots::Finalise() f->cd(); f->Close(); delete f; + + if (printEventWaveform && printEventNumber == 0) + PrintWaveformToTxt(); + return true; } @@ -322,4 +408,54 @@ int LAPPDPlots::CheckInBeamgateWindow() } else return -1; +} + +void LAPPDPlots::PrintWaveformToTxt() +{ + // print all information in WaveformToPringSide0 and WaveformToPringSide1 to two txt files + // print a header of printLAPPDNumber, printEventNumber + ofstream LAPPDPlot_side0_eventWaveform; + LAPPDPlot_side0_eventWaveform.open("LAPPDPlot_side0_eventWaveform.txt"); + LAPPDPlot_side0_eventWaveform << "printLAPPDNumber: " << printLAPPDNumber << " printEventNumber: " << printEventNumber << ", there should be " << printLAPPDNumber << " * " << printEventNumber << " * 256 lines" << endl; + for (int i = 0; i < WaveformToPringSide0.size(); i++) + { + // print i_th event + for (int j = 0; j < WaveformToPringSide0[i].size(); j++) + { + // print j_th LAPPD + // loop the map, in each line, print i, j, key, and all values in vector + for (auto it = WaveformToPringSide0[i][j].begin(); it != WaveformToPringSide0[i][j].end(); it++) + { + LAPPDPlot_side0_eventWaveform << i << " " << j << " " << it->first << " "; + for (int k = 0; k < it->second.size(); k++) + { + LAPPDPlot_side0_eventWaveform << it->second[k] << " "; + } + LAPPDPlot_side0_eventWaveform << endl; + } + } + } + LAPPDPlot_side0_eventWaveform.close(); + + ofstream LAPPDPlot_side1_eventWaveform; + LAPPDPlot_side1_eventWaveform.open("LAPPDPlot_side1_eventWaveform.txt"); + LAPPDPlot_side1_eventWaveform << "printLAPPDNumber: " << printLAPPDNumber << " printEventNumber: " << printEventNumber << ", there should be " << printLAPPDNumber << " * " << printEventNumber << " * 256 lines" << endl; + for (int i = 0; i < WaveformToPringSide1.size(); i++) + { + // print i_th event + for (int j = 0; j < WaveformToPringSide1[i].size(); j++) + { + // print j_th LAPPD + // loop the map, in each line, print i, j, key, and all values in vector + for (auto it = WaveformToPringSide1[i][j].begin(); it != WaveformToPringSide1[i][j].end(); it++) + { + LAPPDPlot_side1_eventWaveform << i << " " << j << " " << it->first << " "; + for (int k = 0; k < it->second.size(); k++) + { + LAPPDPlot_side1_eventWaveform << it->second[k] << " "; + } + LAPPDPlot_side1_eventWaveform << endl; + } + } + } } \ No newline at end of file diff --git a/UserTools/LAPPDPlots/LAPPDPlots.h b/UserTools/LAPPDPlots/LAPPDPlots.h index fe2b0332c..bc31a665e 100644 --- a/UserTools/LAPPDPlots/LAPPDPlots.h +++ b/UserTools/LAPPDPlots/LAPPDPlots.h @@ -41,6 +41,7 @@ class LAPPDPlots : public Tool std::map>> GetDataForBoard(int boardID); int CheckInBeamgateWindow(); void CleanObjects(); + void PrintWaveformToTxt(); private: //**************************** This tool, control variables *************************************************** @@ -100,6 +101,14 @@ class LAPPDPlots : public Tool TCanvas *c; TFile *f; int eventNumber; + + bool printEventWaveform; + int printLAPPDNumber; + int printEventNumber; + + //event number, lappd_id order, map of strip number and waveform + vector>>> WaveformToPringSide0; + vector>>> WaveformToPringSide1; }; #endif diff --git a/configfiles/EventBuilderV2/EBPMTConfig b/configfiles/EventBuilderV2/EBPMTConfig index 06d278434..6899f2395 100644 --- a/configfiles/EventBuilderV2/EBPMTConfig +++ b/configfiles/EventBuilderV2/EBPMTConfig @@ -1,4 +1,4 @@ verbosityEBPMT 3 matchTargetTrigger 5 -matchTolerance_ns 2000 +matchTolerance_ns 200 matchToAllTriggers 1 diff --git a/configfiles/EventBuilderV2/EBTriggerGrouperConfig b/configfiles/EventBuilderV2/EBTriggerGrouperConfig index 02d5ec658..81cb3b2f2 100644 --- a/configfiles/EventBuilderV2/EBTriggerGrouperConfig +++ b/configfiles/EventBuilderV2/EBTriggerGrouperConfig @@ -9,7 +9,7 @@ BeamTolerance 25000000 groupCosmic 1 groupLaser 1 -#LaserTolerance 10000 +LaserTolerance 10000 groupLED 1 #LEDTriggerMain 31 @@ -19,5 +19,7 @@ groupAmBe 0 groupPPS 0 +groupNuMI 1 +maxNumAllowedInBuffer 30000 diff --git a/configfiles/EventBuilderV2/list.txt b/configfiles/EventBuilderV2/list.txt index 178f6b1cb..b7dcf75e3 100644 --- a/configfiles/EventBuilderV2/list.txt +++ b/configfiles/EventBuilderV2/list.txt @@ -1,3 +1,5 @@ -/pnfs/annie/persistent/raw/raw/4877/RAWDataR4877S0p104 -/pnfs/annie/persistent/raw/raw/4877/RAWDataR4877S0p105 -/pnfs/annie/persistent/raw/raw/4877/RAWDataR4877S0p106 +/pnfs/annie/persistent/raw/raw/4890/RAWDataR4890S0p5 +/pnfs/annie/persistent/raw/raw/4890/RAWDataR4890S0p6 +/pnfs/annie/persistent/raw/raw/4890/RAWDataR4890S0p7 +/pnfs/annie/persistent/raw/raw/4890/RAWDataR4890S0p8 +/pnfs/annie/persistent/raw/raw/4890/RAWDataR4890S0p9 diff --git a/configfiles/LAPPDProcessedAna/ConfigGeo b/configfiles/LAPPDProcessedAna/ConfigGeo new file mode 100644 index 000000000..ffe0ca918 --- /dev/null +++ b/configfiles/LAPPDProcessedAna/ConfigGeo @@ -0,0 +1,11 @@ +#LoadGeometry +verbosity 0 +LAPPDChannelCount 60 +FACCMRDGeoFile ./configfiles/LoadGeometry/FullMRDGeometry.csv +DetectorGeoFile ./configfiles/LoadGeometry/DetectorGeometrySpecs.csv +LAPPDGeoFile ./configfiles/LAPPDana/LAPPDGeometry.csv +TankPMTGeoFile ./configfiles/LoadGeometry/FullTankPMTGeometry.csv +TankPMTGainFile ./configfiles/LoadGeometry/ChannelSPEGains_BeamRun20192020.csv +AuxiliaryChannelFile ./configfiles/LoadGeometry/AuxChannels.csv +LAPPDMerging 0 + diff --git a/configfiles/LAPPDProcessedAna/ConfigPlot b/configfiles/LAPPDProcessedAna/ConfigPlot new file mode 100755 index 000000000..a519d3666 --- /dev/null +++ b/configfiles/LAPPDProcessedAna/ConfigPlot @@ -0,0 +1,135 @@ +oldLaser 0 #1 for old data, 0 for new trigger boards + +#LAPPDBaselineSubtract +BLSInputWavLabel AlignedLAPPDData +BaselineSubstractVerbosityLevel 0 +TrigChannel 5 #Specified channel the trigger signal will be on +LAPPDchannelOffset 1000 +LowBLfitrange 25; +HiBLfitrange 60; +TrigLowBLfitrange 30 +TrigHiBLfitrange 100 +BLSOutputWavLabel ABLSLAPPDData +oldLaserTrigAmpRange 40 + +#LAPPDFindPeak +FindPeakVerbosity 0 +FiltPeakInputWavLabel FiltLAPPDData +RawPeakInputWavLabel LAPPDWaveforms +BLSPeakInputWavLabel ABLSLAPPDData +FindPeakOutLabel SimpleRecoLAPPDPulses +TotThreshold 15. +MinimumTot 900. +Deltat 100. + +# General Parameters +Nsamples 256 +SampleSize 100 +NChannels 60 + +#LAPPDPlotWaveForms +requireT0signal 0 +SaveByChannel 1 +#PlotWavLabel RawLAPPDData +#PlotWavLabel LAPPDWaveforms +PlotWavLabel BLsubtractedLAPPDData +#PlotWavLabel AlignedLAPPDData +switchBit 0 + +outfile WaveForms_ablsub.root +NHistos 200 +SaveSingleStrip 0 +SingleStripNo 9 +plotLow -10 +plotHigh 20 + +#LAPPDPlotWaveForms2D +outfile2D RawDataWaveForms_2D.root +plot2DrecoPulseInputLabel thresRecoLAPPDPulses +plot2DrecoHitInputLabel thresRecoLAPPDHits +includeRecoPulses 1 +includeRecoHits 1 +plotAdditionalPart 1 +titleSize 0.04 +canvasMargin 0.15 +canvasTitleOffset 1 +#LAPPDSelectPlot2D +LAPPDSelectPlotWaveform2DLabel LAPPDWaveforms +SelectOutfile2D LAPPDSelectPlot.root +MRDTrackExistSelection 0 +verbosityPlot2D 10 +colorContour 255 +useDefaultPalette 1 +colorPalette 112 + + + +#LAPPDThresReco +LAPPDThresRecoVerbosity 0 +verbosity 0 +printHitsTXT 0 +threshold 10 +minPulseWidth 10 +#thresRecoInputWaveLabel AlignedLAPPDData +ThresRecoInputWaveLabel BLsubtractedLAPPDData +#thresRecoInputWaveLabel LAPPDWaveforms + +ThresRecoOutputPulseLabel LAPPDPulses +ThresRecoOutputHitLabel LAPPDHits +useMaxTime 1 +#signalSpeedOnStrip 0.6667 +signalSpeedOnStrip 0.567 #1.69982/2.99792 +triggerBoardDelay 0 +loadPrintMRDinfo 1 +useRange -1 #set this to 0 for using pulse start time as the saved pulse time, 1 for high, -1 for using peak time +plusClockBit 0 + +savePositionOnStrip 1 + + +#LAPPDStackStrip +verbosityStackStrip 0 +StackOutputFileName stacked.root +#StackInputWaveLabel BLsubtractedLAPPDData +StackInputWaveLabel RawLAPPDData +#StackInputWaveLabel LAPPDWaveforms +StackStripNumber 1 +StackStripSide 0 + +#LAPPDPlotWaveForms +NHistos 200 +SaveByChannel 0 +SaveSingleStrip 0 +SingleStripNo 1 +requireT0signal 0 + + +#LAPPDTreeMaker +treeMakerVerbosity 0 +treeMakerInputPulseLabel LAPPDPulses +treeMakerInputHitLabel LAPPDHits +treeMakerOutputFileName LAPPDTree.root + + + +#LAPPDPlots +LAPPDPlotInputWaveLabel BLsubtractedLAPPDData +LAPPDPlotsVerbosity 0 +CanvasXSubPlotNumber 2 +CanvasYSubPlotNumber 2 +canvasMargin 0.1 +drawHighThreshold 50 +drawLowThreshold -20 + +CanvasWidth 1000 +CanvasHeight 500 + +maxDrawEventNumber 200 + +DrawBinHist 1 +printEventNumber 0 +printLAPPDNumber 1 +printEventWaveform 1 + + + diff --git a/configfiles/LAPPDProcessedAna/ConfigPreProcess b/configfiles/LAPPDProcessedAna/ConfigPreProcess new file mode 100755 index 000000000..ee2a71e11 --- /dev/null +++ b/configfiles/LAPPDProcessedAna/ConfigPreProcess @@ -0,0 +1,65 @@ +# General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +LAPPDchannelOffset 1000 +Folder ../Data/3655/ +#Folder ../Data/2022-06-10/ + +#LAPPDBaselineSubtract +BaselineSubstractVerbosityLevel 0 +TrigChannel1 1005 +TrigChannel2 1035 +#BLSInputWavLabel LAPPDWaveforms #LAPPDWaveforms +BLSInputWavLabel AlignedLAPPDData +#BLSInputWavLabel RawLAPPDData + +LowBLfitrange 0 +HiBLfitrange 60 +TrigLowBLfitrange 110 +TrigHiBLfitrange 160 +BLSOutputWavLabel BLsubtractedLAPPDData +oldLaserTrigAmpRange 40 + +#LAPPDFindT0 +FindT0Verbosity 0 +#FindT0InputWavLabel BLsubtractedLAPPDData +#FindT0InputWavLabel RawLAPPDData +FindT0InputWavLabel LAPPDWaveforms +OneBoardShift 0 +OneBoardShiftValue 16 + + +TrigEarlyCut 20 +TrigLateCut 200 +T0channelNo 1005 +T0channelNo1 1005 +T0channelNo2 1005 +T0signalmax -100. +T0signalthreshold -50. +T0signalmaxOld 50. #Older data uses a positive going signal +T0signalthresholdOld 80. #Older data uses a positive going signal +T0offset 0 +FindT0OutputWavLabel AlignedLAPPDData +GlobalShiftT0 0 +#Added by Marc +Triggerdefault 5 +LAPPDOffset 1000 + +#LAPPDPlotWaveForms +requireT0signal 0 +SaveByChannel 1 +PlotWavLabel BLsubtractedLAPPDData +#PlotWavLabel LAPPDWaveforms +outfile WaveForms_rawblsub.root +NHistos 400 +SaveSingleStrip 0 +SingleStripNo 9 + + + + + + + + diff --git a/configfiles/LAPPDProcessedAna/ConfigStoreReadIn b/configfiles/LAPPDProcessedAna/ConfigStoreReadIn new file mode 100755 index 000000000..d4b3b4e5f --- /dev/null +++ b/configfiles/LAPPDProcessedAna/ConfigStoreReadIn @@ -0,0 +1,43 @@ +# General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +NUM_VECTOR_PPS 16 #Fixed PPS vector size +NUM_VECTOR_DATA 7795 #Fixed DATA vector size +NUM_VECTOR_METADATA 103 #Fixed META vector size +LAPPDchannelOffset 1000 +NChannels 30 +#StoreInputFile /pnfs/annie/persistent/users/redwards/data/filtered_lappd/R3649-R3844/LAPPDEventsBeamgateMRDTrack/FilteredEvents_LAPPDEventsBeamgateMRDTrack_R3649-R3844 + +LAPPDStoreReadInVerbosity 0 + +RawDataInputWavLabel RawWaveform +RawDataOutputWavLabel RawLAPPDData +BoardIndexLabel BoardIndex #Label of the vector of read out boards + +PsecReceiveMode 1 +stopEntries 10000000000 + +DoPedSubtraction 1 +Nboards 6 #Number of pedestal files to be read in +PedinputfileTXT ../Pedestals/swapLAPPD/Pedestal +#PedinputfileTXT ../Pedestals/change/Pedestal + +Pedinputfile1 ../Pedestals/PEDS_ACDC_board0.txt +Pedinputfile2 ../Pedestals/PEDS_ACDC_board1.txt + +#LAPPDReorderData +LAPPDReorderVerbosityLevel 0 +ReorderVerbosityLevel 0 +ReorderInputWavLabel RawLAPPDData +ReorderOutputWavLabel LAPPDWaveforms +DelayOffset 0 +GlobalShift 150 + +ReadStore 0 +NUM_VECTOR_DATA 7795 +NUM_VECTOR_PPS 16 +OutputWavLabel RawLAPPDData +SelectSingleLAPPD false +SelectedLAPPD 0 + diff --git a/configfiles/LAPPDProcessedAna/Configs b/configfiles/LAPPDProcessedAna/Configs new file mode 100644 index 000000000..b26cec99c --- /dev/null +++ b/configfiles/LAPPDProcessedAna/Configs @@ -0,0 +1,68 @@ + General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +NUM_VECTOR_PPS 16 #Fixed PPS vector size +NUM_VECTOR_DATA 7795 #Fixed DATA vector size +NUM_VECTOR_METADATA 103 #Fixed META vector size +LAPPDchannelOffset 1000 +NChannels 30 + +LAPPDStoreReadInVerbosity 0 + +mergingModeReadIn 0 +RawDataInputWavLabel RawWaveform +RawDataOutputWavLabel RawLAPPDData +BoardIndexLabel BoardIndex #Label of the vector of read out boards + +PsecReceiveMode 0 +stopEntries 10000000000 + +DoPedSubtraction 1 +Nboards 6 #Number of pedestal files to be read in +#PedinputfileTXT ../Pedestals/swapLAPPD/Pedestal +PedinputfileTXT ../Pedestals/run3xxx/Pedestal +#PedinputfileTXT ../Pedestals/LAPPD640392/P +PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 + + +Pedinputfile1 ../Pedestals/PEDS_ACDC_board0.txt +Pedinputfile2 ../Pedestals/PEDS_ACDC_board1.txt + +#LAPPDReorderData +ReorderVerbosityLevel 0 +#ReorderInputWavLabel RawLAPPDData +ReorderInputWavLabel AlignedLAPPDData +ReorderOutputWavLabel LAPPDWaveforms +DelayOffset 0 +GlobalShift 180 + +ReadStore 0 +NUM_VECTOR_DATA 7795 +NUM_VECTOR_PPS 16 +OutputWavLabel RawLAPPDData +SelectSingleLAPPD false +SelectedLAPPD 0 +loadPSEC 1 +loadPPS 1 +loadOffsets 0 +num_vector_data 7795 +num_vector_pps 16 + +#LAPPDTreeMaker +LoadPulse 1 +LoadHit 1 +LoadWaveform 1 +LoadLAPPDDataTimeStamp 1 +LoadPPSTimestamp 1 +LoadRunInfoRaw 1 +LoadRunInfoANNIEEvent 0 + +treeMakerVerbosity 0 + +treeMakerInputPulseLabel LAPPDPulses +treeMakerInputHitLabel LAPPDHits +treeMakerOutputFileName LAPPDTree.root +LoadTriggerInfo 0 +LoadGroupOption beam +LoadGroupedTriggerInfo 1 diff --git a/configfiles/LAPPDProcessedAna/FindMrdTracksConfig b/configfiles/LAPPDProcessedAna/FindMrdTracksConfig new file mode 100644 index 000000000..5ba5e8f77 --- /dev/null +++ b/configfiles/LAPPDProcessedAna/FindMrdTracksConfig @@ -0,0 +1,12 @@ +# FindMrdTracks Config File +# all variables retrieved with m_variables.Get() must be defined here! + +verbosity 0 +IsData 1 +OutputDirectory . +OutputFile STEC_MRDTracks_cluster40ns +DrawTruthTracks 0 # whether to add MC Truth track info for drawing in MrdPaddlePlot Tool + ## note you need to run that tool to actually view the tracks! +WriteTracksToFile 0 # should the track information be written to a ROOT-file? +SelectTriggerType 0 #should the loaded data be filtered by trigger type? +TriggerType Beam #options: Cosmic, Beam, No Loopback diff --git a/configfiles/LAPPDProcessedAna/LoadANNIEEventConfig b/configfiles/LAPPDProcessedAna/LoadANNIEEventConfig new file mode 100644 index 000000000..28148f62c --- /dev/null +++ b/configfiles/LAPPDProcessedAna/LoadANNIEEventConfig @@ -0,0 +1,6 @@ +verbose 0 + +FileForListOfInputs configfiles/LAPPDProcessedAna/list.txt + +EventOffset 0 +GlobalEvNr 1 diff --git a/configfiles/LAPPDProcessedAna/TimeClusteringConfig b/configfiles/LAPPDProcessedAna/TimeClusteringConfig new file mode 100644 index 000000000..e778247fc --- /dev/null +++ b/configfiles/LAPPDProcessedAna/TimeClusteringConfig @@ -0,0 +1,13 @@ +#TimeClustering config file + +verbosity 0 +MinDigitsForTrack 3 +MaxMrdSubEventDuration 30 +MinSubeventTimeSep 30 +MakeMrdDigitTimePlot 0 +LaunchTApplication 0 +IsData 1 +#OutputROOTFile TimeClustering_MRDTest28_cluster40ns +OutputROOTFile STEC_TimeClusteringOut +MapChankey_WCSimID ./configfiles/SimpleTankEnergyCalibrator/MRD_Chankey_WCSimID.dat + diff --git a/configfiles/LAPPDProcessedAna/ToolChainConfig b/configfiles/LAPPDProcessedAna/ToolChainConfig new file mode 100644 index 000000000..b94bec1c3 --- /dev/null +++ b/configfiles/LAPPDProcessedAna/ToolChainConfig @@ -0,0 +1,24 @@ + +#ToollChain dynamic setup file + +##### Runtime Paramiters ##### +verbose 1 ## Verbosity level of ToolChain +error_level 0 # 0= do not exit, 1= exit on unhandeled errors only, 2= exit on unhandeled errors and handeled errors +attempt_recover 1 ## 1= will attempt to finalise if an execute fails + +###### Logging ##### +log_mode Interactive # Interactive=cout , Remote= remote logging system "serservice_name Remote_Logging" , Local = local file log; +log_local_path ./log +log_service LogStore + +###### Service discovery ##### Ignore these settings for local analysis +service_publish_sec -1 +service_kick_sec -1 + +##### Tools To Add ##### +Tools_File configfiles/LAPPDProcessedAna/ToolsConfig ## list of tools to run and their config files + +##### Run Type ##### +Inline -1 ## number of Execute steps in program, -1 infinite loop that is ended by user +Interactive 0 ## set to 1 if you want to run the code interactively + diff --git a/configfiles/LAPPDProcessedAna/ToolsConfig b/configfiles/LAPPDProcessedAna/ToolsConfig new file mode 100644 index 000000000..fbf3f106a --- /dev/null +++ b/configfiles/LAPPDProcessedAna/ToolsConfig @@ -0,0 +1,16 @@ +LoadGeometry LoadGeometry configfiles/LAPPDProcessedAna/ConfigGeo +LoadANNIEEvent LoadANNIEEvent configfiles/LAPPDProcessedAna/LoadANNIEEventConfig + +myTimeClustering TimeClustering configfiles/LAPPDProcessedAna/TimeClusteringConfig +myFindMrdTracks FindMrdTracks configfiles/LAPPDProcessedAna/FindMrdTracksConfig + +LAPPDLoadStore LAPPDLoadStore configfiles/LAPPDProcessedAna/Configs +LAPPDStoreReorder LAPPDStoreReorder configfiles/LAPPDProcessedAna/ConfigStoreReadIn + +LAPPDTimeAlignment LAPPDTimeAlignment configfiles/LAPPDProcessedAna/ConfigPreProcess +LAPPDBaseline LAPPDBaseline configfiles/LAPPDProcessedAna/ConfigPreProcess +LAPPDPlots LAPPDPlots configfiles/LAPPDProcessedAna/ConfigPlot + +LAPPDThresReco LAPPDThresReco configfiles/LAPPDProcessedAna/ConfigPlot + +LAPPDTreeMaker LAPPDTreeMaker configfiles/LAPPDProcessedAna/Configs diff --git a/configfiles/LAPPDProcessedAna/list.txt b/configfiles/LAPPDProcessedAna/list.txt new file mode 100644 index 000000000..5c1947483 --- /dev/null +++ b/configfiles/LAPPDProcessedAna/list.txt @@ -0,0 +1 @@ +/pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_50ns_MRDtrack_noVeto_15mV_7strips_3xxx_104 From c8806492749aad87fc55b6b652e08f8767a4c057 Mon Sep 17 00:00:00 2001 From: Yue Date: Wed, 12 Jun 2024 14:49:34 -0500 Subject: [PATCH 037/163] add pot and beam_ok loading to phase II tree maker add beam profile loading to EBSaver Changes to be committed: new file: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp new file: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h new file: UserTools/ANNIEEventTreeMaker/README.md modified: UserTools/EBLoadRaw/EBLoadRaw.cpp modified: UserTools/EBSaver/EBSaver.cpp modified: UserTools/EBSaver/EBSaver.h modified: UserTools/Factory/Factory.cpp modified: UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp modified: UserTools/PhaseIITreeMaker/PhaseIITreeMaker.h modified: UserTools/Unity.h modified: configfiles/EventBuilderV2/EBPMTConfig modified: configfiles/EventBuilderV2/EBSaverConfig modified: configfiles/EventBuilderV2/EBTriggerGrouperConfig modified: configfiles/EventBuilderV2/list.txt --- .../ANNIEEventTreeMaker.cpp | 28 ++ .../ANNIEEventTreeMaker/ANNIEEventTreeMaker.h | 39 +++ UserTools/ANNIEEventTreeMaker/README.md | 20 ++ UserTools/EBLoadRaw/EBLoadRaw.cpp | 5 +- UserTools/EBSaver/EBSaver.cpp | 294 +++++++++++++++--- UserTools/EBSaver/EBSaver.h | 24 ++ UserTools/Factory/Factory.cpp | 1 + .../PhaseIITreeMaker/PhaseIITreeMaker.cpp | 75 ++++- UserTools/PhaseIITreeMaker/PhaseIITreeMaker.h | 8 + UserTools/Unity.h | 1 + configfiles/EventBuilderV2/EBPMTConfig | 2 +- configfiles/EventBuilderV2/EBSaverConfig | 2 +- .../EventBuilderV2/EBTriggerGrouperConfig | 2 +- configfiles/EventBuilderV2/list.txt | 7 +- 14 files changed, 437 insertions(+), 71 deletions(-) create mode 100644 UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp create mode 100644 UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h create mode 100644 UserTools/ANNIEEventTreeMaker/README.md diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp new file mode 100644 index 000000000..6953925f6 --- /dev/null +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -0,0 +1,28 @@ +#include "ANNIEEventTreeMaker.h" + +ANNIEEventTreeMaker::ANNIEEventTreeMaker():Tool(){} + + +bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data){ + + /////////////////// Useful header /////////////////////// + if(configfile!="") m_variables.Initialise(configfile); // loading config file + //m_variables.Print(); + + m_data= &data; //assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + return true; +} + + +bool ANNIEEventTreeMaker::Execute(){ + + return true; +} + + +bool ANNIEEventTreeMaker::Finalise(){ + + return true; +} diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h new file mode 100644 index 000000000..956e11ab2 --- /dev/null +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h @@ -0,0 +1,39 @@ +#ifndef ANNIEEventTreeMaker_H +#define ANNIEEventTreeMaker_H + +#include +#include + +#include "Tool.h" + + +/** + * \class ANNIEEventTreeMaker + * + * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. +* +* $Author: B.Richards $ +* $Date: 2019/05/28 10:44:00 $ +* Contact: b.richards@qmul.ac.uk +*/ +class ANNIEEventTreeMaker: public Tool { + + + public: + + ANNIEEventTreeMaker(); ///< Simple constructor + bool Initialise(std::string configfile,DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + + + private: + + + + + +}; + + +#endif diff --git a/UserTools/ANNIEEventTreeMaker/README.md b/UserTools/ANNIEEventTreeMaker/README.md new file mode 100644 index 000000000..cb2e852ff --- /dev/null +++ b/UserTools/ANNIEEventTreeMaker/README.md @@ -0,0 +1,20 @@ +# ANNIEEventTreeMaker + +ANNIEEventTreeMaker + +## Data + +Describe any data formats ANNIEEventTreeMaker creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for ANNIEEventTreeMaker. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/EBLoadRaw/EBLoadRaw.cpp b/UserTools/EBLoadRaw/EBLoadRaw.cpp index ef04f56c3..abf61c9af 100644 --- a/UserTools/EBLoadRaw/EBLoadRaw.cpp +++ b/UserTools/EBLoadRaw/EBLoadRaw.cpp @@ -150,11 +150,12 @@ bool EBLoadRaw::Execute() } // if more MRD events than VME PMT events, jump to next file + // this is an old option, why? if (MRDTotalEntries > PMTTotalEntries) { - FileCompleted = true; + //FileCompleted = true; Log("EBLoadRaw: Jumping to next file due to MRD entry is more than PMT entry.", v_message, verbosityEBLoadRaw); - return true; + //return true; } if (LoadPMT && PMTEntryNum == PMTTotalEntries) diff --git a/UserTools/EBSaver/EBSaver.cpp b/UserTools/EBSaver/EBSaver.cpp index ad029ef07..f94d3e28a 100644 --- a/UserTools/EBSaver/EBSaver.cpp +++ b/UserTools/EBSaver/EBSaver.cpp @@ -18,6 +18,8 @@ bool EBSaver::Initialise(std::string configfile, DataModel &data) m_variables.Get("savePath", savePath); saveName = "ProcessedData_"; m_variables.Get("saveName", saveName); + beamInfoFileName = "BeamInfo.root"; + m_variables.Get("beamInfoFileName", beamInfoFileName); saveTriggerGroups = true; savePMT = true; @@ -30,6 +32,8 @@ bool EBSaver::Initialise(std::string configfile, DataModel &data) m_variables.Get("saveLAPPD", saveLAPPD); saveOrphan = true; m_variables.Get("saveOrphan", saveOrphan); + saveBeamInfo = true; + m_variables.Get("saveBeamInfo", saveBeamInfo); ANNIEEvent = new BoostStore(false, 2); @@ -62,6 +66,12 @@ bool EBSaver::Initialise(std::string configfile, DataModel &data) InProgressHitsAux = new std::map> *>; FinishedRawAcqSize = new std::map>>; + if (saveBeamInfo) + { + Log("EBSaver: saveBeamInfo is true, loading Beam Info", v_message, verbosityEBSaver); + LoadBeamInfo(); + } + return true; } @@ -125,7 +135,7 @@ bool EBSaver::Execute() // if save Everything, in case there might be some mis aligned events not saved to that processed part file correctly and left in buffer, save them to corresponding part file if (runCode == savingRunCode) { - Log("\033[1;34m ****EBSaver: Saving a new event \033[0m", v_message, verbosityEBSaver); + Log("\033[1;34m ****EBSaver: Saving a new event \033[0m", v_message, verbosityEBSaver); std::string saveFileName = savePath + saveName + "_R" + to_string(runCode / 100000) + "S" + to_string((runCode % 100000) / 10000 - 1) + "p" + to_string(runCode % 10000); Log("EBSaver: Saving to " + saveFileName + " with run code " + std::to_string(runCode) + " at index " + std::to_string(i), v_message, verbosityEBSaver); @@ -421,6 +431,7 @@ bool EBSaver::SaveToANNIEEvent(string saveFileName, int runCode, int triggerTrac bool PMTSaved = false; // incase of multiple 14 found in one group bool MRDSaved = false; bool LAPPDSaved = false; + bool beamInfoSaved = false; std::map GroupedTrigger = GroupedTriggersInTotal[triggerTrack][trackIndex]; // For each element in GroupedTrigger, find is it appear in PairedPMTTriggerTimestamp[triggerTrack], @@ -430,7 +441,14 @@ bool EBSaver::SaveToANNIEEvent(string saveFileName, int runCode, int triggerTrac uint64_t triggerTime = trigger.first; uint32_t triggerType = trigger.second; if (triggerType == 14) + { Log("EBSaver: Found undelayed beam trigger with time " + std::to_string(triggerTime) + " in GroupedTrigger", v_debug, verbosityEBSaver); + if (!beamInfoSaved) + { + SaveBeamInfo(triggerTime); + beamInfoSaved = true; + } + } if (PairedPMTTriggerTimestamp.find(triggerTrack) != PairedPMTTriggerTimestamp.end()) { @@ -453,52 +471,54 @@ bool EBSaver::SaveToANNIEEvent(string saveFileName, int runCode, int triggerTrac } // check if PairedMRDTriggerTimestamp has element with key = triggerTrack - if(!MRDSaved){ - Log("Finding trigger track = " + std::to_string(triggerTrack) + " in PairedMRDTriggerTimestamp", v_debug, verbosityEBSaver); - //print PairedMRDTriggerTimestamp with track number and size - for (auto const &track : PairedMRDTriggerTimestamp) - { - Log("EBSaver: in PairedMRDTriggerTimestamp track " + std::to_string(track.first) + ", left trigger number " + std::to_string(track.second.size()), v_message, verbosityEBSaver); - } - for (auto const &track : PairedMRDTimeStamps) - { - Log("EBSaver: in PairedMRDTimeStamps track " + std::to_string(track.first) + ", left trigger number " + std::to_string(track.second.size()), v_message, verbosityEBSaver); - } - if (PairedMRDTriggerTimestamp.find(triggerTrack) != PairedMRDTriggerTimestamp.end()) + if (!MRDSaved) { - uint64_t minDiff = 100*60*1e9; - Log("Found trigger track = " + std::to_string(triggerTrack) + " in PairedMRDTriggerTimestamp", v_debug, verbosityEBSaver); - //print the size of PairedMRDTriggerTimestamp.at(triggerTrack), print the first and the last timestamp - Log("EBSaver: PairedMRDTriggerTimestamp size " + std::to_string(PairedMRDTriggerTimestamp.at(triggerTrack).size()), v_debug, verbosityEBSaver); - if(PairedMRDTriggerTimestamp.at(triggerTrack).size()>0) - Log("EBSaver: PairedMRDTriggerTimestamp first " + std::to_string(PairedMRDTriggerTimestamp.at(triggerTrack).at(0)) + ", last " + std::to_string(PairedMRDTriggerTimestamp.at(triggerTrack).at(PairedMRDTriggerTimestamp.at(triggerTrack).size()-1)), v_debug, verbosityEBSaver); - - for (int i = 0; i < PairedMRDTriggerTimestamp.at(triggerTrack).size(); i++) + Log("Finding trigger track = " + std::to_string(triggerTrack) + " in PairedMRDTriggerTimestamp", v_debug, verbosityEBSaver); + // print PairedMRDTriggerTimestamp with track number and size + for (auto const &track : PairedMRDTriggerTimestamp) { - uint64_t diff = (PairedMRDTriggerTimestamp.at(triggerTrack).at(i) > triggerTime) ? PairedMRDTriggerTimestamp.at(triggerTrack).at(i) - triggerTime : triggerTime - PairedMRDTriggerTimestamp.at(triggerTrack).at(i); - if(diff < minDiff) - minDiff = diff; - - if (PairedMRDTriggerTimestamp.at(triggerTrack).at(i) == triggerTime || (diff<1e6)) + Log("EBSaver: in PairedMRDTriggerTimestamp track " + std::to_string(track.first) + ", left trigger number " + std::to_string(track.second.size()), v_message, verbosityEBSaver); + } + for (auto const &track : PairedMRDTimeStamps) + { + Log("EBSaver: in PairedMRDTimeStamps track " + std::to_string(track.first) + ", left trigger number " + std::to_string(track.second.size()), v_message, verbosityEBSaver); + } + if (PairedMRDTriggerTimestamp.find(triggerTrack) != PairedMRDTriggerTimestamp.end()) + { + uint64_t minDiff = 100 * 60 * 1e9; + Log("Found trigger track = " + std::to_string(triggerTrack) + " in PairedMRDTriggerTimestamp", v_debug, verbosityEBSaver); + // print the size of PairedMRDTriggerTimestamp.at(triggerTrack), print the first and the last timestamp + Log("EBSaver: PairedMRDTriggerTimestamp size " + std::to_string(PairedMRDTriggerTimestamp.at(triggerTrack).size()), v_debug, verbosityEBSaver); + if (PairedMRDTriggerTimestamp.at(triggerTrack).size() > 0) + Log("EBSaver: PairedMRDTriggerTimestamp first " + std::to_string(PairedMRDTriggerTimestamp.at(triggerTrack).at(0)) + ", last " + std::to_string(PairedMRDTriggerTimestamp.at(triggerTrack).at(PairedMRDTriggerTimestamp.at(triggerTrack).size() - 1)), v_debug, verbosityEBSaver); + + for (int i = 0; i < PairedMRDTriggerTimestamp.at(triggerTrack).size(); i++) { - if(diff<1e6) - {Log("EBSaver: diff<1e6, is " + std::to_string(diff), v_debug, verbosityEBSaver); + uint64_t diff = (PairedMRDTriggerTimestamp.at(triggerTrack).at(i) > triggerTime) ? PairedMRDTriggerTimestamp.at(triggerTrack).at(i) - triggerTime : triggerTime - PairedMRDTriggerTimestamp.at(triggerTrack).at(i); + if (diff < minDiff) + minDiff = diff; + + if (PairedMRDTriggerTimestamp.at(triggerTrack).at(i) == triggerTime || (diff < 1e6)) + { + if (diff < 1e6) + { + Log("EBSaver: diff<1e6, is " + std::to_string(diff), v_debug, verbosityEBSaver); TriggerTimeWithoutMRD.emplace(PairedMRDTriggerTimestamp.at(triggerTrack).at(i), static_cast(diff)); } - uint64_t MRDTime = PairedMRDTimeStamps.at(triggerTrack).at(i); - bool saved = SaveMRDData(MRDTime); - MRDSaved = saved; - DataStreams["MRD"] = 1; - if (MRDSaved) - MRDPairInfoToRemoveTime[triggerTrack].push_back(MRDTime); - Log("EBSaver: Saved " + std::to_string(savedMRDNumber) + " MRD data with MRDTime " + std::to_string(MRDTime), v_debug, verbosityEBSaver); - Log("EBSaver: Found trigger with time " + std::to_string(triggerTime) + " in PairedMRDTriggerTimestamp " + std::to_string(i) + " match with MRDTime " + std::to_string(MRDTime), v_debug, verbosityEBSaver); - // break; + uint64_t MRDTime = PairedMRDTimeStamps.at(triggerTrack).at(i); + bool saved = SaveMRDData(MRDTime); + MRDSaved = saved; + DataStreams["MRD"] = 1; + if (MRDSaved) + MRDPairInfoToRemoveTime[triggerTrack].push_back(MRDTime); + Log("EBSaver: Saved " + std::to_string(savedMRDNumber) + " MRD data with MRDTime " + std::to_string(MRDTime), v_debug, verbosityEBSaver); + Log("EBSaver: Found trigger with time " + std::to_string(triggerTime) + " in PairedMRDTriggerTimestamp " + std::to_string(i) + " match with MRDTime " + std::to_string(MRDTime), v_debug, verbosityEBSaver); + // break; + } } + // Log("EBSaver: MRDData saved", 8, verbosityEBSaver); + Log("EBSaver: While saving MRD data, use trigger time " + std::to_string(triggerTime) + " with minDiff " + std::to_string(minDiff), v_debug, verbosityEBSaver); } - // Log("EBSaver: MRDData saved", 8, verbosityEBSaver); - Log("EBSaver: While saving MRD data, use trigger time " + std::to_string(triggerTime) + " with minDiff " + std::to_string(minDiff), v_debug, verbosityEBSaver); - } } if (PairedLAPPDTriggerTimestamp.find(triggerTrack) != PairedLAPPDTriggerTimestamp.end()) @@ -690,12 +710,13 @@ bool EBSaver::SavePMTData(uint64_t PMTTime) Log("EBSaver: Got PMT data, saving", v_debug, verbosityEBSaver); - //check does the ANNIEEvent already have the key "Hits", if yes, print the size of the vector of each key - //also print the size of the vector of each key in new PMTHits - //Then Merger the two maps + // check does the ANNIEEvent already have the key "Hits", if yes, print the size of the vector of each key + // also print the size of the vector of each key in new PMTHits + // Then Merger the two maps std::map> *OldPMTHits = new std::map>; bool gotHits = ANNIEEvent->Get("Hits", OldPMTHits); - if(gotHits){ + if (gotHits) + { Log("EBSaver: ANNIEEvent already has key Hits, size " + std::to_string(OldPMTHits->size()), v_debug, verbosityEBSaver); for (auto const &time : *OldPMTHits) Log("EBSaver: OldPMTHits old time " + std::to_string(time.first) + " size " + std::to_string(time.second.size()), v_debug, verbosityEBSaver); @@ -718,7 +739,6 @@ bool EBSaver::SavePMTData(uint64_t PMTTime) Log("EBSaver: Merged PMT data, PMTHits size " + std::to_string(PMTHits->size()), v_debug, verbosityEBSaver); } - ANNIEEvent->Set("Hits", PMTHits, true); ANNIEEvent->Set("RecoADCData", PMTRecoADCHits); ANNIEEvent->Set("AuxHits", PMTHitsAux, true); @@ -1147,4 +1167,188 @@ void EBSaver::BuildEmptyLAPPDData() ANNIEEvent->Set("LAPPDTSCorrection", LAPPDTSCorrection); ANNIEEvent->Set("LAPPDBGCorrection", LAPPDBGCorrection); ANNIEEvent->Set("LAPPDOSInMinusPS", LAPPDOSInMinusPS); +} + +void EBSaver::LoadBeamInfo() +{ + TFile *file = new TFile(beamInfoFileName.c_str(), "READ"); + TTree *tree; + file->GetObject("BeamTree", tree); + + if (!tree) + { + cout << "EBSaver: Failed to load beam info from file with name: " << beamInfoFileName << endl; + return; + } + + // copy from IFBeamDBInterfaceV2.cpp + // Here's some documentation for some of the parameters stored in the beam + // database. It's taken from the MicroBooNE operations wiki: + // http://tinyurl.com/z3c4mxs + // + // The status page shows the present reading of beamline instrumentation. All + // of this data is being stored to IF beam Database. The "IF Beam DB + // dashboard":http://dbweb4.fnal.gov:8080/ifbeam/app/BNBDash/index provides + // another view of beam data. Some of it is redundant to the status page, but + // it verifies that the data is being stored in the database. At present the + // page shows following devices: + // * TOR860, TOR875 - two toroids in BNB measuring beam intensity. TOR860 is + // at the beginning of the beamline, and TOR875 is at the end. + // * THCURR - horn current + // * HWTOUT - horn water temperature coming out of the horn. + // * BTJT2 - target temperature + // * HP875, VP875 - beam horizontal and vertical positions at the 875 + // location, about 4.5 m upstream of the target center. + // * HPTG1, VPTG1 - beam horizontal and vertical positions immediately + // (about 2.5 m) upstream of the target center. + // * HPTG2, VPTG2 - beam horizontal and vertical positions more immediately + // (about 1.5 m) upstream of the target center. + // * Because there are no optics between H/VP875 and H/VPTG2, the movements + // on these monitors should scale with the difference in distances. + // * BTJT2 - target air cooling temperature. Four RTD measure the return + // temperature of the cooling air. This is the one closest to the target. + // * BTH2T2 - target air cooling temperature. This is the temperature of the + // air going into the horn. + + // additionally, the unit of E_TOR860 and E_TOR875 is E12 + + uint64_t timestamp; + double E_TOR860, E_TOR875, THCURR, BTJT2, HP875, VP875, HPTG1, VPTG1, HPTG2, VPTG2, BTH2T2; + + tree->SetBranchAddress("Timestamp", ×tamp); + tree->SetBranchAddress("E_TOR860", &E_TOR860); + tree->SetBranchAddress("E_TOR875", &E_TOR875); + tree->SetBranchAddress("E_THCURR", &THCURR); + tree->SetBranchAddress("E_BTJT2", &BTJT2); + tree->SetBranchAddress("E_HP875", &HP875); + tree->SetBranchAddress("E_VP875", &VP875); + tree->SetBranchAddress("E_HPTG1", &HPTG1); + tree->SetBranchAddress("E_VPTG1", &VPTG1); + tree->SetBranchAddress("E_HPTG2", &HPTG2); + tree->SetBranchAddress("E_VPTG2", &VPTG2); + tree->SetBranchAddress("E_BTH2T2", &BTH2T2); + + Long64_t nentries = tree->GetEntries(); + Log("EBSaver: Loading beam infor, total entries in beam info file: " + std::to_string(nentries), v_message, verbosityEBSaver); + for (Long64_t i = 0; i < nentries; ++i) + { + tree->GetEntry(i); + if (i % (static_cast(nentries / 10)) == 0) + Log("EBSaver: Loading beam info, processed " + std::to_string(i) + " entries", v_message, verbosityEBSaver); + BeamInfoTimestamps.push_back(timestamp); + E_TOR860_map.emplace(timestamp, E_TOR860); + E_TOR875_map.emplace(timestamp, E_TOR875); + THCURR_map.emplace(timestamp, THCURR); + BTJT2_map.emplace(timestamp, BTJT2); + HP875_map.emplace(timestamp, HP875); + VP875_map.emplace(timestamp, VP875); + HPTG1_map.emplace(timestamp, HPTG1); + VPTG1_map.emplace(timestamp, VPTG1); + HPTG2_map.emplace(timestamp, HPTG2); + VPTG2_map.emplace(timestamp, VPTG2); + BTH2T2_map.emplace(timestamp, BTH2T2); + } + + Log("EBSaver: Loaded number of E_TOR860 entries: " + std::to_string(E_TOR860_map.size()), v_message, verbosityEBSaver); + + Log("EBSaver: Finished loading beam info from " + beamInfoFileName, v_message, verbosityEBSaver); + + return; +} + +bool EBSaver::SaveBeamInfo(uint64_t TriggerTime) +{ + double E_TOR860, E_TOR875, THCURR, BTJT2, HP875, VP875, HPTG1, VPTG1, HPTG2, VPTG2, BTH2T2; + // find the closest timestamp in vector BeamInfoTimestamps + + uint64_t closestTimestamp = 0; + double minDiff = 5 * 60 * 1e9; // 5 minutes + int minIndex = -1; + + for (int i = 0; i < BeamInfoTimestamps.size(); i++) + { + uint64_t timestamp = BeamInfoTimestamps.at(i) * 1e6; + if(i<2 || i>BeamInfoTimestamps.size()-2) + { + cout<<"BeamInfoTimestamps["<Set("BeamInfoTime", 0); + ANNIEEvent->Set("BeamInfoTimeToTriggerDiff", -9999); + ANNIEEvent->Set("beam_E_TOR860", -9999); + ANNIEEvent->Set("beam_E_TOR875", -9999); + ANNIEEvent->Set("beam_THCURR", -9999); + ANNIEEvent->Set("beam_BTJT2", -9999); + ANNIEEvent->Set("beam_HP875", -9999); + ANNIEEvent->Set("beam_VP875", -9999); + ANNIEEvent->Set("beam_HPTG1", -9999); + ANNIEEvent->Set("beam_VPTG1", -9999); + ANNIEEvent->Set("beam_HPTG2", -9999); + ANNIEEvent->Set("beam_VPTG2", -9999); + ANNIEEvent->Set("beam_BTH2T2", -9999); + ANNIEEvent->Set("beam_good", false); + + Log("EBSaver: Saved beam info with time " + std::to_string(0) + ", pot E_TOR860 = " + std::to_string(-9999) + ", beam_good = " + std::to_string(-9999), v_message, verbosityEBSaver); + } + else + { + Log("Found the closest beam info timestamp to trigger time at index " + std::to_string(minIndex) + " with time " + std::to_string(BeamInfoTimestamps.at(minIndex)), v_message, verbosityEBSaver); + + // get the precise difference + uint64_t beamInfoTime = BeamInfoTimestamps.at(minIndex); + int64_t timeDiff = (beamInfoTime > TriggerTime) ? beamInfoTime - TriggerTime : -static_cast(TriggerTime - beamInfoTime); + + // check if the map has the key + E_TOR860 = E_TOR860_map.at(beamInfoTime); + E_TOR875 = E_TOR875_map.at(beamInfoTime); + THCURR = THCURR_map.at(beamInfoTime); + BTJT2 = BTJT2_map.at(beamInfoTime); + HP875 = HP875_map.at(beamInfoTime); + VP875 = VP875_map.at(beamInfoTime); + HPTG1 = HPTG1_map.at(beamInfoTime); + VPTG1 = VPTG1_map.at(beamInfoTime); + HPTG2 = HPTG2_map.at(beamInfoTime); + VPTG2 = VPTG2_map.at(beamInfoTime); + BTH2T2 = BTH2T2_map.at(beamInfoTime); + + ANNIEEvent->Set("BeamInfoTime", beamInfoTime*1e6); + ANNIEEvent->Set("BeamInfoTimeToTriggerDiff", timeDiff); + + ANNIEEvent->Set("beam_E_TOR860", E_TOR860); + ANNIEEvent->Set("beam_E_TOR875", E_TOR875); + ANNIEEvent->Set("beam_THCURR", THCURR); + ANNIEEvent->Set("beam_BTJT2", BTJT2); + ANNIEEvent->Set("beam_HP875", HP875); + ANNIEEvent->Set("beam_VP875", VP875); + ANNIEEvent->Set("beam_HPTG1", HPTG1); + ANNIEEvent->Set("beam_VPTG1", VPTG1); + ANNIEEvent->Set("beam_HPTG2", HPTG2); + ANNIEEvent->Set("beam_VPTG2", VPTG2); + ANNIEEvent->Set("beam_BTH2T2", BTH2T2); + + int beam_good = 0; + + if (THCURR > 172 && THCURR < 176) + { + if (E_TOR860 > 0.5 && E_TOR860 < 8 && E_TOR875 > 0.5 && E_TOR875 < 8 && (E_TOR875 - E_TOR860) / E_TOR860 < 0.05) + beam_good = 1; + } + + ANNIEEvent->Set("beam_good", beam_good); + + Log("EBSaver: Saved beam info with time " + std::to_string(beamInfoTime) + ", pot E_TOR860 = " + std::to_string(E_TOR860) + ", beam_good = " + std::to_string(beam_good), v_message, verbosityEBSaver); + } + + return true; } \ No newline at end of file diff --git a/UserTools/EBSaver/EBSaver.h b/UserTools/EBSaver/EBSaver.h index 1388b07dd..a9ad3dcee 100644 --- a/UserTools/EBSaver/EBSaver.h +++ b/UserTools/EBSaver/EBSaver.h @@ -14,6 +14,8 @@ #include "ADCPulse.h" #include "CalibratedADCWaveform.h" #include "BeamStatus.h" +#include "TFile.h" +#include "TTree.h" /** * \class EBSaver @@ -45,6 +47,7 @@ class EBSaver : public Tool bool SavePMTData(uint64_t PMTTime); bool SaveMRDData(uint64_t MRDTime); bool SaveLAPPDData(uint64_t LAPPDTime); + bool SaveBeamInfo(uint64_t TriggerTime); bool SaveOrphan(int runCode); bool SaveOrphanPMT(int runCode); @@ -56,6 +59,8 @@ class EBSaver : public Tool void BuildEmptyMRDData(); void BuildEmptyLAPPDData(); + void LoadBeamInfo(); + private: int saveRunNumber; int saveSubrunNumber; @@ -68,10 +73,13 @@ class EBSaver : public Tool bool saveMRD; bool saveLAPPD; bool saveOrphan; + bool saveBeamInfo; string savePath; string saveName; + string beamInfoFileName; + int verbosityEBSaver; int v_message = 1; int v_warning = 2; @@ -162,6 +170,22 @@ class EBSaver : public Tool std::map> PairedLAPPDTriggerTimestamp; std::map> PairedLAPPD_TriggerIndex; std::map> PairedLAPPDTimeStamps; + + + // beam info related objects + vector BeamInfoTimestamps; + std::map E_TOR860_map; + std::map E_TOR875_map; + std::map THCURR_map; + std::map BTJT2_map; + std::map HP875_map; + std::map VP875_map; + std::map HPTG1_map; + std::map VPTG1_map; + std::map HPTG2_map; + std::map VPTG2_map; + std::map BTH2T2_map; + }; #endif diff --git a/UserTools/Factory/Factory.cpp b/UserTools/Factory/Factory.cpp index c062d6343..43dd70ca3 100644 --- a/UserTools/Factory/Factory.cpp +++ b/UserTools/Factory/Factory.cpp @@ -180,5 +180,6 @@ if (tool=="EBLAPPD") ret=new EBLAPPD; if (tool=="EBPMT") ret=new EBPMT; if (tool=="EBMRD") ret=new EBMRD; if (tool=="EBSaver") ret=new EBSaver; +if (tool=="ANNIEEventTreeMaker") ret=new ANNIEEventTreeMaker; return ret; } diff --git a/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp b/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp index f820cb3f7..b0c4d0faf 100644 --- a/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp +++ b/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp @@ -114,8 +114,8 @@ bool PhaseIITreeMaker::Initialise(std::string configfile, DataModel &data){ fPhaseIITankClusterTree->Branch("LAPPD_BGCorrection",&fLAPPD_BGCorrection); fPhaseIITankClusterTree->Branch("LAPPD_OSInMinusPS",&fLAPPD_OSInMinusPS); - fPhaseIITankClusterTree->Branch("fGroupedTriggerTime",&fGroupedTriggerTime); - fPhaseIITankClusterTree->Branch("fGroupedTriggerWord",&fGroupedTriggerWord); + fPhaseIITankClusterTree->Branch("GroupedTriggerTime",&fGroupedTriggerTime); + fPhaseIITankClusterTree->Branch("GroupedTriggerWord",&fGroupedTriggerWord); } } @@ -185,8 +185,8 @@ bool PhaseIITreeMaker::Initialise(std::string configfile, DataModel &data){ fPhaseIIMRDClusterTree->Branch("LAPPD_BGCorrection",&fLAPPD_BGCorrection); fPhaseIIMRDClusterTree->Branch("LAPPD_OSInMinusPS",&fLAPPD_OSInMinusPS); - fPhaseIIMRDClusterTree->Branch("fGroupedTriggerTime",&fGroupedTriggerTime); - fPhaseIIMRDClusterTree->Branch("fGroupedTriggerWord",&fGroupedTriggerWord); + fPhaseIIMRDClusterTree->Branch("GroupedTriggerTime",&fGroupedTriggerTime); + fPhaseIIMRDClusterTree->Branch("GroupedTriggerWord",&fGroupedTriggerWord); } } @@ -437,8 +437,8 @@ bool PhaseIITreeMaker::Initialise(std::string configfile, DataModel &data){ fPhaseIITrigTree->Branch("LAPPD_BGCorrection",&fLAPPD_BGCorrection); fPhaseIITrigTree->Branch("LAPPD_OSInMinusPS",&fLAPPD_OSInMinusPS); - fPhaseIITrigTree->Branch("fGroupedTriggerTime",&fGroupedTriggerTime); - fPhaseIITrigTree->Branch("fGroupedTriggerWord",&fGroupedTriggerWord); + fPhaseIITrigTree->Branch("GroupedTriggerTime",&fGroupedTriggerTime); + fPhaseIITrigTree->Branch("GroupedTriggerWord",&fGroupedTriggerWord); } } return true; @@ -538,11 +538,15 @@ bool PhaseIITreeMaker::Execute(){ fClusterNumber = cluster_num; //Standard run level information - Log("PhaseIITreeMaker Tool: Getting run level information from ANNIEEvent",v_debug,verbosity); + Log("PhaseIITreeMaker Tool: tank cluster, Getting run level information from ANNIEEvent",v_debug,verbosity); + // m_data->Stores.at("ANNIEEvent")->Print(false); + m_data->Stores.at("ANNIEEvent")->Get("RunNumber",fRunNumber); m_data->Stores.at("ANNIEEvent")->Get("SubrunNumber",fSubrunNumber); m_data->Stores.at("ANNIEEvent")->Get("RunType",fRunType); m_data->Stores.at("ANNIEEvent")->Get("RunStartTime",fStartTime); + + fStartTime_Tree = (ULong64_t) fStartTime; // ANNIE Event number @@ -554,10 +558,19 @@ bool PhaseIITreeMaker::Execute(){ fTriggerword = int(trigword_tmp); m_data->Stores["ANNIEEvent"]->Get("TriggerExtended",fExtended); BeamStatus beamstat; - m_data->Stores["ANNIEEvent"]->Get("BeamStatus",beamstat); + bool get_beamstat = m_data->Stores["ANNIEEvent"]->Get("BeamStatus",beamstat); + + if(get_beamstat) + { if (beamstat.ok()) fBeamok = 1; else fBeamok = 0; fPot = beamstat.pot(); + }else{ + bool gotfBeamok = m_data->Stores["ANNIEEvent"]->Get("beam_good",fBeamok); + bool gotpot = m_data->Stores["ANNIEEvent"]->Get("beam_E_TOR875",fPot); + if(!gotfBeamok) fBeamok = 0; + if(!gotpot) fPot = -99999; + } bool pmtmrdcoinc, noveto; m_data->Stores.at("RecoEvent")->Get("PMTMRDCoinc",pmtmrdcoinc); @@ -687,10 +700,19 @@ bool PhaseIITreeMaker::Execute(){ fTriggerword = int(trigword_temp); m_data->Stores["ANNIEEvent"]->Get("TriggerExtended",fExtended); BeamStatus beamstat; - m_data->Stores["ANNIEEvent"]->Get("BeamStatus",beamstat); + bool get_beamstat = m_data->Stores["ANNIEEvent"]->Get("BeamStatus",beamstat); + + if(get_beamstat) + { if (beamstat.ok()) fBeamok = 1; else fBeamok = 0; fPot = beamstat.pot(); + }else{ + m_data->Stores["ANNIEEvent"]->Get("beam_good",fBeamok); + m_data->Stores["ANNIEEvent"]->Get("beam_E_TOR875",fPot); + + } + bool pmtmrdcoinc, noveto; m_data->Stores.at("RecoEvent")->Get("PMTMRDCoinc",pmtmrdcoinc); m_data->Stores.at("RecoEvent")->Get("NoVeto",noveto); @@ -763,7 +785,10 @@ bool PhaseIITreeMaker::Execute(){ //FIXME: calculate fMRDClusterTime //Standard run level information - Log("PhaseIITreeMaker Tool: Getting run level information from ANNIEEvent",v_debug,verbosity); + Log("PhaseIITreeMaker Tool: MRD cluster, Getting run level information from ANNIEEvent",v_debug,verbosity); + + // // m_data->Stores.at("ANNIEEvent")->Print(false); + m_data->Stores.at("ANNIEEvent")->Get("RunNumber",fRunNumber); m_data->Stores.at("ANNIEEvent")->Get("SubrunNumber",fSubrunNumber); m_data->Stores.at("ANNIEEvent")->Get("RunType",fRunType); @@ -792,7 +817,9 @@ bool PhaseIITreeMaker::Execute(){ if(TriggerProcessing) { - Log("PhaseIITreeMaker Tool: Getting run level information from ANNIEEvent",v_debug,verbosity); + Log("PhaseIITreeMaker Tool: trigger, Getting run level information from ANNIEEvent",v_debug,verbosity); + // m_data->Stores.at("ANNIEEvent")->Print(false); + this->ResetVariables(); m_data->Stores.at("ANNIEEvent")->Get("RunNumber",fRunNumber); @@ -812,11 +839,21 @@ bool PhaseIITreeMaker::Execute(){ m_data->Stores.at("ANNIEEvent")->Get("TriggerWord",trigword_temp); fTriggerword = int(trigword_temp); m_data->Stores["ANNIEEvent"]->Get("TriggerExtended",fExtended); - BeamStatus beamstat; - m_data->Stores["ANNIEEvent"]->Get("BeamStatus",beamstat); - if (beamstat.ok()) fBeamok = 1; - else fBeamok = 0; - fPot = beamstat.pot(); + BeamStatus beamstat; + bool get_beamstat = m_data->Stores["ANNIEEvent"]->Get("BeamStatus",beamstat); + + if(get_beamstat) + { + if (beamstat.ok()) fBeamok = 1; + else fBeamok = 0; + fPot = beamstat.pot(); + }else{ + bool gotfBeamok = m_data->Stores["ANNIEEvent"]->Get("beam_good",fBeamok); + bool gotpot = m_data->Stores["ANNIEEvent"]->Get("beam_E_TOR875",fPot); + if(!gotfBeamok) fBeamok = 0; + if(!gotpot) fPot = -99999; + + } m_data->Stores.at("ANNIEEvent")->Get("DataStreams",fDataStreams); m_data->Stores.at("RecoEvent")->Get("PMTMRDCoinc",pmtmrdcoinc); @@ -1928,7 +1965,9 @@ for (std::map::iterator it = LAPPDDataMap.begin(); it != LAP fLAPPD_OSInMinusPS.push_back(LAPPDOSInMinusPS[key]); } + //cout<<"Grouped Trigger Size: "<::iterator it = GroupedTrigger.begin(); it != GroupedTrigger.end(); ++it) { + //cout<<"Grouped Trigger: "<first<<" "<second<first; uint32_t value = it->second; @@ -1949,6 +1988,10 @@ void PhaseIITreeMaker::LoadLAPPDData() m_data->Stores["ANNIEEvent"]->Get("LAPPDTSCorrection", LAPPDTSCorrection); m_data->Stores["ANNIEEvent"]->Get("LAPPDBGCorrection", LAPPDBGCorrection); m_data->Stores["ANNIEEvent"]->Get("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + + + m_data->Stores["ANNIEEvent"]->Get("GroupedTrigger", GroupedTrigger); if(LAPPDDataMap.size() != 0) FillLAPPDData(); + } \ No newline at end of file diff --git a/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.h b/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.h index bffe7e497..c3adca9ad 100644 --- a/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.h +++ b/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.h @@ -387,6 +387,14 @@ class PhaseIITreeMaker: public Tool { vector fGroupedTriggerTime; vector fGroupedTriggerWord; + + uint64_t beamInfoTime; + int64_t timeDiff; + double E_TOR860, E_TOR875, THCURR, BTJT2, HP875, VP875, HPTG1, VPTG1, HPTG2, VPTG2, BTH2T2; + + + + }; diff --git a/UserTools/Unity.h b/UserTools/Unity.h index 574d41e82..92a85c89c 100644 --- a/UserTools/Unity.h +++ b/UserTools/Unity.h @@ -188,3 +188,4 @@ #include "EBPMT.h" #include "EBMRD.h" #include "EBSaver.h" +#include "ANNIEEventTreeMaker.h" diff --git a/configfiles/EventBuilderV2/EBPMTConfig b/configfiles/EventBuilderV2/EBPMTConfig index 6899f2395..f7196af27 100644 --- a/configfiles/EventBuilderV2/EBPMTConfig +++ b/configfiles/EventBuilderV2/EBPMTConfig @@ -1,4 +1,4 @@ verbosityEBPMT 3 matchTargetTrigger 5 -matchTolerance_ns 200 +matchTolerance_ns 100 matchToAllTriggers 1 diff --git a/configfiles/EventBuilderV2/EBSaverConfig b/configfiles/EventBuilderV2/EBSaverConfig index 922c6714c..23005b942 100644 --- a/configfiles/EventBuilderV2/EBSaverConfig +++ b/configfiles/EventBuilderV2/EBSaverConfig @@ -7,4 +7,4 @@ saveLAPPD 1 saveRunInfo 1 saveBeamInfo 1 - +beamInfoFileName BeamInfo.root diff --git a/configfiles/EventBuilderV2/EBTriggerGrouperConfig b/configfiles/EventBuilderV2/EBTriggerGrouperConfig index 81cb3b2f2..bb80aed08 100644 --- a/configfiles/EventBuilderV2/EBTriggerGrouperConfig +++ b/configfiles/EventBuilderV2/EBTriggerGrouperConfig @@ -1,4 +1,4 @@ -verbosityEBTG 5 +verbosityEBTG 3 GroupMode beam GroupTolerance 3000000 GroupTrigWord 14 //undelayed beam diff --git a/configfiles/EventBuilderV2/list.txt b/configfiles/EventBuilderV2/list.txt index b7dcf75e3..cebfc229b 100644 --- a/configfiles/EventBuilderV2/list.txt +++ b/configfiles/EventBuilderV2/list.txt @@ -1,5 +1,2 @@ -/pnfs/annie/persistent/raw/raw/4890/RAWDataR4890S0p5 -/pnfs/annie/persistent/raw/raw/4890/RAWDataR4890S0p6 -/pnfs/annie/persistent/raw/raw/4890/RAWDataR4890S0p7 -/pnfs/annie/persistent/raw/raw/4890/RAWDataR4890S0p8 -/pnfs/annie/persistent/raw/raw/4890/RAWDataR4890S0p9 +/pnfs/annie/persistent/raw/raw/4763/RAWDataR4763S0p6 +/pnfs/annie/persistent/raw/raw/4763/RAWDataR4763S0p7 From 4fb752d0eef280e10a460f88e04d36df4e4eb72a Mon Sep 17 00:00:00 2001 From: Yue Date: Thu, 13 Jun 2024 09:48:55 -0500 Subject: [PATCH 038/163] debug of beam info loading in EBSaver load in PhaseIITriggerTree Changes to be committed: modified: UserTools/EBSaver/EBSaver.cpp modified: UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp --- UserTools/EBSaver/EBSaver.cpp | 32 +++++++++++-------- .../PhaseIITreeMaker/PhaseIITreeMaker.cpp | 8 ++--- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/UserTools/EBSaver/EBSaver.cpp b/UserTools/EBSaver/EBSaver.cpp index f94d3e28a..a64da5d43 100644 --- a/UserTools/EBSaver/EBSaver.cpp +++ b/UserTools/EBSaver/EBSaver.cpp @@ -1284,20 +1284,24 @@ bool EBSaver::SaveBeamInfo(uint64_t TriggerTime) { Log("EBSaver: Failed to find the closest beam info timestamp to trigger time", v_message, verbosityEBSaver); - ANNIEEvent->Set("BeamInfoTime", 0); - ANNIEEvent->Set("BeamInfoTimeToTriggerDiff", -9999); - ANNIEEvent->Set("beam_E_TOR860", -9999); - ANNIEEvent->Set("beam_E_TOR875", -9999); - ANNIEEvent->Set("beam_THCURR", -9999); - ANNIEEvent->Set("beam_BTJT2", -9999); - ANNIEEvent->Set("beam_HP875", -9999); - ANNIEEvent->Set("beam_VP875", -9999); - ANNIEEvent->Set("beam_HPTG1", -9999); - ANNIEEvent->Set("beam_VPTG1", -9999); - ANNIEEvent->Set("beam_HPTG2", -9999); - ANNIEEvent->Set("beam_VPTG2", -9999); - ANNIEEvent->Set("beam_BTH2T2", -9999); - ANNIEEvent->Set("beam_good", false); + uint64_t beamInfoTime = 0; + int64_t timeDiff = -9999; + double defaultVal = -9999.; + int beam_good = 0; + ANNIEEvent->Set("BeamInfoTime", beamInfoTime); + ANNIEEvent->Set("BeamInfoTimeToTriggerDiff", timeDiff); + ANNIEEvent->Set("beam_E_TOR860", defaultVal); + ANNIEEvent->Set("beam_E_TOR875", defaultVal); + ANNIEEvent->Set("beam_THCURR", defaultVal); + ANNIEEvent->Set("beam_BTJT2", defaultVal); + ANNIEEvent->Set("beam_HP875", defaultVal); + ANNIEEvent->Set("beam_VP875", defaultVal); + ANNIEEvent->Set("beam_HPTG1", defaultVal); + ANNIEEvent->Set("beam_VPTG1", defaultVal); + ANNIEEvent->Set("beam_HPTG2", defaultVal); + ANNIEEvent->Set("beam_VPTG2", defaultVal); + ANNIEEvent->Set("beam_BTH2T2", defaultVal); + ANNIEEvent->Set("beam_good", beam_good); Log("EBSaver: Saved beam info with time " + std::to_string(0) + ", pot E_TOR860 = " + std::to_string(-9999) + ", beam_good = " + std::to_string(-9999), v_message, verbosityEBSaver); } diff --git a/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp b/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp index b0c4d0faf..208c766b5 100644 --- a/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp +++ b/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp @@ -708,9 +708,10 @@ bool PhaseIITreeMaker::Execute(){ else fBeamok = 0; fPot = beamstat.pot(); }else{ - m_data->Stores["ANNIEEvent"]->Get("beam_good",fBeamok); - m_data->Stores["ANNIEEvent"]->Get("beam_E_TOR875",fPot); - + bool gotfBeamok = m_data->Stores["ANNIEEvent"]->Get("beam_good",fBeamok); + bool gotpot = m_data->Stores["ANNIEEvent"]->Get("beam_E_TOR875",fPot); + if(!gotfBeamok) fBeamok = 0; + if(!gotpot) fPot = -99999; } bool pmtmrdcoinc, noveto; @@ -852,7 +853,6 @@ bool PhaseIITreeMaker::Execute(){ bool gotpot = m_data->Stores["ANNIEEvent"]->Get("beam_E_TOR875",fPot); if(!gotfBeamok) fBeamok = 0; if(!gotpot) fPot = -99999; - } m_data->Stores.at("ANNIEEvent")->Get("DataStreams",fDataStreams); From e9c41a5195fa7611ac83bc87ead9735060662d4e Mon Sep 17 00:00:00 2001 From: Yue Date: Thu, 13 Jun 2024 17:07:37 -0500 Subject: [PATCH 039/163] update LAPPDLoadStore for loading from multiple lappds map update LAPPDProcessedAna tool chain for processing built mutiple LAPPD data update the lappd offset fit script for empty PPS problem fix bug in EBSaver Changes to be committed: modified: UserTools/EBSaver/EBSaver.cpp modified: UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp modified: UserTools/LAPPDLoadStore/LAPPDLoadStore.h modified: UserTools/LoadANNIEEvent/LoadANNIEEvent.cpp modified: configfiles/LAPPDProcessedAna/Configs modified: configfiles/LAPPDProcessedAna/LoadANNIEEventConfig modified: configfiles/LAPPDProcessedAna/list.txt modified: offsetFit_MultipleLAPPD.cpp --- UserTools/EBSaver/EBSaver.cpp | 22 +-- UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp | 130 +++++++++++++----- UserTools/LAPPDLoadStore/LAPPDLoadStore.h | 24 +++- UserTools/LoadANNIEEvent/LoadANNIEEvent.cpp | 3 +- configfiles/LAPPDProcessedAna/Configs | 7 +- .../LAPPDProcessedAna/LoadANNIEEventConfig | 2 +- configfiles/LAPPDProcessedAna/list.txt | 31 ++++- offsetFit_MultipleLAPPD.cpp | 8 ++ 8 files changed, 177 insertions(+), 50 deletions(-) diff --git a/UserTools/EBSaver/EBSaver.cpp b/UserTools/EBSaver/EBSaver.cpp index a64da5d43..806a58ee9 100644 --- a/UserTools/EBSaver/EBSaver.cpp +++ b/UserTools/EBSaver/EBSaver.cpp @@ -615,7 +615,12 @@ bool EBSaver::SaveGroupedTriggers(int triggerTrack, int groupIndex) ANNIEEvent->Set("GroupedTrigger", GroupedTrigger); int matchTriggerType = triggerTrack; ANNIEEvent->Set("PrimaryTriggerWord", matchTriggerType); - ANNIEEvent->Set("TriggerWord", matchTriggerType); + if(matchTriggerType!=14){ + ANNIEEvent->Set("TriggerWord", matchTriggerType); + } + else{ + ANNIEEvent->Set("TriggerWord", 5); + } // find the triggertrack trigger time in GroupedTrigger uint64_t primaryTrigTime = 0; @@ -1262,17 +1267,18 @@ bool EBSaver::SaveBeamInfo(uint64_t TriggerTime) // find the closest timestamp in vector BeamInfoTimestamps uint64_t closestTimestamp = 0; - double minDiff = 5 * 60 * 1e9; // 5 minutes + double minDiff = 60 * 60 * 1e9; // 60 minutes int minIndex = -1; for (int i = 0; i < BeamInfoTimestamps.size(); i++) { uint64_t timestamp = BeamInfoTimestamps.at(i) * 1e6; - if(i<2 || i>BeamInfoTimestamps.size()-2) - { - cout<<"BeamInfoTimestamps["<Set("BeamInfoTime", beamInfoTime * 1e6); ANNIEEvent->Set("BeamInfoTimeToTriggerDiff", timeDiff); ANNIEEvent->Set("beam_E_TOR860", E_TOR860); diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp index f067f4461..20371452a 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp @@ -43,6 +43,7 @@ bool LAPPDLoadStore::Initialise(std::string configfile, DataModel &data) m_variables.Get("loadOffsets", loadOffsets); // Control variables in this tool, initialized in this tool NonEmptyEvents = 0; + NonEmptyDataEvents = 0; PPSnumber = 0; isFiltered = false; isBLsub = false; @@ -133,7 +134,8 @@ bool LAPPDLoadStore::Initialise(std::string configfile, DataModel &data) if (loadOffsets) LoadOffsetsAndCorrections(); - if(LAPPDStoreReadInVerbosity>11) debugStoreReadIn.open("debugStoreReadIn.txt"); + if (LAPPDStoreReadInVerbosity > 11) + debugStoreReadIn.open("debugStoreReadIn.txt"); return true; } @@ -171,7 +173,8 @@ bool LAPPDLoadStore::Execute() // decide loading data or not, set to LAPPDana for later tools LAPPDana = LoadData(); m_data->CStore.Set("LAPPDana", LAPPDana); - if(LAPPDStoreReadInVerbosity>0) cout<<"LAPPDana for loading was set to "< 0) + cout << "LAPPDana for loading was set to " << LAPPDana << endl; if (!LAPPDana) { // not loading data, return @@ -225,6 +228,7 @@ bool LAPPDLoadStore::Execute() return true; } + NonEmptyDataEvents += 1; } // parsing finished, do pedestal subtraction @@ -243,8 +247,9 @@ bool LAPPDLoadStore::Execute() m_data->Stores["ANNIEEvent"]->Set("SortedBoards", ParaBoards); m_data->Stores["ANNIEEvent"]->Set("TriggerChannelBase", TrigChannel); - m_data->CStore.Set("NewLAPPDDataAvailable",true); - if(LAPPDStoreReadInVerbosity>11) debugStoreReadIn<< " Set NewLAPPDDataAvailable to true"<CStore.Set("NewLAPPDDataAvailable", true); + if (LAPPDStoreReadInVerbosity > 11) + debugStoreReadIn << " Set NewLAPPDDataAvailable to true" << endl; NonEmptyEvents += 1; eventNo++; @@ -260,15 +265,30 @@ bool LAPPDLoadStore::Execute() // assume we only have PSEC data in ANNIEEvent, no PPS event. // loop the map, for each PSEC data, do the same loading and parsing. // load the waveform by using LAPPD_ID * board_number * channel_number as the key + + /* + the format saved in the processed data file of ANNIEEvent is: + std::map LAPPDDataMap; + std::map LAPPDBeamgate_ns; + std::map LAPPDTimeStamps_ns; // data and key are the same + std::map LAPPDTimeStampsRaw; + std::map LAPPDBeamgatesRaw; + std::map LAPPDOffsets; + std::map LAPPDTSCorrection; + std::map LAPPDBGCorrection; + std::map LAPPDOSInMinusPS; + */ + + // data was already loaded in the LoadData() + if (LAPPDStoreReadInVerbosity > 0) cout << "LAPPDStoreReadIn: LAPPDDataMap has " << LAPPDDataMap.size() << " LAPPD PSEC data " << endl; bool ValidDataLoaded = false; std::map::iterator it; for (it = LAPPDDataMap.begin(); it != LAPPDDataMap.end(); it++) { - unsigned long time = it->first; + uint64_t time = it->first; PsecData dat = it->second; - ReadBoards = dat.BoardIndex; Raw_buffer = dat.RawWaveform; LAPPD_ID = dat.LAPPD_ID; @@ -284,14 +304,34 @@ bool LAPPDLoadStore::Execute() m_data->CStore.Set("LAPPDanaData", true); bool parsData = ParsePSECData(); // TODO: now assuming all boards just has 30 channels. Need to be changed for gen 2 if (parsData) + { ValidDataLoaded = true; + LAPPDLoadedTimeStamps.push_back(time); + LAPPD_IDs.push_back(LAPPD_ID); + LAPPDLoadedTimeStampsRaw.push_back(LAPPDTimeStampsRaw.at(time)); + LAPPDLoadedBeamgatesRaw.push_back(LAPPDBeamgatesRaw.at(time)); + LAPPDLoadedOffsets.push_back(LAPPDOffsets.at(time)); + LAPPDLoadedTSCorrections.push_back(LAPPDTSCorrection.at(time)); + LAPPDLoadedBGCorrections.push_back(LAPPDBGCorrection.at(time)); + LAPPDLoadedOSInMinusPS.push_back(LAPPDOSInMinusPS.at(time)); + } + NonEmptyEvents += 1; + NonEmptyDataEvents += 1; } + eventNo++; LAPPDana = ValidDataLoaded; m_data->CStore.Set("LAPPDana", LAPPDana); DoPedestalSubtract(); m_data->Stores["ANNIEEvent"]->Set("RawLAPPDData", LAPPDWaveforms); // leave this only for the merger tool + m_data->Stores["ANNIEEvent"]->Set("LAPPD_IDs", LAPPD_IDs); + m_data->Stores["ANNIEEvent"]->Set("LAPPDLoadedTimeStamps", LAPPDLoadedTimeStamps); // TODO: save other timestamps, variables and metadata for later use + + if (eventNo % 500 == 0) + { + cout << "LAPPDLoadStore: Loaded " << eventNo << " events, " << NonEmptyDataEvents << " non empty LAPPD PSEC data loaded from all LAPPDs" << endl; + } } return true; @@ -299,10 +339,12 @@ bool LAPPDLoadStore::Execute() bool LAPPDLoadStore::Finalise() { + cout << "\033[1;34mLAPPDLoadStore: Finalising\033[0m" << endl; cout << "LAPPDLoadStore: Got pps event in total: " << PPSnumber << endl; - cout << "LAPPDLoadStore: Got error events in total: " << errorEventsNumber << endl; - cout << "LAPPDLoadStore: Got non empty events in total: " << NonEmptyEvents << endl; - cout << "LAPPDLoadStore: Got event in total: " << eventNo << endl; + cout << "LAPPDLoadStore: Got error data or PPS events in total: " << errorEventsNumber << endl; + cout << "LAPPDLoadStore: Got non empty data and PPS events in total: " << NonEmptyEvents << endl; + cout << "LAPPDLoadStore: Got non empty data events in total: " << NonEmptyDataEvents << endl; + cout << "LAPPDLoadStore: End at event number: " << eventNo << endl; return true; } @@ -462,6 +504,7 @@ int LAPPDLoadStore::getParsedMeta(std::vector buffer, int BoardI if (PsecInfo[CHIP].size() < 13) { NonEmptyEvents = NonEmptyEvents - 1; + NonEmptyDataEvents = NonEmptyDataEvents - 1; cout << "meta data parsing wrong! PsecInfo[CHIP].size() < 13" << endl; m_data->CStore.Set("LAPPDana", false); return 1; @@ -474,6 +517,7 @@ int LAPPDLoadStore::getParsedMeta(std::vector buffer, int BoardI catch (...) { NonEmptyEvents = NonEmptyEvents - 1; + NonEmptyDataEvents = NonEmptyDataEvents - 1; cout << "meta data parsing wrong! meta.push_back(PsecInfo[CHIP][INFOWORD]);" << endl; m_data->CStore.Set("LAPPDana", false); return 1; @@ -487,6 +531,7 @@ int LAPPDLoadStore::getParsedMeta(std::vector buffer, int BoardI if (PsecTriggerInfo[CHIP].size() < 6) { NonEmptyEvents = NonEmptyEvents - 1; + NonEmptyDataEvents = NonEmptyDataEvents - 1; cout << "meta data parsing wrong! PsecTriggerInfo[CHIP].size() < 6" << endl; m_data->CStore.Set("LAPPDana", false); return 1; @@ -499,6 +544,7 @@ int LAPPDLoadStore::getParsedMeta(std::vector buffer, int BoardI catch (...) { NonEmptyEvents = NonEmptyEvents - 1; + NonEmptyDataEvents = NonEmptyDataEvents - 1; cout << "meta data parsing wrong! meta.push_back(PsecTriggerInfo[CHIP][TRIGGERWORD]);" << endl; m_data->CStore.Set("LAPPDana", false); return 1; @@ -570,10 +616,11 @@ bool LAPPDLoadStore::LoadData() cout << "Got eventNo " << eventNo << endl; // if loaded enough events, stop the loop and return false - if (NonEmptyEvents == stopEntries) + if (NonEmptyEvents == stopEntries || NonEmptyEvents > stopEntries || NonEmptyDataEvents == stopEntries || NonEmptyDataEvents > stopEntries) + { if (LAPPDStoreReadInVerbosity > 0) - cout << "LAPPDStoreReadIn: NonEmptyEvents is " << NonEmptyEvents << ", stopEntries is " << stopEntries << ", stop the loop" << endl; + cout << "LAPPDStoreReadIn: NonEmptyEvents is " << NonEmptyEvents << ", NonEmptyDataEvents is " << NonEmptyDataEvents << ", stopEntries is " << stopEntries << ", stop the loop" << endl; m_data->vars.Set("StopLoop", 1); return false; } @@ -586,25 +633,26 @@ bool LAPPDLoadStore::LoadData() if (loadPSEC || loadPPS) { // if load any kind of data // if there is no LAPPD data in event store, and not getting data from CStore, return false, don't load - if (!DataStreams["LAPPD"] && PsecReceiveMode == 0) + if (!DataStreams["LAPPD"] && PsecReceiveMode == 0 && !MultiLAPPDMap) // if doesn't have datastream, not reveive data from raw data store (PsecReceiveMode), not loading multiple LAPPD map from processed data { return false; } - else if (PsecReceiveMode == 1) // no LAPPD data in event store, but load from CStore (for merging LAPPD to ANNIEEvent) - { // only get PSEC data from CStore, no PPS + else if (PsecReceiveMode == 1 && !MultiLAPPDMap) // no LAPPD data in event store, but load from CStore (for merging LAPPD to ANNIEEvent) + { // only get PSEC object from CStore // if loading from raw data, and the loading was set to pause, return false bool LAPPDRawLoadingPaused = false; m_data->CStore.Get("PauseLAPPDDecoding", LAPPDRawLoadingPaused); - if (LAPPDRawLoadingPaused){ - m_data->CStore.Set("NewLAPPDDataAvailable",false); + if (LAPPDRawLoadingPaused) + { + m_data->CStore.Set("NewLAPPDDataAvailable", false); return false; } - PsecData dat; bool getData = m_data->CStore.Get("LAPPDData", dat); - if(getData){ - m_data->CStore.Set("StoreLoadedLAPPDData",dat); + if (getData) + { + m_data->CStore.Set("StoreLoadedLAPPDData", dat); } if (LAPPDStoreReadInVerbosity > 0) cout << "LAPPDStoreReadIn: getting LAPPDData from CStore" << endl; @@ -672,7 +720,7 @@ bool LAPPDLoadStore::LoadData() return false; } } - else if (DataStreams["LAPPD"] && PsecReceiveMode == 0) + else if (DataStreams["LAPPD"] && PsecReceiveMode == 0 && !MultiLAPPDMap) // if load single lappd data at ID 0, require Datastream, not receive from cstore, not in multiLAPPDMap mode { PsecData dat; m_data->Stores["ANNIEEvent"]->Get("LAPPDData", dat); @@ -700,13 +748,23 @@ bool LAPPDLoadStore::LoadData() } return true; } - else if (DataStreams["LAPPD"] && MultiLAPPDMap) + else if (DataStreams["LAPPD"] && PsecReceiveMode == 0 && MultiLAPPDMap) // if not receive from cstore, and load multi lappd map { bool getMap = m_data->Stores["ANNIEEvent"]->Get("LAPPDDataMap", LAPPDDataMap); if (LAPPDStoreReadInVerbosity > 0) cout << "LAPPDStoreReadIn: getting LAPPDDataMap from ANNIEEvent" << endl; if (getMap) + { + bool gotBeamgates_ns = m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + bool gotTimeStamps_ns = m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); + bool gotTimeStampsRaw = m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStampsRaw", LAPPDTimeStampsRaw); + bool gotBeamgatesRaw = m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgatesRaw", LAPPDBeamgatesRaw); + bool gotOffsets = m_data->Stores["ANNIEEvent"]->Get("LAPPDOffsets", LAPPDOffsets); + bool gotTSCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDTSCorrection", LAPPDTSCorrection); + bool gotDBGCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDBGCorrection", LAPPDBGCorrection); + bool gotOSInMinusPS = m_data->Stores["ANNIEEvent"]->Get("LAPPDOSInMinusPS", LAPPDOSInMinusPS); return true; + } } } return false; // if not any of the above, return false @@ -981,11 +1039,13 @@ void LAPPDLoadStore::SaveTimeStamps() m_data->Stores["ANNIEEvent"]->Set("LAPPDBeamgate_Raw", beamgate_63_0); m_data->Stores["ANNIEEvent"]->Set("LAPPDTimestamp_Raw", timestamp_63_0); - if(LAPPDStoreReadInVerbosity>11) debugStoreReadIn< 11) + debugStoreReadIn << eventNo << " LAPPDStoreReadIn, Saving timestamps, beamgate_timestamp: " << beamgate_63_0 << ", lappd_timestamp: " << timestamp_63_0 << endl; if (loadOffsets && runInfoLoaded) { // run number + sub run number + partfile number + LAPPD_ID to make a string key + // TODO: need to add a reset number here after got everything work // search it in the maps, then load SaveOffsets(); } @@ -1074,10 +1134,11 @@ void LAPPDLoadStore::SaveOffsets() m_data->CStore.Set("LAPPDOffset", LAPPDOffset); m_data->CStore.Set("LAPPDOffset_minus_ps", LAPPDOffset_minus_ps); - cout<<"LAPPDStoreReadIn, Saving offsets and corrections, key: "<11) debugStoreReadIn< 11) + debugStoreReadIn << eventNo << "+LAPPDStoreReadIn, Saving offsets and corrections, key: " << key << ", LAPPDOffset: " << LAPPDOffset << ", LAPPDOffset_minus_ps: " << LAPPDOffset_minus_ps << ", LAPPDBGCorrection: " << LAPPDBGCorrection << ", LAPPDTSCorrection: " << LAPPDTSCorrection << endl; +} void LAPPDLoadStore::LoadOffsetsAndCorrections() { @@ -1113,7 +1174,7 @@ void LAPPDLoadStore::LoadOffsetsAndCorrections() tree->SetBranchAddress("TSCorrection_tick", &TSCorrection_tick); Long64_t nentries = tree->GetEntries(); - cout<<"LAPPDStoreReadIn Loading offsets and corrections, total entries: "<GetEntry(i); @@ -1135,10 +1196,11 @@ void LAPPDLoadStore::LoadOffsetsAndCorrections() BGCorrections[key][EventIndex] = static_cast(BGCorrection_tick) - 1000; TSCorrections[key][EventIndex] = static_cast(TSCorrection_tick) - 1000; - if(i%(static_cast(nentries/10))==0) - {cout<<"LAPPDStoreReadIn Loading offsets and corrections, "<(nentries / 10)) == 0) + { + cout << "LAPPDStoreReadIn Loading offsets and corrections, " << i << " entries loaded" << endl; + cout << "Printing key: " << key << ", EventIndex: " << EventIndex << ", final_offset_ns_0: " << final_offset_ns_0 << ", final_offset_ps_negative_0: " << final_offset_ps_negative_0 << ", BGCorrection_tick: " << BGCorrection_tick << ", TSCorrection_tick: " << TSCorrection_tick << endl; + } } file->Close(); @@ -1149,8 +1211,8 @@ void LAPPDLoadStore::LoadOffsetsAndCorrections() void LAPPDLoadStore::LoadRunInfo() { - if(LAPPDStoreReadInVerbosity>0) - cout<<"LAPPDStoreReadIn, Loading run info"< 0) + cout << "LAPPDStoreReadIn, Loading run info" << endl; int PFNumberBeforeGet = partFileNumber; m_data->CStore.Get("rawFileNumber", partFileNumber); m_data->CStore.Get("runNumber", runNumber); @@ -1164,6 +1226,6 @@ void LAPPDLoadStore::LoadRunInfo() { eventNumberInPF++; } - if(LAPPDStoreReadInVerbosity>0) - cout<<"LAPPDStoreReadIn, Loaded run info, runNumber: "< 0) + cout << "LAPPDStoreReadIn, Loaded run info, runNumber: " << runNumber << ", subRunNumber: " << subRunNumber << ", partFileNumber: " << partFileNumber << ", eventNumberInPF: " << eventNumberInPF << endl; } \ No newline at end of file diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.h b/UserTools/LAPPDLoadStore/LAPPDLoadStore.h index 0256b1aa0..1679bae12 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.h +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.h @@ -75,6 +75,7 @@ class LAPPDLoadStore : public Tool // Variables that you get from the config file int stopEntries; // stop tool chain after loading this number of PSEC data events int NonEmptyEvents; // count how many non empty data events were loaded + int NonEmptyDataEvents; // count how many non empty data events were loaded bool PsecReceiveMode; // Get PSEC data from CStore or Stores["ANNIEEvent"]. 1: CStore, 0: Stores["ANNIEEvent"] string OutputWavLabel; string InputWavLabel; @@ -96,6 +97,15 @@ class LAPPDLoadStore : public Tool // LAPPD tool chain, data variables. (Will be used in multiple LAPPD tools) // everything you get or set to Store, which means it may be used in other tools or it's from other tools int LAPPD_ID; + vector LAPPD_IDs; + vector LAPPDLoadedTimeStamps; + vector LAPPDLoadedTimeStampsRaw; + vector LAPPDLoadedBeamgatesRaw; + vector LAPPDLoadedOffsets; + vector LAPPDLoadedTSCorrections; + vector LAPPDLoadedBGCorrections; + vector LAPPDLoadedOSInMinusPS; + vector ParaBoards; // save the board index for this PsecData std::map>> LAPPDWaveforms; @@ -111,9 +121,18 @@ class LAPPDLoadStore : public Tool vector pps; vector LAPPD_ID_Channel; // for each LAPPD, how many channels on it's each board vector LAPPD_ID_BoardNumber; // for each LAPPD, how many boards with it - std::map LAPPDDataMap; + std::map LAPPDDataMap; + std::map LAPPDBeamgate_ns; + std::map LAPPDTimeStamps_ns; // data and key are the same + std::map LAPPDTimeStampsRaw; + std::map LAPPDBeamgatesRaw; + std::map LAPPDOffsets; + std::map LAPPDTSCorrection; + std::map LAPPDBGCorrection; + std::map LAPPDOSInMinusPS; // data variables don't need to be cleared in each loop + // these are loaded offset for event building std::map> Offsets; // Loaded offset, use string = run number + sub run number + partfile number as key. std::map> Offsets_minus_ps; // offset in ps, use offset - this/1e3 as the real offset std::map> BGCorrections; // Loaded BGcorrections, same key as Offsets, but offset saved on event by event basis in that part file, in unit of ticks @@ -123,6 +142,9 @@ class LAPPDLoadStore : public Tool int partFileNumber; int eventNumberInPF; std::ofstream debugStoreReadIn; + + + }; #endif diff --git a/UserTools/LoadANNIEEvent/LoadANNIEEvent.cpp b/UserTools/LoadANNIEEvent/LoadANNIEEvent.cpp index eca215941..686a69f86 100644 --- a/UserTools/LoadANNIEEvent/LoadANNIEEvent.cpp +++ b/UserTools/LoadANNIEEvent/LoadANNIEEvent.cpp @@ -246,6 +246,7 @@ bool LoadANNIEEvent::Execute() { std::string input_filename = input_filenames_.at(current_file_); std::cout <<"Reading in current file "<Stores["ANNIEEvent"]->Initialise(input_filename); + Log("LoadANNIEEvent: Loading new file "+input_filename, 1, verbosity_); m_data->Stores["ANNIEEvent"]->Header->Get("TotalEntries", total_entries_in_file_); global_events.push_back(global_events.at(current_file_-1)+total_entries_in_file_); @@ -278,7 +279,7 @@ bool LoadANNIEEvent::Execute() { Log("ANNIEEvent store has "+std::to_string(total_entries_in_file_)+" entries",v_debug,verbosity_); Log("Loading entry " + std::to_string(current_entry_) + " from the" " ANNIEEvent input file \"" + input_filenames_.at(current_file_) - + '\"', 1, verbosity_); + + '\"', 2, verbosity_); if ((int)current_entry_ != offset_evnum) m_data->Stores["ANNIEEvent"]->Delete(); //ensures that we can access pointers without problems diff --git a/configfiles/LAPPDProcessedAna/Configs b/configfiles/LAPPDProcessedAna/Configs index b26cec99c..d83f26fa3 100644 --- a/configfiles/LAPPDProcessedAna/Configs +++ b/configfiles/LAPPDProcessedAna/Configs @@ -16,13 +16,12 @@ RawDataOutputWavLabel RawLAPPDData BoardIndexLabel BoardIndex #Label of the vector of read out boards PsecReceiveMode 0 +MultiLAPPDMap 1 stopEntries 10000000000 DoPedSubtraction 1 Nboards 6 #Number of pedestal files to be read in -#PedinputfileTXT ../Pedestals/swapLAPPD/Pedestal -PedinputfileTXT ../Pedestals/run3xxx/Pedestal -#PedinputfileTXT ../Pedestals/LAPPD640392/P +PedinputfileTXT ../Pedestals/LAPPD645839//P PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 @@ -62,7 +61,7 @@ treeMakerVerbosity 0 treeMakerInputPulseLabel LAPPDPulses treeMakerInputHitLabel LAPPDHits -treeMakerOutputFileName LAPPDTree.root +treeMakerOutputFileName LAPPDTree_processedAna.root LoadTriggerInfo 0 LoadGroupOption beam LoadGroupedTriggerInfo 1 diff --git a/configfiles/LAPPDProcessedAna/LoadANNIEEventConfig b/configfiles/LAPPDProcessedAna/LoadANNIEEventConfig index 28148f62c..b7330eecc 100644 --- a/configfiles/LAPPDProcessedAna/LoadANNIEEventConfig +++ b/configfiles/LAPPDProcessedAna/LoadANNIEEventConfig @@ -1,4 +1,4 @@ -verbose 0 +verbose 1 FileForListOfInputs configfiles/LAPPDProcessedAna/list.txt diff --git a/configfiles/LAPPDProcessedAna/list.txt b/configfiles/LAPPDProcessedAna/list.txt index 5c1947483..91e4e2432 100644 --- a/configfiles/LAPPDProcessedAna/list.txt +++ b/configfiles/LAPPDProcessedAna/list.txt @@ -1 +1,30 @@ -/pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_50ns_MRDtrack_noVeto_15mV_7strips_3xxx_104 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p1 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p2 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p3 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p4 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p5 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p6 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p7 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p8 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p9 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p10 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p14 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p15 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p16 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p17 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p18 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p19 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p20 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p21 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p22 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p23 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p24 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p25 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p26 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p27 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p28 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p29 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p30 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p31 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p32 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p33 diff --git a/offsetFit_MultipleLAPPD.cpp b/offsetFit_MultipleLAPPD.cpp index 72ff663ed..abeca9673 100644 --- a/offsetFit_MultipleLAPPD.cpp +++ b/offsetFit_MultipleLAPPD.cpp @@ -796,6 +796,11 @@ vector> fitInPartFile(TTree *lappdTree, TTree *triggerTree, in vector> ResultTotal; if (LAPPDDataTimeStampUL.size() == LAPPDDataBeamgateUL.size()) { + if(LAPPD_PPS0.size() == 0 || LAPPD_PPS1.size() == 0 ) + { + cout<<"Error: PPS0 or PPS1 is empty, return empty result."<> ResultACDC0 = fitInThisReset(LAPPDDataTimeStampUL, LAPPDDataBeamgateUL, LAPPD_PPS0, fitTargetTriggerWord, CTCTargetTimeStamp, CTCPPSTimeStamp, intervalInSecond * 1E9 * 1000); vector> ResultACDC1 = fitInThisReset(LAPPDDataTimeStampUL, LAPPDDataBeamgateUL, LAPPD_PPS1, fitTargetTriggerWord, CTCTargetTimeStamp, CTCPPSTimeStamp, intervalInSecond * 1E9 * 1000); @@ -1025,6 +1030,9 @@ void offsetFit_MultipleLAPPD(string fileName, int fitTargetTriggerWord, bool tri string key = it->first; vector> Result = it->second; + if(Result.size()==0) + continue; + runNumber_out = std::stoi(key.substr(0, key.find("_"))); subRunNumber_out = std::stoi(key.substr(key.find("_") + 1, key.find("_", key.find("_") + 1) - key.find("_") - 1)); partFileNumber_out = std::stoi(key.substr(key.find("_", key.find("_") + 1) + 1, key.find("_", key.find("_", key.find("_") + 1) + 1) - key.find("_", key.find("_") + 1) - 1)); From 9d2aba35aa24e5f1a921be27d3163107e5ed4cd7 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Fri, 14 Jun 2024 14:34:38 -0500 Subject: [PATCH 040/163] Update BeamFetcherV2.cpp 1. Clear beamdatamap after writing to root file. This increases the speed of the toolchain by ~2x 2. Change trigword from 5 to 14. This doesn't have a huge effect but Yue's new event building toolchain constructs events with 14 as the "base" to pair timestamps as its the beam trigger from the BNB --- UserTools/BeamFetcherV2/BeamFetcherV2.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/UserTools/BeamFetcherV2/BeamFetcherV2.cpp b/UserTools/BeamFetcherV2/BeamFetcherV2.cpp index 2d7cba2d9..b8eca2221 100644 --- a/UserTools/BeamFetcherV2/BeamFetcherV2.cpp +++ b/UserTools/BeamFetcherV2/BeamFetcherV2.cpp @@ -172,7 +172,7 @@ bool BeamFetcherV2::FetchFromTrigger() iterator != TimeToTriggerWordMap->end(); ++iterator) { // We only care about beam triggers here - if (std::find(iterator->second.begin(), iterator->second.end(), 5) == iterator->second.end()) { + if (std::find(iterator->second.begin(), iterator->second.end(), 14) == iterator->second.end()) { continue; } // bool hasBeamTrig = false; @@ -324,7 +324,8 @@ void BeamFetcherV2::WriteTrees() fOutTree->Fill(); }// end loop over timestamps - +// clear BeamDataMap after filling Tree +BeamDataMap->clear(); } From d50b9fcf142cada82db3b21f59cd49377308a522 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Fri, 14 Jun 2024 14:35:53 -0500 Subject: [PATCH 041/163] Update TriggerDataDecoderConfig Adding a trigger mask for this toolchain --- configfiles/BeamFetcherV2/TriggerDataDecoderConfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configfiles/BeamFetcherV2/TriggerDataDecoderConfig b/configfiles/BeamFetcherV2/TriggerDataDecoderConfig index 0b193d920..843bb5357 100644 --- a/configfiles/BeamFetcherV2/TriggerDataDecoderConfig +++ b/configfiles/BeamFetcherV2/TriggerDataDecoderConfig @@ -1,4 +1,4 @@ verbosity 0 -TriggerMaskFile ./configfiles/DataDecoder/DefaultTriggerMask.txt +TriggerMaskFile ./configfiles/BeamFetcherV2/DefaultTriggerMask.txt StoreTrigOverlap 0 ReadTrigOverlap 0 From 75be5fd99f9e7e0c1018da0b211bfe8897d1500e Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Fri, 14 Jun 2024 14:37:00 -0500 Subject: [PATCH 042/163] Create DefaultTriggerMask.txt TriggerDataDecoder will only load trigword 14 from the RawData (undelayed beam trigger) --- configfiles/BeamFetcherV2/DefaultTriggerMask.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 configfiles/BeamFetcherV2/DefaultTriggerMask.txt diff --git a/configfiles/BeamFetcherV2/DefaultTriggerMask.txt b/configfiles/BeamFetcherV2/DefaultTriggerMask.txt new file mode 100644 index 000000000..05f190104 --- /dev/null +++ b/configfiles/BeamFetcherV2/DefaultTriggerMask.txt @@ -0,0 +1,3 @@ +#Triggers are given by Jonathan; place one number per line. Values are index + 1 +#4+1: Delayed beam. 32+1: LED trigger. 34+1: AmBe and Cosmic trigger. 35+1: MRD_CR_Trigger. 30+1: LED_Start. 45+1, 46+1: Laser. 14+1: AmBe external trigger +14 From 3995a15bce1bfde0d271c0bd8032706ba0f31ce2 Mon Sep 17 00:00:00 2001 From: Yue Date: Sat, 15 Jun 2024 16:10:48 -0500 Subject: [PATCH 043/163] add LAPPDProcessedFilter tool chain for event building V2 output modify verbosity of EventBuilderV2 tool chain, reduce the size of output and debug log add and modify LAPPDProcessedAna tool chain for multiple LAPPD loading, some time the LAPPD ID is not exactly followed by the LAPPD board ID. For example, ususaly LAPPD ID = 2 means the it's board ID has 4 and 5, but this is not true. The LAPPDLoadStore was changed to load LAPPD data based on it's ID to channel, rather than using board ID. other LAPPD tools are also changed. Changes to be committed: modified: UserTools/EBSaver/EBSaver.cpp modified: UserTools/Factory/Factory.cpp modified: UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp modified: UserTools/LAPPDLoadStore/LAPPDLoadStore.h modified: UserTools/LAPPDPlots/LAPPDPlots.cpp modified: UserTools/LAPPDPlots/LAPPDPlots.h modified: UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp modified: UserTools/LAPPDStoreReorder/LAPPDStoreReorder.h modified: UserTools/LAPPDThresReco/LAPPDThresReco.cpp modified: UserTools/LAPPDThresReco/LAPPDThresReco.h modified: UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.cpp modified: UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.h modified: UserTools/LAPPDTreeMaker/LAPPDTreeMaker.cpp modified: UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h modified: UserTools/LoadANNIEEvent/LoadANNIEEvent.cpp modified: UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp modified: UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp new file: UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp new file: UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.h new file: UserTools/ProcessedLAPPDFilter/README.md modified: UserTools/Unity.h modified: configfiles/EventBuilderV2/EBLAPPDConfig modified: configfiles/EventBuilderV2/EBLoadRawConfig modified: configfiles/EventBuilderV2/EBMRDConfig modified: configfiles/EventBuilderV2/EBPMTConfig modified: configfiles/EventBuilderV2/EBSaverConfig modified: configfiles/EventBuilderV2/EBTriggerGrouperConfig modified: configfiles/EventBuilderV2/list.txt modified: configfiles/LAPPDProcessedAna/ConfigPlot modified: configfiles/LAPPDProcessedAna/ConfigPreProcess modified: configfiles/LAPPDProcessedAna/ConfigStoreReadIn modified: configfiles/LAPPDProcessedAna/Configs modified: configfiles/LAPPDProcessedAna/LoadANNIEEventConfig new file: configfiles/LAPPDProcessedAna/ProcessedLAPPDFilterConfig modified: configfiles/LAPPDProcessedAna/ToolChainConfig modified: configfiles/LAPPDProcessedAna/ToolsConfig new file: configfiles/LAPPDProcessedAna/knownlist modified: configfiles/LAPPDProcessedAna/list.txt new file: configfiles/LAPPDProcessedFilter/ClusterClassifiersConfig new file: configfiles/LAPPDProcessedFilter/ClusterFinderConfig new file: configfiles/LAPPDProcessedFilter/ConfigGeo new file: configfiles/LAPPDProcessedFilter/EventSelectorConfig new file: configfiles/LAPPDProcessedFilter/FindMrdTracksConfig new file: configfiles/LAPPDProcessedFilter/LoadANNIEEventConfig new file: configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig new file: configfiles/LAPPDProcessedFilter/TimeClusteringConfig new file: configfiles/LAPPDProcessedFilter/ToolChainConfig new file: configfiles/LAPPDProcessedFilter/ToolsConfig new file: configfiles/LAPPDProcessedFilter/list.txt --- UserTools/EBSaver/EBSaver.cpp | 73 +-- UserTools/Factory/Factory.cpp | 1 + UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp | 206 +++++++-- UserTools/LAPPDLoadStore/LAPPDLoadStore.h | 1 + UserTools/LAPPDPlots/LAPPDPlots.cpp | 58 ++- UserTools/LAPPDPlots/LAPPDPlots.h | 3 + .../LAPPDStoreReorder/LAPPDStoreReorder.cpp | 18 +- .../LAPPDStoreReorder/LAPPDStoreReorder.h | 2 + UserTools/LAPPDThresReco/LAPPDThresReco.cpp | 166 ++++--- UserTools/LAPPDThresReco/LAPPDThresReco.h | 2 + .../LAPPDTimeAlignment/LAPPDTimeAlignment.cpp | 14 +- .../LAPPDTimeAlignment/LAPPDTimeAlignment.h | 2 + UserTools/LAPPDTreeMaker/LAPPDTreeMaker.cpp | 275 +++++++++++- UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h | 21 + UserTools/LoadANNIEEvent/LoadANNIEEvent.cpp | 4 +- .../PhaseIIADCHitFinder.cpp | 4 + .../PhaseIITreeMaker/PhaseIITreeMaker.cpp | 7 +- .../ProcessedLAPPDFilter.cpp | 422 ++++++++++++++++++ .../ProcessedLAPPDFilter.h | 77 ++++ UserTools/ProcessedLAPPDFilter/README.md | 20 + UserTools/Unity.h | 1 + configfiles/EventBuilderV2/EBLAPPDConfig | 2 +- configfiles/EventBuilderV2/EBLoadRawConfig | 2 +- configfiles/EventBuilderV2/EBMRDConfig | 2 +- configfiles/EventBuilderV2/EBPMTConfig | 2 +- configfiles/EventBuilderV2/EBSaverConfig | 2 +- .../EventBuilderV2/EBTriggerGrouperConfig | 2 +- configfiles/EventBuilderV2/list.txt | 4 +- configfiles/LAPPDProcessedAna/ConfigPlot | 4 +- .../LAPPDProcessedAna/ConfigPreProcess | 4 +- .../LAPPDProcessedAna/ConfigStoreReadIn | 4 +- configfiles/LAPPDProcessedAna/Configs | 10 +- .../LAPPDProcessedAna/LoadANNIEEventConfig | 2 +- .../ProcessedLAPPDFilterConfig | 1 + configfiles/LAPPDProcessedAna/ToolChainConfig | 2 +- configfiles/LAPPDProcessedAna/ToolsConfig | 2 +- configfiles/LAPPDProcessedAna/knownlist | 1 + configfiles/LAPPDProcessedAna/list.txt | 31 +- .../ClusterClassifiersConfig | 1 + .../LAPPDProcessedFilter/ClusterFinderConfig | 12 + configfiles/LAPPDProcessedFilter/ConfigGeo | 11 + .../LAPPDProcessedFilter/EventSelectorConfig | 29 ++ .../LAPPDProcessedFilter/FindMrdTracksConfig | 12 + .../LAPPDProcessedFilter/LoadANNIEEventConfig | 6 + .../ProcessedLAPPDFilterConfig | 6 + .../LAPPDProcessedFilter/TimeClusteringConfig | 13 + .../LAPPDProcessedFilter/ToolChainConfig | 24 + configfiles/LAPPDProcessedFilter/ToolsConfig | 13 + configfiles/LAPPDProcessedFilter/list.txt | 2 + 49 files changed, 1370 insertions(+), 213 deletions(-) create mode 100644 UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp create mode 100644 UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.h create mode 100644 UserTools/ProcessedLAPPDFilter/README.md create mode 100644 configfiles/LAPPDProcessedAna/ProcessedLAPPDFilterConfig create mode 100644 configfiles/LAPPDProcessedAna/knownlist create mode 100644 configfiles/LAPPDProcessedFilter/ClusterClassifiersConfig create mode 100644 configfiles/LAPPDProcessedFilter/ClusterFinderConfig create mode 100644 configfiles/LAPPDProcessedFilter/ConfigGeo create mode 100644 configfiles/LAPPDProcessedFilter/EventSelectorConfig create mode 100644 configfiles/LAPPDProcessedFilter/FindMrdTracksConfig create mode 100644 configfiles/LAPPDProcessedFilter/LoadANNIEEventConfig create mode 100644 configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig create mode 100644 configfiles/LAPPDProcessedFilter/TimeClusteringConfig create mode 100644 configfiles/LAPPDProcessedFilter/ToolChainConfig create mode 100644 configfiles/LAPPDProcessedFilter/ToolsConfig create mode 100644 configfiles/LAPPDProcessedFilter/list.txt diff --git a/UserTools/EBSaver/EBSaver.cpp b/UserTools/EBSaver/EBSaver.cpp index 806a58ee9..705570555 100644 --- a/UserTools/EBSaver/EBSaver.cpp +++ b/UserTools/EBSaver/EBSaver.cpp @@ -109,10 +109,7 @@ bool EBSaver::Execute() m_data->CStore.Get("GroupedTriggersInTotal", GroupedTriggersInTotal); m_data->CStore.Get("RunCodeInTotal", RunCodeInTotal); - // get the pmt data, runcode buffer, and match information - - // get the pmt buffer, save the data, and remove the saved data from data buffer - + int savedEventNumber = 0; // loop each track in the RunCodeInTotal; for (auto const &track : RunCodeInTotal) { @@ -135,13 +132,14 @@ bool EBSaver::Execute() // if save Everything, in case there might be some mis aligned events not saved to that processed part file correctly and left in buffer, save them to corresponding part file if (runCode == savingRunCode) { - Log("\033[1;34m ****EBSaver: Saving a new event \033[0m", v_message, verbosityEBSaver); + Log("\033[1;34m ****EBSaver: Saving a new event with savedEventNumber = " + std::to_string(savedEventNumber) + " ****\033[0m", v_message, verbosityEBSaver); std::string saveFileName = savePath + saveName + "_R" + to_string(runCode / 100000) + "S" + to_string((runCode % 100000) / 10000 - 1) + "p" + to_string(runCode % 10000); Log("EBSaver: Saving to " + saveFileName + " with run code " + std::to_string(runCode) + " at index " + std::to_string(i), v_message, verbosityEBSaver); // if in last exe, the runcode for that group of trigger equals to the saving RunCode, save to ANNIEEvent Processed File SaveToANNIEEvent(saveFileName, runCode, triggerTrack, i); + savedEventNumber++; } } } @@ -477,47 +475,50 @@ bool EBSaver::SaveToANNIEEvent(string saveFileName, int runCode, int triggerTrac // print PairedMRDTriggerTimestamp with track number and size for (auto const &track : PairedMRDTriggerTimestamp) { - Log("EBSaver: in PairedMRDTriggerTimestamp track " + std::to_string(track.first) + ", left trigger number " + std::to_string(track.second.size()), v_message, verbosityEBSaver); + Log("EBSaver: in PairedMRDTriggerTimestamp track " + std::to_string(track.first) + ", left trigger number " + std::to_string(track.second.size()), v_debug, verbosityEBSaver); } for (auto const &track : PairedMRDTimeStamps) { - Log("EBSaver: in PairedMRDTimeStamps track " + std::to_string(track.first) + ", left trigger number " + std::to_string(track.second.size()), v_message, verbosityEBSaver); + Log("EBSaver: in PairedMRDTimeStamps track " + std::to_string(track.first) + ", left trigger number " + std::to_string(track.second.size()), v_debug, verbosityEBSaver); } if (PairedMRDTriggerTimestamp.find(triggerTrack) != PairedMRDTriggerTimestamp.end()) { - uint64_t minDiff = 100 * 60 * 1e9; - Log("Found trigger track = " + std::to_string(triggerTrack) + " in PairedMRDTriggerTimestamp", v_debug, verbosityEBSaver); - // print the size of PairedMRDTriggerTimestamp.at(triggerTrack), print the first and the last timestamp - Log("EBSaver: PairedMRDTriggerTimestamp size " + std::to_string(PairedMRDTriggerTimestamp.at(triggerTrack).size()), v_debug, verbosityEBSaver); - if (PairedMRDTriggerTimestamp.at(triggerTrack).size() > 0) - Log("EBSaver: PairedMRDTriggerTimestamp first " + std::to_string(PairedMRDTriggerTimestamp.at(triggerTrack).at(0)) + ", last " + std::to_string(PairedMRDTriggerTimestamp.at(triggerTrack).at(PairedMRDTriggerTimestamp.at(triggerTrack).size() - 1)), v_debug, verbosityEBSaver); - - for (int i = 0; i < PairedMRDTriggerTimestamp.at(triggerTrack).size(); i++) + if (triggerTime > PairedMRDTriggerTimestamp.at(triggerTrack).at(0) && triggerTime < PairedMRDTriggerTimestamp.at(triggerTrack).at(PairedMRDTriggerTimestamp.at(triggerTrack).size() - 1)) { - uint64_t diff = (PairedMRDTriggerTimestamp.at(triggerTrack).at(i) > triggerTime) ? PairedMRDTriggerTimestamp.at(triggerTrack).at(i) - triggerTime : triggerTime - PairedMRDTriggerTimestamp.at(triggerTrack).at(i); - if (diff < minDiff) - minDiff = diff; - - if (PairedMRDTriggerTimestamp.at(triggerTrack).at(i) == triggerTime || (diff < 1e6)) + uint64_t minDiff = 100 * 60 * 1e9; + Log("Found trigger track = " + std::to_string(triggerTrack) + " in PairedMRDTriggerTimestamp with current searching trigger type = " + std::to_string(triggerType) + " and trigger time = " + std::to_string(triggerTime), v_debug, verbosityEBSaver); + // print the size of PairedMRDTriggerTimestamp.at(triggerTrack), print the first and the last timestamp + Log("EBSaver: PairedMRDTriggerTimestamp size " + std::to_string(PairedMRDTriggerTimestamp.at(triggerTrack).size()), v_debug, verbosityEBSaver); + if (PairedMRDTriggerTimestamp.at(triggerTrack).size() > 0) + Log("EBSaver: PairedMRDTriggerTimestamp first " + std::to_string(PairedMRDTriggerTimestamp.at(triggerTrack).at(0)) + ", last " + std::to_string(PairedMRDTriggerTimestamp.at(triggerTrack).at(PairedMRDTriggerTimestamp.at(triggerTrack).size() - 1)), v_debug, verbosityEBSaver); + + for (int i = 0; i < PairedMRDTriggerTimestamp.at(triggerTrack).size(); i++) { - if (diff < 1e6) + uint64_t diff = (PairedMRDTriggerTimestamp.at(triggerTrack).at(i) > triggerTime) ? PairedMRDTriggerTimestamp.at(triggerTrack).at(i) - triggerTime : triggerTime - PairedMRDTriggerTimestamp.at(triggerTrack).at(i); + if (diff < minDiff) + minDiff = diff; + + if (PairedMRDTriggerTimestamp.at(triggerTrack).at(i) == triggerTime || (diff < 1e6)) { - Log("EBSaver: diff<1e6, is " + std::to_string(diff), v_debug, verbosityEBSaver); - TriggerTimeWithoutMRD.emplace(PairedMRDTriggerTimestamp.at(triggerTrack).at(i), static_cast(diff)); + if (diff < 1e6) + { + Log("EBSaver: diff<1e6, is " + std::to_string(diff), v_debug, verbosityEBSaver); + TriggerTimeWithoutMRD.emplace(PairedMRDTriggerTimestamp.at(triggerTrack).at(i), static_cast(diff)); + } + uint64_t MRDTime = PairedMRDTimeStamps.at(triggerTrack).at(i); + bool saved = SaveMRDData(MRDTime); + MRDSaved = saved; + DataStreams["MRD"] = 1; + if (MRDSaved) + MRDPairInfoToRemoveTime[triggerTrack].push_back(MRDTime); + Log("EBSaver: Saved " + std::to_string(savedMRDNumber) + " MRD data with MRDTime " + std::to_string(MRDTime), v_debug, verbosityEBSaver); + Log("EBSaver: Found trigger with time " + std::to_string(triggerTime) + " in PairedMRDTriggerTimestamp " + std::to_string(i) + " match with MRDTime " + std::to_string(MRDTime), v_debug, verbosityEBSaver); + // break; + Log("EBSaver: While saving MRD data, use trigger time " + std::to_string(triggerTime) + " with minDiff " + std::to_string(minDiff), v_debug, verbosityEBSaver); } - uint64_t MRDTime = PairedMRDTimeStamps.at(triggerTrack).at(i); - bool saved = SaveMRDData(MRDTime); - MRDSaved = saved; - DataStreams["MRD"] = 1; - if (MRDSaved) - MRDPairInfoToRemoveTime[triggerTrack].push_back(MRDTime); - Log("EBSaver: Saved " + std::to_string(savedMRDNumber) + " MRD data with MRDTime " + std::to_string(MRDTime), v_debug, verbosityEBSaver); - Log("EBSaver: Found trigger with time " + std::to_string(triggerTime) + " in PairedMRDTriggerTimestamp " + std::to_string(i) + " match with MRDTime " + std::to_string(MRDTime), v_debug, verbosityEBSaver); - // break; } } // Log("EBSaver: MRDData saved", 8, verbosityEBSaver); - Log("EBSaver: While saving MRD data, use trigger time " + std::to_string(triggerTime) + " with minDiff " + std::to_string(minDiff), v_debug, verbosityEBSaver); } } @@ -615,10 +616,12 @@ bool EBSaver::SaveGroupedTriggers(int triggerTrack, int groupIndex) ANNIEEvent->Set("GroupedTrigger", GroupedTrigger); int matchTriggerType = triggerTrack; ANNIEEvent->Set("PrimaryTriggerWord", matchTriggerType); - if(matchTriggerType!=14){ + if (matchTriggerType != 14) + { ANNIEEvent->Set("TriggerWord", matchTriggerType); } - else{ + else + { ANNIEEvent->Set("TriggerWord", 5); } diff --git a/UserTools/Factory/Factory.cpp b/UserTools/Factory/Factory.cpp index 43dd70ca3..bea610442 100644 --- a/UserTools/Factory/Factory.cpp +++ b/UserTools/Factory/Factory.cpp @@ -181,5 +181,6 @@ if (tool=="EBPMT") ret=new EBPMT; if (tool=="EBMRD") ret=new EBMRD; if (tool=="EBSaver") ret=new EBSaver; if (tool=="ANNIEEventTreeMaker") ret=new ANNIEEventTreeMaker; +if (tool=="ProcessedLAPPDFilter") ret=new ProcessedLAPPDFilter; return ret; } diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp index 20371452a..fbb392c93 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp @@ -45,6 +45,7 @@ bool LAPPDLoadStore::Initialise(std::string configfile, DataModel &data) NonEmptyEvents = 0; NonEmptyDataEvents = 0; PPSnumber = 0; + mergedEvent = false; isFiltered = false; isBLsub = false; isCFD = false; @@ -72,6 +73,8 @@ bool LAPPDLoadStore::Initialise(std::string configfile, DataModel &data) partFileNumber = 0; eventNumberInPF = 0; + ReadStore = 0; + // get data file if (ReadStore == 1) { @@ -157,8 +160,17 @@ void LAPPDLoadStore::CleanDataObjects() LAPPDWaveforms.clear(); data.clear(); Parse_buffer.clear(); - LAPPDDataMap.clear(); + // LAPPDDataMap.clear(); + // DataStreams.clear(); runInfoLoaded = false; + + LAPPD_IDs.clear(); + LAPPDLoadedTimeStampsRaw.clear(); + LAPPDLoadedBeamgatesRaw.clear(); + LAPPDLoadedOffsets.clear(); + LAPPDLoadedTSCorrections.clear(); + LAPPDLoadedBGCorrections.clear(); + LAPPDLoadedOSInMinusPS.clear(); } bool LAPPDLoadStore::Execute() @@ -170,6 +182,24 @@ bool LAPPDLoadStore::Execute() CleanDataObjects(); m_data->CStore.Set("LAPPD_new_event", false); + if (MultiLAPPDMap) + { + bool gotDataStream = m_data->Stores.at("ANNIEEvent")->Get("DataStreams", DataStreams); + bool getMap = m_data->Stores["ANNIEEvent"]->Get("LAPPDDataMap", LAPPDDataMap); + if (getMap) + { + // cout << "Outside, size of LAPPDDatamap = " << LAPPDDataMap.size() << endl; + bool gotBeamgates_ns = m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + bool gotTimeStamps_ns = m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); + bool gotTimeStampsRaw = m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStampsRaw", LAPPDTimeStampsRaw); + bool gotBeamgatesRaw = m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgatesRaw", LAPPDBeamgatesRaw); + bool gotOffsets = m_data->Stores["ANNIEEvent"]->Get("LAPPDOffsets", LAPPDOffsets); + bool gotTSCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDTSCorrection", LAPPDTSCorrection); + bool gotDBGCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDBGCorrection", LAPPDBGCorrection); + bool gotOSInMinusPS = m_data->Stores["ANNIEEvent"]->Get("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + } + } + // decide loading data or not, set to LAPPDana for later tools LAPPDana = LoadData(); m_data->CStore.Set("LAPPDana", LAPPDana); @@ -281,20 +311,43 @@ bool LAPPDLoadStore::Execute() // data was already loaded in the LoadData() + vector ReadedBoards; + vector ACDCReadedLAPPDID; + if (LAPPDStoreReadInVerbosity > 0) cout << "LAPPDStoreReadIn: LAPPDDataMap has " << LAPPDDataMap.size() << " LAPPD PSEC data " << endl; bool ValidDataLoaded = false; std::map::iterator it; for (it = LAPPDDataMap.begin(); it != LAPPDDataMap.end(); it++) { + ParaBoards.clear(); uint64_t time = it->first; PsecData dat = it->second; - ReadBoards = dat.BoardIndex; + ReadBoards = dat.BoardIndex; // From the data, board index is not related to the LAPPD_ID! WHY use this way? Raw_buffer = dat.RawWaveform; LAPPD_ID = dat.LAPPD_ID; if (LAPPD_ID != SelectedLAPPD && SelectSingleLAPPD) continue; + if (LAPPDStoreReadInVerbosity > 0) + { + // print ReadBoards + cout << "LAPPD ID " << LAPPD_ID << " ReadBoards size is " << ReadBoards.size() << ", data: " << endl; + for (auto it = ReadBoards.begin(); it != ReadBoards.end(); it++) + { + cout << ", " << *it; + } + cout << endl; + } + + // push all elements in ReadBoards to ReadedBoards + for (auto it = ReadBoards.begin(); it != ReadBoards.end(); it++) + { + ReadedBoards.push_back(*it); + ACDCReadedLAPPDID.push_back(LAPPD_ID); + //cout << "ReadedBoards loaded with " << *it << endl; + } + int frametype = static_cast(Raw_buffer.size() / ReadBoards.size()); if (frametype != num_vector_data) { @@ -302,18 +355,64 @@ bool LAPPDLoadStore::Execute() continue; } m_data->CStore.Set("LAPPDanaData", true); + if (LAPPDStoreReadInVerbosity > 3) + { + cout << "Before parsing data, printing size and element in ReadBoards, ReadedBoards, ParaBoards" << endl; + cout << "ReadBoards size is " << ReadBoards.size() << endl; + for (auto it = ReadBoards.begin(); it != ReadBoards.end(); it++) + { + cout << ", " << *it; + } + cout << endl; + cout << "ReadedBoards size is " << ReadedBoards.size() << endl; + for (auto it = ReadedBoards.begin(); it != ReadedBoards.end(); it++) + { + cout << ", " << *it; + } + cout << endl; + cout << "ParaBoards size is " << ParaBoards.size() << endl; + for (auto it = ParaBoards.begin(); it != ParaBoards.end(); it++) + { + cout << ", " << *it; + } + cout << endl; + } bool parsData = ParsePSECData(); // TODO: now assuming all boards just has 30 channels. Need to be changed for gen 2 if (parsData) { ValidDataLoaded = true; + if (LAPPDStoreReadInVerbosity > 2) + cout << "LAPPDLoadStore: Loaded LAPPD data for LAPPD_ID " << LAPPD_ID << " at time " << time << endl; LAPPDLoadedTimeStamps.push_back(time); LAPPD_IDs.push_back(LAPPD_ID); + // print the size of LAPPDTimeStampsRaw, print all keys in it + if (LAPPDStoreReadInVerbosity > 0) + { + cout << "LAPPDTimeStampsRaw size is " << LAPPDTimeStampsRaw.size() << endl; + for (auto it = LAPPDTimeStampsRaw.begin(); it != LAPPDTimeStampsRaw.end(); it++) + { + cout << "LAPPDTimeStampsRaw key is " << it->first << endl; + } + } + // print the size of LAPPDOffsets, print all keys in it + if (LAPPDStoreReadInVerbosity > 0) + { + cout << "LAPPDOffsets size is " << LAPPDOffsets.size() << endl; + for (auto it = LAPPDOffsets.begin(); it != LAPPDOffsets.end(); it++) + { + cout << "LAPPDOffsets key is " << it->first << endl; + } + } + LAPPDLoadedTimeStampsRaw.push_back(LAPPDTimeStampsRaw.at(time)); LAPPDLoadedBeamgatesRaw.push_back(LAPPDBeamgatesRaw.at(time)); LAPPDLoadedOffsets.push_back(LAPPDOffsets.at(time)); LAPPDLoadedTSCorrections.push_back(LAPPDTSCorrection.at(time)); LAPPDLoadedBGCorrections.push_back(LAPPDBGCorrection.at(time)); LAPPDLoadedOSInMinusPS.push_back(LAPPDOSInMinusPS.at(time)); + + if (LAPPDStoreReadInVerbosity > 2) + cout << "parsing finished for LAPPD_ID " << LAPPD_ID << " at time " << time << endl; } NonEmptyEvents += 1; NonEmptyDataEvents += 1; @@ -326,14 +425,32 @@ bool LAPPDLoadStore::Execute() m_data->Stores["ANNIEEvent"]->Set("RawLAPPDData", LAPPDWaveforms); // leave this only for the merger tool m_data->Stores["ANNIEEvent"]->Set("LAPPD_IDs", LAPPD_IDs); m_data->Stores["ANNIEEvent"]->Set("LAPPDLoadedTimeStamps", LAPPDLoadedTimeStamps); + m_data->Stores["ANNIEEvent"]->Set("ACDCboards", ReadedBoards); + m_data->Stores["ANNIEEvent"]->Set("ACDCReadedLAPPDID", ACDCReadedLAPPDID); + m_data->Stores["ANNIEEvent"]->Set("ACDCmetadata", meta); + + m_data->Stores["ANNIEEvent"]->Set("LAPPDDataMap", LAPPDDataMap); + + m_data->Stores["ANNIEEvent"]->Set("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + m_data->Stores["ANNIEEvent"]->Set("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); + m_data->Stores["ANNIEEvent"]->Set("LAPPDTimeStampsRaw", LAPPDTimeStampsRaw); + m_data->Stores["ANNIEEvent"]->Set("LAPPDBeamgatesRaw", LAPPDBeamgatesRaw); + m_data->Stores["ANNIEEvent"]->Set("LAPPDOffsets", LAPPDOffsets); + m_data->Stores["ANNIEEvent"]->Set("LAPPDTSCorrection", LAPPDTSCorrection); + m_data->Stores["ANNIEEvent"]->Set("LAPPDBGCorrection", LAPPDBGCorrection); + m_data->Stores["ANNIEEvent"]->Set("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + // TODO: save other timestamps, variables and metadata for later use - if (eventNo % 500 == 0) + if (eventNo % 100 == 0) { cout << "LAPPDLoadStore: Loaded " << eventNo << " events, " << NonEmptyDataEvents << " non empty LAPPD PSEC data loaded from all LAPPDs" << endl; } } + if(LAPPDStoreReadInVerbosity>0) + cout << "LAPPDLoadStore: Finished loading LAPPD data" << endl; + return true; } @@ -595,6 +712,7 @@ int LAPPDLoadStore::getParsedData(std::vector buffer, int ch_sta if (InfoWord.size() == NUM_SAMP) { data.insert(pair>(ch_start + channel_count, InfoWord)); + if(LAPPDStoreReadInVerbosity>5) cout << "inserted data to channel " << ch_start + channel_count << endl; InfoWord.clear(); channel_count++; } @@ -617,7 +735,6 @@ bool LAPPDLoadStore::LoadData() // if loaded enough events, stop the loop and return false if (NonEmptyEvents == stopEntries || NonEmptyEvents > stopEntries || NonEmptyDataEvents == stopEntries || NonEmptyDataEvents > stopEntries) - { if (LAPPDStoreReadInVerbosity > 0) cout << "LAPPDStoreReadIn: NonEmptyEvents is " << NonEmptyEvents << ", NonEmptyDataEvents is " << NonEmptyDataEvents << ", stopEntries is " << stopEntries << ", stop the loop" << endl; @@ -625,10 +742,22 @@ bool LAPPDLoadStore::LoadData() return false; } - std::map DataStreams; - m_data->Stores["ANNIEEvent"]->Get("DataStreams", DataStreams); - if (mergedEvent) - DataStreams["LAPPD"] = true; + // bool gotDataStream = m_data->Stores.at("ANNIEEvent")->Get("DataStreams", DataStreams); + // cout << "Inside, Got DataStreams = " << gotDataStream << ", "; + /*for (auto it = DataStreams.begin(); it != DataStreams.end(); ++it) + { + cout << "DataStream: " << it->first << " " << it->second << ", "; + } + cout << endl;*/ + + // if (mergedEvent) + // DataStreams["LAPPD"] = true; + + // print the load information: DataStreams["LAPPD"] value, PsecReceiveMode, MultiLAPPDMap + if (LAPPDStoreReadInVerbosity > 0) + { + cout << "LAPPDStoreReadIn: DataStreams[LAPPD] is " << DataStreams["LAPPD"] << ", PsecReceiveMode is " << PsecReceiveMode << ", MultiLAPPDMap is " << MultiLAPPDMap << endl; + } if (loadPSEC || loadPPS) { // if load any kind of data @@ -750,21 +879,16 @@ bool LAPPDLoadStore::LoadData() } else if (DataStreams["LAPPD"] && PsecReceiveMode == 0 && MultiLAPPDMap) // if not receive from cstore, and load multi lappd map { - bool getMap = m_data->Stores["ANNIEEvent"]->Get("LAPPDDataMap", LAPPDDataMap); if (LAPPDStoreReadInVerbosity > 0) - cout << "LAPPDStoreReadIn: getting LAPPDDataMap from ANNIEEvent" << endl; - if (getMap) + cout << "LAPPDLoadStore: Loading multiple LAPPD data from ANNIEEvent" << "Inside, size of LAPPDDatamap = " << LAPPDDataMap.size() << endl; + + if (LAPPDDataMap.size() == 0) { - bool gotBeamgates_ns = m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); - bool gotTimeStamps_ns = m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); - bool gotTimeStampsRaw = m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStampsRaw", LAPPDTimeStampsRaw); - bool gotBeamgatesRaw = m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgatesRaw", LAPPDBeamgatesRaw); - bool gotOffsets = m_data->Stores["ANNIEEvent"]->Get("LAPPDOffsets", LAPPDOffsets); - bool gotTSCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDTSCorrection", LAPPDTSCorrection); - bool gotDBGCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDBGCorrection", LAPPDBGCorrection); - bool gotOSInMinusPS = m_data->Stores["ANNIEEvent"]->Get("LAPPDOSInMinusPS", LAPPDOSInMinusPS); - return true; + cout << "what happened?" << endl; + return false; } + + return true; } } return false; // if not any of the above, return false @@ -895,11 +1019,20 @@ bool LAPPDLoadStore::ParsePSECData() } } // loop all boards, 0, 1 - for (int bi : ParaBoards) + if (LAPPDStoreReadInVerbosity > 2) + { + cout << "ParaBoards size is " << ParaBoards.size() << endl; + for (int i = 0; i < ParaBoards.size(); i++) + { + cout << "ParaBoards " << i << " is " << ParaBoards[i] << endl; + } + } + for (int i = 0; i < ParaBoards.size(); i++) { + int bi = ParaBoards.at(i) % 2; Parse_buffer.clear(); if (LAPPDStoreReadInVerbosity > 2) - std::cout << "Starting with board " << ReadBoards[bi] << std::endl; + std::cout << "Parsing board " << ReadBoards[bi] << std::endl; // Go over all ACDC board data frames by seperating them int frametype = static_cast(Raw_buffer.size() / ReadBoards.size()); for (int c = bi * frametype; c < (bi + 1) * frametype; c++) @@ -907,18 +1040,19 @@ bool LAPPDLoadStore::ParsePSECData() Parse_buffer.push_back(Raw_buffer[c]); } if (LAPPDStoreReadInVerbosity > 2) - std::cout << "Data for board " << ReadBoards[bi] << " was grabbed!" << std::endl; + std::cout << "Data for " << i << "_th board with board number = " << ReadBoards[bi] << " was grabbed!" << std::endl; // Grab the parsed data and give it to a global variable 'data' // insert the data start with channel number 30*ReadBoards[bi] // for instance, when bi=0 , LAPPD ID = 2, ReadBoards[bi] = 4, insert to channel number start with 120, to 150 - retval = getParsedData(Parse_buffer, ReadBoards[bi] * NUM_CH); //(because there are only 2 boards, so it's 0*30 or 1*30). Inserting the channel number start from this then ++ to 30 + int channelShift = bi * NUM_CH + LAPPD_ID * NUM_CH * 2; + retval = getParsedData(Parse_buffer, channelShift); //(because there are only 2 boards, so it's 0*30 or 1*30). Inserting the channel number start from this then ++ to 30 if (retval == 0) { if (LAPPDStoreReadInVerbosity > 2) - std::cout << "Data for board " << ReadBoards[bi] << " was parsed!" << std::endl; + std::cout << "Data for board with number = " << ReadBoards[bi] << " was parsed with channel shift " << channelShift << endl; // Grab the parsed metadata and give it to a global variable 'meta' - retval = getParsedMeta(Parse_buffer, ReadBoards[bi]); + retval = getParsedMeta(Parse_buffer, bi + LAPPD_ID * 2); if (retval != 0) { std::cout << "Meta parsing went wrong! " << retval << endl; @@ -936,15 +1070,33 @@ bool LAPPDLoadStore::ParsePSECData() return false; } } - + if (LAPPDStoreReadInVerbosity > 2) + cout << "Parsed all boards for this event finished" << endl; return true; } bool LAPPDLoadStore::DoPedestalSubtract() { + if(LAPPDStoreReadInVerbosity>0) cout << "LAPPDLoadStore::DoPedestalSubtract()" << endl; Waveform tmpWave; vector> VecTmpWave; int pedval, val; + if (LAPPDStoreReadInVerbosity > 3) + { + // print the size of data and all keys, and the size of PedestalValues and all keys + cout << "Size of data is " << data.size() << endl; + for (std::map>::iterator it = data.begin(); it != data.end(); ++it) // looping over the data map by channel number, from 0 to 60 + { + cout << it->first << ", "; + } + cout << endl; + cout << "Size of PedestalValues is " << PedestalValues->size() << endl; + for (auto it = PedestalValues->begin(); it != PedestalValues->end(); ++it) // looping over the data map by channel number, from 0 to 60 + { + cout << it->first << ", "; + } + cout << endl; + } // Loop over data stream for (std::map>::iterator it = data.begin(); it != data.end(); ++it) // looping over the data map by channel number, from 0 to 60 { diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.h b/UserTools/LAPPDLoadStore/LAPPDLoadStore.h index 1679bae12..a6f28e5d1 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.h +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.h @@ -130,6 +130,7 @@ class LAPPDLoadStore : public Tool std::map LAPPDTSCorrection; std::map LAPPDBGCorrection; std::map LAPPDOSInMinusPS; + std::map DataStreams; // data variables don't need to be cleared in each loop // these are loaded offset for event building diff --git a/UserTools/LAPPDPlots/LAPPDPlots.cpp b/UserTools/LAPPDPlots/LAPPDPlots.cpp index aca3cc758..cf0794b48 100644 --- a/UserTools/LAPPDPlots/LAPPDPlots.cpp +++ b/UserTools/LAPPDPlots/LAPPDPlots.cpp @@ -75,6 +75,9 @@ bool LAPPDPlots::Initialise(std::string configfile, DataModel &data) printEventNumber = 10; m_variables.Get("printEventNumber", printEventNumber); + LoadLAPPDMap = false; + m_variables.Get("LoadLAPPDMap", LoadLAPPDMap); + eventNumber = 0; f = new TFile("LAPPDPlots.root", "RECREATE"); @@ -95,6 +98,15 @@ bool LAPPDPlots::Execute() if (OnlyDrawInBeamWindow && (inBeamWindow == 0 || inBeamWindow == -1)) return true; + m_data->Stores["ANNIEEvent"]->Get("ACDCReadedLAPPDID", ACDCReadedLAPPDID); + m_data->Stores["ANNIEEvent"]->Get("LAPPD_IDs", LAPPD_IDs); + + if (ACDCReadedLAPPDID.size() > 2) + { + CanvasXSubPlotNumber = static_cast(ACDCReadedLAPPDID.size()); + CanvasTotalSubPlotNumber = CanvasXSubPlotNumber * CanvasYSubPlotNumber; + } + c->Clear(); c->Divide(CanvasXSubPlotNumber, CanvasYSubPlotNumber); @@ -115,6 +127,14 @@ bool LAPPDPlots::Execute() if (DrawEventWaveform) { vector DrawPosition = {Side0EventWaveformDrawPosition, Side1EventWaveformDrawPosition}; + if (ReadBoards.size() > DrawPosition.size()) + { + DrawPosition.clear(); + for (int i = 0; i < ReadBoards.size(); i++) + { + DrawPosition.push_back(ReadBoards.at(i) + 1); + } + } for (int i = 0; i < ReadBoards.size(); i++) { const int drawPosition = DrawPosition[i]; @@ -145,12 +165,13 @@ bool LAPPDPlots::Execute() std::map>>::iterator it; for (it = boarddata.begin(); it != boarddata.end(); it++) { - unsigned long channelNo = it->first; + unsigned long originalChannelNo = it->first; + unsigned long channelNo = ((it->first % 1000)) % 60 + 1000; Waveform w = it->second[0]; Channel *ch = _geom->GetChannel(channelNo); int stripNo = ch->GetStripNum(); if (LAPPDPlotsVerbosity > 3) - cout << "Drawing channel " << channelNo << " strip " << stripNo << ", with sample size " << w.GetSamples()->size() << endl; + cout << "Drawing channel " << originalChannelNo << " as channelNo" << channelNo << " strip " << stripNo << ", with sample size " << w.GetSamples()->size() << endl; if (!drawTriggerChannel) if ((channelNo % 1000) % 30 == 5) continue; @@ -186,6 +207,14 @@ bool LAPPDPlots::Execute() { vector DrawPositionBinHist = {Side0BinDrawPosition, Side1BinDrawPosition}; + if (ReadBoards.size() > DrawPositionBinHist.size()) + { + DrawPositionBinHist.clear(); + for (int i = 0; i < ReadBoards.size(); i++) + { + DrawPositionBinHist.push_back(ReadBoards.at(i) + CanvasXSubPlotNumber + 1); + } + } for (int i = 0; i < ReadBoards.size(); i++) { const int drawPosition = DrawPositionBinHist[i]; @@ -216,12 +245,15 @@ bool LAPPDPlots::Execute() std::map>>::iterator it; for (it = boarddata.begin(); it != boarddata.end(); it++) { - unsigned long channelNo = it->first; + + unsigned long originalChannelNo = it->first; + unsigned long channelNo = ((it->first % 1000)) % 60 + 1000; Waveform w = it->second[0]; Channel *ch = _geom->GetChannel(channelNo); int stripNo = ch->GetStripNum(); if (LAPPDPlotsVerbosity > 3) - cout << "Drawing channel " << channelNo << " strip " << stripNo << ", with sample size " << w.GetSamples()->size() << endl; + cout << "Drawing channel " << originalChannelNo << " as channelNo" << channelNo << " strip " << stripNo << ", with sample size " << w.GetSamples()->size() << endl; + if (!drawTriggerChannel) if ((channelNo % 1000) % 30 == 5) continue; @@ -365,12 +397,24 @@ std::map>> LAPPDPlots::GetDataForBoard(in for (auto &it : lappddata) { unsigned long channelNo = it.first; + unsigned long forStripChannelNo = ((it.first % 1000)) % 60 + 1000; - Channel *ch = _geom->GetChannel(channelNo); + Channel *ch = _geom->GetChannel(forStripChannelNo); int stripSide = ch->GetStripSide(); + + int thisLAPPDID = static_cast((channelNo % 1000) / 60); + int beginningBoardIDofThisLAPPDID = ReadBoards.at(std::distance(ACDCReadedLAPPDID.begin(), std::find(ACDCReadedLAPPDID.begin(), ACDCReadedLAPPDID.end(), thisLAPPDID))); + + int targetLAPPDID = static_cast(boardID / 2) * 2; + if (LoadLAPPDMap) + { + targetLAPPDID = thisLAPPDID; + } + if (LAPPDPlotsVerbosity > 4) - cout << "GetData, channelNo: " << channelNo << ", side number" << stripSide << ", boardID " << boardID << endl; - if (static_cast((channelNo % 1000) / 60) == static_cast(boardID / 2) * 2 && stripSide == boardID % 2) + cout << "GetData, channelNo: " << channelNo << ", side number" << stripSide << ", boardID " << boardID << ", targetLAPPDID " << targetLAPPDID << endl; + + if (static_cast((channelNo % 1000) / 60) == targetLAPPDID && stripSide == boardID % 2) { boarddata[channelNo] = it.second; if (LAPPDPlotsVerbosity > 4) diff --git a/UserTools/LAPPDPlots/LAPPDPlots.h b/UserTools/LAPPDPlots/LAPPDPlots.h index bc31a665e..7feaf09d7 100644 --- a/UserTools/LAPPDPlots/LAPPDPlots.h +++ b/UserTools/LAPPDPlots/LAPPDPlots.h @@ -74,6 +74,7 @@ class LAPPDPlots : public Tool double BinHistMin; double BinHistMax; int BinHistNumber; + bool LoadLAPPDMap; // Variables that you need in the tool @@ -94,6 +95,8 @@ class LAPPDPlots : public Tool std::map>> lappddata; std::vector ReadBoards; int LAPPD_ID; + vector ACDCReadedLAPPDID; + vector LAPPD_IDs; //**************************** This tool, data variables *************************************************** // (only used in this tool, every thing that is an data object) diff --git a/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp b/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp index 2d1ad1b2b..f09f8c615 100644 --- a/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp +++ b/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp @@ -25,6 +25,8 @@ bool LAPPDStoreReorder::Initialise(std::string configfile, DataModel &data) Log("Error: LAPPDStoreReorder: Failed to get ANNIEGeometry from the ANNIEEvent store", 0, LAPPDReorderVerbosityLevel); return false; } + LoadLAPPDMap = false; + m_variables.Get("LoadLAPPDMap", LoadLAPPDMap); return true; } @@ -45,6 +47,7 @@ bool LAPPDStoreReorder::Execute() m_data->Stores["ANNIEEvent"]->Get("ACDCmetadata", acdcmetadata); m_data->Stores["ANNIEEvent"]->Get(InputWavLabel, lappddata); m_data->Stores["ANNIEEvent"]->Get("ACDCboards", NReadBoards); + m_data->Stores["ANNIEEvent"]->Get("ACDCReadedLAPPDID;", ACDCReadedLAPPDID); // Loop over waveforms, reorder data DoReorder(); @@ -75,21 +78,25 @@ void LAPPDStoreReorder::CleanDataObjects() lappddata.clear(); acdcmetadata.clear(); NReadBoards.clear(); + ACDCReadedLAPPDID.clear(); tcounters.clear(); } bool LAPPDStoreReorder::DoReorder() { + Log("LAPPDStoreReorder::DoReorder()", 1, LAPPDReorderVerbosityLevel); // For 30 channels change to 10 vector Smeta26; for (int meta26 = 0; meta26 < NReadBoards.size(); meta26++) { Smeta26.push_back(acdcmetadata.at((meta26 * NUM_VECTOR_METADATA) + 10)); if (LAPPDReorderVerbosityLevel > 1) - cout << "Metaword entry " << meta26 << " is " << Smeta26[meta26] << endl; + {cout << "Metaword entry " << meta26 << " is " << Smeta26[meta26] << endl; + cout<<"pushed meta26 = "<< meta26<<", with value at "<<(meta26 * NUM_VECTOR_METADATA) + 10<<" is "< 2) - cout << "REORDER TIME!!!! " << acdcmetadata.size() << " " << acdcmetadata.at(10) << " " << acdcmetadata.at(102) << "lappd data size is " << lappddata.size() << ", reordereddata size is " << reordereddata.size() << endl; + cout << "REORDER TIME!!!! " << acdcmetadata.size() << " " << acdcmetadata.at(10) << " " << acdcmetadata.at(102) << " lappd data size is " << lappddata.size() << ", reordereddata size is " << reordereddata.size() << endl; map>>::iterator itr; for (itr = lappddata.begin(); itr != lappddata.end(); ++itr) { @@ -110,6 +117,12 @@ bool LAPPDStoreReorder::DoReorder() int switchbit = 0; // Get the current board and the respective meta word int bi = (int)channelno / 30; + int LAPPDID = static_cast((channelno%1000)/60); + int beginningBoardIDofThisLAPPDID = NReadBoards.at(std::distance(ACDCReadedLAPPDID.begin(), std::find(ACDCReadedLAPPDID.begin(), ACDCReadedLAPPDID.end(), LAPPDID))); + if(LoadLAPPDMap) + { + bi = beginningBoardIDofThisLAPPDID + bi%2; + } unsigned short switchword = Smeta26[std::distance(NReadBoards.begin(), std::find(NReadBoards.begin(), NReadBoards.end(), bi))]; // Smeta26, 0 or 1, so switchword is the first timestmap or the second // Set the switchbit @@ -143,6 +156,7 @@ bool LAPPDStoreReorder::DoReorder() if (ibin > 255) ibin = ibin - 255; double nsamp = rwav.GetSamples()->at(ibin); + //cout << "ibin before shift is " << j << " value is " << rwav.GetSamples()->at(j) << ", after shift is " << ibin << " value is " << nsamp << endl; rwavCorr.PushSample(nsamp); } diff --git a/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.h b/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.h index 696a79491..746ab5657 100644 --- a/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.h +++ b/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.h @@ -41,6 +41,7 @@ bool ConstructTimestampsFromMeta(); int NUM_VECTOR_METADATA; int delayoffset; int GlobalShift; + bool LoadLAPPDMap; // Variables that you need in the tool //**************************** LAPPD tool chain, control variables *************************************************** @@ -60,6 +61,7 @@ bool ConstructTimestampsFromMeta(); std::map>> lappddata; vector acdcmetadata; vector NReadBoards; + vector ACDCReadedLAPPDID; vector tcounters; //**************************** This tool, data variables *************************************************** diff --git a/UserTools/LAPPDThresReco/LAPPDThresReco.cpp b/UserTools/LAPPDThresReco/LAPPDThresReco.cpp index ce561198e..29605957e 100644 --- a/UserTools/LAPPDThresReco/LAPPDThresReco.cpp +++ b/UserTools/LAPPDThresReco/LAPPDThresReco.cpp @@ -38,6 +38,8 @@ bool LAPPDThresReco::Initialise(std::string configfile, DataModel &data) m_variables.Get("loadPrintMRDinfo", loadPrintMRDinfo); // Control variables in this tool, initialized in this tool eventNumber = 0; + LoadLAPPDMapInfo = false; + m_variables.Get("LoadLAPPDMapInfo", LoadLAPPDMapInfo); // Global Control variables that you get from the config file ThresRecoInputWaveLabel = "LAPPDWave"; @@ -158,34 +160,49 @@ bool LAPPDThresReco::Execute() if (!LAPPDana) return true; + if (LoadLAPPDMapInfo) + { + m_data->Stores["ANNIEEvent"]->Get("LAPPD_IDs", LAPPD_IDs); + // print + /*cout << "ThresReco got LAPPD_IDs: "; + for (int i = 0; i < LAPPD_IDs.size(); i++) + { + cout << LAPPD_IDs.at(i) << " "; + } + cout << endl;*/ + } + else + { + // get current LAPPD_ID + m_data->CStore.Get("LAPPD_ID", LAPPD_ID); + } + // get the input LAPPD Data waveform; m_data->Stores["ANNIEEvent"]->Get(ThresRecoInputWaveLabel, lappdData); - // get current LAPPD_ID - m_data->CStore.Get("LAPPD_ID", LAPPD_ID); - if(LAPPDThresRecoVerbosity>0) - cout<<"Start WaveformMaximaFinding"< 0) + cout << "Start WaveformMaximaFinding" << endl; WaveformMaximaFinding(); // find the maxima of the waveforms - if(LAPPDThresRecoVerbosity>0) - cout<<"Start FillLAPPDPulse"< 0) + cout << "Start FillLAPPDPulse" << endl; FillLAPPDPulse(); // find pulses - if(LAPPDThresRecoVerbosity>0) - cout<<"Start FillLAPPDHit"<0) - cout<<"Reco Finished, start filling"< 0) + cout << "Start FillLAPPDHit" << endl; + FillLAPPDHit(); // find hits + if (LAPPDThresRecoVerbosity > 0) + cout << "Reco Finished, start filling" << endl; m_data->Stores["ANNIEEvent"]->Set(ThresRecoOutputPulseLabel, lappdPulses); m_data->Stores["ANNIEEvent"]->Set(ThresRecoOutputHitLabel, lappdHits); - m_data->Stores["ANNIEEvent"]->Set("waveformMax",waveformMax); - m_data->Stores["ANNIEEvent"]->Set("waveformRMS",waveformRMS); - m_data->Stores["ANNIEEvent"]->Set("waveformMaxLast",waveformMaxLast); - m_data->Stores["ANNIEEvent"]->Set("waveformMaxNearing",waveformMaxNearing); - m_data->Stores["ANNIEEvent"]->Set("waveformMaxTimeBin",waveformMaxTimeBin); + m_data->Stores["ANNIEEvent"]->Set("waveformMax", waveformMax); + m_data->Stores["ANNIEEvent"]->Set("waveformRMS", waveformRMS); + m_data->Stores["ANNIEEvent"]->Set("waveformMaxLast", waveformMaxLast); + m_data->Stores["ANNIEEvent"]->Set("waveformMaxNearing", waveformMaxNearing); + m_data->Stores["ANNIEEvent"]->Set("waveformMaxTimeBin", waveformMaxTimeBin); eventNumber++; // operation in this loop finished, increase the event number - if(LAPPDThresRecoVerbosity>0) - cout<<"Filling finished, printing to txt"< 0) + cout << "Filling finished, printing to txt" << endl; if (printHitsTXT) PrintHitsToTXT(); // print hits to a txt file if (loadPrintMRDinfo) @@ -224,24 +241,30 @@ void LAPPDThresReco::FillLAPPDPulse() // get the waveforms from channel number unsigned long channel = it->first; - channel = channel%1000 + 1000; - if ((channel % 1000)%30 == 5) + channel = channel % 1000 + 1000; + if ((channel % 1000) % 30 == 5) continue; Waveform waveforms = it->second.at(0); vector wav = *waveforms.GetSamples(); vector wave = wav; - if(wave.size() != 256) { - cout<<"FillLAPPDPulse: Found a bug waveform at channel "<2) - cout<<"FillLAPPDPulse: Found waveform at channel "< 2) + cout << "FillLAPPDPulse: Found waveform at channel " << channel << ", size is " << wave.size() << endl; // flip the waveform, so that the signal is positive for (int i = 0; i < wave.size(); i++) { wave.at(i) = -wave.at(i); } + if (LoadLAPPDMapInfo) + LAPPD_ID = static_cast((channel - 1000) / 60); + + //cout << "FillLAPPDPulse LAPPD_ID: " << LAPPD_ID << " channel: " << channel << endl; + // for this channel, find the pulses vector pulses = FindPulses(wave, LAPPD_ID, channel); @@ -388,7 +411,7 @@ vector LAPPDThresReco::FindPulses(vector wave, int LAPPD_ID, double peakBinGaus = GaussianFit(binNumbers, amplitudes); if (LAPPDThresRecoVerbosity > 1) - cout << "inserting pulse at time: " << peakBin * (25. / 256.) << "(" << peakBinGaus << ") with peakAmp: " << peakAmp << " from " << pulseStart << " to " << pulseStart + pulseSize << endl; + cout << "inserting pulse on LAPPD ID =" << LAPPD_ID << " at time: " << peakBin * (25. / 256.) << "(" << peakBinGaus << ") with peakAmp: " << peakAmp << " from " << pulseStart << " to " << pulseStart + pulseSize << endl; if (useMaxTime) { LAPPDPulse thisPulse(LAPPD_ID, channel, peakBin * (25. / 256.), Q, peakAmp, pulseStart, pulseStart + pulseSize); @@ -784,72 +807,81 @@ int LAPPDThresReco::LoadMRDTrackReco(int SubEventID) return NumClusterTracks; } +void LAPPDThresReco::WaveformMaximaFinding() +{ + // loop the lappdData map, for each value, find the maxima and RMS, and put them into waveformMax and waveformRMS + // use the strip number + 30* strip side as the key + if (LAPPDThresRecoVerbosity > 0) + cout << "WaveformMaximaFinding: Start finding maxima and RMS of the waveforms" << endl; - -void LAPPDThresReco::WaveformMaximaFinding(){ - //loop the lappdData map, for each value, find the maxima and RMS, and put them into waveformMax and waveformRMS - //use the strip number + 30* strip side as the key - if(LAPPDThresRecoVerbosity>0 ) cout<<"WaveformMaximaFinding: Start finding maxima and RMS of the waveforms"<>>::iterator it; - for(it = lappdData.begin(); it!= lappdData.end(); it++){ + std::map>>::iterator it; + for (it = lappdData.begin(); it != lappdData.end(); it++) + { unsigned long channel = it->first; - channel = channel%1000 + 1000; - if(channel == 1005 || channel == 1035) continue; - Channel* chan = _geom->GetChannel(channel); + channel = channel % 1000 + 1000; + if (channel == 1005 || channel == 1035) + continue; + Channel *chan = _geom->GetChannel(channel); int stripno = chan->GetStripNum(); int stripSide = chan->GetStripSide(); Waveform waveforms = it->second.at(0); vector wav = *waveforms.GetSamples(); vector wave = wav; - if(wave.size() != 256) { - cout<<"WaveformMaximaFinding: Found a bug waveform at channel "<2) - cout<<"WaveformMaximaFinding: Found a waveform at channel "< 2) + cout << "WaveformMaximaFinding: Found a waveform at channel " << channel << ", size is " << wave.size() << ",side is " << stripSide << ", stripno is " << stripno << endl; + for (int i = 0; i < wave.size(); i++) + { wave.at(i) = -wave.at(i); } double max = wave.at(0); - double rms = wave.at(0)*wave.at(0); + double rms = wave.at(0) * wave.at(0); bool maxIsLast = 0; double nearingMin = 0; int binOfMax = -1; - for(int i = 1; imax) { - if(wave.at(i+1)>0.8*wave.at(i) && wave.at(i-1)>0.8*wave.at(i)){ + for (int i = 1; i < wave.size() - 1; i++) + { + if (wave.at(i) > max) + { + if (wave.at(i + 1) > 0.8 * wave.at(i) && wave.at(i - 1) > 0.8 * wave.at(i)) + { max = wave.at(i); maxIsLast = 1; binOfMax = i; - } - if(wave.at(i+1)>wave.at(i-1)){ - nearingMin = wave.at(i-1); - }else{ - nearingMin = wave.at(i+1); - } + if (wave.at(i + 1) > wave.at(i - 1)) + { + nearingMin = wave.at(i - 1); + } + else + { + nearingMin = wave.at(i + 1); + } } - rms += (wave.at(i))*(wave.at(i)); + rms += (wave.at(i)) * (wave.at(i)); } - rms = sqrt(rms/wave.size()); - int key = stripno + 30*stripSide; - if(waveformMax[stripno].size() == 0){ - waveformMax[stripno].resize(2); - waveformRMS[stripno].resize(2); - waveformMaxLast[stripno].resize(2); - waveformMaxNearing[stripno].resize(2); - waveformMaxTimeBin[stripno].resize(2); + rms = sqrt(rms / wave.size()); + int LAPPD_ID = static_cast((channel - 1000) / 60); + int key = stripno + 30 * stripSide + LAPPD_ID * 60; + if (waveformMax[key].size() == 0) + { + waveformMax[key].resize(2); + waveformRMS[key].resize(2); + waveformMaxLast[key].resize(2); + waveformMaxNearing[key].resize(2); + waveformMaxTimeBin[key].resize(2); } - waveformMax[stripno].at(stripSide) = max; - waveformRMS[stripno].at(stripSide) = rms; - waveformMaxLast[stripno].at(stripSide) = maxIsLast; - waveformMaxNearing[stripno].at(stripSide) = nearingMin; - waveformMaxTimeBin[stripno].at(stripSide) = binOfMax; + waveformMax[key].at(stripSide) = max; + waveformRMS[key].at(stripSide) = rms; + waveformMaxLast[key].at(stripSide) = maxIsLast; + waveformMaxNearing[key].at(stripSide) = nearingMin; + waveformMaxTimeBin[key].at(stripSide) = binOfMax; } - } - diff --git a/UserTools/LAPPDThresReco/LAPPDThresReco.h b/UserTools/LAPPDThresReco/LAPPDThresReco.h index e73af72d1..737be8105 100644 --- a/UserTools/LAPPDThresReco/LAPPDThresReco.h +++ b/UserTools/LAPPDThresReco/LAPPDThresReco.h @@ -70,6 +70,7 @@ class LAPPDThresReco : public Tool // Variables that you need in the tool Geometry *_geom; bool LAPPDana; + bool LoadLAPPDMapInfo; // LAPPD tool chain, data variables. (Will be used in multiple LAPPD tools) // everything you get or set to Store, which means it may be used in other tools or it's from other tools @@ -81,6 +82,7 @@ class LAPPDThresReco : public Tool std::map> waveformMaxLast; std::map> waveformMaxNearing; std::map> waveformMaxTimeBin; + vector LAPPD_IDs; // This tool, data variables (only used in this tool, every thing that is an data object) std::map>> lappdData; // waveform data diff --git a/UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.cpp b/UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.cpp index 1e9192719..5a9430748 100644 --- a/UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.cpp +++ b/UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.cpp @@ -33,6 +33,9 @@ bool LAPPDTimeAlignment::Initialise(std::string configfile, DataModel &data) m_data->Stores["ANNIEEvent"]->Get("TrigChannel",TrigChannel); m_data->Stores["ANNIEEvent"]->Get("LAPPDchannelOffset",LAPPDchannelOffset); + LoadLAPPDMap = false; + m_variables.Get("LoadLAPPDMap",LoadLAPPDMap); + return true; } @@ -71,11 +74,20 @@ bool LAPPDTimeAlignment::Execute(){ bool T0signalInWindow = false; double deltaT; + vector ACDCReadedLAPPDID; + m_data->Stores["ANNIEEvent"]->Get("ACDCReadedLAPPDID", ACDCReadedLAPPDID); map >> :: iterator itr_bi; - for(int bi: NReadBoards) + for(int i = 0;i< NReadBoards.size();i++) { + int bi = NReadBoards.at(i); + int thisLAPPDID = ACDCReadedLAPPDID.at(i); + T0channelNo = LAPPDchannelOffset+(30*bi)+TrigChannel; + if(LoadLAPPDMap) + { + T0channelNo = 1000 + (30*(bi%2)) + 60* thisLAPPDID + TrigChannel; + } if(FindT0VerbosityLevel>0) cout<<"For board "< 0) + cout << "LAPPDTreeMaker::Execute() MultiLAPPDMapTreeMaker" << endl; + LoadLAPPDMapInfo(); + bool getMap = m_data->Stores["ANNIEEvent"]->Get("LAPPDDataMap", LAPPDDataMap); + bool gotBeamgates_ns = m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + bool gotTimeStamps_ns = m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); + bool gotTimeStampsRaw = m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStampsRaw", LAPPDTimeStampsRaw); + bool gotBeamgatesRaw = m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgatesRaw", LAPPDBeamgatesRaw); + bool gotOffsets = m_data->Stores["ANNIEEvent"]->Get("LAPPDOffsets", LAPPDOffsets); + bool gotTSCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDTSCorrection", LAPPDTSCorrection); + bool gotDBGCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDBGCorrection", LAPPDBGCorrection); + bool gotOSInMinusPS = m_data->Stores["ANNIEEvent"]->Get("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::Execute() MultiLAPPDMapTreeMaker get map = " << getMap << endl; + if (getMap) + { + if (treeMakerVerbosity > 0) + cout << "map size: " << LAPPDDataMap.size() << endl; + for (auto &item : LAPPDDataMap) + { + PsecData thisData = item.second; + int thisLAPPD_ID = thisData.LAPPD_ID; + + uint64_t thisDataTime = item.first; + uint64_t thisTSRaw = LAPPDTimeStampsRaw.at(thisDataTime); + uint64_t thisBGRaw = LAPPDBeamgatesRaw.at(thisDataTime); + uint64_t thisOffset = LAPPDOffsets.at(thisDataTime); + int thisTSCorr = LAPPDTSCorrection.at(thisDataTime); + int thisDBGCorr = LAPPDBGCorrection.at(thisDataTime); + int thisOSInMinusPS = LAPPDOSInMinusPS.at(thisDataTime); + + if (treeMakerVerbosity > 0) + cout << "outside tree maker, Got LAPPD ID: " << thisLAPPD_ID << ", time stamp: " << thisDataTime << ", TSraw " << thisTSRaw << ", BGraw " << thisBGRaw << ", offset " << thisOffset << ", TSCorr " << thisTSCorr << ", DBGCorr " << thisDBGCorr << ", OSInMinusPS " << thisOSInMinusPS << endl; + + LAPPD_IDs.push_back(thisLAPPD_ID); + LAPPDMapTimeStampRaw.push_back(thisTSRaw); + LAPPDMapBeamgateRaw.push_back(thisBGRaw); + LAPPDMapOffsets.push_back(thisOffset); + LAPPDMapTSCorrections.push_back(thisTSCorr); + LAPPDMapBGCorrections.push_back(thisDBGCorr); + LAPPDMapOSInMinusPS.push_back(thisOSInMinusPS); + + if (treeMakerVerbosity > 0) + cout << "outside size of LAPPD_IDs: " << LAPPD_IDs.size() << endl; + } + } + else + { + cout << "outside LAPPDTreeMaker::LoadLAPPDMapInfo, no LAPPDDataMap found" << endl; + } + + if (treeMakerVerbosity > 0) + { + cout << "LAPPDMapTimeStampRaw: "; + for (auto &item : LAPPDMapTimeStampRaw) + cout << item << " "; + cout << "LAPPDTreeMaker::Execute() MultiLAPPDMapTreeMaker finished " << endl; + } + } + if (LoadPPSTimestamp && LoadingPPS) { bool gotPPSTimestamp = m_data->CStore.Get("LAPPDPPSVector", pps_vector); @@ -347,6 +411,24 @@ void LAPPDTreeMaker::CleanVariables() groupedTriggerType = -9999; TriggerGroupNumInThisEvent = 0; // start from 0 groupedTriggerType = -9999; + + LAPPD_IDs.clear(); + LAPPDMapTimeStampRaw.clear(); + LAPPDMapBeamgateRaw.clear(); + LAPPDMapOffsets.clear(); + LAPPDMapTSCorrections.clear(); + LAPPDMapBGCorrections.clear(); + LAPPDMapOSInMinusPS.clear(); + + LAPPDDataMap.clear(); + LAPPDBeamgate_ns.clear(); + LAPPDTimeStamps_ns.clear(); + LAPPDTimeStampsRaw.clear(); + LAPPDBeamgatesRaw.clear(); + LAPPDOffsets.clear(); + LAPPDTSCorrection.clear(); + LAPPDBGCorrection.clear(); + LAPPDOSInMinusPS.clear(); } bool LAPPDTreeMaker::LoadRunInfoFromRaw() @@ -363,9 +445,9 @@ bool LAPPDTreeMaker::LoadRunInfoFromANNIEEvent() { if (treeMakerVerbosity > 0) cout << "LAPPDTreeMaker::LoadRunInfoFromANNIEEvent" << endl; - m_data->Stores["ANNIEEvent"]->Header->Get("RunNumber", RunNumber); - m_data->Stores["ANNIEEvent"]->Header->Get("SubRunNumber", SubRunNumber); - m_data->Stores["ANNIEEvent"]->Header->Get("PartFileNumber", PartFileNumber); + m_data->Stores["ANNIEEvent"]->Get("RunNumber", RunNumber); + m_data->Stores["ANNIEEvent"]->Get("SubRunNumber", SubRunNumber); + m_data->Stores["ANNIEEvent"]->Get("PartNumber", PartFileNumber); if (treeMakerVerbosity > 0) cout << "RunNumber: " << RunNumber << ", SubRunNumber: " << SubRunNumber << ", PartFileNumber: " << PartFileNumber << endl; return true; @@ -401,7 +483,24 @@ bool LAPPDTreeMaker::FillPulseTree() PulseStart = thisPulse.GetLowRange(); PulseEnd = thisPulse.GetHiRange(); PulseSize = PulseEnd - PulseStart; - // TODO save threshold and baseline + // cout << " tree maker, this pulse0 LAPPD ID is " << LAPPD_ID << endl; + // TODO save threshold and baseline + if (MultiLAPPDMapTreeMaker) + { + // find the index of LAPPD_ID in LAPPD_IDs, use that index to assign the timestamlUL and beam gate UL, if not found set them to zero + auto it = std::find(LAPPD_IDs.begin(), LAPPD_IDs.end(), LAPPD_ID); + if (it != LAPPD_IDs.end()) + { + int index = std::distance(LAPPD_IDs.begin(), it); + LAPPDDataTimeStampUL = LAPPDMapTimeStampRaw.at(index); + LAPPDDataBeamgateUL = LAPPDMapBeamgateRaw.at(index); + } + else + { + LAPPDDataTimeStampUL = 0; + LAPPDDataBeamgateUL = 0; + } + } fPulse->Fill(); foundPulseNum++; } @@ -418,7 +517,29 @@ bool LAPPDTreeMaker::FillPulseTree() PulseStart = thisPulse.GetLowRange(); PulseEnd = thisPulse.GetHiRange(); PulseSize = PulseEnd - PulseStart; + /*cout << " this pulse1 LAPPD ID is " << LAPPD_ID << endl; + cout << "ThresReco pulse1 got LAPPD_IDs: "; + for (int i = 0; i < LAPPD_IDs.size(); i++) + { + cout << LAPPD_IDs.at(i) << " "; + }*/ // TODO save threshold and baseline + if (MultiLAPPDMapTreeMaker) + { + // find the index of LAPPD_ID in LAPPD_IDs, use that index to assign the timestamlUL and beam gate UL, if not found set them to zero + auto it = std::find(LAPPD_IDs.begin(), LAPPD_IDs.end(), LAPPD_ID); + if (it != LAPPD_IDs.end()) + { + int index = std::distance(LAPPD_IDs.begin(), it); + LAPPDDataTimeStampUL = LAPPDMapTimeStampRaw.at(index); + LAPPDDataBeamgateUL = LAPPDMapBeamgateRaw.at(index); + } + else + { + LAPPDDataTimeStampUL = 0; + LAPPDDataBeamgateUL = 0; + } + } fPulse->Fill(); foundPulseNum++; } @@ -461,6 +582,31 @@ bool LAPPDTreeMaker::FillHitTree() Pulse2StartTime = thisHit.GetPulse2StartTime(); Pulse1LastTime = thisHit.GetPulse1LastTime(); Pulse2LastTime = thisHit.GetPulse2LastTime(); + if (treeMakerVerbosity > 0) + { + cout << " this hit LAPPD ID is " << LAPPD_ID << endl; + cout << "ThresReco hit got LAPPD_IDs: "; + for (int i = 0; i < LAPPD_IDs.size(); i++) + { + cout << LAPPD_IDs.at(i) << " "; + } + } + if (MultiLAPPDMapTreeMaker) + { + // find the index of LAPPD_ID in LAPPD_IDs, use that index to assign the timestamlUL and beam gate UL, if not found set them to zero + auto it = std::find(LAPPD_IDs.begin(), LAPPD_IDs.end(), LAPPD_ID); + if (it != LAPPD_IDs.end()) + { + int index = std::distance(LAPPD_IDs.begin(), it); + LAPPDDataTimeStampUL = LAPPDMapTimeStampRaw.at(index); + LAPPDDataBeamgateUL = LAPPDMapBeamgateRaw.at(index); + } + else + { + LAPPDDataTimeStampUL = 0; + LAPPDDataBeamgateUL = 0; + } + } fHit->Fill(); foundHitNum++; } @@ -481,16 +627,42 @@ bool LAPPDTreeMaker::FillWaveformTree() std::map>::iterator it; for (it = waveformMax.begin(); it != waveformMax.end(); it++) { - StripNumber = it->first; + int key = it->first; + LAPPD_ID = static_cast(key / 60); + int stripSide = static_cast((key - LAPPD_ID * 60) / 30); + StripNumber = key - LAPPD_ID * 60 - stripSide * 30; + // cout << " this waveform LAPPD ID is " << LAPPD_ID << endl; + for (int side = 0; side < 2; side++) { PulseSide = side; - LAPPD_ID = 0; - waveformMaxValue = waveformMax.at(StripNumber).at(side); - waveformRMSValue = waveformRMS.at(StripNumber).at(side); - waveformMaxFoundNear = waveformMaxLast.at(StripNumber).at(side); - waveformMaxNearingValue = waveformMaxNearing.at(StripNumber).at(side); - waveformMaxTimeBinValue = waveformMaxTimeBin.at(StripNumber).at(side); + waveformMaxValue = waveformMax.at(key).at(side); + waveformRMSValue = waveformRMS.at(key).at(side); + waveformMaxFoundNear = waveformMaxLast.at(key).at(side); + waveformMaxNearingValue = waveformMaxNearing.at(key).at(side); + waveformMaxTimeBinValue = waveformMaxTimeBin.at(key).at(side); + /*cout << " LAPPDTreeMaker fill waveform tree, LAPPD ID is " << LAPPD_ID << endl; + cout << "ThresReco got LAPPD_IDs: "; + for (int i = 0; i < LAPPD_IDs.size(); i++) + { + cout << LAPPD_IDs.at(i) << " "; + }*/ + if (MultiLAPPDMapTreeMaker) + { + // find the index of LAPPD_ID in LAPPD_IDs, use that index to assign the timestamlUL and beam gate UL, if not found set them to zero + auto it = std::find(LAPPD_IDs.begin(), LAPPD_IDs.end(), LAPPD_ID); + if (it != LAPPD_IDs.end()) + { + int index = std::distance(LAPPD_IDs.begin(), it); + LAPPDDataTimeStampUL = LAPPDMapTimeStampRaw.at(index); + LAPPDDataBeamgateUL = LAPPDMapBeamgateRaw.at(index); + } + else + { + LAPPDDataTimeStampUL = 0; + LAPPDDataBeamgateUL = 0; + } + } fWaveform->Fill(); } } @@ -517,14 +689,27 @@ bool LAPPDTreeMaker::FillLAPPDDataTimeStamp() { if (treeMakerVerbosity > 0) cout << "LAPPDTreeMaker::FillLAPPDDataTimeStamp. Before fill: LAPPDDataTimeStampUL: " << LAPPDDataTimeStampUL << ", LAPPDDataBeamgateUL: " << LAPPDDataBeamgateUL << ", LAPPDDataTimestampPart1: " << LAPPDDataTimestampPart1 << ", LAPPDDataBeamgatePart1: " << LAPPDDataBeamgatePart1 << ", LAPPDDataTimestampPart2: " << LAPPDDataTimestampPart2 << ", LAPPDDataBeamgatePart2: " << LAPPDDataBeamgatePart2 << endl; - m_data->CStore.Get("LAPPDBeamgate_Raw", LAPPDDataBeamgateUL); - m_data->CStore.Get("LAPPDTimestamp_Raw", LAPPDDataTimeStampUL); - m_data->CStore.Get("LAPPDBGIntCombined", LAPPDDataBeamgatePart1); - m_data->CStore.Get("LAPPDBGFloat", LAPPDDataBeamgatePart2); - m_data->CStore.Get("LAPPDTSIntCombined", LAPPDDataTimestampPart1); - m_data->CStore.Get("LAPPDTSFloat", LAPPDDataTimestampPart2); - m_data->CStore.Get("LAPPD_ID", LAPPD_ID); - fTimeStamp->Fill(); + if (!MultiLAPPDMapTreeMaker) + { + m_data->CStore.Get("LAPPDBeamgate_Raw", LAPPDDataBeamgateUL); + m_data->CStore.Get("LAPPDTimestamp_Raw", LAPPDDataTimeStampUL); + m_data->CStore.Get("LAPPDBGIntCombined", LAPPDDataBeamgatePart1); + m_data->CStore.Get("LAPPDBGFloat", LAPPDDataBeamgatePart2); + m_data->CStore.Get("LAPPDTSIntCombined", LAPPDDataTimestampPart1); + m_data->CStore.Get("LAPPDTSFloat", LAPPDDataTimestampPart2); + m_data->CStore.Get("LAPPD_ID", LAPPD_ID); + fTimeStamp->Fill(); + } + else + { + for (int i = 0; i < LAPPD_IDs.size(); i++) + { + LAPPD_ID = LAPPD_IDs.at(i); + LAPPDDataBeamgateUL = LAPPDMapBeamgateRaw.at(i); + LAPPDDataTimeStampUL = LAPPDMapTimeStampRaw.at(i); + fTimeStamp->Fill(); + } + } if (treeMakerVerbosity > 0) cout << "LAPPDDataTimeStampUL: " << LAPPDDataTimeStampUL << ", LAPPDDataBeamgateUL: " << LAPPDDataBeamgateUL << ", LAPPDDataTimestampPart1: " << LAPPDDataTimestampPart1 << ", LAPPDDataBeamgatePart1: " << LAPPDDataBeamgatePart1 << ", LAPPDDataTimestampPart2: " << LAPPDDataTimestampPart2 << ", LAPPDDataBeamgatePart2: " << LAPPDDataBeamgatePart2 << endl; return true; @@ -787,4 +972,56 @@ void LAPPDTreeMaker::CleanTriggers() std::vector lastTrigTimestamps(unGroupedTriggerTimestamps.end() - 1000, unGroupedTriggerTimestamps.end()); unGroupedTriggerTimestamps = lastTrigTimestamps; } +} + +void LAPPDTreeMaker::LoadLAPPDMapInfo() +{ + //cout << "LAPPDTreeMaker::LoadLAPPDMapInfo" << endl; + bool getMap = m_data->Stores["ANNIEEvent"]->Get("LAPPDDataMap", LAPPDDataMap); + bool gotBeamgates_ns = m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + bool gotTimeStamps_ns = m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); + bool gotTimeStampsRaw = m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStampsRaw", LAPPDTimeStampsRaw); + bool gotBeamgatesRaw = m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgatesRaw", LAPPDBeamgatesRaw); + bool gotOffsets = m_data->Stores["ANNIEEvent"]->Get("LAPPDOffsets", LAPPDOffsets); + bool gotTSCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDTSCorrection", LAPPDTSCorrection); + bool gotDBGCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDBGCorrection", LAPPDBGCorrection); + bool gotOSInMinusPS = m_data->Stores["ANNIEEvent"]->Get("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + //cout << "LAPPDTreeMaker::LoadLAPPDMapInfo() get map = " << getMap << endl; + + if (getMap) + { + if (treeMakerVerbosity > 0) + cout << "map size: " << LAPPDDataMap.size() << endl; + for (auto &item : LAPPDDataMap) + { + PsecData thisData = item.second; + int thisLAPPD_ID = thisData.LAPPD_ID; + + uint64_t thisDataTime = item.first; + uint64_t thisTSRaw = LAPPDTimeStampsRaw.at(thisDataTime); + uint64_t thisBGRaw = LAPPDBeamgatesRaw.at(thisDataTime); + uint64_t thisOffset = LAPPDOffsets.at(thisDataTime); + int thisTSCorr = LAPPDTSCorrection.at(thisDataTime); + int thisDBGCorr = LAPPDBGCorrection.at(thisDataTime); + int thisOSInMinusPS = LAPPDOSInMinusPS.at(thisDataTime); + + if (treeMakerVerbosity > 0) + cout << "tree maker, Got LAPPD ID: " << thisLAPPD_ID << ", time stamp: " << thisDataTime << ", TSraw " << thisTSRaw << ", BGraw " << thisBGRaw << ", offset " << thisOffset << ", TSCorr " << thisTSCorr << ", DBGCorr " << thisDBGCorr << ", OSInMinusPS " << thisOSInMinusPS << endl; + + LAPPD_IDs.push_back(thisLAPPD_ID); + LAPPDMapTimeStampRaw.push_back(thisTSRaw); + LAPPDMapBeamgateRaw.push_back(thisBGRaw); + LAPPDMapOffsets.push_back(thisOffset); + LAPPDMapTSCorrections.push_back(thisTSCorr); + LAPPDMapBGCorrections.push_back(thisDBGCorr); + LAPPDMapOSInMinusPS.push_back(thisOSInMinusPS); + + if (treeMakerVerbosity > 0) + cout << "size of LAPPD_IDs: " << LAPPD_IDs.size() << endl; + } + } + else + { + cout << "LAPPDTreeMaker::LoadLAPPDMapInfo, no LAPPDDataMap found" << endl; + } } \ No newline at end of file diff --git a/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h b/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h index c95e69c86..86650ba0d 100644 --- a/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h +++ b/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h @@ -12,6 +12,7 @@ #include "LAPPDHit.h" #include "Geometry.h" #include "Position.h" +#include "PsecData.h" /** * \class LAPPDTreeMaker @@ -44,6 +45,7 @@ class LAPPDTreeMaker : public Tool bool FillTriggerTree(); bool FillGroupedTriggerTree(); void CleanTriggers(); + void LoadLAPPDMapInfo(); private: TFile *file; @@ -150,6 +152,25 @@ class LAPPDTreeMaker : public Tool int RunNumber; int SubRunNumber; int PartFileNumber; + + bool MultiLAPPDMapTreeMaker; + vector LAPPD_IDs; + vector LAPPDMapTimeStampRaw; + vector LAPPDMapBeamgateRaw; + vector LAPPDMapOffsets; + vector LAPPDMapTSCorrections; + vector LAPPDMapBGCorrections; + vector LAPPDMapOSInMinusPS; + + std::map LAPPDDataMap; + std::map LAPPDBeamgate_ns; + std::map LAPPDTimeStamps_ns; // data and key are the same + std::map LAPPDTimeStampsRaw; + std::map LAPPDBeamgatesRaw; + std::map LAPPDOffsets; + std::map LAPPDTSCorrection; + std::map LAPPDBGCorrection; + std::map LAPPDOSInMinusPS; }; #endif diff --git a/UserTools/LoadANNIEEvent/LoadANNIEEvent.cpp b/UserTools/LoadANNIEEvent/LoadANNIEEvent.cpp index 686a69f86..9fdcc1668 100644 --- a/UserTools/LoadANNIEEvent/LoadANNIEEvent.cpp +++ b/UserTools/LoadANNIEEvent/LoadANNIEEvent.cpp @@ -176,6 +176,7 @@ bool LoadANNIEEvent::Execute() { std::string input_filename = input_filenames_.at(current_file_); bool filename_valid = false; filename_valid = theANNIEEvent->Initialise(input_filename); + Log("LoadANNIEEvent: Loading new file "+input_filename, 1, verbosity_); if (!filename_valid){ Log("LoadANNIEEvent: Filename "+input_filename+" not found! Proceed to next file",v_error,verbosity_); current_file_++; @@ -183,6 +184,8 @@ bool LoadANNIEEvent::Execute() { } m_data->Stores["ANNIEEvent"] = theANNIEEvent; m_data->Stores.at("ANNIEEvent")->Header->Get("TotalEntries",total_entries_in_file_); + Log("LoadANNIEEvent: total number of entry in this file is "+std::to_string(total_entries_in_file_), 1, verbosity_ ); + if (current_file_==0) { global_events.push_back(total_entries_in_file_); global_events_start.push_back(0); @@ -246,7 +249,6 @@ bool LoadANNIEEvent::Execute() { std::string input_filename = input_filenames_.at(current_file_); std::cout <<"Reading in current file "<Stores["ANNIEEvent"]->Initialise(input_filename); - Log("LoadANNIEEvent: Loading new file "+input_filename, 1, verbosity_); m_data->Stores["ANNIEEvent"]->Header->Get("TotalEntries", total_entries_in_file_); global_events.push_back(global_events.at(current_file_-1)+total_entries_in_file_); diff --git a/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp b/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp index a7a4563ca..8d35d113c 100755 --- a/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp +++ b/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp @@ -383,6 +383,9 @@ bool PhaseIIADCHitFinder::Execute() { // std::cout <<"InProgressHits size (calibrator): "<size()<size()<size()<size()<size()<CStore.Set("InProgressRecoADCHits",InProgressRecoADCHits); m_data->CStore.Set("InProgressChkey",InProgressChkey); + cout<<"InProgressChkey size: "<size()<CStore.Set("InProgressHitsAux",InProgressHitsAux); // std::cout <<"FinishedRecoADCHitsAux"<Stores.at("ANNIEEvent")->Get("EventTimeMRD",fEventTimeMRD); fEventTimeMRD_Tree = (ULong64_t) fEventTimeMRD.GetNs(); // bool got_mrdtime = m_data->Stores.at("ANNIEEvent")->Get("EventTime",mrd_timestamp); @@ -1992,6 +1993,10 @@ void PhaseIITreeMaker::LoadLAPPDData() m_data->Stores["ANNIEEvent"]->Get("GroupedTrigger", GroupedTrigger); if(LAPPDDataMap.size() != 0) - FillLAPPDData(); + { + FillLAPPDData(); + //print the content of fDataStreams, and the size of data map + //cout<<"Found LAPPDData, LAPPDDataMap Size: "<Stores.at("ANNIEEvent")->Get("DataStreams", DataStreams); + + + if (FilterVerbosity > 2) + { + for (auto it = DataStreams.begin(); it != DataStreams.end(); ++it) + { + cout << "DataStream: " << it->first << " " << it->second << ", "; + } + cout << endl; + } + + if (DataStreams["LAPPD"] == false) + { + return true; + } + + + if (filterType == "MRDtrack") + { + + CurrentExeNumber += 1; + gotEventMRD = false; + gotEventPMTCluster = false; + + std::map> *m_all_clusters = nullptr; + bool get_clusters = m_data->CStore.Get("ClusterMap", m_all_clusters); + if (!get_clusters) + { + std::cout << "FiltStage1Event tool: No clusters found!" << std::endl; + return false; + } + if ((int)m_all_clusters->size() > 0) + gotEventPMTCluster = true; + + std::vector> MrdTimeClusters; + bool get_clusters_mrd = m_data->CStore.Get("MrdTimeClusters", MrdTimeClusters); + if (!get_clusters_mrd) + { + std::cout << "FiltStage1Event tool: No MRD clusters found! Did you run the TimeClustering tool?" << std::endl; + return false; + } + if (MrdTimeClusters.size() > 0) + gotEventMRD = true; + + bool gotStoreNoVeto = m_data->Stores.at("RecoEvent")->Get("NoVeto", gotEventMRDNoVeto); + if (!gotStoreNoVeto) + { + cout << "The Stage1 Filter doesn't work because it need the Veto information form EventSelector Tool. Please include that." << endl; + return false; + } + + if(saveAllLAPPDEvents) + { + GotANNIEEventAndSave(FilteredAllLAPPD, AllLAPPDDataName); + } + + if (gotEventPMTCluster) + { + EventPMTClusterNumber += 1; + if (FilterVerbosity > 0) + cout << "Got an event with PMT cluster, got event number " << EventPMTClusterNumber << endl; + if (gotEventMRD) + { + GotANNIEEventAndSave(FilteredMRD, MRDDataName); + EventMRDNumber += 1; + if (FilterVerbosity > 0) + cout << "Got an event with PMT cluster, MRD hits, got event number " << EventMRDNumber << endl; + if (gotEventMRDNoVeto) + { + GotANNIEEventAndSave(FilteredMRDNoVeto, MRDNoVetoDataName); + EventMRDNoVetoNumber += 1; + if (FilterVerbosity > 0) + cout << "Got an event with PMT cluster, MRD hits and no veto, got event number " << EventMRDNoVetoNumber << endl; + } + } + + if (CurrentExeNumber % 50 == 0) + { + cout << "Filter event number: " << CurrentExeNumber << ", events with PMT clusters: " << EventPMTClusterNumber << ", also with MRD tracks: " << EventMRDNumber << ", also with MRD tracks and no veto: " << EventMRDNoVetoNumber << endl; + } + + m_data->Stores["ANNIEEvent"]->Get("RunNumber", currentRunNumber); + } + } + + if (filterType == "PMTCluster") + { + CurrentExeNumber += 1; + + gotEventPMTCluster = false; + + std::map> *m_all_clusters = nullptr; + bool get_clusters = m_data->CStore.Get("ClusterMap", m_all_clusters); + if (!get_clusters) + { + std::cout << "FiltStage1Event tool: No clusters found!" << std::endl; + return false; + } + if ((int)m_all_clusters->size() > 0) + gotEventPMTCluster = true; + + if (gotEventPMTCluster) + { + EventPMTClusterNumber += 1; + if (FilterVerbosity > 0) + cout << "Got an event with PMT cluster, got event number " << EventPMTClusterNumber << endl; + GotANNIEEventAndSave(FilteredMRD, MRDDataName); + if (CurrentExeNumber % 50 == 0) + { + cout << "Filter event number: " << CurrentExeNumber << ", events with PMT clusters: " << EventPMTClusterNumber << endl; + } + + m_data->Stores["ANNIEEvent"]->Get("RunNumber", currentRunNumber); + } + } + + /* + if (filterType == "LAPPDPulsedStripNumber") + { + CurrentExeNumber += 1; + int pulsedStripNumber = 0; + std::vector> LAPPDVectorSide0 = std::vector>(30, std::vector(256)); + // loop the vector. For each strip, loop and find maximum, if the maximum > 15, then pulsedStripNumber += 1 + m_data->Stores["ANNIEEvent"]->Get("LAPPDSigVecSide0", LAPPDVectorSide0); + for (int i = 0; i < 30; i++) + { + double max = 0; + for (int j = 0; j < 256; j++) + { + if (LAPPDVectorSide0[i][j] > max) + max = LAPPDVectorSide0[i][j]; + if (FilterVerbosity > requirePulsedStripNumber) + cout << "LAPPDVectorSide0[" << i << "][" << j << "] = " << LAPPDVectorSide0[i][j] << endl; + } + if (max > requirePulsedAmp) + pulsedStripNumber += 1; + } + if (pulsedStripNumber > requirePulsedStripNumber) + { + GotANNIEEventAndSave(FilteredMRD, MRDDataName); + EventMRDNumber += 1; + } + + if (CurrentExeNumber % 50 == 0) + { + cout << "Filter event number " << CurrentExeNumber << ", pulsedStripNumber more than " << requirePulsedStripNumber << " events " << EventMRDNumber << endl; + } + } + */ + + return true; +} + +bool ProcessedLAPPDFilter::Finalise() +{ + FilteredMRD->Close(); + FilteredMRDNoVeto->Close(); + FilteredAllLAPPD->Close(); + + FilteredMRD->Delete(); + FilteredMRDNoVeto->Delete(); + FilteredAllLAPPD->Delete(); + + + if (filterType == "MRDtrack") + { + cout << "Current Run " << currentRunNumber << endl; + cout << "Filter got " << CurrentExeNumber << " events in total" << endl; // this is the total number of events + cout << "Got " << EventPMTClusterNumber << " events with PMT clusters" << endl; + cout << "Got " << EventMRDNumber << " events with PMT clusters and MRD hits" << endl; + cout << "Got " << EventMRDNoVetoNumber << " events with PMT clusters and MRD hits and no veto" << endl; + cout << "Saved " << MRDDataName << " successfully" << endl; + cout << "Saved " << MRDNoVetoDataName << " successfully" << endl; + + std::ofstream file("FilterStat.txt", std::ios::app); + file << currentRunNumber << " " << CurrentExeNumber << " " << EventPMTClusterNumber << " " << EventMRDNumber << " " << EventMRDNoVetoNumber << " " + << "\n"; + file.close(); + } + if (filterType == "PMTCluster") + { + cout << "Current Run " << currentRunNumber << endl; + cout << "Filter got " << CurrentExeNumber << " events in total" << endl; // this is the total number of events + cout << "Got " << EventPMTClusterNumber << " events with PMT clusters" << endl; + cout << "Saved " << MRDDataName << " successfully" << endl; + } + if (filterType == "LAPPDTiming") + { + cout << "Filter got " << CurrentExeNumber << " events in total" << endl; // this is the total number of events + cout << "Got " << EventMRDNumber << " events in beamgate window" << endl; + cout << "Saved " << MRDDataName << " successfully" << endl; + } + + if (filterType == "LAPPDPulsedStripNumber") + { + cout << "Filter got " << CurrentExeNumber << " events in total" << endl; // this is the total number of events + cout << "Got " << EventMRDNumber << " events with more than 5 pulsed strips" << endl; + cout << "Saved " << MRDDataName << " successfully" << endl; + } + + return true; +} + +bool ProcessedLAPPDFilter::GotANNIEEventAndSave(BoostStore *BS, string savePath) +{ + std::map> *AuxHitsOriginal = nullptr; + std::map> *HitsOriginal = nullptr; + m_data->Stores["ANNIEEvent"]->Get("AuxHits", AuxHitsOriginal); + m_data->Stores["ANNIEEvent"]->Get("Hits", HitsOriginal); + auto AuxHitsCopy = new std::map>(*AuxHitsOriginal); + auto HitsCopy = new std::map>(*HitsOriginal); + BS->Set("AuxHits", AuxHitsCopy); + BS->Set("Hits", HitsCopy); + + std::map> TDCData; + BeamStatus BeamStatus; + uint64_t CTCTimestamp, RunStartTime; + std::map DataStreams; + uint32_t EventNumber, TriggerWord; + uint64_t EventTimeTank; + TimeClass EventTimeMRD; + std::map MRDLoopbackTDC; + std::string MRDTriggerType; + std::map> RawAcqSize; + std::map>> RecoADCData, RecoAuxADCData; + int PartNumber, RunNumber, RunType, SubrunNumber, TriggerExtended; + TriggerClass TriggerData; + m_data->Stores["ANNIEEvent"]->Get("TDCData", TDCData); + BS->Set("TDCData", TDCData); + m_data->Stores["ANNIEEvent"]->Get("DataStreams", DataStreams); + BS->Set("DataStreams", DataStreams); + m_data->Stores["ANNIEEvent"]->Get("BeamStatus", BeamStatus); + BS->Set("BeamStatus", BeamStatus); + m_data->Stores["ANNIEEvent"]->Get("RunStartTime", RunStartTime); + BS->Set("RunStartTime", RunStartTime); + m_data->Stores["ANNIEEvent"]->Get("EventNumber", EventNumber); + BS->Set("EventNumber", EventNumber); + m_data->Stores["ANNIEEvent"]->Get("TriggerWord", TriggerWord); + BS->Set("TriggerWord", TriggerWord); + m_data->Stores["ANNIEEvent"]->Get("EventTimeMRD", EventTimeMRD); + BS->Set("EventTimeMRD", EventTimeMRD); + m_data->Stores["ANNIEEvent"]->Get("EventTimeTank", EventTimeTank); + BS->Set("EventTimeTank", EventTimeTank); + m_data->Stores["ANNIEEvent"]->Get("MRDLoopbackTDC", MRDLoopbackTDC); + BS->Set("MRDLoopbackTDC", MRDLoopbackTDC); + m_data->Stores["ANNIEEvent"]->Get("MRDTriggerType", MRDTriggerType); + BS->Set("MRDTriggerType", MRDTriggerType); + m_data->Stores["ANNIEEvent"]->Get("RawAcqSize", RawAcqSize); + BS->Set("RawAcqSize", RawAcqSize); + m_data->Stores["ANNIEEvent"]->Get("RecoADCData", RecoADCData); + BS->Set("RecoADCData", RecoADCData); + m_data->Stores["ANNIEEvent"]->Get("RecoAuxADCData", RecoAuxADCData); + BS->Set("RecoAuxADCData", RecoAuxADCData); + m_data->Stores["ANNIEEvent"]->Get("PartNumber", PartNumber); + BS->Set("PartNumber", PartNumber); + m_data->Stores["ANNIEEvent"]->Get("RunNumber", RunNumber); + BS->Set("RunNumber", RunNumber); + m_data->Stores["ANNIEEvent"]->Get("RunType", RunType); + BS->Set("RunType", RunType); + m_data->Stores["ANNIEEvent"]->Get("SubrunNumber", SubrunNumber); + BS->Set("SubrunNumber", SubrunNumber); + m_data->Stores["ANNIEEvent"]->Get("TriggerExtended", TriggerExtended); + BS->Set("TriggerExtended", TriggerExtended); + m_data->Stores["ANNIEEvent"]->Get("TriggerData", TriggerData); + BS->Set("TriggerData", TriggerData); + m_data->Stores["ANNIEEvent"]->Get("CTCTimestamp", CTCTimestamp); + BS->Set("CTCTimestamp", CTCTimestamp); + + std::map GroupedTrigger; + m_data->Stores["ANNIEEvent"]->Get("GroupedTrigger", GroupedTrigger); + BS->Set("GroupedTrigger", GroupedTrigger); + + int PrimaryTriggerWord; + m_data->Stores["ANNIEEvent"]->Get("PrimaryTriggerWord", PrimaryTriggerWord); + BS->Set("PrimaryTriggerWord", PrimaryTriggerWord); + + uint64_t primaryTrigTime; + m_data->Stores["ANNIEEvent"]->Get("PrimaryTriggerTime", primaryTrigTime); + BS->Set("PrimaryTriggerTime", primaryTrigTime); + + bool NCExtended, CCExtended; + m_data->Stores["ANNIEEvent"]->Get("NCExtended", NCExtended); + BS->Set("NCExtended", NCExtended); + m_data->Stores["ANNIEEvent"]->Get("CCExtended", CCExtended); + BS->Set("CCExtended", CCExtended); + + string TriggerType; + m_data->Stores["ANNIEEvent"]->Get("TriggerType", TriggerType); + BS->Set("TriggerType", TriggerType); + + int CTCWordExtended; + m_data->Stores["ANNIEEvent"]->Get("CTCWordExtended", CTCWordExtended); + BS->Set("CTCWordExtended", CTCWordExtended); + + std::map LAPPDDataMap; + std::map LAPPDBeamgate_ns; + std::map LAPPDTimeStamps_ns; // data and key are the same + std::map LAPPDTimeStampsRaw; + std::map LAPPDBeamgatesRaw; + std::map LAPPDOffsets; + std::map LAPPDTSCorrection; + std::map LAPPDBGCorrection; + std::map LAPPDOSInMinusPS; + + m_data->Stores["ANNIEEvent"]->Get("LAPPDDataMap", LAPPDDataMap); + BS->Set("LAPPDDataMap", LAPPDDataMap); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + BS->Set("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); + BS->Set("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStampsRaw", LAPPDTimeStampsRaw); + BS->Set("LAPPDTimeStampsRaw", LAPPDTimeStampsRaw); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgatesRaw", LAPPDBeamgatesRaw); + BS->Set("LAPPDBeamgatesRaw", LAPPDBeamgatesRaw); + m_data->Stores["ANNIEEvent"]->Get("LAPPDOffsets", LAPPDOffsets); + BS->Set("LAPPDOffsets", LAPPDOffsets); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTSCorrection", LAPPDTSCorrection); + BS->Set("LAPPDTSCorrection", LAPPDTSCorrection); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBGCorrection", LAPPDBGCorrection); + BS->Set("LAPPDBGCorrection", LAPPDBGCorrection); + m_data->Stores["ANNIEEvent"]->Get("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + BS->Set("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + + uint64_t beamInfoTime = 0; + int64_t timeDiff = -9999; + double defaultVal = -9999.; + int beam_good = 0; + double E_TOR860, E_TOR875, THCURR, BTJT2, HP875, VP875, HPTG1, VPTG1, HPTG2, VPTG2, BTH2T2; + m_data->Stores["ANNIEEvent"]->Get("BeamInfoTime", beamInfoTime); + BS->Set("BeamInfoTime", beamInfoTime); + m_data->Stores["ANNIEEvent"]->Get("BeamInfoTimeToTriggerDiff", timeDiff); + BS->Set("BeamInfoTimeToTriggerDiff", timeDiff); + m_data->Stores["ANNIEEvent"]->Get("beam_E_TOR860", E_TOR860); + BS->Set("beam_E_TOR860", E_TOR860); + m_data->Stores["ANNIEEvent"]->Get("beam_E_TOR875", E_TOR875); + BS->Set("beam_E_TOR875", E_TOR875); + m_data->Stores["ANNIEEvent"]->Get("beam_THCURR", THCURR); + BS->Set("beam_THCURR", THCURR); + m_data->Stores["ANNIEEvent"]->Get("beam_BTJT2", BTJT2); + BS->Set("beam_BTJT2", BTJT2); + m_data->Stores["ANNIEEvent"]->Get("beam_HP875", HP875); + BS->Set("beam_HP875", HP875); + m_data->Stores["ANNIEEvent"]->Get("beam_VP875", VP875); + BS->Set("beam_VP875", VP875); + m_data->Stores["ANNIEEvent"]->Get("beam_HPTG1", HPTG1); + BS->Set("beam_HPTG1", HPTG1); + m_data->Stores["ANNIEEvent"]->Get("beam_VPTG1", VPTG1); + BS->Set("beam_VPTG1", VPTG1); + m_data->Stores["ANNIEEvent"]->Get("beam_HPTG2", HPTG2); + BS->Set("beam_HPTG2", HPTG2); + m_data->Stores["ANNIEEvent"]->Get("beam_VPTG2", VPTG2); + BS->Set("beam_VPTG2", VPTG2); + m_data->Stores["ANNIEEvent"]->Get("beam_BTH2T2", BTH2T2); + BS->Set("beam_BTH2T2", BTH2T2); + m_data->Stores["ANNIEEvent"]->Get("beam_good", beam_good); + BS->Set("beam_good", beam_good); + + BS->Save(savePath); + if(FilterVerbosity>2) + cout<<"Saved to "<Delete(); + + return true; +} \ No newline at end of file diff --git a/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.h b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.h new file mode 100644 index 000000000..7b7e871cc --- /dev/null +++ b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.h @@ -0,0 +1,77 @@ +#ifndef ProcessedLAPPDFilter_H +#define ProcessedLAPPDFilter_H + +#include +#include + +#include "Tool.h" +#include "PsecData.h" +#include "Waveform.h" +#include "BoostStore.h" +#include "Store.h" +#include "ADCPulse.h" +#include "TimeClass.h" +#include "TriggerClass.h" +#include "ANNIEalgorithms.h" +#include "CalibratedADCWaveform.h" +#include "BeamStatus.h" +#include "Geometry.h" + +/** + * \class ProcessedLAPPDFilter + * + * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. + * + * $Author: B.Richards $ + * $Date: 2019/05/28 10:44:00 $ + * Contact: b.richards@qmul.ac.uk + */ +class ProcessedLAPPDFilter : public Tool +{ + +public: + ProcessedLAPPDFilter(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + + bool GotANNIEEventAndSave(BoostStore *BS, string savePath); + +private: + std::map DataStreams; + + int FilterVerbosity; + + string MRDDataName; + string MRDNoVetoDataName; + string AllLAPPDDataName; + + string filterType; + + BoostStore *FilteredMRD = nullptr; + BoostStore *FilteredMRDNoVeto = nullptr; + BoostStore *FilteredAllLAPPD = nullptr; + + bool gotEventMRD; + bool gotEventMRDNoVeto; + bool gotEventPMTCluster; + + bool saveAllLAPPDEvents; + + int EventMRDNumber; + int EventMRDNoVetoNumber; + int EventPMTClusterNumber; + int CurrentExeNumber; + int pairedEventNumber; + + + + int currentRunNumber; + + double requirePulsedAmp; + int requirePulsedStripNumber; + + +}; + +#endif diff --git a/UserTools/ProcessedLAPPDFilter/README.md b/UserTools/ProcessedLAPPDFilter/README.md new file mode 100644 index 000000000..689d0864f --- /dev/null +++ b/UserTools/ProcessedLAPPDFilter/README.md @@ -0,0 +1,20 @@ +# ProcessedLAPPDFilter + +ProcessedLAPPDFilter + +## Data + +Describe any data formats ProcessedLAPPDFilter creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for ProcessedLAPPDFilter. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/Unity.h b/UserTools/Unity.h index 92a85c89c..577b38609 100644 --- a/UserTools/Unity.h +++ b/UserTools/Unity.h @@ -189,3 +189,4 @@ #include "EBMRD.h" #include "EBSaver.h" #include "ANNIEEventTreeMaker.h" +#include "ProcessedLAPPDFilter.h" diff --git a/configfiles/EventBuilderV2/EBLAPPDConfig b/configfiles/EventBuilderV2/EBLAPPDConfig index b6981cdec..016b554fd 100644 --- a/configfiles/EventBuilderV2/EBLAPPDConfig +++ b/configfiles/EventBuilderV2/EBLAPPDConfig @@ -1,4 +1,4 @@ -verbosityEBLAPPD 5 +verbosityEBLAPPD 1 matchTargetTrigger 14 matchTolerance_ns 400000 #matchTolerance_ns 10000 diff --git a/configfiles/EventBuilderV2/EBLoadRawConfig b/configfiles/EventBuilderV2/EBLoadRawConfig index bae579561..4f5af443e 100644 --- a/configfiles/EventBuilderV2/EBLoadRawConfig +++ b/configfiles/EventBuilderV2/EBLoadRawConfig @@ -1,4 +1,4 @@ -verbosityEBLoadRaw 5 +verbosityEBLoadRaw 2 ReadTriggerOverlap 1 InputFile ./configfiles/EventBuilderV2/list.txt diff --git a/configfiles/EventBuilderV2/EBMRDConfig b/configfiles/EventBuilderV2/EBMRDConfig index 1914f4cc9..331c10f85 100644 --- a/configfiles/EventBuilderV2/EBMRDConfig +++ b/configfiles/EventBuilderV2/EBMRDConfig @@ -1,4 +1,4 @@ -verbosityEBMRD 5 +verbosityEBMRD 1 matchTargetTrigger 8 matchTolerance_ns 3000000 matchToAllTriggers 0 diff --git a/configfiles/EventBuilderV2/EBPMTConfig b/configfiles/EventBuilderV2/EBPMTConfig index f7196af27..bfc7ee9ac 100644 --- a/configfiles/EventBuilderV2/EBPMTConfig +++ b/configfiles/EventBuilderV2/EBPMTConfig @@ -1,4 +1,4 @@ -verbosityEBPMT 3 +verbosityEBPMT 1 matchTargetTrigger 5 matchTolerance_ns 100 matchToAllTriggers 1 diff --git a/configfiles/EventBuilderV2/EBSaverConfig b/configfiles/EventBuilderV2/EBSaverConfig index 23005b942..781d748e2 100644 --- a/configfiles/EventBuilderV2/EBSaverConfig +++ b/configfiles/EventBuilderV2/EBSaverConfig @@ -1,4 +1,4 @@ -verbosityEBSaver 5 +verbosityEBSaver 1 savePMT 1 saveMRD 1 diff --git a/configfiles/EventBuilderV2/EBTriggerGrouperConfig b/configfiles/EventBuilderV2/EBTriggerGrouperConfig index bb80aed08..73cabfe5a 100644 --- a/configfiles/EventBuilderV2/EBTriggerGrouperConfig +++ b/configfiles/EventBuilderV2/EBTriggerGrouperConfig @@ -1,4 +1,4 @@ -verbosityEBTG 3 +verbosityEBTG 1 GroupMode beam GroupTolerance 3000000 GroupTrigWord 14 //undelayed beam diff --git a/configfiles/EventBuilderV2/list.txt b/configfiles/EventBuilderV2/list.txt index cebfc229b..26561a266 100644 --- a/configfiles/EventBuilderV2/list.txt +++ b/configfiles/EventBuilderV2/list.txt @@ -1,2 +1,2 @@ -/pnfs/annie/persistent/raw/raw/4763/RAWDataR4763S0p6 -/pnfs/annie/persistent/raw/raw/4763/RAWDataR4763S0p7 +/pnfs/annie/persistent/raw/raw/4804/RAWDataR4804S0p332 +/pnfs/annie/persistent/raw/raw/4804/RAWDataR4804S0p333 diff --git a/configfiles/LAPPDProcessedAna/ConfigPlot b/configfiles/LAPPDProcessedAna/ConfigPlot index a519d3666..1e79bce72 100755 --- a/configfiles/LAPPDProcessedAna/ConfigPlot +++ b/configfiles/LAPPDProcessedAna/ConfigPlot @@ -85,7 +85,7 @@ useRange -1 #set this to 0 for using pulse start time as the saved pulse time, plusClockBit 0 savePositionOnStrip 1 - +LoadLAPPDMapInfo 1 #LAPPDStackStrip verbosityStackStrip 0 @@ -111,7 +111,6 @@ treeMakerInputHitLabel LAPPDHits treeMakerOutputFileName LAPPDTree.root - #LAPPDPlots LAPPDPlotInputWaveLabel BLsubtractedLAPPDData LAPPDPlotsVerbosity 0 @@ -132,4 +131,3 @@ printLAPPDNumber 1 printEventWaveform 1 - diff --git a/configfiles/LAPPDProcessedAna/ConfigPreProcess b/configfiles/LAPPDProcessedAna/ConfigPreProcess index ee2a71e11..11cb9b98a 100755 --- a/configfiles/LAPPDProcessedAna/ConfigPreProcess +++ b/configfiles/LAPPDProcessedAna/ConfigPreProcess @@ -28,7 +28,7 @@ FindT0Verbosity 0 FindT0InputWavLabel LAPPDWaveforms OneBoardShift 0 OneBoardShiftValue 16 - +LoadLAPPDMap 1 TrigEarlyCut 20 TrigLateCut 200 @@ -41,7 +41,7 @@ T0signalmaxOld 50. #Older data uses a positive going signal T0signalthresholdOld 80. #Older data uses a positive going signal T0offset 0 FindT0OutputWavLabel AlignedLAPPDData -GlobalShiftT0 0 +GlobalShiftT0 80 #Added by Marc Triggerdefault 5 LAPPDOffset 1000 diff --git a/configfiles/LAPPDProcessedAna/ConfigStoreReadIn b/configfiles/LAPPDProcessedAna/ConfigStoreReadIn index d4b3b4e5f..c6f5ddf1c 100755 --- a/configfiles/LAPPDProcessedAna/ConfigStoreReadIn +++ b/configfiles/LAPPDProcessedAna/ConfigStoreReadIn @@ -32,7 +32,7 @@ ReorderVerbosityLevel 0 ReorderInputWavLabel RawLAPPDData ReorderOutputWavLabel LAPPDWaveforms DelayOffset 0 -GlobalShift 150 +GlobalShift 0 ReadStore 0 NUM_VECTOR_DATA 7795 @@ -40,4 +40,4 @@ NUM_VECTOR_PPS 16 OutputWavLabel RawLAPPDData SelectSingleLAPPD false SelectedLAPPD 0 - +LoadLAPPDMap 1 diff --git a/configfiles/LAPPDProcessedAna/Configs b/configfiles/LAPPDProcessedAna/Configs index d83f26fa3..472ab885f 100644 --- a/configfiles/LAPPDProcessedAna/Configs +++ b/configfiles/LAPPDProcessedAna/Configs @@ -21,7 +21,7 @@ stopEntries 10000000000 DoPedSubtraction 1 Nboards 6 #Number of pedestal files to be read in -PedinputfileTXT ../Pedestals/LAPPD645839//P +PedinputfileTXT ../Pedestals/LAPPD645839/P PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 @@ -43,7 +43,7 @@ OutputWavLabel RawLAPPDData SelectSingleLAPPD false SelectedLAPPD 0 loadPSEC 1 -loadPPS 1 +loadPPS 0 loadOffsets 0 num_vector_data 7795 num_vector_pps 16 @@ -54,11 +54,11 @@ LoadHit 1 LoadWaveform 1 LoadLAPPDDataTimeStamp 1 LoadPPSTimestamp 1 -LoadRunInfoRaw 1 -LoadRunInfoANNIEEvent 0 +LoadRunInfoRaw 0 +LoadRunInfoANNIEEvent 1 treeMakerVerbosity 0 - +MultiLAPPDMapTreeMaker 1 treeMakerInputPulseLabel LAPPDPulses treeMakerInputHitLabel LAPPDHits treeMakerOutputFileName LAPPDTree_processedAna.root diff --git a/configfiles/LAPPDProcessedAna/LoadANNIEEventConfig b/configfiles/LAPPDProcessedAna/LoadANNIEEventConfig index b7330eecc..5aa56ef88 100644 --- a/configfiles/LAPPDProcessedAna/LoadANNIEEventConfig +++ b/configfiles/LAPPDProcessedAna/LoadANNIEEventConfig @@ -1,4 +1,4 @@ -verbose 1 +verbose 2 FileForListOfInputs configfiles/LAPPDProcessedAna/list.txt diff --git a/configfiles/LAPPDProcessedAna/ProcessedLAPPDFilterConfig b/configfiles/LAPPDProcessedAna/ProcessedLAPPDFilterConfig new file mode 100644 index 000000000..752200268 --- /dev/null +++ b/configfiles/LAPPDProcessedAna/ProcessedLAPPDFilterConfig @@ -0,0 +1 @@ +verbosity 0 diff --git a/configfiles/LAPPDProcessedAna/ToolChainConfig b/configfiles/LAPPDProcessedAna/ToolChainConfig index b94bec1c3..577961b75 100644 --- a/configfiles/LAPPDProcessedAna/ToolChainConfig +++ b/configfiles/LAPPDProcessedAna/ToolChainConfig @@ -19,6 +19,6 @@ service_kick_sec -1 Tools_File configfiles/LAPPDProcessedAna/ToolsConfig ## list of tools to run and their config files ##### Run Type ##### -Inline -1 ## number of Execute steps in program, -1 infinite loop that is ended by user +Inline 50 ## number of Execute steps in program, -1 infinite loop that is ended by user Interactive 0 ## set to 1 if you want to run the code interactively diff --git a/configfiles/LAPPDProcessedAna/ToolsConfig b/configfiles/LAPPDProcessedAna/ToolsConfig index fbf3f106a..a56fd1db3 100644 --- a/configfiles/LAPPDProcessedAna/ToolsConfig +++ b/configfiles/LAPPDProcessedAna/ToolsConfig @@ -1,5 +1,5 @@ -LoadGeometry LoadGeometry configfiles/LAPPDProcessedAna/ConfigGeo LoadANNIEEvent LoadANNIEEvent configfiles/LAPPDProcessedAna/LoadANNIEEventConfig +LoadGeometry LoadGeometry configfiles/LAPPDProcessedAna/ConfigGeo myTimeClustering TimeClustering configfiles/LAPPDProcessedAna/TimeClusteringConfig myFindMrdTracks FindMrdTracks configfiles/LAPPDProcessedAna/FindMrdTracksConfig diff --git a/configfiles/LAPPDProcessedAna/knownlist b/configfiles/LAPPDProcessedAna/knownlist new file mode 100644 index 000000000..22c51f858 --- /dev/null +++ b/configfiles/LAPPDProcessedAna/knownlist @@ -0,0 +1 @@ +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4843/ProcessedData_PMTMRDLAPPD_R4843S0p5 diff --git a/configfiles/LAPPDProcessedAna/list.txt b/configfiles/LAPPDProcessedAna/list.txt index 91e4e2432..fa6752711 100644 --- a/configfiles/LAPPDProcessedAna/list.txt +++ b/configfiles/LAPPDProcessedAna/list.txt @@ -1,30 +1 @@ -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p1 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p2 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p3 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p4 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p5 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p6 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p7 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p8 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p9 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p10 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p14 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p15 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p16 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p17 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p18 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p19 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p20 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p21 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p22 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p23 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p24 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p25 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p26 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p27 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p28 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p29 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p30 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p31 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p32 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4804/ProcessedData_PMTMRDLAPPD_R4804S0p33 +/exp/annie/app/users/yuefeng/MyForkANNIE/MyForkRewiriting/testPRTA/ToolAnalysis/FilteredAllLAPPDData diff --git a/configfiles/LAPPDProcessedFilter/ClusterClassifiersConfig b/configfiles/LAPPDProcessedFilter/ClusterClassifiersConfig new file mode 100644 index 000000000..752200268 --- /dev/null +++ b/configfiles/LAPPDProcessedFilter/ClusterClassifiersConfig @@ -0,0 +1 @@ +verbosity 0 diff --git a/configfiles/LAPPDProcessedFilter/ClusterFinderConfig b/configfiles/LAPPDProcessedFilter/ClusterFinderConfig new file mode 100644 index 000000000..c25b028f1 --- /dev/null +++ b/configfiles/LAPPDProcessedFilter/ClusterFinderConfig @@ -0,0 +1,12 @@ +# ClusterFinder Config File + +verbosity 0 +HitStore Hits #Either MCHits or Hits (accessed in ANNIEEvent store) +OutputFile BeamRun_ClusterFinder_DefaultOutput #Output root prefix name for the current run +ClusterFindingWindow 40 # in ns, size of the window used to "clusterize" +AcqTimeWindow 70000 # in ns, size of the acquisition window +ClusterIntegrationWindow 40 # in ns, all hits with +/- 1/2 of this window are considered in the cluster +MinHitsPerCluster 10 # group of hits are considered clusters above this amount of hits +end_of_window_time_cut 0.95 # from o to 1, length of the window you want to loop over with respect to acq. window (1 for full window, 0.95 for 95% from the start) +Plots2D 0 #Draw 2D charge-vs-time plots? +ChankeyToPMTIDMap ./configfiles/EventDisplay/Data-RecoEvent/Chankey_WCSimID.dat diff --git a/configfiles/LAPPDProcessedFilter/ConfigGeo b/configfiles/LAPPDProcessedFilter/ConfigGeo new file mode 100644 index 000000000..ffe0ca918 --- /dev/null +++ b/configfiles/LAPPDProcessedFilter/ConfigGeo @@ -0,0 +1,11 @@ +#LoadGeometry +verbosity 0 +LAPPDChannelCount 60 +FACCMRDGeoFile ./configfiles/LoadGeometry/FullMRDGeometry.csv +DetectorGeoFile ./configfiles/LoadGeometry/DetectorGeometrySpecs.csv +LAPPDGeoFile ./configfiles/LAPPDana/LAPPDGeometry.csv +TankPMTGeoFile ./configfiles/LoadGeometry/FullTankPMTGeometry.csv +TankPMTGainFile ./configfiles/LoadGeometry/ChannelSPEGains_BeamRun20192020.csv +AuxiliaryChannelFile ./configfiles/LoadGeometry/AuxChannels.csv +LAPPDMerging 0 + diff --git a/configfiles/LAPPDProcessedFilter/EventSelectorConfig b/configfiles/LAPPDProcessedFilter/EventSelectorConfig new file mode 100644 index 000000000..a711f08bf --- /dev/null +++ b/configfiles/LAPPDProcessedFilter/EventSelectorConfig @@ -0,0 +1,29 @@ +# EventSelector config file + +verbosity 0 +MCPMTVolCut 0 +MCFVCut 0 +MCMRDCut 0 +MCPiKCut 0 +MCIsMuonCut 0 +MCIsElectronCut 0 +MCIsSingleRingCut 0 +MCIsMultiRingCut 0 +MCProjectedMRDHit 0 +MCEnergyCut 0 +Emin 0 #Minimum energy in MeV +Emax 1000 #Maximum energy in MeV +MRDRecoCut 0 +RecoPMTVolCut 0 +RecoFVCut 0 +NHitCut 0 +NHitmin 4 #Minimum number of hit digits +PMTMRDCoincCut 0 +PMTMRDOffset 755 +PromptTrigOnly 0 +TriggerWord -1 +SaveStatusToStore 1 +NoVeto 0 +Veto 0 +ThroughGoing 0 +IsMC 0 #MC or Data? diff --git a/configfiles/LAPPDProcessedFilter/FindMrdTracksConfig b/configfiles/LAPPDProcessedFilter/FindMrdTracksConfig new file mode 100644 index 000000000..5ba5e8f77 --- /dev/null +++ b/configfiles/LAPPDProcessedFilter/FindMrdTracksConfig @@ -0,0 +1,12 @@ +# FindMrdTracks Config File +# all variables retrieved with m_variables.Get() must be defined here! + +verbosity 0 +IsData 1 +OutputDirectory . +OutputFile STEC_MRDTracks_cluster40ns +DrawTruthTracks 0 # whether to add MC Truth track info for drawing in MrdPaddlePlot Tool + ## note you need to run that tool to actually view the tracks! +WriteTracksToFile 0 # should the track information be written to a ROOT-file? +SelectTriggerType 0 #should the loaded data be filtered by trigger type? +TriggerType Beam #options: Cosmic, Beam, No Loopback diff --git a/configfiles/LAPPDProcessedFilter/LoadANNIEEventConfig b/configfiles/LAPPDProcessedFilter/LoadANNIEEventConfig new file mode 100644 index 000000000..03fe45a19 --- /dev/null +++ b/configfiles/LAPPDProcessedFilter/LoadANNIEEventConfig @@ -0,0 +1,6 @@ +verbose 2 + +FileForListOfInputs configfiles/LAPPDProcessedFilter/list.txt + +EventOffset 0 +GlobalEvNr 1 diff --git a/configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig b/configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig new file mode 100644 index 000000000..75d4bf752 --- /dev/null +++ b/configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig @@ -0,0 +1,6 @@ +FilterVerbosity 0 + +saveAllLAPPDEvents 1 +filterType MRDtrack +requirePulsedAmp 15 +requirePulsedStripNumber 7 diff --git a/configfiles/LAPPDProcessedFilter/TimeClusteringConfig b/configfiles/LAPPDProcessedFilter/TimeClusteringConfig new file mode 100644 index 000000000..e778247fc --- /dev/null +++ b/configfiles/LAPPDProcessedFilter/TimeClusteringConfig @@ -0,0 +1,13 @@ +#TimeClustering config file + +verbosity 0 +MinDigitsForTrack 3 +MaxMrdSubEventDuration 30 +MinSubeventTimeSep 30 +MakeMrdDigitTimePlot 0 +LaunchTApplication 0 +IsData 1 +#OutputROOTFile TimeClustering_MRDTest28_cluster40ns +OutputROOTFile STEC_TimeClusteringOut +MapChankey_WCSimID ./configfiles/SimpleTankEnergyCalibrator/MRD_Chankey_WCSimID.dat + diff --git a/configfiles/LAPPDProcessedFilter/ToolChainConfig b/configfiles/LAPPDProcessedFilter/ToolChainConfig new file mode 100644 index 000000000..f0ebd361f --- /dev/null +++ b/configfiles/LAPPDProcessedFilter/ToolChainConfig @@ -0,0 +1,24 @@ + +#ToollChain dynamic setup file + +##### Runtime Paramiters ##### +verbose 1 ## Verbosity level of ToolChain +error_level 0 # 0= do not exit, 1= exit on unhandeled errors only, 2= exit on unhandeled errors and handeled errors +attempt_recover 1 ## 1= will attempt to finalise if an execute fails + +###### Logging ##### +log_mode Interactive # Interactive=cout , Remote= remote logging system "serservice_name Remote_Logging" , Local = local file log; +log_local_path ./log +log_service LogStore + +###### Service discovery ##### Ignore these settings for local analysis +service_publish_sec -1 +service_kick_sec -1 + +##### Tools To Add ##### +Tools_File configfiles/LAPPDProcessedFilter/ToolsConfig ## list of tools to run and their config files + +##### Run Type ##### +Inline -1 ## number of Execute steps in program, -1 infinite loop that is ended by user +Interactive 0 ## set to 1 if you want to run the code interactively + diff --git a/configfiles/LAPPDProcessedFilter/ToolsConfig b/configfiles/LAPPDProcessedFilter/ToolsConfig new file mode 100644 index 000000000..9df8fdad7 --- /dev/null +++ b/configfiles/LAPPDProcessedFilter/ToolsConfig @@ -0,0 +1,13 @@ +LoadANNIEEvent LoadANNIEEvent configfiles/LAPPDProcessedFilter/LoadANNIEEventConfig +LoadGeometry LoadGeometry configfiles/LAPPDProcessedFilter/ConfigGeo + +myTimeClustering TimeClustering configfiles/LAPPDProcessedFilter/TimeClusteringConfig +myFindMrdTracks FindMrdTracks configfiles/LAPPDProcessedFilter/FindMrdTracksConfig +myClusterFinder ClusterFinder ./configfiles/LAPPDProcessedFilter/ClusterFinderConfig +myClusterClassifiers ClusterClassifiers ./configfiles/LAPPDProcessedFilter/ClusterClassifiersConfig +myEventSelector EventSelector ./configfiles/LAPPDProcessedFilter/EventSelectorConfig + + +ProcessedLAPPDFilter ProcessedLAPPDFilter configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig + + diff --git a/configfiles/LAPPDProcessedFilter/list.txt b/configfiles/LAPPDProcessedFilter/list.txt new file mode 100644 index 000000000..d011fc7d5 --- /dev/null +++ b/configfiles/LAPPDProcessedFilter/list.txt @@ -0,0 +1,2 @@ +/exp/annie/app/users/yuefeng/MyForkANNIE/MyForkRewiriting/testPRTA/ToolAnalysis/ProcessedData_PMTMRDLAPPD_R4804S0p332 +/exp/annie/app/users/yuefeng/MyForkANNIE/MyForkRewiriting/testPRTA/ToolAnalysis/ProcessedData_PMTMRDLAPPD_R4804S0p333 From 784035b3d2586062be90d276a2e27191353d7291 Mon Sep 17 00:00:00 2001 From: Yue Date: Tue, 18 Jun 2024 17:47:53 -0500 Subject: [PATCH 044/163] Modify the BeamFetcherV2, add default value for necessery devices in event builder add modifications for building laser events in EBLAPPD add modifications for LAPPDProcessedAna tool chain --- .../BeamFetcherV2/IFBeamDBInterfaceV2.cpp | 74 ++++++++++++++++++- UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.h | 3 + UserTools/EBLAPPD/EBLAPPD.cpp | 6 +- configfiles/EventBuilderV2/EBLAPPDConfig | 2 +- configfiles/LAPPDProcessedAna/ConfigPlot | 3 +- .../LAPPDProcessedAna/LoadANNIEEventConfig | 2 +- configfiles/LAPPDProcessedAna/ToolChainConfig | 2 +- offsetFit_MultipleLAPPD.cpp | 43 +++++------ 8 files changed, 107 insertions(+), 28 deletions(-) diff --git a/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp b/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp index 99e0a5148..c1e65e348 100644 --- a/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp +++ b/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp @@ -16,6 +16,20 @@ IFBeamDBInterfaceV2::IFBeamDBInterfaceV2() fCurl = curl_easy_init(); if (!fCurl) throw std::runtime_error("IFBeamDBInterfaceV2 failed to" " initialize libcurl"); + + // the map include the device name we want to have in the output + requiredDevices = { + {"E:TOR860", "E12"}, + {"E:TOR875", "E12"}, + {"E:THCURR", "KA"}, + {"E:BTJT2", "DegC"}, + {"E:HP875", "mm"}, + {"E:VP875", "mm"}, + {"E:HPTG1", "mm"}, + {"E:VPTG1", "mm"}, + {"E:HPTG2", "mm"}, + {"E:VPTG2", "mm"}, + {"E:BTH2T2", "DegC"}}; } IFBeamDBInterfaceV2::~IFBeamDBInterfaceV2() @@ -237,6 +251,14 @@ IFBeamDBInterfaceV2::ParseDBResponseSingleSpan(const std::string& response) cons unit, timestamp); } + + for (auto &ts : retMap) { + for (auto &dev : requiredDevices) { + if (ts.second.find(dev.first) == ts.second.end()) { + ts.second[dev.first] = BeamDataPoint(-9999, dev.second, ts.first); + } + } + } return retMap; } @@ -281,6 +303,41 @@ IFBeamDBInterfaceV2::ParseDBResponseBundleSpan(const std::string& response) cons timestamp); } + //count the total number of elements in retMap times the number of elements in that element, print the total number + int total = 0; + for (auto &ts : retMap) { + total += ts.second.size(); + } + std::cout << "Total number of elements in retMap: " << total << std::endl; + std::cout << "Size of retMap is " << retMap.size() << std::endl; + + + //check each timestamp in the retMap, to see if it have all the devices in the requiredDevices map keys, if yes, continue + //if not, create entry for that device at retMap[TS], use the data type from the value of requiredDevices + // use value as -9999, unit as doulbe, timestamp = TS + for (auto &ts : retMap) { + /*cout<<"size of this timestamp is "< requiredDevices; protected: /// @brief Create the singleton IFBeamDBInterfaceV2 object diff --git a/UserTools/EBLAPPD/EBLAPPD.cpp b/UserTools/EBLAPPD/EBLAPPD.cpp index a7ee2e6b2..6cf335d23 100644 --- a/UserTools/EBLAPPD/EBLAPPD.cpp +++ b/UserTools/EBLAPPD/EBLAPPD.cpp @@ -84,7 +84,7 @@ bool EBLAPPD::Execute() bool LaserTriggerGroupped = false; m_data->CStore.Get("LaserTriggerGroupped", LaserTriggerGroupped); if (LaserTriggerGroupped) - Matching(47, 46); + Matching(47, 47); else Log("EBLAPPD: LaserTriggerGroupped is false, no laser trigger groupped in the grouper, stop matching", v_message, verbosityEBLAPPD); @@ -116,6 +116,7 @@ bool EBLAPPD::Execute() m_data->CStore.Set("PairedLAPPDTimeStamps", PairedLAPPDTimeStamps); m_data->CStore.Set("PairedLAPPD_TriggerIndex", PairedLAPPD_TriggerIndex); Log("EBLAPPD: Set pairing information to CStore, PairedLAPPDTimeStamps[14] size = " + std::to_string(PairedLAPPDTimeStamps[14].size()), v_message, verbosityEBLAPPD); + Log("EBLAPPD: Set pairing information to CStore, PairedLAPPDTimeStamps[47] size = " + std::to_string(PairedLAPPDTimeStamps[47].size()), v_message, verbosityEBLAPPD); // Set the indexing of buffer m_data->CStore.Set("Buffer_LAPPDTimestamp_ns", Buffer_LAPPDTimestamp_ns); @@ -216,6 +217,7 @@ bool EBLAPPD::LoadLAPPDData() bool EBLAPPD::Matching(int targetTrigger, int matchToTrack) { cout << "\033[1;34m******* EBLAPPD : Matching *******\033[0m" << endl; + Log("EBLAPPD: Matching LAPPD data with target trigger " + std::to_string(targetTrigger) + " in track " + std::to_string(matchToTrack), v_message, verbosityEBLAPPD); std::map>> GroupedTriggersInTotal; // each map is a group of triggers, with the key is the target trigger word m_data->CStore.Get("GroupedTriggersInTotal", GroupedTriggersInTotal); @@ -253,7 +255,7 @@ bool EBLAPPD::Matching(int targetTrigger, int matchToTrack) matchedNumberInTrack.emplace(TrackTriggerWord, 0); if (TrackTriggerWord != matchToTrack && !matchToAllTriggers) { - Log("EBLAPPD: Skipping TrackTriggerWord " + std::to_string(TrackTriggerWord), v_debug, verbosityEBLAPPD); + //Log("EBLAPPD: Skipping TrackTriggerWord " + std::to_string(TrackTriggerWord), v_debug, verbosityEBLAPPD); continue; } vector> GroupedTriggers = pair.second; diff --git a/configfiles/EventBuilderV2/EBLAPPDConfig b/configfiles/EventBuilderV2/EBLAPPDConfig index 016b554fd..b6981cdec 100644 --- a/configfiles/EventBuilderV2/EBLAPPDConfig +++ b/configfiles/EventBuilderV2/EBLAPPDConfig @@ -1,4 +1,4 @@ -verbosityEBLAPPD 1 +verbosityEBLAPPD 5 matchTargetTrigger 14 matchTolerance_ns 400000 #matchTolerance_ns 10000 diff --git a/configfiles/LAPPDProcessedAna/ConfigPlot b/configfiles/LAPPDProcessedAna/ConfigPlot index 1e79bce72..f20bafc4b 100755 --- a/configfiles/LAPPDProcessedAna/ConfigPlot +++ b/configfiles/LAPPDProcessedAna/ConfigPlot @@ -112,7 +112,8 @@ treeMakerOutputFileName LAPPDTree.root #LAPPDPlots -LAPPDPlotInputWaveLabel BLsubtractedLAPPDData +#LAPPDPlotInputWaveLabel BLsubtractedLAPPDData +LAPPDPlotInputWaveLabel LAPPDWaveforms LAPPDPlotsVerbosity 0 CanvasXSubPlotNumber 2 CanvasYSubPlotNumber 2 diff --git a/configfiles/LAPPDProcessedAna/LoadANNIEEventConfig b/configfiles/LAPPDProcessedAna/LoadANNIEEventConfig index 5aa56ef88..b7330eecc 100644 --- a/configfiles/LAPPDProcessedAna/LoadANNIEEventConfig +++ b/configfiles/LAPPDProcessedAna/LoadANNIEEventConfig @@ -1,4 +1,4 @@ -verbose 2 +verbose 1 FileForListOfInputs configfiles/LAPPDProcessedAna/list.txt diff --git a/configfiles/LAPPDProcessedAna/ToolChainConfig b/configfiles/LAPPDProcessedAna/ToolChainConfig index 577961b75..b94bec1c3 100644 --- a/configfiles/LAPPDProcessedAna/ToolChainConfig +++ b/configfiles/LAPPDProcessedAna/ToolChainConfig @@ -19,6 +19,6 @@ service_kick_sec -1 Tools_File configfiles/LAPPDProcessedAna/ToolsConfig ## list of tools to run and their config files ##### Run Type ##### -Inline 50 ## number of Execute steps in program, -1 infinite loop that is ended by user +Inline -1 ## number of Execute steps in program, -1 infinite loop that is ended by user Interactive 0 ## set to 1 if you want to run the code interactively diff --git a/offsetFit_MultipleLAPPD.cpp b/offsetFit_MultipleLAPPD.cpp index abeca9673..7cad5de6b 100644 --- a/offsetFit_MultipleLAPPD.cpp +++ b/offsetFit_MultipleLAPPD.cpp @@ -99,21 +99,23 @@ vector> fitInThisReset( std::cout << "True PPS interval in ps is " << trueInterval << std::endl; delete gausf; delete h; - // initialize variables need for fitting int orphanCount = 0; // count the number that how many data event timestamp doesn't matched to a target trigger within an interval. - std::map>> DerivationMap; + cout << "LAPPD_PPS.size() " << LAPPD_PPS.size() << " CTCPPS.size() " << CTCPPS.size() << endl; for (int i = 0; i < LAPPD_PPS.size(); i++) { - if (i % static_cast(LAPPD_PPS.size() / 5) == 0) - cout << "Fitting PPS " << i << " of " << LAPPD_PPS.size() << endl; - + if (i > 5) + { + if (i % static_cast(LAPPD_PPS.size() / 5) == 0) + cout << "Fitting PPS " << i << " of " << LAPPD_PPS.size() << endl; + } ULong64_t LAPPD_PPS_ns = LAPPD_PPS.at(i) / 1000; ULong64_t LAPPD_PPS_truncated_ps = LAPPD_PPS.at(i) % 1000; for (int j = 0; j < CTCPPS.size(); j++) { + vector diffSum; ULong64_t offsetNow_ns = 0; if (drift == 0) @@ -295,7 +297,6 @@ vector> fitInThisReset( } } } - // finish matching, found the minimum mean_dev in the map, extract the matching information double min_mean_dev = std::numeric_limits::max(); int final_i = 0; @@ -306,7 +307,6 @@ vector> fitInThisReset( vector final_notOrphanIndex; vector final_ctcPairedIndex; vector final_ctcOrphanIndex; - for (const auto &minIter : DerivationMap) { if (minIter.first > 10 && minIter.first < min_mean_dev) @@ -420,9 +420,10 @@ vector> fitInThisReset( missingPTicks = intervalTicks - pInterval; else if (pInterval < 30) missingPTicks = -pInterval; -////// - if(missingPTicks == 1 || missingPTicks == -1){ - cout<<"Found missing tick is "<> fitInThisReset( { if (LAPPD_PPS.at(i) / 3125 < LAPPDDataTimeStampUL.at(l) / 3125 && LAPPD_PPS.at(i + 1) / 3125 > LAPPDDataTimeStampUL.at(l) / 3125) { - TimeStamp_correction_tick.push_back(PPS_tick_correction.at(i)+1000); + TimeStamp_correction_tick.push_back(PPS_tick_correction.at(i) + 1000); TSFound = true; break; } } if (!TSFound && LAPPDDataTimeStampUL.at(l) / 3125 > LAPPD_PPS.at(LAPPD_PPS.size() - 1) / 3125) { - TimeStamp_correction_tick.push_back(PPS_tick_correction.at(LAPPD_PPS.size() - 1)+1000); + TimeStamp_correction_tick.push_back(PPS_tick_correction.at(LAPPD_PPS.size() - 1) + 1000); TSFound = true; } if (!TSFound && LAPPDDataTimeStampUL.at(l) / 3125 < LAPPD_PPS.at(0) / 3125) { - TimeStamp_correction_tick.push_back(0+1000); + TimeStamp_correction_tick.push_back(0 + 1000); TSFound = true; } @@ -524,10 +525,10 @@ vector> fitInThisReset( { if (LAPPD_PPS.at(i) / 3125 < LAPPDDataBeamgateUL.at(l) / 3125 && LAPPD_PPS.at(i + 1) / 3125 > LAPPDDataBeamgateUL.at(l) / 3125) { - BeamGate_correction_tick.push_back(PPS_tick_correction.at(i)+1000); + BeamGate_correction_tick.push_back(PPS_tick_correction.at(i) + 1000); BGFound = true; cout << "Normal push: BGraw = " << LAPPDDataBeamgateUL.at(l) / 3125 << ", pps = " << LAPPD_PPS.at(i) << ", pps/3125 = " << LAPPD_PPS.at(i) / 3125 << endl; - if(LAPPD_PPS_interval_ticks.at(i) != intervalTicks) + if (LAPPD_PPS_interval_ticks.at(i) != intervalTicks) { cout << "Warning: PPS interval is not " << intervalTicks << " at index " << i << ", it is " << LAPPD_PPS_interval_ticks.at(i) << endl; } @@ -536,13 +537,13 @@ vector> fitInThisReset( } if (!BGFound && LAPPDDataBeamgateUL.at(l) / 3125 > LAPPD_PPS.at(LAPPD_PPS.size() - 1) / 3125) { - BeamGate_correction_tick.push_back(PPS_tick_correction.at(LAPPD_PPS.size() - 1)+1000); + BeamGate_correction_tick.push_back(PPS_tick_correction.at(LAPPD_PPS.size() - 1) + 1000); cout << "BGraw = " << LAPPDDataBeamgateUL.at(l) / 3125 << ", pps = " << LAPPD_PPS.at(LAPPD_PPS.size() - 1) << ", pps/3125 = " << LAPPD_PPS.at(LAPPD_PPS.size() - 1) / 3125 << endl; BGFound = true; } if (!BGFound && LAPPDDataBeamgateUL.at(l) / 3125 < LAPPD_PPS.at(0) / 3125) { - BeamGate_correction_tick.push_back(0+1000); + BeamGate_correction_tick.push_back(0 + 1000); cout << "BGraw less than pps0" << endl; BGFound = true; } @@ -796,9 +797,9 @@ vector> fitInPartFile(TTree *lappdTree, TTree *triggerTree, in vector> ResultTotal; if (LAPPDDataTimeStampUL.size() == LAPPDDataBeamgateUL.size()) { - if(LAPPD_PPS0.size() == 0 || LAPPD_PPS1.size() == 0 ) + if (LAPPD_PPS0.size() == 0 || LAPPD_PPS1.size() == 0) { - cout<<"Error: PPS0 or PPS1 is empty, return empty result."<> ResultACDC0 = fitInThisReset(LAPPDDataTimeStampUL, LAPPDDataBeamgateUL, LAPPD_PPS0, fitTargetTriggerWord, CTCTargetTimeStamp, CTCPPSTimeStamp, intervalInSecond * 1E9 * 1000); @@ -1030,7 +1031,7 @@ void offsetFit_MultipleLAPPD(string fileName, int fitTargetTriggerWord, bool tri string key = it->first; vector> Result = it->second; - if(Result.size()==0) + if (Result.size() == 0) continue; runNumber_out = std::stoi(key.substr(0, key.find("_"))); @@ -1056,7 +1057,7 @@ void offsetFit_MultipleLAPPD(string fileName, int fitTargetTriggerWord, bool tri long long BGTdiff = Result[4][j] - Result[10][j] - 325250; // cout<<"BGTDiff: "< Date: Wed, 19 Jun 2024 17:17:43 -0500 Subject: [PATCH 045/163] Debug for LAPPDPlots, adjust the board ID - LAPPD ID - channel number mapping update print out for LAPPD data filter update LAPPDProcessedAna toolchain config Changes to be committed: modified: UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp modified: UserTools/LAPPDPlots/LAPPDPlots.cpp modified: UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp modified: UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.h modified: configfiles/LAPPDProcessedAna/ConfigPlot modified: configfiles/LAPPDProcessedAna/Configs modified: configfiles/LAPPDProcessedAna/ToolChainConfig modified: configfiles/LAPPDProcessedFilter/LoadANNIEEventConfig modified: configfiles/LAPPDProcessedFilter/list.txt --- UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp | 10 +- UserTools/LAPPDPlots/LAPPDPlots.cpp | 98 ++++-- .../ProcessedLAPPDFilter.cpp | 45 ++- .../ProcessedLAPPDFilter.h | 1 + configfiles/LAPPDProcessedAna/ConfigPlot | 8 +- configfiles/LAPPDProcessedAna/Configs | 2 +- configfiles/LAPPDProcessedAna/ToolChainConfig | 2 +- .../LAPPDProcessedFilter/LoadANNIEEventConfig | 2 +- configfiles/LAPPDProcessedFilter/list.txt | 302 +++++++++++++++++- 9 files changed, 416 insertions(+), 54 deletions(-) diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp index fbb392c93..e6b5f906e 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp @@ -1032,7 +1032,7 @@ bool LAPPDLoadStore::ParsePSECData() int bi = ParaBoards.at(i) % 2; Parse_buffer.clear(); if (LAPPDStoreReadInVerbosity > 2) - std::cout << "Parsing board " << ReadBoards[bi] << std::endl; + std::cout << "Parsing board with ReadBoards ID" << ReadBoards[bi] << std::endl; // Go over all ACDC board data frames by seperating them int frametype = static_cast(Raw_buffer.size() / ReadBoards.size()); for (int c = bi * frametype; c < (bi + 1) * frametype; c++) @@ -1101,11 +1101,16 @@ bool LAPPDLoadStore::DoPedestalSubtract() for (std::map>::iterator it = data.begin(); it != data.end(); ++it) // looping over the data map by channel number, from 0 to 60 { int wrongPedChannel = 0; + if(LAPPDStoreReadInVerbosity>5) + cout<<"Do Pedestal sub at Channel "<first; + for (int kvec = 0; kvec < it->second.size(); kvec++) { // loop all data point in this channel if (DoPedSubtract == 1) { auto iter = PedestalValues->find((it->first)); + if(kvec==0) + cout<first<<" with value = "<second.at(0); if (iter != PedestalValues->end() && iter->second.size() > kvec) { pedval = iter->second.at(kvec); @@ -1122,6 +1127,8 @@ bool LAPPDLoadStore::DoPedestalSubtract() } val = it->second.at(kvec); tmpWave.PushSample(0.3 * (double)(val - pedval)); + if(LAPPDStoreReadInVerbosity>5 && kvec<10) + cout<<", "<first channel" << it->first << ", LAPPD channel shift " << LAPPD_ID * 60 << endl; @@ -1130,6 +1137,7 @@ bool LAPPDLoadStore::DoPedestalSubtract() unsigned long pushChannelNo = (unsigned long)it->first; LAPPDWaveforms.insert(pair>>(pushChannelNo, VecTmpWave)); + cout<<", Pushed to LAPPDWaveforms with channel number "<Stores["ANNIEEvent"]->Get("ACDCReadedLAPPDID", ACDCReadedLAPPDID); m_data->Stores["ANNIEEvent"]->Get("LAPPD_IDs", LAPPD_IDs); - if (ACDCReadedLAPPDID.size() > 2) - { - CanvasXSubPlotNumber = static_cast(ACDCReadedLAPPDID.size()); - CanvasTotalSubPlotNumber = CanvasXSubPlotNumber * CanvasYSubPlotNumber; - } + // if (ACDCReadedLAPPDID.size() > 2) + //{ + CanvasXSubPlotNumber = static_cast(ACDCReadedLAPPDID.size()); + CanvasTotalSubPlotNumber = CanvasXSubPlotNumber * CanvasYSubPlotNumber; + //} c->Clear(); c->Divide(CanvasXSubPlotNumber, CanvasYSubPlotNumber); @@ -119,23 +119,53 @@ bool LAPPDPlots::Execute() bool gotdata = m_data->Stores["ANNIEEvent"]->Get(LAPPDPlotInputWaveLabel, lappddata); m_data->Stores["ANNIEEvent"]->Get("ACDCboards", ReadBoards); + cout << "LAPPDPlots, got ACDCboards size = " << ReadBoards.size() << " with id = "; + for (auto i : ReadBoards) + cout << i << " "; + cout << endl; + m_data->CStore.Get("LAPPD_ID", LAPPD_ID); + cout << "ACDCReadedLAPPDID size = " << ACDCReadedLAPPDID.size() << ": "; + for (auto i : ACDCReadedLAPPDID) + cout << i << " "; + cout << endl; + + vector drawPositions = ACDCReadedLAPPDID; + int minID = *min_element(ACDCReadedLAPPDID.begin(), ACDCReadedLAPPDID.end()); + for (int i = 0; i < drawPositions.size(); i++) + { + drawPositions.at(i) = (drawPositions.at(i) - minID) * 2 + 1; + if (i % 2 == 1) + drawPositions.at(i) = drawPositions.at(i) + 1; + } + cout << "drawPositions size = " << drawPositions.size() << ": "; + for (auto i : drawPositions) + cout << i << " "; + cout << endl; + + vector drawBoardID = ACDCReadedLAPPDID; + for (int i = 0; i < drawBoardID.size(); i++) + { + drawBoardID.at(i) = drawBoardID.at(i) * 2; + if (i % 2 == 1) + drawBoardID.at(i) = (drawBoardID.at(i) + 1); + } + cout << "drawBoardID size = " << drawBoardID.size() << ": "; + for (auto i : drawBoardID) + cout << i << " "; + cout << endl; if (LAPPDPlotsVerbosity > 0) - cout << "LAPPDPlots execute with data " << LAPPDPlotInputWaveLabel << ", got data " << gotdata << ", data size " << lappddata.size() << ", Boards number" << ReadBoards.size() << ", ID " << LAPPD_ID << endl; + cout << "LAPPDPlots execute with data " << LAPPDPlotInputWaveLabel << ", got data " << gotdata << ", data size " << lappddata.size() << ", Board IDs size " << ReadBoards.size() << ", (single) ID " << LAPPD_ID << endl; if (DrawEventWaveform) { vector DrawPosition = {Side0EventWaveformDrawPosition, Side1EventWaveformDrawPosition}; - if (ReadBoards.size() > DrawPosition.size()) + if (ACDCReadedLAPPDID.size() > DrawPosition.size()) { - DrawPosition.clear(); - for (int i = 0; i < ReadBoards.size(); i++) - { - DrawPosition.push_back(ReadBoards.at(i) + 1); - } + DrawPosition = drawPositions; } - for (int i = 0; i < ReadBoards.size(); i++) + for (int i = 0; i < drawBoardID.size(); i++) { const int drawPosition = DrawPosition[i]; TPad *p = (TPad *)c->cd(drawPosition); @@ -146,9 +176,9 @@ bool LAPPDPlots::Execute() p->SetTopMargin(canvasMargin); p->SetBottomMargin(canvasMargin); if (LAPPDPlotsVerbosity > 0) - cout << "Drawing board " << ReadBoards[i] << " at position " << DrawPosition[i] << " start" << endl; - std::map>> boarddata = GetDataForBoard(ReadBoards[i]); - TString HistoName = "Event" + TString::Itoa(eventNumber, 10) + "_B" + ReadBoards[i] + "_ID" + LAPPD_ID; + cout << "Drawing board " << drawBoardID[i] << " at canvas position " << drawPosition << " start" << endl; + std::map>> boarddata = GetDataForBoard(drawBoardID[i]); + TString HistoName = "Event" + TString::Itoa(eventNumber, 10) + "_B" + drawBoardID[i] + "_ID" + ACDCReadedLAPPDID[i]; // convert BGTiming to string and add to HistoName // if (OnlyDrawInBeamWindow) HistoName += "_BG" + TString::Itoa(BGTiming, 10); @@ -171,7 +201,7 @@ bool LAPPDPlots::Execute() Channel *ch = _geom->GetChannel(channelNo); int stripNo = ch->GetStripNum(); if (LAPPDPlotsVerbosity > 3) - cout << "Drawing channel " << originalChannelNo << " as channelNo" << channelNo << " strip " << stripNo << ", with sample size " << w.GetSamples()->size() << endl; + cout << "Drawing channel " << originalChannelNo << " as channelNo " << channelNo << " strip " << stripNo << ", with sample size " << w.GetSamples()->size() <<", data at bin 0 = "<<-w.GetSamples()->at(0)<size(); i++) { h->SetBinContent(i, stripNo + 1, -w.GetSamples()->at(i)); + if(i<5) cout<<-w.GetSamples()->at(i)<<", "; } } if (LAPPDPlotsVerbosity > 3) - cout << "Finish Drawing event waveform" << endl; + cout << " Finish Drawing event waveform" << endl; h->SetMaximum(drawHighThreshold); h->SetMinimum(drawLowThreshold); h->SetStats(0); - h->GetXaxis()->SetTitle("Time (ns)"); + h->GetXaxis()->SetTitle("Time (0.1ns)"); h->GetXaxis()->SetTitleSize(titleSize); h->GetXaxis()->SetTitleOffset(canvasTitleOffset); h->GetYaxis()->SetTitle("Strip Number"); @@ -199,7 +230,7 @@ bool LAPPDPlots::Execute() f->cd(); h->Write(); if (LAPPDPlotsVerbosity > 0) - cout << "Drawing board " << ReadBoards[i] << " finished for Draw Event waveform" << endl; + cout << "Drawing board " << drawBoardID[i] << " finished for Draw Event waveform" << endl; } } @@ -207,15 +238,15 @@ bool LAPPDPlots::Execute() { vector DrawPositionBinHist = {Side0BinDrawPosition, Side1BinDrawPosition}; - if (ReadBoards.size() > DrawPositionBinHist.size()) + if (drawBoardID.size() > DrawPositionBinHist.size()) { DrawPositionBinHist.clear(); - for (int i = 0; i < ReadBoards.size(); i++) + for (int i = 0; i < drawBoardID.size(); i++) { - DrawPositionBinHist.push_back(ReadBoards.at(i) + CanvasXSubPlotNumber + 1); + DrawPositionBinHist.push_back(drawBoardID.at(i) + CanvasXSubPlotNumber); } } - for (int i = 0; i < ReadBoards.size(); i++) + for (int i = 0; i < drawBoardID.size(); i++) { const int drawPosition = DrawPositionBinHist[i]; TPad *p = (TPad *)c->cd(drawPosition); @@ -226,9 +257,9 @@ bool LAPPDPlots::Execute() p->SetTopMargin(canvasMargin); p->SetBottomMargin(canvasMargin); if (LAPPDPlotsVerbosity > 0) - cout << "Drawing board " << ReadBoards[i] << " at position " << DrawPositionBinHist[i] << " start" << endl; - std::map>> boarddata = GetDataForBoard(ReadBoards[i]); - TString HistoName = "Event" + TString::Itoa(eventNumber, 10) + "_Bin_B" + ReadBoards[i] + "_ID" + LAPPD_ID; + cout << "Drawing board " << drawBoardID[i] << " at position " << DrawPositionBinHist[i] << " start" << endl; + std::map>> boarddata = GetDataForBoard(drawBoardID[i]); + TString HistoName = "Event" + TString::Itoa(eventNumber, 10) + "_Bin_B" + drawBoardID[i] + "_ID" + ACDCReadedLAPPDID[i]; // convert BGTiming to string and add to HistoName // if (OnlyDrawInBeamWindow) HistoName += "_BG" + TString::Itoa(BGTiming, 10); @@ -279,7 +310,7 @@ bool LAPPDPlots::Execute() f->cd(); h->Write(); if (LAPPDPlotsVerbosity > 0) - cout << "Drawing board " << ReadBoards[i] << ", i=" << i << " in " << ReadBoards.size() << " finished for Draw Bin Hist" << endl; + cout << "Drawing board " << drawBoardID[i] << ", i=" << i << " in " << drawBoardID.size() << " finished for Draw Bin Hist" << endl; } } @@ -307,10 +338,10 @@ bool LAPPDPlots::Execute() savedBoard.push_back(0); } - for (int i = 0; i < ReadBoards.size(); i++) + for (int i = 0; i < drawBoardID.size(); i++) { // data on board i, in key as channel number - std::map>> boarddata = GetDataForBoard(ReadBoards[i]); + std::map>> boarddata = GetDataForBoard(drawBoardID[i]); std::map>>::iterator it; for (it = boarddata.begin(); it != boarddata.end(); it++) { @@ -337,7 +368,7 @@ bool LAPPDPlots::Execute() if (LAPPDPlotsVerbosity > 0) cout << "Saved waveform " << endl; - savedBoard[ReadBoards[i]] = 1; + savedBoard[drawBoardID[i]] = 1; } } } @@ -403,16 +434,15 @@ std::map>> LAPPDPlots::GetDataForBoard(in int stripSide = ch->GetStripSide(); int thisLAPPDID = static_cast((channelNo % 1000) / 60); - int beginningBoardIDofThisLAPPDID = ReadBoards.at(std::distance(ACDCReadedLAPPDID.begin(), std::find(ACDCReadedLAPPDID.begin(), ACDCReadedLAPPDID.end(), thisLAPPDID))); - int targetLAPPDID = static_cast(boardID / 2) * 2; + int targetLAPPDID = static_cast(boardID / 2); if (LoadLAPPDMap) { targetLAPPDID = thisLAPPDID; } if (LAPPDPlotsVerbosity > 4) - cout << "GetData, channelNo: " << channelNo << ", side number" << stripSide << ", boardID " << boardID << ", targetLAPPDID " << targetLAPPDID << endl; + cout << "GetData, channelNo: " << channelNo << ", side number" << stripSide << ", with input boardID " << boardID << ", targetLAPPDID " << targetLAPPDID << endl; if (static_cast((channelNo % 1000) / 60) == targetLAPPDID && stripSide == boardID % 2) { diff --git a/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp index 304b0a4b6..105d9669c 100644 --- a/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp +++ b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp @@ -31,8 +31,8 @@ bool ProcessedLAPPDFilter::Initialise(std::string configfile, DataModel &data) AllLAPPDDataName = "FilteredAllLAPPDData"; m_variables.Get("AllLAPPDDataName", AllLAPPDDataName); - filterType = "MRDtrack"; //MRDtrack and pmt cluster - //filterType = "PMTCluster"; // pmt cluster only + filterType = "MRDtrack"; // MRDtrack and pmt cluster + // filterType = "PMTCluster"; // pmt cluster only m_variables.Get("filterType", filterType); FilteredMRD = new BoostStore(false, 2); // all events with MRD in it //if gotEventMRD = true; @@ -48,6 +48,7 @@ bool ProcessedLAPPDFilter::Initialise(std::string configfile, DataModel &data) EventMRDNoVetoNumber = 0; CurrentExeNumber = 0; pairedEventNumber = 0; + PsecDataNumber = 0; return true; } @@ -57,7 +58,6 @@ bool ProcessedLAPPDFilter::Execute() m_data->Stores.at("ANNIEEvent")->Get("DataStreams", DataStreams); - if (FilterVerbosity > 2) { for (auto it = DataStreams.begin(); it != DataStreams.end(); ++it) @@ -72,14 +72,19 @@ bool ProcessedLAPPDFilter::Execute() return true; } - if (filterType == "MRDtrack") { CurrentExeNumber += 1; + gotEventMRD = false; gotEventPMTCluster = false; + std::map LAPPDBeamgate_ns; + m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + PsecDataNumber += LAPPDBeamgate_ns.size(); + m_data->Stores["ANNIEEvent"]->Set("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + std::map> *m_all_clusters = nullptr; bool get_clusters = m_data->CStore.Get("ClusterMap", m_all_clusters); if (!get_clusters) @@ -107,7 +112,7 @@ bool ProcessedLAPPDFilter::Execute() return false; } - if(saveAllLAPPDEvents) + if (saveAllLAPPDEvents) { GotANNIEEventAndSave(FilteredAllLAPPD, AllLAPPDDataName); } @@ -132,9 +137,9 @@ bool ProcessedLAPPDFilter::Execute() } } - if (CurrentExeNumber % 50 == 0) + if (CurrentExeNumber % 10 == 0) { - cout << "Filter event number: " << CurrentExeNumber << ", events with PMT clusters: " << EventPMTClusterNumber << ", also with MRD tracks: " << EventMRDNumber << ", also with MRD tracks and no veto: " << EventMRDNoVetoNumber << endl; + cout << "Filter event number: " << CurrentExeNumber << ", PsecDataNumber " << PsecDataNumber << ", events with PMT clusters: " << EventPMTClusterNumber << ", also with MRD tracks: " << EventMRDNumber << ", also with MRD tracks and no veto: " << EventMRDNoVetoNumber << endl; } m_data->Stores["ANNIEEvent"]->Get("RunNumber", currentRunNumber); @@ -144,6 +149,9 @@ bool ProcessedLAPPDFilter::Execute() if (filterType == "PMTCluster") { CurrentExeNumber += 1; + std::map LAPPDBeamgate_ns; + m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + PsecDataNumber += LAPPDBeamgate_ns.size(); gotEventPMTCluster = false; @@ -165,7 +173,7 @@ bool ProcessedLAPPDFilter::Execute() GotANNIEEventAndSave(FilteredMRD, MRDDataName); if (CurrentExeNumber % 50 == 0) { - cout << "Filter event number: " << CurrentExeNumber << ", events with PMT clusters: " << EventPMTClusterNumber << endl; + cout << "Filter event number: " << CurrentExeNumber << ", PsecDataNumber " << PsecDataNumber << ", events with PMT clusters: " << EventPMTClusterNumber << endl; } m_data->Stores["ANNIEEvent"]->Get("RunNumber", currentRunNumber); @@ -218,12 +226,12 @@ bool ProcessedLAPPDFilter::Finalise() FilteredMRD->Delete(); FilteredMRDNoVeto->Delete(); FilteredAllLAPPD->Delete(); - if (filterType == "MRDtrack") { cout << "Current Run " << currentRunNumber << endl; cout << "Filter got " << CurrentExeNumber << " events in total" << endl; // this is the total number of events + cout << "Got " << PsecDataNumber << " psec data objects on all LAPPD"<Set("beam_good", beam_good); BS->Save(savePath); - if(FilterVerbosity>2) - cout<<"Saved to "< 2) + cout << "Saved to " << savePath << " successfully" << endl; BS->Delete(); + // removd and clean the data pointers from here + /* std::map> *AuxHitsOriginal = nullptr; + std::map> *HitsOriginal = nullptr; + m_data->Stores["ANNIEEvent"]->Get("AuxHits", AuxHitsOriginal); + m_data->Stores["ANNIEEvent"]->Get("Hits", HitsOriginal); + auto AuxHitsCopy = new std::map>(*AuxHitsOriginal); + auto HitsCopy = new std::map>(*HitsOriginal); + BS->Set("AuxHits", AuxHitsCopy); + BS->Set("Hits", HitsCopy); + + AuxHitsCopy->clear(); + HitsCopy->clear(); + delete AuxHitsCopy; + delete HitsCopy;*/ + return true; } \ No newline at end of file diff --git a/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.h b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.h index 7b7e871cc..684585554 100644 --- a/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.h +++ b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.h @@ -63,6 +63,7 @@ class ProcessedLAPPDFilter : public Tool int EventPMTClusterNumber; int CurrentExeNumber; int pairedEventNumber; + int PsecDataNumber; diff --git a/configfiles/LAPPDProcessedAna/ConfigPlot b/configfiles/LAPPDProcessedAna/ConfigPlot index f20bafc4b..60a9a15d8 100755 --- a/configfiles/LAPPDProcessedAna/ConfigPlot +++ b/configfiles/LAPPDProcessedAna/ConfigPlot @@ -112,9 +112,11 @@ treeMakerOutputFileName LAPPDTree.root #LAPPDPlots -#LAPPDPlotInputWaveLabel BLsubtractedLAPPDData -LAPPDPlotInputWaveLabel LAPPDWaveforms -LAPPDPlotsVerbosity 0 +LAPPDPlotInputWaveLabel BLsubtractedLAPPDData +#LAPPDPlotInputWaveLabel LAPPDWaveforms +#LAPPDPlotInputWaveLabel AlignedLAPPDData +#LAPPDPlotInputWaveLabel RawLAPPDData +LAPPDPlotsVerbosity 5 CanvasXSubPlotNumber 2 CanvasYSubPlotNumber 2 canvasMargin 0.1 diff --git a/configfiles/LAPPDProcessedAna/Configs b/configfiles/LAPPDProcessedAna/Configs index 472ab885f..e306132d2 100644 --- a/configfiles/LAPPDProcessedAna/Configs +++ b/configfiles/LAPPDProcessedAna/Configs @@ -8,7 +8,7 @@ NUM_VECTOR_METADATA 103 #Fixed META vector size LAPPDchannelOffset 1000 NChannels 30 -LAPPDStoreReadInVerbosity 0 +LAPPDStoreReadInVerbosity 10 mergingModeReadIn 0 RawDataInputWavLabel RawWaveform diff --git a/configfiles/LAPPDProcessedAna/ToolChainConfig b/configfiles/LAPPDProcessedAna/ToolChainConfig index b94bec1c3..15e9f5283 100644 --- a/configfiles/LAPPDProcessedAna/ToolChainConfig +++ b/configfiles/LAPPDProcessedAna/ToolChainConfig @@ -19,6 +19,6 @@ service_kick_sec -1 Tools_File configfiles/LAPPDProcessedAna/ToolsConfig ## list of tools to run and their config files ##### Run Type ##### -Inline -1 ## number of Execute steps in program, -1 infinite loop that is ended by user +Inline 100 ## number of Execute steps in program, -1 infinite loop that is ended by user Interactive 0 ## set to 1 if you want to run the code interactively diff --git a/configfiles/LAPPDProcessedFilter/LoadANNIEEventConfig b/configfiles/LAPPDProcessedFilter/LoadANNIEEventConfig index 03fe45a19..ad0298064 100644 --- a/configfiles/LAPPDProcessedFilter/LoadANNIEEventConfig +++ b/configfiles/LAPPDProcessedFilter/LoadANNIEEventConfig @@ -1,4 +1,4 @@ -verbose 2 +verbose 1 FileForListOfInputs configfiles/LAPPDProcessedFilter/list.txt diff --git a/configfiles/LAPPDProcessedFilter/list.txt b/configfiles/LAPPDProcessedFilter/list.txt index d011fc7d5..dc3e96f2e 100644 --- a/configfiles/LAPPDProcessedFilter/list.txt +++ b/configfiles/LAPPDProcessedFilter/list.txt @@ -1,2 +1,300 @@ -/exp/annie/app/users/yuefeng/MyForkANNIE/MyForkRewiriting/testPRTA/ToolAnalysis/ProcessedData_PMTMRDLAPPD_R4804S0p332 -/exp/annie/app/users/yuefeng/MyForkANNIE/MyForkRewiriting/testPRTA/ToolAnalysis/ProcessedData_PMTMRDLAPPD_R4804S0p333 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p2 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p3 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p4 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p5 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p6 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p7 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p8 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p9 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p10 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p11 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p12 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p13 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p14 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p15 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p16 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p17 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p18 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p19 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p20 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p21 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p22 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p23 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p24 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p25 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p26 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p27 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p28 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p29 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p30 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p31 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p32 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p33 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p34 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p35 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p36 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p37 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p38 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p39 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p40 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p41 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p42 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p43 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p44 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p45 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p46 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p47 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p48 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p49 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p50 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p51 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p52 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p53 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p54 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p55 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p56 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p57 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p58 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p59 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p60 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p61 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p62 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p63 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p64 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p65 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p66 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p67 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p68 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p69 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p70 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p71 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p72 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p73 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p74 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p75 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p76 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p77 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p78 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p79 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p80 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p81 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p82 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p83 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p84 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p85 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p86 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p87 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p88 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p89 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p90 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p91 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p92 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p93 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p94 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p95 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p96 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p97 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p98 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p99 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p100 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p101 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p102 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p103 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p104 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p105 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p106 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p107 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p108 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p109 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p110 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p111 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p112 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p113 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p114 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p115 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p116 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p117 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p118 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p119 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p120 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p121 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p122 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p123 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p124 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p125 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p126 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p127 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p128 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p129 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p130 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p131 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p132 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p133 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p134 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p135 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p136 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p137 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p138 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p139 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p140 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p141 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p142 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p143 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p144 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p145 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p146 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p147 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p148 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p149 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p150 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p151 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p152 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p153 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p154 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p155 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p156 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p157 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p158 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p159 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p160 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p161 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p162 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p163 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p164 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p165 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p166 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p167 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p168 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p169 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p170 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p171 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p172 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p173 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p174 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p175 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p176 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p177 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p179 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p180 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p181 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p182 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p183 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p184 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p185 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p186 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p191 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p192 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p193 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p194 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p195 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p196 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p197 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p198 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p203 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p204 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p205 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p206 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p207 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p209 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p210 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p211 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p212 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p213 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p214 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p215 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p216 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p221 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p222 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p223 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p224 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p225 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p227 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p228 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p229 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p230 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p231 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p233 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p234 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p235 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p236 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p237 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p257 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p258 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p259 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p260 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p261 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p263 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p264 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p265 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p266 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p267 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p268 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p269 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p270 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p278 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p279 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p280 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p281 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p282 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p283 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p284 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p285 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p286 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p287 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p288 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p290 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p291 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p292 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p293 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p294 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p299 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p300 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p301 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p302 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p303 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p308 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p309 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p310 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p311 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p312 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p326 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p327 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p328 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p329 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p330 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p338 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p339 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p340 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p341 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p342 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p343 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p344 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p345 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p347 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p348 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p349 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p350 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p351 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p353 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p354 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p355 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p356 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p357 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p358 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p359 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p360 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p368 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p369 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p370 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p371 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p372 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p374 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p375 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p376 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p377 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p378 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p380 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p381 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p382 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p383 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p384 From 6c51914a70bcc124e990b7809ff0b39b9a906635 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Thu, 20 Jun 2024 07:38:17 -0500 Subject: [PATCH 046/163] Update EventSelector.cpp Removed the charge threshold (> 200 pe) needed to consider tank/MRD coincidence. Given the README states "PMTMRDCoincCut: Flags events that do not have a certain time offset between PMT & MRD cluster" this should include all PMT clusters, and not just some that are over a certain charge threshold. This change in reality likely won't change much, as most muon tracks in the MRD deposit enough light to leave more than 200 pe worth of charge, but per our Slack convo it's probably best to just remove this condition as its not obvious. --- UserTools/EventSelector/EventSelector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UserTools/EventSelector/EventSelector.cpp b/UserTools/EventSelector/EventSelector.cpp index 4ef5a779f..580929850 100644 --- a/UserTools/EventSelector/EventSelector.cpp +++ b/UserTools/EventSelector/EventSelector.cpp @@ -776,7 +776,7 @@ bool EventSelector::EventSelectionByPMTMRDCoinc() { if (verbosity > 1) std::cout <<"max_charge: "< pmtmrd_coinc_min && time_diff < pmtmrd_coinc_max && max_charge > 200 && n_hits >= 20){ + if (time_diff > pmtmrd_coinc_min && time_diff < pmtmrd_coinc_max){ coincidence = true; vector_mrd_coincidence.push_back(i_mrd); } From 77551ea46a1b82006e1cef17f94723773efcc1c6 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Thu, 20 Jun 2024 07:55:29 -0500 Subject: [PATCH 047/163] Update IFBeamDBInterfaceV2.cpp When the tool fetches information and writes to the TTree, if a device was empty/didn't return any values from the database, the entire branch will not be written to the root file to ensure the number of entries is the same between all branches. If there are no entries for a fetched device, fill the "blank" entries with -9999. --- .../BeamFetcherV2/IFBeamDBInterfaceV2.cpp | 75 ++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp b/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp index 99e0a5148..e24894bbc 100644 --- a/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp +++ b/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp @@ -16,6 +16,20 @@ IFBeamDBInterfaceV2::IFBeamDBInterfaceV2() fCurl = curl_easy_init(); if (!fCurl) throw std::runtime_error("IFBeamDBInterfaceV2 failed to" " initialize libcurl"); + +// the map include the device name we want to have in the output + requiredDevices = { + {"E:TOR860", "E12"}, + {"E:TOR875", "E12"}, + {"E:THCURR", "KA"}, + {"E:BTJT2", "DegC"}, + {"E:HP875", "mm"}, + {"E:VP875", "mm"}, + {"E:HPTG1", "mm"}, + {"E:VPTG1", "mm"}, + {"E:HPTG2", "mm"}, + {"E:VPTG2", "mm"}, + {"E:BTH2T2", "DegC"}}; } IFBeamDBInterfaceV2::~IFBeamDBInterfaceV2() @@ -237,6 +251,14 @@ IFBeamDBInterfaceV2::ParseDBResponseSingleSpan(const std::string& response) cons unit, timestamp); } + +for (auto &ts : retMap) { + for (auto &dev : requiredDevices) { + if (ts.second.find(dev.first) == ts.second.end()) { + ts.second[dev.first] = BeamDataPoint(-9999, dev.second, ts.first); + } + } + } return retMap; } @@ -280,6 +302,41 @@ IFBeamDBInterfaceV2::ParseDBResponseBundleSpan(const std::string& response) cons unit, timestamp); } + + //count the total number of elements in retMap times the number of elements in that element, print the total number + int total = 0; + for (auto &ts : retMap) { + total += ts.second.size(); + } + std::cout << "Total number of elements in retMap: " << total << std::endl; + std::cout << "Size of retMap is " << retMap.size() << std::endl; + + + //check each timestamp in the retMap, to see if it have all the devices in the requiredDevices map keys, if yes, continue + //if not, create entry for that device at retMap[TS], use the data type from the value of requiredDevices + // use value as -9999, unit as doulbe, timestamp = TS + for (auto &ts : retMap) { + /*cout<<"size of this timestamp is "< Date: Thu, 20 Jun 2024 07:57:35 -0500 Subject: [PATCH 048/163] Update IFBeamDBInterfaceV2.h --- UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.h b/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.h index 91835d78c..b48b5fda2 100644 --- a/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.h +++ b/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.h @@ -48,9 +48,9 @@ class IFBeamDBInterfaceV2 { /// @param t0 Starting timestamp (milliseconds since the Unix epoch) /// @param t1 Starting timestamp (milliseconds since the Unix epoch) /// @return A nested map containing the parsed data. Keys of the outer map - /// are timestamps (milliseconds since the Unix epoch), values are inner maps. - /// Keys of the inner map are device names , values are elements of class type - /// BeamDataPoint that hold a numerical value, a unit string, and timestamp. + /// are device names, values are inner maps. Keys of the inner map are + /// timestamps (milliseconds since the Unix epoch), values are + /// BeamDataPoint structs that hold a numerical value and a unit string. /// @note An easy way to get the current milliseconds since the Unix epoch /// is to use the terminal utility date like this: @verbatim date +%s%3N /// @endverbatim @@ -68,6 +68,9 @@ class IFBeamDBInterfaceV2 { QueryBeamDBBundle(std::string bundle, uint64_t time) const; int RunQuery(const std::stringstream &url_stream, std::string &response_string) const; + + /// @brief The list of devices required to save in the root tree + std::map requiredDevices; protected: /// @brief Create the singleton IFBeamDBInterfaceV2 object From 2fac3f8a9eb5bac99a3a4976398c083dffe34b9e Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Mon, 24 Jun 2024 09:50:26 -0500 Subject: [PATCH 049/163] Update ToolsConfig Correct path to LoadGeometry file with PMT Timing offsets --- configfiles/LAPPD_EB/ToolsConfig | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/configfiles/LAPPD_EB/ToolsConfig b/configfiles/LAPPD_EB/ToolsConfig index ea786fae4..0d6e4d1bb 100644 --- a/configfiles/LAPPD_EB/ToolsConfig +++ b/configfiles/LAPPD_EB/ToolsConfig @@ -1,11 +1,5 @@ -LoadGeometry LoadGeometry configfiles/LAPPD_EB/ConfigGeo +LoadGeometry LoadGeometry configfiles/LoadGeometry/LoadGeometryConfig LoadRawData LoadRawData configfiles/LAPPD_EB/LoadRawDataConfig - TriggerDataDecoder TriggerDataDecoder configfiles/LAPPD_EB/TriggerDataDecoderConfig - LAPPDLoadStore LAPPDLoadStore configfiles/LAPPD_EB/Configs - LAPPDTreeMaker LAPPDTreeMaker configfiles/LAPPD_EB/Configs - - - From a73d59e7bcbf0dc5bb14f955cdaa66dbab8817f5 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Mon, 24 Jun 2024 09:52:14 -0500 Subject: [PATCH 050/163] Update ConfigGeo Use this geometry file instead - needed to add PMT offsets --- configfiles/LAPPD_EB/ConfigGeo | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configfiles/LAPPD_EB/ConfigGeo b/configfiles/LAPPD_EB/ConfigGeo index ffe0ca918..759b28663 100644 --- a/configfiles/LAPPD_EB/ConfigGeo +++ b/configfiles/LAPPD_EB/ConfigGeo @@ -5,7 +5,8 @@ FACCMRDGeoFile ./configfiles/LoadGeometry/FullMRDGeometry.csv DetectorGeoFile ./configfiles/LoadGeometry/DetectorGeometrySpecs.csv LAPPDGeoFile ./configfiles/LAPPDana/LAPPDGeometry.csv TankPMTGeoFile ./configfiles/LoadGeometry/FullTankPMTGeometry.csv -TankPMTGainFile ./configfiles/LoadGeometry/ChannelSPEGains_BeamRun20192020.csv +TankPMTGainFile ./configfiles/LoadGeometry/ChannelSPEGains2023.csv +TankPMTTimingOffsetFile ./configfiles/LoadGeometry/TankPMTTimingOffsets.csv AuxiliaryChannelFile ./configfiles/LoadGeometry/AuxChannels.csv LAPPDMerging 0 From a16cb2b53530203c82dd3e3e4d7f2ea9be7b08e8 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Mon, 24 Jun 2024 09:53:15 -0500 Subject: [PATCH 051/163] Update ToolsConfig revert change --- configfiles/LAPPD_EB/ToolsConfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configfiles/LAPPD_EB/ToolsConfig b/configfiles/LAPPD_EB/ToolsConfig index 0d6e4d1bb..71b067fe2 100644 --- a/configfiles/LAPPD_EB/ToolsConfig +++ b/configfiles/LAPPD_EB/ToolsConfig @@ -1,4 +1,4 @@ -LoadGeometry LoadGeometry configfiles/LoadGeometry/LoadGeometryConfig +LoadGeometry LoadGeometry configfiles/LAPPD_EB/ConfigGeo LoadRawData LoadRawData configfiles/LAPPD_EB/LoadRawDataConfig TriggerDataDecoder TriggerDataDecoder configfiles/LAPPD_EB/TriggerDataDecoderConfig LAPPDLoadStore LAPPDLoadStore configfiles/LAPPD_EB/Configs From 2f9830b1d75aab849cf86fcfa325c28c9c13558f Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Mon, 24 Jun 2024 10:28:32 -0500 Subject: [PATCH 052/163] Update LoadRawDataConfig Changed .txt file list to be consistent with the EventBuilder toolchain --- configfiles/LAPPD_EB/LoadRawDataConfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configfiles/LAPPD_EB/LoadRawDataConfig b/configfiles/LAPPD_EB/LoadRawDataConfig index 3b9a2ea0a..d849fc8f2 100644 --- a/configfiles/LAPPD_EB/LoadRawDataConfig +++ b/configfiles/LAPPD_EB/LoadRawDataConfig @@ -3,7 +3,7 @@ BuildType LAPPDAndCTC Mode FileList -InputFile ./configfiles/LAPPD_EB/list.txt +InputFile ./configfiles/LAPPD_EB/my_files.txt DummyRunInfo 1 From cc77d1fdf5c092fbc2040868e219b83fb7f5c93d Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Mon, 24 Jun 2024 10:30:18 -0500 Subject: [PATCH 053/163] Rename list.txt to my_files.txt Consistency with eventbuilder --- configfiles/LAPPD_EB/{list.txt => my_files.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename configfiles/LAPPD_EB/{list.txt => my_files.txt} (100%) diff --git a/configfiles/LAPPD_EB/list.txt b/configfiles/LAPPD_EB/my_files.txt similarity index 100% rename from configfiles/LAPPD_EB/list.txt rename to configfiles/LAPPD_EB/my_files.txt From e7ded7012dbc0cc08cf752f959c56c138032b812 Mon Sep 17 00:00:00 2001 From: Yue Date: Mon, 24 Jun 2024 11:35:06 -0500 Subject: [PATCH 054/163] Update for board index in LAPPDTimeAlignment and tree maker update configs files in LAPPDProcessedAna, now normal run without print out Changes to be committed: modified: UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp modified: UserTools/LAPPDPlots/LAPPDPlots.cpp modified: UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.cpp modified: UserTools/LAPPDTreeMaker/LAPPDTreeMaker.cpp modified: UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h modified: configfiles/LAPPDProcessedAna/ConfigPlot modified: configfiles/LAPPDProcessedAna/Configs modified: configfiles/LAPPDProcessedAna/ToolChainConfig modified: configfiles/LAPPDProcessedAna/list.txt --- UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp | 4 +- UserTools/LAPPDPlots/LAPPDPlots.cpp | 61 ++- .../LAPPDTimeAlignment/LAPPDTimeAlignment.cpp | 442 ++++++++++-------- UserTools/LAPPDTreeMaker/LAPPDTreeMaker.cpp | 132 ++++-- UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h | 9 + configfiles/LAPPDProcessedAna/ConfigPlot | 6 +- configfiles/LAPPDProcessedAna/Configs | 2 +- configfiles/LAPPDProcessedAna/ToolChainConfig | 2 +- configfiles/LAPPDProcessedAna/list.txt | 12 +- 9 files changed, 422 insertions(+), 248 deletions(-) diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp index e6b5f906e..f386be6f5 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp @@ -1109,7 +1109,7 @@ bool LAPPDLoadStore::DoPedestalSubtract() if (DoPedSubtract == 1) { auto iter = PedestalValues->find((it->first)); - if(kvec==0) + if(kvec==0 && LAPPDStoreReadInVerbosity>5) cout<first<<" with value = "<second.at(0); if (iter != PedestalValues->end() && iter->second.size() > kvec) { @@ -1137,7 +1137,7 @@ bool LAPPDLoadStore::DoPedestalSubtract() unsigned long pushChannelNo = (unsigned long)it->first; LAPPDWaveforms.insert(pair>>(pushChannelNo, VecTmpWave)); - cout<<", Pushed to LAPPDWaveforms with channel number "< 2) //{ - CanvasXSubPlotNumber = static_cast(ACDCReadedLAPPDID.size()); + // CanvasXSubPlotNumber = static_cast(ACDCReadedLAPPDID.size()); + // CanvasXSubPlotNumber = max element of ACDCReadedLAPPDID minus min element of ACDCReadedLAPPDID + 1 + CanvasXSubPlotNumber = *max_element(ACDCReadedLAPPDID.begin(), ACDCReadedLAPPDID.end()) - *min_element(ACDCReadedLAPPDID.begin(), ACDCReadedLAPPDID.end()) + 1; + CanvasXSubPlotNumber = CanvasXSubPlotNumber * 2; CanvasTotalSubPlotNumber = CanvasXSubPlotNumber * CanvasYSubPlotNumber; //} @@ -119,17 +122,19 @@ bool LAPPDPlots::Execute() bool gotdata = m_data->Stores["ANNIEEvent"]->Get(LAPPDPlotInputWaveLabel, lappddata); m_data->Stores["ANNIEEvent"]->Get("ACDCboards", ReadBoards); - cout << "LAPPDPlots, got ACDCboards size = " << ReadBoards.size() << " with id = "; - for (auto i : ReadBoards) - cout << i << " "; - cout << endl; - m_data->CStore.Get("LAPPD_ID", LAPPD_ID); - cout << "ACDCReadedLAPPDID size = " << ACDCReadedLAPPDID.size() << ": "; - for (auto i : ACDCReadedLAPPDID) - cout << i << " "; - cout << endl; - + if (LAPPDPlotsVerbosity > 0) + { + cout << "LAPPDPlots, got ACDCboards size = " << ReadBoards.size() << " with id = "; + for (auto i : ReadBoards) + cout << i << " "; + cout << endl; + + cout << "ACDCReadedLAPPDID size = " << ACDCReadedLAPPDID.size() << ": "; + for (auto i : ACDCReadedLAPPDID) + cout << i << " "; + cout << endl; + } vector drawPositions = ACDCReadedLAPPDID; int minID = *min_element(ACDCReadedLAPPDID.begin(), ACDCReadedLAPPDID.end()); for (int i = 0; i < drawPositions.size(); i++) @@ -138,10 +143,13 @@ bool LAPPDPlots::Execute() if (i % 2 == 1) drawPositions.at(i) = drawPositions.at(i) + 1; } - cout << "drawPositions size = " << drawPositions.size() << ": "; - for (auto i : drawPositions) - cout << i << " "; - cout << endl; + if (LAPPDPlotsVerbosity > 0) + { + cout << "drawPositions size = " << drawPositions.size() << ": "; + for (auto i : drawPositions) + cout << i << " "; + cout << endl; + } vector drawBoardID = ACDCReadedLAPPDID; for (int i = 0; i < drawBoardID.size(); i++) @@ -150,14 +158,15 @@ bool LAPPDPlots::Execute() if (i % 2 == 1) drawBoardID.at(i) = (drawBoardID.at(i) + 1); } - cout << "drawBoardID size = " << drawBoardID.size() << ": "; - for (auto i : drawBoardID) - cout << i << " "; - cout << endl; - if (LAPPDPlotsVerbosity > 0) - cout << "LAPPDPlots execute with data " << LAPPDPlotInputWaveLabel << ", got data " << gotdata << ", data size " << lappddata.size() << ", Board IDs size " << ReadBoards.size() << ", (single) ID " << LAPPD_ID << endl; + { + cout << "drawBoardID size = " << drawBoardID.size() << ": "; + for (auto i : drawBoardID) + cout << i << " "; + cout << endl; + cout << "LAPPDPlots execute with data " << LAPPDPlotInputWaveLabel << ", got data " << gotdata << ", data size " << lappddata.size() << ", Board IDs size " << ReadBoards.size() << ", (single) ID " << LAPPD_ID << endl; + } if (DrawEventWaveform) { vector DrawPosition = {Side0EventWaveformDrawPosition, Side1EventWaveformDrawPosition}; @@ -201,7 +210,7 @@ bool LAPPDPlots::Execute() Channel *ch = _geom->GetChannel(channelNo); int stripNo = ch->GetStripNum(); if (LAPPDPlotsVerbosity > 3) - cout << "Drawing channel " << originalChannelNo << " as channelNo " << channelNo << " strip " << stripNo << ", with sample size " << w.GetSamples()->size() <<", data at bin 0 = "<<-w.GetSamples()->at(0)<size() << ", data at bin 0 = " << -w.GetSamples()->at(0) << endl; if (!drawTriggerChannel) if ((channelNo % 1000) % 30 == 5) continue; @@ -209,7 +218,11 @@ bool LAPPDPlots::Execute() for (int i = 0; i < w.GetSamples()->size(); i++) { h->SetBinContent(i, stripNo + 1, -w.GetSamples()->at(i)); - if(i<5) cout<<-w.GetSamples()->at(i)<<", "; + if (LAPPDPlotsVerbosity > 0) + { + if (i < 5) + cout << -w.GetSamples()->at(i) << ", "; + } } } if (LAPPDPlotsVerbosity > 3) @@ -243,7 +256,7 @@ bool LAPPDPlots::Execute() DrawPositionBinHist.clear(); for (int i = 0; i < drawBoardID.size(); i++) { - DrawPositionBinHist.push_back(drawBoardID.at(i) + CanvasXSubPlotNumber); + DrawPositionBinHist.push_back(drawBoardID.at(i) + CanvasXSubPlotNumber + 1); } } for (int i = 0; i < drawBoardID.size(); i++) diff --git a/UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.cpp b/UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.cpp index 5a9430748..8df0890d4 100644 --- a/UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.cpp +++ b/UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.cpp @@ -1,260 +1,336 @@ #include "LAPPDTimeAlignment.h" #include "TGraph.h" -LAPPDTimeAlignment::LAPPDTimeAlignment():Tool(){} - +LAPPDTimeAlignment::LAPPDTimeAlignment() : Tool() {} bool LAPPDTimeAlignment::Initialise(std::string configfile, DataModel &data) { - /////////////////// Useful header /////////////////////// - if(configfile!="") m_variables.Initialise(configfile); // loading config file - //m_variables.Print(); + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); - m_data= &data; //assigning transient data pointer - ///////////////////////////////////////////////////////////////// + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// - m_variables.Get("FindT0InputWavLabel",InputWavLabel); - m_variables.Get("FindT0OutputWavLabel",OutputWavLabel); + m_variables.Get("FindT0InputWavLabel", InputWavLabel); + m_variables.Get("FindT0OutputWavLabel", OutputWavLabel); - m_variables.Get("FindT0Verbosity",FindT0VerbosityLevel); + m_variables.Get("FindT0Verbosity", FindT0VerbosityLevel); - m_variables.Get("TrigEarlyCut",trigearlycut); - m_variables.Get("TrigLateCut",triglatecut); + m_variables.Get("TrigEarlyCut", trigearlycut); + m_variables.Get("TrigLateCut", triglatecut); - m_variables.Get("T0signalmax",T0signalmax); - m_variables.Get("T0signalthreshold",T0signalthreshold); + m_variables.Get("T0signalmax", T0signalmax); + m_variables.Get("T0signalthreshold", T0signalthreshold); - m_variables.Get("T0signalmaxOld",T0signalmaxOld); - m_variables.Get("T0signalthresholdOld",T0signalthresholdOld); + m_variables.Get("T0signalmaxOld", T0signalmaxOld); + m_variables.Get("T0signalthresholdOld", T0signalthresholdOld); - m_variables.Get("T0offset",T0offset); - m_variables.Get("GlobalShiftT0",globalshiftT0); + m_variables.Get("T0offset", T0offset); + m_variables.Get("GlobalShiftT0", globalshiftT0); - m_data->Stores["ANNIEEvent"]->Get("TrigChannel",TrigChannel); - m_data->Stores["ANNIEEvent"]->Get("LAPPDchannelOffset",LAPPDchannelOffset); + m_data->Stores["ANNIEEvent"]->Get("TrigChannel", TrigChannel); + m_data->Stores["ANNIEEvent"]->Get("LAPPDchannelOffset", LAPPDchannelOffset); - LoadLAPPDMap = false; - m_variables.Get("LoadLAPPDMap",LoadLAPPDMap); + LoadLAPPDMap = false; + m_variables.Get("LoadLAPPDMap", LoadLAPPDMap); - return true; + return true; } - -bool LAPPDTimeAlignment::Execute(){ +bool LAPPDTimeAlignment::Execute() +{ oldLaser = 0; m_data->Stores["ANNIEEvent"]->Get("oldLaser", oldLaser); - if(oldLaser == 1){T0signalmax=T0signalmaxOld; T0signalthreshold=T0signalthresholdOld;} - - if(FindT0VerbosityLevel>0) cout<<"OLD LASER? "< 0) + cout << "OLD LASER? " << oldLaser << " " << T0signalmax << " " << T0signalthreshold << endl; + + double AnalogBoardShift[60] = { + 54, 54, 54, 54, 0, 0, // 0-5 + 88, 88, 88, 88, 88, 88, // 6-11 + 232, 232, 232, 232, 232, 232, // 12-17 + 220, 220, 220, 220, 220, 220, // 18-23 + 185, 185, 185, 185, 185, 185, // 24-29 + 54, 54, 54, 54, 0, 0, // 30-35 + 88, 88, 88, 88, 88, 88, // 36-41 + 232, 232, 232, 232, 232, 232, // 42-47 + 220, 220, 220, 220, 220, 220, // 48-53 + 185, 185, 185, 185, 185, 185, // 54-59 }; - for (auto& k : AnalogBoardShift){ - //k=(k-54)*10/197.86272; - k=(k-54)*10/169.982; + for (auto &k : AnalogBoardShift) + { + // k=(k-54)*10/197.86272; + k = (k - 54) * 10 / 169.982; } - - std::map>> lappddata; - m_data->Stores["ANNIEEvent"]->Get(InputWavLabel,lappddata); + std::map>> lappddata; + m_data->Stores["ANNIEEvent"]->Get(InputWavLabel, lappddata); vector NReadBoards; - m_data->Stores["ANNIEEvent"]->Get("ACDCboards",NReadBoards); - std::map>> reordereddata; + m_data->Stores["ANNIEEvent"]->Get("ACDCboards", NReadBoards); + std::map>> reordereddata; bool T0signalInWindow = false; double deltaT; - + vector ACDCReadedLAPPDID; m_data->Stores["ANNIEEvent"]->Get("ACDCReadedLAPPDID", ACDCReadedLAPPDID); - map >> :: iterator itr_bi; - for(int i = 0;i< NReadBoards.size();i++) + //print NReadBoards + if (FindT0VerbosityLevel > 0) + { + cout << "NReadBoards: "; + for (int i = 0; i < NReadBoards.size(); i++) { - int bi = NReadBoards.at(i); - int thisLAPPDID = ACDCReadedLAPPDID.at(i); + cout << NReadBoards.at(i) << " "; + } + cout << endl; + } + // print ACDCReadedLAPPDID + if (FindT0VerbosityLevel > 0) + { + cout << "ACDCReadedLAPPDID: "; + for (int i = 0; i < ACDCReadedLAPPDID.size(); i++) + { + cout << ACDCReadedLAPPDID.at(i) << " "; + } + cout << endl; + } + vector fittedBoardIDInMap; - T0channelNo = LAPPDchannelOffset+(30*bi)+TrigChannel; - if(LoadLAPPDMap) - { - T0channelNo = 1000 + (30*(bi%2)) + 60* thisLAPPDID + TrigChannel; - } + map>>::iterator itr_bi; + for (int i = 0; i < NReadBoards.size(); i++) + { + int bi = NReadBoards.at(i); + int thisLAPPDID = ACDCReadedLAPPDID.at(i); - if(FindT0VerbosityLevel>0) cout<<"For board "<0) cout<<"In LAPPDTimeAlignment, T0 channel:"<< T0channelNo<<" , InputWavlabel: "< bwav = (itr_bi->second).at(0); + if (FindT0VerbosityLevel > 0) + cout << "For board " << bi << ", InputWavlabel: " << InputWavLabel << endl; + + if (FindT0VerbosityLevel > 0) + cout << "In LAPPDTimeAlignment, T0 channel:" << T0channelNo << " , InputWavlabel: " << InputWavLabel << " , LAPPDdata.size()=" << lappddata.size() << endl; + if (FindT0VerbosityLevel > 1) + cout << "is the channel there? " << lappddata.count((unsigned long)T0channelNo) << endl; + + itr_bi = lappddata.find((unsigned long)T0channelNo); + Waveform bwav = (itr_bi->second).at(0); + + double thetime = Tfit(bwav.GetSamples()); + int switchbit = (int)(thetime / 100.); + deltaT = thetime - (100. * (double)switchbit); + int Qvar = 0; + if ((switchbit >= trigearlycut) && (switchbit <= triglatecut)) + T0signalInWindow = true; + + // vector transcribe + vec_deltaT.push_back(deltaT); + vec_T0signalInWindow.push_back(T0signalInWindow); + vec_T0Bin.push_back(switchbit); + fittedBoardIDInMap.push_back(static_cast((T0channelNo-1000)/30)); + + if (FindT0VerbosityLevel > 0) + cout << "Done finding the time, switchbit:" << switchbit << " , deltaT: " << deltaT << " , inwindow: " << T0signalInWindow << endl; + if (FindT0VerbosityLevel > 1) + cout << "ready to loop" << endl; + } - double thetime = Tfit(bwav.GetSamples()); - int switchbit = (int)(thetime/100.); - deltaT = thetime - (100.*(double)switchbit); - int Qvar=0; - if( (switchbit>=trigearlycut) && (switchbit<=triglatecut) ) T0signalInWindow = true; + for (bool k : vec_T0signalInWindow) + { + if (!k) + { + T0signalInWindow = false; + } + } - //vector transcribe - vec_deltaT.push_back(deltaT); - vec_T0signalInWindow.push_back(T0signalInWindow); - vec_T0Bin.push_back(switchbit); + map>>::iterator itr; + for (itr = lappddata.begin(); itr != lappddata.end(); ++itr) + { + unsigned long channelno = itr->first; + if (FindT0VerbosityLevel > 5) + cout << "Found channelno: " << channelno << endl; + } - if(FindT0VerbosityLevel>0) cout<<"Done finding the time, switchbit:" << switchbit << " , deltaT: "<1) cout<<"ready to loop"<first; + vector> Vwavs = itr->second; + vector> Vrwav; + int bi = (int)(channelno - LAPPDchannelOffset) / 30 % 2; // TODO: fix this, why loading data with board 2 and 3 have channel from 0 to 120? + int thisBoardID = static_cast((channelno-1000)/30); + if(LoadLAPPDMap) + { + int index = std::distance(fittedBoardIDInMap.begin(), std::find(fittedBoardIDInMap.begin(), fittedBoardIDInMap.end(), thisBoardID)); + bi = index; + if(FindT0VerbosityLevel>5 && printcount<5) + { + cout << "thisBoardID: " << thisBoardID << " , index: " << index << " , bi: " << bi << endl; + printcount++; + } } + + int countnumber = (channelno % 1000) % 60; + if (FindT0VerbosityLevel > 2) + cout << "Looping with channelno: " << channelno << " , bi: " << bi << " , countnumber: " << countnumber << endl; - for(bool k: vec_T0signalInWindow) + // loop over all Waveforms + for (int i = 0; i < Vwavs.size(); i++) { - if(!k){T0signalInWindow=false;} - } + if (FindT0VerbosityLevel > 2 && i == 0) + cout << "Looping waveform at" << i << endl; + Waveform bwav = Vwavs.at(i); + Waveform rwav; + Waveform rwavShift; - map >> :: iterator itr; - for (itr = lappddata.begin(); itr != lappddata.end(); ++itr) - { - unsigned long channelno = itr->first; - if(FindT0VerbosityLevel>2) - cout<<"Found channelno: "<first; - vector> Vwavs = itr->second; - vector> Vrwav; - int bi = (int)(channelno-LAPPDchannelOffset)/30%2; //TODO: fix this, why loading data with board 2 and 3 have channel from 0 to 120? - int countnumber = (channelno%1000)%60; - if(FindT0VerbosityLevel>2)cout <<"Looping with channelno: "<2 && i ==0) cout<<"Looping waveform at"< bwav = Vwavs.at(i); - Waveform rwav; - Waveform rwavShift; - - int sb = vec_T0Bin[bi] + T0offset + AnalogBoardShift[countnumber]; - - countnumber++; - - - if(sb<0) sb+=255; - - for(int j=0; j< bwav.GetSamples()->size(); j++) - { - if(sb>255) sb=0; - double nsamp = bwav.GetSamples()->at(sb); - rwav.PushSample(nsamp); - sb++; - } - - for(int j=0; j< rwav.GetSamples()->size(); j++) - { - int ibin = j + globalshiftT0; - if(ibin > 255) ibin = ibin - 255; - double nsamp = rwav.GetSamples()->at(ibin); - rwavShift.PushSample(nsamp); - } - Vrwav.push_back(rwavShift); - } - reordereddata.insert(pair>>(channelno,Vrwav)); + countnumber++; + + if (sb < 0) + sb += 255; + + for (int j = 0; j < bwav.GetSamples()->size(); j++) + { + if (sb > 255) + sb = 0; + double nsamp = bwav.GetSamples()->at(sb); + rwav.PushSample(nsamp); + sb++; + } + + for (int j = 0; j < rwav.GetSamples()->size(); j++) + { + int ibin = j + globalshiftT0; + if (ibin > 255) + ibin = ibin - 255; + double nsamp = rwav.GetSamples()->at(ibin); + rwavShift.PushSample(nsamp); + } + Vrwav.push_back(rwavShift); } + reordereddata.insert(pair>>(channelno, Vrwav)); + } - if(FindT0VerbosityLevel>0) cout<<"End of LAPPDTimeAlignment..."< 0) + cout << "End of LAPPDTimeAlignment..." << endl; - m_data->Stores["ANNIEEvent"]->Set(OutputWavLabel,reordereddata); - m_data->Stores["ANNIEEvent"]->Set("deltaT",vec_deltaT); - m_data->Stores["ANNIEEvent"]->Set("T0signalInWindow",T0signalInWindow); - m_data->Stores["ANNIEEvent"]->Set("T0Bin",vec_T0Bin); - vec_deltaT.clear(); - vec_T0signalInWindow.clear(); - vec_T0Bin.clear(); + m_data->Stores["ANNIEEvent"]->Set(OutputWavLabel, reordereddata); + m_data->Stores["ANNIEEvent"]->Set("deltaT", vec_deltaT); + m_data->Stores["ANNIEEvent"]->Set("T0signalInWindow", T0signalInWindow); + m_data->Stores["ANNIEEvent"]->Set("T0Bin", vec_T0Bin); + vec_deltaT.clear(); + vec_T0signalInWindow.clear(); + vec_T0Bin.clear(); - return true; + return true; } - bool LAPPDTimeAlignment::Finalise() { - return true; + return true; } - - -double LAPPDTimeAlignment::Tfit(std::vector* wf) +double LAPPDTimeAlignment::Tfit(std::vector *wf) { - int nbin = wf->size(); - - double ppre=0.0; - double pvol=0.0; + int nbin = wf->size(); + double ppre = 0.0; + double pvol = 0.0; - bool firstcross=true; - double ttime=0; + bool firstcross = true; + double ttime = 0; - for(int i=0;iat(i)); - if(i>1) ppre = (wf->at(i-1)); + if (i > 1) + ppre = (wf->at(i - 1)); - if(FindT0VerbosityLevel>2) cout< 2) + cout << i << " " << ppre << " " << pvol << " " << T0signalmax << endl; - if(oldLaser == 1){ - if(firstcross && pvol > T0signalmax && ppre < T0signalmax && i>5 && i<250){ //trigger up to +200 2020 data - if(FindT0VerbosityLevel>1) cout<<"Old t0 bin: "<SetPoint(j+7,(i+j)*100.,(wf->at(i+j))); //select 7 points - } - bool firstthreshcross=true; - for(int k=(i-7)*100; k<(i+1)*100; k+=10){ - if(FindT0VerbosityLevel==3) cout<Eval((double)k, 0, "S"))<Eval((double)k, 0, "S"))2) cout<<"time: "< T0signalmax && ppre < T0signalmax && i > 5 && i < 250) + { // trigger up to +200 2020 data + if (FindT0VerbosityLevel > 1) + cout << "Old t0 bin: " << i << endl; + TGraph *edge = new TGraph(); + for (int j = -7; j < 1; j++) + { + edge->SetPoint(j + 7, (i + j) * 100., (wf->at(i + j))); // select 7 points + } + bool firstthreshcross = true; + for (int k = (i - 7) * 100; k < (i + 1) * 100; k += 10) + { + if (FindT0VerbosityLevel == 3) + cout << k << " " << (edge->Eval((double)k, 0, "S")) << endl; + if (((edge->Eval((double)k, 0, "S")) < T0signalthreshold) && firstthreshcross) + { + if (FindT0VerbosityLevel > 2) + cout << "time: " << k << endl; + ttime = (double)k; + firstthreshcross = false; } - firstcross=false; + } + firstcross = false; } - }else{ + } + else + { - if(firstcross && pvol < T0signalmax && ppre > T0signalmax && i>7 && i<249){ + if (firstcross && pvol < T0signalmax && ppre > T0signalmax && i > 7 && i < 249) + { - if(FindT0VerbosityLevel>1) cout<<"New t0 bin: "< 1) + cout << "New t0 bin: " << i << endl; - TGraph *edge = new TGraph(); - for(int j=-7; j<1; j++){ - edge->SetPoint(j+7,(i+j)*100.,(wf->at(i+j))); - } + TGraph *edge = new TGraph(); + for (int j = -7; j < 1; j++) + { + edge->SetPoint(j + 7, (i + j) * 100., (wf->at(i + j))); + } - bool firstthreshcross=true; - for(int k=(i-7)*100; k<(i+1)*100; k+=10){ + bool firstthreshcross = true; + for (int k = (i - 7) * 100; k < (i + 1) * 100; k += 10) + { - if(FindT0VerbosityLevel==3) cout<Eval((double)k, 0, "S"))<Eval((double)k, 0, "S")) << endl; - if(((edge->Eval((double)k, 0, "S"))2) cout<<"time: "<Eval((double)k, 0, "S")) < T0signalthreshold) && firstthreshcross) + { + if (FindT0VerbosityLevel > 2) + cout << "time: " << k << endl; + ttime = (double)k; + firstthreshcross = false; } + } - firstcross=false; + firstcross = false; } } } - if(FindT0VerbosityLevel>0) cout<<"Done Finding T0"< 0) + cout << "Done Finding T0" << endl; return ttime; } diff --git a/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.cpp b/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.cpp index b97bc319b..3091f508f 100644 --- a/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.cpp +++ b/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.cpp @@ -71,6 +71,16 @@ bool LAPPDTreeMaker::Initialise(std::string configfile, DataModel &data) fPulse->Branch("PulseSide", &PulseSide, "PulseSide/I"); fPulse->Branch("PulseThreshold", &PulseThreshold, "PulseThreshold/D"); fPulse->Branch("PulseBaseline", &PulseBaseline, "PulseBaseline/D"); + if (MultiLAPPDMapTreeMaker) + { + fPulse->Branch("LTSRaw", <SRaw, "LTSRaw/l"); + fPulse->Branch("LBGRaw", &LBGRaw, "LBGRaw/l"); + fPulse->Branch("LOffset_ns", &LOffset_ns, "LOffset_ns/l"); + fPulse->Branch("LTSCorrection", <SCorrection, "LTSCorrection/I"); + fPulse->Branch("LBGCorrection", &LBGCorrection, "LBGCorrection/I"); + fPulse->Branch("LOSInMinusPS", &LOSInMinusPS, "LOSInMinusPS/I"); + fPulse->Branch("CTCPrimeTriggerTime", &CTCPrimeTriggerTime, "CTCPrimeTriggerTime/l"); + } fHit->Branch("RunNumber", &RunNumber, "RunNumber/I"); fHit->Branch("SubRunNumber", &SubRunNumber, "SubRunNumber/I"); @@ -91,6 +101,16 @@ bool LAPPDTreeMaker::Initialise(std::string configfile, DataModel &data) fHit->Branch("Pulse2StartTime", &Pulse2StartTime, "Pulse2StartTime/D"); fHit->Branch("Pulse1LastTime", &Pulse1LastTime, "Pulse1LastTime/D"); fHit->Branch("Pulse2LastTime", &Pulse2LastTime, "Pulse2LastTime/D"); + if (MultiLAPPDMapTreeMaker) + { + fHit->Branch("LTSRaw", <SRaw, "LTSRaw/l"); + fHit->Branch("LBGRaw", &LBGRaw, "LBGRaw/l"); + fHit->Branch("LOffset_ns", &LOffset_ns, "LOffset_ns/l"); + fHit->Branch("LTSCorrection", <SCorrection, "LTSCorrection/I"); + fHit->Branch("LBGCorrection", &LBGCorrection, "LBGCorrection/I"); + fHit->Branch("LOSInMinusPS", &LOSInMinusPS, "LOSInMinusPS/I"); + fHit->Branch("CTCPrimeTriggerTime", &CTCPrimeTriggerTime, "CTCPrimeTriggerTime/l"); + } fWaveform->Branch("RunNumber", &RunNumber, "RunNumber/I"); fWaveform->Branch("SubRunNumber", &SubRunNumber, "SubRunNumber/I"); @@ -106,6 +126,16 @@ bool LAPPDTreeMaker::Initialise(std::string configfile, DataModel &data) fWaveform->Branch("WaveformMaxTimeBin", &waveformMaxTimeBinValue, "WaveformMaxTimeBin/I"); fWaveform->Branch("waveformMaxFoundNear", &waveformMaxFoundNear, "waveformMaxFoundNear/O"); // O is boolean fWaveform->Branch("WaveformMaxNearing", &waveformMaxNearingValue, "WaveformMaxNearing/D"); + if (MultiLAPPDMapTreeMaker) + { + fWaveform->Branch("LTSRaw", <SRaw, "LTSRaw/l"); + fWaveform->Branch("LBGRaw", &LBGRaw, "LBGRaw/l"); + fWaveform->Branch("LOffset_ns", &LOffset_ns, "LOffset_ns/l"); + fWaveform->Branch("LTSCorrection", <SCorrection, "LTSCorrection/I"); + fWaveform->Branch("LBGCorrection", &LBGCorrection, "LBGCorrection/I"); + fWaveform->Branch("LOSInMinusPS", &LOSInMinusPS, "LOSInMinusPS/I"); + fWaveform->Branch("CTCPrimeTriggerTime", &CTCPrimeTriggerTime, "CTCPrimeTriggerTime/l"); + } fTimeStamp->Branch("RunNumber", &RunNumber, "RunNumber/I"); fTimeStamp->Branch("SubRunNumber", &SubRunNumber, "SubRunNumber/I"); @@ -193,6 +223,7 @@ bool LAPPDTreeMaker::Execute() if (MultiLAPPDMapTreeMaker && LAPPDana) { + m_data->Stores["ANNIEEvent"]->Get("PrimaryTriggerTime", CTCPrimeTriggerTime); if (treeMakerVerbosity > 0) cout << "LAPPDTreeMaker::Execute() MultiLAPPDMapTreeMaker" << endl; LoadLAPPDMapInfo(); @@ -487,20 +518,30 @@ bool LAPPDTreeMaker::FillPulseTree() // TODO save threshold and baseline if (MultiLAPPDMapTreeMaker) { - // find the index of LAPPD_ID in LAPPD_IDs, use that index to assign the timestamlUL and beam gate UL, if not found set them to zero - auto it = std::find(LAPPD_IDs.begin(), LAPPD_IDs.end(), LAPPD_ID); - if (it != LAPPD_IDs.end()) + // find the LAPPD_ID in LAPPD_IDs, get the index + // use that index to get the timestamp and beamgate + // if not found, set them to zero + int index = std::distance(LAPPD_IDs.begin(), std::find(LAPPD_IDs.begin(), LAPPD_IDs.end(), LAPPD_ID)); + if (index < LAPPDMapTimeStampRaw.size()) { - int index = std::distance(LAPPD_IDs.begin(), it); - LAPPDDataTimeStampUL = LAPPDMapTimeStampRaw.at(index); - LAPPDDataBeamgateUL = LAPPDMapBeamgateRaw.at(index); + LTSRaw = LAPPDMapTimeStampRaw.at(index); + LBGRaw = LAPPDMapBeamgateRaw.at(index); + LOffset_ns = LAPPDMapOffsets.at(index); + LTSCorrection = LAPPDMapTSCorrections.at(index); + LBGCorrection = LAPPDMapBGCorrections.at(index); + LOSInMinusPS = LAPPDMapOSInMinusPS.at(index); } else { - LAPPDDataTimeStampUL = 0; - LAPPDDataBeamgateUL = 0; + LTSRaw = 0; + LBGRaw = 0; + LOffset_ns = 0; + LTSCorrection = 0; + LBGCorrection = 0; + LOSInMinusPS = 0; } } + fPulse->Fill(); foundPulseNum++; } @@ -527,17 +568,24 @@ bool LAPPDTreeMaker::FillPulseTree() if (MultiLAPPDMapTreeMaker) { // find the index of LAPPD_ID in LAPPD_IDs, use that index to assign the timestamlUL and beam gate UL, if not found set them to zero - auto it = std::find(LAPPD_IDs.begin(), LAPPD_IDs.end(), LAPPD_ID); - if (it != LAPPD_IDs.end()) + int index = std::distance(LAPPD_IDs.begin(), std::find(LAPPD_IDs.begin(), LAPPD_IDs.end(), LAPPD_ID)); + if (index < LAPPDMapTimeStampRaw.size()) { - int index = std::distance(LAPPD_IDs.begin(), it); - LAPPDDataTimeStampUL = LAPPDMapTimeStampRaw.at(index); - LAPPDDataBeamgateUL = LAPPDMapBeamgateRaw.at(index); + LTSRaw = LAPPDMapTimeStampRaw.at(index); + LBGRaw = LAPPDMapBeamgateRaw.at(index); + LOffset_ns = LAPPDMapOffsets.at(index); + LTSCorrection = LAPPDMapTSCorrections.at(index); + LBGCorrection = LAPPDMapBGCorrections.at(index); + LOSInMinusPS = LAPPDMapOSInMinusPS.at(index); } else { - LAPPDDataTimeStampUL = 0; - LAPPDDataBeamgateUL = 0; + LTSRaw = 0; + LBGRaw = 0; + LOffset_ns = 0; + LTSCorrection = 0; + LBGCorrection = 0; + LOSInMinusPS = 0; } } fPulse->Fill(); @@ -593,18 +641,27 @@ bool LAPPDTreeMaker::FillHitTree() } if (MultiLAPPDMapTreeMaker) { - // find the index of LAPPD_ID in LAPPD_IDs, use that index to assign the timestamlUL and beam gate UL, if not found set them to zero - auto it = std::find(LAPPD_IDs.begin(), LAPPD_IDs.end(), LAPPD_ID); - if (it != LAPPD_IDs.end()) + // find the LAPPD_ID in LAPPD_IDs, get the index + // use that index to get the timestamp and beamgate + // if not found, set them to zero + int index = std::distance(LAPPD_IDs.begin(), std::find(LAPPD_IDs.begin(), LAPPD_IDs.end(), LAPPD_ID)); + if (index < LAPPDMapTimeStampRaw.size()) { - int index = std::distance(LAPPD_IDs.begin(), it); - LAPPDDataTimeStampUL = LAPPDMapTimeStampRaw.at(index); - LAPPDDataBeamgateUL = LAPPDMapBeamgateRaw.at(index); + LTSRaw = LAPPDMapTimeStampRaw.at(index); + LBGRaw = LAPPDMapBeamgateRaw.at(index); + LOffset_ns = LAPPDMapOffsets.at(index); + LTSCorrection = LAPPDMapTSCorrections.at(index); + LBGCorrection = LAPPDMapBGCorrections.at(index); + LOSInMinusPS = LAPPDMapOSInMinusPS.at(index); } else { - LAPPDDataTimeStampUL = 0; - LAPPDDataBeamgateUL = 0; + LTSRaw = 0; + LBGRaw = 0; + LOffset_ns = 0; + LTSCorrection = 0; + LBGCorrection = 0; + LOSInMinusPS = 0; } } fHit->Fill(); @@ -649,18 +706,27 @@ bool LAPPDTreeMaker::FillWaveformTree() }*/ if (MultiLAPPDMapTreeMaker) { - // find the index of LAPPD_ID in LAPPD_IDs, use that index to assign the timestamlUL and beam gate UL, if not found set them to zero - auto it = std::find(LAPPD_IDs.begin(), LAPPD_IDs.end(), LAPPD_ID); - if (it != LAPPD_IDs.end()) + // find the LAPPD_ID in LAPPD_IDs, get the index + // use that index to get the timestamp and beamgate + // if not found, set them to zero + int index = std::distance(LAPPD_IDs.begin(), std::find(LAPPD_IDs.begin(), LAPPD_IDs.end(), LAPPD_ID)); + if (index < LAPPDMapTimeStampRaw.size()) { - int index = std::distance(LAPPD_IDs.begin(), it); - LAPPDDataTimeStampUL = LAPPDMapTimeStampRaw.at(index); - LAPPDDataBeamgateUL = LAPPDMapBeamgateRaw.at(index); + LTSRaw = LAPPDMapTimeStampRaw.at(index); + LBGRaw = LAPPDMapBeamgateRaw.at(index); + LOffset_ns = LAPPDMapOffsets.at(index); + LTSCorrection = LAPPDMapTSCorrections.at(index); + LBGCorrection = LAPPDMapBGCorrections.at(index); + LOSInMinusPS = LAPPDMapOSInMinusPS.at(index); } else { - LAPPDDataTimeStampUL = 0; - LAPPDDataBeamgateUL = 0; + LTSRaw = 0; + LBGRaw = 0; + LOffset_ns = 0; + LTSCorrection = 0; + LBGCorrection = 0; + LOSInMinusPS = 0; } } fWaveform->Fill(); @@ -976,7 +1042,7 @@ void LAPPDTreeMaker::CleanTriggers() void LAPPDTreeMaker::LoadLAPPDMapInfo() { - //cout << "LAPPDTreeMaker::LoadLAPPDMapInfo" << endl; + // cout << "LAPPDTreeMaker::LoadLAPPDMapInfo" << endl; bool getMap = m_data->Stores["ANNIEEvent"]->Get("LAPPDDataMap", LAPPDDataMap); bool gotBeamgates_ns = m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); bool gotTimeStamps_ns = m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); @@ -986,7 +1052,7 @@ void LAPPDTreeMaker::LoadLAPPDMapInfo() bool gotTSCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDTSCorrection", LAPPDTSCorrection); bool gotDBGCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDBGCorrection", LAPPDBGCorrection); bool gotOSInMinusPS = m_data->Stores["ANNIEEvent"]->Get("LAPPDOSInMinusPS", LAPPDOSInMinusPS); - //cout << "LAPPDTreeMaker::LoadLAPPDMapInfo() get map = " << getMap << endl; + // cout << "LAPPDTreeMaker::LoadLAPPDMapInfo() get map = " << getMap << endl; if (getMap) { diff --git a/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h b/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h index 86650ba0d..9fc491e2b 100644 --- a/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h +++ b/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h @@ -171,6 +171,15 @@ class LAPPDTreeMaker : public Tool std::map LAPPDTSCorrection; std::map LAPPDBGCorrection; std::map LAPPDOSInMinusPS; + + + uint64_t LTSRaw; + uint64_t LBGRaw; + uint64_t LOffset_ns; + int LTSCorrection; + int LBGCorrection; + int LOSInMinusPS; + uint64_t CTCPrimeTriggerTime; }; #endif diff --git a/configfiles/LAPPDProcessedAna/ConfigPlot b/configfiles/LAPPDProcessedAna/ConfigPlot index 60a9a15d8..ab05732bf 100755 --- a/configfiles/LAPPDProcessedAna/ConfigPlot +++ b/configfiles/LAPPDProcessedAna/ConfigPlot @@ -76,12 +76,12 @@ ThresRecoInputWaveLabel BLsubtractedLAPPDData ThresRecoOutputPulseLabel LAPPDPulses ThresRecoOutputHitLabel LAPPDHits -useMaxTime 1 +useMaxTime 1 # 1: use max bin as pulse time, 0: use gaus fit bin as pulse peak time #signalSpeedOnStrip 0.6667 signalSpeedOnStrip 0.567 #1.69982/2.99792 triggerBoardDelay 0 loadPrintMRDinfo 1 -useRange -1 #set this to 0 for using pulse start time as the saved pulse time, 1 for high, -1 for using peak time +useRange 0 #set this to 0 for using pulse start time as the saved pulse time, 1 for high, -1 for using peak time plusClockBit 0 savePositionOnStrip 1 @@ -116,7 +116,7 @@ LAPPDPlotInputWaveLabel BLsubtractedLAPPDData #LAPPDPlotInputWaveLabel LAPPDWaveforms #LAPPDPlotInputWaveLabel AlignedLAPPDData #LAPPDPlotInputWaveLabel RawLAPPDData -LAPPDPlotsVerbosity 5 +LAPPDPlotsVerbosity 0 CanvasXSubPlotNumber 2 CanvasYSubPlotNumber 2 canvasMargin 0.1 diff --git a/configfiles/LAPPDProcessedAna/Configs b/configfiles/LAPPDProcessedAna/Configs index e306132d2..472ab885f 100644 --- a/configfiles/LAPPDProcessedAna/Configs +++ b/configfiles/LAPPDProcessedAna/Configs @@ -8,7 +8,7 @@ NUM_VECTOR_METADATA 103 #Fixed META vector size LAPPDchannelOffset 1000 NChannels 30 -LAPPDStoreReadInVerbosity 10 +LAPPDStoreReadInVerbosity 0 mergingModeReadIn 0 RawDataInputWavLabel RawWaveform diff --git a/configfiles/LAPPDProcessedAna/ToolChainConfig b/configfiles/LAPPDProcessedAna/ToolChainConfig index 15e9f5283..b94bec1c3 100644 --- a/configfiles/LAPPDProcessedAna/ToolChainConfig +++ b/configfiles/LAPPDProcessedAna/ToolChainConfig @@ -19,6 +19,6 @@ service_kick_sec -1 Tools_File configfiles/LAPPDProcessedAna/ToolsConfig ## list of tools to run and their config files ##### Run Type ##### -Inline 100 ## number of Execute steps in program, -1 infinite loop that is ended by user +Inline -1 ## number of Execute steps in program, -1 infinite loop that is ended by user Interactive 0 ## set to 1 if you want to run the code interactively diff --git a/configfiles/LAPPDProcessedAna/list.txt b/configfiles/LAPPDProcessedAna/list.txt index fa6752711..c202b69e1 100644 --- a/configfiles/LAPPDProcessedAna/list.txt +++ b/configfiles/LAPPDProcessedAna/list.txt @@ -1 +1,11 @@ -/exp/annie/app/users/yuefeng/MyForkANNIE/MyForkRewiriting/testPRTA/ToolAnalysis/FilteredAllLAPPDData +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4804 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4805 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4825 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4831 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4839 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4843 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4852 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4856 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4880 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4890 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4897 From c2b8735753a8820ae23bad053b60abe9b3aab854 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Mon, 24 Jun 2024 13:32:45 -0500 Subject: [PATCH 055/163] Update IFBeamDBInterfaceV2.cpp Accidentally included the same verbose statement twice --- .../BeamFetcherV2/IFBeamDBInterfaceV2.cpp | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp b/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp index 08b9b8e87..5c8724c55 100644 --- a/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp +++ b/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp @@ -314,42 +314,6 @@ IFBeamDBInterfaceV2::ParseDBResponseBundleSpan(const std::string& response) cons std::cout << "Total number of elements in retMap: " << total << std::endl; std::cout << "Size of retMap is " << retMap.size() << std::endl; - - //check each timestamp in the retMap, to see if it have all the devices in the requiredDevices map keys, if yes, continue - //if not, create entry for that device at retMap[TS], use the data type from the value of requiredDevices - // use value as -9999, unit as doulbe, timestamp = TS - for (auto &ts : retMap) { - /*cout<<"size of this timestamp is "< Date: Mon, 24 Jun 2024 13:33:43 -0500 Subject: [PATCH 056/163] Rename list.txt to my_files.txt consistency for grid submissions (same .txt file) --- configfiles/EventBuilderV2/{list.txt => my_files.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename configfiles/EventBuilderV2/{list.txt => my_files.txt} (100%) diff --git a/configfiles/EventBuilderV2/list.txt b/configfiles/EventBuilderV2/my_files.txt similarity index 100% rename from configfiles/EventBuilderV2/list.txt rename to configfiles/EventBuilderV2/my_files.txt From 8ff9f62a04116a0a2d5e5028c3ed0c6eac636b91 Mon Sep 17 00:00:00 2001 From: Yue Date: Mon, 24 Jun 2024 17:02:49 -0500 Subject: [PATCH 057/163] Add LAPPD pulse and hit information to PhaseeIITreeMaker Add LAPPD tools to BeamClusterAnalysis tool chain Changes to be committed: modified: UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp modified: UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp modified: UserTools/PhaseIITreeMaker/PhaseIITreeMaker.h modified: configfiles/BeamClusterAnalysis/LoadANNIEEventConfig modified: configfiles/BeamClusterAnalysis/PhaseIITreeMakerConfig modified: configfiles/BeamClusterAnalysis/ToolsConfig modified: configfiles/BeamClusterAnalysis/my_inputs.txt --- .../BeamFetcherV2/IFBeamDBInterfaceV2.cpp | 35 --- .../PhaseIITreeMaker/PhaseIITreeMaker.cpp | 209 +++++++++++++++++- UserTools/PhaseIITreeMaker/PhaseIITreeMaker.h | 31 +++ .../BeamClusterAnalysis/LoadANNIEEventConfig | 2 +- .../PhaseIITreeMakerConfig | 1 + configfiles/BeamClusterAnalysis/ToolsConfig | 7 + configfiles/BeamClusterAnalysis/my_inputs.txt | 95 +------- 7 files changed, 255 insertions(+), 125 deletions(-) diff --git a/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp b/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp index 08b9b8e87..5224d5d66 100644 --- a/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp +++ b/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp @@ -315,41 +315,6 @@ IFBeamDBInterfaceV2::ParseDBResponseBundleSpan(const std::string& response) cons std::cout << "Size of retMap is " << retMap.size() << std::endl; - //check each timestamp in the retMap, to see if it have all the devices in the requiredDevices map keys, if yes, continue - //if not, create entry for that device at retMap[TS], use the data type from the value of requiredDevices - // use value as -9999, unit as doulbe, timestamp = TS - for (auto &ts : retMap) { - /*cout<<"size of this timestamp is "<Branch("GroupedTriggerTime",&fGroupedTriggerTime); fPhaseIITankClusterTree->Branch("GroupedTriggerWord",&fGroupedTriggerWord); + + if(LAPPDReco_fill) + { + fPhaseIITankClusterTree->Branch("LAPPD_PulseIDs",&fLAPPD_IDs); + fPhaseIITankClusterTree->Branch("LAPPD_ChannelID",&fChannelID); + fPhaseIITankClusterTree->Branch("LAPPD_PeakTime",&fPulsePeakTime); + fPhaseIITankClusterTree->Branch("LAPPD_PeakAmp",&fPulsePeakAmp); + fPhaseIITankClusterTree->Branch("LAPPD_Charge",&fPulseCharge); + fPhaseIITankClusterTree->Branch("LAPPD_PulseStart",&fPulseStart); + fPhaseIITankClusterTree->Branch("LAPPD_PulseEnd",&fPulseEnd); + fPhaseIITankClusterTree->Branch("LAPPD_PulseWidth",&fPulseWidth); + fPhaseIITankClusterTree->Branch("LAPPD_PulseSide",&fPulseSide); + fPhaseIITankClusterTree->Branch("LAPPD_PulseStripNum",&fPulseStripNum); + + fPhaseIITankClusterTree->Branch("LAPPDID_Hit",&fLAPPDHit_IDs); + fPhaseIITankClusterTree->Branch("LAPPDHitChannel",&fLAPPDHitChannel); + fPhaseIITankClusterTree->Branch("LAPPDHitStrip",&fLAPPDHitStrip); + fPhaseIITankClusterTree->Branch("LAPPDHitTime",&fLAPPDHitTime); + fPhaseIITankClusterTree->Branch("LAPPDHitAmp",&fLAPPDHitAmp); + fPhaseIITankClusterTree->Branch("LAPPDHitParallelPos",&fLAPPDHitParallelPos); + fPhaseIITankClusterTree->Branch("LAPPDHitTransversePos",&fLAPPDHitTransversePos); + fPhaseIITankClusterTree->Branch("LAPPDHitP1StartTime",&fLAPPDHitP1StartTime); + fPhaseIITankClusterTree->Branch("LAPPDHitP2StartTime",&fLAPPDHitP2StartTime); + fPhaseIITankClusterTree->Branch("LAPPDHitP1EndTime",&fLAPPDHitP1EndTime); + fPhaseIITankClusterTree->Branch("LAPPDHitP2EndTime",&fLAPPDHitP2EndTime); + } } } @@ -187,6 +214,33 @@ bool PhaseIITreeMaker::Initialise(std::string configfile, DataModel &data){ fPhaseIIMRDClusterTree->Branch("GroupedTriggerTime",&fGroupedTriggerTime); fPhaseIIMRDClusterTree->Branch("GroupedTriggerWord",&fGroupedTriggerWord); + + if(LAPPDReco_fill) + { + fPhaseIIMRDClusterTree->Branch("LAPPD_PulseIDs",&fLAPPD_IDs); + fPhaseIIMRDClusterTree->Branch("LAPPD_ChannelID",&fChannelID); + fPhaseIIMRDClusterTree->Branch("LAPPD_PeakTime",&fPulsePeakTime); + fPhaseIIMRDClusterTree->Branch("LAPPD_PeakAmp",&fPulsePeakAmp); + fPhaseIIMRDClusterTree->Branch("LAPPD_Charge",&fPulseCharge); + fPhaseIIMRDClusterTree->Branch("LAPPD_PulseStart",&fPulseStart); + fPhaseIIMRDClusterTree->Branch("LAPPD_PulseEnd",&fPulseEnd); + fPhaseIIMRDClusterTree->Branch("LAPPD_PulseWidth",&fPulseWidth); + fPhaseIIMRDClusterTree->Branch("LAPPD_PulseSide",&fPulseSide); + fPhaseIIMRDClusterTree->Branch("LAPPD_PulseStripNum",&fPulseStripNum); + + fPhaseIIMRDClusterTree->Branch("LAPPDID_Hit",&fLAPPDHit_IDs); + fPhaseIIMRDClusterTree->Branch("LAPPDHitChannel",&fLAPPDHitChannel); + fPhaseIIMRDClusterTree->Branch("LAPPDHitStrip",&fLAPPDHitStrip); + fPhaseIIMRDClusterTree->Branch("LAPPDHitTime",&fLAPPDHitTime); + fPhaseIIMRDClusterTree->Branch("LAPPDHitAmp",&fLAPPDHitAmp); + fPhaseIIMRDClusterTree->Branch("LAPPDHitParallelPos",&fLAPPDHitParallelPos); + fPhaseIIMRDClusterTree->Branch("LAPPDHitTransversePos",&fLAPPDHitTransversePos); + fPhaseIIMRDClusterTree->Branch("LAPPDHitP1StartTime",&fLAPPDHitP1StartTime); + fPhaseIIMRDClusterTree->Branch("LAPPDHitP2StartTime",&fLAPPDHitP2StartTime); + fPhaseIIMRDClusterTree->Branch("LAPPDHitP1EndTime",&fLAPPDHitP1EndTime); + fPhaseIIMRDClusterTree->Branch("LAPPDHitP2EndTime",&fLAPPDHitP2EndTime); + } + } } @@ -439,6 +493,32 @@ bool PhaseIITreeMaker::Initialise(std::string configfile, DataModel &data){ fPhaseIITrigTree->Branch("GroupedTriggerTime",&fGroupedTriggerTime); fPhaseIITrigTree->Branch("GroupedTriggerWord",&fGroupedTriggerWord); + + if(LAPPDReco_fill) + { + fPhaseIITrigTree->Branch("LAPPD_PulseIDs",&fLAPPD_IDs); + fPhaseIITrigTree->Branch("LAPPD_ChannelID",&fChannelID); + fPhaseIITrigTree->Branch("LAPPD_PeakTime",&fPulsePeakTime); + fPhaseIITrigTree->Branch("LAPPD_PeakAmp",&fPulsePeakAmp); + fPhaseIITrigTree->Branch("LAPPD_Charge",&fPulseCharge); + fPhaseIITrigTree->Branch("LAPPD_PulseStart",&fPulseStart); + fPhaseIITrigTree->Branch("LAPPD_PulseEnd",&fPulseEnd); + fPhaseIITrigTree->Branch("LAPPD_PulseWidth",&fPulseWidth); + fPhaseIITrigTree->Branch("LAPPD_PulseSide",&fPulseSide); + fPhaseIITrigTree->Branch("LAPPD_PulseStripNum",&fPulseStripNum); + + fPhaseIITrigTree->Branch("LAPPDID_Hit",&fLAPPDHit_IDs); + fPhaseIITrigTree->Branch("LAPPDHitChannel",&fLAPPDHitChannel); + fPhaseIITrigTree->Branch("LAPPDHitStrip",&fLAPPDHitStrip); + fPhaseIITrigTree->Branch("LAPPDHitTime",&fLAPPDHitTime); + fPhaseIITrigTree->Branch("LAPPDHitAmp",&fLAPPDHitAmp); + fPhaseIITrigTree->Branch("LAPPDHitParallelPos",&fLAPPDHitParallelPos); + fPhaseIITrigTree->Branch("LAPPDHitTransversePos",&fLAPPDHitTransversePos); + fPhaseIITrigTree->Branch("LAPPDHitP1StartTime",&fLAPPDHitP1StartTime); + fPhaseIITrigTree->Branch("LAPPDHitP2StartTime",&fLAPPDHitP2StartTime); + fPhaseIITrigTree->Branch("LAPPDHitP1EndTime",&fLAPPDHitP1EndTime); + fPhaseIITrigTree->Branch("LAPPDHitP2EndTime",&fLAPPDHitP2EndTime); + } } } return true; @@ -546,9 +626,10 @@ bool PhaseIITreeMaker::Execute(){ m_data->Stores.at("ANNIEEvent")->Get("RunType",fRunType); m_data->Stores.at("ANNIEEvent")->Get("RunStartTime",fStartTime); - + uint64_t primaryTrigTime = 0; + m_data->Stores.at("ANNIEEvent")->Get("PrimaryTriggerTime", primaryTrigTime); - fStartTime_Tree = (ULong64_t) fStartTime; + fStartTime_Tree = (ULong64_t) primaryTrigTime; // ANNIE Event number m_data->Stores.at("ANNIEEvent")->Get("EventTimeTank",fEventTimeTank); fEventTimeTank_Tree = (ULong64_t) fEventTimeTank; @@ -794,7 +875,9 @@ bool PhaseIITreeMaker::Execute(){ m_data->Stores.at("ANNIEEvent")->Get("SubrunNumber",fSubrunNumber); m_data->Stores.at("ANNIEEvent")->Get("RunType",fRunType); m_data->Stores.at("ANNIEEvent")->Get("RunStartTime",fStartTime); - fStartTime_Tree = (ULong64_t) fStartTime; + uint64_t primaryTrigTime = 0; + m_data->Stores.at("ANNIEEvent")->Get("PrimaryTriggerTime", primaryTrigTime); + fStartTime_Tree = (ULong64_t) primaryTrigTime; m_data->Stores.at("ANNIEEvent")->Get("EventNumber",fEventNumber); m_data->Stores.at("ANNIEEvent")->Get("EventTimeTank",fEventTimeTank); fEventTimeTank_Tree = (ULong64_t) fEventTimeTank; @@ -827,7 +910,9 @@ bool PhaseIITreeMaker::Execute(){ m_data->Stores.at("ANNIEEvent")->Get("SubrunNumber",fSubrunNumber); m_data->Stores.at("ANNIEEvent")->Get("RunType",fRunType); m_data->Stores.at("ANNIEEvent")->Get("RunStartTime",fStartTime); - fStartTime_Tree = (ULong64_t) fStartTime; + uint64_t primaryTrigTime = 0; + m_data->Stores.at("ANNIEEvent")->Get("PrimaryTriggerTime", primaryTrigTime); + fStartTime_Tree = (ULong64_t) primaryTrigTime; // ANNIE Event number m_data->Stores.at("ANNIEEvent")->Get("EventNumber",fEventNumber); @@ -1163,6 +1248,33 @@ void PhaseIITreeMaker::ResetVariables() { fGroupedTriggerTime.clear(); fGroupedTriggerWord.clear(); + + lappdPulses.clear(); + lappdHits.clear(); + + fLAPPD_IDs.clear(); + fChannelID.clear(); + fPulsePeakTime.clear(); + fPulseCharge.clear(); + fPulsePeakAmp.clear(); + fPulseStart.clear(); + fPulseEnd.clear(); + fPulseWidth.clear(); + fPulseSide.clear(); + fPulseStripNum.clear(); + + fLAPPDHit_IDs.clear(); + fLAPPDHitChannel.clear(); + fLAPPDHitStrip.clear(); + fLAPPDHitTime.clear(); + fLAPPDHitAmp.clear(); + fLAPPDHitParallelPos.clear(); + fLAPPDHitTransversePos.clear(); + fLAPPDHitP1StartTime.clear(); + fLAPPDHitP2StartTime.clear(); + fLAPPDHitP1EndTime.clear(); + fLAPPDHitP2EndTime.clear(); + } } @@ -1997,6 +2109,93 @@ void PhaseIITreeMaker::LoadLAPPDData() FillLAPPDData(); //print the content of fDataStreams, and the size of data map //cout<<"Found LAPPDData, LAPPDDataMap Size: "<Stores["ANNIEEvent"]->Get("LAPPDPulses", lappdPulses); + if(gotPulse) + { + + std::map>>::iterator it; + for (it = lappdPulses.begin(); it != lappdPulses.end(); it++) + { + int stripno = it->first; + vector> stripPulses = it->second; + + vector pulse0 = stripPulses.at(0); + vector pulse1 = stripPulses.at(1); + for (int i = 0; i < pulse0.size(); i++) + { + fPulseSide.push_back(0); + LAPPDPulse thisPulse = pulse0.at(i); + fLAPPD_IDs.push_back(thisPulse.GetTubeId()); + fChannelID.push_back(thisPulse.GetChannelID()); + fPulseStripNum.push_back(stripno); + fPulsePeakTime.push_back(thisPulse.GetTime()); + fPulseCharge.push_back(thisPulse.GetCharge()); + fPulsePeakAmp.push_back(thisPulse.GetPeak()); + fPulseStart.push_back(thisPulse.GetLowRange()); + fPulseEnd.push_back(thisPulse.GetHiRange()); + fPulseWidth.push_back(thisPulse.GetHiRange() - thisPulse.GetLowRange()); + } + for(int i = 0; iStores["ANNIEEvent"]->Get("LAPPDHits", lappdHits); + + if(gotHit) + { + std::map>::iterator it; + for (it = lappdHits.begin(); it != lappdHits.end(); it++) + { + int stripno = it->first; + vector stripHits = it->second; + for (int i = 0; i < stripHits.size(); i++) + { + LAPPDHit thisHit = stripHits.at(i); + fLAPPDHit_IDs.push_back(thisHit.GetTubeId()); + fLAPPDHitStrip.push_back(stripno); + fLAPPDHitTime.push_back(thisHit.GetTime()); + fLAPPDHitAmp.push_back(thisHit.GetCharge()); + vector position = thisHit.GetPosition(); + /* + XPosTank = position.at(0); + YPosTank = position.at(1); + ZPosTank = position.at(2);*/ + vector localPosition = thisHit.GetLocalPosition(); + fLAPPDHitParallelPos.push_back(localPosition.at(0)); + fLAPPDHitTransversePos.push_back(localPosition.at(1)); + fLAPPDHitP1StartTime.push_back(thisHit.GetPulse1StartTime()); + fLAPPDHitP2StartTime.push_back(thisHit.GetPulse2StartTime()); + fLAPPDHitP1EndTime.push_back(thisHit.GetPulse1LastTime()); + fLAPPDHitP2EndTime.push_back(thisHit.GetPulse2LastTime()); } -} \ No newline at end of file + } + } +} diff --git a/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.h b/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.h index c3adca9ad..b26e8c9f1 100644 --- a/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.h +++ b/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.h @@ -22,6 +22,8 @@ #include "TimeClass.h" #include "BeamStatus.h" #include "PsecData.h" +#include "LAPPDPulse.h" +#include "LAPPDHit.h" class PhaseIITreeMaker: public Tool { @@ -54,6 +56,9 @@ class PhaseIITreeMaker: public Tool { void LoadLAPPDData(); void FillLAPPDData(); + void FillLAPPDHit(); + void FillLAPPDPulse(); + private: //General variables @@ -393,6 +398,32 @@ class PhaseIITreeMaker: public Tool { double E_TOR860, E_TOR875, THCURR, BTJT2, HP875, VP875, HPTG1, VPTG1, HPTG2, VPTG2, BTH2T2; + bool LAPPDReco_fill = 0; + std::map>> lappdPulses; + std::map> lappdHits; + + vector fLAPPD_IDs; + vector fChannelID; + vector fPulsePeakTime; + vector fPulseCharge; + vector fPulsePeakAmp; + vector fPulseStart; + vector fPulseEnd; + vector fPulseWidth; + vector fPulseSide; + vector fPulseStripNum; + + vector fLAPPDHit_IDs; + vector fLAPPDHitChannel; + vector fLAPPDHitStrip; + vector fLAPPDHitTime; + vector fLAPPDHitAmp; + vector fLAPPDHitParallelPos; + vector fLAPPDHitTransversePos; + vector fLAPPDHitP1StartTime; + vector fLAPPDHitP2StartTime; + vector fLAPPDHitP1EndTime; + vector fLAPPDHitP2EndTime; }; diff --git a/configfiles/BeamClusterAnalysis/LoadANNIEEventConfig b/configfiles/BeamClusterAnalysis/LoadANNIEEventConfig index a26db8731..73ea107d7 100644 --- a/configfiles/BeamClusterAnalysis/LoadANNIEEventConfig +++ b/configfiles/BeamClusterAnalysis/LoadANNIEEventConfig @@ -1,4 +1,4 @@ -verbose 0 +verbose 1 FileForListOfInputs ./configfiles/BeamClusterAnalysis/my_inputs.txt EventOffset 0 GlobalEvNr 1 diff --git a/configfiles/BeamClusterAnalysis/PhaseIITreeMakerConfig b/configfiles/BeamClusterAnalysis/PhaseIITreeMakerConfig index 5afabc7ea..991caba81 100644 --- a/configfiles/BeamClusterAnalysis/PhaseIITreeMakerConfig +++ b/configfiles/BeamClusterAnalysis/PhaseIITreeMakerConfig @@ -17,3 +17,4 @@ IsData 1 HasGenie 0 LAPPDData_fill 1 +LAPPDReco_fill 1 diff --git a/configfiles/BeamClusterAnalysis/ToolsConfig b/configfiles/BeamClusterAnalysis/ToolsConfig index 021e2f2f6..98325bb76 100644 --- a/configfiles/BeamClusterAnalysis/ToolsConfig +++ b/configfiles/BeamClusterAnalysis/ToolsConfig @@ -7,4 +7,11 @@ myFindMrdTracks FindMrdTracks configfiles/BeamClusterAnalysis/FindMrdTracksConfi myClusterFinder ClusterFinder ./configfiles/BeamClusterAnalysis/ClusterFinderConfig myClusterClassifiers ClusterClassifiers ./configfiles/BeamClusterAnalysis/ClusterClassifiersConfig myEventSelector EventSelector ./configfiles/BeamClusterAnalysis/EventSelectorConfig + +LAPPDLoadStore LAPPDLoadStore configfiles/LAPPDProcessedAna/Configs +LAPPDStoreReorder LAPPDStoreReorder configfiles/LAPPDProcessedAna/ConfigStoreReadIn +LAPPDTimeAlignment LAPPDTimeAlignment configfiles/LAPPDProcessedAna/ConfigPreProcess +LAPPDBaseline LAPPDBaseline configfiles/LAPPDProcessedAna/ConfigPreProcess +LAPPDThresReco LAPPDThresReco configfiles/LAPPDProcessedAna/ConfigPlot + myPhaseIITreeMaker PhaseIITreeMaker ./configfiles/BeamClusterAnalysis/PhaseIITreeMakerConfig diff --git a/configfiles/BeamClusterAnalysis/my_inputs.txt b/configfiles/BeamClusterAnalysis/my_inputs.txt index 030e62e88..302349a95 100644 --- a/configfiles/BeamClusterAnalysis/my_inputs.txt +++ b/configfiles/BeamClusterAnalysis/my_inputs.txt @@ -1,84 +1,11 @@ -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p4 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p5 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p6 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p7 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p8 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p9 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p10 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p11 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p12 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p13 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p14 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p15 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p29 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p30 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p31 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p32 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p33 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p34 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p35 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p39 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p40 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p41 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p42 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p43 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p44 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p45 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p74 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p75 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p76 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p77 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p78 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p79 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p80 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p224 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p225 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p226 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p227 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p349 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p350 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p351 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p352 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p353 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p354 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p355 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p369 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p370 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p371 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p372 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p373 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p374 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p375 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p434 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p435 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p436 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p437 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p438 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p439 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p440 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p441 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p442 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p443 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p444 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p445 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p474 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p475 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p476 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p477 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p478 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p479 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p480 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p599 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p600 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p601 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p602 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p603 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p604 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p605 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p624 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p625 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p626 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p627 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p628 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p629 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4890/ProcessedData_PMTMRDLAPPD_R4890S0p630 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredMRDNoVetoData_4804 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredMRDNoVetoData_4805 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredMRDNoVetoData_4825 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredMRDNoVetoData_4831 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredMRDNoVetoData_4839 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredMRDNoVetoData_4843 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredMRDNoVetoData_4852 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredMRDNoVetoData_4856 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredMRDNoVetoData_4880 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredMRDNoVetoData_4890 +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredMRDNoVetoData_4897 From 006a88a22d564c59f9863be0ea65ffb256ca15dd Mon Sep 17 00:00:00 2001 From: Yue Date: Tue, 25 Jun 2024 11:27:24 -0500 Subject: [PATCH 058/163] Fix a bug in trigger data decoder about the verbosity Changes to be committed: modified: UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp --- .../TriggerDataDecoder/TriggerDataDecoder.cpp | 26 +++---------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp b/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp index c6391c11c..d0888da6b 100644 --- a/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp +++ b/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp @@ -60,15 +60,13 @@ bool TriggerDataDecoder::Initialise(std::string configfile, DataModel &data){ bool TriggerDataDecoder::Execute(){ if (mode == "EventBuilding"){ - -processed_sources.clear(); -processed_ns.clear(); - m_data->CStore.Set("NewCTCDataAvailable",false); bool PauseCTCDecoding = false; m_data->CStore.Get("PauseCTCDecoding",PauseCTCDecoding); - if (PauseCTCDecoding && verbosity > 0){ - std::cout << "TriggerDataDecoder tool: Pausing trigger decoding to let Tank and MRD data catch up..." << std::endl; + if (PauseCTCDecoding) + if(verbosity > 0){ + std::cout << "TriggerDataDecoder tool: Pausing trigger decoding to let Tank and MRD data catch up..." << std::endl; + } return true; } //Clear decoding maps if a new run/subrun is encountered @@ -212,22 +210,6 @@ bool TriggerDataDecoder::Finalise(){ StoreC1C2.Set("c2",c2); StoreC1C2.Save(storec1c2.c_str()); }*/ - ofstream trigDebug; - trigDebug.open("TrigDecoderDebug.txt"); - int i = 0; - for (auto it = TimeToTriggerWordMapComplete->begin(); it != TimeToTriggerWordMapComplete->end(); ++it) - { - if (i > 10000) - break; - trigDebug << it->first << " "; - for (auto trig = it->second.begin(); trig != it->second.end(); ++trig) - { - trigDebug << *trig << " "; - } - trigDebug << endl; - i++; - } - trigDebug.close(); return true; } From 8e9a68183d153c7ad3cf84635e81a3b1dea208af Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Tue, 25 Jun 2024 11:34:56 -0500 Subject: [PATCH 059/163] Update TriggerDataDecoder.cpp Verbosity was accidentally a condition on pausing the decoding - this caused the toolchain to dramatically slow down if verbose = 0 --- UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp b/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp index c6391c11c..b17aa26b8 100644 --- a/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp +++ b/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp @@ -67,8 +67,8 @@ processed_ns.clear(); m_data->CStore.Set("NewCTCDataAvailable",false); bool PauseCTCDecoding = false; m_data->CStore.Get("PauseCTCDecoding",PauseCTCDecoding); - if (PauseCTCDecoding && verbosity > 0){ - std::cout << "TriggerDataDecoder tool: Pausing trigger decoding to let Tank and MRD data catch up..." << std::endl; + if (PauseCTCDecoding){ + if(verbosity>0) std::cout << "TriggerDataDecoder tool: Pausing trigger decoding to let Tank and MRD data catch up..." << std::endl; return true; } //Clear decoding maps if a new run/subrun is encountered From 8c8e82ee0b1990403fabb8e7079ad0b5c34cee7a Mon Sep 17 00:00:00 2001 From: Yue Date: Tue, 25 Jun 2024 11:37:15 -0500 Subject: [PATCH 060/163] fix bug again Changes to be committed: modified: UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp --- .../TriggerDataDecoder/TriggerDataDecoder.cpp | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp b/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp index d0888da6b..435f5bf3e 100644 --- a/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp +++ b/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp @@ -60,13 +60,17 @@ bool TriggerDataDecoder::Initialise(std::string configfile, DataModel &data){ bool TriggerDataDecoder::Execute(){ if (mode == "EventBuilding"){ + +processed_sources.clear(); +processed_ns.clear(); + m_data->CStore.Set("NewCTCDataAvailable",false); bool PauseCTCDecoding = false; m_data->CStore.Get("PauseCTCDecoding",PauseCTCDecoding); - if (PauseCTCDecoding) - if(verbosity > 0){ - std::cout << "TriggerDataDecoder tool: Pausing trigger decoding to let Tank and MRD data catch up..." << std::endl; - } + if (PauseCTCDecoding ){ + if(verbosity > 0){ + std::cout << "TriggerDataDecoder tool: Pausing trigger decoding to let Tank and MRD data catch up..." << std::endl; + } return true; } //Clear decoding maps if a new run/subrun is encountered @@ -210,6 +214,22 @@ bool TriggerDataDecoder::Finalise(){ StoreC1C2.Set("c2",c2); StoreC1C2.Save(storec1c2.c_str()); }*/ + ofstream trigDebug; + trigDebug.open("TrigDecoderDebug.txt"); + int i = 0; + for (auto it = TimeToTriggerWordMapComplete->begin(); it != TimeToTriggerWordMapComplete->end(); ++it) + { + if (i > 10000) + break; + trigDebug << it->first << " "; + for (auto trig = it->second.begin(); trig != it->second.end(); ++trig) + { + trigDebug << *trig << " "; + } + trigDebug << endl; + i++; + } + trigDebug.close(); return true; } From 700fae936691ffabab5864c8cba6f3e3b318bcd5 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Tue, 25 Jun 2024 12:36:44 -0500 Subject: [PATCH 061/163] Update EBLoadRawConfig --- configfiles/EventBuilderV2/EBLoadRawConfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configfiles/EventBuilderV2/EBLoadRawConfig b/configfiles/EventBuilderV2/EBLoadRawConfig index 4f5af443e..083ae9111 100644 --- a/configfiles/EventBuilderV2/EBLoadRawConfig +++ b/configfiles/EventBuilderV2/EBLoadRawConfig @@ -1,7 +1,7 @@ verbosityEBLoadRaw 2 ReadTriggerOverlap 1 -InputFile ./configfiles/EventBuilderV2/list.txt +InputFile ./configfiles/EventBuilderV2/my_files.txt LoadPMT 1 LoadMRD 1 From 162c8957779014b63856da94c32e28e02b39ba7c Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Tue, 25 Jun 2024 12:37:08 -0500 Subject: [PATCH 062/163] Update EBSaverConfig Changed to reflect the output file created from the BeamFetcherV2 tool --- configfiles/EventBuilderV2/EBSaverConfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configfiles/EventBuilderV2/EBSaverConfig b/configfiles/EventBuilderV2/EBSaverConfig index 781d748e2..7cf77b14f 100644 --- a/configfiles/EventBuilderV2/EBSaverConfig +++ b/configfiles/EventBuilderV2/EBSaverConfig @@ -7,4 +7,4 @@ saveLAPPD 1 saveRunInfo 1 saveBeamInfo 1 -beamInfoFileName BeamInfo.root +beamInfoFileName beamfetcher_tree.root From 8862a8c7aa2680103c22c4757f8d099a99ad4e65 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:45:08 -0500 Subject: [PATCH 063/163] Update CreateMyList.sh added hard coded raw data path so that users can simply supply the run number and it will find the part files --- configfiles/PreProcessTrigOverlap/CreateMyList.sh | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/configfiles/PreProcessTrigOverlap/CreateMyList.sh b/configfiles/PreProcessTrigOverlap/CreateMyList.sh index e72ac51a6..04e1aa7a5 100755 --- a/configfiles/PreProcessTrigOverlap/CreateMyList.sh +++ b/configfiles/PreProcessTrigOverlap/CreateMyList.sh @@ -1,17 +1,19 @@ if [ "$#" -ne 2 ]; then - echo "Usage: ./CreateMyList.sh DIR RUN" - echo "Specified input variable must contain the directory where the files are stored, second variable run number" + echo "Usage: ./CreateMyList.sh RUN" + echo "Specified input variable must contain the run number" exit 1 fi -FILEDIR=$1 -RUN=$2 +RUN=$1 +DIR=/pnfs/annie/persistent/raw/raw/ NUMFILES=$(ls -1q ${FILEDIR}/RAWDataR${RUN}* | wc -l) echo "NUMBER OF FILES IN ${FILEDIR}: ${NUMFILES}" +rm my_files.txt + for p in $(seq 0 $(($NUMFILES -1 ))) do - echo "${FILEDIR}/RAWDataR${RUN}S0p${p}" >> my_files.txt + echo "${DIR}${RUN}/RAWDataR${RUN}S0p${p}" >> my_files.txt done From 4b71db52b309c188893686c41f232c66cab47635 Mon Sep 17 00:00:00 2001 From: Yue Date: Tue, 25 Jun 2024 17:55:38 -0500 Subject: [PATCH 064/163] debug for LAPPDLoad Raw and Plot after adding LoadMap functions Changes to be committed: modified: UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp modified: UserTools/LAPPDPlots/LAPPDPlots.cpp modified: UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp modified: UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.cpp modified: configfiles/EventBuilderV2/EBLoadRawConfig modified: configfiles/EventBuilderV2/EBTriggerGrouperConfig modified: configfiles/EventBuilderV2/TriggerDataDecoderConfig modified: configfiles/EventBuilderV2/my_files.txt modified: configfiles/LAPPDProcessedAna/ConfigPlot modified: configfiles/LAPPDProcessedAna/ToolChainConfig modified: configfiles/LAPPDProcessedAna/ToolsConfig modified: configfiles/LAPPDRaw/ConfigPlot modified: configfiles/LAPPDRaw/ConfigStoreReadIn modified: configfiles/LAPPDRaw/ToolsConfig modified: configfiles/LAPPDRaw/list.txt modified: configfiles/LoadGeometry/LAPPDGeometry.csv --- UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp | 37 +- UserTools/LAPPDPlots/LAPPDPlots.cpp | 69 +- .../LAPPDStoreReorder/LAPPDStoreReorder.cpp | 43 +- .../LAPPDTimeAlignment/LAPPDTimeAlignment.cpp | 38 +- configfiles/EventBuilderV2/EBLoadRawConfig | 2 +- .../EventBuilderV2/EBTriggerGrouperConfig | 2 +- .../EventBuilderV2/TriggerDataDecoderConfig | 2 +- configfiles/EventBuilderV2/my_files.txt | 4 +- configfiles/LAPPDProcessedAna/ConfigPlot | 2 +- configfiles/LAPPDProcessedAna/ToolChainConfig | 2 +- configfiles/LAPPDProcessedAna/ToolsConfig | 2 +- configfiles/LAPPDRaw/ConfigPlot | 1 + configfiles/LAPPDRaw/ConfigStoreReadIn | 2 +- configfiles/LAPPDRaw/ToolsConfig | 3 +- configfiles/LAPPDRaw/list.txt | 715 +--- configfiles/LoadGeometry/LAPPDGeometry.csv | 2890 ++++++++--------- 16 files changed, 1583 insertions(+), 2231 deletions(-) diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp index f386be6f5..7bac3bf63 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp @@ -266,6 +266,15 @@ bool LAPPDLoadStore::Execute() // save some timestamps relate to this event, for later using SaveTimeStamps(); + vector ReadedBoards; + vector ACDCReadedLAPPDID; + for (auto it = ReadBoards.begin(); it != ReadBoards.end(); it++) + { + ReadedBoards.push_back(*it); + ACDCReadedLAPPDID.push_back(LAPPD_ID); + // cout << "ReadedBoards loaded with " << *it << endl; + } + if (LAPPDStoreReadInVerbosity > 0) cout << "*************************END LAPPDStoreReadIn************************************" << endl; m_data->CStore.Set("LAPPD_ID", LAPPD_ID); @@ -276,6 +285,8 @@ bool LAPPDLoadStore::Execute() m_data->Stores["ANNIEEvent"]->Set("ACDCboards", ReadBoards); m_data->Stores["ANNIEEvent"]->Set("SortedBoards", ParaBoards); m_data->Stores["ANNIEEvent"]->Set("TriggerChannelBase", TrigChannel); + m_data->Stores["ANNIEEvent"]->Set("ACDCReadedLAPPDID", ACDCReadedLAPPDID); + m_data->Stores["ANNIEEvent"]->Set("ReadedBoards", ReadedBoards); m_data->CStore.Set("NewLAPPDDataAvailable", true); if (LAPPDStoreReadInVerbosity > 11) @@ -345,7 +356,7 @@ bool LAPPDLoadStore::Execute() { ReadedBoards.push_back(*it); ACDCReadedLAPPDID.push_back(LAPPD_ID); - //cout << "ReadedBoards loaded with " << *it << endl; + // cout << "ReadedBoards loaded with " << *it << endl; } int frametype = static_cast(Raw_buffer.size() / ReadBoards.size()); @@ -448,7 +459,7 @@ bool LAPPDLoadStore::Execute() } } - if(LAPPDStoreReadInVerbosity>0) + if (LAPPDStoreReadInVerbosity > 0) cout << "LAPPDLoadStore: Finished loading LAPPD data" << endl; return true; @@ -712,7 +723,8 @@ int LAPPDLoadStore::getParsedData(std::vector buffer, int ch_sta if (InfoWord.size() == NUM_SAMP) { data.insert(pair>(ch_start + channel_count, InfoWord)); - if(LAPPDStoreReadInVerbosity>5) cout << "inserted data to channel " << ch_start + channel_count << endl; + if (LAPPDStoreReadInVerbosity > 5) + cout << "inserted data to channel " << ch_start + channel_count << endl; InfoWord.clear(); channel_count++; } @@ -1077,7 +1089,8 @@ bool LAPPDLoadStore::ParsePSECData() bool LAPPDLoadStore::DoPedestalSubtract() { - if(LAPPDStoreReadInVerbosity>0) cout << "LAPPDLoadStore::DoPedestalSubtract()" << endl; + if (LAPPDStoreReadInVerbosity > 0) + cout << "LAPPDLoadStore::DoPedestalSubtract()" << endl; Waveform tmpWave; vector> VecTmpWave; int pedval, val; @@ -1101,16 +1114,16 @@ bool LAPPDLoadStore::DoPedestalSubtract() for (std::map>::iterator it = data.begin(); it != data.end(); ++it) // looping over the data map by channel number, from 0 to 60 { int wrongPedChannel = 0; - if(LAPPDStoreReadInVerbosity>5) - cout<<"Do Pedestal sub at Channel "<first; - + if (LAPPDStoreReadInVerbosity > 5) + cout << "Do Pedestal sub at Channel " << it->first; + for (int kvec = 0; kvec < it->second.size(); kvec++) { // loop all data point in this channel if (DoPedSubtract == 1) { auto iter = PedestalValues->find((it->first)); - if(kvec==0 && LAPPDStoreReadInVerbosity>5) - cout<first<<" with value = "<second.at(0); + if (kvec == 0 && LAPPDStoreReadInVerbosity > 5) + cout << std::fixed << ", found PedestalValues for channel " << it->first << " with value = " << iter->second.at(0); if (iter != PedestalValues->end() && iter->second.size() > kvec) { pedval = iter->second.at(kvec); @@ -1127,8 +1140,8 @@ bool LAPPDLoadStore::DoPedestalSubtract() } val = it->second.at(kvec); tmpWave.PushSample(0.3 * (double)(val - pedval)); - if(LAPPDStoreReadInVerbosity>5 && kvec<10) - cout<<", "< 5 && kvec < 10) + cout << ", " << val << "-" << pedval << "=" << 0.3 * (double)(val - pedval); } if (wrongPedChannel != 0) cout << "Pedestal value not found for channel " << wrongPedChannel << "with it->first channel" << it->first << ", LAPPD channel shift " << LAPPD_ID * 60 << endl; @@ -1137,7 +1150,7 @@ bool LAPPDLoadStore::DoPedestalSubtract() unsigned long pushChannelNo = (unsigned long)it->first; LAPPDWaveforms.insert(pair>>(pushChannelNo, VecTmpWave)); - //cout<<", Pushed to LAPPDWaveforms with channel number "<Stores["ANNIEEvent"]->Get("ACDCReadedLAPPDID", ACDCReadedLAPPDID); m_data->Stores["ANNIEEvent"]->Get("LAPPD_IDs", LAPPD_IDs); - // if (ACDCReadedLAPPDID.size() > 2) - //{ - // CanvasXSubPlotNumber = static_cast(ACDCReadedLAPPDID.size()); - // CanvasXSubPlotNumber = max element of ACDCReadedLAPPDID minus min element of ACDCReadedLAPPDID + 1 - CanvasXSubPlotNumber = *max_element(ACDCReadedLAPPDID.begin(), ACDCReadedLAPPDID.end()) - *min_element(ACDCReadedLAPPDID.begin(), ACDCReadedLAPPDID.end()) + 1; + if (LoadLAPPDMap) + CanvasXSubPlotNumber = *max_element(ACDCReadedLAPPDID.begin(), ACDCReadedLAPPDID.end()) - *min_element(ACDCReadedLAPPDID.begin(), ACDCReadedLAPPDID.end()) + 1; CanvasXSubPlotNumber = CanvasXSubPlotNumber * 2; CanvasTotalSubPlotNumber = CanvasXSubPlotNumber * CanvasYSubPlotNumber; - //} c->Clear(); c->Divide(CanvasXSubPlotNumber, CanvasYSubPlotNumber); @@ -129,19 +125,26 @@ bool LAPPDPlots::Execute() for (auto i : ReadBoards) cout << i << " "; cout << endl; - - cout << "ACDCReadedLAPPDID size = " << ACDCReadedLAPPDID.size() << ": "; - for (auto i : ACDCReadedLAPPDID) - cout << i << " "; - cout << endl; + if (LoadLAPPDMap) + { + cout << "ACDCReadedLAPPDID size = " << ACDCReadedLAPPDID.size() << ": "; + for (auto i : ACDCReadedLAPPDID) + cout << i << " "; + cout << endl; + } } - vector drawPositions = ACDCReadedLAPPDID; - int minID = *min_element(ACDCReadedLAPPDID.begin(), ACDCReadedLAPPDID.end()); - for (int i = 0; i < drawPositions.size(); i++) + + vector drawPositions = ReadBoards; + if (LoadLAPPDMap) { - drawPositions.at(i) = (drawPositions.at(i) - minID) * 2 + 1; - if (i % 2 == 1) - drawPositions.at(i) = drawPositions.at(i) + 1; + vector drawPositions = ACDCReadedLAPPDID; + int minID = *min_element(ACDCReadedLAPPDID.begin(), ACDCReadedLAPPDID.end()); + for (int i = 0; i < drawPositions.size(); i++) + { + drawPositions.at(i) = (drawPositions.at(i) - minID) * 2 + 1; + if (i % 2 == 1) + drawPositions.at(i) = drawPositions.at(i) + 1; + } } if (LAPPDPlotsVerbosity > 0) { @@ -151,12 +154,17 @@ bool LAPPDPlots::Execute() cout << endl; } - vector drawBoardID = ACDCReadedLAPPDID; - for (int i = 0; i < drawBoardID.size(); i++) + vector drawBoardID = ReadBoards; + + if (LoadLAPPDMap) { - drawBoardID.at(i) = drawBoardID.at(i) * 2; - if (i % 2 == 1) - drawBoardID.at(i) = (drawBoardID.at(i) + 1); + drawBoardID = ACDCReadedLAPPDID; + for (int i = 0; i < drawBoardID.size(); i++) + { + drawBoardID.at(i) = drawBoardID.at(i) * 2; + if (i % 2 == 1) + drawBoardID.at(i) = (drawBoardID.at(i) + 1); + } } if (LAPPDPlotsVerbosity > 0) { @@ -164,15 +172,18 @@ bool LAPPDPlots::Execute() for (auto i : drawBoardID) cout << i << " "; cout << endl; - cout << "LAPPDPlots execute with data " << LAPPDPlotInputWaveLabel << ", got data " << gotdata << ", data size " << lappddata.size() << ", Board IDs size " << ReadBoards.size() << ", (single) ID " << LAPPD_ID << endl; } + if (DrawEventWaveform) { vector DrawPosition = {Side0EventWaveformDrawPosition, Side1EventWaveformDrawPosition}; - if (ACDCReadedLAPPDID.size() > DrawPosition.size()) + if (LoadLAPPDMap) { - DrawPosition = drawPositions; + if (ACDCReadedLAPPDID.size() > DrawPosition.size()) + { + DrawPosition = drawPositions; + } } for (int i = 0; i < drawBoardID.size(); i++) { @@ -187,7 +198,9 @@ bool LAPPDPlots::Execute() if (LAPPDPlotsVerbosity > 0) cout << "Drawing board " << drawBoardID[i] << " at canvas position " << drawPosition << " start" << endl; std::map>> boarddata = GetDataForBoard(drawBoardID[i]); - TString HistoName = "Event" + TString::Itoa(eventNumber, 10) + "_B" + drawBoardID[i] + "_ID" + ACDCReadedLAPPDID[i]; + TString HistoName = "Event" + TString::Itoa(eventNumber, 10) + "_B" + drawBoardID[i] + "_ID"; + if (LoadLAPPDMap) + HistoName += ACDCReadedLAPPDID[i]; // convert BGTiming to string and add to HistoName // if (OnlyDrawInBeamWindow) HistoName += "_BG" + TString::Itoa(BGTiming, 10); @@ -272,7 +285,9 @@ bool LAPPDPlots::Execute() if (LAPPDPlotsVerbosity > 0) cout << "Drawing board " << drawBoardID[i] << " at position " << DrawPositionBinHist[i] << " start" << endl; std::map>> boarddata = GetDataForBoard(drawBoardID[i]); - TString HistoName = "Event" + TString::Itoa(eventNumber, 10) + "_Bin_B" + drawBoardID[i] + "_ID" + ACDCReadedLAPPDID[i]; + TString HistoName = "Event" + TString::Itoa(eventNumber, 10) + "_Bin_B" + drawBoardID[i] + "_ID"; + if (LoadLAPPDMap) + HistoName += ACDCReadedLAPPDID[i]; // convert BGTiming to string and add to HistoName // if (OnlyDrawInBeamWindow) HistoName += "_BG" + TString::Itoa(BGTiming, 10); diff --git a/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp b/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp index f09f8c615..c9dccae76 100644 --- a/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp +++ b/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp @@ -57,9 +57,9 @@ bool LAPPDStoreReorder::Execute() m_data->Stores["ANNIEEvent"]->Set(OutputWavLabel, reordereddata); if (LAPPDReorderVerbosityLevel > 1) - { - cout<<"LAPPDStoreReorder, reordered data size is "< 3) cout << "LAPPDStoreReorder::Execute() done" << endl; @@ -91,9 +91,10 @@ bool LAPPDStoreReorder::DoReorder() { Smeta26.push_back(acdcmetadata.at((meta26 * NUM_VECTOR_METADATA) + 10)); if (LAPPDReorderVerbosityLevel > 1) - {cout << "Metaword entry " << meta26 << " is " << Smeta26[meta26] << endl; - cout<<"pushed meta26 = "<< meta26<<", with value at "<<(meta26 * NUM_VECTOR_METADATA) + 10<<" is "< 2) cout << "REORDER TIME!!!! " << acdcmetadata.size() << " " << acdcmetadata.at(10) << " " << acdcmetadata.at(102) << " lappd data size is " << lappddata.size() << ", reordereddata size is " << reordereddata.size() << endl; @@ -117,11 +118,23 @@ bool LAPPDStoreReorder::DoReorder() int switchbit = 0; // Get the current board and the respective meta word int bi = (int)channelno / 30; - int LAPPDID = static_cast((channelno%1000)/60); - int beginningBoardIDofThisLAPPDID = NReadBoards.at(std::distance(ACDCReadedLAPPDID.begin(), std::find(ACDCReadedLAPPDID.begin(), ACDCReadedLAPPDID.end(), LAPPDID))); - if(LoadLAPPDMap) + int LAPPDID = static_cast((channelno % 1000) / 60); + // if (LoadLAPPDMap) + // { + int beginningBoardIDofThisLAPPDID = NReadBoards.at(std::distance(ACDCReadedLAPPDID.begin(), std::find(ACDCReadedLAPPDID.begin(), ACDCReadedLAPPDID.end(), LAPPDID))); + bi = beginningBoardIDofThisLAPPDID + bi % 2; + // }else{ + // bi = bi%2; + // } + if(LAPPDReorderVerbosityLevel>5) { - bi = beginningBoardIDofThisLAPPDID + bi%2; + //print the elements in NReadBoards, print LAPPDID; + cout << "NReadBoards size is " << NReadBoards.size() << endl; + for(int i = 0; i < NReadBoards.size(); i++) + { + cout << "NReadBoards[" << i << "] = " << NReadBoards[i] << endl; + } + cout << "LAPPDID = " << LAPPDID << endl; } unsigned short switchword = Smeta26[std::distance(NReadBoards.begin(), std::find(NReadBoards.begin(), NReadBoards.end(), bi))]; // Smeta26, 0 or 1, so switchword is the first timestmap or the second @@ -156,7 +169,7 @@ bool LAPPDStoreReorder::DoReorder() if (ibin > 255) ibin = ibin - 255; double nsamp = rwav.GetSamples()->at(ibin); - //cout << "ibin before shift is " << j << " value is " << rwav.GetSamples()->at(j) << ", after shift is " << ibin << " value is " << nsamp << endl; + // cout << "ibin before shift is " << j << " value is " << rwav.GetSamples()->at(j) << ", after shift is " << ibin << " value is " << nsamp << endl; rwavCorr.PushSample(nsamp); } @@ -164,12 +177,12 @@ bool LAPPDStoreReorder::DoReorder() } reordereddata.insert(pair>>(LAPPDchannelOffset + channelno, Vrwav)); - if(LAPPDReorderVerbosityLevel>2) - cout<<"inserted channelno: "< 2) + cout << "inserted channelno: " << LAPPDchannelOffset + channelno << ", current reorded data size is " << reordereddata.size() << endl; } - if(LAPPDReorderVerbosityLevel>1) + if (LAPPDReorderVerbosityLevel > 1) { - cout<<"LAPPDStoreReorder, reordered data size is "<CStore.Get("LAPPDana", LAPPDana); + if (!LAPPDana) + return true; oldLaser = 0; m_data->Stores["ANNIEEvent"]->Get("oldLaser", oldLaser); @@ -82,7 +86,7 @@ bool LAPPDTimeAlignment::Execute() vector ACDCReadedLAPPDID; m_data->Stores["ANNIEEvent"]->Get("ACDCReadedLAPPDID", ACDCReadedLAPPDID); - //print NReadBoards + // print NReadBoards if (FindT0VerbosityLevel > 0) { cout << "NReadBoards: "; @@ -93,7 +97,7 @@ bool LAPPDTimeAlignment::Execute() cout << endl; } // print ACDCReadedLAPPDID - if (FindT0VerbosityLevel > 0) + if (FindT0VerbosityLevel > 0 && LoadLAPPDMap) { cout << "ACDCReadedLAPPDID: "; for (int i = 0; i < ACDCReadedLAPPDID.size(); i++) @@ -108,12 +112,14 @@ bool LAPPDTimeAlignment::Execute() for (int i = 0; i < NReadBoards.size(); i++) { int bi = NReadBoards.at(i); - int thisLAPPDID = ACDCReadedLAPPDID.at(i); - //TrigChannel is 5; + int thisLAPPDID = 0; + + // TrigChannel is 5; T0channelNo = LAPPDchannelOffset + (30 * bi) + TrigChannel; if (LoadLAPPDMap) { + thisLAPPDID = ACDCReadedLAPPDID.at(i); T0channelNo = 1000 + (30 * (bi % 2)) + 60 * thisLAPPDID + TrigChannel; } @@ -122,8 +128,17 @@ bool LAPPDTimeAlignment::Execute() if (FindT0VerbosityLevel > 0) cout << "In LAPPDTimeAlignment, T0 channel:" << T0channelNo << " , InputWavlabel: " << InputWavLabel << " , LAPPDdata.size()=" << lappddata.size() << endl; + bool channelthere = lappddata.count((unsigned long)T0channelNo); if (FindT0VerbosityLevel > 1) - cout << "is the channel there? " << lappddata.count((unsigned long)T0channelNo) << endl; + cout << "is the channel there? " << channelthere << endl; + if (!channelthere) + { + int LAPPD_ID = 0; + m_data->CStore.Get("LAPPD_ID", LAPPD_ID); + T0channelNo = 1000 + (30 * (bi % 2)) + 60 * LAPPD_ID + TrigChannel; + if (FindT0VerbosityLevel > 0) + cout << " channel number " << T0channelNo << " not found, use LAPPD ID " << LAPPD_ID << " to find channel No " << T0channelNo << endl; + } itr_bi = lappddata.find((unsigned long)T0channelNo); Waveform bwav = (itr_bi->second).at(0); @@ -139,7 +154,7 @@ bool LAPPDTimeAlignment::Execute() vec_deltaT.push_back(deltaT); vec_T0signalInWindow.push_back(T0signalInWindow); vec_T0Bin.push_back(switchbit); - fittedBoardIDInMap.push_back(static_cast((T0channelNo-1000)/30)); + fittedBoardIDInMap.push_back(static_cast((T0channelNo - 1000) / 30)); if (FindT0VerbosityLevel > 0) cout << "Done finding the time, switchbit:" << switchbit << " , deltaT: " << deltaT << " , inwindow: " << T0signalInWindow << endl; @@ -170,18 +185,18 @@ bool LAPPDTimeAlignment::Execute() vector> Vwavs = itr->second; vector> Vrwav; int bi = (int)(channelno - LAPPDchannelOffset) / 30 % 2; // TODO: fix this, why loading data with board 2 and 3 have channel from 0 to 120? - int thisBoardID = static_cast((channelno-1000)/30); - if(LoadLAPPDMap) + int thisBoardID = static_cast((channelno - 1000) / 30); + if (LoadLAPPDMap) { int index = std::distance(fittedBoardIDInMap.begin(), std::find(fittedBoardIDInMap.begin(), fittedBoardIDInMap.end(), thisBoardID)); bi = index; - if(FindT0VerbosityLevel>5 && printcount<5) + if (FindT0VerbosityLevel > 5 && printcount < 5) { cout << "thisBoardID: " << thisBoardID << " , index: " << index << " , bi: " << bi << endl; printcount++; } } - + int countnumber = (channelno % 1000) % 60; if (FindT0VerbosityLevel > 2) cout << "Looping with channelno: " << channelno << " , bi: " << bi << " , countnumber: " << countnumber << endl; @@ -196,9 +211,8 @@ bool LAPPDTimeAlignment::Execute() Waveform rwavShift; int sb = vec_T0Bin[bi] + T0offset + AnalogBoardShift[countnumber]; - if(LoadLAPPDMap) + if (LoadLAPPDMap) { - } countnumber++; diff --git a/configfiles/EventBuilderV2/EBLoadRawConfig b/configfiles/EventBuilderV2/EBLoadRawConfig index 4f5af443e..083ae9111 100644 --- a/configfiles/EventBuilderV2/EBLoadRawConfig +++ b/configfiles/EventBuilderV2/EBLoadRawConfig @@ -1,7 +1,7 @@ verbosityEBLoadRaw 2 ReadTriggerOverlap 1 -InputFile ./configfiles/EventBuilderV2/list.txt +InputFile ./configfiles/EventBuilderV2/my_files.txt LoadPMT 1 LoadMRD 1 diff --git a/configfiles/EventBuilderV2/EBTriggerGrouperConfig b/configfiles/EventBuilderV2/EBTriggerGrouperConfig index 73cabfe5a..81cb3b2f2 100644 --- a/configfiles/EventBuilderV2/EBTriggerGrouperConfig +++ b/configfiles/EventBuilderV2/EBTriggerGrouperConfig @@ -1,4 +1,4 @@ -verbosityEBTG 1 +verbosityEBTG 5 GroupMode beam GroupTolerance 3000000 GroupTrigWord 14 //undelayed beam diff --git a/configfiles/EventBuilderV2/TriggerDataDecoderConfig b/configfiles/EventBuilderV2/TriggerDataDecoderConfig index 7cff259ea..a8ef6641f 100644 --- a/configfiles/EventBuilderV2/TriggerDataDecoderConfig +++ b/configfiles/EventBuilderV2/TriggerDataDecoderConfig @@ -1,3 +1,3 @@ -verbosity 1 +verbosity 0 StoreTrigOverlap 0 ReadTrigOverlap 0 diff --git a/configfiles/EventBuilderV2/my_files.txt b/configfiles/EventBuilderV2/my_files.txt index 26561a266..20d80ce49 100644 --- a/configfiles/EventBuilderV2/my_files.txt +++ b/configfiles/EventBuilderV2/my_files.txt @@ -1,2 +1,2 @@ -/pnfs/annie/persistent/raw/raw/4804/RAWDataR4804S0p332 -/pnfs/annie/persistent/raw/raw/4804/RAWDataR4804S0p333 +/pnfs/annie/persistent/raw/raw/4779/RAWDataR4779S0p0 +/pnfs/annie/persistent/raw/raw/4779/RAWDataR4779S0p1 diff --git a/configfiles/LAPPDProcessedAna/ConfigPlot b/configfiles/LAPPDProcessedAna/ConfigPlot index ab05732bf..d42ca22d3 100755 --- a/configfiles/LAPPDProcessedAna/ConfigPlot +++ b/configfiles/LAPPDProcessedAna/ConfigPlot @@ -133,4 +133,4 @@ printEventNumber 0 printLAPPDNumber 1 printEventWaveform 1 - +LoadLAPPDMap 1 diff --git a/configfiles/LAPPDProcessedAna/ToolChainConfig b/configfiles/LAPPDProcessedAna/ToolChainConfig index b94bec1c3..577961b75 100644 --- a/configfiles/LAPPDProcessedAna/ToolChainConfig +++ b/configfiles/LAPPDProcessedAna/ToolChainConfig @@ -19,6 +19,6 @@ service_kick_sec -1 Tools_File configfiles/LAPPDProcessedAna/ToolsConfig ## list of tools to run and their config files ##### Run Type ##### -Inline -1 ## number of Execute steps in program, -1 infinite loop that is ended by user +Inline 50 ## number of Execute steps in program, -1 infinite loop that is ended by user Interactive 0 ## set to 1 if you want to run the code interactively diff --git a/configfiles/LAPPDProcessedAna/ToolsConfig b/configfiles/LAPPDProcessedAna/ToolsConfig index a56fd1db3..3af77fe8a 100644 --- a/configfiles/LAPPDProcessedAna/ToolsConfig +++ b/configfiles/LAPPDProcessedAna/ToolsConfig @@ -1,5 +1,5 @@ LoadANNIEEvent LoadANNIEEvent configfiles/LAPPDProcessedAna/LoadANNIEEventConfig -LoadGeometry LoadGeometry configfiles/LAPPDProcessedAna/ConfigGeo +LoadGeometry LoadGeometry configfiles/LoadGeometry/LoadGeometryConfig myTimeClustering TimeClustering configfiles/LAPPDProcessedAna/TimeClusteringConfig myFindMrdTracks FindMrdTracks configfiles/LAPPDProcessedAna/FindMrdTracksConfig diff --git a/configfiles/LAPPDRaw/ConfigPlot b/configfiles/LAPPDRaw/ConfigPlot index 2e1fa034f..562cc91a2 100755 --- a/configfiles/LAPPDRaw/ConfigPlot +++ b/configfiles/LAPPDRaw/ConfigPlot @@ -127,3 +127,4 @@ CanvasHeight 500 maxDrawEventNumber 50 DrawBinHist 1 +LoadLAPPDMap 1 diff --git a/configfiles/LAPPDRaw/ConfigStoreReadIn b/configfiles/LAPPDRaw/ConfigStoreReadIn index d4b3b4e5f..c55ae7ea0 100755 --- a/configfiles/LAPPDRaw/ConfigStoreReadIn +++ b/configfiles/LAPPDRaw/ConfigStoreReadIn @@ -28,7 +28,7 @@ Pedinputfile2 ../Pedestals/PEDS_ACDC_board1.txt #LAPPDReorderData LAPPDReorderVerbosityLevel 0 -ReorderVerbosityLevel 0 +ReorderVerbosityLevel 10 ReorderInputWavLabel RawLAPPDData ReorderOutputWavLabel LAPPDWaveforms DelayOffset 0 diff --git a/configfiles/LAPPDRaw/ToolsConfig b/configfiles/LAPPDRaw/ToolsConfig index 1bae5453d..a9c7536e8 100644 --- a/configfiles/LAPPDRaw/ToolsConfig +++ b/configfiles/LAPPDRaw/ToolsConfig @@ -1,4 +1,5 @@ -LoadGeometry LoadGeometry configfiles/LAPPDRaw/ConfigGeo +#LoadGeometry LoadGeometry configfiles/LAPPDRaw/ConfigGeo +LoadGeometry LoadGeometry configfiles/LoadGeometry/LoadGeometryConfig LoadRawData LoadRawData configfiles/LAPPDRaw/LoadRawDataConfig #TriggerDataDecoder TriggerDataDecoder configfiles/LAPPDRaw/TriggerDataDecoderConfig diff --git a/configfiles/LAPPDRaw/list.txt b/configfiles/LAPPDRaw/list.txt index 9e8c65863..337ffd617 100644 --- a/configfiles/LAPPDRaw/list.txt +++ b/configfiles/LAPPDRaw/list.txt @@ -1,710 +1,5 @@ -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p0 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p1 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p2 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p3 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p4 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p5 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p6 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p7 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p8 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p9 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p10 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p11 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p12 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p13 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p14 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p15 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p16 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p17 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p18 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p19 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p20 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p21 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p22 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p23 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p24 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p25 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p26 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p27 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p28 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p29 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p30 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p31 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p32 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p33 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p34 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p35 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p36 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p37 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p38 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p39 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p40 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p41 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p42 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p43 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p44 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p45 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p46 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p47 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p48 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p49 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p50 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p51 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p52 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p53 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p54 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p55 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p56 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p57 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p58 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p59 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p60 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p61 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p62 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p63 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p64 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p65 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p66 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p67 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p68 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p69 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p70 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p71 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p72 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p73 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p74 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p75 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p76 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p77 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p78 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p79 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p80 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p81 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p82 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p83 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p84 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p85 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p86 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p87 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p88 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p89 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p90 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p91 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p92 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p93 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p94 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p95 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p96 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p97 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p98 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p99 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p100 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p101 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p102 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p103 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p104 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p105 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p106 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p107 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p108 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p109 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p110 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p111 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p112 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p113 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p114 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p115 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p116 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p117 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p118 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p119 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p120 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p121 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p122 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p123 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p124 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p125 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p126 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p127 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p128 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p129 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p130 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p131 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p132 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p133 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p134 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p135 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p136 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p137 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p138 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p139 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p140 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p141 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p142 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p143 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p144 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p145 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p146 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p147 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p148 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p149 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p150 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p151 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p152 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p153 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p154 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p155 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p156 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p157 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p158 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p159 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p160 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p161 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p162 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p163 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p164 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p165 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p166 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p167 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p168 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p169 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p170 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p171 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p172 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p173 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p174 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p175 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p176 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p177 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p178 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p179 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p180 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p181 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p182 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p183 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p184 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p185 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p186 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p187 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p188 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p189 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p190 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p191 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p192 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p193 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p194 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p195 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p196 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p197 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p198 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p199 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p200 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p201 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p202 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p203 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p204 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p205 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p206 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p207 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p208 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p209 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p210 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p211 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p212 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p213 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p214 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p215 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p216 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p217 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p218 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p219 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p220 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p221 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p222 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p223 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p224 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p225 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p226 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p227 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p228 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p229 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p230 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p231 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p232 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p233 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p234 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p235 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p236 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p237 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p238 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p239 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p240 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p241 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p242 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p243 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p244 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p245 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p246 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p247 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p248 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p249 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p250 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p251 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p252 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p253 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p254 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p255 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p256 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p257 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p258 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p259 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p260 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p261 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p262 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p263 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p264 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p265 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p266 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p267 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p268 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p269 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p270 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p271 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p272 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p273 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p274 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p275 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p276 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p277 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p278 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p279 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p280 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p281 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p282 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p283 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p284 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p285 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p286 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p287 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p288 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p289 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p290 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p291 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p292 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p293 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p294 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p295 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p296 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p297 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p298 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p299 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p300 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p301 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p302 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p303 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p304 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p305 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p306 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p307 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p308 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p309 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p310 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p311 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p312 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p313 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p314 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p315 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p316 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p317 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p318 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p319 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p320 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p321 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p322 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p323 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p324 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p325 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p326 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p327 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p328 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p329 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p330 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p331 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p332 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p333 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p334 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p335 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p336 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p337 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p338 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p339 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p340 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p341 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p342 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p343 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p344 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p345 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p346 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p347 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p348 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p349 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p350 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p351 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p352 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p353 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p354 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p355 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p356 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p357 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p358 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p359 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p360 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p361 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p362 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p363 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p364 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p365 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p366 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p367 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p368 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p369 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p370 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p371 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p372 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p373 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p374 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p375 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p376 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p377 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p378 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p379 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p380 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p381 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p382 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p383 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p384 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p385 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p386 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p387 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p388 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p389 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p390 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p391 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p392 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p393 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p394 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p395 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p396 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p397 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p398 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p399 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p400 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p401 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p402 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p403 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p404 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p405 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p406 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p407 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p408 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p409 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p410 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p411 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p412 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p413 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p414 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p415 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p416 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p417 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p418 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p419 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p420 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p421 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p422 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p423 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p424 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p425 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p426 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p427 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p428 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p429 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p430 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p431 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p432 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p433 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p434 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p435 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p436 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p437 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p438 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p439 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p440 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p441 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p442 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p443 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p444 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p445 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p446 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p447 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p448 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p449 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p450 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p451 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p452 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p453 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p454 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p455 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p456 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p457 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p458 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p459 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p460 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p461 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p462 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p463 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p464 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p465 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p466 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p467 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p468 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p469 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p470 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p471 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p472 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p473 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p474 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p475 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p476 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p477 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p478 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p479 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p480 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p481 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p482 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p483 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p484 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p485 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p486 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p487 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p488 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p489 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p490 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p491 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p492 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p493 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p494 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p495 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p496 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p497 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p498 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p499 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p500 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p501 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p502 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p503 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p504 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p505 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p506 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p507 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p508 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p509 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p510 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p511 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p512 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p513 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p514 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p515 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p516 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p517 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p518 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p519 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p520 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p521 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p522 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p523 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p524 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p525 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p526 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p527 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p528 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p529 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p530 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p531 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p532 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p533 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p534 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p535 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p536 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p537 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p538 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p539 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p540 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p541 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p542 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p543 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p544 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p545 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p546 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p547 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p548 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p549 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p550 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p551 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p552 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p553 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p554 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p555 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p556 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p557 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p558 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p559 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p560 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p561 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p562 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p563 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p564 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p565 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p566 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p567 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p568 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p569 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p570 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p571 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p572 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p573 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p574 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p575 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p576 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p577 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p578 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p579 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p580 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p581 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p582 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p583 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p584 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p585 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p586 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p587 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p588 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p589 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p590 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p591 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p592 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p593 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p594 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p595 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p596 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p597 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p598 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p599 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p600 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p601 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p602 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p603 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p604 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p605 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p606 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p607 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p608 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p609 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p610 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p611 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p612 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p613 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p614 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p615 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p616 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p617 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p618 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p619 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p620 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p621 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p622 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p623 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p624 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p625 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p626 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p627 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p628 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p629 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p630 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p631 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p632 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p633 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p634 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p635 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p636 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p637 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p638 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p639 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p640 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p641 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p642 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p643 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p644 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p645 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p646 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p647 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p648 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p649 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p650 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p651 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p652 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p653 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p654 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p655 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p656 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p657 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p658 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p659 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p660 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p661 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p662 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p663 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p664 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p665 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p666 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p667 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p668 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p669 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p670 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p671 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p672 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p673 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p674 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p675 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p676 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p677 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p678 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p679 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p680 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p681 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p682 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p683 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p684 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p685 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p686 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p687 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p688 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p689 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p690 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p691 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p692 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p693 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p694 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p695 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p696 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p697 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p698 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p699 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p700 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p701 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p702 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p703 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p704 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p705 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p706 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p707 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p708 -/pnfs/annie/persistent/raw/raw/4856/RAWDataR4856S0p709 +/pnfs/annie/persistent/raw/raw/4920/RAWDataR4920S0p0 +/pnfs/annie/persistent/raw/raw/4920/RAWDataR4920S0p1 +/pnfs/annie/persistent/raw/raw/4920/RAWDataR4920S0p2 +/pnfs/annie/persistent/raw/raw/4920/RAWDataR4920S0p3 +/pnfs/annie/persistent/raw/raw/4920/RAWDataR4920S0p4 diff --git a/configfiles/LoadGeometry/LAPPDGeometry.csv b/configfiles/LoadGeometry/LAPPDGeometry.csv index 4fec97347..df2b434c8 100644 --- a/configfiles/LoadGeometry/LAPPDGeometry.csv +++ b/configfiles/LoadGeometry/LAPPDGeometry.csv @@ -1,1445 +1,1445 @@ -LEGEND_LINE -detector_num,detector_position_x,detector_position_y,detector_position_z,detector_direction_x,detector_direction_y,detector_direction_z,detector_type,detector_status,channel_num,channel_position_x,channel_position_y,channel_position_z,channel_strip_side,channel_strip_num,channel_signal_crate,channel_signal_card,channel_signal_channel,channel_level2_crate,channel_level2_card,channel_level2_channel,channel_hv_crate,channel_hv_card,channel_hv_channel,channel_status - -DATA_START -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,0,100,-300,0,0,0,0,0,1,0,0,32669,0,0,1,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,1,100,-290,0,0,1,0,0,2,0,0,32669,0,0,2,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,2,100,-280,0,0,2,0,0,3,0,0,32669,0,0,3,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,3,100,-270,0,0,3,0,0,4,0,0,32669,0,1,0,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,4,100,-260,0,0,4,0,0,5,0,0,32669,0,1,1,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,5,100,-250,0,0,5,0,0,6,0,0,32669,0,1,2,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,6,100,-240,0,0,6,0,0,7,0,0,32669,0,1,3,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,7,100,-230,0,0,7,0,0,8,0,0,32669,0,2,0,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,8,100,-220,0,0,8,0,0,9,0,0,32669,0,2,1,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,9,100,-210,0,0,9,0,0,10,0,0,32669,0,2,2,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,10,100,-200,0,0,10,0,0,11,0,0,32669,0,2,3,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,11,100,-190,0,0,11,0,0,12,0,0,32669,0,3,0,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,12,100,-180,0,0,12,0,0,13,0,0,32669,0,3,1,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,13,100,-170,0,0,13,0,0,14,0,0,32669,0,3,2,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,14,100,-160,0,0,14,0,0,15,0,0,32669,0,3,3,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,15,100,-150,0,0,15,0,0,16,0,0,32669,0,4,0,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,16,100,-140,0,0,16,0,0,17,0,0,32669,0,4,1,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,17,100,-130,0,0,17,0,0,18,0,0,32669,0,4,2,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,18,100,-120,0,0,18,0,0,19,0,0,32669,0,4,3,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,19,100,-110,0,0,19,0,0,20,0,0,32669,0,5,0,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,20,100,-100,0,0,20,0,0,21,0,0,32669,0,5,1,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,21,100,-90,0,0,21,0,0,22,0,0,32669,0,5,2,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,22,100,-80,0,0,22,0,0,23,0,0,32669,0,5,3,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,23,100,-70,0,0,23,0,0,24,0,0,32669,0,6,0,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,24,100,-60,0,0,24,0,0,25,0,0,32669,0,6,1,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,25,100,-50,0,0,25,0,0,26,0,0,32669,0,6,2,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,26,100,-40,0,0,26,0,0,27,0,0,32669,0,6,3,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,27,100,-30,0,0,27,0,0,28,0,0,32669,0,7,0,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,28,100,-20,0,0,28,0,0,29,0,0,32669,0,7,1,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,29,100,-10,0,0,29,0,1,0,0,0,32669,0,7,2,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,30,-100,-300,0,1,0,0,1,1,0,0,32669,0,7,3,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,31,-100,-290,0,1,1,0,1,2,0,0,32669,0,8,0,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,32,-100,-280,0,1,2,0,1,3,0,0,32669,0,8,1,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,33,-100,-270,0,1,3,0,1,4,0,0,32669,0,8,2,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,34,-100,-260,0,1,4,0,1,5,0,0,32669,0,8,3,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,35,-100,-250,0,1,5,0,1,6,0,0,32669,0,9,0,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,36,-100,-240,0,1,6,0,1,7,0,0,32669,0,9,1,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,37,-100,-230,0,1,7,0,1,8,0,0,32669,0,9,2,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,38,-100,-220,0,1,8,0,1,9,0,0,32669,0,9,3,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,39,-100,-210,0,1,9,0,1,10,0,0,32669,1,0,0,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,40,-100,-200,0,1,10,0,1,11,0,0,32669,1,0,1,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,41,-100,-190,0,1,11,0,1,12,0,0,32669,1,0,2,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,42,-100,-180,0,1,12,0,1,13,0,0,32669,1,0,3,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,43,-100,-170,0,1,13,0,1,14,0,0,32669,1,1,0,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,44,-100,-160,0,1,14,0,1,15,0,0,32669,1,1,1,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,45,-100,-150,0,1,15,0,1,16,0,0,32669,1,1,2,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,46,-100,-140,0,1,16,0,1,17,0,0,32669,1,1,3,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,47,-100,-130,0,1,17,0,1,18,0,0,32669,1,2,0,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,48,-100,-120,0,1,18,0,1,19,0,0,32669,1,2,1,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,49,-100,-110,0,1,19,0,1,20,0,0,32669,1,2,2,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,50,-100,-100,0,1,20,0,1,21,0,0,32669,1,2,3,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,51,-100,-90,0,1,21,0,1,22,0,0,32669,1,3,0,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,52,-100,-80,0,1,22,0,1,23,0,0,32669,1,3,1,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,53,-100,-70,0,1,23,0,1,24,0,0,32669,1,3,2,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,54,-100,-60,0,1,24,0,1,25,0,0,32669,1,3,3,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,55,-100,-50,0,1,25,0,1,26,0,0,32669,1,4,0,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,56,-100,-40,0,1,26,0,1,27,0,0,32669,1,4,1,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,57,-100,-30,0,1,27,0,1,28,0,0,32669,1,4,2,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,58,-100,-20,0,1,28,0,1,29,0,0,32669,1,4,3,ON -0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,59,-100,-10,0,1,29,0,2,0,0,0,32669,1,5,0,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,60,100,-300,0,0,0,0,2,1,0,0,32669,1,5,1,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,61,100,-290,0,0,1,0,2,2,0,0,32669,1,5,2,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,62,100,-280,0,0,2,0,2,3,0,0,32669,1,5,3,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,63,100,-270,0,0,3,0,2,4,0,0,32669,1,6,0,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,64,100,-260,0,0,4,0,2,5,0,0,32669,1,6,1,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,65,100,-250,0,0,5,0,2,6,0,0,32669,1,6,2,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,66,100,-240,0,0,6,0,2,7,0,0,32669,1,6,3,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,67,100,-230,0,0,7,0,2,8,0,0,32669,1,7,0,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,68,100,-220,0,0,8,0,2,9,0,0,32669,1,7,1,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,69,100,-210,0,0,9,0,2,10,0,0,32669,1,7,2,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,70,100,-200,0,0,10,0,2,11,0,0,32669,1,7,3,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,71,100,-190,0,0,11,0,2,12,0,0,32669,1,8,0,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,72,100,-180,0,0,12,0,2,13,0,0,32669,1,8,1,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,73,100,-170,0,0,13,0,2,14,0,0,32669,1,8,2,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,74,100,-160,0,0,14,0,2,15,0,0,32669,1,8,3,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,75,100,-150,0,0,15,0,2,16,0,0,32669,1,9,0,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,76,100,-140,0,0,16,0,2,17,0,0,32669,1,9,1,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,77,100,-130,0,0,17,0,2,18,0,0,32669,1,9,2,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,78,100,-120,0,0,18,0,2,19,0,0,32669,1,9,3,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,79,100,-110,0,0,19,0,2,20,0,0,32669,2,0,0,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,80,100,-100,0,0,20,0,2,21,0,0,32669,2,0,1,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,81,100,-90,0,0,21,0,2,22,0,0,32669,2,0,2,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,82,100,-80,0,0,22,0,2,23,0,0,32669,2,0,3,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,83,100,-70,0,0,23,0,2,24,0,0,32669,2,1,0,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,84,100,-60,0,0,24,0,2,25,0,0,32669,2,1,1,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,85,100,-50,0,0,25,0,2,26,0,0,32669,2,1,2,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,86,100,-40,0,0,26,0,2,27,0,0,32669,2,1,3,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,87,100,-30,0,0,27,0,2,28,0,0,32669,2,2,0,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,88,100,-20,0,0,28,0,2,29,0,0,32669,2,2,1,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,89,100,-10,0,0,29,0,3,0,0,0,32669,2,2,2,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,90,-100,-300,0,1,0,0,3,1,0,0,32669,2,2,3,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,91,-100,-290,0,1,1,0,3,2,0,0,32669,2,3,0,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,92,-100,-280,0,1,2,0,3,3,0,0,32669,2,3,1,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,93,-100,-270,0,1,3,0,3,4,0,0,32669,2,3,2,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,94,-100,-260,0,1,4,0,3,5,0,0,32669,2,3,3,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,95,-100,-250,0,1,5,0,3,6,0,0,32669,2,4,0,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,96,-100,-240,0,1,6,0,3,7,0,0,32669,2,4,1,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,97,-100,-230,0,1,7,0,3,8,0,0,32669,2,4,2,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,98,-100,-220,0,1,8,0,3,9,0,0,32669,2,4,3,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,99,-100,-210,0,1,9,0,3,10,0,0,32669,2,5,0,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,100,-100,-200,0,1,10,0,3,11,0,0,32669,2,5,1,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,101,-100,-190,0,1,11,0,3,12,0,0,32669,2,5,2,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,102,-100,-180,0,1,12,0,3,13,0,0,32669,2,5,3,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,103,-100,-170,0,1,13,0,3,14,0,0,32669,2,6,0,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,104,-100,-160,0,1,14,0,3,15,0,0,32669,2,6,1,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,105,-100,-150,0,1,15,0,3,16,0,0,32669,2,6,2,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,106,-100,-140,0,1,16,0,3,17,0,0,32669,2,6,3,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,107,-100,-130,0,1,17,0,3,18,0,0,32669,2,7,0,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,108,-100,-120,0,1,18,0,3,19,0,0,32669,2,7,1,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,109,-100,-110,0,1,19,0,3,20,0,0,32669,2,7,2,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,110,-100,-100,0,1,20,0,3,21,0,0,32669,2,7,3,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,111,-100,-90,0,1,21,0,3,22,0,0,32669,2,8,0,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,112,-100,-80,0,1,22,0,3,23,0,0,32669,2,8,1,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,113,-100,-70,0,1,23,0,3,24,0,0,32669,2,8,2,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,114,-100,-60,0,1,24,0,3,25,0,0,32669,2,8,3,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,115,-100,-50,0,1,25,0,3,26,0,0,32669,2,9,0,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,116,-100,-40,0,1,26,0,3,27,0,0,32669,2,9,1,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,117,-100,-30,0,1,27,0,3,28,0,0,32669,2,9,2,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,118,-100,-20,0,1,28,0,3,29,0,0,32669,2,9,3,ON -1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,119,-100,-10,0,1,29,0,4,0,0,0,32669,3,0,0,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,120,100,-300,0,0,0,0,4,1,0,0,32669,3,0,1,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,121,100,-290,0,0,1,0,4,2,0,0,32669,3,0,2,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,122,100,-280,0,0,2,0,4,3,0,0,32669,3,0,3,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,123,100,-270,0,0,3,0,4,4,0,0,32669,3,1,0,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,124,100,-260,0,0,4,0,4,5,0,0,32669,3,1,1,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,125,100,-250,0,0,5,0,4,6,0,0,32669,3,1,2,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,126,100,-240,0,0,6,0,4,7,0,0,32669,3,1,3,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,127,100,-230,0,0,7,0,4,8,0,0,32669,3,2,0,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,128,100,-220,0,0,8,0,4,9,0,0,32669,3,2,1,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,129,100,-210,0,0,9,0,4,10,0,0,32669,3,2,2,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,130,100,-200,0,0,10,0,4,11,0,0,32669,3,2,3,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,131,100,-190,0,0,11,0,4,12,0,0,32669,3,3,0,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,132,100,-180,0,0,12,0,4,13,0,0,32669,3,3,1,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,133,100,-170,0,0,13,0,4,14,0,0,32669,3,3,2,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,134,100,-160,0,0,14,0,4,15,0,0,32669,3,3,3,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,135,100,-150,0,0,15,0,4,16,0,0,32669,3,4,0,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,136,100,-140,0,0,16,0,4,17,0,0,32669,3,4,1,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,137,100,-130,0,0,17,0,4,18,0,0,32669,3,4,2,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,138,100,-120,0,0,18,0,4,19,0,0,32669,3,4,3,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,139,100,-110,0,0,19,0,4,20,0,0,32669,3,5,0,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,140,100,-100,0,0,20,0,4,21,0,0,32669,3,5,1,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,141,100,-90,0,0,21,0,4,22,0,0,32669,3,5,2,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,142,100,-80,0,0,22,0,4,23,0,0,32669,3,5,3,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,143,100,-70,0,0,23,0,4,24,0,0,32669,3,6,0,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,144,100,-60,0,0,24,0,4,25,0,0,32669,3,6,1,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,145,100,-50,0,0,25,0,4,26,0,0,32669,3,6,2,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,146,100,-40,0,0,26,0,4,27,0,0,32669,3,6,3,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,147,100,-30,0,0,27,0,4,28,0,0,32669,3,7,0,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,148,100,-20,0,0,28,0,4,29,0,0,32669,3,7,1,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,149,100,-10,0,0,29,0,5,0,0,0,32669,3,7,2,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,150,-100,-300,0,1,0,0,5,1,0,0,32669,3,7,3,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,151,-100,-290,0,1,1,0,5,2,0,0,32669,3,8,0,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,152,-100,-280,0,1,2,0,5,3,0,0,32669,3,8,1,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,153,-100,-270,0,1,3,0,5,4,0,0,32669,3,8,2,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,154,-100,-260,0,1,4,0,5,5,0,0,32669,3,8,3,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,155,-100,-250,0,1,5,0,5,6,0,0,32669,3,9,0,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,156,-100,-240,0,1,6,0,5,7,0,0,32669,3,9,1,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,157,-100,-230,0,1,7,0,5,8,0,0,32669,3,9,2,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,158,-100,-220,0,1,8,0,5,9,0,0,32669,3,9,3,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,159,-100,-210,0,1,9,0,5,10,0,0,32669,4,0,0,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,160,-100,-200,0,1,10,0,5,11,0,0,32669,4,0,1,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,161,-100,-190,0,1,11,0,5,12,0,0,32669,4,0,2,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,162,-100,-180,0,1,12,0,5,13,0,0,32669,4,0,3,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,163,-100,-170,0,1,13,0,5,14,0,0,32669,4,1,0,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,164,-100,-160,0,1,14,0,5,15,0,0,32669,4,1,1,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,165,-100,-150,0,1,15,0,5,16,0,0,32669,4,1,2,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,166,-100,-140,0,1,16,0,5,17,0,0,32669,4,1,3,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,167,-100,-130,0,1,17,0,5,18,0,0,32669,4,2,0,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,168,-100,-120,0,1,18,0,5,19,0,0,32669,4,2,1,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,169,-100,-110,0,1,19,0,5,20,0,0,32669,4,2,2,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,170,-100,-100,0,1,20,0,5,21,0,0,32669,4,2,3,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,171,-100,-90,0,1,21,0,5,22,0,0,32669,4,3,0,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,172,-100,-80,0,1,22,0,5,23,0,0,32669,4,3,1,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,173,-100,-70,0,1,23,0,5,24,0,0,32669,4,3,2,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,174,-100,-60,0,1,24,0,5,25,0,0,32669,4,3,3,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,175,-100,-50,0,1,25,0,5,26,0,0,32669,4,4,0,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,176,-100,-40,0,1,26,0,5,27,0,0,32669,4,4,1,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,177,-100,-30,0,1,27,0,5,28,0,0,32669,4,4,2,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,178,-100,-20,0,1,28,0,5,29,0,0,32669,4,4,3,ON -2,0,0.637851,0.404,0,0,1,lappd_v1,ON,179,-100,-10,0,1,29,0,6,0,0,0,32669,4,5,0,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,180,100,-300,0,0,0,0,6,1,0,0,32669,4,5,1,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,181,100,-290,0,0,1,0,6,2,0,0,32669,4,5,2,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,182,100,-280,0,0,2,0,6,3,0,0,32669,4,5,3,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,183,100,-270,0,0,3,0,6,4,0,0,32669,4,6,0,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,184,100,-260,0,0,4,0,6,5,0,0,32669,4,6,1,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,185,100,-250,0,0,5,0,6,6,0,0,32669,4,6,2,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,186,100,-240,0,0,6,0,6,7,0,0,32669,4,6,3,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,187,100,-230,0,0,7,0,6,8,0,0,32669,4,7,0,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,188,100,-220,0,0,8,0,6,9,0,0,32669,4,7,1,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,189,100,-210,0,0,9,0,6,10,0,0,32669,4,7,2,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,190,100,-200,0,0,10,0,6,11,0,0,32669,4,7,3,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,191,100,-190,0,0,11,0,6,12,0,0,32669,4,8,0,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,192,100,-180,0,0,12,0,6,13,0,0,32669,4,8,1,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,193,100,-170,0,0,13,0,6,14,0,0,32669,4,8,2,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,194,100,-160,0,0,14,0,6,15,0,0,32669,4,8,3,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,195,100,-150,0,0,15,0,6,16,0,0,32669,4,9,0,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,196,100,-140,0,0,16,0,6,17,0,0,32669,4,9,1,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,197,100,-130,0,0,17,0,6,18,0,0,32669,4,9,2,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,198,100,-120,0,0,18,0,6,19,0,0,32669,4,9,3,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,199,100,-110,0,0,19,0,6,20,0,0,32669,5,0,0,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,200,100,-100,0,0,20,0,6,21,0,0,32669,5,0,1,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,201,100,-90,0,0,21,0,6,22,0,0,32669,5,0,2,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,202,100,-80,0,0,22,0,6,23,0,0,32669,5,0,3,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,203,100,-70,0,0,23,0,6,24,0,0,32669,5,1,0,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,204,100,-60,0,0,24,0,6,25,0,0,32669,5,1,1,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,205,100,-50,0,0,25,0,6,26,0,0,32669,5,1,2,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,206,100,-40,0,0,26,0,6,27,0,0,32669,5,1,3,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,207,100,-30,0,0,27,0,6,28,0,0,32669,5,2,0,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,208,100,-20,0,0,28,0,6,29,0,0,32669,5,2,1,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,209,100,-10,0,0,29,0,7,0,0,0,32669,5,2,2,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,210,-100,-300,0,1,0,0,7,1,0,0,32669,5,2,3,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,211,-100,-290,0,1,1,0,7,2,0,0,32669,5,3,0,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,212,-100,-280,0,1,2,0,7,3,0,0,32669,5,3,1,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,213,-100,-270,0,1,3,0,7,4,0,0,32669,5,3,2,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,214,-100,-260,0,1,4,0,7,5,0,0,32669,5,3,3,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,215,-100,-250,0,1,5,0,7,6,0,0,32669,5,4,0,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,216,-100,-240,0,1,6,0,7,7,0,0,32669,5,4,1,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,217,-100,-230,0,1,7,0,7,8,0,0,32669,5,4,2,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,218,-100,-220,0,1,8,0,7,9,0,0,32669,5,4,3,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,219,-100,-210,0,1,9,0,7,10,0,0,32669,5,5,0,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,220,-100,-200,0,1,10,0,7,11,0,0,32669,5,5,1,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,221,-100,-190,0,1,11,0,7,12,0,0,32669,5,5,2,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,222,-100,-180,0,1,12,0,7,13,0,0,32669,5,5,3,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,223,-100,-170,0,1,13,0,7,14,0,0,32669,5,6,0,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,224,-100,-160,0,1,14,0,7,15,0,0,32669,5,6,1,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,225,-100,-150,0,1,15,0,7,16,0,0,32669,5,6,2,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,226,-100,-140,0,1,16,0,7,17,0,0,32669,5,6,3,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,227,-100,-130,0,1,17,0,7,18,0,0,32669,5,7,0,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,228,-100,-120,0,1,18,0,7,19,0,0,32669,5,7,1,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,229,-100,-110,0,1,19,0,7,20,0,0,32669,5,7,2,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,230,-100,-100,0,1,20,0,7,21,0,0,32669,5,7,3,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,231,-100,-90,0,1,21,0,7,22,0,0,32669,5,8,0,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,232,-100,-80,0,1,22,0,7,23,0,0,32669,5,8,1,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,233,-100,-70,0,1,23,0,7,24,0,0,32669,5,8,2,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,234,-100,-60,0,1,24,0,7,25,0,0,32669,5,8,3,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,235,-100,-50,0,1,25,0,7,26,0,0,32669,5,9,0,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,236,-100,-40,0,1,26,0,7,27,0,0,32669,5,9,1,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,237,-100,-30,0,1,27,0,7,28,0,0,32669,5,9,2,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,238,-100,-20,0,1,28,0,7,29,0,0,32669,5,9,3,ON -3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,239,-100,-10,0,1,29,0,8,0,0,1,32669,6,0,0,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,240,100,-300,0,0,0,0,8,1,0,1,32669,6,0,1,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,241,100,-290,0,0,1,0,8,2,0,1,32669,6,0,2,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,242,100,-280,0,0,2,0,8,3,0,1,32669,6,0,3,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,243,100,-270,0,0,3,0,8,4,0,1,32669,6,1,0,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,244,100,-260,0,0,4,0,8,5,0,1,32669,6,1,1,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,245,100,-250,0,0,5,0,8,6,0,1,32669,6,1,2,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,246,100,-240,0,0,6,0,8,7,0,1,32669,6,1,3,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,247,100,-230,0,0,7,0,8,8,0,1,32669,6,2,0,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,248,100,-220,0,0,8,0,8,9,0,1,32669,6,2,1,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,249,100,-210,0,0,9,0,8,10,0,1,32669,6,2,2,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,250,100,-200,0,0,10,0,8,11,0,1,32669,6,2,3,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,251,100,-190,0,0,11,0,8,12,0,1,32669,6,3,0,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,252,100,-180,0,0,12,0,8,13,0,1,32669,6,3,1,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,253,100,-170,0,0,13,0,8,14,0,1,32669,6,3,2,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,254,100,-160,0,0,14,0,8,15,0,1,32669,6,3,3,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,255,100,-150,0,0,15,0,8,16,0,1,32669,6,4,0,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,256,100,-140,0,0,16,0,8,17,0,1,32669,6,4,1,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,257,100,-130,0,0,17,0,8,18,0,1,32669,6,4,2,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,258,100,-120,0,0,18,0,8,19,0,1,32669,6,4,3,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,259,100,-110,0,0,19,0,8,20,0,1,32669,6,5,0,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,260,100,-100,0,0,20,0,8,21,0,1,32669,6,5,1,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,261,100,-90,0,0,21,0,8,22,0,1,32669,6,5,2,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,262,100,-80,0,0,22,0,8,23,0,1,32669,6,5,3,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,263,100,-70,0,0,23,0,8,24,0,1,32669,6,6,0,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,264,100,-60,0,0,24,0,8,25,0,1,32669,6,6,1,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,265,100,-50,0,0,25,0,8,26,0,1,32669,6,6,2,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,266,100,-40,0,0,26,0,8,27,0,1,32669,6,6,3,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,267,100,-30,0,0,27,0,8,28,0,1,32669,6,7,0,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,268,100,-20,0,0,28,0,8,29,0,1,32669,6,7,1,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,269,100,-10,0,0,29,0,9,0,0,1,32669,6,7,2,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,270,-100,-300,0,1,0,0,9,1,0,1,32669,6,7,3,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,271,-100,-290,0,1,1,0,9,2,0,1,32669,6,8,0,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,272,-100,-280,0,1,2,0,9,3,0,1,32669,6,8,1,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,273,-100,-270,0,1,3,0,9,4,0,1,32669,6,8,2,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,274,-100,-260,0,1,4,0,9,5,0,1,32669,6,8,3,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,275,-100,-250,0,1,5,0,9,6,0,1,32669,6,9,0,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,276,-100,-240,0,1,6,0,9,7,0,1,32669,6,9,1,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,277,-100,-230,0,1,7,0,9,8,0,1,32669,6,9,2,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,278,-100,-220,0,1,8,0,9,9,0,1,32669,6,9,3,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,279,-100,-210,0,1,9,0,9,10,0,1,32669,7,0,0,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,280,-100,-200,0,1,10,0,9,11,0,1,32669,7,0,1,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,281,-100,-190,0,1,11,0,9,12,0,1,32669,7,0,2,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,282,-100,-180,0,1,12,0,9,13,0,1,32669,7,0,3,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,283,-100,-170,0,1,13,0,9,14,0,1,32669,7,1,0,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,284,-100,-160,0,1,14,0,9,15,0,1,32669,7,1,1,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,285,-100,-150,0,1,15,0,9,16,0,1,32669,7,1,2,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,286,-100,-140,0,1,16,0,9,17,0,1,32669,7,1,3,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,287,-100,-130,0,1,17,0,9,18,0,1,32669,7,2,0,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,288,-100,-120,0,1,18,0,9,19,0,1,32669,7,2,1,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,289,-100,-110,0,1,19,0,9,20,0,1,32669,7,2,2,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,290,-100,-100,0,1,20,0,9,21,0,1,32669,7,2,3,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,291,-100,-90,0,1,21,0,9,22,0,1,32669,7,3,0,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,292,-100,-80,0,1,22,0,9,23,0,1,32669,7,3,1,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,293,-100,-70,0,1,23,0,9,24,0,1,32669,7,3,2,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,294,-100,-60,0,1,24,0,9,25,0,1,32669,7,3,3,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,295,-100,-50,0,1,25,0,9,26,0,1,32669,7,4,0,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,296,-100,-40,0,1,26,0,9,27,0,1,32669,7,4,1,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,297,-100,-30,0,1,27,0,9,28,0,1,32669,7,4,2,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,298,-100,-20,0,1,28,0,9,29,0,1,32669,7,4,3,ON -4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,299,-100,-10,0,1,29,0,10,0,0,1,32669,7,5,0,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,300,100,-300,0,0,0,0,10,1,0,1,32669,7,5,1,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,301,100,-290,0,0,1,0,10,2,0,1,32669,7,5,2,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,302,100,-280,0,0,2,0,10,3,0,1,32669,7,5,3,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,303,100,-270,0,0,3,0,10,4,0,1,32669,7,6,0,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,304,100,-260,0,0,4,0,10,5,0,1,32669,7,6,1,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,305,100,-250,0,0,5,0,10,6,0,1,32669,7,6,2,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,306,100,-240,0,0,6,0,10,7,0,1,32669,7,6,3,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,307,100,-230,0,0,7,0,10,8,0,1,32669,7,7,0,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,308,100,-220,0,0,8,0,10,9,0,1,32669,7,7,1,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,309,100,-210,0,0,9,0,10,10,0,1,32669,7,7,2,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,310,100,-200,0,0,10,0,10,11,0,1,32669,7,7,3,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,311,100,-190,0,0,11,0,10,12,0,1,32669,7,8,0,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,312,100,-180,0,0,12,0,10,13,0,1,32669,7,8,1,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,313,100,-170,0,0,13,0,10,14,0,1,32669,7,8,2,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,314,100,-160,0,0,14,0,10,15,0,1,32669,7,8,3,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,315,100,-150,0,0,15,0,10,16,0,1,32669,7,9,0,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,316,100,-140,0,0,16,0,10,17,0,1,32669,7,9,1,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,317,100,-130,0,0,17,0,10,18,0,1,32669,7,9,2,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,318,100,-120,0,0,18,0,10,19,0,1,32669,7,9,3,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,319,100,-110,0,0,19,0,10,20,0,1,32669,8,0,0,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,320,100,-100,0,0,20,0,10,21,0,1,32669,8,0,1,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,321,100,-90,0,0,21,0,10,22,0,1,32669,8,0,2,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,322,100,-80,0,0,22,0,10,23,0,1,32669,8,0,3,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,323,100,-70,0,0,23,0,10,24,0,1,32669,8,1,0,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,324,100,-60,0,0,24,0,10,25,0,1,32669,8,1,1,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,325,100,-50,0,0,25,0,10,26,0,1,32669,8,1,2,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,326,100,-40,0,0,26,0,10,27,0,1,32669,8,1,3,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,327,100,-30,0,0,27,0,10,28,0,1,32669,8,2,0,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,328,100,-20,0,0,28,0,10,29,0,1,32669,8,2,1,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,329,100,-10,0,0,29,0,11,0,0,1,32669,8,2,2,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,330,-100,-300,0,1,0,0,11,1,0,1,32669,8,2,3,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,331,-100,-290,0,1,1,0,11,2,0,1,32669,8,3,0,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,332,-100,-280,0,1,2,0,11,3,0,1,32669,8,3,1,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,333,-100,-270,0,1,3,0,11,4,0,1,32669,8,3,2,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,334,-100,-260,0,1,4,0,11,5,0,1,32669,8,3,3,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,335,-100,-250,0,1,5,0,11,6,0,1,32669,8,4,0,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,336,-100,-240,0,1,6,0,11,7,0,1,32669,8,4,1,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,337,-100,-230,0,1,7,0,11,8,0,1,32669,8,4,2,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,338,-100,-220,0,1,8,0,11,9,0,1,32669,8,4,3,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,339,-100,-210,0,1,9,0,11,10,0,1,32669,8,5,0,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,340,-100,-200,0,1,10,0,11,11,0,1,32669,8,5,1,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,341,-100,-190,0,1,11,0,11,12,0,1,32669,8,5,2,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,342,-100,-180,0,1,12,0,11,13,0,1,32669,8,5,3,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,343,-100,-170,0,1,13,0,11,14,0,1,32669,8,6,0,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,344,-100,-160,0,1,14,0,11,15,0,1,32669,8,6,1,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,345,-100,-150,0,1,15,0,11,16,0,1,32669,8,6,2,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,346,-100,-140,0,1,16,0,11,17,0,1,32669,8,6,3,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,347,-100,-130,0,1,17,0,11,18,0,1,32669,8,7,0,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,348,-100,-120,0,1,18,0,11,19,0,1,32669,8,7,1,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,349,-100,-110,0,1,19,0,11,20,0,1,32669,8,7,2,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,350,-100,-100,0,1,20,0,11,21,0,1,32669,8,7,3,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,351,-100,-90,0,1,21,0,11,22,0,1,32669,8,8,0,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,352,-100,-80,0,1,22,0,11,23,0,1,32669,8,8,1,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,353,-100,-70,0,1,23,0,11,24,0,1,32669,8,8,2,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,354,-100,-60,0,1,24,0,11,25,0,1,32669,8,8,3,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,355,-100,-50,0,1,25,0,11,26,0,1,32669,8,9,0,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,356,-100,-40,0,1,26,0,11,27,0,1,32669,8,9,1,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,357,-100,-30,0,1,27,0,11,28,0,1,32669,8,9,2,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,358,-100,-20,0,1,28,0,11,29,0,1,32669,8,9,3,ON -5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,359,-100,-10,0,1,29,0,12,0,0,1,32669,9,0,0,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,360,100,-300,0,0,0,0,12,1,0,1,32669,9,0,1,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,361,100,-290,0,0,1,0,12,2,0,1,32669,9,0,2,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,362,100,-280,0,0,2,0,12,3,0,1,32669,9,0,3,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,363,100,-270,0,0,3,0,12,4,0,1,32669,9,1,0,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,364,100,-260,0,0,4,0,12,5,0,1,32669,9,1,1,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,365,100,-250,0,0,5,0,12,6,0,1,32669,9,1,2,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,366,100,-240,0,0,6,0,12,7,0,1,32669,9,1,3,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,367,100,-230,0,0,7,0,12,8,0,1,32669,9,2,0,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,368,100,-220,0,0,8,0,12,9,0,1,32669,9,2,1,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,369,100,-210,0,0,9,0,12,10,0,1,32669,9,2,2,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,370,100,-200,0,0,10,0,12,11,0,1,32669,9,2,3,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,371,100,-190,0,0,11,0,12,12,0,1,32669,9,3,0,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,372,100,-180,0,0,12,0,12,13,0,1,32669,9,3,1,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,373,100,-170,0,0,13,0,12,14,0,1,32669,9,3,2,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,374,100,-160,0,0,14,0,12,15,0,1,32669,9,3,3,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,375,100,-150,0,0,15,0,12,16,0,1,32669,9,4,0,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,376,100,-140,0,0,16,0,12,17,0,1,32669,9,4,1,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,377,100,-130,0,0,17,0,12,18,0,1,32669,9,4,2,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,378,100,-120,0,0,18,0,12,19,0,1,32669,9,4,3,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,379,100,-110,0,0,19,0,12,20,0,1,32669,9,5,0,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,380,100,-100,0,0,20,0,12,21,0,1,32669,9,5,1,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,381,100,-90,0,0,21,0,12,22,0,1,32669,9,5,2,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,382,100,-80,0,0,22,0,12,23,0,1,32669,9,5,3,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,383,100,-70,0,0,23,0,12,24,0,1,32669,9,6,0,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,384,100,-60,0,0,24,0,12,25,0,1,32669,9,6,1,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,385,100,-50,0,0,25,0,12,26,0,1,32669,9,6,2,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,386,100,-40,0,0,26,0,12,27,0,1,32669,9,6,3,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,387,100,-30,0,0,27,0,12,28,0,1,32669,9,7,0,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,388,100,-20,0,0,28,0,12,29,0,1,32669,9,7,1,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,389,100,-10,0,0,29,0,13,0,0,1,32669,9,7,2,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,390,-100,-300,0,1,0,0,13,1,0,1,32669,9,7,3,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,391,-100,-290,0,1,1,0,13,2,0,1,32669,9,8,0,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,392,-100,-280,0,1,2,0,13,3,0,1,32669,9,8,1,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,393,-100,-270,0,1,3,0,13,4,0,1,32669,9,8,2,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,394,-100,-260,0,1,4,0,13,5,0,1,32669,9,8,3,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,395,-100,-250,0,1,5,0,13,6,0,1,32669,9,9,0,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,396,-100,-240,0,1,6,0,13,7,0,1,32669,9,9,1,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,397,-100,-230,0,1,7,0,13,8,0,1,32669,9,9,2,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,398,-100,-220,0,1,8,0,13,9,0,1,32669,9,9,3,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,399,-100,-210,0,1,9,0,13,10,0,1,32669,10,0,0,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,400,-100,-200,0,1,10,0,13,11,0,1,32669,10,0,1,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,401,-100,-190,0,1,11,0,13,12,0,1,32669,10,0,2,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,402,-100,-180,0,1,12,0,13,13,0,1,32669,10,0,3,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,403,-100,-170,0,1,13,0,13,14,0,1,32669,10,1,0,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,404,-100,-160,0,1,14,0,13,15,0,1,32669,10,1,1,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,405,-100,-150,0,1,15,0,13,16,0,1,32669,10,1,2,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,406,-100,-140,0,1,16,0,13,17,0,1,32669,10,1,3,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,407,-100,-130,0,1,17,0,13,18,0,1,32669,10,2,0,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,408,-100,-120,0,1,18,0,13,19,0,1,32669,10,2,1,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,409,-100,-110,0,1,19,0,13,20,0,1,32669,10,2,2,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,410,-100,-100,0,1,20,0,13,21,0,1,32669,10,2,3,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,411,-100,-90,0,1,21,0,13,22,0,1,32669,10,3,0,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,412,-100,-80,0,1,22,0,13,23,0,1,32669,10,3,1,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,413,-100,-70,0,1,23,0,13,24,0,1,32669,10,3,2,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,414,-100,-60,0,1,24,0,13,25,0,1,32669,10,3,3,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,415,-100,-50,0,1,25,0,13,26,0,1,32669,10,4,0,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,416,-100,-40,0,1,26,0,13,27,0,1,32669,10,4,1,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,417,-100,-30,0,1,27,0,13,28,0,1,32669,10,4,2,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,418,-100,-20,0,1,28,0,13,29,0,1,32669,10,4,3,ON -6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,419,-100,-10,0,1,29,0,14,0,0,1,32669,10,5,0,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,420,100,-300,0,0,0,0,14,1,0,1,32669,10,5,1,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,421,100,-290,0,0,1,0,14,2,0,1,32669,10,5,2,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,422,100,-280,0,0,2,0,14,3,0,1,32669,10,5,3,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,423,100,-270,0,0,3,0,14,4,0,1,32669,10,6,0,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,424,100,-260,0,0,4,0,14,5,0,1,32669,10,6,1,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,425,100,-250,0,0,5,0,14,6,0,1,32669,10,6,2,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,426,100,-240,0,0,6,0,14,7,0,1,32669,10,6,3,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,427,100,-230,0,0,7,0,14,8,0,1,32669,10,7,0,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,428,100,-220,0,0,8,0,14,9,0,1,32669,10,7,1,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,429,100,-210,0,0,9,0,14,10,0,1,32669,10,7,2,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,430,100,-200,0,0,10,0,14,11,0,1,32669,10,7,3,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,431,100,-190,0,0,11,0,14,12,0,1,32669,10,8,0,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,432,100,-180,0,0,12,0,14,13,0,1,32669,10,8,1,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,433,100,-170,0,0,13,0,14,14,0,1,32669,10,8,2,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,434,100,-160,0,0,14,0,14,15,0,1,32669,10,8,3,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,435,100,-150,0,0,15,0,14,16,0,1,32669,10,9,0,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,436,100,-140,0,0,16,0,14,17,0,1,32669,10,9,1,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,437,100,-130,0,0,17,0,14,18,0,1,32669,10,9,2,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,438,100,-120,0,0,18,0,14,19,0,1,32669,10,9,3,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,439,100,-110,0,0,19,0,14,20,0,1,32669,11,0,0,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,440,100,-100,0,0,20,0,14,21,0,1,32669,11,0,1,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,441,100,-90,0,0,21,0,14,22,0,1,32669,11,0,2,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,442,100,-80,0,0,22,0,14,23,0,1,32669,11,0,3,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,443,100,-70,0,0,23,0,14,24,0,1,32669,11,1,0,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,444,100,-60,0,0,24,0,14,25,0,1,32669,11,1,1,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,445,100,-50,0,0,25,0,14,26,0,1,32669,11,1,2,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,446,100,-40,0,0,26,0,14,27,0,1,32669,11,1,3,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,447,100,-30,0,0,27,0,14,28,0,1,32669,11,2,0,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,448,100,-20,0,0,28,0,14,29,0,1,32669,11,2,1,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,449,100,-10,0,0,29,0,15,0,0,1,32669,11,2,2,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,450,-100,-300,0,1,0,0,15,1,0,1,32669,11,2,3,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,451,-100,-290,0,1,1,0,15,2,0,1,32669,11,3,0,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,452,-100,-280,0,1,2,0,15,3,0,1,32669,11,3,1,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,453,-100,-270,0,1,3,0,15,4,0,1,32669,11,3,2,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,454,-100,-260,0,1,4,0,15,5,0,1,32669,11,3,3,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,455,-100,-250,0,1,5,0,15,6,0,1,32669,11,4,0,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,456,-100,-240,0,1,6,0,15,7,0,1,32669,11,4,1,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,457,-100,-230,0,1,7,0,15,8,0,1,32669,11,4,2,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,458,-100,-220,0,1,8,0,15,9,0,1,32669,11,4,3,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,459,-100,-210,0,1,9,0,15,10,0,1,32669,11,5,0,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,460,-100,-200,0,1,10,0,15,11,0,1,32669,11,5,1,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,461,-100,-190,0,1,11,0,15,12,0,1,32669,11,5,2,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,462,-100,-180,0,1,12,0,15,13,0,1,32669,11,5,3,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,463,-100,-170,0,1,13,0,15,14,0,1,32669,11,6,0,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,464,-100,-160,0,1,14,0,15,15,0,1,32669,11,6,1,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,465,-100,-150,0,1,15,0,15,16,0,1,32669,11,6,2,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,466,-100,-140,0,1,16,0,15,17,0,1,32669,11,6,3,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,467,-100,-130,0,1,17,0,15,18,0,1,32669,11,7,0,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,468,-100,-120,0,1,18,0,15,19,0,1,32669,11,7,1,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,469,-100,-110,0,1,19,0,15,20,0,1,32669,11,7,2,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,470,-100,-100,0,1,20,0,15,21,0,1,32669,11,7,3,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,471,-100,-90,0,1,21,0,15,22,0,1,32669,11,8,0,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,472,-100,-80,0,1,22,0,15,23,0,1,32669,11,8,1,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,473,-100,-70,0,1,23,0,15,24,0,1,32669,11,8,2,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,474,-100,-60,0,1,24,0,15,25,0,1,32669,11,8,3,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,475,-100,-50,0,1,25,0,15,26,0,1,32669,11,9,0,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,476,-100,-40,0,1,26,0,15,27,0,1,32669,11,9,1,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,477,-100,-30,0,1,27,0,15,28,0,1,32669,11,9,2,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,478,-100,-20,0,1,28,0,15,29,0,1,32669,11,9,3,ON -7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,479,-100,-10,0,1,29,0,16,0,0,2,32669,12,0,0,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,480,100,-300,0,0,0,0,16,1,0,2,32669,12,0,1,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,481,100,-290,0,0,1,0,16,2,0,2,32669,12,0,2,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,482,100,-280,0,0,2,0,16,3,0,2,32669,12,0,3,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,483,100,-270,0,0,3,0,16,4,0,2,32669,12,1,0,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,484,100,-260,0,0,4,0,16,5,0,2,32669,12,1,1,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,485,100,-250,0,0,5,0,16,6,0,2,32669,12,1,2,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,486,100,-240,0,0,6,0,16,7,0,2,32669,12,1,3,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,487,100,-230,0,0,7,0,16,8,0,2,32669,12,2,0,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,488,100,-220,0,0,8,0,16,9,0,2,32669,12,2,1,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,489,100,-210,0,0,9,0,16,10,0,2,32669,12,2,2,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,490,100,-200,0,0,10,0,16,11,0,2,32669,12,2,3,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,491,100,-190,0,0,11,0,16,12,0,2,32669,12,3,0,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,492,100,-180,0,0,12,0,16,13,0,2,32669,12,3,1,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,493,100,-170,0,0,13,0,16,14,0,2,32669,12,3,2,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,494,100,-160,0,0,14,0,16,15,0,2,32669,12,3,3,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,495,100,-150,0,0,15,0,16,16,0,2,32669,12,4,0,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,496,100,-140,0,0,16,0,16,17,0,2,32669,12,4,1,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,497,100,-130,0,0,17,0,16,18,0,2,32669,12,4,2,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,498,100,-120,0,0,18,0,16,19,0,2,32669,12,4,3,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,499,100,-110,0,0,19,0,16,20,0,2,32669,12,5,0,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,500,100,-100,0,0,20,0,16,21,0,2,32669,12,5,1,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,501,100,-90,0,0,21,0,16,22,0,2,32669,12,5,2,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,502,100,-80,0,0,22,0,16,23,0,2,32669,12,5,3,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,503,100,-70,0,0,23,0,16,24,0,2,32669,12,6,0,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,504,100,-60,0,0,24,0,16,25,0,2,32669,12,6,1,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,505,100,-50,0,0,25,0,16,26,0,2,32669,12,6,2,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,506,100,-40,0,0,26,0,16,27,0,2,32669,12,6,3,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,507,100,-30,0,0,27,0,16,28,0,2,32669,12,7,0,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,508,100,-20,0,0,28,0,16,29,0,2,32669,12,7,1,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,509,100,-10,0,0,29,0,17,0,0,2,32669,12,7,2,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,510,-100,-300,0,1,0,0,17,1,0,2,32669,12,7,3,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,511,-100,-290,0,1,1,0,17,2,0,2,32669,12,8,0,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,512,-100,-280,0,1,2,0,17,3,0,2,32669,12,8,1,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,513,-100,-270,0,1,3,0,17,4,0,2,32669,12,8,2,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,514,-100,-260,0,1,4,0,17,5,0,2,32669,12,8,3,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,515,-100,-250,0,1,5,0,17,6,0,2,32669,12,9,0,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,516,-100,-240,0,1,6,0,17,7,0,2,32669,12,9,1,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,517,-100,-230,0,1,7,0,17,8,0,2,32669,12,9,2,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,518,-100,-220,0,1,8,0,17,9,0,2,32669,12,9,3,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,519,-100,-210,0,1,9,0,17,10,0,2,32669,13,0,0,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,520,-100,-200,0,1,10,0,17,11,0,2,32669,13,0,1,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,521,-100,-190,0,1,11,0,17,12,0,2,32669,13,0,2,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,522,-100,-180,0,1,12,0,17,13,0,2,32669,13,0,3,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,523,-100,-170,0,1,13,0,17,14,0,2,32669,13,1,0,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,524,-100,-160,0,1,14,0,17,15,0,2,32669,13,1,1,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,525,-100,-150,0,1,15,0,17,16,0,2,32669,13,1,2,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,526,-100,-140,0,1,16,0,17,17,0,2,32669,13,1,3,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,527,-100,-130,0,1,17,0,17,18,0,2,32669,13,2,0,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,528,-100,-120,0,1,18,0,17,19,0,2,32669,13,2,1,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,529,-100,-110,0,1,19,0,17,20,0,2,32669,13,2,2,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,530,-100,-100,0,1,20,0,17,21,0,2,32669,13,2,3,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,531,-100,-90,0,1,21,0,17,22,0,2,32669,13,3,0,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,532,-100,-80,0,1,22,0,17,23,0,2,32669,13,3,1,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,533,-100,-70,0,1,23,0,17,24,0,2,32669,13,3,2,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,534,-100,-60,0,1,24,0,17,25,0,2,32669,13,3,3,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,535,-100,-50,0,1,25,0,17,26,0,2,32669,13,4,0,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,536,-100,-40,0,1,26,0,17,27,0,2,32669,13,4,1,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,537,-100,-30,0,1,27,0,17,28,0,2,32669,13,4,2,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,538,-100,-20,0,1,28,0,17,29,0,2,32669,13,4,3,ON -8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,539,-100,-10,0,1,29,0,18,0,0,2,32669,13,5,0,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,540,100,-300,0,0,0,0,18,1,0,2,32669,13,5,1,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,541,100,-290,0,0,1,0,18,2,0,2,32669,13,5,2,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,542,100,-280,0,0,2,0,18,3,0,2,32669,13,5,3,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,543,100,-270,0,0,3,0,18,4,0,2,32669,13,6,0,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,544,100,-260,0,0,4,0,18,5,0,2,32669,13,6,1,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,545,100,-250,0,0,5,0,18,6,0,2,32669,13,6,2,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,546,100,-240,0,0,6,0,18,7,0,2,32669,13,6,3,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,547,100,-230,0,0,7,0,18,8,0,2,32669,13,7,0,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,548,100,-220,0,0,8,0,18,9,0,2,32669,13,7,1,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,549,100,-210,0,0,9,0,18,10,0,2,32669,13,7,2,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,550,100,-200,0,0,10,0,18,11,0,2,32669,13,7,3,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,551,100,-190,0,0,11,0,18,12,0,2,32669,13,8,0,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,552,100,-180,0,0,12,0,18,13,0,2,32669,13,8,1,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,553,100,-170,0,0,13,0,18,14,0,2,32669,13,8,2,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,554,100,-160,0,0,14,0,18,15,0,2,32669,13,8,3,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,555,100,-150,0,0,15,0,18,16,0,2,32669,13,9,0,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,556,100,-140,0,0,16,0,18,17,0,2,32669,13,9,1,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,557,100,-130,0,0,17,0,18,18,0,2,32669,13,9,2,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,558,100,-120,0,0,18,0,18,19,0,2,32669,13,9,3,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,559,100,-110,0,0,19,0,18,20,0,2,32669,14,0,0,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,560,100,-100,0,0,20,0,18,21,0,2,32669,14,0,1,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,561,100,-90,0,0,21,0,18,22,0,2,32669,14,0,2,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,562,100,-80,0,0,22,0,18,23,0,2,32669,14,0,3,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,563,100,-70,0,0,23,0,18,24,0,2,32669,14,1,0,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,564,100,-60,0,0,24,0,18,25,0,2,32669,14,1,1,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,565,100,-50,0,0,25,0,18,26,0,2,32669,14,1,2,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,566,100,-40,0,0,26,0,18,27,0,2,32669,14,1,3,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,567,100,-30,0,0,27,0,18,28,0,2,32669,14,2,0,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,568,100,-20,0,0,28,0,18,29,0,2,32669,14,2,1,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,569,100,-10,0,0,29,0,19,0,0,2,32669,14,2,2,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,570,-100,-300,0,1,0,0,19,1,0,2,32669,14,2,3,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,571,-100,-290,0,1,1,0,19,2,0,2,32669,14,3,0,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,572,-100,-280,0,1,2,0,19,3,0,2,32669,14,3,1,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,573,-100,-270,0,1,3,0,19,4,0,2,32669,14,3,2,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,574,-100,-260,0,1,4,0,19,5,0,2,32669,14,3,3,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,575,-100,-250,0,1,5,0,19,6,0,2,32669,14,4,0,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,576,-100,-240,0,1,6,0,19,7,0,2,32669,14,4,1,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,577,-100,-230,0,1,7,0,19,8,0,2,32669,14,4,2,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,578,-100,-220,0,1,8,0,19,9,0,2,32669,14,4,3,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,579,-100,-210,0,1,9,0,19,10,0,2,32669,14,5,0,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,580,-100,-200,0,1,10,0,19,11,0,2,32669,14,5,1,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,581,-100,-190,0,1,11,0,19,12,0,2,32669,14,5,2,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,582,-100,-180,0,1,12,0,19,13,0,2,32669,14,5,3,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,583,-100,-170,0,1,13,0,19,14,0,2,32669,14,6,0,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,584,-100,-160,0,1,14,0,19,15,0,2,32669,14,6,1,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,585,-100,-150,0,1,15,0,19,16,0,2,32669,14,6,2,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,586,-100,-140,0,1,16,0,19,17,0,2,32669,14,6,3,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,587,-100,-130,0,1,17,0,19,18,0,2,32669,14,7,0,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,588,-100,-120,0,1,18,0,19,19,0,2,32669,14,7,1,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,589,-100,-110,0,1,19,0,19,20,0,2,32669,14,7,2,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,590,-100,-100,0,1,20,0,19,21,0,2,32669,14,7,3,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,591,-100,-90,0,1,21,0,19,22,0,2,32669,14,8,0,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,592,-100,-80,0,1,22,0,19,23,0,2,32669,14,8,1,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,593,-100,-70,0,1,23,0,19,24,0,2,32669,14,8,2,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,594,-100,-60,0,1,24,0,19,25,0,2,32669,14,8,3,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,595,-100,-50,0,1,25,0,19,26,0,2,32669,14,9,0,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,596,-100,-40,0,1,26,0,19,27,0,2,32669,14,9,1,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,597,-100,-30,0,1,27,0,19,28,0,2,32669,14,9,2,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,598,-100,-20,0,1,28,0,19,29,0,2,32669,14,9,3,ON -9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,599,-100,-10,0,1,29,1,0,0,0,2,32669,15,0,0,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,600,100,-300,0,0,0,1,0,1,0,2,32669,15,0,1,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,601,100,-290,0,0,1,1,0,2,0,2,32669,15,0,2,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,602,100,-280,0,0,2,1,0,3,0,2,32669,15,0,3,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,603,100,-270,0,0,3,1,0,4,0,2,32669,15,1,0,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,604,100,-260,0,0,4,1,0,5,0,2,32669,15,1,1,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,605,100,-250,0,0,5,1,0,6,0,2,32669,15,1,2,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,606,100,-240,0,0,6,1,0,7,0,2,32669,15,1,3,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,607,100,-230,0,0,7,1,0,8,0,2,32669,15,2,0,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,608,100,-220,0,0,8,1,0,9,0,2,32669,15,2,1,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,609,100,-210,0,0,9,1,0,10,0,2,32669,15,2,2,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,610,100,-200,0,0,10,1,0,11,0,2,32669,15,2,3,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,611,100,-190,0,0,11,1,0,12,0,2,32669,15,3,0,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,612,100,-180,0,0,12,1,0,13,0,2,32669,15,3,1,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,613,100,-170,0,0,13,1,0,14,0,2,32669,15,3,2,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,614,100,-160,0,0,14,1,0,15,0,2,32669,15,3,3,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,615,100,-150,0,0,15,1,0,16,0,2,32669,15,4,0,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,616,100,-140,0,0,16,1,0,17,0,2,32669,15,4,1,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,617,100,-130,0,0,17,1,0,18,0,2,32669,15,4,2,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,618,100,-120,0,0,18,1,0,19,0,2,32669,15,4,3,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,619,100,-110,0,0,19,1,0,20,0,2,32669,15,5,0,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,620,100,-100,0,0,20,1,0,21,0,2,32669,15,5,1,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,621,100,-90,0,0,21,1,0,22,0,2,32669,15,5,2,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,622,100,-80,0,0,22,1,0,23,0,2,32669,15,5,3,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,623,100,-70,0,0,23,1,0,24,0,2,32669,15,6,0,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,624,100,-60,0,0,24,1,0,25,0,2,32669,15,6,1,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,625,100,-50,0,0,25,1,0,26,0,2,32669,15,6,2,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,626,100,-40,0,0,26,1,0,27,0,2,32669,15,6,3,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,627,100,-30,0,0,27,1,0,28,0,2,32669,15,7,0,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,628,100,-20,0,0,28,1,0,29,0,2,32669,15,7,1,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,629,100,-10,0,0,29,1,1,0,0,2,32669,15,7,2,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,630,-100,-300,0,1,0,1,1,1,0,2,32669,15,7,3,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,631,-100,-290,0,1,1,1,1,2,0,2,32669,15,8,0,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,632,-100,-280,0,1,2,1,1,3,0,2,32669,15,8,1,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,633,-100,-270,0,1,3,1,1,4,0,2,32669,15,8,2,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,634,-100,-260,0,1,4,1,1,5,0,2,32669,15,8,3,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,635,-100,-250,0,1,5,1,1,6,0,2,32669,15,9,0,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,636,-100,-240,0,1,6,1,1,7,0,2,32669,15,9,1,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,637,-100,-230,0,1,7,1,1,8,0,2,32669,15,9,2,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,638,-100,-220,0,1,8,1,1,9,0,2,32669,15,9,3,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,639,-100,-210,0,1,9,1,1,10,0,2,32669,16,0,0,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,640,-100,-200,0,1,10,1,1,11,0,2,32669,16,0,1,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,641,-100,-190,0,1,11,1,1,12,0,2,32669,16,0,2,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,642,-100,-180,0,1,12,1,1,13,0,2,32669,16,0,3,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,643,-100,-170,0,1,13,1,1,14,0,2,32669,16,1,0,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,644,-100,-160,0,1,14,1,1,15,0,2,32669,16,1,1,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,645,-100,-150,0,1,15,1,1,16,0,2,32669,16,1,2,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,646,-100,-140,0,1,16,1,1,17,0,2,32669,16,1,3,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,647,-100,-130,0,1,17,1,1,18,0,2,32669,16,2,0,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,648,-100,-120,0,1,18,1,1,19,0,2,32669,16,2,1,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,649,-100,-110,0,1,19,1,1,20,0,2,32669,16,2,2,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,650,-100,-100,0,1,20,1,1,21,0,2,32669,16,2,3,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,651,-100,-90,0,1,21,1,1,22,0,2,32669,16,3,0,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,652,-100,-80,0,1,22,1,1,23,0,2,32669,16,3,1,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,653,-100,-70,0,1,23,1,1,24,0,2,32669,16,3,2,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,654,-100,-60,0,1,24,1,1,25,0,2,32669,16,3,3,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,655,-100,-50,0,1,25,1,1,26,0,2,32669,16,4,0,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,656,-100,-40,0,1,26,1,1,27,0,2,32669,16,4,1,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,657,-100,-30,0,1,27,1,1,28,0,2,32669,16,4,2,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,658,-100,-20,0,1,28,1,1,29,0,2,32669,16,4,3,ON -10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,659,-100,-10,0,1,29,1,2,0,0,2,32669,16,5,0,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,660,100,-300,0,0,0,1,2,1,0,2,32669,16,5,1,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,661,100,-290,0,0,1,1,2,2,0,2,32669,16,5,2,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,662,100,-280,0,0,2,1,2,3,0,2,32669,16,5,3,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,663,100,-270,0,0,3,1,2,4,0,2,32669,16,6,0,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,664,100,-260,0,0,4,1,2,5,0,2,32669,16,6,1,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,665,100,-250,0,0,5,1,2,6,0,2,32669,16,6,2,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,666,100,-240,0,0,6,1,2,7,0,2,32669,16,6,3,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,667,100,-230,0,0,7,1,2,8,0,2,32669,16,7,0,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,668,100,-220,0,0,8,1,2,9,0,2,32669,16,7,1,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,669,100,-210,0,0,9,1,2,10,0,2,32669,16,7,2,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,670,100,-200,0,0,10,1,2,11,0,2,32669,16,7,3,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,671,100,-190,0,0,11,1,2,12,0,2,32669,16,8,0,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,672,100,-180,0,0,12,1,2,13,0,2,32669,16,8,1,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,673,100,-170,0,0,13,1,2,14,0,2,32669,16,8,2,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,674,100,-160,0,0,14,1,2,15,0,2,32669,16,8,3,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,675,100,-150,0,0,15,1,2,16,0,2,32669,16,9,0,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,676,100,-140,0,0,16,1,2,17,0,2,32669,16,9,1,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,677,100,-130,0,0,17,1,2,18,0,2,32669,16,9,2,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,678,100,-120,0,0,18,1,2,19,0,2,32669,16,9,3,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,679,100,-110,0,0,19,1,2,20,0,2,32669,17,0,0,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,680,100,-100,0,0,20,1,2,21,0,2,32669,17,0,1,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,681,100,-90,0,0,21,1,2,22,0,2,32669,17,0,2,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,682,100,-80,0,0,22,1,2,23,0,2,32669,17,0,3,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,683,100,-70,0,0,23,1,2,24,0,2,32669,17,1,0,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,684,100,-60,0,0,24,1,2,25,0,2,32669,17,1,1,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,685,100,-50,0,0,25,1,2,26,0,2,32669,17,1,2,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,686,100,-40,0,0,26,1,2,27,0,2,32669,17,1,3,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,687,100,-30,0,0,27,1,2,28,0,2,32669,17,2,0,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,688,100,-20,0,0,28,1,2,29,0,2,32669,17,2,1,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,689,100,-10,0,0,29,1,3,0,0,2,32669,17,2,2,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,690,-100,-300,0,1,0,1,3,1,0,2,32669,17,2,3,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,691,-100,-290,0,1,1,1,3,2,0,2,32669,17,3,0,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,692,-100,-280,0,1,2,1,3,3,0,2,32669,17,3,1,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,693,-100,-270,0,1,3,1,3,4,0,2,32669,17,3,2,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,694,-100,-260,0,1,4,1,3,5,0,2,32669,17,3,3,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,695,-100,-250,0,1,5,1,3,6,0,2,32669,17,4,0,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,696,-100,-240,0,1,6,1,3,7,0,2,32669,17,4,1,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,697,-100,-230,0,1,7,1,3,8,0,2,32669,17,4,2,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,698,-100,-220,0,1,8,1,3,9,0,2,32669,17,4,3,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,699,-100,-210,0,1,9,1,3,10,0,2,32669,17,5,0,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,700,-100,-200,0,1,10,1,3,11,0,2,32669,17,5,1,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,701,-100,-190,0,1,11,1,3,12,0,2,32669,17,5,2,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,702,-100,-180,0,1,12,1,3,13,0,2,32669,17,5,3,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,703,-100,-170,0,1,13,1,3,14,0,2,32669,17,6,0,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,704,-100,-160,0,1,14,1,3,15,0,2,32669,17,6,1,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,705,-100,-150,0,1,15,1,3,16,0,2,32669,17,6,2,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,706,-100,-140,0,1,16,1,3,17,0,2,32669,17,6,3,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,707,-100,-130,0,1,17,1,3,18,0,2,32669,17,7,0,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,708,-100,-120,0,1,18,1,3,19,0,2,32669,17,7,1,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,709,-100,-110,0,1,19,1,3,20,0,2,32669,17,7,2,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,710,-100,-100,0,1,20,1,3,21,0,2,32669,17,7,3,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,711,-100,-90,0,1,21,1,3,22,0,2,32669,17,8,0,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,712,-100,-80,0,1,22,1,3,23,0,2,32669,17,8,1,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,713,-100,-70,0,1,23,1,3,24,0,2,32669,17,8,2,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,714,-100,-60,0,1,24,1,3,25,0,2,32669,17,8,3,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,715,-100,-50,0,1,25,1,3,26,0,2,32669,17,9,0,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,716,-100,-40,0,1,26,1,3,27,0,2,32669,17,9,1,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,717,-100,-30,0,1,27,1,3,28,0,2,32669,17,9,2,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,718,-100,-20,0,1,28,1,3,29,0,2,32669,17,9,3,ON -11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,719,-100,-10,0,1,29,1,4,0,0,3,32669,18,0,0,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,720,100,-300,0,0,0,1,4,1,0,3,32669,18,0,1,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,721,100,-290,0,0,1,1,4,2,0,3,32669,18,0,2,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,722,100,-280,0,0,2,1,4,3,0,3,32669,18,0,3,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,723,100,-270,0,0,3,1,4,4,0,3,32669,18,1,0,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,724,100,-260,0,0,4,1,4,5,0,3,32669,18,1,1,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,725,100,-250,0,0,5,1,4,6,0,3,32669,18,1,2,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,726,100,-240,0,0,6,1,4,7,0,3,32669,18,1,3,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,727,100,-230,0,0,7,1,4,8,0,3,32669,18,2,0,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,728,100,-220,0,0,8,1,4,9,0,3,32669,18,2,1,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,729,100,-210,0,0,9,1,4,10,0,3,32669,18,2,2,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,730,100,-200,0,0,10,1,4,11,0,3,32669,18,2,3,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,731,100,-190,0,0,11,1,4,12,0,3,32669,18,3,0,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,732,100,-180,0,0,12,1,4,13,0,3,32669,18,3,1,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,733,100,-170,0,0,13,1,4,14,0,3,32669,18,3,2,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,734,100,-160,0,0,14,1,4,15,0,3,32669,18,3,3,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,735,100,-150,0,0,15,1,4,16,0,3,32669,18,4,0,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,736,100,-140,0,0,16,1,4,17,0,3,32669,18,4,1,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,737,100,-130,0,0,17,1,4,18,0,3,32669,18,4,2,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,738,100,-120,0,0,18,1,4,19,0,3,32669,18,4,3,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,739,100,-110,0,0,19,1,4,20,0,3,32669,18,5,0,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,740,100,-100,0,0,20,1,4,21,0,3,32669,18,5,1,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,741,100,-90,0,0,21,1,4,22,0,3,32669,18,5,2,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,742,100,-80,0,0,22,1,4,23,0,3,32669,18,5,3,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,743,100,-70,0,0,23,1,4,24,0,3,32669,18,6,0,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,744,100,-60,0,0,24,1,4,25,0,3,32669,18,6,1,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,745,100,-50,0,0,25,1,4,26,0,3,32669,18,6,2,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,746,100,-40,0,0,26,1,4,27,0,3,32669,18,6,3,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,747,100,-30,0,0,27,1,4,28,0,3,32669,18,7,0,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,748,100,-20,0,0,28,1,4,29,0,3,32669,18,7,1,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,749,100,-10,0,0,29,1,5,0,0,3,32669,18,7,2,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,750,-100,-300,0,1,0,1,5,1,0,3,32669,18,7,3,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,751,-100,-290,0,1,1,1,5,2,0,3,32669,18,8,0,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,752,-100,-280,0,1,2,1,5,3,0,3,32669,18,8,1,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,753,-100,-270,0,1,3,1,5,4,0,3,32669,18,8,2,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,754,-100,-260,0,1,4,1,5,5,0,3,32669,18,8,3,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,755,-100,-250,0,1,5,1,5,6,0,3,32669,18,9,0,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,756,-100,-240,0,1,6,1,5,7,0,3,32669,18,9,1,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,757,-100,-230,0,1,7,1,5,8,0,3,32669,18,9,2,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,758,-100,-220,0,1,8,1,5,9,0,3,32669,18,9,3,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,759,-100,-210,0,1,9,1,5,10,0,3,32669,19,0,0,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,760,-100,-200,0,1,10,1,5,11,0,3,32669,19,0,1,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,761,-100,-190,0,1,11,1,5,12,0,3,32669,19,0,2,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,762,-100,-180,0,1,12,1,5,13,0,3,32669,19,0,3,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,763,-100,-170,0,1,13,1,5,14,0,3,32669,19,1,0,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,764,-100,-160,0,1,14,1,5,15,0,3,32669,19,1,1,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,765,-100,-150,0,1,15,1,5,16,0,3,32669,19,1,2,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,766,-100,-140,0,1,16,1,5,17,0,3,32669,19,1,3,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,767,-100,-130,0,1,17,1,5,18,0,3,32669,19,2,0,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,768,-100,-120,0,1,18,1,5,19,0,3,32669,19,2,1,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,769,-100,-110,0,1,19,1,5,20,0,3,32669,19,2,2,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,770,-100,-100,0,1,20,1,5,21,0,3,32669,19,2,3,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,771,-100,-90,0,1,21,1,5,22,0,3,32669,19,3,0,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,772,-100,-80,0,1,22,1,5,23,0,3,32669,19,3,1,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,773,-100,-70,0,1,23,1,5,24,0,3,32669,19,3,2,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,774,-100,-60,0,1,24,1,5,25,0,3,32669,19,3,3,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,775,-100,-50,0,1,25,1,5,26,0,3,32669,19,4,0,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,776,-100,-40,0,1,26,1,5,27,0,3,32669,19,4,1,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,777,-100,-30,0,1,27,1,5,28,0,3,32669,19,4,2,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,778,-100,-20,0,1,28,1,5,29,0,3,32669,19,4,3,ON -12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,779,-100,-10,0,1,29,1,6,0,0,3,32669,19,5,0,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,780,100,-300,0,0,0,1,6,1,0,3,32669,19,5,1,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,781,100,-290,0,0,1,1,6,2,0,3,32669,19,5,2,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,782,100,-280,0,0,2,1,6,3,0,3,32669,19,5,3,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,783,100,-270,0,0,3,1,6,4,0,3,32669,19,6,0,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,784,100,-260,0,0,4,1,6,5,0,3,32669,19,6,1,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,785,100,-250,0,0,5,1,6,6,0,3,32669,19,6,2,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,786,100,-240,0,0,6,1,6,7,0,3,32669,19,6,3,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,787,100,-230,0,0,7,1,6,8,0,3,32669,19,7,0,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,788,100,-220,0,0,8,1,6,9,0,3,32669,19,7,1,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,789,100,-210,0,0,9,1,6,10,0,3,32669,19,7,2,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,790,100,-200,0,0,10,1,6,11,0,3,32669,19,7,3,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,791,100,-190,0,0,11,1,6,12,0,3,32669,19,8,0,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,792,100,-180,0,0,12,1,6,13,0,3,32669,19,8,1,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,793,100,-170,0,0,13,1,6,14,0,3,32669,19,8,2,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,794,100,-160,0,0,14,1,6,15,0,3,32669,19,8,3,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,795,100,-150,0,0,15,1,6,16,0,3,32669,19,9,0,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,796,100,-140,0,0,16,1,6,17,0,3,32669,19,9,1,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,797,100,-130,0,0,17,1,6,18,0,3,32669,19,9,2,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,798,100,-120,0,0,18,1,6,19,0,3,32669,19,9,3,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,799,100,-110,0,0,19,1,6,20,0,3,32669,20,0,0,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,800,100,-100,0,0,20,1,6,21,0,3,32669,20,0,1,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,801,100,-90,0,0,21,1,6,22,0,3,32669,20,0,2,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,802,100,-80,0,0,22,1,6,23,0,3,32669,20,0,3,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,803,100,-70,0,0,23,1,6,24,0,3,32669,20,1,0,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,804,100,-60,0,0,24,1,6,25,0,3,32669,20,1,1,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,805,100,-50,0,0,25,1,6,26,0,3,32669,20,1,2,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,806,100,-40,0,0,26,1,6,27,0,3,32669,20,1,3,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,807,100,-30,0,0,27,1,6,28,0,3,32669,20,2,0,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,808,100,-20,0,0,28,1,6,29,0,3,32669,20,2,1,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,809,100,-10,0,0,29,1,7,0,0,3,32669,20,2,2,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,810,-100,-300,0,1,0,1,7,1,0,3,32669,20,2,3,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,811,-100,-290,0,1,1,1,7,2,0,3,32669,20,3,0,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,812,-100,-280,0,1,2,1,7,3,0,3,32669,20,3,1,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,813,-100,-270,0,1,3,1,7,4,0,3,32669,20,3,2,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,814,-100,-260,0,1,4,1,7,5,0,3,32669,20,3,3,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,815,-100,-250,0,1,5,1,7,6,0,3,32669,20,4,0,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,816,-100,-240,0,1,6,1,7,7,0,3,32669,20,4,1,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,817,-100,-230,0,1,7,1,7,8,0,3,32669,20,4,2,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,818,-100,-220,0,1,8,1,7,9,0,3,32669,20,4,3,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,819,-100,-210,0,1,9,1,7,10,0,3,32669,20,5,0,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,820,-100,-200,0,1,10,1,7,11,0,3,32669,20,5,1,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,821,-100,-190,0,1,11,1,7,12,0,3,32669,20,5,2,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,822,-100,-180,0,1,12,1,7,13,0,3,32669,20,5,3,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,823,-100,-170,0,1,13,1,7,14,0,3,32669,20,6,0,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,824,-100,-160,0,1,14,1,7,15,0,3,32669,20,6,1,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,825,-100,-150,0,1,15,1,7,16,0,3,32669,20,6,2,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,826,-100,-140,0,1,16,1,7,17,0,3,32669,20,6,3,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,827,-100,-130,0,1,17,1,7,18,0,3,32669,20,7,0,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,828,-100,-120,0,1,18,1,7,19,0,3,32669,20,7,1,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,829,-100,-110,0,1,19,1,7,20,0,3,32669,20,7,2,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,830,-100,-100,0,1,20,1,7,21,0,3,32669,20,7,3,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,831,-100,-90,0,1,21,1,7,22,0,3,32669,20,8,0,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,832,-100,-80,0,1,22,1,7,23,0,3,32669,20,8,1,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,833,-100,-70,0,1,23,1,7,24,0,3,32669,20,8,2,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,834,-100,-60,0,1,24,1,7,25,0,3,32669,20,8,3,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,835,-100,-50,0,1,25,1,7,26,0,3,32669,20,9,0,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,836,-100,-40,0,1,26,1,7,27,0,3,32669,20,9,1,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,837,-100,-30,0,1,27,1,7,28,0,3,32669,20,9,2,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,838,-100,-20,0,1,28,1,7,29,0,3,32669,20,9,3,ON -13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,839,-100,-10,0,1,29,1,8,0,0,3,32669,21,0,0,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,840,100,-300,0,0,0,1,8,1,0,3,32669,21,0,1,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,841,100,-290,0,0,1,1,8,2,0,3,32669,21,0,2,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,842,100,-280,0,0,2,1,8,3,0,3,32669,21,0,3,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,843,100,-270,0,0,3,1,8,4,0,3,32669,21,1,0,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,844,100,-260,0,0,4,1,8,5,0,3,32669,21,1,1,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,845,100,-250,0,0,5,1,8,6,0,3,32669,21,1,2,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,846,100,-240,0,0,6,1,8,7,0,3,32669,21,1,3,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,847,100,-230,0,0,7,1,8,8,0,3,32669,21,2,0,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,848,100,-220,0,0,8,1,8,9,0,3,32669,21,2,1,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,849,100,-210,0,0,9,1,8,10,0,3,32669,21,2,2,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,850,100,-200,0,0,10,1,8,11,0,3,32669,21,2,3,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,851,100,-190,0,0,11,1,8,12,0,3,32669,21,3,0,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,852,100,-180,0,0,12,1,8,13,0,3,32669,21,3,1,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,853,100,-170,0,0,13,1,8,14,0,3,32669,21,3,2,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,854,100,-160,0,0,14,1,8,15,0,3,32669,21,3,3,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,855,100,-150,0,0,15,1,8,16,0,3,32669,21,4,0,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,856,100,-140,0,0,16,1,8,17,0,3,32669,21,4,1,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,857,100,-130,0,0,17,1,8,18,0,3,32669,21,4,2,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,858,100,-120,0,0,18,1,8,19,0,3,32669,21,4,3,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,859,100,-110,0,0,19,1,8,20,0,3,32669,21,5,0,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,860,100,-100,0,0,20,1,8,21,0,3,32669,21,5,1,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,861,100,-90,0,0,21,1,8,22,0,3,32669,21,5,2,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,862,100,-80,0,0,22,1,8,23,0,3,32669,21,5,3,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,863,100,-70,0,0,23,1,8,24,0,3,32669,21,6,0,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,864,100,-60,0,0,24,1,8,25,0,3,32669,21,6,1,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,865,100,-50,0,0,25,1,8,26,0,3,32669,21,6,2,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,866,100,-40,0,0,26,1,8,27,0,3,32669,21,6,3,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,867,100,-30,0,0,27,1,8,28,0,3,32669,21,7,0,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,868,100,-20,0,0,28,1,8,29,0,3,32669,21,7,1,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,869,100,-10,0,0,29,1,9,0,0,3,32669,21,7,2,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,870,-100,-300,0,1,0,1,9,1,0,3,32669,21,7,3,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,871,-100,-290,0,1,1,1,9,2,0,3,32669,21,8,0,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,872,-100,-280,0,1,2,1,9,3,0,3,32669,21,8,1,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,873,-100,-270,0,1,3,1,9,4,0,3,32669,21,8,2,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,874,-100,-260,0,1,4,1,9,5,0,3,32669,21,8,3,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,875,-100,-250,0,1,5,1,9,6,0,3,32669,21,9,0,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,876,-100,-240,0,1,6,1,9,7,0,3,32669,21,9,1,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,877,-100,-230,0,1,7,1,9,8,0,3,32669,21,9,2,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,878,-100,-220,0,1,8,1,9,9,0,3,32669,21,9,3,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,879,-100,-210,0,1,9,1,9,10,0,3,32669,22,0,0,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,880,-100,-200,0,1,10,1,9,11,0,3,32669,22,0,1,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,881,-100,-190,0,1,11,1,9,12,0,3,32669,22,0,2,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,882,-100,-180,0,1,12,1,9,13,0,3,32669,22,0,3,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,883,-100,-170,0,1,13,1,9,14,0,3,32669,22,1,0,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,884,-100,-160,0,1,14,1,9,15,0,3,32669,22,1,1,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,885,-100,-150,0,1,15,1,9,16,0,3,32669,22,1,2,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,886,-100,-140,0,1,16,1,9,17,0,3,32669,22,1,3,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,887,-100,-130,0,1,17,1,9,18,0,3,32669,22,2,0,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,888,-100,-120,0,1,18,1,9,19,0,3,32669,22,2,1,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,889,-100,-110,0,1,19,1,9,20,0,3,32669,22,2,2,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,890,-100,-100,0,1,20,1,9,21,0,3,32669,22,2,3,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,891,-100,-90,0,1,21,1,9,22,0,3,32669,22,3,0,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,892,-100,-80,0,1,22,1,9,23,0,3,32669,22,3,1,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,893,-100,-70,0,1,23,1,9,24,0,3,32669,22,3,2,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,894,-100,-60,0,1,24,1,9,25,0,3,32669,22,3,3,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,895,-100,-50,0,1,25,1,9,26,0,3,32669,22,4,0,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,896,-100,-40,0,1,26,1,9,27,0,3,32669,22,4,1,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,897,-100,-30,0,1,27,1,9,28,0,3,32669,22,4,2,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,898,-100,-20,0,1,28,1,9,29,0,3,32669,22,4,3,ON -14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,899,-100,-10,0,1,29,1,10,0,0,3,32669,22,5,0,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,900,100,-300,0,0,0,1,10,1,0,3,32669,22,5,1,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,901,100,-290,0,0,1,1,10,2,0,3,32669,22,5,2,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,902,100,-280,0,0,2,1,10,3,0,3,32669,22,5,3,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,903,100,-270,0,0,3,1,10,4,0,3,32669,22,6,0,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,904,100,-260,0,0,4,1,10,5,0,3,32669,22,6,1,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,905,100,-250,0,0,5,1,10,6,0,3,32669,22,6,2,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,906,100,-240,0,0,6,1,10,7,0,3,32669,22,6,3,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,907,100,-230,0,0,7,1,10,8,0,3,32669,22,7,0,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,908,100,-220,0,0,8,1,10,9,0,3,32669,22,7,1,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,909,100,-210,0,0,9,1,10,10,0,3,32669,22,7,2,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,910,100,-200,0,0,10,1,10,11,0,3,32669,22,7,3,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,911,100,-190,0,0,11,1,10,12,0,3,32669,22,8,0,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,912,100,-180,0,0,12,1,10,13,0,3,32669,22,8,1,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,913,100,-170,0,0,13,1,10,14,0,3,32669,22,8,2,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,914,100,-160,0,0,14,1,10,15,0,3,32669,22,8,3,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,915,100,-150,0,0,15,1,10,16,0,3,32669,22,9,0,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,916,100,-140,0,0,16,1,10,17,0,3,32669,22,9,1,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,917,100,-130,0,0,17,1,10,18,0,3,32669,22,9,2,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,918,100,-120,0,0,18,1,10,19,0,3,32669,22,9,3,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,919,100,-110,0,0,19,1,10,20,0,3,32669,23,0,0,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,920,100,-100,0,0,20,1,10,21,0,3,32669,23,0,1,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,921,100,-90,0,0,21,1,10,22,0,3,32669,23,0,2,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,922,100,-80,0,0,22,1,10,23,0,3,32669,23,0,3,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,923,100,-70,0,0,23,1,10,24,0,3,32669,23,1,0,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,924,100,-60,0,0,24,1,10,25,0,3,32669,23,1,1,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,925,100,-50,0,0,25,1,10,26,0,3,32669,23,1,2,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,926,100,-40,0,0,26,1,10,27,0,3,32669,23,1,3,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,927,100,-30,0,0,27,1,10,28,0,3,32669,23,2,0,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,928,100,-20,0,0,28,1,10,29,0,3,32669,23,2,1,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,929,100,-10,0,0,29,1,11,0,0,3,32669,23,2,2,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,930,-100,-300,0,1,0,1,11,1,0,3,32669,23,2,3,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,931,-100,-290,0,1,1,1,11,2,0,3,32669,23,3,0,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,932,-100,-280,0,1,2,1,11,3,0,3,32669,23,3,1,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,933,-100,-270,0,1,3,1,11,4,0,3,32669,23,3,2,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,934,-100,-260,0,1,4,1,11,5,0,3,32669,23,3,3,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,935,-100,-250,0,1,5,1,11,6,0,3,32669,23,4,0,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,936,-100,-240,0,1,6,1,11,7,0,3,32669,23,4,1,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,937,-100,-230,0,1,7,1,11,8,0,3,32669,23,4,2,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,938,-100,-220,0,1,8,1,11,9,0,3,32669,23,4,3,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,939,-100,-210,0,1,9,1,11,10,0,3,32669,23,5,0,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,940,-100,-200,0,1,10,1,11,11,0,3,32669,23,5,1,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,941,-100,-190,0,1,11,1,11,12,0,3,32669,23,5,2,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,942,-100,-180,0,1,12,1,11,13,0,3,32669,23,5,3,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,943,-100,-170,0,1,13,1,11,14,0,3,32669,23,6,0,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,944,-100,-160,0,1,14,1,11,15,0,3,32669,23,6,1,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,945,-100,-150,0,1,15,1,11,16,0,3,32669,23,6,2,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,946,-100,-140,0,1,16,1,11,17,0,3,32669,23,6,3,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,947,-100,-130,0,1,17,1,11,18,0,3,32669,23,7,0,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,948,-100,-120,0,1,18,1,11,19,0,3,32669,23,7,1,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,949,-100,-110,0,1,19,1,11,20,0,3,32669,23,7,2,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,950,-100,-100,0,1,20,1,11,21,0,3,32669,23,7,3,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,951,-100,-90,0,1,21,1,11,22,0,3,32669,23,8,0,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,952,-100,-80,0,1,22,1,11,23,0,3,32669,23,8,1,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,953,-100,-70,0,1,23,1,11,24,0,3,32669,23,8,2,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,954,-100,-60,0,1,24,1,11,25,0,3,32669,23,8,3,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,955,-100,-50,0,1,25,1,11,26,0,3,32669,23,9,0,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,956,-100,-40,0,1,26,1,11,27,0,3,32669,23,9,1,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,957,-100,-30,0,1,27,1,11,28,0,3,32669,23,9,2,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,958,-100,-20,0,1,28,1,11,29,0,3,32669,23,9,3,ON -15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,959,-100,-10,0,1,29,1,12,0,0,4,32669,24,0,0,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,960,100,-300,0,0,0,1,12,1,0,4,32669,24,0,1,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,961,100,-290,0,0,1,1,12,2,0,4,32669,24,0,2,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,962,100,-280,0,0,2,1,12,3,0,4,32669,24,0,3,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,963,100,-270,0,0,3,1,12,4,0,4,32669,24,1,0,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,964,100,-260,0,0,4,1,12,5,0,4,32669,24,1,1,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,965,100,-250,0,0,5,1,12,6,0,4,32669,24,1,2,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,966,100,-240,0,0,6,1,12,7,0,4,32669,24,1,3,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,967,100,-230,0,0,7,1,12,8,0,4,32669,24,2,0,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,968,100,-220,0,0,8,1,12,9,0,4,32669,24,2,1,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,969,100,-210,0,0,9,1,12,10,0,4,32669,24,2,2,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,970,100,-200,0,0,10,1,12,11,0,4,32669,24,2,3,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,971,100,-190,0,0,11,1,12,12,0,4,32669,24,3,0,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,972,100,-180,0,0,12,1,12,13,0,4,32669,24,3,1,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,973,100,-170,0,0,13,1,12,14,0,4,32669,24,3,2,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,974,100,-160,0,0,14,1,12,15,0,4,32669,24,3,3,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,975,100,-150,0,0,15,1,12,16,0,4,32669,24,4,0,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,976,100,-140,0,0,16,1,12,17,0,4,32669,24,4,1,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,977,100,-130,0,0,17,1,12,18,0,4,32669,24,4,2,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,978,100,-120,0,0,18,1,12,19,0,4,32669,24,4,3,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,979,100,-110,0,0,19,1,12,20,0,4,32669,24,5,0,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,980,100,-100,0,0,20,1,12,21,0,4,32669,24,5,1,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,981,100,-90,0,0,21,1,12,22,0,4,32669,24,5,2,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,982,100,-80,0,0,22,1,12,23,0,4,32669,24,5,3,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,983,100,-70,0,0,23,1,12,24,0,4,32669,24,6,0,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,984,100,-60,0,0,24,1,12,25,0,4,32669,24,6,1,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,985,100,-50,0,0,25,1,12,26,0,4,32669,24,6,2,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,986,100,-40,0,0,26,1,12,27,0,4,32669,24,6,3,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,987,100,-30,0,0,27,1,12,28,0,4,32669,24,7,0,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,988,100,-20,0,0,28,1,12,29,0,4,32669,24,7,1,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,989,100,-10,0,0,29,1,13,0,0,4,32669,24,7,2,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,990,-100,-300,0,1,0,1,13,1,0,4,32669,24,7,3,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,991,-100,-290,0,1,1,1,13,2,0,4,32669,24,8,0,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,992,-100,-280,0,1,2,1,13,3,0,4,32669,24,8,1,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,993,-100,-270,0,1,3,1,13,4,0,4,32669,24,8,2,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,994,-100,-260,0,1,4,1,13,5,0,4,32669,24,8,3,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,995,-100,-250,0,1,5,1,13,6,0,4,32669,24,9,0,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,996,-100,-240,0,1,6,1,13,7,0,4,32669,24,9,1,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,997,-100,-230,0,1,7,1,13,8,0,4,32669,24,9,2,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,998,-100,-220,0,1,8,1,13,9,0,4,32669,24,9,3,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,999,-100,-210,0,1,9,1,13,10,0,4,32669,25,0,0,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1000,-100,-200,0,1,10,1,13,11,0,4,32669,25,0,1,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1001,-100,-190,0,1,11,1,13,12,0,4,32669,25,0,2,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1002,-100,-180,0,1,12,1,13,13,0,4,32669,25,0,3,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1003,-100,-170,0,1,13,1,13,14,0,4,32669,25,1,0,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1004,-100,-160,0,1,14,1,13,15,0,4,32669,25,1,1,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1005,-100,-150,0,1,15,1,13,16,0,4,32669,25,1,2,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1006,-100,-140,0,1,16,1,13,17,0,4,32669,25,1,3,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1007,-100,-130,0,1,17,1,13,18,0,4,32669,25,2,0,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1008,-100,-120,0,1,18,1,13,19,0,4,32669,25,2,1,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1009,-100,-110,0,1,19,1,13,20,0,4,32669,25,2,2,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1010,-100,-100,0,1,20,1,13,21,0,4,32669,25,2,3,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1011,-100,-90,0,1,21,1,13,22,0,4,32669,25,3,0,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1012,-100,-80,0,1,22,1,13,23,0,4,32669,25,3,1,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1013,-100,-70,0,1,23,1,13,24,0,4,32669,25,3,2,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1014,-100,-60,0,1,24,1,13,25,0,4,32669,25,3,3,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1015,-100,-50,0,1,25,1,13,26,0,4,32669,25,4,0,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1016,-100,-40,0,1,26,1,13,27,0,4,32669,25,4,1,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1017,-100,-30,0,1,27,1,13,28,0,4,32669,25,4,2,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1018,-100,-20,0,1,28,1,13,29,0,4,32669,25,4,3,ON -16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1019,-100,-10,0,1,29,1,14,0,0,4,32669,25,5,0,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1020,100,-300,0,0,0,1,14,1,0,4,32669,25,5,1,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1021,100,-290,0,0,1,1,14,2,0,4,32669,25,5,2,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1022,100,-280,0,0,2,1,14,3,0,4,32669,25,5,3,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1023,100,-270,0,0,3,1,14,4,0,4,32669,25,6,0,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1024,100,-260,0,0,4,1,14,5,0,4,32669,25,6,1,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1025,100,-250,0,0,5,1,14,6,0,4,32669,25,6,2,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1026,100,-240,0,0,6,1,14,7,0,4,32669,25,6,3,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1027,100,-230,0,0,7,1,14,8,0,4,32669,25,7,0,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1028,100,-220,0,0,8,1,14,9,0,4,32669,25,7,1,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1029,100,-210,0,0,9,1,14,10,0,4,32669,25,7,2,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1030,100,-200,0,0,10,1,14,11,0,4,32669,25,7,3,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1031,100,-190,0,0,11,1,14,12,0,4,32669,25,8,0,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1032,100,-180,0,0,12,1,14,13,0,4,32669,25,8,1,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1033,100,-170,0,0,13,1,14,14,0,4,32669,25,8,2,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1034,100,-160,0,0,14,1,14,15,0,4,32669,25,8,3,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1035,100,-150,0,0,15,1,14,16,0,4,32669,25,9,0,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1036,100,-140,0,0,16,1,14,17,0,4,32669,25,9,1,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1037,100,-130,0,0,17,1,14,18,0,4,32669,25,9,2,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1038,100,-120,0,0,18,1,14,19,0,4,32669,25,9,3,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1039,100,-110,0,0,19,1,14,20,0,4,32669,26,0,0,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1040,100,-100,0,0,20,1,14,21,0,4,32669,26,0,1,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1041,100,-90,0,0,21,1,14,22,0,4,32669,26,0,2,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1042,100,-80,0,0,22,1,14,23,0,4,32669,26,0,3,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1043,100,-70,0,0,23,1,14,24,0,4,32669,26,1,0,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1044,100,-60,0,0,24,1,14,25,0,4,32669,26,1,1,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1045,100,-50,0,0,25,1,14,26,0,4,32669,26,1,2,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1046,100,-40,0,0,26,1,14,27,0,4,32669,26,1,3,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1047,100,-30,0,0,27,1,14,28,0,4,32669,26,2,0,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1048,100,-20,0,0,28,1,14,29,0,4,32669,26,2,1,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1049,100,-10,0,0,29,1,15,0,0,4,32669,26,2,2,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1050,-100,-300,0,1,0,1,15,1,0,4,32669,26,2,3,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1051,-100,-290,0,1,1,1,15,2,0,4,32669,26,3,0,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1052,-100,-280,0,1,2,1,15,3,0,4,32669,26,3,1,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1053,-100,-270,0,1,3,1,15,4,0,4,32669,26,3,2,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1054,-100,-260,0,1,4,1,15,5,0,4,32669,26,3,3,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1055,-100,-250,0,1,5,1,15,6,0,4,32669,26,4,0,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1056,-100,-240,0,1,6,1,15,7,0,4,32669,26,4,1,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1057,-100,-230,0,1,7,1,15,8,0,4,32669,26,4,2,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1058,-100,-220,0,1,8,1,15,9,0,4,32669,26,4,3,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1059,-100,-210,0,1,9,1,15,10,0,4,32669,26,5,0,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1060,-100,-200,0,1,10,1,15,11,0,4,32669,26,5,1,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1061,-100,-190,0,1,11,1,15,12,0,4,32669,26,5,2,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1062,-100,-180,0,1,12,1,15,13,0,4,32669,26,5,3,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1063,-100,-170,0,1,13,1,15,14,0,4,32669,26,6,0,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1064,-100,-160,0,1,14,1,15,15,0,4,32669,26,6,1,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1065,-100,-150,0,1,15,1,15,16,0,4,32669,26,6,2,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1066,-100,-140,0,1,16,1,15,17,0,4,32669,26,6,3,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1067,-100,-130,0,1,17,1,15,18,0,4,32669,26,7,0,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1068,-100,-120,0,1,18,1,15,19,0,4,32669,26,7,1,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1069,-100,-110,0,1,19,1,15,20,0,4,32669,26,7,2,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1070,-100,-100,0,1,20,1,15,21,0,4,32669,26,7,3,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1071,-100,-90,0,1,21,1,15,22,0,4,32669,26,8,0,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1072,-100,-80,0,1,22,1,15,23,0,4,32669,26,8,1,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1073,-100,-70,0,1,23,1,15,24,0,4,32669,26,8,2,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1074,-100,-60,0,1,24,1,15,25,0,4,32669,26,8,3,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1075,-100,-50,0,1,25,1,15,26,0,4,32669,26,9,0,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1076,-100,-40,0,1,26,1,15,27,0,4,32669,26,9,1,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1077,-100,-30,0,1,27,1,15,28,0,4,32669,26,9,2,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1078,-100,-20,0,1,28,1,15,29,0,4,32669,26,9,3,ON -17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1079,-100,-10,0,1,29,1,16,0,0,4,32669,27,0,0,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1080,100,-300,0,0,0,1,16,1,0,4,32669,27,0,1,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1081,100,-290,0,0,1,1,16,2,0,4,32669,27,0,2,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1082,100,-280,0,0,2,1,16,3,0,4,32669,27,0,3,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1083,100,-270,0,0,3,1,16,4,0,4,32669,27,1,0,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1084,100,-260,0,0,4,1,16,5,0,4,32669,27,1,1,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1085,100,-250,0,0,5,1,16,6,0,4,32669,27,1,2,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1086,100,-240,0,0,6,1,16,7,0,4,32669,27,1,3,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1087,100,-230,0,0,7,1,16,8,0,4,32669,27,2,0,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1088,100,-220,0,0,8,1,16,9,0,4,32669,27,2,1,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1089,100,-210,0,0,9,1,16,10,0,4,32669,27,2,2,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1090,100,-200,0,0,10,1,16,11,0,4,32669,27,2,3,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1091,100,-190,0,0,11,1,16,12,0,4,32669,27,3,0,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1092,100,-180,0,0,12,1,16,13,0,4,32669,27,3,1,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1093,100,-170,0,0,13,1,16,14,0,4,32669,27,3,2,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1094,100,-160,0,0,14,1,16,15,0,4,32669,27,3,3,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1095,100,-150,0,0,15,1,16,16,0,4,32669,27,4,0,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1096,100,-140,0,0,16,1,16,17,0,4,32669,27,4,1,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1097,100,-130,0,0,17,1,16,18,0,4,32669,27,4,2,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1098,100,-120,0,0,18,1,16,19,0,4,32669,27,4,3,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1099,100,-110,0,0,19,1,16,20,0,4,32669,27,5,0,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1100,100,-100,0,0,20,1,16,21,0,4,32669,27,5,1,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1101,100,-90,0,0,21,1,16,22,0,4,32669,27,5,2,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1102,100,-80,0,0,22,1,16,23,0,4,32669,27,5,3,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1103,100,-70,0,0,23,1,16,24,0,4,32669,27,6,0,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1104,100,-60,0,0,24,1,16,25,0,4,32669,27,6,1,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1105,100,-50,0,0,25,1,16,26,0,4,32669,27,6,2,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1106,100,-40,0,0,26,1,16,27,0,4,32669,27,6,3,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1107,100,-30,0,0,27,1,16,28,0,4,32669,27,7,0,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1108,100,-20,0,0,28,1,16,29,0,4,32669,27,7,1,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1109,100,-10,0,0,29,1,17,0,0,4,32669,27,7,2,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1110,-100,-300,0,1,0,1,17,1,0,4,32669,27,7,3,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1111,-100,-290,0,1,1,1,17,2,0,4,32669,27,8,0,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1112,-100,-280,0,1,2,1,17,3,0,4,32669,27,8,1,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1113,-100,-270,0,1,3,1,17,4,0,4,32669,27,8,2,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1114,-100,-260,0,1,4,1,17,5,0,4,32669,27,8,3,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1115,-100,-250,0,1,5,1,17,6,0,4,32669,27,9,0,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1116,-100,-240,0,1,6,1,17,7,0,4,32669,27,9,1,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1117,-100,-230,0,1,7,1,17,8,0,4,32669,27,9,2,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1118,-100,-220,0,1,8,1,17,9,0,4,32669,27,9,3,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1119,-100,-210,0,1,9,1,17,10,0,4,32669,28,0,0,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1120,-100,-200,0,1,10,1,17,11,0,4,32669,28,0,1,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1121,-100,-190,0,1,11,1,17,12,0,4,32669,28,0,2,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1122,-100,-180,0,1,12,1,17,13,0,4,32669,28,0,3,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1123,-100,-170,0,1,13,1,17,14,0,4,32669,28,1,0,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1124,-100,-160,0,1,14,1,17,15,0,4,32669,28,1,1,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1125,-100,-150,0,1,15,1,17,16,0,4,32669,28,1,2,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1126,-100,-140,0,1,16,1,17,17,0,4,32669,28,1,3,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1127,-100,-130,0,1,17,1,17,18,0,4,32669,28,2,0,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1128,-100,-120,0,1,18,1,17,19,0,4,32669,28,2,1,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1129,-100,-110,0,1,19,1,17,20,0,4,32669,28,2,2,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1130,-100,-100,0,1,20,1,17,21,0,4,32669,28,2,3,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1131,-100,-90,0,1,21,1,17,22,0,4,32669,28,3,0,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1132,-100,-80,0,1,22,1,17,23,0,4,32669,28,3,1,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1133,-100,-70,0,1,23,1,17,24,0,4,32669,28,3,2,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1134,-100,-60,0,1,24,1,17,25,0,4,32669,28,3,3,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1135,-100,-50,0,1,25,1,17,26,0,4,32669,28,4,0,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1136,-100,-40,0,1,26,1,17,27,0,4,32669,28,4,1,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1137,-100,-30,0,1,27,1,17,28,0,4,32669,28,4,2,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1138,-100,-20,0,1,28,1,17,29,0,4,32669,28,4,3,ON -18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1139,-100,-10,0,1,29,1,18,0,0,4,32669,28,5,0,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1140,100,-300,0,0,0,1,18,1,0,4,32669,28,5,1,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1141,100,-290,0,0,1,1,18,2,0,4,32669,28,5,2,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1142,100,-280,0,0,2,1,18,3,0,4,32669,28,5,3,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1143,100,-270,0,0,3,1,18,4,0,4,32669,28,6,0,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1144,100,-260,0,0,4,1,18,5,0,4,32669,28,6,1,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1145,100,-250,0,0,5,1,18,6,0,4,32669,28,6,2,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1146,100,-240,0,0,6,1,18,7,0,4,32669,28,6,3,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1147,100,-230,0,0,7,1,18,8,0,4,32669,28,7,0,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1148,100,-220,0,0,8,1,18,9,0,4,32669,28,7,1,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1149,100,-210,0,0,9,1,18,10,0,4,32669,28,7,2,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1150,100,-200,0,0,10,1,18,11,0,4,32669,28,7,3,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1151,100,-190,0,0,11,1,18,12,0,4,32669,28,8,0,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1152,100,-180,0,0,12,1,18,13,0,4,32669,28,8,1,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1153,100,-170,0,0,13,1,18,14,0,4,32669,28,8,2,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1154,100,-160,0,0,14,1,18,15,0,4,32669,28,8,3,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1155,100,-150,0,0,15,1,18,16,0,4,32669,28,9,0,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1156,100,-140,0,0,16,1,18,17,0,4,32669,28,9,1,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1157,100,-130,0,0,17,1,18,18,0,4,32669,28,9,2,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1158,100,-120,0,0,18,1,18,19,0,4,32669,28,9,3,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1159,100,-110,0,0,19,1,18,20,0,4,32669,29,0,0,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1160,100,-100,0,0,20,1,18,21,0,4,32669,29,0,1,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1161,100,-90,0,0,21,1,18,22,0,4,32669,29,0,2,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1162,100,-80,0,0,22,1,18,23,0,4,32669,29,0,3,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1163,100,-70,0,0,23,1,18,24,0,4,32669,29,1,0,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1164,100,-60,0,0,24,1,18,25,0,4,32669,29,1,1,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1165,100,-50,0,0,25,1,18,26,0,4,32669,29,1,2,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1166,100,-40,0,0,26,1,18,27,0,4,32669,29,1,3,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1167,100,-30,0,0,27,1,18,28,0,4,32669,29,2,0,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1168,100,-20,0,0,28,1,18,29,0,4,32669,29,2,1,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1169,100,-10,0,0,29,1,19,0,0,4,32669,29,2,2,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1170,-100,-300,0,1,0,1,19,1,0,4,32669,29,2,3,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1171,-100,-290,0,1,1,1,19,2,0,4,32669,29,3,0,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1172,-100,-280,0,1,2,1,19,3,0,4,32669,29,3,1,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1173,-100,-270,0,1,3,1,19,4,0,4,32669,29,3,2,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1174,-100,-260,0,1,4,1,19,5,0,4,32669,29,3,3,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1175,-100,-250,0,1,5,1,19,6,0,4,32669,29,4,0,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1176,-100,-240,0,1,6,1,19,7,0,4,32669,29,4,1,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1177,-100,-230,0,1,7,1,19,8,0,4,32669,29,4,2,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1178,-100,-220,0,1,8,1,19,9,0,4,32669,29,4,3,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1179,-100,-210,0,1,9,1,19,10,0,4,32669,29,5,0,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1180,-100,-200,0,1,10,1,19,11,0,4,32669,29,5,1,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1181,-100,-190,0,1,11,1,19,12,0,4,32669,29,5,2,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1182,-100,-180,0,1,12,1,19,13,0,4,32669,29,5,3,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1183,-100,-170,0,1,13,1,19,14,0,4,32669,29,6,0,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1184,-100,-160,0,1,14,1,19,15,0,4,32669,29,6,1,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1185,-100,-150,0,1,15,1,19,16,0,4,32669,29,6,2,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1186,-100,-140,0,1,16,1,19,17,0,4,32669,29,6,3,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1187,-100,-130,0,1,17,1,19,18,0,4,32669,29,7,0,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1188,-100,-120,0,1,18,1,19,19,0,4,32669,29,7,1,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1189,-100,-110,0,1,19,1,19,20,0,4,32669,29,7,2,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1190,-100,-100,0,1,20,1,19,21,0,4,32669,29,7,3,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1191,-100,-90,0,1,21,1,19,22,0,4,32669,29,8,0,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1192,-100,-80,0,1,22,1,19,23,0,4,32669,29,8,1,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1193,-100,-70,0,1,23,1,19,24,0,4,32669,29,8,2,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1194,-100,-60,0,1,24,1,19,25,0,4,32669,29,8,3,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1195,-100,-50,0,1,25,1,19,26,0,4,32669,29,9,0,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1196,-100,-40,0,1,26,1,19,27,0,4,32669,29,9,1,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1197,-100,-30,0,1,27,1,19,28,0,4,32669,29,9,2,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1198,-100,-20,0,1,28,1,19,29,0,4,32669,29,9,3,ON -19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1199,-100,-10,0,1,29,2,0,0,0,5,32669,30,0,0,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1200,100,-300,0,0,0,2,0,1,0,5,32669,30,0,1,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1201,100,-290,0,0,1,2,0,2,0,5,32669,30,0,2,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1202,100,-280,0,0,2,2,0,3,0,5,32669,30,0,3,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1203,100,-270,0,0,3,2,0,4,0,5,32669,30,1,0,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1204,100,-260,0,0,4,2,0,5,0,5,32669,30,1,1,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1205,100,-250,0,0,5,2,0,6,0,5,32669,30,1,2,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1206,100,-240,0,0,6,2,0,7,0,5,32669,30,1,3,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1207,100,-230,0,0,7,2,0,8,0,5,32669,30,2,0,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1208,100,-220,0,0,8,2,0,9,0,5,32669,30,2,1,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1209,100,-210,0,0,9,2,0,10,0,5,32669,30,2,2,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1210,100,-200,0,0,10,2,0,11,0,5,32669,30,2,3,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1211,100,-190,0,0,11,2,0,12,0,5,32669,30,3,0,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1212,100,-180,0,0,12,2,0,13,0,5,32669,30,3,1,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1213,100,-170,0,0,13,2,0,14,0,5,32669,30,3,2,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1214,100,-160,0,0,14,2,0,15,0,5,32669,30,3,3,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1215,100,-150,0,0,15,2,0,16,0,5,32669,30,4,0,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1216,100,-140,0,0,16,2,0,17,0,5,32669,30,4,1,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1217,100,-130,0,0,17,2,0,18,0,5,32669,30,4,2,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1218,100,-120,0,0,18,2,0,19,0,5,32669,30,4,3,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1219,100,-110,0,0,19,2,0,20,0,5,32669,30,5,0,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1220,100,-100,0,0,20,2,0,21,0,5,32669,30,5,1,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1221,100,-90,0,0,21,2,0,22,0,5,32669,30,5,2,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1222,100,-80,0,0,22,2,0,23,0,5,32669,30,5,3,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1223,100,-70,0,0,23,2,0,24,0,5,32669,30,6,0,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1224,100,-60,0,0,24,2,0,25,0,5,32669,30,6,1,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1225,100,-50,0,0,25,2,0,26,0,5,32669,30,6,2,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1226,100,-40,0,0,26,2,0,27,0,5,32669,30,6,3,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1227,100,-30,0,0,27,2,0,28,0,5,32669,30,7,0,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1228,100,-20,0,0,28,2,0,29,0,5,32669,30,7,1,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1229,100,-10,0,0,29,2,1,0,0,5,32669,30,7,2,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1230,-100,-300,0,1,0,2,1,1,0,5,32669,30,7,3,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1231,-100,-290,0,1,1,2,1,2,0,5,32669,30,8,0,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1232,-100,-280,0,1,2,2,1,3,0,5,32669,30,8,1,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1233,-100,-270,0,1,3,2,1,4,0,5,32669,30,8,2,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1234,-100,-260,0,1,4,2,1,5,0,5,32669,30,8,3,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1235,-100,-250,0,1,5,2,1,6,0,5,32669,30,9,0,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1236,-100,-240,0,1,6,2,1,7,0,5,32669,30,9,1,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1237,-100,-230,0,1,7,2,1,8,0,5,32669,30,9,2,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1238,-100,-220,0,1,8,2,1,9,0,5,32669,30,9,3,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1239,-100,-210,0,1,9,2,1,10,0,5,32669,31,0,0,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1240,-100,-200,0,1,10,2,1,11,0,5,32669,31,0,1,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1241,-100,-190,0,1,11,2,1,12,0,5,32669,31,0,2,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1242,-100,-180,0,1,12,2,1,13,0,5,32669,31,0,3,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1243,-100,-170,0,1,13,2,1,14,0,5,32669,31,1,0,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1244,-100,-160,0,1,14,2,1,15,0,5,32669,31,1,1,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1245,-100,-150,0,1,15,2,1,16,0,5,32669,31,1,2,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1246,-100,-140,0,1,16,2,1,17,0,5,32669,31,1,3,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1247,-100,-130,0,1,17,2,1,18,0,5,32669,31,2,0,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1248,-100,-120,0,1,18,2,1,19,0,5,32669,31,2,1,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1249,-100,-110,0,1,19,2,1,20,0,5,32669,31,2,2,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1250,-100,-100,0,1,20,2,1,21,0,5,32669,31,2,3,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1251,-100,-90,0,1,21,2,1,22,0,5,32669,31,3,0,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1252,-100,-80,0,1,22,2,1,23,0,5,32669,31,3,1,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1253,-100,-70,0,1,23,2,1,24,0,5,32669,31,3,2,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1254,-100,-60,0,1,24,2,1,25,0,5,32669,31,3,3,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1255,-100,-50,0,1,25,2,1,26,0,5,32669,31,4,0,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1256,-100,-40,0,1,26,2,1,27,0,5,32669,31,4,1,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1257,-100,-30,0,1,27,2,1,28,0,5,32669,31,4,2,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1258,-100,-20,0,1,28,2,1,29,0,5,32669,31,4,3,ON -20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1259,-100,-10,0,1,29,2,2,0,0,5,32669,31,5,0,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1260,100,-300,0,0,0,2,2,1,0,5,32669,31,5,1,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1261,100,-290,0,0,1,2,2,2,0,5,32669,31,5,2,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1262,100,-280,0,0,2,2,2,3,0,5,32669,31,5,3,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1263,100,-270,0,0,3,2,2,4,0,5,32669,31,6,0,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1264,100,-260,0,0,4,2,2,5,0,5,32669,31,6,1,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1265,100,-250,0,0,5,2,2,6,0,5,32669,31,6,2,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1266,100,-240,0,0,6,2,2,7,0,5,32669,31,6,3,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1267,100,-230,0,0,7,2,2,8,0,5,32669,31,7,0,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1268,100,-220,0,0,8,2,2,9,0,5,32669,31,7,1,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1269,100,-210,0,0,9,2,2,10,0,5,32669,31,7,2,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1270,100,-200,0,0,10,2,2,11,0,5,32669,31,7,3,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1271,100,-190,0,0,11,2,2,12,0,5,32669,31,8,0,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1272,100,-180,0,0,12,2,2,13,0,5,32669,31,8,1,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1273,100,-170,0,0,13,2,2,14,0,5,32669,31,8,2,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1274,100,-160,0,0,14,2,2,15,0,5,32669,31,8,3,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1275,100,-150,0,0,15,2,2,16,0,5,32669,31,9,0,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1276,100,-140,0,0,16,2,2,17,0,5,32669,31,9,1,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1277,100,-130,0,0,17,2,2,18,0,5,32669,31,9,2,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1278,100,-120,0,0,18,2,2,19,0,5,32669,31,9,3,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1279,100,-110,0,0,19,2,2,20,0,5,32669,32,0,0,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1280,100,-100,0,0,20,2,2,21,0,5,32669,32,0,1,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1281,100,-90,0,0,21,2,2,22,0,5,32669,32,0,2,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1282,100,-80,0,0,22,2,2,23,0,5,32669,32,0,3,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1283,100,-70,0,0,23,2,2,24,0,5,32669,32,1,0,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1284,100,-60,0,0,24,2,2,25,0,5,32669,32,1,1,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1285,100,-50,0,0,25,2,2,26,0,5,32669,32,1,2,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1286,100,-40,0,0,26,2,2,27,0,5,32669,32,1,3,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1287,100,-30,0,0,27,2,2,28,0,5,32669,32,2,0,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1288,100,-20,0,0,28,2,2,29,0,5,32669,32,2,1,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1289,100,-10,0,0,29,2,3,0,0,5,32669,32,2,2,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1290,-100,-300,0,1,0,2,3,1,0,5,32669,32,2,3,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1291,-100,-290,0,1,1,2,3,2,0,5,32669,32,3,0,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1292,-100,-280,0,1,2,2,3,3,0,5,32669,32,3,1,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1293,-100,-270,0,1,3,2,3,4,0,5,32669,32,3,2,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1294,-100,-260,0,1,4,2,3,5,0,5,32669,32,3,3,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1295,-100,-250,0,1,5,2,3,6,0,5,32669,32,4,0,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1296,-100,-240,0,1,6,2,3,7,0,5,32669,32,4,1,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1297,-100,-230,0,1,7,2,3,8,0,5,32669,32,4,2,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1298,-100,-220,0,1,8,2,3,9,0,5,32669,32,4,3,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1299,-100,-210,0,1,9,2,3,10,0,5,32669,32,5,0,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1300,-100,-200,0,1,10,2,3,11,0,5,32669,32,5,1,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1301,-100,-190,0,1,11,2,3,12,0,5,32669,32,5,2,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1302,-100,-180,0,1,12,2,3,13,0,5,32669,32,5,3,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1303,-100,-170,0,1,13,2,3,14,0,5,32669,32,6,0,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1304,-100,-160,0,1,14,2,3,15,0,5,32669,32,6,1,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1305,-100,-150,0,1,15,2,3,16,0,5,32669,32,6,2,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1306,-100,-140,0,1,16,2,3,17,0,5,32669,32,6,3,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1307,-100,-130,0,1,17,2,3,18,0,5,32669,32,7,0,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1308,-100,-120,0,1,18,2,3,19,0,5,32669,32,7,1,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1309,-100,-110,0,1,19,2,3,20,0,5,32669,32,7,2,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1310,-100,-100,0,1,20,2,3,21,0,5,32669,32,7,3,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1311,-100,-90,0,1,21,2,3,22,0,5,32669,32,8,0,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1312,-100,-80,0,1,22,2,3,23,0,5,32669,32,8,1,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1313,-100,-70,0,1,23,2,3,24,0,5,32669,32,8,2,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1314,-100,-60,0,1,24,2,3,25,0,5,32669,32,8,3,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1315,-100,-50,0,1,25,2,3,26,0,5,32669,32,9,0,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1316,-100,-40,0,1,26,2,3,27,0,5,32669,32,9,1,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1317,-100,-30,0,1,27,2,3,28,0,5,32669,32,9,2,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1318,-100,-20,0,1,28,2,3,29,0,5,32669,32,9,3,ON -21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1319,-100,-10,0,1,29,2,4,0,0,5,32669,33,0,0,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1320,100,-300,0,0,0,2,4,1,0,5,32669,33,0,1,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1321,100,-290,0,0,1,2,4,2,0,5,32669,33,0,2,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1322,100,-280,0,0,2,2,4,3,0,5,32669,33,0,3,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1323,100,-270,0,0,3,2,4,4,0,5,32669,33,1,0,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1324,100,-260,0,0,4,2,4,5,0,5,32669,33,1,1,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1325,100,-250,0,0,5,2,4,6,0,5,32669,33,1,2,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1326,100,-240,0,0,6,2,4,7,0,5,32669,33,1,3,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1327,100,-230,0,0,7,2,4,8,0,5,32669,33,2,0,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1328,100,-220,0,0,8,2,4,9,0,5,32669,33,2,1,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1329,100,-210,0,0,9,2,4,10,0,5,32669,33,2,2,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1330,100,-200,0,0,10,2,4,11,0,5,32669,33,2,3,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1331,100,-190,0,0,11,2,4,12,0,5,32669,33,3,0,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1332,100,-180,0,0,12,2,4,13,0,5,32669,33,3,1,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1333,100,-170,0,0,13,2,4,14,0,5,32669,33,3,2,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1334,100,-160,0,0,14,2,4,15,0,5,32669,33,3,3,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1335,100,-150,0,0,15,2,4,16,0,5,32669,33,4,0,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1336,100,-140,0,0,16,2,4,17,0,5,32669,33,4,1,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1337,100,-130,0,0,17,2,4,18,0,5,32669,33,4,2,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1338,100,-120,0,0,18,2,4,19,0,5,32669,33,4,3,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1339,100,-110,0,0,19,2,4,20,0,5,32669,33,5,0,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1340,100,-100,0,0,20,2,4,21,0,5,32669,33,5,1,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1341,100,-90,0,0,21,2,4,22,0,5,32669,33,5,2,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1342,100,-80,0,0,22,2,4,23,0,5,32669,33,5,3,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1343,100,-70,0,0,23,2,4,24,0,5,32669,33,6,0,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1344,100,-60,0,0,24,2,4,25,0,5,32669,33,6,1,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1345,100,-50,0,0,25,2,4,26,0,5,32669,33,6,2,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1346,100,-40,0,0,26,2,4,27,0,5,32669,33,6,3,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1347,100,-30,0,0,27,2,4,28,0,5,32669,33,7,0,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1348,100,-20,0,0,28,2,4,29,0,5,32669,33,7,1,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1349,100,-10,0,0,29,2,5,0,0,5,32669,33,7,2,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1350,-100,-300,0,1,0,2,5,1,0,5,32669,33,7,3,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1351,-100,-290,0,1,1,2,5,2,0,5,32669,33,8,0,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1352,-100,-280,0,1,2,2,5,3,0,5,32669,33,8,1,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1353,-100,-270,0,1,3,2,5,4,0,5,32669,33,8,2,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1354,-100,-260,0,1,4,2,5,5,0,5,32669,33,8,3,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1355,-100,-250,0,1,5,2,5,6,0,5,32669,33,9,0,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1356,-100,-240,0,1,6,2,5,7,0,5,32669,33,9,1,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1357,-100,-230,0,1,7,2,5,8,0,5,32669,33,9,2,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1358,-100,-220,0,1,8,2,5,9,0,5,32669,33,9,3,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1359,-100,-210,0,1,9,2,5,10,0,5,32669,34,0,0,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1360,-100,-200,0,1,10,2,5,11,0,5,32669,34,0,1,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1361,-100,-190,0,1,11,2,5,12,0,5,32669,34,0,2,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1362,-100,-180,0,1,12,2,5,13,0,5,32669,34,0,3,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1363,-100,-170,0,1,13,2,5,14,0,5,32669,34,1,0,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1364,-100,-160,0,1,14,2,5,15,0,5,32669,34,1,1,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1365,-100,-150,0,1,15,2,5,16,0,5,32669,34,1,2,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1366,-100,-140,0,1,16,2,5,17,0,5,32669,34,1,3,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1367,-100,-130,0,1,17,2,5,18,0,5,32669,34,2,0,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1368,-100,-120,0,1,18,2,5,19,0,5,32669,34,2,1,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1369,-100,-110,0,1,19,2,5,20,0,5,32669,34,2,2,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1370,-100,-100,0,1,20,2,5,21,0,5,32669,34,2,3,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1371,-100,-90,0,1,21,2,5,22,0,5,32669,34,3,0,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1372,-100,-80,0,1,22,2,5,23,0,5,32669,34,3,1,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1373,-100,-70,0,1,23,2,5,24,0,5,32669,34,3,2,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1374,-100,-60,0,1,24,2,5,25,0,5,32669,34,3,3,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1375,-100,-50,0,1,25,2,5,26,0,5,32669,34,4,0,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1376,-100,-40,0,1,26,2,5,27,0,5,32669,34,4,1,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1377,-100,-30,0,1,27,2,5,28,0,5,32669,34,4,2,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1378,-100,-20,0,1,28,2,5,29,0,5,32669,34,4,3,ON -22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1379,-100,-10,0,1,29,2,6,0,0,5,32669,34,5,0,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1380,100,-300,0,0,0,2,6,1,0,5,32669,34,5,1,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1381,100,-290,0,0,1,2,6,2,0,5,32669,34,5,2,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1382,100,-280,0,0,2,2,6,3,0,5,32669,34,5,3,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1383,100,-270,0,0,3,2,6,4,0,5,32669,34,6,0,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1384,100,-260,0,0,4,2,6,5,0,5,32669,34,6,1,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1385,100,-250,0,0,5,2,6,6,0,5,32669,34,6,2,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1386,100,-240,0,0,6,2,6,7,0,5,32669,34,6,3,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1387,100,-230,0,0,7,2,6,8,0,5,32669,34,7,0,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1388,100,-220,0,0,8,2,6,9,0,5,32669,34,7,1,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1389,100,-210,0,0,9,2,6,10,0,5,32669,34,7,2,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1390,100,-200,0,0,10,2,6,11,0,5,32669,34,7,3,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1391,100,-190,0,0,11,2,6,12,0,5,32669,34,8,0,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1392,100,-180,0,0,12,2,6,13,0,5,32669,34,8,1,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1393,100,-170,0,0,13,2,6,14,0,5,32669,34,8,2,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1394,100,-160,0,0,14,2,6,15,0,5,32669,34,8,3,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1395,100,-150,0,0,15,2,6,16,0,5,32669,34,9,0,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1396,100,-140,0,0,16,2,6,17,0,5,32669,34,9,1,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1397,100,-130,0,0,17,2,6,18,0,5,32669,34,9,2,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1398,100,-120,0,0,18,2,6,19,0,5,32669,34,9,3,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1399,100,-110,0,0,19,2,6,20,0,5,32669,35,0,0,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1400,100,-100,0,0,20,2,6,21,0,5,32669,35,0,1,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1401,100,-90,0,0,21,2,6,22,0,5,32669,35,0,2,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1402,100,-80,0,0,22,2,6,23,0,5,32669,35,0,3,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1403,100,-70,0,0,23,2,6,24,0,5,32669,35,1,0,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1404,100,-60,0,0,24,2,6,25,0,5,32669,35,1,1,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1405,100,-50,0,0,25,2,6,26,0,5,32669,35,1,2,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1406,100,-40,0,0,26,2,6,27,0,5,32669,35,1,3,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1407,100,-30,0,0,27,2,6,28,0,5,32669,35,2,0,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1408,100,-20,0,0,28,2,6,29,0,5,32669,35,2,1,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1409,100,-10,0,0,29,2,7,0,0,5,32669,35,2,2,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1410,-100,-300,0,1,0,2,7,1,0,5,32669,35,2,3,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1411,-100,-290,0,1,1,2,7,2,0,5,32669,35,3,0,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1412,-100,-280,0,1,2,2,7,3,0,5,32669,35,3,1,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1413,-100,-270,0,1,3,2,7,4,0,5,32669,35,3,2,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1414,-100,-260,0,1,4,2,7,5,0,5,32669,35,3,3,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1415,-100,-250,0,1,5,2,7,6,0,5,32669,35,4,0,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1416,-100,-240,0,1,6,2,7,7,0,5,32669,35,4,1,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1417,-100,-230,0,1,7,2,7,8,0,5,32669,35,4,2,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1418,-100,-220,0,1,8,2,7,9,0,5,32669,35,4,3,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1419,-100,-210,0,1,9,2,7,10,0,5,32669,35,5,0,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1420,-100,-200,0,1,10,2,7,11,0,5,32669,35,5,1,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1421,-100,-190,0,1,11,2,7,12,0,5,32669,35,5,2,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1422,-100,-180,0,1,12,2,7,13,0,5,32669,35,5,3,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1423,-100,-170,0,1,13,2,7,14,0,5,32669,35,6,0,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1424,-100,-160,0,1,14,2,7,15,0,5,32669,35,6,1,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1425,-100,-150,0,1,15,2,7,16,0,5,32669,35,6,2,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1426,-100,-140,0,1,16,2,7,17,0,5,32669,35,6,3,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1427,-100,-130,0,1,17,2,7,18,0,5,32669,35,7,0,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1428,-100,-120,0,1,18,2,7,19,0,5,32669,35,7,1,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1429,-100,-110,0,1,19,2,7,20,0,5,32669,35,7,2,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1430,-100,-100,0,1,20,2,7,21,0,5,32669,35,7,3,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1431,-100,-90,0,1,21,2,7,22,0,5,32669,35,8,0,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1432,-100,-80,0,1,22,2,7,23,0,5,32669,35,8,1,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1433,-100,-70,0,1,23,2,7,24,0,5,32669,35,8,2,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1434,-100,-60,0,1,24,2,7,25,0,5,32669,35,8,3,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1435,-100,-50,0,1,25,2,7,26,0,5,32669,35,9,0,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1436,-100,-40,0,1,26,2,7,27,0,5,32669,35,9,1,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1437,-100,-30,0,1,27,2,7,28,0,5,32669,35,9,2,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1438,-100,-20,0,1,28,2,7,29,0,5,32669,35,9,3,ON -23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1439,-100,-10,0,1,29,2,8,0,0,6,32669,36,0,0,ON -DATA_END +LEGEND_LINE,,,,,,,,,,,,,,,,,,,,,,,, +detector_num,detector_position_x,detector_position_y,detector_position_z,detector_direction_x,detector_direction_y,detector_direction_z,detector_type,detector_status,channel_num,channel_position_x,channel_position_y,channel_position_z,channel_strip_side,channel_strip_num,channel_signal_crate,channel_signal_card,channel_signal_channel,channel_level2_crate,channel_level2_card,channel_level2_channel,channel_hv_crate,channel_hv_card,channel_hv_channel,channel_status +,,,,,,,,,,,,,,,,,,,,,,,, +DATA_START,,,,,,,,,,,,,,,,,,,,,,,, +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,4,100,-300,0,0,0,0,0,1,0,0,32669,0,0,1,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,3,100,-290,0,0,1,0,0,2,0,0,32669,0,0,2,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,2,100,-280,0,0,2,0,0,3,0,0,32669,0,0,3,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,1,100,-270,0,0,3,0,0,4,0,0,32669,0,1,0,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,0,100,-260,0,0,4,0,0,5,0,0,32669,0,1,1,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,11,100,-250,0,0,5,0,0,6,0,0,32669,0,1,2,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,10,100,-240,0,0,6,0,0,7,0,0,32669,0,1,3,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,9,100,-230,0,0,7,0,0,8,0,0,32669,0,2,0,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,8,100,-220,0,0,8,0,0,9,0,0,32669,0,2,1,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,7,100,-210,0,0,9,0,0,10,0,0,32669,0,2,2,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,6,100,-200,0,0,10,0,0,11,0,0,32669,0,2,3,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,17,100,-190,0,0,11,0,0,12,0,0,32669,0,3,0,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,16,100,-180,0,0,12,0,0,13,0,0,32669,0,3,1,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,15,100,-170,0,0,13,0,0,14,0,0,32669,0,3,2,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,14,100,-160,0,0,14,0,0,15,0,0,32669,0,3,3,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,43,100,-150,0,0,15,0,0,16,0,0,32669,0,4,0,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,42,100,-140,0,0,16,0,0,17,0,0,32669,0,4,1,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,53,100,-130,0,0,17,0,0,18,0,0,32669,0,4,2,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,52,100,-120,0,0,18,0,0,19,0,0,32669,0,4,3,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,51,100,-110,0,0,19,0,0,20,0,0,32669,0,5,0,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,50,100,-100,0,0,20,0,0,21,0,0,32669,0,5,1,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,49,100,-90,0,0,21,0,0,22,0,0,32669,0,5,2,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,48,100,-80,0,0,22,0,0,23,0,0,32669,0,5,3,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,59,100,-70,0,0,23,0,0,24,0,0,32669,0,6,0,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,58,100,-60,0,0,24,0,0,25,0,0,32669,0,6,1,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,57,100,-50,0,0,25,0,0,26,0,0,32669,0,6,2,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,56,100,-40,0,0,26,0,0,27,0,0,32669,0,6,3,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,55,100,-30,0,0,27,0,0,28,0,0,32669,0,7,0,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,54,100,-20,0,0,28,0,0,29,0,0,32669,0,7,1,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,34,100,-10,0,0,29,0,1,0,0,0,32669,0,7,2,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,5,-100,-300,0,1,0,0,1,1,0,0,32669,0,7,3,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,24,-100,-290,0,1,1,0,1,2,0,0,32669,0,8,0,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,25,-100,-280,0,1,2,0,1,3,0,0,32669,0,8,1,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,26,-100,-270,0,1,3,0,1,4,0,0,32669,0,8,2,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,27,-100,-260,0,1,4,0,1,5,0,0,32669,0,8,3,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,28,-100,-250,0,1,5,0,1,6,0,0,32669,0,9,0,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,29,-100,-240,0,1,6,0,1,7,0,0,32669,0,9,1,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,18,-100,-230,0,1,7,0,1,8,0,0,32669,0,9,2,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,19,-100,-220,0,1,8,0,1,9,0,0,32669,0,9,3,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,20,-100,-210,0,1,9,0,1,10,0,0,32669,1,0,0,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,21,-100,-200,0,1,10,0,1,11,0,0,32669,1,0,1,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,22,-100,-190,0,1,11,0,1,12,0,0,32669,1,0,2,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,23,-100,-180,0,1,12,0,1,13,0,0,32669,1,0,3,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,12,-100,-170,0,1,13,0,1,14,0,0,32669,1,1,0,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,13,-100,-160,0,1,14,0,1,15,0,0,32669,1,1,1,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,44,-100,-150,0,1,15,0,1,16,0,0,32669,1,1,2,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,45,-100,-140,0,1,16,0,1,17,0,0,32669,1,1,3,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,46,-100,-130,0,1,17,0,1,18,0,0,32669,1,2,0,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,47,-100,-120,0,1,18,0,1,19,0,0,32669,1,2,1,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,36,-100,-110,0,1,19,0,1,20,0,0,32669,1,2,2,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,37,-100,-100,0,1,20,0,1,21,0,0,32669,1,2,3,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,38,-100,-90,0,1,21,0,1,22,0,0,32669,1,3,0,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,39,-100,-80,0,1,22,0,1,23,0,0,32669,1,3,1,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,40,-100,-70,0,1,23,0,1,24,0,0,32669,1,3,2,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,41,-100,-60,0,1,24,0,1,25,0,0,32669,1,3,3,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,30,-100,-50,0,1,25,0,1,26,0,0,32669,1,4,0,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,31,-100,-40,0,1,26,0,1,27,0,0,32669,1,4,1,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,32,-100,-30,0,1,27,0,1,28,0,0,32669,1,4,2,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,33,-100,-20,0,1,28,0,1,29,0,0,32669,1,4,3,ON +0,0,-0.927149,0.404,0,0,1,lappd_v1,ON,35,-100,-10,0,1,29,0,2,0,0,0,32669,1,5,0,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,60,100,-300,0,0,0,0,2,1,0,0,32669,1,5,1,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,61,100,-290,0,0,1,0,2,2,0,0,32669,1,5,2,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,62,100,-280,0,0,2,0,2,3,0,0,32669,1,5,3,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,63,100,-270,0,0,3,0,2,4,0,0,32669,1,6,0,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,64,100,-260,0,0,4,0,2,5,0,0,32669,1,6,1,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,65,100,-250,0,0,5,0,2,6,0,0,32669,1,6,2,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,66,100,-240,0,0,6,0,2,7,0,0,32669,1,6,3,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,67,100,-230,0,0,7,0,2,8,0,0,32669,1,7,0,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,68,100,-220,0,0,8,0,2,9,0,0,32669,1,7,1,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,69,100,-210,0,0,9,0,2,10,0,0,32669,1,7,2,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,70,100,-200,0,0,10,0,2,11,0,0,32669,1,7,3,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,71,100,-190,0,0,11,0,2,12,0,0,32669,1,8,0,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,72,100,-180,0,0,12,0,2,13,0,0,32669,1,8,1,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,73,100,-170,0,0,13,0,2,14,0,0,32669,1,8,2,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,74,100,-160,0,0,14,0,2,15,0,0,32669,1,8,3,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,75,100,-150,0,0,15,0,2,16,0,0,32669,1,9,0,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,76,100,-140,0,0,16,0,2,17,0,0,32669,1,9,1,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,77,100,-130,0,0,17,0,2,18,0,0,32669,1,9,2,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,78,100,-120,0,0,18,0,2,19,0,0,32669,1,9,3,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,79,100,-110,0,0,19,0,2,20,0,0,32669,2,0,0,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,80,100,-100,0,0,20,0,2,21,0,0,32669,2,0,1,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,81,100,-90,0,0,21,0,2,22,0,0,32669,2,0,2,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,82,100,-80,0,0,22,0,2,23,0,0,32669,2,0,3,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,83,100,-70,0,0,23,0,2,24,0,0,32669,2,1,0,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,84,100,-60,0,0,24,0,2,25,0,0,32669,2,1,1,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,85,100,-50,0,0,25,0,2,26,0,0,32669,2,1,2,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,86,100,-40,0,0,26,0,2,27,0,0,32669,2,1,3,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,87,100,-30,0,0,27,0,2,28,0,0,32669,2,2,0,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,88,100,-20,0,0,28,0,2,29,0,0,32669,2,2,1,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,89,100,-10,0,0,29,0,3,0,0,0,32669,2,2,2,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,90,-100,-300,0,1,0,0,3,1,0,0,32669,2,2,3,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,91,-100,-290,0,1,1,0,3,2,0,0,32669,2,3,0,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,92,-100,-280,0,1,2,0,3,3,0,0,32669,2,3,1,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,93,-100,-270,0,1,3,0,3,4,0,0,32669,2,3,2,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,94,-100,-260,0,1,4,0,3,5,0,0,32669,2,3,3,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,95,-100,-250,0,1,5,0,3,6,0,0,32669,2,4,0,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,96,-100,-240,0,1,6,0,3,7,0,0,32669,2,4,1,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,97,-100,-230,0,1,7,0,3,8,0,0,32669,2,4,2,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,98,-100,-220,0,1,8,0,3,9,0,0,32669,2,4,3,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,99,-100,-210,0,1,9,0,3,10,0,0,32669,2,5,0,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,100,-100,-200,0,1,10,0,3,11,0,0,32669,2,5,1,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,101,-100,-190,0,1,11,0,3,12,0,0,32669,2,5,2,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,102,-100,-180,0,1,12,0,3,13,0,0,32669,2,5,3,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,103,-100,-170,0,1,13,0,3,14,0,0,32669,2,6,0,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,104,-100,-160,0,1,14,0,3,15,0,0,32669,2,6,1,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,105,-100,-150,0,1,15,0,3,16,0,0,32669,2,6,2,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,106,-100,-140,0,1,16,0,3,17,0,0,32669,2,6,3,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,107,-100,-130,0,1,17,0,3,18,0,0,32669,2,7,0,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,108,-100,-120,0,1,18,0,3,19,0,0,32669,2,7,1,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,109,-100,-110,0,1,19,0,3,20,0,0,32669,2,7,2,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,110,-100,-100,0,1,20,0,3,21,0,0,32669,2,7,3,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,111,-100,-90,0,1,21,0,3,22,0,0,32669,2,8,0,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,112,-100,-80,0,1,22,0,3,23,0,0,32669,2,8,1,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,113,-100,-70,0,1,23,0,3,24,0,0,32669,2,8,2,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,114,-100,-60,0,1,24,0,3,25,0,0,32669,2,8,3,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,115,-100,-50,0,1,25,0,3,26,0,0,32669,2,9,0,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,116,-100,-40,0,1,26,0,3,27,0,0,32669,2,9,1,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,117,-100,-30,0,1,27,0,3,28,0,0,32669,2,9,2,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,118,-100,-20,0,1,28,0,3,29,0,0,32669,2,9,3,ON +1,0,-0.144649,0.404,0,0,1,lappd_v1,ON,119,-100,-10,0,1,29,0,4,0,0,0,32669,3,0,0,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,120,100,-300,0,0,0,0,4,1,0,0,32669,3,0,1,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,121,100,-290,0,0,1,0,4,2,0,0,32669,3,0,2,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,122,100,-280,0,0,2,0,4,3,0,0,32669,3,0,3,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,123,100,-270,0,0,3,0,4,4,0,0,32669,3,1,0,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,124,100,-260,0,0,4,0,4,5,0,0,32669,3,1,1,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,125,100,-250,0,0,5,0,4,6,0,0,32669,3,1,2,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,126,100,-240,0,0,6,0,4,7,0,0,32669,3,1,3,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,127,100,-230,0,0,7,0,4,8,0,0,32669,3,2,0,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,128,100,-220,0,0,8,0,4,9,0,0,32669,3,2,1,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,129,100,-210,0,0,9,0,4,10,0,0,32669,3,2,2,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,130,100,-200,0,0,10,0,4,11,0,0,32669,3,2,3,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,131,100,-190,0,0,11,0,4,12,0,0,32669,3,3,0,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,132,100,-180,0,0,12,0,4,13,0,0,32669,3,3,1,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,133,100,-170,0,0,13,0,4,14,0,0,32669,3,3,2,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,134,100,-160,0,0,14,0,4,15,0,0,32669,3,3,3,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,135,100,-150,0,0,15,0,4,16,0,0,32669,3,4,0,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,136,100,-140,0,0,16,0,4,17,0,0,32669,3,4,1,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,137,100,-130,0,0,17,0,4,18,0,0,32669,3,4,2,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,138,100,-120,0,0,18,0,4,19,0,0,32669,3,4,3,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,139,100,-110,0,0,19,0,4,20,0,0,32669,3,5,0,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,140,100,-100,0,0,20,0,4,21,0,0,32669,3,5,1,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,141,100,-90,0,0,21,0,4,22,0,0,32669,3,5,2,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,142,100,-80,0,0,22,0,4,23,0,0,32669,3,5,3,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,143,100,-70,0,0,23,0,4,24,0,0,32669,3,6,0,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,144,100,-60,0,0,24,0,4,25,0,0,32669,3,6,1,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,145,100,-50,0,0,25,0,4,26,0,0,32669,3,6,2,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,146,100,-40,0,0,26,0,4,27,0,0,32669,3,6,3,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,147,100,-30,0,0,27,0,4,28,0,0,32669,3,7,0,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,148,100,-20,0,0,28,0,4,29,0,0,32669,3,7,1,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,149,100,-10,0,0,29,0,5,0,0,0,32669,3,7,2,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,150,-100,-300,0,1,0,0,5,1,0,0,32669,3,7,3,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,151,-100,-290,0,1,1,0,5,2,0,0,32669,3,8,0,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,152,-100,-280,0,1,2,0,5,3,0,0,32669,3,8,1,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,153,-100,-270,0,1,3,0,5,4,0,0,32669,3,8,2,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,154,-100,-260,0,1,4,0,5,5,0,0,32669,3,8,3,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,155,-100,-250,0,1,5,0,5,6,0,0,32669,3,9,0,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,156,-100,-240,0,1,6,0,5,7,0,0,32669,3,9,1,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,157,-100,-230,0,1,7,0,5,8,0,0,32669,3,9,2,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,158,-100,-220,0,1,8,0,5,9,0,0,32669,3,9,3,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,159,-100,-210,0,1,9,0,5,10,0,0,32669,4,0,0,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,160,-100,-200,0,1,10,0,5,11,0,0,32669,4,0,1,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,161,-100,-190,0,1,11,0,5,12,0,0,32669,4,0,2,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,162,-100,-180,0,1,12,0,5,13,0,0,32669,4,0,3,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,163,-100,-170,0,1,13,0,5,14,0,0,32669,4,1,0,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,164,-100,-160,0,1,14,0,5,15,0,0,32669,4,1,1,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,165,-100,-150,0,1,15,0,5,16,0,0,32669,4,1,2,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,166,-100,-140,0,1,16,0,5,17,0,0,32669,4,1,3,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,167,-100,-130,0,1,17,0,5,18,0,0,32669,4,2,0,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,168,-100,-120,0,1,18,0,5,19,0,0,32669,4,2,1,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,169,-100,-110,0,1,19,0,5,20,0,0,32669,4,2,2,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,170,-100,-100,0,1,20,0,5,21,0,0,32669,4,2,3,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,171,-100,-90,0,1,21,0,5,22,0,0,32669,4,3,0,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,172,-100,-80,0,1,22,0,5,23,0,0,32669,4,3,1,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,173,-100,-70,0,1,23,0,5,24,0,0,32669,4,3,2,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,174,-100,-60,0,1,24,0,5,25,0,0,32669,4,3,3,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,175,-100,-50,0,1,25,0,5,26,0,0,32669,4,4,0,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,176,-100,-40,0,1,26,0,5,27,0,0,32669,4,4,1,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,177,-100,-30,0,1,27,0,5,28,0,0,32669,4,4,2,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,178,-100,-20,0,1,28,0,5,29,0,0,32669,4,4,3,ON +2,0,0.637851,0.404,0,0,1,lappd_v1,ON,179,-100,-10,0,1,29,0,6,0,0,0,32669,4,5,0,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,180,100,-300,0,0,0,0,6,1,0,0,32669,4,5,1,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,181,100,-290,0,0,1,0,6,2,0,0,32669,4,5,2,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,182,100,-280,0,0,2,0,6,3,0,0,32669,4,5,3,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,183,100,-270,0,0,3,0,6,4,0,0,32669,4,6,0,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,184,100,-260,0,0,4,0,6,5,0,0,32669,4,6,1,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,185,100,-250,0,0,5,0,6,6,0,0,32669,4,6,2,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,186,100,-240,0,0,6,0,6,7,0,0,32669,4,6,3,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,187,100,-230,0,0,7,0,6,8,0,0,32669,4,7,0,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,188,100,-220,0,0,8,0,6,9,0,0,32669,4,7,1,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,189,100,-210,0,0,9,0,6,10,0,0,32669,4,7,2,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,190,100,-200,0,0,10,0,6,11,0,0,32669,4,7,3,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,191,100,-190,0,0,11,0,6,12,0,0,32669,4,8,0,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,192,100,-180,0,0,12,0,6,13,0,0,32669,4,8,1,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,193,100,-170,0,0,13,0,6,14,0,0,32669,4,8,2,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,194,100,-160,0,0,14,0,6,15,0,0,32669,4,8,3,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,195,100,-150,0,0,15,0,6,16,0,0,32669,4,9,0,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,196,100,-140,0,0,16,0,6,17,0,0,32669,4,9,1,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,197,100,-130,0,0,17,0,6,18,0,0,32669,4,9,2,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,198,100,-120,0,0,18,0,6,19,0,0,32669,4,9,3,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,199,100,-110,0,0,19,0,6,20,0,0,32669,5,0,0,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,200,100,-100,0,0,20,0,6,21,0,0,32669,5,0,1,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,201,100,-90,0,0,21,0,6,22,0,0,32669,5,0,2,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,202,100,-80,0,0,22,0,6,23,0,0,32669,5,0,3,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,203,100,-70,0,0,23,0,6,24,0,0,32669,5,1,0,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,204,100,-60,0,0,24,0,6,25,0,0,32669,5,1,1,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,205,100,-50,0,0,25,0,6,26,0,0,32669,5,1,2,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,206,100,-40,0,0,26,0,6,27,0,0,32669,5,1,3,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,207,100,-30,0,0,27,0,6,28,0,0,32669,5,2,0,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,208,100,-20,0,0,28,0,6,29,0,0,32669,5,2,1,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,209,100,-10,0,0,29,0,7,0,0,0,32669,5,2,2,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,210,-100,-300,0,1,0,0,7,1,0,0,32669,5,2,3,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,211,-100,-290,0,1,1,0,7,2,0,0,32669,5,3,0,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,212,-100,-280,0,1,2,0,7,3,0,0,32669,5,3,1,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,213,-100,-270,0,1,3,0,7,4,0,0,32669,5,3,2,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,214,-100,-260,0,1,4,0,7,5,0,0,32669,5,3,3,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,215,-100,-250,0,1,5,0,7,6,0,0,32669,5,4,0,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,216,-100,-240,0,1,6,0,7,7,0,0,32669,5,4,1,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,217,-100,-230,0,1,7,0,7,8,0,0,32669,5,4,2,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,218,-100,-220,0,1,8,0,7,9,0,0,32669,5,4,3,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,219,-100,-210,0,1,9,0,7,10,0,0,32669,5,5,0,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,220,-100,-200,0,1,10,0,7,11,0,0,32669,5,5,1,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,221,-100,-190,0,1,11,0,7,12,0,0,32669,5,5,2,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,222,-100,-180,0,1,12,0,7,13,0,0,32669,5,5,3,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,223,-100,-170,0,1,13,0,7,14,0,0,32669,5,6,0,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,224,-100,-160,0,1,14,0,7,15,0,0,32669,5,6,1,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,225,-100,-150,0,1,15,0,7,16,0,0,32669,5,6,2,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,226,-100,-140,0,1,16,0,7,17,0,0,32669,5,6,3,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,227,-100,-130,0,1,17,0,7,18,0,0,32669,5,7,0,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,228,-100,-120,0,1,18,0,7,19,0,0,32669,5,7,1,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,229,-100,-110,0,1,19,0,7,20,0,0,32669,5,7,2,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,230,-100,-100,0,1,20,0,7,21,0,0,32669,5,7,3,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,231,-100,-90,0,1,21,0,7,22,0,0,32669,5,8,0,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,232,-100,-80,0,1,22,0,7,23,0,0,32669,5,8,1,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,233,-100,-70,0,1,23,0,7,24,0,0,32669,5,8,2,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,234,-100,-60,0,1,24,0,7,25,0,0,32669,5,8,3,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,235,-100,-50,0,1,25,0,7,26,0,0,32669,5,9,0,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,236,-100,-40,0,1,26,0,7,27,0,0,32669,5,9,1,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,237,-100,-30,0,1,27,0,7,28,0,0,32669,5,9,2,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,238,-100,-20,0,1,28,0,7,29,0,0,32669,5,9,3,ON +3,0.902975,-0.927149,0.778025,-0.707107,0,0.707107,lappd_v1,ON,239,-100,-10,0,1,29,0,8,0,0,1,32669,6,0,0,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,240,100,-300,0,0,0,0,8,1,0,1,32669,6,0,1,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,241,100,-290,0,0,1,0,8,2,0,1,32669,6,0,2,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,242,100,-280,0,0,2,0,8,3,0,1,32669,6,0,3,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,243,100,-270,0,0,3,0,8,4,0,1,32669,6,1,0,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,244,100,-260,0,0,4,0,8,5,0,1,32669,6,1,1,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,245,100,-250,0,0,5,0,8,6,0,1,32669,6,1,2,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,246,100,-240,0,0,6,0,8,7,0,1,32669,6,1,3,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,247,100,-230,0,0,7,0,8,8,0,1,32669,6,2,0,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,248,100,-220,0,0,8,0,8,9,0,1,32669,6,2,1,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,249,100,-210,0,0,9,0,8,10,0,1,32669,6,2,2,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,250,100,-200,0,0,10,0,8,11,0,1,32669,6,2,3,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,251,100,-190,0,0,11,0,8,12,0,1,32669,6,3,0,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,252,100,-180,0,0,12,0,8,13,0,1,32669,6,3,1,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,253,100,-170,0,0,13,0,8,14,0,1,32669,6,3,2,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,254,100,-160,0,0,14,0,8,15,0,1,32669,6,3,3,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,255,100,-150,0,0,15,0,8,16,0,1,32669,6,4,0,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,256,100,-140,0,0,16,0,8,17,0,1,32669,6,4,1,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,257,100,-130,0,0,17,0,8,18,0,1,32669,6,4,2,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,258,100,-120,0,0,18,0,8,19,0,1,32669,6,4,3,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,259,100,-110,0,0,19,0,8,20,0,1,32669,6,5,0,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,260,100,-100,0,0,20,0,8,21,0,1,32669,6,5,1,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,261,100,-90,0,0,21,0,8,22,0,1,32669,6,5,2,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,262,100,-80,0,0,22,0,8,23,0,1,32669,6,5,3,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,263,100,-70,0,0,23,0,8,24,0,1,32669,6,6,0,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,264,100,-60,0,0,24,0,8,25,0,1,32669,6,6,1,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,265,100,-50,0,0,25,0,8,26,0,1,32669,6,6,2,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,266,100,-40,0,0,26,0,8,27,0,1,32669,6,6,3,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,267,100,-30,0,0,27,0,8,28,0,1,32669,6,7,0,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,268,100,-20,0,0,28,0,8,29,0,1,32669,6,7,1,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,269,100,-10,0,0,29,0,9,0,0,1,32669,6,7,2,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,270,-100,-300,0,1,0,0,9,1,0,1,32669,6,7,3,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,271,-100,-290,0,1,1,0,9,2,0,1,32669,6,8,0,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,272,-100,-280,0,1,2,0,9,3,0,1,32669,6,8,1,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,273,-100,-270,0,1,3,0,9,4,0,1,32669,6,8,2,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,274,-100,-260,0,1,4,0,9,5,0,1,32669,6,8,3,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,275,-100,-250,0,1,5,0,9,6,0,1,32669,6,9,0,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,276,-100,-240,0,1,6,0,9,7,0,1,32669,6,9,1,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,277,-100,-230,0,1,7,0,9,8,0,1,32669,6,9,2,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,278,-100,-220,0,1,8,0,9,9,0,1,32669,6,9,3,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,279,-100,-210,0,1,9,0,9,10,0,1,32669,7,0,0,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,280,-100,-200,0,1,10,0,9,11,0,1,32669,7,0,1,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,281,-100,-190,0,1,11,0,9,12,0,1,32669,7,0,2,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,282,-100,-180,0,1,12,0,9,13,0,1,32669,7,0,3,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,283,-100,-170,0,1,13,0,9,14,0,1,32669,7,1,0,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,284,-100,-160,0,1,14,0,9,15,0,1,32669,7,1,1,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,285,-100,-150,0,1,15,0,9,16,0,1,32669,7,1,2,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,286,-100,-140,0,1,16,0,9,17,0,1,32669,7,1,3,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,287,-100,-130,0,1,17,0,9,18,0,1,32669,7,2,0,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,288,-100,-120,0,1,18,0,9,19,0,1,32669,7,2,1,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,289,-100,-110,0,1,19,0,9,20,0,1,32669,7,2,2,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,290,-100,-100,0,1,20,0,9,21,0,1,32669,7,2,3,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,291,-100,-90,0,1,21,0,9,22,0,1,32669,7,3,0,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,292,-100,-80,0,1,22,0,9,23,0,1,32669,7,3,1,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,293,-100,-70,0,1,23,0,9,24,0,1,32669,7,3,2,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,294,-100,-60,0,1,24,0,9,25,0,1,32669,7,3,3,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,295,-100,-50,0,1,25,0,9,26,0,1,32669,7,4,0,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,296,-100,-40,0,1,26,0,9,27,0,1,32669,7,4,1,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,297,-100,-30,0,1,27,0,9,28,0,1,32669,7,4,2,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,298,-100,-20,0,1,28,0,9,29,0,1,32669,7,4,3,ON +4,0.902975,-0.144649,0.778025,-0.707107,0,0.707107,lappd_v1,ON,299,-100,-10,0,1,29,0,10,0,0,1,32669,7,5,0,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,300,100,-300,0,0,0,0,10,1,0,1,32669,7,5,1,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,301,100,-290,0,0,1,0,10,2,0,1,32669,7,5,2,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,302,100,-280,0,0,2,0,10,3,0,1,32669,7,5,3,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,303,100,-270,0,0,3,0,10,4,0,1,32669,7,6,0,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,304,100,-260,0,0,4,0,10,5,0,1,32669,7,6,1,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,305,100,-250,0,0,5,0,10,6,0,1,32669,7,6,2,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,306,100,-240,0,0,6,0,10,7,0,1,32669,7,6,3,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,307,100,-230,0,0,7,0,10,8,0,1,32669,7,7,0,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,308,100,-220,0,0,8,0,10,9,0,1,32669,7,7,1,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,309,100,-210,0,0,9,0,10,10,0,1,32669,7,7,2,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,310,100,-200,0,0,10,0,10,11,0,1,32669,7,7,3,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,311,100,-190,0,0,11,0,10,12,0,1,32669,7,8,0,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,312,100,-180,0,0,12,0,10,13,0,1,32669,7,8,1,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,313,100,-170,0,0,13,0,10,14,0,1,32669,7,8,2,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,314,100,-160,0,0,14,0,10,15,0,1,32669,7,8,3,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,315,100,-150,0,0,15,0,10,16,0,1,32669,7,9,0,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,316,100,-140,0,0,16,0,10,17,0,1,32669,7,9,1,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,317,100,-130,0,0,17,0,10,18,0,1,32669,7,9,2,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,318,100,-120,0,0,18,0,10,19,0,1,32669,7,9,3,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,319,100,-110,0,0,19,0,10,20,0,1,32669,8,0,0,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,320,100,-100,0,0,20,0,10,21,0,1,32669,8,0,1,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,321,100,-90,0,0,21,0,10,22,0,1,32669,8,0,2,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,322,100,-80,0,0,22,0,10,23,0,1,32669,8,0,3,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,323,100,-70,0,0,23,0,10,24,0,1,32669,8,1,0,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,324,100,-60,0,0,24,0,10,25,0,1,32669,8,1,1,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,325,100,-50,0,0,25,0,10,26,0,1,32669,8,1,2,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,326,100,-40,0,0,26,0,10,27,0,1,32669,8,1,3,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,327,100,-30,0,0,27,0,10,28,0,1,32669,8,2,0,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,328,100,-20,0,0,28,0,10,29,0,1,32669,8,2,1,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,329,100,-10,0,0,29,0,11,0,0,1,32669,8,2,2,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,330,-100,-300,0,1,0,0,11,1,0,1,32669,8,2,3,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,331,-100,-290,0,1,1,0,11,2,0,1,32669,8,3,0,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,332,-100,-280,0,1,2,0,11,3,0,1,32669,8,3,1,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,333,-100,-270,0,1,3,0,11,4,0,1,32669,8,3,2,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,334,-100,-260,0,1,4,0,11,5,0,1,32669,8,3,3,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,335,-100,-250,0,1,5,0,11,6,0,1,32669,8,4,0,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,336,-100,-240,0,1,6,0,11,7,0,1,32669,8,4,1,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,337,-100,-230,0,1,7,0,11,8,0,1,32669,8,4,2,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,338,-100,-220,0,1,8,0,11,9,0,1,32669,8,4,3,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,339,-100,-210,0,1,9,0,11,10,0,1,32669,8,5,0,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,340,-100,-200,0,1,10,0,11,11,0,1,32669,8,5,1,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,341,-100,-190,0,1,11,0,11,12,0,1,32669,8,5,2,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,342,-100,-180,0,1,12,0,11,13,0,1,32669,8,5,3,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,343,-100,-170,0,1,13,0,11,14,0,1,32669,8,6,0,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,344,-100,-160,0,1,14,0,11,15,0,1,32669,8,6,1,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,345,-100,-150,0,1,15,0,11,16,0,1,32669,8,6,2,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,346,-100,-140,0,1,16,0,11,17,0,1,32669,8,6,3,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,347,-100,-130,0,1,17,0,11,18,0,1,32669,8,7,0,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,348,-100,-120,0,1,18,0,11,19,0,1,32669,8,7,1,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,349,-100,-110,0,1,19,0,11,20,0,1,32669,8,7,2,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,350,-100,-100,0,1,20,0,11,21,0,1,32669,8,7,3,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,351,-100,-90,0,1,21,0,11,22,0,1,32669,8,8,0,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,352,-100,-80,0,1,22,0,11,23,0,1,32669,8,8,1,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,353,-100,-70,0,1,23,0,11,24,0,1,32669,8,8,2,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,354,-100,-60,0,1,24,0,11,25,0,1,32669,8,8,3,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,355,-100,-50,0,1,25,0,11,26,0,1,32669,8,9,0,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,356,-100,-40,0,1,26,0,11,27,0,1,32669,8,9,1,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,357,-100,-30,0,1,27,0,11,28,0,1,32669,8,9,2,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,358,-100,-20,0,1,28,0,11,29,0,1,32669,8,9,3,ON +5,0.902975,0.637851,0.778025,-0.707107,0,0.707107,lappd_v1,ON,359,-100,-10,0,1,29,0,12,0,0,1,32669,9,0,0,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,360,100,-300,0,0,0,0,12,1,0,1,32669,9,0,1,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,361,100,-290,0,0,1,0,12,2,0,1,32669,9,0,2,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,362,100,-280,0,0,2,0,12,3,0,1,32669,9,0,3,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,363,100,-270,0,0,3,0,12,4,0,1,32669,9,1,0,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,364,100,-260,0,0,4,0,12,5,0,1,32669,9,1,1,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,365,100,-250,0,0,5,0,12,6,0,1,32669,9,1,2,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,366,100,-240,0,0,6,0,12,7,0,1,32669,9,1,3,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,367,100,-230,0,0,7,0,12,8,0,1,32669,9,2,0,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,368,100,-220,0,0,8,0,12,9,0,1,32669,9,2,1,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,369,100,-210,0,0,9,0,12,10,0,1,32669,9,2,2,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,370,100,-200,0,0,10,0,12,11,0,1,32669,9,2,3,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,371,100,-190,0,0,11,0,12,12,0,1,32669,9,3,0,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,372,100,-180,0,0,12,0,12,13,0,1,32669,9,3,1,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,373,100,-170,0,0,13,0,12,14,0,1,32669,9,3,2,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,374,100,-160,0,0,14,0,12,15,0,1,32669,9,3,3,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,375,100,-150,0,0,15,0,12,16,0,1,32669,9,4,0,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,376,100,-140,0,0,16,0,12,17,0,1,32669,9,4,1,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,377,100,-130,0,0,17,0,12,18,0,1,32669,9,4,2,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,378,100,-120,0,0,18,0,12,19,0,1,32669,9,4,3,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,379,100,-110,0,0,19,0,12,20,0,1,32669,9,5,0,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,380,100,-100,0,0,20,0,12,21,0,1,32669,9,5,1,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,381,100,-90,0,0,21,0,12,22,0,1,32669,9,5,2,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,382,100,-80,0,0,22,0,12,23,0,1,32669,9,5,3,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,383,100,-70,0,0,23,0,12,24,0,1,32669,9,6,0,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,384,100,-60,0,0,24,0,12,25,0,1,32669,9,6,1,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,385,100,-50,0,0,25,0,12,26,0,1,32669,9,6,2,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,386,100,-40,0,0,26,0,12,27,0,1,32669,9,6,3,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,387,100,-30,0,0,27,0,12,28,0,1,32669,9,7,0,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,388,100,-20,0,0,28,0,12,29,0,1,32669,9,7,1,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,389,100,-10,0,0,29,0,13,0,0,1,32669,9,7,2,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,390,-100,-300,0,1,0,0,13,1,0,1,32669,9,7,3,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,391,-100,-290,0,1,1,0,13,2,0,1,32669,9,8,0,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,392,-100,-280,0,1,2,0,13,3,0,1,32669,9,8,1,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,393,-100,-270,0,1,3,0,13,4,0,1,32669,9,8,2,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,394,-100,-260,0,1,4,0,13,5,0,1,32669,9,8,3,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,395,-100,-250,0,1,5,0,13,6,0,1,32669,9,9,0,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,396,-100,-240,0,1,6,0,13,7,0,1,32669,9,9,1,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,397,-100,-230,0,1,7,0,13,8,0,1,32669,9,9,2,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,398,-100,-220,0,1,8,0,13,9,0,1,32669,9,9,3,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,399,-100,-210,0,1,9,0,13,10,0,1,32669,10,0,0,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,400,-100,-200,0,1,10,0,13,11,0,1,32669,10,0,1,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,401,-100,-190,0,1,11,0,13,12,0,1,32669,10,0,2,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,402,-100,-180,0,1,12,0,13,13,0,1,32669,10,0,3,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,403,-100,-170,0,1,13,0,13,14,0,1,32669,10,1,0,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,404,-100,-160,0,1,14,0,13,15,0,1,32669,10,1,1,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,405,-100,-150,0,1,15,0,13,16,0,1,32669,10,1,2,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,406,-100,-140,0,1,16,0,13,17,0,1,32669,10,1,3,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,407,-100,-130,0,1,17,0,13,18,0,1,32669,10,2,0,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,408,-100,-120,0,1,18,0,13,19,0,1,32669,10,2,1,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,409,-100,-110,0,1,19,0,13,20,0,1,32669,10,2,2,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,410,-100,-100,0,1,20,0,13,21,0,1,32669,10,2,3,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,411,-100,-90,0,1,21,0,13,22,0,1,32669,10,3,0,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,412,-100,-80,0,1,22,0,13,23,0,1,32669,10,3,1,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,413,-100,-70,0,1,23,0,13,24,0,1,32669,10,3,2,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,414,-100,-60,0,1,24,0,13,25,0,1,32669,10,3,3,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,415,-100,-50,0,1,25,0,13,26,0,1,32669,10,4,0,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,416,-100,-40,0,1,26,0,13,27,0,1,32669,10,4,1,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,417,-100,-30,0,1,27,0,13,28,0,1,32669,10,4,2,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,418,-100,-20,0,1,28,0,13,29,0,1,32669,10,4,3,ON +6,1.277,-0.927149,1.681,-1,0,0,lappd_v1,ON,419,-100,-10,0,1,29,0,14,0,0,1,32669,10,5,0,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,420,100,-300,0,0,0,0,14,1,0,1,32669,10,5,1,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,421,100,-290,0,0,1,0,14,2,0,1,32669,10,5,2,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,422,100,-280,0,0,2,0,14,3,0,1,32669,10,5,3,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,423,100,-270,0,0,3,0,14,4,0,1,32669,10,6,0,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,424,100,-260,0,0,4,0,14,5,0,1,32669,10,6,1,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,425,100,-250,0,0,5,0,14,6,0,1,32669,10,6,2,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,426,100,-240,0,0,6,0,14,7,0,1,32669,10,6,3,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,427,100,-230,0,0,7,0,14,8,0,1,32669,10,7,0,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,428,100,-220,0,0,8,0,14,9,0,1,32669,10,7,1,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,429,100,-210,0,0,9,0,14,10,0,1,32669,10,7,2,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,430,100,-200,0,0,10,0,14,11,0,1,32669,10,7,3,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,431,100,-190,0,0,11,0,14,12,0,1,32669,10,8,0,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,432,100,-180,0,0,12,0,14,13,0,1,32669,10,8,1,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,433,100,-170,0,0,13,0,14,14,0,1,32669,10,8,2,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,434,100,-160,0,0,14,0,14,15,0,1,32669,10,8,3,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,435,100,-150,0,0,15,0,14,16,0,1,32669,10,9,0,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,436,100,-140,0,0,16,0,14,17,0,1,32669,10,9,1,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,437,100,-130,0,0,17,0,14,18,0,1,32669,10,9,2,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,438,100,-120,0,0,18,0,14,19,0,1,32669,10,9,3,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,439,100,-110,0,0,19,0,14,20,0,1,32669,11,0,0,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,440,100,-100,0,0,20,0,14,21,0,1,32669,11,0,1,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,441,100,-90,0,0,21,0,14,22,0,1,32669,11,0,2,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,442,100,-80,0,0,22,0,14,23,0,1,32669,11,0,3,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,443,100,-70,0,0,23,0,14,24,0,1,32669,11,1,0,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,444,100,-60,0,0,24,0,14,25,0,1,32669,11,1,1,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,445,100,-50,0,0,25,0,14,26,0,1,32669,11,1,2,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,446,100,-40,0,0,26,0,14,27,0,1,32669,11,1,3,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,447,100,-30,0,0,27,0,14,28,0,1,32669,11,2,0,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,448,100,-20,0,0,28,0,14,29,0,1,32669,11,2,1,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,449,100,-10,0,0,29,0,15,0,0,1,32669,11,2,2,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,450,-100,-300,0,1,0,0,15,1,0,1,32669,11,2,3,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,451,-100,-290,0,1,1,0,15,2,0,1,32669,11,3,0,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,452,-100,-280,0,1,2,0,15,3,0,1,32669,11,3,1,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,453,-100,-270,0,1,3,0,15,4,0,1,32669,11,3,2,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,454,-100,-260,0,1,4,0,15,5,0,1,32669,11,3,3,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,455,-100,-250,0,1,5,0,15,6,0,1,32669,11,4,0,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,456,-100,-240,0,1,6,0,15,7,0,1,32669,11,4,1,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,457,-100,-230,0,1,7,0,15,8,0,1,32669,11,4,2,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,458,-100,-220,0,1,8,0,15,9,0,1,32669,11,4,3,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,459,-100,-210,0,1,9,0,15,10,0,1,32669,11,5,0,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,460,-100,-200,0,1,10,0,15,11,0,1,32669,11,5,1,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,461,-100,-190,0,1,11,0,15,12,0,1,32669,11,5,2,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,462,-100,-180,0,1,12,0,15,13,0,1,32669,11,5,3,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,463,-100,-170,0,1,13,0,15,14,0,1,32669,11,6,0,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,464,-100,-160,0,1,14,0,15,15,0,1,32669,11,6,1,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,465,-100,-150,0,1,15,0,15,16,0,1,32669,11,6,2,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,466,-100,-140,0,1,16,0,15,17,0,1,32669,11,6,3,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,467,-100,-130,0,1,17,0,15,18,0,1,32669,11,7,0,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,468,-100,-120,0,1,18,0,15,19,0,1,32669,11,7,1,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,469,-100,-110,0,1,19,0,15,20,0,1,32669,11,7,2,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,470,-100,-100,0,1,20,0,15,21,0,1,32669,11,7,3,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,471,-100,-90,0,1,21,0,15,22,0,1,32669,11,8,0,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,472,-100,-80,0,1,22,0,15,23,0,1,32669,11,8,1,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,473,-100,-70,0,1,23,0,15,24,0,1,32669,11,8,2,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,474,-100,-60,0,1,24,0,15,25,0,1,32669,11,8,3,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,475,-100,-50,0,1,25,0,15,26,0,1,32669,11,9,0,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,476,-100,-40,0,1,26,0,15,27,0,1,32669,11,9,1,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,477,-100,-30,0,1,27,0,15,28,0,1,32669,11,9,2,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,478,-100,-20,0,1,28,0,15,29,0,1,32669,11,9,3,ON +7,1.277,-0.144649,1.681,-1,0,0,lappd_v1,ON,479,-100,-10,0,1,29,0,16,0,0,2,32669,12,0,0,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,480,100,-300,0,0,0,0,16,1,0,2,32669,12,0,1,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,481,100,-290,0,0,1,0,16,2,0,2,32669,12,0,2,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,482,100,-280,0,0,2,0,16,3,0,2,32669,12,0,3,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,483,100,-270,0,0,3,0,16,4,0,2,32669,12,1,0,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,484,100,-260,0,0,4,0,16,5,0,2,32669,12,1,1,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,485,100,-250,0,0,5,0,16,6,0,2,32669,12,1,2,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,486,100,-240,0,0,6,0,16,7,0,2,32669,12,1,3,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,487,100,-230,0,0,7,0,16,8,0,2,32669,12,2,0,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,488,100,-220,0,0,8,0,16,9,0,2,32669,12,2,1,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,489,100,-210,0,0,9,0,16,10,0,2,32669,12,2,2,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,490,100,-200,0,0,10,0,16,11,0,2,32669,12,2,3,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,491,100,-190,0,0,11,0,16,12,0,2,32669,12,3,0,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,492,100,-180,0,0,12,0,16,13,0,2,32669,12,3,1,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,493,100,-170,0,0,13,0,16,14,0,2,32669,12,3,2,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,494,100,-160,0,0,14,0,16,15,0,2,32669,12,3,3,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,495,100,-150,0,0,15,0,16,16,0,2,32669,12,4,0,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,496,100,-140,0,0,16,0,16,17,0,2,32669,12,4,1,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,497,100,-130,0,0,17,0,16,18,0,2,32669,12,4,2,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,498,100,-120,0,0,18,0,16,19,0,2,32669,12,4,3,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,499,100,-110,0,0,19,0,16,20,0,2,32669,12,5,0,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,500,100,-100,0,0,20,0,16,21,0,2,32669,12,5,1,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,501,100,-90,0,0,21,0,16,22,0,2,32669,12,5,2,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,502,100,-80,0,0,22,0,16,23,0,2,32669,12,5,3,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,503,100,-70,0,0,23,0,16,24,0,2,32669,12,6,0,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,504,100,-60,0,0,24,0,16,25,0,2,32669,12,6,1,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,505,100,-50,0,0,25,0,16,26,0,2,32669,12,6,2,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,506,100,-40,0,0,26,0,16,27,0,2,32669,12,6,3,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,507,100,-30,0,0,27,0,16,28,0,2,32669,12,7,0,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,508,100,-20,0,0,28,0,16,29,0,2,32669,12,7,1,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,509,100,-10,0,0,29,0,17,0,0,2,32669,12,7,2,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,510,-100,-300,0,1,0,0,17,1,0,2,32669,12,7,3,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,511,-100,-290,0,1,1,0,17,2,0,2,32669,12,8,0,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,512,-100,-280,0,1,2,0,17,3,0,2,32669,12,8,1,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,513,-100,-270,0,1,3,0,17,4,0,2,32669,12,8,2,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,514,-100,-260,0,1,4,0,17,5,0,2,32669,12,8,3,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,515,-100,-250,0,1,5,0,17,6,0,2,32669,12,9,0,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,516,-100,-240,0,1,6,0,17,7,0,2,32669,12,9,1,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,517,-100,-230,0,1,7,0,17,8,0,2,32669,12,9,2,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,518,-100,-220,0,1,8,0,17,9,0,2,32669,12,9,3,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,519,-100,-210,0,1,9,0,17,10,0,2,32669,13,0,0,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,520,-100,-200,0,1,10,0,17,11,0,2,32669,13,0,1,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,521,-100,-190,0,1,11,0,17,12,0,2,32669,13,0,2,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,522,-100,-180,0,1,12,0,17,13,0,2,32669,13,0,3,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,523,-100,-170,0,1,13,0,17,14,0,2,32669,13,1,0,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,524,-100,-160,0,1,14,0,17,15,0,2,32669,13,1,1,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,525,-100,-150,0,1,15,0,17,16,0,2,32669,13,1,2,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,526,-100,-140,0,1,16,0,17,17,0,2,32669,13,1,3,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,527,-100,-130,0,1,17,0,17,18,0,2,32669,13,2,0,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,528,-100,-120,0,1,18,0,17,19,0,2,32669,13,2,1,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,529,-100,-110,0,1,19,0,17,20,0,2,32669,13,2,2,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,530,-100,-100,0,1,20,0,17,21,0,2,32669,13,2,3,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,531,-100,-90,0,1,21,0,17,22,0,2,32669,13,3,0,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,532,-100,-80,0,1,22,0,17,23,0,2,32669,13,3,1,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,533,-100,-70,0,1,23,0,17,24,0,2,32669,13,3,2,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,534,-100,-60,0,1,24,0,17,25,0,2,32669,13,3,3,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,535,-100,-50,0,1,25,0,17,26,0,2,32669,13,4,0,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,536,-100,-40,0,1,26,0,17,27,0,2,32669,13,4,1,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,537,-100,-30,0,1,27,0,17,28,0,2,32669,13,4,2,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,538,-100,-20,0,1,28,0,17,29,0,2,32669,13,4,3,ON +8,1.277,0.637851,1.681,-1,0,0,lappd_v1,ON,539,-100,-10,0,1,29,0,18,0,0,2,32669,13,5,0,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,540,100,-300,0,0,0,0,18,1,0,2,32669,13,5,1,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,541,100,-290,0,0,1,0,18,2,0,2,32669,13,5,2,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,542,100,-280,0,0,2,0,18,3,0,2,32669,13,5,3,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,543,100,-270,0,0,3,0,18,4,0,2,32669,13,6,0,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,544,100,-260,0,0,4,0,18,5,0,2,32669,13,6,1,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,545,100,-250,0,0,5,0,18,6,0,2,32669,13,6,2,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,546,100,-240,0,0,6,0,18,7,0,2,32669,13,6,3,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,547,100,-230,0,0,7,0,18,8,0,2,32669,13,7,0,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,548,100,-220,0,0,8,0,18,9,0,2,32669,13,7,1,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,549,100,-210,0,0,9,0,18,10,0,2,32669,13,7,2,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,550,100,-200,0,0,10,0,18,11,0,2,32669,13,7,3,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,551,100,-190,0,0,11,0,18,12,0,2,32669,13,8,0,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,552,100,-180,0,0,12,0,18,13,0,2,32669,13,8,1,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,553,100,-170,0,0,13,0,18,14,0,2,32669,13,8,2,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,554,100,-160,0,0,14,0,18,15,0,2,32669,13,8,3,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,555,100,-150,0,0,15,0,18,16,0,2,32669,13,9,0,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,556,100,-140,0,0,16,0,18,17,0,2,32669,13,9,1,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,557,100,-130,0,0,17,0,18,18,0,2,32669,13,9,2,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,558,100,-120,0,0,18,0,18,19,0,2,32669,13,9,3,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,559,100,-110,0,0,19,0,18,20,0,2,32669,14,0,0,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,560,100,-100,0,0,20,0,18,21,0,2,32669,14,0,1,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,561,100,-90,0,0,21,0,18,22,0,2,32669,14,0,2,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,562,100,-80,0,0,22,0,18,23,0,2,32669,14,0,3,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,563,100,-70,0,0,23,0,18,24,0,2,32669,14,1,0,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,564,100,-60,0,0,24,0,18,25,0,2,32669,14,1,1,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,565,100,-50,0,0,25,0,18,26,0,2,32669,14,1,2,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,566,100,-40,0,0,26,0,18,27,0,2,32669,14,1,3,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,567,100,-30,0,0,27,0,18,28,0,2,32669,14,2,0,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,568,100,-20,0,0,28,0,18,29,0,2,32669,14,2,1,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,569,100,-10,0,0,29,0,19,0,0,2,32669,14,2,2,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,570,-100,-300,0,1,0,0,19,1,0,2,32669,14,2,3,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,571,-100,-290,0,1,1,0,19,2,0,2,32669,14,3,0,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,572,-100,-280,0,1,2,0,19,3,0,2,32669,14,3,1,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,573,-100,-270,0,1,3,0,19,4,0,2,32669,14,3,2,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,574,-100,-260,0,1,4,0,19,5,0,2,32669,14,3,3,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,575,-100,-250,0,1,5,0,19,6,0,2,32669,14,4,0,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,576,-100,-240,0,1,6,0,19,7,0,2,32669,14,4,1,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,577,-100,-230,0,1,7,0,19,8,0,2,32669,14,4,2,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,578,-100,-220,0,1,8,0,19,9,0,2,32669,14,4,3,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,579,-100,-210,0,1,9,0,19,10,0,2,32669,14,5,0,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,580,-100,-200,0,1,10,0,19,11,0,2,32669,14,5,1,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,581,-100,-190,0,1,11,0,19,12,0,2,32669,14,5,2,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,582,-100,-180,0,1,12,0,19,13,0,2,32669,14,5,3,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,583,-100,-170,0,1,13,0,19,14,0,2,32669,14,6,0,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,584,-100,-160,0,1,14,0,19,15,0,2,32669,14,6,1,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,585,-100,-150,0,1,15,0,19,16,0,2,32669,14,6,2,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,586,-100,-140,0,1,16,0,19,17,0,2,32669,14,6,3,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,587,-100,-130,0,1,17,0,19,18,0,2,32669,14,7,0,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,588,-100,-120,0,1,18,0,19,19,0,2,32669,14,7,1,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,589,-100,-110,0,1,19,0,19,20,0,2,32669,14,7,2,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,590,-100,-100,0,1,20,0,19,21,0,2,32669,14,7,3,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,591,-100,-90,0,1,21,0,19,22,0,2,32669,14,8,0,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,592,-100,-80,0,1,22,0,19,23,0,2,32669,14,8,1,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,593,-100,-70,0,1,23,0,19,24,0,2,32669,14,8,2,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,594,-100,-60,0,1,24,0,19,25,0,2,32669,14,8,3,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,595,-100,-50,0,1,25,0,19,26,0,2,32669,14,9,0,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,596,-100,-40,0,1,26,0,19,27,0,2,32669,14,9,1,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,597,-100,-30,0,1,27,0,19,28,0,2,32669,14,9,2,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,598,-100,-20,0,1,28,0,19,29,0,2,32669,14,9,3,ON +9,0.902975,-0.927149,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,599,-100,-10,0,1,29,1,0,0,0,2,32669,15,0,0,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,600,100,-300,0,0,0,1,0,1,0,2,32669,15,0,1,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,601,100,-290,0,0,1,1,0,2,0,2,32669,15,0,2,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,602,100,-280,0,0,2,1,0,3,0,2,32669,15,0,3,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,603,100,-270,0,0,3,1,0,4,0,2,32669,15,1,0,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,604,100,-260,0,0,4,1,0,5,0,2,32669,15,1,1,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,605,100,-250,0,0,5,1,0,6,0,2,32669,15,1,2,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,606,100,-240,0,0,6,1,0,7,0,2,32669,15,1,3,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,607,100,-230,0,0,7,1,0,8,0,2,32669,15,2,0,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,608,100,-220,0,0,8,1,0,9,0,2,32669,15,2,1,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,609,100,-210,0,0,9,1,0,10,0,2,32669,15,2,2,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,610,100,-200,0,0,10,1,0,11,0,2,32669,15,2,3,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,611,100,-190,0,0,11,1,0,12,0,2,32669,15,3,0,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,612,100,-180,0,0,12,1,0,13,0,2,32669,15,3,1,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,613,100,-170,0,0,13,1,0,14,0,2,32669,15,3,2,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,614,100,-160,0,0,14,1,0,15,0,2,32669,15,3,3,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,615,100,-150,0,0,15,1,0,16,0,2,32669,15,4,0,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,616,100,-140,0,0,16,1,0,17,0,2,32669,15,4,1,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,617,100,-130,0,0,17,1,0,18,0,2,32669,15,4,2,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,618,100,-120,0,0,18,1,0,19,0,2,32669,15,4,3,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,619,100,-110,0,0,19,1,0,20,0,2,32669,15,5,0,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,620,100,-100,0,0,20,1,0,21,0,2,32669,15,5,1,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,621,100,-90,0,0,21,1,0,22,0,2,32669,15,5,2,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,622,100,-80,0,0,22,1,0,23,0,2,32669,15,5,3,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,623,100,-70,0,0,23,1,0,24,0,2,32669,15,6,0,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,624,100,-60,0,0,24,1,0,25,0,2,32669,15,6,1,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,625,100,-50,0,0,25,1,0,26,0,2,32669,15,6,2,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,626,100,-40,0,0,26,1,0,27,0,2,32669,15,6,3,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,627,100,-30,0,0,27,1,0,28,0,2,32669,15,7,0,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,628,100,-20,0,0,28,1,0,29,0,2,32669,15,7,1,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,629,100,-10,0,0,29,1,1,0,0,2,32669,15,7,2,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,630,-100,-300,0,1,0,1,1,1,0,2,32669,15,7,3,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,631,-100,-290,0,1,1,1,1,2,0,2,32669,15,8,0,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,632,-100,-280,0,1,2,1,1,3,0,2,32669,15,8,1,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,633,-100,-270,0,1,3,1,1,4,0,2,32669,15,8,2,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,634,-100,-260,0,1,4,1,1,5,0,2,32669,15,8,3,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,635,-100,-250,0,1,5,1,1,6,0,2,32669,15,9,0,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,636,-100,-240,0,1,6,1,1,7,0,2,32669,15,9,1,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,637,-100,-230,0,1,7,1,1,8,0,2,32669,15,9,2,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,638,-100,-220,0,1,8,1,1,9,0,2,32669,15,9,3,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,639,-100,-210,0,1,9,1,1,10,0,2,32669,16,0,0,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,640,-100,-200,0,1,10,1,1,11,0,2,32669,16,0,1,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,641,-100,-190,0,1,11,1,1,12,0,2,32669,16,0,2,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,642,-100,-180,0,1,12,1,1,13,0,2,32669,16,0,3,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,643,-100,-170,0,1,13,1,1,14,0,2,32669,16,1,0,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,644,-100,-160,0,1,14,1,1,15,0,2,32669,16,1,1,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,645,-100,-150,0,1,15,1,1,16,0,2,32669,16,1,2,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,646,-100,-140,0,1,16,1,1,17,0,2,32669,16,1,3,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,647,-100,-130,0,1,17,1,1,18,0,2,32669,16,2,0,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,648,-100,-120,0,1,18,1,1,19,0,2,32669,16,2,1,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,649,-100,-110,0,1,19,1,1,20,0,2,32669,16,2,2,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,650,-100,-100,0,1,20,1,1,21,0,2,32669,16,2,3,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,651,-100,-90,0,1,21,1,1,22,0,2,32669,16,3,0,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,652,-100,-80,0,1,22,1,1,23,0,2,32669,16,3,1,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,653,-100,-70,0,1,23,1,1,24,0,2,32669,16,3,2,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,654,-100,-60,0,1,24,1,1,25,0,2,32669,16,3,3,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,655,-100,-50,0,1,25,1,1,26,0,2,32669,16,4,0,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,656,-100,-40,0,1,26,1,1,27,0,2,32669,16,4,1,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,657,-100,-30,0,1,27,1,1,28,0,2,32669,16,4,2,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,658,-100,-20,0,1,28,1,1,29,0,2,32669,16,4,3,ON +10,0.902975,-0.144649,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,659,-100,-10,0,1,29,1,2,0,0,2,32669,16,5,0,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,660,100,-300,0,0,0,1,2,1,0,2,32669,16,5,1,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,661,100,-290,0,0,1,1,2,2,0,2,32669,16,5,2,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,662,100,-280,0,0,2,1,2,3,0,2,32669,16,5,3,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,663,100,-270,0,0,3,1,2,4,0,2,32669,16,6,0,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,664,100,-260,0,0,4,1,2,5,0,2,32669,16,6,1,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,665,100,-250,0,0,5,1,2,6,0,2,32669,16,6,2,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,666,100,-240,0,0,6,1,2,7,0,2,32669,16,6,3,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,667,100,-230,0,0,7,1,2,8,0,2,32669,16,7,0,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,668,100,-220,0,0,8,1,2,9,0,2,32669,16,7,1,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,669,100,-210,0,0,9,1,2,10,0,2,32669,16,7,2,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,670,100,-200,0,0,10,1,2,11,0,2,32669,16,7,3,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,671,100,-190,0,0,11,1,2,12,0,2,32669,16,8,0,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,672,100,-180,0,0,12,1,2,13,0,2,32669,16,8,1,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,673,100,-170,0,0,13,1,2,14,0,2,32669,16,8,2,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,674,100,-160,0,0,14,1,2,15,0,2,32669,16,8,3,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,675,100,-150,0,0,15,1,2,16,0,2,32669,16,9,0,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,676,100,-140,0,0,16,1,2,17,0,2,32669,16,9,1,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,677,100,-130,0,0,17,1,2,18,0,2,32669,16,9,2,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,678,100,-120,0,0,18,1,2,19,0,2,32669,16,9,3,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,679,100,-110,0,0,19,1,2,20,0,2,32669,17,0,0,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,680,100,-100,0,0,20,1,2,21,0,2,32669,17,0,1,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,681,100,-90,0,0,21,1,2,22,0,2,32669,17,0,2,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,682,100,-80,0,0,22,1,2,23,0,2,32669,17,0,3,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,683,100,-70,0,0,23,1,2,24,0,2,32669,17,1,0,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,684,100,-60,0,0,24,1,2,25,0,2,32669,17,1,1,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,685,100,-50,0,0,25,1,2,26,0,2,32669,17,1,2,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,686,100,-40,0,0,26,1,2,27,0,2,32669,17,1,3,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,687,100,-30,0,0,27,1,2,28,0,2,32669,17,2,0,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,688,100,-20,0,0,28,1,2,29,0,2,32669,17,2,1,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,689,100,-10,0,0,29,1,3,0,0,2,32669,17,2,2,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,690,-100,-300,0,1,0,1,3,1,0,2,32669,17,2,3,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,691,-100,-290,0,1,1,1,3,2,0,2,32669,17,3,0,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,692,-100,-280,0,1,2,1,3,3,0,2,32669,17,3,1,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,693,-100,-270,0,1,3,1,3,4,0,2,32669,17,3,2,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,694,-100,-260,0,1,4,1,3,5,0,2,32669,17,3,3,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,695,-100,-250,0,1,5,1,3,6,0,2,32669,17,4,0,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,696,-100,-240,0,1,6,1,3,7,0,2,32669,17,4,1,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,697,-100,-230,0,1,7,1,3,8,0,2,32669,17,4,2,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,698,-100,-220,0,1,8,1,3,9,0,2,32669,17,4,3,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,699,-100,-210,0,1,9,1,3,10,0,2,32669,17,5,0,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,700,-100,-200,0,1,10,1,3,11,0,2,32669,17,5,1,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,701,-100,-190,0,1,11,1,3,12,0,2,32669,17,5,2,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,702,-100,-180,0,1,12,1,3,13,0,2,32669,17,5,3,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,703,-100,-170,0,1,13,1,3,14,0,2,32669,17,6,0,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,704,-100,-160,0,1,14,1,3,15,0,2,32669,17,6,1,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,705,-100,-150,0,1,15,1,3,16,0,2,32669,17,6,2,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,706,-100,-140,0,1,16,1,3,17,0,2,32669,17,6,3,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,707,-100,-130,0,1,17,1,3,18,0,2,32669,17,7,0,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,708,-100,-120,0,1,18,1,3,19,0,2,32669,17,7,1,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,709,-100,-110,0,1,19,1,3,20,0,2,32669,17,7,2,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,710,-100,-100,0,1,20,1,3,21,0,2,32669,17,7,3,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,711,-100,-90,0,1,21,1,3,22,0,2,32669,17,8,0,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,712,-100,-80,0,1,22,1,3,23,0,2,32669,17,8,1,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,713,-100,-70,0,1,23,1,3,24,0,2,32669,17,8,2,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,714,-100,-60,0,1,24,1,3,25,0,2,32669,17,8,3,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,715,-100,-50,0,1,25,1,3,26,0,2,32669,17,9,0,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,716,-100,-40,0,1,26,1,3,27,0,2,32669,17,9,1,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,717,-100,-30,0,1,27,1,3,28,0,2,32669,17,9,2,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,718,-100,-20,0,1,28,1,3,29,0,2,32669,17,9,3,ON +11,0.902975,0.637851,2.58398,-0.707107,0,-0.707107,lappd_v1,ON,719,-100,-10,0,1,29,1,4,0,0,3,32669,18,0,0,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,720,100,-300,0,0,0,1,4,1,0,3,32669,18,0,1,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,721,100,-290,0,0,1,1,4,2,0,3,32669,18,0,2,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,722,100,-280,0,0,2,1,4,3,0,3,32669,18,0,3,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,723,100,-270,0,0,3,1,4,4,0,3,32669,18,1,0,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,724,100,-260,0,0,4,1,4,5,0,3,32669,18,1,1,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,725,100,-250,0,0,5,1,4,6,0,3,32669,18,1,2,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,726,100,-240,0,0,6,1,4,7,0,3,32669,18,1,3,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,727,100,-230,0,0,7,1,4,8,0,3,32669,18,2,0,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,728,100,-220,0,0,8,1,4,9,0,3,32669,18,2,1,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,729,100,-210,0,0,9,1,4,10,0,3,32669,18,2,2,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,730,100,-200,0,0,10,1,4,11,0,3,32669,18,2,3,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,731,100,-190,0,0,11,1,4,12,0,3,32669,18,3,0,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,732,100,-180,0,0,12,1,4,13,0,3,32669,18,3,1,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,733,100,-170,0,0,13,1,4,14,0,3,32669,18,3,2,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,734,100,-160,0,0,14,1,4,15,0,3,32669,18,3,3,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,735,100,-150,0,0,15,1,4,16,0,3,32669,18,4,0,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,736,100,-140,0,0,16,1,4,17,0,3,32669,18,4,1,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,737,100,-130,0,0,17,1,4,18,0,3,32669,18,4,2,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,738,100,-120,0,0,18,1,4,19,0,3,32669,18,4,3,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,739,100,-110,0,0,19,1,4,20,0,3,32669,18,5,0,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,740,100,-100,0,0,20,1,4,21,0,3,32669,18,5,1,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,741,100,-90,0,0,21,1,4,22,0,3,32669,18,5,2,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,742,100,-80,0,0,22,1,4,23,0,3,32669,18,5,3,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,743,100,-70,0,0,23,1,4,24,0,3,32669,18,6,0,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,744,100,-60,0,0,24,1,4,25,0,3,32669,18,6,1,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,745,100,-50,0,0,25,1,4,26,0,3,32669,18,6,2,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,746,100,-40,0,0,26,1,4,27,0,3,32669,18,6,3,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,747,100,-30,0,0,27,1,4,28,0,3,32669,18,7,0,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,748,100,-20,0,0,28,1,4,29,0,3,32669,18,7,1,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,749,100,-10,0,0,29,1,5,0,0,3,32669,18,7,2,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,750,-100,-300,0,1,0,1,5,1,0,3,32669,18,7,3,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,751,-100,-290,0,1,1,1,5,2,0,3,32669,18,8,0,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,752,-100,-280,0,1,2,1,5,3,0,3,32669,18,8,1,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,753,-100,-270,0,1,3,1,5,4,0,3,32669,18,8,2,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,754,-100,-260,0,1,4,1,5,5,0,3,32669,18,8,3,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,755,-100,-250,0,1,5,1,5,6,0,3,32669,18,9,0,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,756,-100,-240,0,1,6,1,5,7,0,3,32669,18,9,1,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,757,-100,-230,0,1,7,1,5,8,0,3,32669,18,9,2,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,758,-100,-220,0,1,8,1,5,9,0,3,32669,18,9,3,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,759,-100,-210,0,1,9,1,5,10,0,3,32669,19,0,0,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,760,-100,-200,0,1,10,1,5,11,0,3,32669,19,0,1,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,761,-100,-190,0,1,11,1,5,12,0,3,32669,19,0,2,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,762,-100,-180,0,1,12,1,5,13,0,3,32669,19,0,3,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,763,-100,-170,0,1,13,1,5,14,0,3,32669,19,1,0,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,764,-100,-160,0,1,14,1,5,15,0,3,32669,19,1,1,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,765,-100,-150,0,1,15,1,5,16,0,3,32669,19,1,2,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,766,-100,-140,0,1,16,1,5,17,0,3,32669,19,1,3,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,767,-100,-130,0,1,17,1,5,18,0,3,32669,19,2,0,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,768,-100,-120,0,1,18,1,5,19,0,3,32669,19,2,1,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,769,-100,-110,0,1,19,1,5,20,0,3,32669,19,2,2,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,770,-100,-100,0,1,20,1,5,21,0,3,32669,19,2,3,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,771,-100,-90,0,1,21,1,5,22,0,3,32669,19,3,0,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,772,-100,-80,0,1,22,1,5,23,0,3,32669,19,3,1,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,773,-100,-70,0,1,23,1,5,24,0,3,32669,19,3,2,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,774,-100,-60,0,1,24,1,5,25,0,3,32669,19,3,3,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,775,-100,-50,0,1,25,1,5,26,0,3,32669,19,4,0,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,776,-100,-40,0,1,26,1,5,27,0,3,32669,19,4,1,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,777,-100,-30,0,1,27,1,5,28,0,3,32669,19,4,2,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,778,-100,-20,0,1,28,1,5,29,0,3,32669,19,4,3,ON +12,0,-0.927149,2.958,0,0,-1,lappd_v1,ON,779,-100,-10,0,1,29,1,6,0,0,3,32669,19,5,0,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,780,100,-300,0,0,0,1,6,1,0,3,32669,19,5,1,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,781,100,-290,0,0,1,1,6,2,0,3,32669,19,5,2,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,782,100,-280,0,0,2,1,6,3,0,3,32669,19,5,3,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,783,100,-270,0,0,3,1,6,4,0,3,32669,19,6,0,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,784,100,-260,0,0,4,1,6,5,0,3,32669,19,6,1,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,785,100,-250,0,0,5,1,6,6,0,3,32669,19,6,2,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,786,100,-240,0,0,6,1,6,7,0,3,32669,19,6,3,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,787,100,-230,0,0,7,1,6,8,0,3,32669,19,7,0,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,788,100,-220,0,0,8,1,6,9,0,3,32669,19,7,1,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,789,100,-210,0,0,9,1,6,10,0,3,32669,19,7,2,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,790,100,-200,0,0,10,1,6,11,0,3,32669,19,7,3,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,791,100,-190,0,0,11,1,6,12,0,3,32669,19,8,0,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,792,100,-180,0,0,12,1,6,13,0,3,32669,19,8,1,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,793,100,-170,0,0,13,1,6,14,0,3,32669,19,8,2,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,794,100,-160,0,0,14,1,6,15,0,3,32669,19,8,3,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,795,100,-150,0,0,15,1,6,16,0,3,32669,19,9,0,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,796,100,-140,0,0,16,1,6,17,0,3,32669,19,9,1,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,797,100,-130,0,0,17,1,6,18,0,3,32669,19,9,2,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,798,100,-120,0,0,18,1,6,19,0,3,32669,19,9,3,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,799,100,-110,0,0,19,1,6,20,0,3,32669,20,0,0,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,800,100,-100,0,0,20,1,6,21,0,3,32669,20,0,1,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,801,100,-90,0,0,21,1,6,22,0,3,32669,20,0,2,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,802,100,-80,0,0,22,1,6,23,0,3,32669,20,0,3,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,803,100,-70,0,0,23,1,6,24,0,3,32669,20,1,0,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,804,100,-60,0,0,24,1,6,25,0,3,32669,20,1,1,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,805,100,-50,0,0,25,1,6,26,0,3,32669,20,1,2,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,806,100,-40,0,0,26,1,6,27,0,3,32669,20,1,3,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,807,100,-30,0,0,27,1,6,28,0,3,32669,20,2,0,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,808,100,-20,0,0,28,1,6,29,0,3,32669,20,2,1,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,809,100,-10,0,0,29,1,7,0,0,3,32669,20,2,2,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,810,-100,-300,0,1,0,1,7,1,0,3,32669,20,2,3,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,811,-100,-290,0,1,1,1,7,2,0,3,32669,20,3,0,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,812,-100,-280,0,1,2,1,7,3,0,3,32669,20,3,1,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,813,-100,-270,0,1,3,1,7,4,0,3,32669,20,3,2,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,814,-100,-260,0,1,4,1,7,5,0,3,32669,20,3,3,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,815,-100,-250,0,1,5,1,7,6,0,3,32669,20,4,0,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,816,-100,-240,0,1,6,1,7,7,0,3,32669,20,4,1,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,817,-100,-230,0,1,7,1,7,8,0,3,32669,20,4,2,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,818,-100,-220,0,1,8,1,7,9,0,3,32669,20,4,3,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,819,-100,-210,0,1,9,1,7,10,0,3,32669,20,5,0,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,820,-100,-200,0,1,10,1,7,11,0,3,32669,20,5,1,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,821,-100,-190,0,1,11,1,7,12,0,3,32669,20,5,2,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,822,-100,-180,0,1,12,1,7,13,0,3,32669,20,5,3,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,823,-100,-170,0,1,13,1,7,14,0,3,32669,20,6,0,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,824,-100,-160,0,1,14,1,7,15,0,3,32669,20,6,1,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,825,-100,-150,0,1,15,1,7,16,0,3,32669,20,6,2,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,826,-100,-140,0,1,16,1,7,17,0,3,32669,20,6,3,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,827,-100,-130,0,1,17,1,7,18,0,3,32669,20,7,0,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,828,-100,-120,0,1,18,1,7,19,0,3,32669,20,7,1,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,829,-100,-110,0,1,19,1,7,20,0,3,32669,20,7,2,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,830,-100,-100,0,1,20,1,7,21,0,3,32669,20,7,3,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,831,-100,-90,0,1,21,1,7,22,0,3,32669,20,8,0,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,832,-100,-80,0,1,22,1,7,23,0,3,32669,20,8,1,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,833,-100,-70,0,1,23,1,7,24,0,3,32669,20,8,2,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,834,-100,-60,0,1,24,1,7,25,0,3,32669,20,8,3,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,835,-100,-50,0,1,25,1,7,26,0,3,32669,20,9,0,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,836,-100,-40,0,1,26,1,7,27,0,3,32669,20,9,1,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,837,-100,-30,0,1,27,1,7,28,0,3,32669,20,9,2,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,838,-100,-20,0,1,28,1,7,29,0,3,32669,20,9,3,ON +13,0,-0.144649,2.958,0,0,-1,lappd_v1,ON,839,-100,-10,0,1,29,1,8,0,0,3,32669,21,0,0,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,840,100,-300,0,0,0,1,8,1,0,3,32669,21,0,1,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,841,100,-290,0,0,1,1,8,2,0,3,32669,21,0,2,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,842,100,-280,0,0,2,1,8,3,0,3,32669,21,0,3,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,843,100,-270,0,0,3,1,8,4,0,3,32669,21,1,0,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,844,100,-260,0,0,4,1,8,5,0,3,32669,21,1,1,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,845,100,-250,0,0,5,1,8,6,0,3,32669,21,1,2,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,846,100,-240,0,0,6,1,8,7,0,3,32669,21,1,3,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,847,100,-230,0,0,7,1,8,8,0,3,32669,21,2,0,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,848,100,-220,0,0,8,1,8,9,0,3,32669,21,2,1,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,849,100,-210,0,0,9,1,8,10,0,3,32669,21,2,2,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,850,100,-200,0,0,10,1,8,11,0,3,32669,21,2,3,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,851,100,-190,0,0,11,1,8,12,0,3,32669,21,3,0,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,852,100,-180,0,0,12,1,8,13,0,3,32669,21,3,1,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,853,100,-170,0,0,13,1,8,14,0,3,32669,21,3,2,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,854,100,-160,0,0,14,1,8,15,0,3,32669,21,3,3,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,855,100,-150,0,0,15,1,8,16,0,3,32669,21,4,0,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,856,100,-140,0,0,16,1,8,17,0,3,32669,21,4,1,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,857,100,-130,0,0,17,1,8,18,0,3,32669,21,4,2,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,858,100,-120,0,0,18,1,8,19,0,3,32669,21,4,3,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,859,100,-110,0,0,19,1,8,20,0,3,32669,21,5,0,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,860,100,-100,0,0,20,1,8,21,0,3,32669,21,5,1,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,861,100,-90,0,0,21,1,8,22,0,3,32669,21,5,2,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,862,100,-80,0,0,22,1,8,23,0,3,32669,21,5,3,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,863,100,-70,0,0,23,1,8,24,0,3,32669,21,6,0,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,864,100,-60,0,0,24,1,8,25,0,3,32669,21,6,1,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,865,100,-50,0,0,25,1,8,26,0,3,32669,21,6,2,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,866,100,-40,0,0,26,1,8,27,0,3,32669,21,6,3,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,867,100,-30,0,0,27,1,8,28,0,3,32669,21,7,0,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,868,100,-20,0,0,28,1,8,29,0,3,32669,21,7,1,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,869,100,-10,0,0,29,1,9,0,0,3,32669,21,7,2,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,870,-100,-300,0,1,0,1,9,1,0,3,32669,21,7,3,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,871,-100,-290,0,1,1,1,9,2,0,3,32669,21,8,0,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,872,-100,-280,0,1,2,1,9,3,0,3,32669,21,8,1,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,873,-100,-270,0,1,3,1,9,4,0,3,32669,21,8,2,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,874,-100,-260,0,1,4,1,9,5,0,3,32669,21,8,3,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,875,-100,-250,0,1,5,1,9,6,0,3,32669,21,9,0,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,876,-100,-240,0,1,6,1,9,7,0,3,32669,21,9,1,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,877,-100,-230,0,1,7,1,9,8,0,3,32669,21,9,2,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,878,-100,-220,0,1,8,1,9,9,0,3,32669,21,9,3,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,879,-100,-210,0,1,9,1,9,10,0,3,32669,22,0,0,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,880,-100,-200,0,1,10,1,9,11,0,3,32669,22,0,1,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,881,-100,-190,0,1,11,1,9,12,0,3,32669,22,0,2,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,882,-100,-180,0,1,12,1,9,13,0,3,32669,22,0,3,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,883,-100,-170,0,1,13,1,9,14,0,3,32669,22,1,0,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,884,-100,-160,0,1,14,1,9,15,0,3,32669,22,1,1,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,885,-100,-150,0,1,15,1,9,16,0,3,32669,22,1,2,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,886,-100,-140,0,1,16,1,9,17,0,3,32669,22,1,3,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,887,-100,-130,0,1,17,1,9,18,0,3,32669,22,2,0,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,888,-100,-120,0,1,18,1,9,19,0,3,32669,22,2,1,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,889,-100,-110,0,1,19,1,9,20,0,3,32669,22,2,2,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,890,-100,-100,0,1,20,1,9,21,0,3,32669,22,2,3,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,891,-100,-90,0,1,21,1,9,22,0,3,32669,22,3,0,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,892,-100,-80,0,1,22,1,9,23,0,3,32669,22,3,1,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,893,-100,-70,0,1,23,1,9,24,0,3,32669,22,3,2,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,894,-100,-60,0,1,24,1,9,25,0,3,32669,22,3,3,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,895,-100,-50,0,1,25,1,9,26,0,3,32669,22,4,0,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,896,-100,-40,0,1,26,1,9,27,0,3,32669,22,4,1,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,897,-100,-30,0,1,27,1,9,28,0,3,32669,22,4,2,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,898,-100,-20,0,1,28,1,9,29,0,3,32669,22,4,3,ON +14,0,0.637851,2.958,0,0,-1,lappd_v1,ON,899,-100,-10,0,1,29,1,10,0,0,3,32669,22,5,0,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,900,100,-300,0,0,0,1,10,1,0,3,32669,22,5,1,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,901,100,-290,0,0,1,1,10,2,0,3,32669,22,5,2,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,902,100,-280,0,0,2,1,10,3,0,3,32669,22,5,3,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,903,100,-270,0,0,3,1,10,4,0,3,32669,22,6,0,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,904,100,-260,0,0,4,1,10,5,0,3,32669,22,6,1,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,905,100,-250,0,0,5,1,10,6,0,3,32669,22,6,2,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,906,100,-240,0,0,6,1,10,7,0,3,32669,22,6,3,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,907,100,-230,0,0,7,1,10,8,0,3,32669,22,7,0,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,908,100,-220,0,0,8,1,10,9,0,3,32669,22,7,1,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,909,100,-210,0,0,9,1,10,10,0,3,32669,22,7,2,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,910,100,-200,0,0,10,1,10,11,0,3,32669,22,7,3,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,911,100,-190,0,0,11,1,10,12,0,3,32669,22,8,0,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,912,100,-180,0,0,12,1,10,13,0,3,32669,22,8,1,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,913,100,-170,0,0,13,1,10,14,0,3,32669,22,8,2,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,914,100,-160,0,0,14,1,10,15,0,3,32669,22,8,3,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,915,100,-150,0,0,15,1,10,16,0,3,32669,22,9,0,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,916,100,-140,0,0,16,1,10,17,0,3,32669,22,9,1,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,917,100,-130,0,0,17,1,10,18,0,3,32669,22,9,2,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,918,100,-120,0,0,18,1,10,19,0,3,32669,22,9,3,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,919,100,-110,0,0,19,1,10,20,0,3,32669,23,0,0,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,920,100,-100,0,0,20,1,10,21,0,3,32669,23,0,1,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,921,100,-90,0,0,21,1,10,22,0,3,32669,23,0,2,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,922,100,-80,0,0,22,1,10,23,0,3,32669,23,0,3,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,923,100,-70,0,0,23,1,10,24,0,3,32669,23,1,0,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,924,100,-60,0,0,24,1,10,25,0,3,32669,23,1,1,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,925,100,-50,0,0,25,1,10,26,0,3,32669,23,1,2,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,926,100,-40,0,0,26,1,10,27,0,3,32669,23,1,3,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,927,100,-30,0,0,27,1,10,28,0,3,32669,23,2,0,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,928,100,-20,0,0,28,1,10,29,0,3,32669,23,2,1,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,929,100,-10,0,0,29,1,11,0,0,3,32669,23,2,2,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,930,-100,-300,0,1,0,1,11,1,0,3,32669,23,2,3,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,931,-100,-290,0,1,1,1,11,2,0,3,32669,23,3,0,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,932,-100,-280,0,1,2,1,11,3,0,3,32669,23,3,1,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,933,-100,-270,0,1,3,1,11,4,0,3,32669,23,3,2,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,934,-100,-260,0,1,4,1,11,5,0,3,32669,23,3,3,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,935,-100,-250,0,1,5,1,11,6,0,3,32669,23,4,0,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,936,-100,-240,0,1,6,1,11,7,0,3,32669,23,4,1,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,937,-100,-230,0,1,7,1,11,8,0,3,32669,23,4,2,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,938,-100,-220,0,1,8,1,11,9,0,3,32669,23,4,3,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,939,-100,-210,0,1,9,1,11,10,0,3,32669,23,5,0,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,940,-100,-200,0,1,10,1,11,11,0,3,32669,23,5,1,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,941,-100,-190,0,1,11,1,11,12,0,3,32669,23,5,2,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,942,-100,-180,0,1,12,1,11,13,0,3,32669,23,5,3,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,943,-100,-170,0,1,13,1,11,14,0,3,32669,23,6,0,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,944,-100,-160,0,1,14,1,11,15,0,3,32669,23,6,1,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,945,-100,-150,0,1,15,1,11,16,0,3,32669,23,6,2,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,946,-100,-140,0,1,16,1,11,17,0,3,32669,23,6,3,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,947,-100,-130,0,1,17,1,11,18,0,3,32669,23,7,0,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,948,-100,-120,0,1,18,1,11,19,0,3,32669,23,7,1,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,949,-100,-110,0,1,19,1,11,20,0,3,32669,23,7,2,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,950,-100,-100,0,1,20,1,11,21,0,3,32669,23,7,3,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,951,-100,-90,0,1,21,1,11,22,0,3,32669,23,8,0,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,952,-100,-80,0,1,22,1,11,23,0,3,32669,23,8,1,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,953,-100,-70,0,1,23,1,11,24,0,3,32669,23,8,2,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,954,-100,-60,0,1,24,1,11,25,0,3,32669,23,8,3,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,955,-100,-50,0,1,25,1,11,26,0,3,32669,23,9,0,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,956,-100,-40,0,1,26,1,11,27,0,3,32669,23,9,1,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,957,-100,-30,0,1,27,1,11,28,0,3,32669,23,9,2,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,958,-100,-20,0,1,28,1,11,29,0,3,32669,23,9,3,ON +15,-0.902975,-0.927149,2.58398,0.707107,0,-0.707107,lappd_v1,ON,959,-100,-10,0,1,29,1,12,0,0,4,32669,24,0,0,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,960,100,-300,0,0,0,1,12,1,0,4,32669,24,0,1,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,961,100,-290,0,0,1,1,12,2,0,4,32669,24,0,2,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,962,100,-280,0,0,2,1,12,3,0,4,32669,24,0,3,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,963,100,-270,0,0,3,1,12,4,0,4,32669,24,1,0,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,964,100,-260,0,0,4,1,12,5,0,4,32669,24,1,1,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,965,100,-250,0,0,5,1,12,6,0,4,32669,24,1,2,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,966,100,-240,0,0,6,1,12,7,0,4,32669,24,1,3,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,967,100,-230,0,0,7,1,12,8,0,4,32669,24,2,0,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,968,100,-220,0,0,8,1,12,9,0,4,32669,24,2,1,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,969,100,-210,0,0,9,1,12,10,0,4,32669,24,2,2,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,970,100,-200,0,0,10,1,12,11,0,4,32669,24,2,3,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,971,100,-190,0,0,11,1,12,12,0,4,32669,24,3,0,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,972,100,-180,0,0,12,1,12,13,0,4,32669,24,3,1,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,973,100,-170,0,0,13,1,12,14,0,4,32669,24,3,2,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,974,100,-160,0,0,14,1,12,15,0,4,32669,24,3,3,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,975,100,-150,0,0,15,1,12,16,0,4,32669,24,4,0,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,976,100,-140,0,0,16,1,12,17,0,4,32669,24,4,1,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,977,100,-130,0,0,17,1,12,18,0,4,32669,24,4,2,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,978,100,-120,0,0,18,1,12,19,0,4,32669,24,4,3,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,979,100,-110,0,0,19,1,12,20,0,4,32669,24,5,0,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,980,100,-100,0,0,20,1,12,21,0,4,32669,24,5,1,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,981,100,-90,0,0,21,1,12,22,0,4,32669,24,5,2,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,982,100,-80,0,0,22,1,12,23,0,4,32669,24,5,3,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,983,100,-70,0,0,23,1,12,24,0,4,32669,24,6,0,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,984,100,-60,0,0,24,1,12,25,0,4,32669,24,6,1,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,985,100,-50,0,0,25,1,12,26,0,4,32669,24,6,2,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,986,100,-40,0,0,26,1,12,27,0,4,32669,24,6,3,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,987,100,-30,0,0,27,1,12,28,0,4,32669,24,7,0,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,988,100,-20,0,0,28,1,12,29,0,4,32669,24,7,1,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,989,100,-10,0,0,29,1,13,0,0,4,32669,24,7,2,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,990,-100,-300,0,1,0,1,13,1,0,4,32669,24,7,3,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,991,-100,-290,0,1,1,1,13,2,0,4,32669,24,8,0,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,992,-100,-280,0,1,2,1,13,3,0,4,32669,24,8,1,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,993,-100,-270,0,1,3,1,13,4,0,4,32669,24,8,2,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,994,-100,-260,0,1,4,1,13,5,0,4,32669,24,8,3,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,995,-100,-250,0,1,5,1,13,6,0,4,32669,24,9,0,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,996,-100,-240,0,1,6,1,13,7,0,4,32669,24,9,1,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,997,-100,-230,0,1,7,1,13,8,0,4,32669,24,9,2,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,998,-100,-220,0,1,8,1,13,9,0,4,32669,24,9,3,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,999,-100,-210,0,1,9,1,13,10,0,4,32669,25,0,0,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1000,-100,-200,0,1,10,1,13,11,0,4,32669,25,0,1,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1001,-100,-190,0,1,11,1,13,12,0,4,32669,25,0,2,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1002,-100,-180,0,1,12,1,13,13,0,4,32669,25,0,3,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1003,-100,-170,0,1,13,1,13,14,0,4,32669,25,1,0,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1004,-100,-160,0,1,14,1,13,15,0,4,32669,25,1,1,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1005,-100,-150,0,1,15,1,13,16,0,4,32669,25,1,2,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1006,-100,-140,0,1,16,1,13,17,0,4,32669,25,1,3,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1007,-100,-130,0,1,17,1,13,18,0,4,32669,25,2,0,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1008,-100,-120,0,1,18,1,13,19,0,4,32669,25,2,1,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1009,-100,-110,0,1,19,1,13,20,0,4,32669,25,2,2,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1010,-100,-100,0,1,20,1,13,21,0,4,32669,25,2,3,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1011,-100,-90,0,1,21,1,13,22,0,4,32669,25,3,0,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1012,-100,-80,0,1,22,1,13,23,0,4,32669,25,3,1,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1013,-100,-70,0,1,23,1,13,24,0,4,32669,25,3,2,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1014,-100,-60,0,1,24,1,13,25,0,4,32669,25,3,3,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1015,-100,-50,0,1,25,1,13,26,0,4,32669,25,4,0,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1016,-100,-40,0,1,26,1,13,27,0,4,32669,25,4,1,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1017,-100,-30,0,1,27,1,13,28,0,4,32669,25,4,2,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1018,-100,-20,0,1,28,1,13,29,0,4,32669,25,4,3,ON +16,-0.902975,-0.144649,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1019,-100,-10,0,1,29,1,14,0,0,4,32669,25,5,0,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1020,100,-300,0,0,0,1,14,1,0,4,32669,25,5,1,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1021,100,-290,0,0,1,1,14,2,0,4,32669,25,5,2,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1022,100,-280,0,0,2,1,14,3,0,4,32669,25,5,3,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1023,100,-270,0,0,3,1,14,4,0,4,32669,25,6,0,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1024,100,-260,0,0,4,1,14,5,0,4,32669,25,6,1,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1025,100,-250,0,0,5,1,14,6,0,4,32669,25,6,2,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1026,100,-240,0,0,6,1,14,7,0,4,32669,25,6,3,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1027,100,-230,0,0,7,1,14,8,0,4,32669,25,7,0,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1028,100,-220,0,0,8,1,14,9,0,4,32669,25,7,1,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1029,100,-210,0,0,9,1,14,10,0,4,32669,25,7,2,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1030,100,-200,0,0,10,1,14,11,0,4,32669,25,7,3,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1031,100,-190,0,0,11,1,14,12,0,4,32669,25,8,0,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1032,100,-180,0,0,12,1,14,13,0,4,32669,25,8,1,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1033,100,-170,0,0,13,1,14,14,0,4,32669,25,8,2,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1034,100,-160,0,0,14,1,14,15,0,4,32669,25,8,3,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1035,100,-150,0,0,15,1,14,16,0,4,32669,25,9,0,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1036,100,-140,0,0,16,1,14,17,0,4,32669,25,9,1,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1037,100,-130,0,0,17,1,14,18,0,4,32669,25,9,2,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1038,100,-120,0,0,18,1,14,19,0,4,32669,25,9,3,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1039,100,-110,0,0,19,1,14,20,0,4,32669,26,0,0,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1040,100,-100,0,0,20,1,14,21,0,4,32669,26,0,1,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1041,100,-90,0,0,21,1,14,22,0,4,32669,26,0,2,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1042,100,-80,0,0,22,1,14,23,0,4,32669,26,0,3,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1043,100,-70,0,0,23,1,14,24,0,4,32669,26,1,0,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1044,100,-60,0,0,24,1,14,25,0,4,32669,26,1,1,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1045,100,-50,0,0,25,1,14,26,0,4,32669,26,1,2,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1046,100,-40,0,0,26,1,14,27,0,4,32669,26,1,3,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1047,100,-30,0,0,27,1,14,28,0,4,32669,26,2,0,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1048,100,-20,0,0,28,1,14,29,0,4,32669,26,2,1,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1049,100,-10,0,0,29,1,15,0,0,4,32669,26,2,2,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1050,-100,-300,0,1,0,1,15,1,0,4,32669,26,2,3,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1051,-100,-290,0,1,1,1,15,2,0,4,32669,26,3,0,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1052,-100,-280,0,1,2,1,15,3,0,4,32669,26,3,1,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1053,-100,-270,0,1,3,1,15,4,0,4,32669,26,3,2,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1054,-100,-260,0,1,4,1,15,5,0,4,32669,26,3,3,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1055,-100,-250,0,1,5,1,15,6,0,4,32669,26,4,0,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1056,-100,-240,0,1,6,1,15,7,0,4,32669,26,4,1,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1057,-100,-230,0,1,7,1,15,8,0,4,32669,26,4,2,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1058,-100,-220,0,1,8,1,15,9,0,4,32669,26,4,3,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1059,-100,-210,0,1,9,1,15,10,0,4,32669,26,5,0,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1060,-100,-200,0,1,10,1,15,11,0,4,32669,26,5,1,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1061,-100,-190,0,1,11,1,15,12,0,4,32669,26,5,2,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1062,-100,-180,0,1,12,1,15,13,0,4,32669,26,5,3,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1063,-100,-170,0,1,13,1,15,14,0,4,32669,26,6,0,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1064,-100,-160,0,1,14,1,15,15,0,4,32669,26,6,1,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1065,-100,-150,0,1,15,1,15,16,0,4,32669,26,6,2,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1066,-100,-140,0,1,16,1,15,17,0,4,32669,26,6,3,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1067,-100,-130,0,1,17,1,15,18,0,4,32669,26,7,0,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1068,-100,-120,0,1,18,1,15,19,0,4,32669,26,7,1,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1069,-100,-110,0,1,19,1,15,20,0,4,32669,26,7,2,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1070,-100,-100,0,1,20,1,15,21,0,4,32669,26,7,3,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1071,-100,-90,0,1,21,1,15,22,0,4,32669,26,8,0,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1072,-100,-80,0,1,22,1,15,23,0,4,32669,26,8,1,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1073,-100,-70,0,1,23,1,15,24,0,4,32669,26,8,2,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1074,-100,-60,0,1,24,1,15,25,0,4,32669,26,8,3,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1075,-100,-50,0,1,25,1,15,26,0,4,32669,26,9,0,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1076,-100,-40,0,1,26,1,15,27,0,4,32669,26,9,1,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1077,-100,-30,0,1,27,1,15,28,0,4,32669,26,9,2,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1078,-100,-20,0,1,28,1,15,29,0,4,32669,26,9,3,ON +17,-0.902975,0.637851,2.58398,0.707107,0,-0.707107,lappd_v1,ON,1079,-100,-10,0,1,29,1,16,0,0,4,32669,27,0,0,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1080,100,-300,0,0,0,1,16,1,0,4,32669,27,0,1,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1081,100,-290,0,0,1,1,16,2,0,4,32669,27,0,2,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1082,100,-280,0,0,2,1,16,3,0,4,32669,27,0,3,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1083,100,-270,0,0,3,1,16,4,0,4,32669,27,1,0,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1084,100,-260,0,0,4,1,16,5,0,4,32669,27,1,1,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1085,100,-250,0,0,5,1,16,6,0,4,32669,27,1,2,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1086,100,-240,0,0,6,1,16,7,0,4,32669,27,1,3,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1087,100,-230,0,0,7,1,16,8,0,4,32669,27,2,0,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1088,100,-220,0,0,8,1,16,9,0,4,32669,27,2,1,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1089,100,-210,0,0,9,1,16,10,0,4,32669,27,2,2,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1090,100,-200,0,0,10,1,16,11,0,4,32669,27,2,3,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1091,100,-190,0,0,11,1,16,12,0,4,32669,27,3,0,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1092,100,-180,0,0,12,1,16,13,0,4,32669,27,3,1,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1093,100,-170,0,0,13,1,16,14,0,4,32669,27,3,2,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1094,100,-160,0,0,14,1,16,15,0,4,32669,27,3,3,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1095,100,-150,0,0,15,1,16,16,0,4,32669,27,4,0,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1096,100,-140,0,0,16,1,16,17,0,4,32669,27,4,1,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1097,100,-130,0,0,17,1,16,18,0,4,32669,27,4,2,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1098,100,-120,0,0,18,1,16,19,0,4,32669,27,4,3,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1099,100,-110,0,0,19,1,16,20,0,4,32669,27,5,0,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1100,100,-100,0,0,20,1,16,21,0,4,32669,27,5,1,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1101,100,-90,0,0,21,1,16,22,0,4,32669,27,5,2,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1102,100,-80,0,0,22,1,16,23,0,4,32669,27,5,3,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1103,100,-70,0,0,23,1,16,24,0,4,32669,27,6,0,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1104,100,-60,0,0,24,1,16,25,0,4,32669,27,6,1,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1105,100,-50,0,0,25,1,16,26,0,4,32669,27,6,2,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1106,100,-40,0,0,26,1,16,27,0,4,32669,27,6,3,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1107,100,-30,0,0,27,1,16,28,0,4,32669,27,7,0,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1108,100,-20,0,0,28,1,16,29,0,4,32669,27,7,1,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1109,100,-10,0,0,29,1,17,0,0,4,32669,27,7,2,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1110,-100,-300,0,1,0,1,17,1,0,4,32669,27,7,3,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1111,-100,-290,0,1,1,1,17,2,0,4,32669,27,8,0,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1112,-100,-280,0,1,2,1,17,3,0,4,32669,27,8,1,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1113,-100,-270,0,1,3,1,17,4,0,4,32669,27,8,2,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1114,-100,-260,0,1,4,1,17,5,0,4,32669,27,8,3,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1115,-100,-250,0,1,5,1,17,6,0,4,32669,27,9,0,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1116,-100,-240,0,1,6,1,17,7,0,4,32669,27,9,1,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1117,-100,-230,0,1,7,1,17,8,0,4,32669,27,9,2,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1118,-100,-220,0,1,8,1,17,9,0,4,32669,27,9,3,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1119,-100,-210,0,1,9,1,17,10,0,4,32669,28,0,0,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1120,-100,-200,0,1,10,1,17,11,0,4,32669,28,0,1,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1121,-100,-190,0,1,11,1,17,12,0,4,32669,28,0,2,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1122,-100,-180,0,1,12,1,17,13,0,4,32669,28,0,3,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1123,-100,-170,0,1,13,1,17,14,0,4,32669,28,1,0,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1124,-100,-160,0,1,14,1,17,15,0,4,32669,28,1,1,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1125,-100,-150,0,1,15,1,17,16,0,4,32669,28,1,2,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1126,-100,-140,0,1,16,1,17,17,0,4,32669,28,1,3,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1127,-100,-130,0,1,17,1,17,18,0,4,32669,28,2,0,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1128,-100,-120,0,1,18,1,17,19,0,4,32669,28,2,1,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1129,-100,-110,0,1,19,1,17,20,0,4,32669,28,2,2,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1130,-100,-100,0,1,20,1,17,21,0,4,32669,28,2,3,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1131,-100,-90,0,1,21,1,17,22,0,4,32669,28,3,0,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1132,-100,-80,0,1,22,1,17,23,0,4,32669,28,3,1,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1133,-100,-70,0,1,23,1,17,24,0,4,32669,28,3,2,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1134,-100,-60,0,1,24,1,17,25,0,4,32669,28,3,3,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1135,-100,-50,0,1,25,1,17,26,0,4,32669,28,4,0,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1136,-100,-40,0,1,26,1,17,27,0,4,32669,28,4,1,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1137,-100,-30,0,1,27,1,17,28,0,4,32669,28,4,2,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1138,-100,-20,0,1,28,1,17,29,0,4,32669,28,4,3,ON +18,-1.277,-0.927149,1.681,1,0,0,lappd_v1,ON,1139,-100,-10,0,1,29,1,18,0,0,4,32669,28,5,0,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1140,100,-300,0,0,0,1,18,1,0,4,32669,28,5,1,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1141,100,-290,0,0,1,1,18,2,0,4,32669,28,5,2,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1142,100,-280,0,0,2,1,18,3,0,4,32669,28,5,3,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1143,100,-270,0,0,3,1,18,4,0,4,32669,28,6,0,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1144,100,-260,0,0,4,1,18,5,0,4,32669,28,6,1,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1145,100,-250,0,0,5,1,18,6,0,4,32669,28,6,2,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1146,100,-240,0,0,6,1,18,7,0,4,32669,28,6,3,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1147,100,-230,0,0,7,1,18,8,0,4,32669,28,7,0,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1148,100,-220,0,0,8,1,18,9,0,4,32669,28,7,1,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1149,100,-210,0,0,9,1,18,10,0,4,32669,28,7,2,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1150,100,-200,0,0,10,1,18,11,0,4,32669,28,7,3,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1151,100,-190,0,0,11,1,18,12,0,4,32669,28,8,0,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1152,100,-180,0,0,12,1,18,13,0,4,32669,28,8,1,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1153,100,-170,0,0,13,1,18,14,0,4,32669,28,8,2,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1154,100,-160,0,0,14,1,18,15,0,4,32669,28,8,3,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1155,100,-150,0,0,15,1,18,16,0,4,32669,28,9,0,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1156,100,-140,0,0,16,1,18,17,0,4,32669,28,9,1,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1157,100,-130,0,0,17,1,18,18,0,4,32669,28,9,2,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1158,100,-120,0,0,18,1,18,19,0,4,32669,28,9,3,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1159,100,-110,0,0,19,1,18,20,0,4,32669,29,0,0,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1160,100,-100,0,0,20,1,18,21,0,4,32669,29,0,1,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1161,100,-90,0,0,21,1,18,22,0,4,32669,29,0,2,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1162,100,-80,0,0,22,1,18,23,0,4,32669,29,0,3,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1163,100,-70,0,0,23,1,18,24,0,4,32669,29,1,0,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1164,100,-60,0,0,24,1,18,25,0,4,32669,29,1,1,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1165,100,-50,0,0,25,1,18,26,0,4,32669,29,1,2,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1166,100,-40,0,0,26,1,18,27,0,4,32669,29,1,3,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1167,100,-30,0,0,27,1,18,28,0,4,32669,29,2,0,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1168,100,-20,0,0,28,1,18,29,0,4,32669,29,2,1,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1169,100,-10,0,0,29,1,19,0,0,4,32669,29,2,2,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1170,-100,-300,0,1,0,1,19,1,0,4,32669,29,2,3,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1171,-100,-290,0,1,1,1,19,2,0,4,32669,29,3,0,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1172,-100,-280,0,1,2,1,19,3,0,4,32669,29,3,1,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1173,-100,-270,0,1,3,1,19,4,0,4,32669,29,3,2,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1174,-100,-260,0,1,4,1,19,5,0,4,32669,29,3,3,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1175,-100,-250,0,1,5,1,19,6,0,4,32669,29,4,0,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1176,-100,-240,0,1,6,1,19,7,0,4,32669,29,4,1,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1177,-100,-230,0,1,7,1,19,8,0,4,32669,29,4,2,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1178,-100,-220,0,1,8,1,19,9,0,4,32669,29,4,3,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1179,-100,-210,0,1,9,1,19,10,0,4,32669,29,5,0,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1180,-100,-200,0,1,10,1,19,11,0,4,32669,29,5,1,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1181,-100,-190,0,1,11,1,19,12,0,4,32669,29,5,2,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1182,-100,-180,0,1,12,1,19,13,0,4,32669,29,5,3,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1183,-100,-170,0,1,13,1,19,14,0,4,32669,29,6,0,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1184,-100,-160,0,1,14,1,19,15,0,4,32669,29,6,1,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1185,-100,-150,0,1,15,1,19,16,0,4,32669,29,6,2,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1186,-100,-140,0,1,16,1,19,17,0,4,32669,29,6,3,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1187,-100,-130,0,1,17,1,19,18,0,4,32669,29,7,0,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1188,-100,-120,0,1,18,1,19,19,0,4,32669,29,7,1,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1189,-100,-110,0,1,19,1,19,20,0,4,32669,29,7,2,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1190,-100,-100,0,1,20,1,19,21,0,4,32669,29,7,3,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1191,-100,-90,0,1,21,1,19,22,0,4,32669,29,8,0,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1192,-100,-80,0,1,22,1,19,23,0,4,32669,29,8,1,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1193,-100,-70,0,1,23,1,19,24,0,4,32669,29,8,2,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1194,-100,-60,0,1,24,1,19,25,0,4,32669,29,8,3,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1195,-100,-50,0,1,25,1,19,26,0,4,32669,29,9,0,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1196,-100,-40,0,1,26,1,19,27,0,4,32669,29,9,1,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1197,-100,-30,0,1,27,1,19,28,0,4,32669,29,9,2,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1198,-100,-20,0,1,28,1,19,29,0,4,32669,29,9,3,ON +19,-1.277,-0.144649,1.681,1,0,0,lappd_v1,ON,1199,-100,-10,0,1,29,2,0,0,0,5,32669,30,0,0,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1200,100,-300,0,0,0,2,0,1,0,5,32669,30,0,1,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1201,100,-290,0,0,1,2,0,2,0,5,32669,30,0,2,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1202,100,-280,0,0,2,2,0,3,0,5,32669,30,0,3,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1203,100,-270,0,0,3,2,0,4,0,5,32669,30,1,0,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1204,100,-260,0,0,4,2,0,5,0,5,32669,30,1,1,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1205,100,-250,0,0,5,2,0,6,0,5,32669,30,1,2,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1206,100,-240,0,0,6,2,0,7,0,5,32669,30,1,3,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1207,100,-230,0,0,7,2,0,8,0,5,32669,30,2,0,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1208,100,-220,0,0,8,2,0,9,0,5,32669,30,2,1,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1209,100,-210,0,0,9,2,0,10,0,5,32669,30,2,2,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1210,100,-200,0,0,10,2,0,11,0,5,32669,30,2,3,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1211,100,-190,0,0,11,2,0,12,0,5,32669,30,3,0,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1212,100,-180,0,0,12,2,0,13,0,5,32669,30,3,1,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1213,100,-170,0,0,13,2,0,14,0,5,32669,30,3,2,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1214,100,-160,0,0,14,2,0,15,0,5,32669,30,3,3,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1215,100,-150,0,0,15,2,0,16,0,5,32669,30,4,0,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1216,100,-140,0,0,16,2,0,17,0,5,32669,30,4,1,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1217,100,-130,0,0,17,2,0,18,0,5,32669,30,4,2,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1218,100,-120,0,0,18,2,0,19,0,5,32669,30,4,3,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1219,100,-110,0,0,19,2,0,20,0,5,32669,30,5,0,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1220,100,-100,0,0,20,2,0,21,0,5,32669,30,5,1,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1221,100,-90,0,0,21,2,0,22,0,5,32669,30,5,2,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1222,100,-80,0,0,22,2,0,23,0,5,32669,30,5,3,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1223,100,-70,0,0,23,2,0,24,0,5,32669,30,6,0,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1224,100,-60,0,0,24,2,0,25,0,5,32669,30,6,1,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1225,100,-50,0,0,25,2,0,26,0,5,32669,30,6,2,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1226,100,-40,0,0,26,2,0,27,0,5,32669,30,6,3,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1227,100,-30,0,0,27,2,0,28,0,5,32669,30,7,0,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1228,100,-20,0,0,28,2,0,29,0,5,32669,30,7,1,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1229,100,-10,0,0,29,2,1,0,0,5,32669,30,7,2,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1230,-100,-300,0,1,0,2,1,1,0,5,32669,30,7,3,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1231,-100,-290,0,1,1,2,1,2,0,5,32669,30,8,0,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1232,-100,-280,0,1,2,2,1,3,0,5,32669,30,8,1,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1233,-100,-270,0,1,3,2,1,4,0,5,32669,30,8,2,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1234,-100,-260,0,1,4,2,1,5,0,5,32669,30,8,3,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1235,-100,-250,0,1,5,2,1,6,0,5,32669,30,9,0,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1236,-100,-240,0,1,6,2,1,7,0,5,32669,30,9,1,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1237,-100,-230,0,1,7,2,1,8,0,5,32669,30,9,2,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1238,-100,-220,0,1,8,2,1,9,0,5,32669,30,9,3,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1239,-100,-210,0,1,9,2,1,10,0,5,32669,31,0,0,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1240,-100,-200,0,1,10,2,1,11,0,5,32669,31,0,1,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1241,-100,-190,0,1,11,2,1,12,0,5,32669,31,0,2,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1242,-100,-180,0,1,12,2,1,13,0,5,32669,31,0,3,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1243,-100,-170,0,1,13,2,1,14,0,5,32669,31,1,0,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1244,-100,-160,0,1,14,2,1,15,0,5,32669,31,1,1,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1245,-100,-150,0,1,15,2,1,16,0,5,32669,31,1,2,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1246,-100,-140,0,1,16,2,1,17,0,5,32669,31,1,3,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1247,-100,-130,0,1,17,2,1,18,0,5,32669,31,2,0,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1248,-100,-120,0,1,18,2,1,19,0,5,32669,31,2,1,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1249,-100,-110,0,1,19,2,1,20,0,5,32669,31,2,2,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1250,-100,-100,0,1,20,2,1,21,0,5,32669,31,2,3,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1251,-100,-90,0,1,21,2,1,22,0,5,32669,31,3,0,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1252,-100,-80,0,1,22,2,1,23,0,5,32669,31,3,1,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1253,-100,-70,0,1,23,2,1,24,0,5,32669,31,3,2,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1254,-100,-60,0,1,24,2,1,25,0,5,32669,31,3,3,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1255,-100,-50,0,1,25,2,1,26,0,5,32669,31,4,0,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1256,-100,-40,0,1,26,2,1,27,0,5,32669,31,4,1,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1257,-100,-30,0,1,27,2,1,28,0,5,32669,31,4,2,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1258,-100,-20,0,1,28,2,1,29,0,5,32669,31,4,3,ON +20,-1.277,0.637851,1.681,1,0,0,lappd_v1,ON,1259,-100,-10,0,1,29,2,2,0,0,5,32669,31,5,0,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1260,100,-300,0,0,0,2,2,1,0,5,32669,31,5,1,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1261,100,-290,0,0,1,2,2,2,0,5,32669,31,5,2,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1262,100,-280,0,0,2,2,2,3,0,5,32669,31,5,3,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1263,100,-270,0,0,3,2,2,4,0,5,32669,31,6,0,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1264,100,-260,0,0,4,2,2,5,0,5,32669,31,6,1,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1265,100,-250,0,0,5,2,2,6,0,5,32669,31,6,2,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1266,100,-240,0,0,6,2,2,7,0,5,32669,31,6,3,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1267,100,-230,0,0,7,2,2,8,0,5,32669,31,7,0,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1268,100,-220,0,0,8,2,2,9,0,5,32669,31,7,1,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1269,100,-210,0,0,9,2,2,10,0,5,32669,31,7,2,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1270,100,-200,0,0,10,2,2,11,0,5,32669,31,7,3,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1271,100,-190,0,0,11,2,2,12,0,5,32669,31,8,0,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1272,100,-180,0,0,12,2,2,13,0,5,32669,31,8,1,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1273,100,-170,0,0,13,2,2,14,0,5,32669,31,8,2,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1274,100,-160,0,0,14,2,2,15,0,5,32669,31,8,3,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1275,100,-150,0,0,15,2,2,16,0,5,32669,31,9,0,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1276,100,-140,0,0,16,2,2,17,0,5,32669,31,9,1,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1277,100,-130,0,0,17,2,2,18,0,5,32669,31,9,2,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1278,100,-120,0,0,18,2,2,19,0,5,32669,31,9,3,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1279,100,-110,0,0,19,2,2,20,0,5,32669,32,0,0,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1280,100,-100,0,0,20,2,2,21,0,5,32669,32,0,1,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1281,100,-90,0,0,21,2,2,22,0,5,32669,32,0,2,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1282,100,-80,0,0,22,2,2,23,0,5,32669,32,0,3,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1283,100,-70,0,0,23,2,2,24,0,5,32669,32,1,0,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1284,100,-60,0,0,24,2,2,25,0,5,32669,32,1,1,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1285,100,-50,0,0,25,2,2,26,0,5,32669,32,1,2,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1286,100,-40,0,0,26,2,2,27,0,5,32669,32,1,3,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1287,100,-30,0,0,27,2,2,28,0,5,32669,32,2,0,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1288,100,-20,0,0,28,2,2,29,0,5,32669,32,2,1,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1289,100,-10,0,0,29,2,3,0,0,5,32669,32,2,2,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1290,-100,-300,0,1,0,2,3,1,0,5,32669,32,2,3,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1291,-100,-290,0,1,1,2,3,2,0,5,32669,32,3,0,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1292,-100,-280,0,1,2,2,3,3,0,5,32669,32,3,1,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1293,-100,-270,0,1,3,2,3,4,0,5,32669,32,3,2,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1294,-100,-260,0,1,4,2,3,5,0,5,32669,32,3,3,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1295,-100,-250,0,1,5,2,3,6,0,5,32669,32,4,0,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1296,-100,-240,0,1,6,2,3,7,0,5,32669,32,4,1,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1297,-100,-230,0,1,7,2,3,8,0,5,32669,32,4,2,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1298,-100,-220,0,1,8,2,3,9,0,5,32669,32,4,3,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1299,-100,-210,0,1,9,2,3,10,0,5,32669,32,5,0,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1300,-100,-200,0,1,10,2,3,11,0,5,32669,32,5,1,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1301,-100,-190,0,1,11,2,3,12,0,5,32669,32,5,2,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1302,-100,-180,0,1,12,2,3,13,0,5,32669,32,5,3,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1303,-100,-170,0,1,13,2,3,14,0,5,32669,32,6,0,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1304,-100,-160,0,1,14,2,3,15,0,5,32669,32,6,1,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1305,-100,-150,0,1,15,2,3,16,0,5,32669,32,6,2,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1306,-100,-140,0,1,16,2,3,17,0,5,32669,32,6,3,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1307,-100,-130,0,1,17,2,3,18,0,5,32669,32,7,0,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1308,-100,-120,0,1,18,2,3,19,0,5,32669,32,7,1,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1309,-100,-110,0,1,19,2,3,20,0,5,32669,32,7,2,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1310,-100,-100,0,1,20,2,3,21,0,5,32669,32,7,3,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1311,-100,-90,0,1,21,2,3,22,0,5,32669,32,8,0,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1312,-100,-80,0,1,22,2,3,23,0,5,32669,32,8,1,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1313,-100,-70,0,1,23,2,3,24,0,5,32669,32,8,2,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1314,-100,-60,0,1,24,2,3,25,0,5,32669,32,8,3,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1315,-100,-50,0,1,25,2,3,26,0,5,32669,32,9,0,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1316,-100,-40,0,1,26,2,3,27,0,5,32669,32,9,1,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1317,-100,-30,0,1,27,2,3,28,0,5,32669,32,9,2,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1318,-100,-20,0,1,28,2,3,29,0,5,32669,32,9,3,ON +21,-0.902975,-0.927149,0.778025,0.707107,0,0.707107,lappd_v1,ON,1319,-100,-10,0,1,29,2,4,0,0,5,32669,33,0,0,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1320,100,-300,0,0,0,2,4,1,0,5,32669,33,0,1,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1321,100,-290,0,0,1,2,4,2,0,5,32669,33,0,2,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1322,100,-280,0,0,2,2,4,3,0,5,32669,33,0,3,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1323,100,-270,0,0,3,2,4,4,0,5,32669,33,1,0,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1324,100,-260,0,0,4,2,4,5,0,5,32669,33,1,1,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1325,100,-250,0,0,5,2,4,6,0,5,32669,33,1,2,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1326,100,-240,0,0,6,2,4,7,0,5,32669,33,1,3,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1327,100,-230,0,0,7,2,4,8,0,5,32669,33,2,0,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1328,100,-220,0,0,8,2,4,9,0,5,32669,33,2,1,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1329,100,-210,0,0,9,2,4,10,0,5,32669,33,2,2,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1330,100,-200,0,0,10,2,4,11,0,5,32669,33,2,3,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1331,100,-190,0,0,11,2,4,12,0,5,32669,33,3,0,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1332,100,-180,0,0,12,2,4,13,0,5,32669,33,3,1,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1333,100,-170,0,0,13,2,4,14,0,5,32669,33,3,2,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1334,100,-160,0,0,14,2,4,15,0,5,32669,33,3,3,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1335,100,-150,0,0,15,2,4,16,0,5,32669,33,4,0,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1336,100,-140,0,0,16,2,4,17,0,5,32669,33,4,1,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1337,100,-130,0,0,17,2,4,18,0,5,32669,33,4,2,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1338,100,-120,0,0,18,2,4,19,0,5,32669,33,4,3,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1339,100,-110,0,0,19,2,4,20,0,5,32669,33,5,0,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1340,100,-100,0,0,20,2,4,21,0,5,32669,33,5,1,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1341,100,-90,0,0,21,2,4,22,0,5,32669,33,5,2,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1342,100,-80,0,0,22,2,4,23,0,5,32669,33,5,3,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1343,100,-70,0,0,23,2,4,24,0,5,32669,33,6,0,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1344,100,-60,0,0,24,2,4,25,0,5,32669,33,6,1,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1345,100,-50,0,0,25,2,4,26,0,5,32669,33,6,2,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1346,100,-40,0,0,26,2,4,27,0,5,32669,33,6,3,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1347,100,-30,0,0,27,2,4,28,0,5,32669,33,7,0,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1348,100,-20,0,0,28,2,4,29,0,5,32669,33,7,1,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1349,100,-10,0,0,29,2,5,0,0,5,32669,33,7,2,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1350,-100,-300,0,1,0,2,5,1,0,5,32669,33,7,3,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1351,-100,-290,0,1,1,2,5,2,0,5,32669,33,8,0,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1352,-100,-280,0,1,2,2,5,3,0,5,32669,33,8,1,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1353,-100,-270,0,1,3,2,5,4,0,5,32669,33,8,2,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1354,-100,-260,0,1,4,2,5,5,0,5,32669,33,8,3,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1355,-100,-250,0,1,5,2,5,6,0,5,32669,33,9,0,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1356,-100,-240,0,1,6,2,5,7,0,5,32669,33,9,1,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1357,-100,-230,0,1,7,2,5,8,0,5,32669,33,9,2,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1358,-100,-220,0,1,8,2,5,9,0,5,32669,33,9,3,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1359,-100,-210,0,1,9,2,5,10,0,5,32669,34,0,0,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1360,-100,-200,0,1,10,2,5,11,0,5,32669,34,0,1,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1361,-100,-190,0,1,11,2,5,12,0,5,32669,34,0,2,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1362,-100,-180,0,1,12,2,5,13,0,5,32669,34,0,3,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1363,-100,-170,0,1,13,2,5,14,0,5,32669,34,1,0,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1364,-100,-160,0,1,14,2,5,15,0,5,32669,34,1,1,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1365,-100,-150,0,1,15,2,5,16,0,5,32669,34,1,2,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1366,-100,-140,0,1,16,2,5,17,0,5,32669,34,1,3,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1367,-100,-130,0,1,17,2,5,18,0,5,32669,34,2,0,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1368,-100,-120,0,1,18,2,5,19,0,5,32669,34,2,1,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1369,-100,-110,0,1,19,2,5,20,0,5,32669,34,2,2,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1370,-100,-100,0,1,20,2,5,21,0,5,32669,34,2,3,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1371,-100,-90,0,1,21,2,5,22,0,5,32669,34,3,0,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1372,-100,-80,0,1,22,2,5,23,0,5,32669,34,3,1,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1373,-100,-70,0,1,23,2,5,24,0,5,32669,34,3,2,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1374,-100,-60,0,1,24,2,5,25,0,5,32669,34,3,3,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1375,-100,-50,0,1,25,2,5,26,0,5,32669,34,4,0,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1376,-100,-40,0,1,26,2,5,27,0,5,32669,34,4,1,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1377,-100,-30,0,1,27,2,5,28,0,5,32669,34,4,2,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1378,-100,-20,0,1,28,2,5,29,0,5,32669,34,4,3,ON +22,-0.902975,-0.144649,0.778025,0.707107,0,0.707107,lappd_v1,ON,1379,-100,-10,0,1,29,2,6,0,0,5,32669,34,5,0,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1380,100,-300,0,0,0,2,6,1,0,5,32669,34,5,1,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1381,100,-290,0,0,1,2,6,2,0,5,32669,34,5,2,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1382,100,-280,0,0,2,2,6,3,0,5,32669,34,5,3,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1383,100,-270,0,0,3,2,6,4,0,5,32669,34,6,0,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1384,100,-260,0,0,4,2,6,5,0,5,32669,34,6,1,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1385,100,-250,0,0,5,2,6,6,0,5,32669,34,6,2,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1386,100,-240,0,0,6,2,6,7,0,5,32669,34,6,3,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1387,100,-230,0,0,7,2,6,8,0,5,32669,34,7,0,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1388,100,-220,0,0,8,2,6,9,0,5,32669,34,7,1,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1389,100,-210,0,0,9,2,6,10,0,5,32669,34,7,2,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1390,100,-200,0,0,10,2,6,11,0,5,32669,34,7,3,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1391,100,-190,0,0,11,2,6,12,0,5,32669,34,8,0,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1392,100,-180,0,0,12,2,6,13,0,5,32669,34,8,1,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1393,100,-170,0,0,13,2,6,14,0,5,32669,34,8,2,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1394,100,-160,0,0,14,2,6,15,0,5,32669,34,8,3,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1395,100,-150,0,0,15,2,6,16,0,5,32669,34,9,0,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1396,100,-140,0,0,16,2,6,17,0,5,32669,34,9,1,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1397,100,-130,0,0,17,2,6,18,0,5,32669,34,9,2,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1398,100,-120,0,0,18,2,6,19,0,5,32669,34,9,3,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1399,100,-110,0,0,19,2,6,20,0,5,32669,35,0,0,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1400,100,-100,0,0,20,2,6,21,0,5,32669,35,0,1,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1401,100,-90,0,0,21,2,6,22,0,5,32669,35,0,2,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1402,100,-80,0,0,22,2,6,23,0,5,32669,35,0,3,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1403,100,-70,0,0,23,2,6,24,0,5,32669,35,1,0,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1404,100,-60,0,0,24,2,6,25,0,5,32669,35,1,1,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1405,100,-50,0,0,25,2,6,26,0,5,32669,35,1,2,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1406,100,-40,0,0,26,2,6,27,0,5,32669,35,1,3,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1407,100,-30,0,0,27,2,6,28,0,5,32669,35,2,0,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1408,100,-20,0,0,28,2,6,29,0,5,32669,35,2,1,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1409,100,-10,0,0,29,2,7,0,0,5,32669,35,2,2,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1410,-100,-300,0,1,0,2,7,1,0,5,32669,35,2,3,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1411,-100,-290,0,1,1,2,7,2,0,5,32669,35,3,0,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1412,-100,-280,0,1,2,2,7,3,0,5,32669,35,3,1,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1413,-100,-270,0,1,3,2,7,4,0,5,32669,35,3,2,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1414,-100,-260,0,1,4,2,7,5,0,5,32669,35,3,3,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1415,-100,-250,0,1,5,2,7,6,0,5,32669,35,4,0,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1416,-100,-240,0,1,6,2,7,7,0,5,32669,35,4,1,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1417,-100,-230,0,1,7,2,7,8,0,5,32669,35,4,2,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1418,-100,-220,0,1,8,2,7,9,0,5,32669,35,4,3,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1419,-100,-210,0,1,9,2,7,10,0,5,32669,35,5,0,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1420,-100,-200,0,1,10,2,7,11,0,5,32669,35,5,1,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1421,-100,-190,0,1,11,2,7,12,0,5,32669,35,5,2,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1422,-100,-180,0,1,12,2,7,13,0,5,32669,35,5,3,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1423,-100,-170,0,1,13,2,7,14,0,5,32669,35,6,0,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1424,-100,-160,0,1,14,2,7,15,0,5,32669,35,6,1,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1425,-100,-150,0,1,15,2,7,16,0,5,32669,35,6,2,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1426,-100,-140,0,1,16,2,7,17,0,5,32669,35,6,3,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1427,-100,-130,0,1,17,2,7,18,0,5,32669,35,7,0,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1428,-100,-120,0,1,18,2,7,19,0,5,32669,35,7,1,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1429,-100,-110,0,1,19,2,7,20,0,5,32669,35,7,2,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1430,-100,-100,0,1,20,2,7,21,0,5,32669,35,7,3,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1431,-100,-90,0,1,21,2,7,22,0,5,32669,35,8,0,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1432,-100,-80,0,1,22,2,7,23,0,5,32669,35,8,1,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1433,-100,-70,0,1,23,2,7,24,0,5,32669,35,8,2,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1434,-100,-60,0,1,24,2,7,25,0,5,32669,35,8,3,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1435,-100,-50,0,1,25,2,7,26,0,5,32669,35,9,0,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1436,-100,-40,0,1,26,2,7,27,0,5,32669,35,9,1,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1437,-100,-30,0,1,27,2,7,28,0,5,32669,35,9,2,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1438,-100,-20,0,1,28,2,7,29,0,5,32669,35,9,3,ON +23,-0.902975,0.637851,0.778025,0.707107,0,0.707107,lappd_v1,ON,1439,-100,-10,0,1,29,2,8,0,0,6,32669,36,0,0,ON +DATA_END,,,,,,,,,,,,,,,,,,,,,,,, \ No newline at end of file From e17f26100a066c2a4ccc87029c03a86a29436c0b Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 26 Jun 2024 12:47:36 -0500 Subject: [PATCH 065/163] Update LAPPDLoadStore.cpp This verbose for loading progress assumed there are more than 10 LAPPD events; if there are less it would lead to a floating point exception --- UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp index f386be6f5..62bfdfd12 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp @@ -1356,7 +1356,7 @@ void LAPPDLoadStore::LoadOffsetsAndCorrections() BGCorrections[key][EventIndex] = static_cast(BGCorrection_tick) - 1000; TSCorrections[key][EventIndex] = static_cast(TSCorrection_tick) - 1000; - if (i % (static_cast(nentries / 10)) == 0) + if (nentries > 10 && i % (static_cast(nentries / 10)) == 0) { cout << "LAPPDStoreReadIn Loading offsets and corrections, " << i << " entries loaded" << endl; cout << "Printing key: " << key << ", EventIndex: " << EventIndex << ", final_offset_ns_0: " << final_offset_ns_0 << ", final_offset_ps_negative_0: " << final_offset_ps_negative_0 << ", BGCorrection_tick: " << BGCorrection_tick << ", TSCorrection_tick: " << TSCorrection_tick << endl; @@ -1388,4 +1388,4 @@ void LAPPDLoadStore::LoadRunInfo() } if (LAPPDStoreReadInVerbosity > 0) cout << "LAPPDStoreReadIn, Loaded run info, runNumber: " << runNumber << ", subRunNumber: " << subRunNumber << ", partFileNumber: " << partFileNumber << ", eventNumberInPF: " << eventNumberInPF << endl; -} \ No newline at end of file +} From 15561850b882ff976aa3e7bb30ac0c63463168a0 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 26 Jun 2024 15:01:42 -0500 Subject: [PATCH 066/163] Update ToolsConfig Add SaveConfig Tool to save the configuration files to the ProcessedData --- configfiles/EventBuilderV2/ToolsConfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configfiles/EventBuilderV2/ToolsConfig b/configfiles/EventBuilderV2/ToolsConfig index e6fcaa2bf..007d55c76 100644 --- a/configfiles/EventBuilderV2/ToolsConfig +++ b/configfiles/EventBuilderV2/ToolsConfig @@ -16,6 +16,9 @@ EBTriggerGrouper EBTriggerGrouper ./configfiles/EventBuilderV2/EBTriggerGrouperC EBPMT EBPMT ./configfiles/EventBuilderV2/EBPMTConfig EBMRD EBMRD ./configfiles/EventBuilderV2/EBMRDConfig EBLAPPD EBLAPPD ./configfiles/EventBuilderV2/EBLAPPDConfig + +SaveConfigInfo SaveConfigInfo ./configfiles/EventBuilderV2/SaveConfigInfoConfig + EBSaver EBSaver ./configfiles/EventBuilderV2/EBSaverConfig From 80fcdc8f2f046c6302e3d044a782891541186c54 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 26 Jun 2024 15:03:48 -0500 Subject: [PATCH 067/163] Add files via upload Add SaveConfigInfo configuration file - FullDepth = 0 set to just save the configuration files and not all the .csv or other files that are linked. When = 1 was set, it was grabbing non-human readable text from I think root files. --- configfiles/EventBuilderV2/SaveConfigInfoConfig | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 configfiles/EventBuilderV2/SaveConfigInfoConfig diff --git a/configfiles/EventBuilderV2/SaveConfigInfoConfig b/configfiles/EventBuilderV2/SaveConfigInfoConfig new file mode 100644 index 000000000..569dcf758 --- /dev/null +++ b/configfiles/EventBuilderV2/SaveConfigInfoConfig @@ -0,0 +1,3 @@ +verbosity 5 +OutFileName config_info.txt +FullDepth 0 From bd9559e1ce669d1b0065ec50e36e8966b9d92e13 Mon Sep 17 00:00:00 2001 From: Yue Date: Fri, 28 Jun 2024 12:09:24 -0500 Subject: [PATCH 068/163] Add ANNIEEventTreeMaker, save all information of ANNIEEvent to one root tree. Add it to BeamClusterAnalysis tool chain Add PMT cluster only filter option to ProcessedLAPPDFilter Changes to be committed: modified: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp modified: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h modified: UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp modified: UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp modified: UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.h new file: configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig modified: configfiles/BeamClusterAnalysis/ToolsConfig modified: configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig modified: configfiles/LAPPDProcessedFilter/ToolsConfig modified: configfiles/PreProcessTrigOverlap/CreateMyList.sh --- .../ANNIEEventTreeMaker.cpp | 2208 ++++++++++++++++- .../ANNIEEventTreeMaker/ANNIEEventTreeMaker.h | 493 +++- UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp | 4 +- .../ProcessedLAPPDFilter.cpp | 58 +- .../ProcessedLAPPDFilter.h | 5 + .../ANNIEEventTreeMakerConfig | 28 + configfiles/BeamClusterAnalysis/ToolsConfig | 4 +- .../ProcessedLAPPDFilterConfig | 4 + configfiles/LAPPDProcessedFilter/ToolsConfig | 2 +- .../PreProcessTrigOverlap/CreateMyList.sh | 12 +- 10 files changed, 2766 insertions(+), 52 deletions(-) create mode 100644 configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig mode change 100755 => 100644 configfiles/PreProcessTrigOverlap/CreateMyList.sh diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index 6953925f6..a3e01236a 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -1,28 +1,2220 @@ #include "ANNIEEventTreeMaker.h" -ANNIEEventTreeMaker::ANNIEEventTreeMaker():Tool(){} +ANNIEEventTreeMaker::ANNIEEventTreeMaker() : Tool() {} - -bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data){ +bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) +{ /////////////////// Useful header /////////////////////// - if(configfile!="") m_variables.Initialise(configfile); // loading config file - //m_variables.Print(); + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); - m_data= &data; //assigning transient data pointer + m_data = &data; // assigning transient data pointer ///////////////////////////////////////////////////////////////// + m_variables.Get("ANNIEEventTreeMakerVerbosity", ANNIEEventTreeMakerVerbosity); + m_variables.Get("isData", isData); + m_variables.Get("HasGenie", hasGenie); + + fillAllTriggers = true; + m_variables.Get("fillAllTriggers", fillAllTriggers); + fill_singleTrigger = true; + m_variables.Get("fill_singleTrigger", fill_singleTrigger); + fill_singleTriggerWord = 14; + m_variables.Get("fill_singleTriggerWord", fill_singleTriggerWord); + fill_TriggerWord = {14, 47}; + + m_variables.Get("fillCleanEventsOnly", fillCleanEventsOnly); + m_variables.Get("fillLAPPDEventsOnly", fillLAPPDEventsOnly); + + m_variables.Get("TankHitInfo_fill", TankHitInfo_fill); + m_variables.Get("TankCluster_fill", TankCluster_fill); + m_variables.Get("cluster_TankHitInfo_fill", cluster_TankHitInfo_fill); + m_variables.Get("MRDHitInfo_fill", MRDHitInfo_fill); + + m_variables.Get("MCTruth_fill", MCTruth_fill); + m_variables.Get("MRDReco_fill", MRDReco_fill); + m_variables.Get("TankReco_fill", TankReco_fill); + m_variables.Get("RecoDebug_fill", RecoDebug_fill); + m_variables.Get("muonTruthRecoDiff_fill", muonTruthRecoDiff_fill); + m_variables.Get("LAPPDData_fill", LAPPDData_fill); + m_variables.Get("SiPMPulseInfo_fill", SiPMPulseInfo_fill); + m_variables.Get("LAPPDReco_fill", LAPPDReco_fill); + + std::string output_filename = "ANNIEEventTree.root"; + m_variables.Get("OutputFile", output_filename); + fOutput_tfile = new TFile(output_filename.c_str(), "recreate"); + fANNIETree = new TTree("Event", "ANNIE Phase II Event Tree"); + + m_data->CStore.Get("AuxChannelNumToTypeMap", AuxChannelNumToTypeMap); + m_data->CStore.Get("ChannelNumToTankPMTSPEChargeMap", ChannelKeyToSPEMap); + m_data->CStore.Get("pmt_tubeid_to_channelkey_data", pmtid_to_channelkey); + m_data->CStore.Get("channelkey_to_pmtid", channelkey_to_pmtid); + m_data->CStore.Get("channelkey_to_mrdpmtid", channelkey_to_mrdpmtid); + m_data->CStore.Get("mrdpmtid_to_channelkey_data", mrdpmtid_to_channelkey_data); + m_data->CStore.Get("channelkey_to_faccpmtid", channelkey_to_faccpmtid); + + auto get_geometry = m_data->Stores.at("ANNIEEvent")->Header->Get("AnnieGeometry", geom); + if (!get_geometry) + { + Log("ANNIEEventTreeMaker Tool: Error retrieving Geometry from ANNIEEvent!", v_error, ANNIEEventTreeMakerVerbosity); + return false; + } + + // general information in an event + fANNIETree->Branch("runNumber", &fRunNumber, "runNumber/I"); + fANNIETree->Branch("subrunNumber", &fSubrunNumber, "subrunNumber/I"); + fANNIETree->Branch("partFileNumber", &fPartFileNumber, "partFileNumber/I"); + fANNIETree->Branch("runType", &fRunType, "runType/I"); + fANNIETree->Branch("eventNumber", &fEventNumber, "eventNumber/I"); // + fANNIETree->Branch("PrimaryTriggerWord", &fPrimaryTriggerWord, "PrimaryTriggerWord/I"); + fANNIETree->Branch("GroupedTriggerTime", &fGroupedTriggerTime); + fANNIETree->Branch("GroupedTriggerWord", &fGroupedTriggerWord); + fANNIETree->Branch("trigword", &fTriggerword, "trigword/I"); // keep for trigger 5 or 14 + + // flags from event selector + fANNIETree->Branch("Extended", &fExtended, "Extended/I"); + fANNIETree->Branch("HasTank", &fHasTank, "HasTank/I"); + fANNIETree->Branch("HasMRD", &fHasMRD, "HasMRD/I"); + fANNIETree->Branch("HasLAPPD", &fHasLAPPD, "HasLAPPD/I"); + fANNIETree->Branch("TankMRDCoinc", &fTankMRDCoinc, "TankMRDCoinc/I"); + fANNIETree->Branch("NoVeto", &fNoVeto, "NoVeto/I"); + + // event information of data + fANNIETree->Branch("eventTimeTank", &fEventTimeTank, "eventTimeTank/l"); + fANNIETree->Branch("eventTimeMRD", &fEventTimeMRD, "eventTimeMRD/l"); + + // beam information + if (BeamInfo_fill) + { + fANNIETree->Branch("beam_pot_875", &fPot, "beam_pot_875/D"); + fANNIETree->Branch("beam_ok", &fBeamok, "beam_ok/I"); + fANNIETree->Branch("beam_E_TOR860", &beam_E_TOR860, "beam_E_TOR860/D"); + fANNIETree->Branch("beam_E_TOR875", &beam_E_TOR875, "beam_E_TOR875/D"); + fANNIETree->Branch("beam_THCURR", &beam_THCURR, "beam_THCURR/D"); + fANNIETree->Branch("beam_BTJT2", &beam_BTJT2, "beam_BTJT2/D"); + fANNIETree->Branch("beam_HP875", &beam_HP875, "beam_HP875/D"); + fANNIETree->Branch("beam_VP875", &beam_VP875, "beam_VP875/D"); + fANNIETree->Branch("beam_HPTG1", &beam_HPTG1, "beam_HPTG1/D"); + fANNIETree->Branch("beam_VPTG1", &beam_VPTG1, "beam_VPTG1/D"); + fANNIETree->Branch("beam_HPTG2", &beam_HPTG2, "beam_HPTG2/D"); + fANNIETree->Branch("beam_VPTG2", &beam_VPTG2, "beam_VPTG2/D"); + fANNIETree->Branch("beam_BTH2T2", &beam_BTH2T2, "beam_BTH2T2/D"); + fANNIETree->Branch("BeamInfoTime", &fBeamInfoTime, "BeamInfoTime/l"); + fANNIETree->Branch("BeamInfoTimeToTriggerDiff", &fBeamInfoTimeToTriggerDiff, "BeamInfoTimeToTriggerDiff/G"); + } + + //********************************************************// + + // Tank cluster information + + fANNIETree->Branch("numberOfClusters", &fNumberOfClusters, "fNumberOfClusters/I"); + fANNIETree->Branch("clusterTime", &fClusterTimeV); + fANNIETree->Branch("clusterCharge", &fClusterChargeV); + fANNIETree->Branch("clusterPE", &fClusterPEV); + fANNIETree->Branch("clusterMaxPE", &fClusterMaxPEV); + fANNIETree->Branch("clusterChargePointX", &fClusterChargePointXV); + fANNIETree->Branch("clusterChargePointY", &fClusterChargePointYV); + fANNIETree->Branch("clusterChargePointZ", &fClusterChargePointZV); + fANNIETree->Branch("clusterChargeBalance", &fClusterChargeBalanceV); + fANNIETree->Branch("clusterHits", &fClusterHits); + + // MRD cluster information + fANNIETree->Branch("eventTimeMRD", &fEventTimeMRD_Tree); + fANNIETree->Branch("MRDClusterNumber", &fMRDClusterNumber); + fANNIETree->Branch("MRDClusterTime", &fMRDClusterTime); + fANNIETree->Branch("MRDClusterTimeSigma", &fMRDClusterTimeSigma); + fANNIETree->Branch("MRDClusterHits", &fMRDClusterHits); + + if (TankHitInfo_fill) + { + // Tank Hit information + fANNIETree->Branch("nhits", &fNHits, "nhits/I"); + fANNIETree->Branch("filter", &fIsFiltered); + fANNIETree->Branch("hitX", &fHitX); + fANNIETree->Branch("hitY", &fHitY); + fANNIETree->Branch("hitZ", &fHitZ); + fANNIETree->Branch("hitT", &fHitT); + fANNIETree->Branch("hitQ", &fHitQ); + fANNIETree->Branch("hitPE", &fHitPE); + fANNIETree->Branch("hitType", &fHitType); + fANNIETree->Branch("hitDetID", &fHitDetID); + fANNIETree->Branch("hitChankey", &fHitChankey); + fANNIETree->Branch("hitChankeyMC", &fHitChankeyMC); + } + + if (SiPMPulseInfo_fill) + { + fANNIETree->Branch("SiPMhitQ", &fSiPMHitQ); + fANNIETree->Branch("SiPMhitT", &fSiPMHitT); + fANNIETree->Branch("SiPMhitAmplitude", &fSiPMHitAmplitude); + fANNIETree->Branch("SiPMNum", &fSiPMNum); + fANNIETree->Branch("SiPM1NPulses", &fSiPM1NPulses, "SiPM1NPulses/I"); + fANNIETree->Branch("SiPM2NPulses", &fSiPM2NPulses, "SiPM2NPulses/I"); + } + + if (LAPPDData_fill) + { + fANNIETree->Branch("LAPPD_ID", &fLAPPD_ID); + fANNIETree->Branch("fLAPPD_Count", &fLAPPD_Count); + fANNIETree->Branch("LAPPD_Beamgate_ns", &fLAPPD_Beamgate_ns); + fANNIETree->Branch("LAPPD_Timestamp_ns", &fLAPPD_Timestamp_ns); + fANNIETree->Branch("LAPPD_Beamgate_Raw", &fLAPPD_Beamgate_Raw); + fANNIETree->Branch("LAPPD_Timestamp_Raw", &fLAPPD_Timestamp_Raw); + fANNIETree->Branch("LAPPD_Offset", &fLAPPD_Offset); + fANNIETree->Branch("LAPPD_TSCorrection", &fLAPPD_TSCorrection); + fANNIETree->Branch("LAPPD_BGCorrection", &fLAPPD_BGCorrection); + fANNIETree->Branch("LAPPD_OSInMinusPS", &fLAPPD_OSInMinusPS); + } + + // LAPPD reconstruction information + if (LAPPDReco_fill) + { + // fANNIETree->Branch("LAPPDPulseTimeStampUL", &fLAPPDPulseTimeStampUL, "LAPPDPulseTimeStampUL/l"); + // fANNIETree->Branch("LAPPDPulseBeamgateUL", &fLAPPDPulseBeamgateUL, "LAPPDPulseBeamgateUL/l"); + // actually we don't need these two for pulse and hit, because it is impossible to have multiple events from one LAPPD in one ANNIEEvent due to the dead time and the trigger scheme + // LAPPD ID is enough to find the corresponding unix timestamp + // but leave them there in case + + fANNIETree->Branch("LAPPD_PulseIDs", &fLAPPD_IDs); + fANNIETree->Branch("LAPPD_ChannelID", &fChannelID); + fANNIETree->Branch("LAPPD_PeakTime", &fPulsePeakTime); + fANNIETree->Branch("LAPPD_PeakAmp", &fPulsePeakAmp); + fANNIETree->Branch("LAPPD_Charge", &fPulseCharge); + fANNIETree->Branch("LAPPD_PulseStart", &fPulseStart); + fANNIETree->Branch("LAPPD_PulseEnd", &fPulseEnd); + fANNIETree->Branch("LAPPD_PulseWidth", &fPulseWidth); + fANNIETree->Branch("LAPPD_PulseSide", &fPulseSide); + fANNIETree->Branch("LAPPD_PulseStripNum", &fPulseStripNum); + + // fANNIETree->Branch("LAPPDHitTimeStampUL", &fLAPPDHitTimeStampUL, "LAPPDHitTimeStampUL/l"); + // fANNIETree->Branch("LAPPDHitBeamgateUL", &fLAPPDHitBeamgateUL, "LAPPDHitBeamgateUL/l"); + + fANNIETree->Branch("LAPPDID_Hit", &fLAPPDHit_IDs); + fANNIETree->Branch("LAPPDHitChannel", &fLAPPDHitChannel); + fANNIETree->Branch("LAPPDHitStrip", &fLAPPDHitStrip); + fANNIETree->Branch("LAPPDHitTime", &fLAPPDHitTime); + fANNIETree->Branch("LAPPDHitAmp", &fLAPPDHitAmp); + fANNIETree->Branch("LAPPDHitParallelPos", &fLAPPDHitParallelPos); + fANNIETree->Branch("LAPPDHitTransversePos", &fLAPPDHitTransversePos); + fANNIETree->Branch("LAPPDHitP1StartTime", &fLAPPDHitP1StartTime); + fANNIETree->Branch("LAPPDHitP2StartTime", &fLAPPDHitP2StartTime); + fANNIETree->Branch("LAPPDHitP1EndTime", &fLAPPDHitP1EndTime); + fANNIETree->Branch("LAPPDHitP2EndTime", &fLAPPDHitP2EndTime); + + /* + fANNIETree->Branch("LAPPDWaveformChankey", &LAPPDWaveformChankey, "LAPPDWaveformChankey/I"); + fANNIETree->Branch("WaveformMax", &waveformMaxValue, "WaveformMax/D"); + fANNIETree->Branch("WaveformRMS", &waveformRMSValue, "WaveformRMS/D"); + fANNIETree->Branch("WaveformMaxTimeBin", &waveformMaxTimeBinValue, "WaveformMaxTimeBin/I"); + fANNIETree->Branch("waveformMaxFoundNear", &waveformMaxFoundNear, "waveformMaxFoundNear/O"); // O is boolean + fANNIETree->Branch("WaveformMaxNearing", &waveformMaxNearingValue, "WaveformMaxNearing/D"); + */ + } + + if (MRDHitInfo_fill) + { + fANNIETree->Branch("MRDhitT", &fMRDHitT); + fANNIETree->Branch("MRDhitDetID", &fMRDHitDetID); + fANNIETree->Branch("MRDhitChankey", &fMRDHitChankey); + fANNIETree->Branch("MRDhitChankeyMC", &fMRDHitChankeyMC); + fANNIETree->Branch("FMVhitT", &fFMVHitT); + fANNIETree->Branch("FMVhitDetID", &fFMVHitDetID); + fANNIETree->Branch("FMVhitChankey", &fFMVHitChankey); + fANNIETree->Branch("FMVhitChankeyMC", &fFMVHitChankeyMC); + fANNIETree->Branch("vetoHit", &fVetoHit, "vetoHit/I"); + } + + if (MRDReco_fill) + { + fANNIETree->Branch("fMRDClusterIndex", &fMRDClusterIndex); + fANNIETree->Branch("NumClusterTracks", &fNumClusterTracks); + fANNIETree->Branch("MRDTrackAngle", &fMRDTrackAngle); + fANNIETree->Branch("MRDTrackAngleError", &fMRDTrackAngleError); + fANNIETree->Branch("MRDPenetrationDepth", &fMRDPenetrationDepth); + fANNIETree->Branch("MRDTrackLength", &fMRDTrackLength); + fANNIETree->Branch("MRDEntryPointRadius", &fMRDEntryPointRadius); + fANNIETree->Branch("MRDEnergyLoss", &fMRDEnergyLoss); + fANNIETree->Branch("MRDEnergyLossError", &fMRDEnergyLossError); + fANNIETree->Branch("MRDTrackStartX", &fMRDTrackStartX); + fANNIETree->Branch("MRDTrackStartY", &fMRDTrackStartY); + fANNIETree->Branch("MRDTrackStartZ", &fMRDTrackStartZ); + fANNIETree->Branch("MRDTrackStopX", &fMRDTrackStopX); + fANNIETree->Branch("MRDTrackStopY", &fMRDTrackStopY); + fANNIETree->Branch("MRDTrackStopZ", &fMRDTrackStopZ); + fANNIETree->Branch("MRDSide", &fMRDSide); + fANNIETree->Branch("MRDStop", &fMRDStop); + fANNIETree->Branch("MRDThrough", &fMRDThrough); + } + + if (fillCleanEventsOnly) + { + fANNIETree->Branch("eventStatusApplied", &fEventStatusApplied, "eventStatusApplied/I"); + fANNIETree->Branch("eventStatusFlagged", &fEventStatusFlagged, "eventStatusFlagged/I"); + } + + // MC truth information for muons + // Output to tree when MCTruth_fill = 1 in config + if (MCTruth_fill) + { + fTrueNeutCapVtxX = new std::vector; + fTrueNeutCapVtxY = new std::vector; + fTrueNeutCapVtxZ = new std::vector; + fTrueNeutCapNucleus = new std::vector; + fTrueNeutCapTime = new std::vector; + fTrueNeutCapGammas = new std::vector; + fTrueNeutCapE = new std::vector; + fTrueNeutCapGammaE = new std::vector; + fTruePrimaryPdgs = new std::vector; + fANNIETree->Branch("triggerNumber", &fiMCTriggerNum, "triggerNumber/I"); + fANNIETree->Branch("mcEntryNumber", &fMCEventNum, "mcEntryNumber/I"); + fANNIETree->Branch("trueVtxX", &fTrueVtxX, "trueVtxX/D"); + fANNIETree->Branch("trueVtxY", &fTrueVtxY, "trueVtxY/D"); + fANNIETree->Branch("trueVtxZ", &fTrueVtxZ, "trueVtxZ/D"); + fANNIETree->Branch("trueVtxTime", &fTrueVtxTime, "trueVtxTime/D"); + fANNIETree->Branch("trueDirX", &fTrueDirX, "trueDirX/D"); + fANNIETree->Branch("trueDirY", &fTrueDirY, "trueDirY/D"); + fANNIETree->Branch("trueDirZ", &fTrueDirZ, "trueDirZ/D"); + fANNIETree->Branch("trueAngle", &fTrueAngle, "trueAngle/D"); + fANNIETree->Branch("truePhi", &fTruePhi, "truePhi/D"); + fANNIETree->Branch("trueMuonEnergy", &fTrueMuonEnergy, "trueMuonEnergy/D"); + fANNIETree->Branch("truePrimaryPdg", &fTruePrimaryPdg, "truePrimaryPdg/I"); + fANNIETree->Branch("trueTrackLengthInWater", &fTrueTrackLengthInWater, "trueTrackLengthInWater/D"); + fANNIETree->Branch("trueTrackLengthInMRD", &fTrueTrackLengthInMRD, "trueTrackLengthInMRD/D"); + fANNIETree->Branch("trueMultiRing", &fTrueMultiRing, "trueMultiRing/I"); + fANNIETree->Branch("Pi0Count", &fPi0Count, "Pi0Count/I"); + fANNIETree->Branch("PiPlusCount", &fPiPlusCount, "PiPlusCount/I"); + fANNIETree->Branch("PiMinusCount", &fPiMinusCount, "PiMinusCount/I"); + fANNIETree->Branch("K0Count", &fK0Count, "K0Count/I"); + fANNIETree->Branch("KPlusCount", &fKPlusCount, "KPlusCount/I"); + fANNIETree->Branch("KMinusCount", &fKMinusCount, "KMinusCount/I"); + fANNIETree->Branch("truePrimaryPdgs", &fTruePrimaryPdgs); + fANNIETree->Branch("trueNeutCapVtxX", &fTrueNeutCapVtxX); + fANNIETree->Branch("trueNeutCapVtxY", &fTrueNeutCapVtxY); + fANNIETree->Branch("trueNeutCapVtxZ", &fTrueNeutCapVtxZ); + fANNIETree->Branch("trueNeutCapNucleus", &fTrueNeutCapNucleus); + fANNIETree->Branch("trueNeutCapTime", &fTrueNeutCapTime); + fANNIETree->Branch("trueNeutCapGammas", &fTrueNeutCapGammas); + fANNIETree->Branch("trueNeutCapE", &fTrueNeutCapE); + fANNIETree->Branch("trueNeutCapGammaE", &fTrueNeutCapGammaE); + fANNIETree->Branch("trueNeutrinoEnergy", &fTrueNeutrinoEnergy, "trueNeutrinoEnergy/D"); + fANNIETree->Branch("trueNeutrinoMomentum_X", &fTrueNeutrinoMomentum_X, "trueNeutrinoMomentum_X/D"); + fANNIETree->Branch("trueNeutrinoMomentum_Y", &fTrueNeutrinoMomentum_Y, "trueNeutrinoMomentum_Y/D"); + fANNIETree->Branch("trueNeutrinoMomentum_Z", &fTrueNeutrinoMomentum_Z, "trueNeutrinoMomentum_Z/D"); + fANNIETree->Branch("trueNuIntxVtx_X", &fTrueNuIntxVtx_X, "trueNuIntxVtx_X/D"); + fANNIETree->Branch("trueNuIntxVtx_Y", &fTrueNuIntxVtx_Y, "trueNuIntxVtx_Y/D"); + fANNIETree->Branch("trueNuIntxVtx_Z", &fTrueNuIntxVtx_Z, "trueNuIntxVtx_Z/D"); + fANNIETree->Branch("trueNuIntxVtx_T", &fTrueNuIntxVtx_T, "trueNuIntxVtx_T/D"); + fANNIETree->Branch("trueFSLVtx_X", &fTrueFSLVtx_X, "trueFSLVtx_X/D"); + fANNIETree->Branch("trueFSLVtx_Y", &fTrueFSLVtx_Y, "trueFSLVtx_Y/D"); + fANNIETree->Branch("trueFSLVtx_Z", &fTrueFSLVtx_Z, "trueFSLVtx_Z/D"); + fANNIETree->Branch("trueFSLMomentum_X", &fTrueFSLMomentum_X, "trueFSLMomentum_X/D"); + fANNIETree->Branch("trueFSLMomentum_Y", &fTrueFSLMomentum_Y, "trueFSLMomentum_Y/D"); + fANNIETree->Branch("trueFSLMomentum_Z", &fTrueFSLMomentum_Z, "trueFSLMomentum_Z/D"); + fANNIETree->Branch("trueFSLTime", &fTrueFSLTime, "trueFSLTime/D"); + fANNIETree->Branch("trueFSLMass", &fTrueFSLMass, "trueFSLMass/D"); + fANNIETree->Branch("trueFSLPdg", &fTrueFSLPdg, "trueFSLPdg/I"); + fANNIETree->Branch("trueFSLEnergy", &fTrueFSLEnergy, "trueFSLEnergy/D"); + fANNIETree->Branch("trueQ2", &fTrueQ2, "trueQ2/D"); + fANNIETree->Branch("trueCC", &fTrueCC, "trueCC/I"); + fANNIETree->Branch("trueNC", &fTrueNC, "trueNC/I"); + fANNIETree->Branch("trueQEL", &fTrueQEL, "trueQEL/I"); + fANNIETree->Branch("trueRES", &fTrueRES, "trueRES/I"); + fANNIETree->Branch("trueDIS", &fTrueDIS, "trueDIS/I"); + fANNIETree->Branch("trueCOH", &fTrueCOH, "trueCOH/I"); + fANNIETree->Branch("trueMEC", &fTrueMEC, "trueMEC/I"); + fANNIETree->Branch("trueNeutrons", &fTrueNeutrons, "trueNeutrons/I"); + fANNIETree->Branch("trueProtons", &fTrueProtons, "trueProtons/I"); + fANNIETree->Branch("truePi0", &fTruePi0, "truePi0/I"); + fANNIETree->Branch("truePiPlus", &fTruePiPlus, "truePiPlus/I"); + fANNIETree->Branch("truePiPlusCher", &fTruePiPlusCher, "truePiPlusCher/I"); + fANNIETree->Branch("truePiMinus", &fTruePiMinus, "truePiMinus/I"); + fANNIETree->Branch("truePiMinusCher", &fTruePiMinusCher, "truePiMinusCher/I"); + fANNIETree->Branch("trueKPlus", &fTrueKPlus, "trueKPlus/I"); + fANNIETree->Branch("trueKPlusCher", &fTrueKPlusCher, "trueKPlusCher/I"); + fANNIETree->Branch("trueKMinus", &fTrueKMinus, "trueKMinus/I"); + fANNIETree->Branch("trueKMinusCher", &fTrueKMinusCher, "trueKMinusCher/I"); + } + + // Reconstructed variables after full Muon Reco Analysis + if (TankReco_fill) + { + fANNIETree->Branch("recoVtxX", &fRecoVtxX, "recoVtxX/D"); + fANNIETree->Branch("recoVtxY", &fRecoVtxY, "recoVtxY/D"); + fANNIETree->Branch("recoVtxZ", &fRecoVtxZ, "recoVtxZ/D"); + fANNIETree->Branch("recoVtxTime", &fRecoVtxTime, "recoVtxTime/D"); + fANNIETree->Branch("recoDirX", &fRecoDirX, "recoDirX/D"); + fANNIETree->Branch("recoDirY", &fRecoDirY, "recoDirY/D"); + fANNIETree->Branch("recoDirZ", &fRecoDirZ, "recoDirZ/D"); + fANNIETree->Branch("recoAngle", &fRecoAngle, "recoAngle/D"); + fANNIETree->Branch("recoPhi", &fRecoPhi, "recoPhi/D"); + fANNIETree->Branch("recoVtxFOM", &fRecoVtxFOM, "recoVtxFOM/D"); + fANNIETree->Branch("recoStatus", &fRecoStatus, "recoStatus/I"); + } + + // Reconstructed variables from each step in Muon Reco Analysis + // Currently output when RecoDebug_fill = 1 in config + if (RecoDebug_fill) + { + fANNIETree->Branch("seedVtxX", &fSeedVtxX); + fANNIETree->Branch("seedVtxY", &fSeedVtxY); + fANNIETree->Branch("seedVtxZ", &fSeedVtxZ); + fANNIETree->Branch("seedVtxFOM", &fSeedVtxFOM); + fANNIETree->Branch("seedVtxTime", &fSeedVtxTime, "seedVtxTime/D"); + + fANNIETree->Branch("pointPosX", &fPointPosX, "pointPosX/D"); + fANNIETree->Branch("pointPosY", &fPointPosY, "pointPosY/D"); + fANNIETree->Branch("pointPosZ", &fPointPosZ, "pointPosZ/D"); + fANNIETree->Branch("pointPosTime", &fPointPosTime, "pointPosTime/D"); + fANNIETree->Branch("pointPosFOM", &fPointPosFOM, "pointPosFOM/D"); + fANNIETree->Branch("pointPosStatus", &fPointPosStatus, "pointPosStatus/I"); + + fANNIETree->Branch("pointDirX", &fPointDirX, "pointDirX/D"); + fANNIETree->Branch("pointDirY", &fPointDirY, "pointDirY/D"); + fANNIETree->Branch("pointDirZ", &fPointDirZ, "pointDirZ/D"); + fANNIETree->Branch("pointDirTime", &fPointDirTime, "pointDirTime/D"); + fANNIETree->Branch("pointDirStatus", &fPointDirStatus, "pointDirStatus/I"); + fANNIETree->Branch("pointDirFOM", &fPointDirFOM, "pointDirFOM/D"); + + fANNIETree->Branch("pointVtxPosX", &fPointVtxPosX, "pointVtxPosX/D"); + fANNIETree->Branch("pointVtxPosY", &fPointVtxPosY, "pointVtxPosY/D"); + fANNIETree->Branch("pointVtxPosZ", &fPointVtxPosZ, "pointVtxPosZ/D"); + fANNIETree->Branch("pointVtxTime", &fPointVtxTime, "pointVtxTime/D"); + fANNIETree->Branch("pointVtxDirX", &fPointVtxDirX, "pointVtxDirX/D"); + fANNIETree->Branch("pointVtxDirY", &fPointVtxDirY, "pointVtxDirY/D"); + fANNIETree->Branch("pointVtxDirZ", &fPointVtxDirZ, "pointVtxDirZ/D"); + fANNIETree->Branch("pointVtxFOM", &fPointVtxFOM, "pointVtxFOM/D"); + fANNIETree->Branch("pointVtxStatus", &fPointVtxStatus, "pointVtxStatus/I"); + } + + // Difference in MC Truth and Muon Reconstruction Analysis + // Output to tree when muonTruthRecoDiff_fill = 1 in config + if (muonTruthRecoDiff_fill) + { + fANNIETree->Branch("deltaVtxX", &fDeltaVtxX, "deltaVtxX/D"); + fANNIETree->Branch("deltaVtxY", &fDeltaVtxY, "deltaVtxY/D"); + fANNIETree->Branch("deltaVtxZ", &fDeltaVtxZ, "deltaVtxZ/D"); + fANNIETree->Branch("deltaVtxR", &fDeltaVtxR, "deltaVtxR/D"); + fANNIETree->Branch("deltaVtxT", &fDeltaVtxT, "deltaVtxT/D"); + fANNIETree->Branch("deltaParallel", &fDeltaParallel, "deltaParallel/D"); + fANNIETree->Branch("deltaPerpendicular", &fDeltaPerpendicular, "deltaPerpendicular/D"); + fANNIETree->Branch("deltaAzimuth", &fDeltaAzimuth, "deltaAzimuth/D"); + fANNIETree->Branch("deltaZenith", &fDeltaZenith, "deltaZenith/D"); + fANNIETree->Branch("deltaAngle", &fDeltaAngle, "deltaAngle/D"); + } + return true; } +bool ANNIEEventTreeMaker::Execute() +{ + //****************************** Reset Variables *************************************// + ResetVariables(); + + //****************************** fillCleanEventsOnly *************************************// + // If only clean events are built, return true for dirty events + if (fillCleanEventsOnly) + { + auto get_flagsapp = m_data->Stores.at("RecoEvent")->Get("EventFlagApplied", fEventStatusApplied); + auto get_flags = m_data->Stores.at("RecoEvent")->Get("EventFlagged", fEventStatusFlagged); + // auto get_cutstatus = m_data->Stores.at("RecoEvent")->Get("EventCutStatus",fEventCutStatus); + if (!get_flagsapp || !get_flags) + { + Log("PhaseITreeMaker tool: No Event status applied or flagged bitmask!!", v_error, ANNIEEventTreeMakerVerbosity); + return false; + } + // check if event passes the cut + if ((fEventStatusFlagged) != 0) + { + // if (!fEventCutStatus){ + Log("ANNIEEventTreeMaker Tool: Event was flagged with one of the active cuts.", v_debug, ANNIEEventTreeMakerVerbosity); + return true; + } + } + // done + + //****************************** Fill Event Info *************************************// + bool keepLoading = LoadEventInfo(); + if (!keepLoading) + return false; + LoadBeamInfo(); + // done + + //****************************** Fill Hit Info *************************************// + if (TankHitInfo_fill) + { + // this will fill all hits in this event + LoadAllTankHits(); + } + if (SiPMPulseInfo_fill) + { + LoadSiPMHits(); + } + // done + //****************************** Fill Cluster Info *************************************// + if (TankCluster_fill) + { + LoadClusterInfo(); + } + + //****************************** Fill LAPPD Info *************************************// + if (LAPPDData_fill) + { + LoadLAPPDInfo(); + } + + //****************************** Fill MRD Info *************************************// + if (MRDHitInfo_fill) + { + LoadMRDCluster(); + } + + //****************************** Fill Reco Info *************************************// + bool got_reco = false; + if (TankReco_fill) + { + got_reco = FillTankRecoInfo(); + } + + if (RecoDebug_fill) + FillRecoDebugInfo(); + + //****************************** Fill MCTruth Info *************************************// + bool gotmctruth = false; + if (MCTruth_fill) + { + gotmctruth = FillMCTruthInfo(); // todo + } + if (muonTruthRecoDiff_fill) + this->FillTruthRecoDiffInfo(gotmctruth, got_reco); + + //****************************** Fill Reco Summary *************************************// + if (got_reco && gotmctruth && (ANNIEEventTreeMakerVerbosity > 4)) + { + RecoSummary(); + } + + //****************************** Fill Tree *************************************// + fANNIETree->Fill(); + + processedEvents++; + return true; +} -bool ANNIEEventTreeMaker::Execute(){ +bool ANNIEEventTreeMaker::Finalise() +{ + Log("ANNIEEventTreeMaker Tool: Got " + std::to_string(processedEvents) + " events", 0, ANNIEEventTreeMakerVerbosity); + fOutput_tfile->cd(); + fANNIETree->Write(); + fOutput_tfile->Close(); + Log("ANNIEEventTreeMaker Tool: Tree written to file", 0, ANNIEEventTreeMakerVerbosity); return true; } +void ANNIEEventTreeMaker::ResetVariables() +{ + // Reset all variables + + // Event Info + fRunNumber = 0; + fSubrunNumber = 0; + fPartFileNumber = 0; + fEventNumber = 0; + fPrimaryTriggerWord = 0; + fPrimaryTriggerTime = 0; + fTriggerword = 0; + fExtended = 0; + fTankMRDCoinc = 0; + fNoVeto = 0; + fHasTank = 0; + fHasMRD = 0; + fHasLAPPD = 0; + fGroupedTriggerTime.clear(); + fGroupedTriggerWord.clear(); + fDataStreams.clear(); + fEventTimeTank = 0; + fEventTimeMRD = 0; + + // beam info + fPot = -9999; + fBeamok = 0; + beam_E_TOR860 = -9999; + beam_E_TOR875 = -9999; + beam_THCURR = -9999; + beam_BTJT2 = -9999; + beam_HP875 = -9999; + beam_VP875 = -9999; + beam_HPTG1 = -9999; + beam_VPTG1 = -9999; + beam_HPTG2 = -9999; + beam_VPTG2 = -9999; + beam_BTH2T2 = -9999; + fBeamInfoTime = 0; + fBeamInfoTimeToTriggerDiff = -9999; + + // TankHitInfo + fNHits = 0; + fIsFiltered.clear(); + fHitX.clear(); + fHitY.clear(); + fHitZ.clear(); + fHitT.clear(); + fHitQ.clear(); + fHitPE.clear(); + fHitType.clear(); + fHitDetID.clear(); + fHitChankey.clear(); + fHitChankeyMC.clear(); + + // SiPMPulse Info + fSiPM1NPulses = 0; + fSiPM2NPulses = 0; + fSiPMHitQ.clear(); + fSiPMHitT.clear(); + fSiPMHitAmplitude.clear(); + fSiPMNum.clear(); + + // LAPPDData_fill + fLAPPD_Count = 0; + fLAPPD_ID.clear(); + fLAPPD_Beamgate_ns.clear(); + fLAPPD_Timestamp_ns.clear(); + fLAPPD_Beamgate_Raw.clear(); + fLAPPD_Timestamp_Raw.clear(); + fLAPPD_Offset.clear(); + fLAPPD_TSCorrection.clear(); + fLAPPD_BGCorrection.clear(); + fLAPPD_OSInMinusPS.clear(); + + // LAPPD Reco Fill + fLAPPDPulseTimeStampUL.clear(); + fLAPPDPulseBeamgateUL.clear(); + fLAPPD_IDs.clear(); + fChannelID.clear(); + fPulsePeakTime.clear(); + fPulseCharge.clear(); + fPulsePeakAmp.clear(); + fPulseStart.clear(); + fPulseEnd.clear(); + fPulseWidth.clear(); + fPulseSide.clear(); + fPulseStripNum.clear(); + fChannelBaseline.clear(); + + fLAPPDHitTimeStampUL.clear(); + fLAPPDHitBeamgateUL.clear(); + fLAPPDHit_IDs.clear(); + fLAPPDHitChannel.clear(); + fLAPPDHitStrip.clear(); + fLAPPDHitTime.clear(); + fLAPPDHitAmp.clear(); + fLAPPDHitParallelPos.clear(); + fLAPPDHitTransversePos.clear(); + fLAPPDHitP1StartTime.clear(); + fLAPPDHitP2StartTime.clear(); + fLAPPDHitP1EndTime.clear(); + fLAPPDHitP2EndTime.clear(); + + LAPPDWaveformChankey.clear(); + waveformMaxValue.clear(); + waveformRMSValue.clear(); + waveformMaxFoundNear.clear(); + waveformMaxNearingValue.clear(); + waveformMaxTimeBinValue.clear(); + + // tank cluster information + fNumberOfClusters = 0; + + fClusterHits.clear(); + fClusterChargeV.clear(); + fClusterTimeV.clear(); + fClusterPEV.clear(); + + fCluster_HitX.clear(); + fCluster_HitY.clear(); + fCluster_HitZ.clear(); + fCluster_HitT.clear(); + fCluster_HitQ.clear(); + fCluster_HitPE.clear(); + fCluster_HitType.clear(); + fCluster_HitDetID.clear(); + fCluster_HitChankey.clear(); + fCluster_HitChankeyMC.clear(); + + fClusterMaxPEV.clear(); + fClusterChargePointXV.clear(); + fClusterChargePointYV.clear(); + fClusterChargePointZV.clear(); + fClusterChargeBalanceV.clear(); + + // MRD cluster information + fEventTimeMRD_Tree = 0; + fMRDClusterNumber = 0; + fMRDClusterHits = 0; + fMRDClusterTime = 0; + fMRDClusterTimeSigma = 0; + + fVetoHit = 0; + fMRDHitT.clear(); + fMRDHitDetID.clear(); + fMRDHitChankey.clear(); + fMRDHitChankeyMC.clear(); + fFMVHitT.clear(); + fFMVHitDetID.clear(); + fFMVHitChankey.clear(); + fFMVHitChankeyMC.clear(); + + fNumMRDClusterTracks = 0; + fMRDTrackAngle.clear(); + fMRDTrackAngleError.clear(); + fMRDPenetrationDepth.clear(); + fMRDTrackLength.clear(); + fMRDEntryPointRadius.clear(); + fMRDEnergyLoss.clear(); + fMRDEnergyLossError.clear(); + fMRDTrackStartX.clear(); + fMRDTrackStartY.clear(); + fMRDTrackStartZ.clear(); + fMRDTrackStopX.clear(); + fMRDTrackStopY.clear(); + fMRDTrackStopZ.clear(); + fMRDSide.clear(); + fMRDStop.clear(); + fMRDThrough.clear(); + fMRDClusterIndex.clear(); + fNumClusterTracks.clear(); + + // fillCleanEventsOnly + fEventStatusApplied = 0; + fEventStatusFlagged = 0; + + // MCTruth_fill + if (MCTruth_fill) + { + fMCEventNum = 0; + fMCTriggerNum = 0; + fiMCTriggerNum = -9999; + + fTrueVtxX = -9999; + fTrueVtxY = -9999; + fTrueVtxZ = -9999; + fTrueVtxTime = -9999; + fTrueDirX = -9999; + fTrueDirY = -9999; + fTrueDirZ = -9999; + fTrueAngle = -9999; + fTruePhi = -9999; + fTrueMuonEnergy = -9999; + fTruePrimaryPdg = -9999; + fTrueTrackLengthInWater = -9999; + fTrueTrackLengthInMRD = -9999; + fTruePrimaryPdgs->clear(); + fTrueNeutCapVtxX->clear(); + fTrueNeutCapVtxY->clear(); + fTrueNeutCapVtxZ->clear(); + fTrueNeutCapNucleus->clear(); + fTrueNeutCapTime->clear(); + fTrueNeutCapGammas->clear(); + fTrueNeutCapE->clear(); + fTrueNeutCapGammaE->clear(); + fTrueMultiRing = -9999; + } + + // Genie information for event + fTrueNeutrinoEnergy = -9999; + fTrueNeutrinoMomentum_X = -9999; + fTrueNeutrinoMomentum_Y = -9999; + fTrueNeutrinoMomentum_Z = -9999; + fTrueNuIntxVtx_X = -9999; + fTrueNuIntxVtx_Y = -9999; + fTrueNuIntxVtx_Z = -9999; + fTrueNuIntxVtx_T = -9999; + fTrueFSLVtx_X = -9999; + fTrueFSLVtx_Y = -9999; + fTrueFSLVtx_Z = -9999; + fTrueFSLMomentum_X = -9999; + fTrueFSLMomentum_Y = -9999; + fTrueFSLMomentum_Z = -9999; + fTrueFSLTime = -9999; + fTrueFSLMass = -9999; + fTrueFSLPdg = -9999; + fTrueFSLEnergy = -9999; + fTrueQ2 = -9999; + fTrueCC = -9999; + fTrueNC = -9999; + fTrueQEL = -9999; + fTrueRES = -9999; + fTrueDIS = -9999; + fTrueCOH = -9999; + fTrueMEC = -9999; + fTrueNeutrons = -9999; + fTrueProtons = -9999; + fTruePi0 = -9999; + fTruePiPlus = -9999; + fTruePiPlusCher = -9999; + fTruePiMinus = -9999; + fTruePiMinusCher = -9999; + fTrueKPlus = -9999; + fTrueKPlusCher = -9999; + fTrueKMinus = -9999; + fTrueKMinusCher = -9999; + + // TankReco_fill + fRecoVtxX = -9999; + fRecoVtxY = -9999; + fRecoVtxZ = -9999; + fRecoVtxTime = -9999; + fRecoVtxFOM = -9999; + fRecoDirX = -9999; + fRecoDirY = -9999; + fRecoDirZ = -9999; + fRecoAngle = -9999; + fRecoPhi = -9999; + fRecoStatus = -9999; + + // RecoDebug_fill + fSeedVtxX.clear(); + fSeedVtxY.clear(); + fSeedVtxZ.clear(); + fSeedVtxFOM.clear(); + fSeedVtxTime = -9999; + + // Reco vertex + // Point Position Vertex + fPointVtxPosX = -9999; + fPointVtxPosY = -9999; + fPointVtxPosZ = -9999; + fPointVtxTime = -9999; + fPointPosFOM = -9999; + fPointPosStatus = -9999; + fPointVtxDirX = -9999; + fPointVtxDirY = -9999; + fPointVtxDirZ = -9999; + fPointDirTime = -9999; + fPointDirFOM = -9999; + fPointDirStatus = -9999; + + // Point Vertex Finder + fPointVtxPosX = -9999; + fPointVtxPosY = -9999; + fPointVtxPosZ = -9999; + fPointVtxTime = -9999; + fPointVtxDirX = -9999; + fPointVtxDirY = -9999; + fPointVtxDirZ = -9999; + fPointVtxFOM = -9999; + fPointVtxStatus = -9999; + + // Difference between MC and Truth + fDeltaVtxX = -9999; + fDeltaVtxY = -9999; + fDeltaVtxZ = -9999; + fDeltaVtxR = -9999; + fDeltaVtxT = -9999; + fDeltaParallel = -9999; + fDeltaPerpendicular = -9999; + fDeltaAzimuth = -9999; + fDeltaZenith = -9999; + fDeltaAngle = -9999; + + // Pion and kaon counts for event + fPi0Count = 0; + fPiPlusCount = 0; + fPiMinusCount = 0; + fK0Count = 0; + fKPlusCount = 0; + fKMinusCount = 0; + + // Event Info + fDataStreams.clear(); + GroupedTrigger.clear(); + + // LAPPDData_fill + LAPPDDataMap.clear(); + LAPPDBeamgate_ns.clear(); + LAPPDTimeStamps_ns.clear(); + LAPPDTimeStampsRaw.clear(); + LAPPDBeamgatesRaw.clear(); + LAPPDOffsets.clear(); + LAPPDTSCorrection.clear(); + LAPPDBGCorrection.clear(); + LAPPDOSInMinusPS.clear(); + + // LAPPD Reco Fill + lappdPulses.clear(); + lappdHits.clear(); + + waveformMax.clear(); + waveformRMS.clear(); + waveformMaxLast.clear(); + waveformMaxNearing.clear(); + waveformMaxTimeBin.clear(); +} + +bool ANNIEEventTreeMaker::LoadEventInfo() +{ + Log("ANNIEEventTreeMaker Tool: LoadEventInfo", v_warning, ANNIEEventTreeMakerVerbosity); + m_data->Stores["ANNIEEvent"]->Get("RunNumber", fRunNumber); + m_data->Stores["ANNIEEvent"]->Get("SubRunNumber", fSubrunNumber); + m_data->Stores["ANNIEEvent"]->Get("PartNumber", fPartFileNumber); + m_data->Stores["ANNIEEvent"]->Get("EventNumber", fEventNumber); + m_data->Stores["ANNIEEvent"]->Get("PrimaryTriggerWord", fPrimaryTriggerWord); + if (fPrimaryTriggerWord == 14) + trigword = 5; + else + trigword = fPrimaryTriggerWord; + m_data->Stores["ANNIEEvent"]->Get("PrimaryTriggerTime", fPrimaryTriggerTime); + m_data->Stores["ANNIEEvent"]->Get("GroupedTrigger", GroupedTrigger); + m_data->Stores["ANNIEEvent"]->Get("TriggerWord", fTriggerword); + m_data->Stores["ANNIEEvent"]->Get("TriggerExtended", fExtended); + m_data->Stores["ANNIEEvent"]->Get("DataStreams", fDataStreams); + + bool pmtmrdcoinc, noveto; + m_data->Stores["RecoEvent"]->Get("PMTMRDCoinc", pmtmrdcoinc); + m_data->Stores["RecoEvent"]->Get("NoVeto", noveto); + if (pmtmrdcoinc) + fTankMRDCoinc = 1; + else + fTankMRDCoinc = 0; + + if (noveto) + fNoVeto = 1; + else + fNoVeto = 0; + + if (fDataStreams["Tank"] == 1) + fHasTank = 1; + else + fHasTank = 0; + + if (fDataStreams["MRD"] == 1) + fHasMRD = 1; + else + fHasMRD = 0; + + if (fDataStreams["LAPPD"] == 1) + fHasLAPPD = 1; + else + fHasLAPPD = 0; + + for (std::map::iterator it = GroupedTrigger.begin(); it != GroupedTrigger.end(); ++it) + { + uint64_t key = it->first; + uint32_t value = it->second; + + fGroupedTriggerTime.push_back(key); + fGroupedTriggerWord.push_back(value); + } + + bool gotETT = m_data->Stores["ANNIEEvent"]->Get("EventTimeTank", fEventTimeTank); + if (!gotETT) + fEventTimeTank = 0; + + TimeClass tm; + bool gotETMRD = m_data->Stores["ANNIEEvent"]->Get("EventTimeMRD", tm); + fEventTimeMRD = (ULong64_t)tm.GetNs(); + + if (!gotETMRD) + fEventTimeMRD = 0; + + + if (fillAllTriggers) + return true; + else if (fill_singleTrigger) + { + if (fPrimaryTriggerWord == fill_singleTriggerWord) + return true; + else + return false; + } + else if (fill_TriggerWord.size() > 0) + { + for (auto trig : fill_TriggerWord) + { + if (fPrimaryTriggerWord == trig) + return true; + } + return false; + } + else + return true; + +} + +void ANNIEEventTreeMaker::LoadBeamInfo() +{ + Log("ANNIEEventTreeMaker Tool: LoadBeamInfo", v_debug, ANNIEEventTreeMakerVerbosity); -bool ANNIEEventTreeMaker::Finalise(){ + m_data->Stores["ANNIEEvent"]->Get("beam_E_TOR860", beam_E_TOR860); + m_data->Stores["ANNIEEvent"]->Get("beam_E_TOR875", beam_E_TOR875); + m_data->Stores["ANNIEEvent"]->Get("beam_THCURR", beam_THCURR); + m_data->Stores["ANNIEEvent"]->Get("beam_BTJT2", beam_BTJT2); + m_data->Stores["ANNIEEvent"]->Get("beam_HP875", beam_HP875); + m_data->Stores["ANNIEEvent"]->Get("beam_VP875", beam_VP875); + m_data->Stores["ANNIEEvent"]->Get("beam_HPTG1", beam_HPTG1); + m_data->Stores["ANNIEEvent"]->Get("beam_VPTG1", beam_VPTG1); + m_data->Stores["ANNIEEvent"]->Get("beam_HPTG2", beam_HPTG2); + m_data->Stores["ANNIEEvent"]->Get("beam_VPTG2", beam_VPTG2); + m_data->Stores["ANNIEEvent"]->Get("beam_BTH2T2", beam_BTH2T2); + + m_data->Stores["ANNIEEvent"]->Get("beam_E_TOR875", fPot); + m_data->Stores["ANNIEEvent"]->Get("beam_good", fBeamok); + + m_data->Stores["ANNIEEvent"]->Get("BeamInfoTime", fBeamInfoTime); + m_data->Stores["ANNIEEvent"]->Get("BeamInfoTimeToTriggerDiff", fBeamInfoTimeToTriggerDiff); +} + +void ANNIEEventTreeMaker::LoadAllTankHits() +{ + Log("ANNIEEventTreeMaker Tool: LoadAllTankHits", v_debug, ANNIEEventTreeMakerVerbosity); + std::map> *Hits = nullptr; + std::map> *MCHits = nullptr; + bool got_hits = false; + if (isData) + got_hits = m_data->Stores["ANNIEEvent"]->Get("Hits", Hits); + else + got_hits = m_data->Stores["ANNIEEvent"]->Get("MCHits", MCHits); + if (!got_hits) + { + std::cout << "No Hits store in ANNIEEvent. Continuing to build tree " << std::endl; + return; + } + + Position detector_center = geom->GetTankCentre(); + double tank_center_x = detector_center.X(); + double tank_center_y = detector_center.Y(); + double tank_center_z = detector_center.Z(); + fNHits = 0; + + std::map>::iterator it_tank_data; + std::map>::iterator it_tank_mc; + if (isData) + it_tank_data = (*Hits).begin(); + else + it_tank_mc = (*MCHits).begin(); + bool loop_tank = true; + int hits_size = (isData) ? Hits->size() : MCHits->size(); + if (hits_size == 0) + loop_tank = false; + + while (loop_tank) + { + // start to fill tank info to vectors + unsigned long channel_key; + if (isData) + channel_key = it_tank_data->first; + else + channel_key = it_tank_mc->first; + Detector *this_detector = geom->ChannelToDetector(channel_key); + Position det_position = this_detector->GetDetectorPosition(); + unsigned long detkey = this_detector->GetDetectorID(); + unsigned long channel_key_data = channel_key; + if (!isData) + { + int wcsimid = channelkey_to_pmtid.at(channel_key); + channel_key_data = pmtid_to_channelkey[wcsimid]; + } + std::map::iterator it = ChannelKeyToSPEMap.find(channel_key); + std::map::iterator it_mc = ChannelKeyToSPEMap.find(channel_key_data); + bool SPE_available = true; + if (isData) + SPE_available = (it != ChannelKeyToSPEMap.end()); + else + SPE_available = (it_mc != ChannelKeyToSPEMap.end()); + if (SPE_available) + { // Charge to SPE conversion is available + if (isData) + { + std::vector ThisPMTHits = it_tank_data->second; + fNHits += ThisPMTHits.size(); + for (Hit &ahit : ThisPMTHits) + { + double hit_charge = ahit.GetCharge(); + double hit_PE = hit_charge / ChannelKeyToSPEMap.at(channel_key); + fHitX.push_back((det_position.X() - tank_center_x)); + fHitY.push_back((det_position.Y() - tank_center_y)); + fHitZ.push_back((det_position.Z() - tank_center_z)); + fHitT.push_back(ahit.GetTime()); + fHitQ.push_back(hit_charge); + fHitPE.push_back(hit_PE); + fHitDetID.push_back(detkey); + fHitChankey.push_back(channel_key); + fHitChankeyMC.push_back(channel_key); + fHitType.push_back(RecoDigit::PMT8inch); // 0 For PMTs + } + } + else + { + std::vector ThisPMTHits = it_tank_mc->second; + fNHits += ThisPMTHits.size(); + for (MCHit &ahit : ThisPMTHits) + { + double hit_PE = ahit.GetCharge(); + double hit_charge = hit_PE * ChannelKeyToSPEMap.at(channel_key_data); + fHitX.push_back((det_position.X() - tank_center_x)); + fHitY.push_back((det_position.Y() - tank_center_y)); + fHitZ.push_back((det_position.Z() - tank_center_z)); + fHitT.push_back(ahit.GetTime()); + fHitQ.push_back(hit_charge); + fHitPE.push_back(hit_PE); + fHitDetID.push_back(detkey); + fHitChankey.push_back(channel_key_data); + fHitChankeyMC.push_back(channel_key); + fHitType.push_back(RecoDigit::PMT8inch); // 0 For PMTs + } + } + } + + if (isData) + { + it_tank_data++; + if (it_tank_data == (*Hits).end()) + loop_tank = false; + } + else + { + it_tank_mc++; + if (it_tank_mc == (*MCHits).end()) + loop_tank = false; + } + } + return; +} + +void ANNIEEventTreeMaker::LoadSiPMHits() +{ + Log("ANNIEEventTreeMaker Tool: LoadSiPMHits", v_debug, ANNIEEventTreeMakerVerbosity); + std::map>> aux_pulse_map; + m_data->Stores.at("ANNIEEvent")->Get("RecoADCAuxHits", aux_pulse_map); + fSiPM1NPulses = 0; + fSiPM2NPulses = 0; + for (const auto &temp_pair : aux_pulse_map) + { + const auto &channel_key = temp_pair.first; + // For now, only calibrate the SiPM waveforms + int sipm_number = -1; + if (AuxChannelNumToTypeMap->at(channel_key) == "SiPM1") + { + sipm_number = 1; + } + else if (AuxChannelNumToTypeMap->at(channel_key) == "SiPM2") + { + sipm_number = 2; + } + else + continue; + + std::vector> sipm_minibuffers = temp_pair.second; + size_t num_minibuffers = sipm_minibuffers.size(); // Should be size 1 in FrankDAQ mode + for (size_t mb = 0; mb < num_minibuffers; ++mb) + { + std::vector thisbuffer_pulses = sipm_minibuffers.at(mb); + if (sipm_number == 1) + fSiPM1NPulses += thisbuffer_pulses.size(); + if (sipm_number == 2) + fSiPM2NPulses += thisbuffer_pulses.size(); + for (size_t i = 0; i < thisbuffer_pulses.size(); i++) + { + ADCPulse apulse = thisbuffer_pulses.at(i); + fSiPMHitAmplitude.push_back(apulse.amplitude()); + fSiPMHitT.push_back(apulse.peak_time()); + fSiPMHitQ.push_back(apulse.charge()); + fSiPMNum.push_back(sipm_number); + } + } + } +} + +void ANNIEEventTreeMaker::LoadLAPPDInfo() +{ + m_data->Stores["ANNIEEvent"]->Get("LAPPDDataMap", LAPPDDataMap); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStampsRaw", LAPPDTimeStampsRaw); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgatesRaw", LAPPDBeamgatesRaw); + m_data->Stores["ANNIEEvent"]->Get("LAPPDOffsets", LAPPDOffsets); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTSCorrection", LAPPDTSCorrection); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBGCorrection", LAPPDBGCorrection); + m_data->Stores["ANNIEEvent"]->Get("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + if (LAPPDDataMap.size() != 0) + { + FillLAPPDInfo(); + // print the content of fDataStreams, and the size of data map + // cout<<"Found LAPPDData, LAPPDDataMap Size: "<::iterator it = LAPPDDataMap.begin(); it != LAPPDDataMap.end(); ++it) + { + uint64_t key = it->first; + PsecData psecData = it->second; + fLAPPD_ID.push_back(psecData.LAPPD_ID); + fLAPPD_Beamgate_ns.push_back(LAPPDBeamgate_ns[key]); + fLAPPD_Timestamp_ns.push_back(LAPPDTimeStamps_ns[key]); + fLAPPD_Beamgate_Raw.push_back(LAPPDBeamgatesRaw[key]); + fLAPPD_Timestamp_Raw.push_back(LAPPDTimeStampsRaw[key]); + fLAPPD_Offset.push_back(LAPPDOffsets[key]); + fLAPPD_TSCorrection.push_back(LAPPDTSCorrection[key]); + fLAPPD_BGCorrection.push_back(LAPPDBGCorrection[key]); + fLAPPD_OSInMinusPS.push_back(LAPPDOSInMinusPS[key]); + } +} + +void ANNIEEventTreeMaker::FillLAPPDPulse() +{ + bool gotPulse = m_data->Stores["ANNIEEvent"]->Get("LAPPDPulses", lappdPulses); + if (gotPulse) + { + + std::map>>::iterator it; + for (it = lappdPulses.begin(); it != lappdPulses.end(); it++) + { + int stripno = it->first; + vector> stripPulses = it->second; + + vector pulse0 = stripPulses.at(0); + vector pulse1 = stripPulses.at(1); + for (int i = 0; i < pulse0.size(); i++) + { + fPulseSide.push_back(0); + LAPPDPulse thisPulse = pulse0.at(i); + fLAPPD_IDs.push_back(thisPulse.GetTubeId()); + fChannelID.push_back(thisPulse.GetChannelID()); + fPulseStripNum.push_back(stripno); + fPulsePeakTime.push_back(thisPulse.GetTime()); + fPulseCharge.push_back(thisPulse.GetCharge()); + fPulsePeakAmp.push_back(thisPulse.GetPeak()); + fPulseStart.push_back(thisPulse.GetLowRange()); + fPulseEnd.push_back(thisPulse.GetHiRange()); + fPulseWidth.push_back(thisPulse.GetHiRange() - thisPulse.GetLowRange()); + } + for (int i = 0; i < pulse1.size(); i++) + { + fPulseSide.push_back(1); + LAPPDPulse thisPulse = pulse1.at(i); + fLAPPD_IDs.push_back(thisPulse.GetTubeId()); + fChannelID.push_back(thisPulse.GetChannelID()); + fPulseStripNum.push_back(stripno); + fPulsePeakTime.push_back(thisPulse.GetTime()); + fPulseCharge.push_back(thisPulse.GetCharge()); + fPulsePeakAmp.push_back(thisPulse.GetPeak()); + fPulseStart.push_back(thisPulse.GetLowRange()); + fPulseEnd.push_back(thisPulse.GetHiRange()); + fPulseWidth.push_back(thisPulse.GetHiRange() - thisPulse.GetLowRange()); + } + } + } +} + +void ANNIEEventTreeMaker::FillLAPPDHit() +{ + bool gotHit = m_data->Stores["ANNIEEvent"]->Get("LAPPDHits", lappdHits); + + if (gotHit) + { + std::map>::iterator it; + for (it = lappdHits.begin(); it != lappdHits.end(); it++) + { + int stripno = it->first; + vector stripHits = it->second; + for (int i = 0; i < stripHits.size(); i++) + { + LAPPDHit thisHit = stripHits.at(i); + fLAPPDHit_IDs.push_back(thisHit.GetTubeId()); + fLAPPDHitStrip.push_back(stripno); + fLAPPDHitTime.push_back(thisHit.GetTime()); + fLAPPDHitAmp.push_back(thisHit.GetCharge()); + vector position = thisHit.GetPosition(); + /* + XPosTank = position.at(0); + YPosTank = position.at(1); + ZPosTank = position.at(2);*/ + vector localPosition = thisHit.GetLocalPosition(); + fLAPPDHitParallelPos.push_back(localPosition.at(0)); + fLAPPDHitTransversePos.push_back(localPosition.at(1)); + fLAPPDHitP1StartTime.push_back(thisHit.GetPulse1StartTime()); + fLAPPDHitP2StartTime.push_back(thisHit.GetPulse2StartTime()); + fLAPPDHitP1EndTime.push_back(thisHit.GetPulse1LastTime()); + fLAPPDHitP2EndTime.push_back(thisHit.GetPulse2LastTime()); + } + } + } +} + +bool ANNIEEventTreeMaker::LoadClusterInfo() +{ + Log("ANNIEEventTreeMaker Tool: LoadClusterInfo", v_debug, ANNIEEventTreeMakerVerbosity); + + std::map> *m_all_clusters = nullptr; + std::map> *m_all_clusters_MC = nullptr; + std::map> *m_all_clusters_detkeys = nullptr; + + bool get_clusters = false; + if (isData) + { + get_clusters = m_data->CStore.Get("ClusterMap", m_all_clusters); + if (!get_clusters) + { + std::cout << "ANNIEEventTreeMaker tool: No clusters found!" << std::endl; + return false; + } + } + else + { + get_clusters = m_data->CStore.Get("ClusterMapMC", m_all_clusters_MC); + if (!get_clusters) + { + std::cout << "ANNIEEventTreeMaker tool: No clusters found (MC)!" << std::endl; + return false; + } + } + get_clusters = m_data->CStore.Get("ClusterMapDetkey", m_all_clusters_detkeys); + if (!get_clusters) + { + std::cout << "ANNIEEventTreeMaker tool: No cluster detkeys found!" << std::endl; + return false; + } + Log("ANNIEEventTreeMaker Tool: Accessing pairs in all_clusters map", v_debug, ANNIEEventTreeMakerVerbosity); + + int cluster_num = 0; + int cluster_size = 0; + if (isData) + cluster_size = (int)m_all_clusters->size(); + else + cluster_size = (int)m_all_clusters_MC->size(); + + std::map>::iterator it_cluster_pair; + std::map>::iterator it_cluster_pair_mc; + bool loop_map = true; + if (isData) + it_cluster_pair = (*m_all_clusters).begin(); + else + it_cluster_pair_mc = (*m_all_clusters_MC).begin(); + if (cluster_size == 0) + loop_map = false; + + fNumberOfClusters = cluster_size; + while (loop_map) + { + if (isData) + { + std::vector cluster_hits = it_cluster_pair->second; + double thisClusterTime = it_cluster_pair->first; + if (cluster_TankHitInfo_fill) + { + Log("ANNIEEventTreeMaker Tool: Loading tank cluster hits into cluster tree", v_debug, ANNIEEventTreeMakerVerbosity); + fClusterTimeV.push_back(thisClusterTime); + this->LoadTankClusterHits(cluster_hits); + } + + bool good_class = this->LoadTankClusterClassifiers(it_cluster_pair->first); + if (!good_class) + { + if (ANNIEEventTreeMakerVerbosity > 3) + Log("ANNIEEventTreeMaker Tool: No cluster classifiers. Continuing tree", v_debug, ANNIEEventTreeMakerVerbosity); + } + } + else + { + std::vector cluster_hits = it_cluster_pair_mc->second; + double thisClusterTime = it_cluster_pair_mc->first; + std::vector cluster_detkeys = m_all_clusters_detkeys->at(it_cluster_pair_mc->first); + if (cluster_TankHitInfo_fill) + { + Log("ANNIEEventTreeMaker Tool: Loading tank cluster hits into cluster tree", v_debug, ANNIEEventTreeMakerVerbosity); + fClusterTimeV.push_back(thisClusterTime); + this->LoadTankClusterHitsMC(cluster_hits, cluster_detkeys); + } + bool good_class = this->LoadTankClusterClassifiers(it_cluster_pair_mc->first); + if (!good_class) + { + if (ANNIEEventTreeMakerVerbosity > 3) + Log("ANNIEEventTreeMaker Tool: No cluster classifiers. Continuing tree", v_debug, ANNIEEventTreeMakerVerbosity); + } + } + + if (isData) + { + it_cluster_pair++; + if (it_cluster_pair == (*m_all_clusters).end()) + loop_map = false; + } + else + { + it_cluster_pair_mc++; + if (it_cluster_pair_mc == (*m_all_clusters_MC).end()) + loop_map = false; + } + } return true; } + +void ANNIEEventTreeMaker::LoadTankClusterHits(std::vector cluster_hits) +{ + Position detector_center = geom->GetTankCentre(); + double tank_center_x = detector_center.X(); + double tank_center_y = detector_center.Y(); + double tank_center_z = detector_center.Z(); + + double ClusterCharge = 0; + double ClusterPE = 0; + int ClusterHitNum = 0; + vector HitXV; + vector HitYV; + vector HitZV; + vector HitTV; + vector HitQV; + vector HitPEV; + vector HitTypeV; + vector HitDetIDV; + vector HitChankeyV; + vector HitCKMC; + + for (int i = 0; i < (int)cluster_hits.size(); i++) + { + int channel_key = cluster_hits.at(i).GetTubeId(); + std::map::iterator it = ChannelKeyToSPEMap.find(channel_key); + if (it != ChannelKeyToSPEMap.end()) + { // Charge to SPE conversion is available + Detector *this_detector = geom->ChannelToDetector(channel_key); + unsigned long detkey = this_detector->GetDetectorID(); + Position det_position = this_detector->GetDetectorPosition(); + double hit_charge = cluster_hits.at(i).GetCharge(); + double hit_PE = hit_charge / ChannelKeyToSPEMap.at(channel_key); + HitXV.push_back((det_position.X() - tank_center_x)); + HitYV.push_back((det_position.Y() - tank_center_y)); + HitZV.push_back((det_position.Z() - tank_center_z)); + HitQV.push_back(hit_charge); + HitPEV.push_back(hit_PE); + HitTV.push_back(cluster_hits.at(i).GetTime()); + HitDetIDV.push_back(detkey); + + HitChankeyV.push_back(channel_key); + HitCKMC.push_back(channel_key); + HitTypeV.push_back(RecoDigit::PMT8inch); + ClusterCharge += hit_charge; + ClusterPE += hit_PE; + ClusterHitNum += 1; + } + else + { + if (ANNIEEventTreeMakerVerbosity > 4) + { + std::cout << "FOUND A HIT FOR CHANNELKEY " << channel_key << "BUT NO CONVERSION " << "TO PE AVAILABLE. SKIPPING PE." << std::endl; + } + } + } + fClusterHits.push_back(ClusterHitNum); + fClusterChargeV.push_back(ClusterCharge); + fClusterPEV.push_back(ClusterPE); + + fCluster_HitX.push_back(HitXV); + fCluster_HitY.push_back(HitYV); + fCluster_HitZ.push_back(HitZV); + fCluster_HitT.push_back(HitTV); + fCluster_HitQ.push_back(HitQV); + fCluster_HitPE.push_back(HitPEV); + fCluster_HitType.push_back(HitTypeV); + fCluster_HitDetID.push_back(HitDetIDV); + fCluster_HitChankey.push_back(HitChankeyV); + fCluster_HitChankeyMC.push_back(HitCKMC); + + return; +} + +void ANNIEEventTreeMaker::LoadTankClusterHitsMC(std::vector cluster_hits, std::vector cluster_detkeys) +{ + Position detector_center = geom->GetTankCentre(); + double tank_center_x = detector_center.X(); + double tank_center_y = detector_center.Y(); + double tank_center_z = detector_center.Z(); + + double ClusterCharge = 0; + double ClusterPE = 0; + int ClusterHitNum = 0; + vector HitXV; + vector HitYV; + vector HitZV; + vector HitTV; + vector HitQV; + vector HitPEV; + vector HitTypeV; + vector HitDetIDV; + vector HitChankeyV; + vector HitCKMC; + + for (int i = 0; i < (int)cluster_hits.size(); i++) + { + unsigned long detkey = cluster_detkeys.at(i); + int channel_key = (int)detkey; + int tubeid = cluster_hits.at(i).GetTubeId(); + unsigned long utubeid = (unsigned long)tubeid; + int wcsimid = channelkey_to_pmtid.at(utubeid); + unsigned long detkey_data = pmtid_to_channelkey[wcsimid]; + int channel_key_data = (int)detkey_data; + std::map::iterator it = ChannelKeyToSPEMap.find(channel_key_data); + if (it != ChannelKeyToSPEMap.end()) + { // Charge to SPE conversion is available + Detector *this_detector = geom->ChannelToDetector(tubeid); + Position det_position = this_detector->GetDetectorPosition(); + unsigned long detkey = this_detector->GetDetectorID(); + double hit_PE = cluster_hits.at(i).GetCharge(); + double hit_charge = hit_PE * ChannelKeyToSPEMap.at(channel_key_data); + HitXV.push_back((det_position.X() - tank_center_x)); + HitYV.push_back((det_position.Y() - tank_center_y)); + HitZV.push_back((det_position.Z() - tank_center_z)); + HitQV.push_back(hit_charge); + HitPEV.push_back(hit_PE); + HitTV.push_back(cluster_hits.at(i).GetTime()); + HitDetIDV.push_back(detkey); + HitChankeyV.push_back(channel_key_data); + HitCKMC.push_back(channel_key); + HitTypeV.push_back(RecoDigit::PMT8inch); + ClusterCharge += hit_charge; + ClusterPE += hit_PE; + ClusterHitNum += 1; + } + else + { + if (ANNIEEventTreeMakerVerbosity > 4) + { + std::cout << "FOUND A HIT FOR CHANNELKEY " << channel_key_data << "(MC detkey: " << channel_key << ", chankey = " << utubeid << ", wcsimid = " << wcsimid << ") BUT NO CONVERSION " << "TO PE AVAILABLE. SKIPPING PE." << std::endl; + } + } + } + fClusterHits.push_back(ClusterHitNum); + fClusterChargeV.push_back(ClusterCharge); + fClusterPEV.push_back(ClusterPE); + + fCluster_HitX.push_back(HitXV); + fCluster_HitY.push_back(HitYV); + fCluster_HitZ.push_back(HitZV); + fCluster_HitT.push_back(HitTV); + fCluster_HitQ.push_back(HitQV); + fCluster_HitPE.push_back(HitPEV); + fCluster_HitType.push_back(HitTypeV); + fCluster_HitDetID.push_back(HitDetIDV); + fCluster_HitChankey.push_back(HitChankeyV); + fCluster_HitChankeyMC.push_back(HitCKMC); + + return; +} + +bool ANNIEEventTreeMaker::LoadTankClusterClassifiers(double cluster_time) +{ + // Save classifiers to ANNIEEvent + Log("PhaseITreeMaker tool: Getting cluster classifiers", v_debug, ANNIEEventTreeMakerVerbosity); + std::map ClusterMaxPEs; + std::map ClusterChargePoints; + std::map ClusterChargeBalances; + + bool got_ccp = m_data->Stores.at("ANNIEEvent")->Get("ClusterChargePoints", ClusterChargePoints); + bool got_ccb = m_data->Stores.at("ANNIEEvent")->Get("ClusterChargeBalances", ClusterChargeBalances); + bool got_cmpe = m_data->Stores.at("ANNIEEvent")->Get("ClusterMaxPEs", ClusterMaxPEs); + bool good_classifiers = got_ccp && got_ccb && got_cmpe; + if (!good_classifiers) + { + Log("PhaseITreeMaker tool: One of the charge cluster classifiers is not available", v_debug, ANNIEEventTreeMakerVerbosity); + } + else + { + Log("PhaseITreeMaker tool: Setting fCluster variables to classifier parameters", v_debug, ANNIEEventTreeMakerVerbosity); + fClusterMaxPEV.push_back(ClusterMaxPEs.at(cluster_time)); + Position ClusterChargePoint = ClusterChargePoints.at(cluster_time); + fClusterChargePointXV.push_back(ClusterChargePoint.X()); + fClusterChargePointYV.push_back(ClusterChargePoint.Y()); + fClusterChargePointZV.push_back(ClusterChargePoint.Z()); + fClusterChargeBalanceV.push_back(ClusterChargeBalances.at(cluster_time)); + } + return good_classifiers; +} + +void ANNIEEventTreeMaker::LoadMRDCluster() +{ + std::vector mrddigittimesthisevent; + std::vector mrddigitpmtsthisevent; + std::vector mrddigitchankeysthisevent; + std::vector> MrdTimeClusters; + + bool get_clusters = m_data->CStore.Get("MrdTimeClusters", MrdTimeClusters); + if (!get_clusters) + { + std::cout << "ANNIEEventTreeMaker tool: No MRD clusters found! Did you run the TimeClustering tool?" << std::endl; + return; + } + + int num_mrd_clusters; + m_data->CStore.Get("NumMrdTimeClusters", num_mrd_clusters); + + if (num_mrd_clusters > 0) + { + m_data->CStore.Get("MrdDigitTimes", mrddigittimesthisevent); + m_data->CStore.Get("MrdDigitPmts", mrddigitpmtsthisevent); + m_data->CStore.Get("MrdDigitChankeys", mrddigitchankeysthisevent); + } + + std::map> *TDCData = nullptr; + std::map> *TDCData_MC = nullptr; + + int TrigHasVetoHit = 0; + bool has_tdc = false; + if (isData) + has_tdc = m_data->Stores["ANNIEEvent"]->Get("TDCData", TDCData); // a std::map> + else + has_tdc = m_data->Stores["ANNIEEvent"]->Get("TDCData", TDCData_MC); + if (!has_tdc) + { + std::cout << "No TDCData store in ANNIEEvent." << std::endl; + } + + int cluster_num = 0; + for (int i = 0; i < (int)MrdTimeClusters.size(); i++) + { + int tdcdata_size = (isData) ? TDCData->size() : TDCData_MC->size(); + fMRDClusterHits = 0; + if (has_tdc && tdcdata_size > 0) + { + Log("ANNIEEventTreeMaker tool: Looping over FACC/MRD hits... looking for Veto activity", v_debug, ANNIEEventTreeMakerVerbosity); + if (isData) + { + for (auto &&anmrdpmt : (*TDCData)) + { + unsigned long chankey = anmrdpmt.first; + std::vector mrdhits = anmrdpmt.second; + Detector *thedetector = geom->ChannelToDetector(chankey); + unsigned long detkey = thedetector->GetDetectorID(); + if (thedetector->GetDetectorElement() == "Veto") + { + TrigHasVetoHit = 1; // this is a veto hit, not an MRD hit. + for (int j = 0; j < (int)mrdhits.size(); j++) + { + fFMVHitT.push_back(mrdhits.at(j).GetTime()); + fFMVHitDetID.push_back(detkey); + fFMVHitChankey.push_back(chankey); + fFMVHitChankeyMC.push_back(chankey); + } + } + } + } + else + { + for (auto &&anmrdpmt : (*TDCData_MC)) + { + unsigned long chankey = anmrdpmt.first; + Detector *thedetector = geom->ChannelToDetector(chankey); + unsigned long detkey = thedetector->GetDetectorID(); + if (thedetector->GetDetectorElement() == "Veto") + { + TrigHasVetoHit = 1; // this is a veto hit, not an MRD hit. + int wcsimid = channelkey_to_faccpmtid.at(chankey) - 1; + unsigned long chankey_data = wcsimid; + std::vector mrdhits = anmrdpmt.second; + for (int j = 0; j < (int)mrdhits.size(); j++) + { + fFMVHitT.push_back(mrdhits.at(j).GetTime()); + fFMVHitDetID.push_back(detkey); + fFMVHitChankey.push_back(chankey_data); + fFMVHitChankeyMC.push_back(chankey); + } + } + } + } + } + + fVetoHit = TrigHasVetoHit; + std::vector ThisClusterIndices = MrdTimeClusters.at(i); + for (int j = 0; j < (int)ThisClusterIndices.size(); j++) + { + Detector *thedetector = geom->ChannelToDetector(mrddigitchankeysthisevent.at(ThisClusterIndices.at(j))); + unsigned long detkey = thedetector->GetDetectorID(); + + fMRDHitT.push_back(mrddigittimesthisevent.at(ThisClusterIndices.at(j))); + fMRDHitDetID.push_back(detkey); + if (isData) + fMRDHitChankey.push_back(mrddigitchankeysthisevent.at(ThisClusterIndices.at(j))); + else + { + int wcsimid = channelkey_to_mrdpmtid.at(mrddigitchankeysthisevent.at(ThisClusterIndices.at(j))) - 1; + unsigned long chankey_data = mrdpmtid_to_channelkey_data[wcsimid]; + fMRDHitChankey.push_back(chankey_data); + } + fMRDHitChankeyMC.push_back(mrddigitchankeysthisevent.at(ThisClusterIndices.at(j))); + fMRDClusterHits += 1; + } + + ComputeMeanAndVariance(fMRDHitT, fMRDClusterTime, fMRDClusterTimeSigma); + // FIXME: calculate fMRDClusterTime + + // Standard run level information + Log("ANNIEEventTreeMaker Tool: MRD cluster, Getting run level information from ANNIEEvent", v_debug, ANNIEEventTreeMakerVerbosity); + + if (MRDReco_fill) + { + int ThisMRDClusterTrackNum = this->LoadMRDTrackReco(i); + fNumClusterTracks.push_back(ThisMRDClusterTrackNum); + // Get the track info + } + cluster_num++; + } + fMRDClusterNumber = cluster_num; + Log("ANNIEEventTreeMaker Tool: MRD cluster, Finished loading MRD cluster info", v_debug, ANNIEEventTreeMakerVerbosity); +} + +int ANNIEEventTreeMaker::LoadMRDTrackReco(int SubEventID) +{ + std::vector *theMrdTracks; // the reconstructed tracks + int numtracksinev; + + // Check for valid track criteria + m_data->Stores["MRDTracks"]->Get("MRDTracks", theMrdTracks); + m_data->Stores["MRDTracks"]->Get("NumMrdTracks", numtracksinev); + // Loop over reconstructed tracks + + Position StartVertex; + Position StopVertex; + double TrackLength = -9999; + double TrackAngle = -9999; + double TrackAngleError = -9999; + double PenetrationDepth = -9999; + Position MrdEntryPoint; + double EnergyLoss = -9999; // in MeV + double EnergyLossError = -9999; + double EntryPointRadius = -9999; + bool IsMrdPenetrating; + bool IsMrdStopped; + bool IsMrdSideExit; + + int NumClusterTracks = 0; + for (int tracki = 0; tracki < numtracksinev; tracki++) + { + BoostStore *thisTrackAsBoostStore = &(theMrdTracks->at(tracki)); + int TrackEventID = -1; + // get track properties that are needed for the through-going muon selection + thisTrackAsBoostStore->Get("MrdSubEventID", TrackEventID); + if (TrackEventID != SubEventID) + continue; + + // If we're here, this track is associated with this cluster + thisTrackAsBoostStore->Get("StartVertex", StartVertex); + thisTrackAsBoostStore->Get("StopVertex", StopVertex); + thisTrackAsBoostStore->Get("TrackAngle", TrackAngle); + thisTrackAsBoostStore->Get("TrackAngleError", TrackAngleError); + thisTrackAsBoostStore->Get("PenetrationDepth", PenetrationDepth); + thisTrackAsBoostStore->Get("MrdEntryPoint", MrdEntryPoint); + thisTrackAsBoostStore->Get("EnergyLoss", EnergyLoss); + thisTrackAsBoostStore->Get("EnergyLossError", EnergyLossError); + thisTrackAsBoostStore->Get("IsMrdPenetrating", IsMrdPenetrating); // bool + thisTrackAsBoostStore->Get("IsMrdStopped", IsMrdStopped); // bool + thisTrackAsBoostStore->Get("IsMrdSideExit", IsMrdSideExit); + TrackLength = sqrt(pow((StopVertex.X() - StartVertex.X()), 2) + pow(StopVertex.Y() - StartVertex.Y(), 2) + pow(StopVertex.Z() - StartVertex.Z(), 2)) * 100.0; + EntryPointRadius = sqrt(pow(MrdEntryPoint.X(), 2) + pow(MrdEntryPoint.Y(), 2)) * 100.0; // convert to cm + PenetrationDepth = PenetrationDepth * 100.0; + + // Push back some properties + fMRDTrackAngle.push_back(TrackAngle); + fMRDTrackAngleError.push_back(TrackAngleError); + fMRDTrackLength.push_back(TrackLength); + fMRDPenetrationDepth.push_back(PenetrationDepth); + fMRDEntryPointRadius.push_back(EntryPointRadius); + fMRDEnergyLoss.push_back(EnergyLoss); + fMRDEnergyLossError.push_back(EnergyLossError); + fMRDTrackStartX.push_back(StartVertex.X()); + fMRDTrackStartY.push_back(StartVertex.Y()); + fMRDTrackStartZ.push_back(StartVertex.Z()); + fMRDTrackStopX.push_back(StopVertex.X()); + fMRDTrackStopY.push_back(StopVertex.Y()); + fMRDTrackStopZ.push_back(StopVertex.Z()); + fMRDStop.push_back(IsMrdStopped); + fMRDSide.push_back(IsMrdSideExit); + fMRDThrough.push_back(IsMrdPenetrating); + NumClusterTracks += 1; + fMRDClusterIndex.push_back(SubEventID); + } + return NumClusterTracks; +} + +// MC and tank reco information below + +bool ANNIEEventTreeMaker::FillTankRecoInfo() +{ + bool got_reco_info = true; + auto *reco_event = m_data->Stores["RecoEvent"]; + if (!reco_event) + { + Log("Error: The PhaseITreeMaker tool could not find the RecoEvent Store", v_error, ANNIEEventTreeMakerVerbosity); + got_reco_info = false; + } + // Read reconstructed Vertex + RecoVertex *recovtx = 0; + auto get_extendedvtx = m_data->Stores.at("RecoEvent")->Get("ExtendedVertex", recovtx); + if (!get_extendedvtx) + { + Log("Warning: The PhaseITreeMaker tool could not find ExtendedVertex. Continuing to build tree", v_message, ANNIEEventTreeMakerVerbosity); + got_reco_info = false; + } + else + { + fRecoVtxX = recovtx->GetPosition().X(); + fRecoVtxY = recovtx->GetPosition().Y(); + fRecoVtxZ = recovtx->GetPosition().Z(); + fRecoVtxTime = recovtx->GetTime(); + fRecoVtxFOM = recovtx->GetFOM(); + fRecoDirX = recovtx->GetDirection().X(); + fRecoDirY = recovtx->GetDirection().Y(); + fRecoDirZ = recovtx->GetDirection().Z(); + fRecoAngle = TMath::ACos(fRecoDirZ); + if (fRecoDirX > 0.0) + { + fRecoPhi = atan(fRecoDirY / fRecoDirX); + } + if (fRecoDirX < 0.0) + { + fRecoPhi = atan(fRecoDirY / fRecoDirX); + if (fRecoDirY > 0.0) + fRecoPhi += TMath::Pi(); + if (fRecoDirY <= 0.0) + fRecoPhi -= TMath::Pi(); + } + if (fRecoDirX == 0.0) + { + if (fRecoDirY > 0.0) + fRecoPhi = 0.5 * TMath::Pi(); + else if (fRecoDirY < 0.0) + fRecoPhi = -0.5 * TMath::Pi(); + else + fRecoPhi = 0; + } + fRecoStatus = recovtx->GetStatus(); + } + return got_reco_info; +} + +void ANNIEEventTreeMaker::FillRecoDebugInfo() +{ + // Read Seed candidates + std::vector *seedvtxlist = 0; + auto get_seedvtxlist = m_data->Stores.at("RecoEvent")->Get("vSeedVtxList", seedvtxlist); ///> Get List of seeds from "RecoEvent" + if (get_seedvtxlist) + { + for (auto &seed : *seedvtxlist) + { + fSeedVtxX.push_back(seed.GetPosition().X()); + fSeedVtxY.push_back(seed.GetPosition().Y()); + fSeedVtxZ.push_back(seed.GetPosition().Z()); + fSeedVtxTime = seed.GetTime(); + } + } + else + { + Log("ANNIEEventTreeMaker Tool: No Seed List found. Continuing to build tree ", v_message, ANNIEEventTreeMakerVerbosity); + } + std::vector *seedfomlist = 0; + auto get_seedfomlist = m_data->Stores.at("RecoEvent")->Get("vSeedFOMList", seedfomlist); ///> Get List of seed FOMs from "RecoEvent" + if (get_seedfomlist) + { + for (auto &seedFOM : *seedfomlist) + { + fSeedVtxFOM.push_back(seedFOM); + } + } + else + { + Log("ANNIEEventTreeMaker Tool: No Seed FOM List found. Continuing to build tree ", v_message, ANNIEEventTreeMakerVerbosity); + } + + // Read PointPosition-fitted Vertex + RecoVertex *pointposvtx = 0; + auto get_pointposdata = m_data->Stores.at("RecoEvent")->Get("PointPosition", pointposvtx); + if (get_pointposdata) + { + fPointPosX = pointposvtx->GetPosition().X(); + fPointPosY = pointposvtx->GetPosition().Y(); + fPointPosZ = pointposvtx->GetPosition().Z(); + fPointPosTime = pointposvtx->GetTime(); + fPointPosFOM = pointposvtx->GetFOM(); + fPointPosStatus = pointposvtx->GetStatus(); + } + else + { + Log("ANNIEEventTreeMaker Tool: No PointPosition Tool data found. Continuing to build remaining tree", v_message, ANNIEEventTreeMakerVerbosity); + } + + // Read PointDirection-fitted Vertex + RecoVertex *pointdirvtx = 0; + auto get_pointdirdata = m_data->Stores.at("RecoEvent")->Get("PointDirection", pointdirvtx); + if (get_pointdirdata) + { + fPointDirX = pointdirvtx->GetDirection().X(); + fPointDirY = pointdirvtx->GetDirection().Y(); + fPointDirZ = pointdirvtx->GetDirection().Z(); + fPointDirTime = pointdirvtx->GetTime(); + fPointDirFOM = pointdirvtx->GetFOM(); + fPointDirStatus = pointdirvtx->GetStatus(); + } + else + { + Log("ANNIEEventTreeMaker Tool: No PointDirection Tool data found. Continuing to build remaining tree", v_message, ANNIEEventTreeMakerVerbosity); + } + + // Read PointVertex Tool's fitted Vertex + RecoVertex *pointvtx = 0; + auto get_pointvtxdata = m_data->Stores.at("RecoEvent")->Get("PointVertex", pointvtx); + if (get_pointvtxdata) + { + fPointVtxPosX = pointvtx->GetPosition().X(); + fPointVtxPosY = pointvtx->GetPosition().Y(); + fPointVtxPosZ = pointvtx->GetPosition().Z(); + fPointVtxDirX = pointvtx->GetDirection().X(); + fPointVtxDirY = pointvtx->GetDirection().Y(); + fPointVtxDirZ = pointvtx->GetDirection().Z(); + fPointVtxTime = pointvtx->GetTime(); + fPointVtxFOM = pointvtx->GetFOM(); + fPointVtxStatus = pointvtx->GetStatus(); + } + else + { + Log("ANNIEEventTreeMaker Tool: No PointVertex Tool data found. Continuing to build remaining tree", v_message, ANNIEEventTreeMakerVerbosity); + } +} + +bool ANNIEEventTreeMaker::FillMCTruthInfo() +{ + bool successful_load = true; + // MC entry number + m_data->Stores.at("ANNIEEvent")->Get("MCEventNum", fMCEventNum); + // MC trigger number + m_data->Stores.at("ANNIEEvent")->Get("MCTriggernum", fMCTriggerNum); + std::string logmessage = " Retriving information for MCEntry " + to_string(fMCEventNum) + + ", MCTrigger " + to_string(fMCTriggerNum) + ", EventNumber " + to_string(fEventNumber); + Log(logmessage, v_message, ANNIEEventTreeMakerVerbosity); + + fiMCTriggerNum = (int)fMCTriggerNum; + + std::map> MCNeutCap; + bool get_neutcap = m_data->Stores.at("ANNIEEvent")->Get("MCNeutCap", MCNeutCap); + if (!get_neutcap) + { + Log("ANNIEEventTreeMaker: Did not find MCNeutCap in ANNIEEvent Store!", v_warning, ANNIEEventTreeMakerVerbosity); + } + std::map>> MCNeutCapGammas; + bool get_neutcap_gammas = m_data->Stores.at("ANNIEEvent")->Get("MCNeutCapGammas", MCNeutCapGammas); + if (!get_neutcap_gammas) + { + Log("ANNIEEventTreeMaker: Did not find MCNeutCapGammas in ANNIEEvent Store!", v_warning, ANNIEEventTreeMakerVerbosity); + } + + for (std::map>>::iterator it = MCNeutCapGammas.begin(); it != MCNeutCapGammas.end(); it++) + { + std::vector> mcneutgammas = it->second; + for (int i_cap = 0; i_cap < (int)mcneutgammas.size(); i_cap++) + { + std::vector capgammas = mcneutgammas.at(i_cap); + for (int i_gamma = 0; i_gamma < (int)capgammas.size(); i_gamma++) + { + std::cout << "gamma # " << i_gamma << ", energy: " << capgammas.at(i_gamma) << std::endl; + } + } + } + + RecoVertex *truevtx = 0; + auto get_muonMC = m_data->Stores.at("RecoEvent")->Get("TrueVertex", truevtx); + auto get_muonMCEnergy = m_data->Stores.at("RecoEvent")->Get("TrueMuonEnergy", fTrueMuonEnergy); + auto get_pdg = m_data->Stores.at("RecoEvent")->Get("PdgPrimary", fTruePrimaryPdg); + if (get_muonMC && get_muonMCEnergy) + { + fTrueVtxX = truevtx->GetPosition().X(); + fTrueVtxY = truevtx->GetPosition().Y(); + fTrueVtxZ = truevtx->GetPosition().Z(); + fTrueVtxTime = truevtx->GetTime(); + fTrueDirX = truevtx->GetDirection().X(); + fTrueDirY = truevtx->GetDirection().Y(); + fTrueDirZ = truevtx->GetDirection().Z(); + double TrueAngRad = TMath::ACos(fTrueDirZ); + fTrueAngle = TrueAngRad / (TMath::Pi() / 180.0); // radians->degrees + if (fTrueDirX > 0.0) + { + fTruePhi = atan(fTrueDirY / fTrueDirX); + } + if (fTrueDirX < 0.0) + { + fTruePhi = atan(fTrueDirY / fTrueDirX); + if (fTrueDirY > 0.0) + fTruePhi += TMath::Pi(); + if (fTrueDirY <= 0.0) + fTruePhi -= TMath::Pi(); + } + if (fTrueDirX == 0.0) + { + if (fTrueDirY > 0.0) + fTruePhi = 0.5 * TMath::Pi(); + else if (fTrueDirY < 0.0) + fTruePhi = -0.5 * TMath::Pi(); + else + fTruePhi = 0; + } + } + else + { + Log("ANNIEEventTreeMaker Tool: Missing MC Energy/Vertex info; is this MC? Continuing to build remaining tree", v_message, ANNIEEventTreeMakerVerbosity); + successful_load = false; + } + double waterT, MRDT; + auto get_tankTrackLength = m_data->Stores.at("RecoEvent")->Get("TrueTrackLengthInWater", waterT); + auto get_MRDTrackLength = m_data->Stores.at("RecoEvent")->Get("TrueTrackLengthInMRD", MRDT); + if (get_tankTrackLength && get_MRDTrackLength) + { + fTrueTrackLengthInWater = waterT; + fTrueTrackLengthInMRD = MRDT; + } + else + { + Log("ANNIEEventTreeMaker Tool: True track lengths missing. Continuing to build tree", v_message, ANNIEEventTreeMakerVerbosity); + successful_load = false; + } + + bool IsMultiRing = false; + bool get_multi = m_data->Stores.at("RecoEvent")->Get("MCMultiRingEvent", IsMultiRing); + if (get_multi) + { + fTrueMultiRing = (IsMultiRing) ? 1 : 0; + } + else + { + Log("ANNIEEventTreeMaker Tool: True Multi Ring information missing. Continuing to build tree", v_message, ANNIEEventTreeMakerVerbosity); + successful_load = false; + } + + std::vector primary_pdgs; + bool has_primaries = m_data->Stores.at("RecoEvent")->Get("PrimaryPdgs", primary_pdgs); + if (has_primaries) + { + for (int i_part = 0; i_part < (int)primary_pdgs.size(); i_part++) + { + fTruePrimaryPdgs->push_back(primary_pdgs.at(i_part)); + } + } + else + { + Log("ANNIEEventTreeMaker Tool: Primary Pdgs information missing. Continuing to build tree", v_message, ANNIEEventTreeMakerVerbosity); + successful_load = false; + } + + int pi0count, pipcount, pimcount, K0count, Kpcount, Kmcount; + auto get_pi0 = m_data->Stores.at("RecoEvent")->Get("MCPi0Count", pi0count); + auto get_pim = m_data->Stores.at("RecoEvent")->Get("MCPiMinusCount", pimcount); + auto get_pip = m_data->Stores.at("RecoEvent")->Get("MCPiPlusCount", pipcount); + auto get_k0 = m_data->Stores.at("RecoEvent")->Get("MCK0Count", K0count); + auto get_km = m_data->Stores.at("RecoEvent")->Get("MCKMinusCount", Kmcount); + auto get_kp = m_data->Stores.at("RecoEvent")->Get("MCKPlusCount", Kpcount); + if (get_pi0 && get_pim && get_pip && get_k0 && get_km && get_kp) + { + // set values in tree to thouse grabbed from the RecoEvent Store + fPi0Count = pi0count; + fPiPlusCount = pipcount; + fPiMinusCount = pimcount; + fK0Count = K0count; + fKPlusCount = Kpcount; + fKMinusCount = Kmcount; + } + else + { + Log("ANNIEEventTreeMaker Tool: Missing MC Pion/Kaon count information. Continuing to build remaining tree", v_message, ANNIEEventTreeMakerVerbosity); + successful_load = false; + } + + if (MCNeutCap.count("CaptVtxX") > 0) + { + std::vector n_vtxx = MCNeutCap["CaptVtxX"]; + std::vector n_vtxy = MCNeutCap["CaptVtxY"]; + std::vector n_vtxz = MCNeutCap["CaptVtxZ"]; + std::vector n_parent = MCNeutCap["CaptParent"]; + std::vector n_ngamma = MCNeutCap["CaptNGamma"]; + std::vector n_totale = MCNeutCap["CaptTotalE"]; + std::vector n_time = MCNeutCap["CaptTime"]; + std::vector n_nuc = MCNeutCap["CaptNucleus"]; + + for (int i_cap = 0; i_cap < (int)n_vtxx.size(); i_cap++) + { + fTrueNeutCapVtxX->push_back(n_vtxx.at(i_cap)); + fTrueNeutCapVtxY->push_back(n_vtxy.at(i_cap)); + fTrueNeutCapVtxZ->push_back(n_vtxz.at(i_cap)); + fTrueNeutCapNucleus->push_back(n_nuc.at(i_cap)); + fTrueNeutCapTime->push_back(n_time.at(i_cap)); + fTrueNeutCapGammas->push_back(n_ngamma.at(i_cap)); + fTrueNeutCapE->push_back(n_totale.at(i_cap)); + } + } + + std::cout << "MCNeutCapGammas count CaptGammas: " << MCNeutCapGammas.count("CaptGammas") << std::endl; + if (MCNeutCapGammas.count("CaptGammas") > 0) + { + std::vector> cap_energies = MCNeutCapGammas["CaptGammas"]; + std::cout << "cap_energies size: " << cap_energies.size() << std::endl; + for (int i_cap = 0; i_cap < (int)cap_energies.size(); i_cap++) + { + for (int i_gamma = 0; i_gamma < cap_energies.at(i_cap).size(); i_gamma++) + { + std::cout << "gamma energy: " << cap_energies.at(i_cap).at(i_gamma) << std::endl; + fTrueNeutCapGammaE->push_back(cap_energies.at(i_cap).at(i_gamma)); + } + } + } + + // Load genie information + if (hasGenie) + { + double TrueNeutrinoEnergy, TrueQ2, TrueNuIntxVtx_X, TrueNuIntxVtx_Y, TrueNuIntxVtx_Z, TrueNuIntxVtx_T; + double TrueFSLeptonMass, TrueFSLeptonEnergy, TrueFSLeptonTime; + bool TrueCC, TrueNC, TrueQEL, TrueDIS, TrueCOH, TrueMEC, TrueRES; + int fsNeutrons, fsProtons, fsPi0, fsPiPlus, fsPiPlusCher, fsPiMinus, fsPiMinusCher; + int fsKPlus, fsKPlusCher, fsKMinus, fsKMinusCher, TrueNuPDG, TrueFSLeptonPdg; + Position TrueFSLeptonVtx; + Direction TrueFSLeptonMomentum; + Direction TrueNeutrinoMomentum; + bool get_neutrino_energy = m_data->Stores["GenieInfo"]->Get("NeutrinoEnergy", TrueNeutrinoEnergy); + bool get_neutrino_mom = m_data->Stores["GenieInfo"]->Get("NeutrinoMomentum", TrueNeutrinoMomentum); + bool get_neutrino_vtxx = m_data->Stores["GenieInfo"]->Get("NuIntxVtx_X", TrueNuIntxVtx_X); + bool get_neutrino_vtxy = m_data->Stores["GenieInfo"]->Get("NuIntxVtx_Y", TrueNuIntxVtx_Y); + bool get_neutrino_vtxz = m_data->Stores["GenieInfo"]->Get("NuIntxVtx_Z", TrueNuIntxVtx_Z); + bool get_neutrino_vtxt = m_data->Stores["GenieInfo"]->Get("NuIntxVtx_T", TrueNuIntxVtx_T); + bool get_q2 = m_data->Stores["GenieInfo"]->Get("EventQ2", TrueQ2); + bool get_cc = m_data->Stores["GenieInfo"]->Get("IsWeakCC", TrueCC); + bool get_nc = m_data->Stores["GenieInfo"]->Get("IsWeakNC", TrueNC); + bool get_qel = m_data->Stores["GenieInfo"]->Get("IsQuasiElastic", TrueQEL); + bool get_res = m_data->Stores["GenieInfo"]->Get("IsResonant", TrueRES); + bool get_dis = m_data->Stores["GenieInfo"]->Get("IsDeepInelastic", TrueDIS); + bool get_coh = m_data->Stores["GenieInfo"]->Get("IsCoherent", TrueCOH); + bool get_mec = m_data->Stores["GenieInfo"]->Get("IsMEC", TrueMEC); + bool get_n = m_data->Stores["GenieInfo"]->Get("NumFSNeutrons", fsNeutrons); + bool get_p = m_data->Stores["GenieInfo"]->Get("NumFSProtons", fsProtons); + bool get_pi0 = m_data->Stores["GenieInfo"]->Get("NumFSPi0", fsPi0); + bool get_piplus = m_data->Stores["GenieInfo"]->Get("NumFSPiPlus", fsPiPlus); + bool get_pipluscher = m_data->Stores["GenieInfo"]->Get("NumFSPiPlusCher", fsPiPlusCher); + bool get_piminus = m_data->Stores["GenieInfo"]->Get("NumFSPiMinus", fsPiMinus); + bool get_piminuscher = m_data->Stores["GenieInfo"]->Get("NumFSPiMinusCher", fsPiMinusCher); + bool get_kplus = m_data->Stores["GenieInfo"]->Get("NumFSKPlus", fsKPlus); + bool get_kpluscher = m_data->Stores["GenieInfo"]->Get("NumFSKPlusCher", fsKPlusCher); + bool get_kminus = m_data->Stores["GenieInfo"]->Get("NumFSKMinus", fsKMinus); + bool get_kminuscher = m_data->Stores["GenieInfo"]->Get("NumFSKMinusCher", fsKMinusCher); + bool get_fsl_vtx = m_data->Stores["GenieInfo"]->Get("FSLeptonVertex", TrueFSLeptonVtx); + bool get_fsl_momentum = m_data->Stores["GenieInfo"]->Get("FSLeptonMomentum", TrueFSLeptonMomentum); + bool get_fsl_time = m_data->Stores["GenieInfo"]->Get("FSLeptonTime", TrueFSLeptonTime); + bool get_fsl_mass = m_data->Stores["GenieInfo"]->Get("FSLeptonMass", TrueFSLeptonMass); + bool get_fsl_pdg = m_data->Stores["GenieInfo"]->Get("FSLeptonPdg", TrueFSLeptonPdg); + bool get_fsl_energy = m_data->Stores["GenieInfo"]->Get("FSLeptonEnergy", TrueFSLeptonEnergy); + std::cout << "get_neutrino_energy: " << get_neutrino_energy << "get_neutrino_vtxx: " << get_neutrino_vtxx << "get_neutrino_vtxy: " << get_neutrino_vtxy << "get_neutrino_vtxz: " << get_neutrino_vtxz << "get_neutrino_time: " << get_neutrino_vtxt << std::endl; + std::cout << "get_q2: " << get_q2 << ", get_cc: " << get_cc << ", get_qel: " << get_qel << ", get_res: " << get_res << ", get_dis: " << get_dis << ", get_coh: " << get_coh << ", get_mec: " << get_mec << std::endl; + std::cout << "get_n: " << get_n << ", get_p: " << get_p << ", get_pi0: " << get_pi0 << ", get_piplus: " << get_piplus << ", get_pipluscher: " << get_pipluscher << ", get_piminus: " << get_piminus << ", get_piminuscher: " << get_piminuscher << ", get_kplus: " << get_kplus << ", get_kpluscher: " << get_kpluscher << ", get_kminus: " << get_kminus << ", get_kminuscher: " << get_kminuscher << std::endl; + std::cout << "get_fsl_vtx: " << get_fsl_vtx << ", get_fsl_momentum: " << get_fsl_momentum << ", get_fsl_time: " << get_fsl_time << ", get_fsl_mass: " << get_fsl_mass << ", get_fsl_pdg: " << get_fsl_pdg << ", get_fsl_energy: " << get_fsl_energy << std::endl; + if (get_neutrino_energy && get_neutrino_mom && get_neutrino_vtxx && get_neutrino_vtxy && get_neutrino_vtxz && get_neutrino_vtxt && get_q2 && get_cc && get_nc && get_qel && get_res && get_dis && get_coh && get_mec && get_n && get_p && get_pi0 && get_piplus && get_pipluscher && get_piminus && get_piminuscher && get_kplus && get_kpluscher && get_kminus && get_kminuscher && get_fsl_vtx && get_fsl_momentum && get_fsl_time && get_fsl_mass && get_fsl_pdg && get_fsl_energy) + { + fTrueNeutrinoEnergy = TrueNeutrinoEnergy; + fTrueNeutrinoMomentum_X = TrueNeutrinoMomentum.X(); + fTrueNeutrinoMomentum_Y = TrueNeutrinoMomentum.Y(); + fTrueNeutrinoMomentum_Z = TrueNeutrinoMomentum.Z(); + fTrueNuIntxVtx_X = TrueNuIntxVtx_X; + fTrueNuIntxVtx_Y = TrueNuIntxVtx_Y; + fTrueNuIntxVtx_Z = TrueNuIntxVtx_Z; + fTrueNuIntxVtx_T = TrueNuIntxVtx_T; + fTrueFSLVtx_X = TrueFSLeptonVtx.X(); + fTrueFSLVtx_Y = TrueFSLeptonVtx.Y(); + fTrueFSLVtx_Z = TrueFSLeptonVtx.Z(); + fTrueFSLMomentum_X = TrueFSLeptonMomentum.X(); + fTrueFSLMomentum_Y = TrueFSLeptonMomentum.Y(); + fTrueFSLMomentum_Z = TrueFSLeptonMomentum.Z(); + fTrueFSLTime = TrueFSLeptonTime; + fTrueFSLMass = TrueFSLeptonMass; + fTrueFSLPdg = TrueFSLeptonPdg; + fTrueFSLEnergy = TrueFSLeptonEnergy; + fTrueQ2 = TrueQ2; + fTrueCC = (TrueCC) ? 1 : 0; + fTrueNC = (TrueNC) ? 1 : 0; + fTrueQEL = (TrueQEL) ? 1 : 0; + fTrueRES = (TrueRES) ? 1 : 0; + fTrueDIS = (TrueDIS) ? 1 : 0; + fTrueCOH = (TrueCOH) ? 1 : 0; + fTrueMEC = (TrueMEC) ? 1 : 0; + fTrueNeutrons = fsNeutrons; + fTrueProtons = fsProtons; + fTruePi0 = fsPi0; + fTruePiPlus = fsPiPlus; + fTruePiPlusCher = fsPiPlusCher; + fTruePiMinus = fsPiMinus; + fTruePiMinusCher = fsPiMinusCher; + fTrueKPlus = fsKPlus; + fTrueKPlusCher = fsKPlusCher; + fTrueKMinus = fsKMinus; + fTrueKMinusCher = fsKMinusCher; + } + else + { + Log("ANNIEEventTreeMaker tool: Did not find GENIE information. Continuing building remaining tree", v_message, ANNIEEventTreeMakerVerbosity); + successful_load = false; + } + } // end if hasGenie + + return successful_load; +} + +void ANNIEEventTreeMaker::FillTruthRecoDiffInfo(bool successful_mcload, bool successful_recoload) +{ + if (!successful_mcload || !successful_recoload) + { + Log("ANNIEEventTreeMaker Tool: Error loading True Muon Vertex or Extended Vertex information. Continuing to build remaining tree", v_message, ANNIEEventTreeMakerVerbosity); + } + else + { + // Make sure MCTruth Information is loaded from store + // Let's fill in stuff from the RecoSummary + fDeltaVtxX = fRecoVtxX - fTrueVtxX; + fDeltaVtxY = fRecoVtxY - fTrueVtxY; + fDeltaVtxZ = fRecoVtxZ - fTrueVtxZ; + fDeltaVtxT = fRecoVtxTime - fTrueVtxTime; + fDeltaVtxR = sqrt(pow(fDeltaVtxX, 2) + pow(fDeltaVtxY, 2) + pow(fDeltaVtxZ, 2)); + fDeltaParallel = fDeltaVtxX * fRecoDirX + fDeltaVtxY * fRecoDirY + fDeltaVtxZ * fRecoDirZ; + fDeltaPerpendicular = sqrt(pow(fDeltaVtxR, 2) - pow(fDeltaParallel, 2)); + fDeltaAzimuth = (fRecoAngle - fTrueAngle) / (TMath::Pi() / 180.0); + fDeltaZenith = (fRecoPhi - fTruePhi) / (TMath::Pi() / 180.0); + double cosphi = fTrueDirX * fRecoDirX + fTrueDirY * fRecoDirY + fTrueDirZ * fRecoDirZ; + double phi = TMath::ACos(cosphi); // radians + double TheAngle = phi / (TMath::Pi() / 180.0); // radians->degrees + fDeltaAngle = TheAngle; + } +} + +void ANNIEEventTreeMaker::RecoSummary() +{ + + // get reconstruction output + double dx = fRecoVtxX - fTrueVtxX; + double dy = fRecoVtxY - fTrueVtxY; + double dz = fRecoVtxZ - fTrueVtxZ; + double dt = fRecoVtxTime - fTrueVtxTime; + double deltaR = sqrt(dx * dx + dy * dy + dz * dz); + double cosphi = 0., phi = 0., DeltaAngle = 0.; + cosphi = fTrueDirX * fRecoDirX + fTrueDirY * fRecoDirY + fTrueDirZ * fRecoDirZ; + phi = TMath::ACos(cosphi); // radians + DeltaAngle = phi / (TMath::Pi() / 180.0); // radians->degrees + std::cout << "============================================================================" << std::endl; + std::cout << " Event number " << fEventNumber << std::endl; + std::cout << " trueVtx=(" << fTrueVtxX << ", " << fTrueVtxY << ", " << fTrueVtxZ << ", " << fTrueVtxTime << std::endl + << " TrueMuonEnergy= " << fTrueMuonEnergy << " Primary Pdg = " << fTruePrimaryPdg << std::endl + << " " << fTrueDirX << ", " << fTrueDirY << ", " << fTrueDirZ << ") " << std::endl; + std::cout << " recoVtx=(" << fRecoVtxX << ", " << fRecoVtxY << ", " << fRecoVtxZ << ", " << fRecoVtxTime << std::endl + << " " << fRecoDirX << ", " << fRecoDirY << ", " << fRecoDirZ << ") " << std::endl; + std::cout << " DeltaR = " << deltaR << "[cm]" << "\t" << " DeltaAngle = " << DeltaAngle << " [degree]" << std::endl; + std::cout << " FOM = " << fRecoVtxFOM << std::endl; + std::cout << " RecoStatus = " << fRecoStatus << std::endl; + std::cout << std::endl; +} diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h index 956e11ab2..9e8823690 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h @@ -5,35 +5,500 @@ #include #include "Tool.h" - +// ROOT includes +#include "TApplication.h" +#include +#include +#include "TFile.h" +#include "TTree.h" +#include "TH1D.h" +#include "TMath.h" +#include "ADCPulse.h" +#include "Waveform.h" +#include "CalibratedADCWaveform.h" +#include "Hit.h" +#include "RecoDigit.h" +#include "ANNIEalgorithms.h" +#include "TimeClass.h" +#include "BeamStatus.h" +#include "PsecData.h" +#include "LAPPDPulse.h" +#include "LAPPDHit.h" /** * \class ANNIEEventTreeMaker * * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. -* -* $Author: B.Richards $ -* $Date: 2019/05/28 10:44:00 $ -* Contact: b.richards@qmul.ac.uk -*/ -class ANNIEEventTreeMaker: public Tool { + * + * $Author: B.Richards $ + * $Date: 2019/05/28 10:44:00 $ + * Contact: b.richards@qmul.ac.uk + */ +class ANNIEEventTreeMaker : public Tool +{ +public: + ANNIEEventTreeMaker(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. - public: + bool LoadEventInfo(); + void LoadBeamInfo(); - ANNIEEventTreeMaker(); ///< Simple constructor - bool Initialise(std::string configfile,DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. - bool Execute(); ///< Execute function used to perform Tool purpose. - bool Finalise(); ///< Finalise function used to clean up resources. + void LoadAllTankHits(); + void LoadSiPMHits(); + void LoadLAPPDInfo(); + void FillLAPPDInfo(); + void FillLAPPDHit(); + void FillLAPPDPulse(); - private: + bool LoadClusterInfo(); + void LoadMRDCluster(); + void LoadMRDInfo(); + void LoadLAPPDRecoInfo(); + void FillLAPPDRecoInfo(); + bool FillMCTruthInfo(); + bool FillTankRecoInfo(); + int LoadMRDTrackReco(int SubEventNumber); + void LoadAllMRDHits(bool isData); + void FillRecoDebugInfo(); + void FillTruthRecoDiffInfo(bool got_mc, bool got_reco); + void RecoSummary(); + void LoadTankClusterHits(std::vector cluster_hits); + void LoadTankClusterHitsMC(std::vector cluster_hits, std::vector cluster_detkeys); + bool LoadTankClusterClassifiers(double cluster_time); -}; + void ResetVariables(); + +private: + // General variables + bool isData = 1; + bool hasGenie; + + int ANNIEEventTreeMakerVerbosity = 0; + int v_error = 0; + int v_warning = 1; + int v_message = 2; + int v_debug = 3; + + int EventNumberIndex = 0; + + // What events will be filled - Triggers + bool fillAllTriggers; // if true, fill all events with any major trigger + // if fillAllTriggers = false: + bool fill_singleTrigger; // if true, only fill events with selected trigger, for example 14 + int fill_singleTriggerWord; + // if fillAllTriggers = false and fill_singleTrigger = false: + vector fill_TriggerWord; // fill events with any of these triggers in this vector + + // What events will be filled - status + bool fillCleanEventsOnly = 0; // Only output events not flagged by EventSelector tool + bool fillLAPPDEventsOnly = 0; // Only fill events with LAPPD data + + // What information will be filled + bool TankHitInfo_fill = 1; + bool TankCluster_fill = 1; + bool cluster_TankHitInfo_fill = 1; + bool MRDHitInfo_fill = 1; + bool LAPPDData_fill = 1; + + // What reco information will be filled + bool MCTruth_fill = 0; // Output the MC truth information + bool TankReco_fill = 0; + bool MRDReco_fill = 1; + bool RecoDebug_fill = 0; // Outputs results of Reconstruction at each step (best fits, FOMs, etc.) + bool muonTruthRecoDiff_fill = 0; // Output difference in tmuonruth and reconstructed values + bool SiPMPulseInfo_fill = 0; + bool LAPPDReco_fill = 1; + bool BeamInfo_fill = 1; + + TFile *fOutput_tfile = nullptr; + TTree *fANNIETree = nullptr; + Geometry *geom = nullptr; + + int processedEvents = 0; + + // Variables for filling the tree + + // EventInfo + int fRunNumber; + int fSubrunNumber; + int fPartFileNumber; + int fRunType = 0; + int fEventNumber; + int fPrimaryTriggerWord; + int trigword; + uint64_t fPrimaryTriggerTime; + vector fGroupedTriggerTime; + vector fGroupedTriggerWord; + int fTriggerword; + int fExtended; + int fTankMRDCoinc; + int fNoVeto; + int fHasTank; + int fHasMRD; + int fHasLAPPD; + + ULong64_t fEventTimeTank; + ULong64_t fEventTimeMRD; + + // beam information + double fPot; + int fBeamok; + double beam_E_TOR860; + double beam_E_TOR875; + double beam_THCURR; + double beam_BTJT2; + double beam_HP875; + double beam_VP875; + double beam_HPTG1; + double beam_VPTG1; + double beam_HPTG2; + double beam_VPTG2; + double beam_BTH2T2; + uint64_t fBeamInfoTime; + int64_t fBeamInfoTimeToTriggerDiff; + + // TankHitInfo_fill + int fNHits = 0; + std::vector fIsFiltered; + std::vector fHitX; + std::vector fHitY; + std::vector fHitZ; + std::vector fHitT; + std::vector fHitQ; + std::vector fHitPE; + std::vector fHitType; + std::vector fHitDetID; + std::vector fHitChankey; + std::vector fHitChankeyMC; + + // SiPMPulseInfo_fill + int fSiPM1NPulses; + int fSiPM2NPulses; + std::vector fSiPMHitQ; + std::vector fSiPMHitT; + std::vector fSiPMHitAmplitude; + std::vector fSiPMNum; + + // LAPPDData_fill + int fLAPPD_Count; + vector fLAPPD_ID; + vector fLAPPD_Beamgate_ns; + vector fLAPPD_Timestamp_ns; + vector fLAPPD_Beamgate_Raw; + vector fLAPPD_Timestamp_Raw; + vector fLAPPD_Offset; + vector fLAPPD_TSCorrection; + vector fLAPPD_BGCorrection; + vector fLAPPD_OSInMinusPS; + + // LAPPD Reco Fill + vector fLAPPDPulseTimeStampUL; + vector fLAPPDPulseBeamgateUL; + vector fLAPPD_IDs; + vector fChannelID; + vector fPulsePeakTime; + vector fPulseCharge; + vector fPulsePeakAmp; + vector fPulseStart; + vector fPulseEnd; + vector fPulseWidth; + vector fPulseSide; + vector fPulseStripNum; + std::map fChannelBaseline; + + vector fLAPPDHitTimeStampUL; + vector fLAPPDHitBeamgateUL; + vector fLAPPDHit_IDs; + vector fLAPPDHitChannel; + vector fLAPPDHitStrip; + vector fLAPPDHitTime; + vector fLAPPDHitAmp; + vector fLAPPDHitParallelPos; + vector fLAPPDHitTransversePos; + vector fLAPPDHitP1StartTime; + vector fLAPPDHitP2StartTime; + vector fLAPPDHitP1EndTime; + vector fLAPPDHitP2EndTime; + + // waveform + vector LAPPDWaveformChankey; + vector waveformMaxValue; + vector waveformRMSValue; + vector waveformMaxFoundNear; + vector waveformMaxNearingValue; + vector waveformMaxTimeBinValue; + + // finished **************************************************** + + // tank cluster information + + int fNumberOfClusters; // how many clusters in this event + // vector fClusterIndex; // index of which cluster this data belongs to + vector fClusterHits; // how many hits in this cluster + vector fClusterChargeV; + vector fClusterTimeV; + vector fClusterPEV; + + vector> fCluster_HitX; // each vector is a cluster, each element is a hit in that cluster + vector> fCluster_HitY; + vector> fCluster_HitZ; + vector> fCluster_HitT; + vector> fCluster_HitQ; + vector> fCluster_HitPE; + vector> fCluster_HitType; + vector> fCluster_HitDetID; + vector> fCluster_HitChankey; + vector> fCluster_HitChankeyMC; + + vector fClusterMaxPEV; + vector fClusterChargePointXV; + vector fClusterChargePointYV; + vector fClusterChargePointZV; + vector fClusterChargeBalanceV; + // MRD cluster information + ULong64_t fEventTimeMRD_Tree; + int fMRDClusterNumber; + int fMRDClusterHits; + double fMRDClusterTime; + double fMRDClusterTimeSigma; + + // MRDHitInfo_fill + int fVetoHit; + std::vector fMRDHitT; + std::vector fMRDHitDetID; + std::vector fMRDHitChankey; + std::vector fMRDHitChankeyMC; + + std::vector fFMVHitT; + std::vector fFMVHitDetID; + std::vector fFMVHitChankey; + std::vector fFMVHitChankeyMC; + + // MRDReco_fill + int fNumMRDClusterTracks; + std::vector fMRDTrackAngle; + std::vector fMRDTrackAngleError; + std::vector fMRDPenetrationDepth; + std::vector fMRDTrackLength; + std::vector fMRDEntryPointRadius; + std::vector fMRDEnergyLoss; + std::vector fMRDEnergyLossError; + std::vector fMRDTrackStartX; + std::vector fMRDTrackStartY; + std::vector fMRDTrackStartZ; + std::vector fMRDTrackStopX; + std::vector fMRDTrackStopY; + std::vector fMRDTrackStopZ; + std::vector fMRDSide; + std::vector fMRDStop; + std::vector fMRDThrough; + std::vector fMRDClusterIndex; + + std::vector fNumClusterTracks; + + // fillCleanEventsOnly + int fEventStatusApplied; + int fEventStatusFlagged; + + // MCTruth_fill + // ************ MC Truth Information **************** // + uint64_t fMCEventNum; + uint16_t fMCTriggerNum; + int fiMCTriggerNum; + // True muon + double fTrueVtxX; + double fTrueVtxY; + double fTrueVtxZ; + double fTrueVtxTime; + double fTrueDirX; + double fTrueDirY; + double fTrueDirZ; + double fTrueAngle; + double fTruePhi; + double fTrueMuonEnergy; + int fTruePrimaryPdg; + double fTrueTrackLengthInWater; + double fTrueTrackLengthInMRD; + std::vector *fTruePrimaryPdgs = nullptr; + std::vector *fTrueNeutCapVtxX = nullptr; + std::vector *fTrueNeutCapVtxY = nullptr; + std::vector *fTrueNeutCapVtxZ = nullptr; + std::vector *fTrueNeutCapNucleus = nullptr; + std::vector *fTrueNeutCapTime = nullptr; + std::vector *fTrueNeutCapGammas = nullptr; + std::vector *fTrueNeutCapE = nullptr; + std::vector *fTrueNeutCapGammaE = nullptr; + int fTrueMultiRing; + + // Genie information for event + double fTrueNeutrinoEnergy; + double fTrueNeutrinoMomentum_X; + double fTrueNeutrinoMomentum_Y; + double fTrueNeutrinoMomentum_Z; + double fTrueNuIntxVtx_X; + double fTrueNuIntxVtx_Y; + double fTrueNuIntxVtx_Z; + double fTrueNuIntxVtx_T; + double fTrueFSLVtx_X; + double fTrueFSLVtx_Y; + double fTrueFSLVtx_Z; + double fTrueFSLMomentum_X; + double fTrueFSLMomentum_Y; + double fTrueFSLMomentum_Z; + double fTrueFSLTime; + double fTrueFSLMass; + int fTrueFSLPdg; + double fTrueFSLEnergy; + double fTrueQ2; + int fTrueCC; + int fTrueNC; + int fTrueQEL; + int fTrueRES; + int fTrueDIS; + int fTrueCOH; + int fTrueMEC; + int fTrueNeutrons; + int fTrueProtons; + int fTruePi0; + int fTruePiPlus; + int fTruePiPlusCher; + int fTruePiMinus; + int fTruePiMinusCher; + int fTrueKPlus; + int fTrueKPlusCher; + int fTrueKMinus; + int fTrueKMinusCher; + + // TankReco_fill + double fRecoVtxX; + double fRecoVtxY; + double fRecoVtxZ; + double fRecoVtxTime; + double fRecoVtxFOM; + double fRecoDirX; + double fRecoDirY; + double fRecoDirZ; + double fRecoAngle; + double fRecoPhi; + int fRecoStatus; + + // RecoDebug_fill + // **************** Full reco chain information ************* // + // seed vertices + std::vector fSeedVtxX; + std::vector fSeedVtxY; + std::vector fSeedVtxZ; + std::vector fSeedVtxFOM; + double fSeedVtxTime; + + // Reco vertex + // Point Position Vertex + double fPointPosX; + double fPointPosY; + double fPointPosZ; + double fPointPosTime; + double fPointPosFOM; + int fPointPosStatus; + double fPointDirX; + double fPointDirY; + double fPointDirZ; + double fPointDirTime; + double fPointDirFOM; + int fPointDirStatus; + + // Point Vertex Finder + double fPointVtxPosX; + double fPointVtxPosY; + double fPointVtxPosZ; + double fPointVtxTime; + double fPointVtxDirX; + double fPointVtxDirY; + double fPointVtxDirZ; + double fPointVtxFOM; + int fPointVtxStatus; + + // muonTruthRecoDiff_fill + // ************* Difference between MC and Truth *********** // + double fDeltaVtxX; + double fDeltaVtxY; + double fDeltaVtxZ; + double fDeltaVtxR; + double fDeltaVtxT; + double fDeltaParallel; + double fDeltaPerpendicular; + double fDeltaAzimuth; + double fDeltaZenith; + double fDeltaAngle; + + // Pion and kaon counts for event + int fPi0Count; + int fPiPlusCount; + int fPiMinusCount; + int fK0Count; + int fKPlusCount; + int fKMinusCount; + + //******************************************************************************************************************** + + // data variables for filling the tree + // Event Info + std::map fDataStreams; + std::map GroupedTrigger; + + // LAPPDData_fill + std::map LAPPDDataMap; + std::map LAPPDBeamgate_ns; + std::map LAPPDTimeStamps_ns; // data and key are the same + std::map LAPPDTimeStampsRaw; + std::map LAPPDBeamgatesRaw; + std::map LAPPDOffsets; + std::map LAPPDTSCorrection; + std::map LAPPDBGCorrection; + std::map LAPPDOSInMinusPS; + + std::map>> lappdPulses; + std::map> lappdHits; + + //******************************************************************************************************************** + + // detector maps, don't clear + std::map *AuxChannelNumToTypeMap; + std::map ChannelKeyToSPEMap; + + std::map pmtid_to_channelkey; + std::map channelkey_to_pmtid; + std::map channelkey_to_mrdpmtid; + std::map mrdpmtid_to_channelkey_data; + std::map channelkey_to_faccpmtid; + std::map faccpmtid_to_channelkey_data; + + //******************************************************************************************************************** + // some left not used objects + + // left for raw data + std::vector fADCWaveformChankeys; + std::vector fADCWaveformSamples; + + // ************ Muon reconstruction level information ******** // + std::string MRDTriggertype; + + // ************* LAPPD RecoInfo *********** // + // left for LAPPD waveforms if needed + std::map> waveformMax; // strip number+30*side, value + std::map> waveformRMS; + std::map> waveformMaxLast; + std::map> waveformMaxNearing; + std::map> waveformMaxTimeBin; + +}; #endif diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp index 7bac3bf63..893331435 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp @@ -1369,7 +1369,7 @@ void LAPPDLoadStore::LoadOffsetsAndCorrections() BGCorrections[key][EventIndex] = static_cast(BGCorrection_tick) - 1000; TSCorrections[key][EventIndex] = static_cast(TSCorrection_tick) - 1000; - if (i % (static_cast(nentries / 10)) == 0) + if (nentries > 10 && i % (static_cast(nentries / 10)) == 0) { cout << "LAPPDStoreReadIn Loading offsets and corrections, " << i << " entries loaded" << endl; cout << "Printing key: " << key << ", EventIndex: " << EventIndex << ", final_offset_ns_0: " << final_offset_ns_0 << ", final_offset_ps_negative_0: " << final_offset_ps_negative_0 << ", BGCorrection_tick: " << BGCorrection_tick << ", TSCorrection_tick: " << TSCorrection_tick << endl; @@ -1401,4 +1401,4 @@ void LAPPDLoadStore::LoadRunInfo() } if (LAPPDStoreReadInVerbosity > 0) cout << "LAPPDStoreReadIn, Loaded run info, runNumber: " << runNumber << ", subRunNumber: " << subRunNumber << ", partFileNumber: " << partFileNumber << ", eventNumberInPF: " << eventNumberInPF << endl; -} \ No newline at end of file +} diff --git a/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp index 105d9669c..0454415d9 100644 --- a/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp +++ b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp @@ -22,6 +22,8 @@ bool ProcessedLAPPDFilter::Initialise(std::string configfile, DataModel &data) saveAllLAPPDEvents = false; m_variables.Get("saveAllLAPPDEvents", saveAllLAPPDEvents); + savePMTClusterEvents = false; + m_variables.Get("savePMTClusterEvents", savePMTClusterEvents); MRDDataName = "FilteredMRDData"; MRDNoVetoDataName = "FilteredMRDNoVetoData"; @@ -30,14 +32,17 @@ bool ProcessedLAPPDFilter::Initialise(std::string configfile, DataModel &data) AllLAPPDDataName = "FilteredAllLAPPDData"; m_variables.Get("AllLAPPDDataName", AllLAPPDDataName); + PMTClusterDataName = "FilteredPMTClusterData"; + m_variables.Get("PMTClusterDataName", PMTClusterDataName); filterType = "MRDtrack"; // MRDtrack and pmt cluster // filterType = "PMTCluster"; // pmt cluster only m_variables.Get("filterType", filterType); - FilteredMRD = new BoostStore(false, 2); // all events with MRD in it //if gotEventMRD = true; - FilteredMRDNoVeto = new BoostStore(false, 2); // all events with MRD but no veto// if gotEventMRD && gotEventMRDNoVeto = true - FilteredAllLAPPD = new BoostStore(false, 2); // all events with LAPPD data + FilteredMRD = new BoostStore(false, 2); // all events with MRD in it //if gotEventMRD = true; + FilteredMRDNoVeto = new BoostStore(false, 2); // all events with MRD but no veto// if gotEventMRD && gotEventMRDNoVeto = true + FilteredAllLAPPD = new BoostStore(false, 2); // all events with LAPPD data + FilteredPMTCluster = new BoostStore(false, 2); // all events with PMT cluster gotEventMRD = false; gotEventMRDNoVeto = false; @@ -49,6 +54,7 @@ bool ProcessedLAPPDFilter::Initialise(std::string configfile, DataModel &data) CurrentExeNumber = 0; pairedEventNumber = 0; PsecDataNumber = 0; + PMTClusterEventNum = 0; return true; } @@ -67,39 +73,44 @@ bool ProcessedLAPPDFilter::Execute() cout << endl; } - if (DataStreams["LAPPD"] == false) - { - return true; - } - if (filterType == "MRDtrack") { - - CurrentExeNumber += 1; - gotEventMRD = false; gotEventPMTCluster = false; - std::map LAPPDBeamgate_ns; - m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); - PsecDataNumber += LAPPDBeamgate_ns.size(); - m_data->Stores["ANNIEEvent"]->Set("LAPPDBeamgate_ns", LAPPDBeamgate_ns); - std::map> *m_all_clusters = nullptr; bool get_clusters = m_data->CStore.Get("ClusterMap", m_all_clusters); if (!get_clusters) { - std::cout << "FiltStage1Event tool: No clusters found!" << std::endl; + std::cout << "ProcessedLAPPDFilter tool: No clusters found!" << std::endl; return false; } if ((int)m_all_clusters->size() > 0) gotEventPMTCluster = true; + if (savePMTClusterEvents && gotEventPMTCluster) + { + GotANNIEEventAndSave(FilteredPMTCluster, PMTClusterDataName); + PMTClusterEventNum += 1; + } + + if (DataStreams["LAPPD"] == false) + { + return true; + } + + CurrentExeNumber += 1; + + std::map LAPPDBeamgate_ns; + m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + PsecDataNumber += LAPPDBeamgate_ns.size(); + m_data->Stores["ANNIEEvent"]->Set("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + std::vector> MrdTimeClusters; bool get_clusters_mrd = m_data->CStore.Get("MrdTimeClusters", MrdTimeClusters); if (!get_clusters_mrd) { - std::cout << "FiltStage1Event tool: No MRD clusters found! Did you run the TimeClustering tool?" << std::endl; + std::cout << "ProcessedLAPPDFilter tool: No MRD clusters found! Did you run the TimeClustering tool?" << std::endl; return false; } if (MrdTimeClusters.size() > 0) @@ -139,7 +150,7 @@ bool ProcessedLAPPDFilter::Execute() if (CurrentExeNumber % 10 == 0) { - cout << "Filter event number: " << CurrentExeNumber << ", PsecDataNumber " << PsecDataNumber << ", events with PMT clusters: " << EventPMTClusterNumber << ", also with MRD tracks: " << EventMRDNumber << ", also with MRD tracks and no veto: " << EventMRDNoVetoNumber << endl; + cout << "Filter event number: " << CurrentExeNumber << ", PsecDataNumber " << PsecDataNumber << ", LAPPD events with PMT clusters: " << EventPMTClusterNumber << ", also with MRD tracks: " << EventMRDNumber << ", also with MRD tracks and no veto: " << EventMRDNoVetoNumber << ", events with PMT cluster (may not have LAPPD): " << PMTClusterEventNum << endl; } m_data->Stores["ANNIEEvent"]->Get("RunNumber", currentRunNumber); @@ -159,7 +170,7 @@ bool ProcessedLAPPDFilter::Execute() bool get_clusters = m_data->CStore.Get("ClusterMap", m_all_clusters); if (!get_clusters) { - std::cout << "FiltStage1Event tool: No clusters found!" << std::endl; + std::cout << "ProcessedLAPPDFilter tool: No clusters found!" << std::endl; return false; } if ((int)m_all_clusters->size() > 0) @@ -222,21 +233,26 @@ bool ProcessedLAPPDFilter::Finalise() FilteredMRD->Close(); FilteredMRDNoVeto->Close(); FilteredAllLAPPD->Close(); + FilteredPMTCluster->Close(); FilteredMRD->Delete(); FilteredMRDNoVeto->Delete(); FilteredAllLAPPD->Delete(); + FilteredPMTCluster->Delete(); if (filterType == "MRDtrack") { cout << "Current Run " << currentRunNumber << endl; cout << "Filter got " << CurrentExeNumber << " events in total" << endl; // this is the total number of events - cout << "Got " << PsecDataNumber << " psec data objects on all LAPPD"<> my_files.txt + echo "${DIR}${RUN}/RAWDataR${RUN}S0p${p}" >> my_files.txt done From 7d1768a7f8ecf6b23361d06e54d7f8c416480f88 Mon Sep 17 00:00:00 2001 From: Yue Date: Tue, 16 Jul 2024 10:35:14 -0500 Subject: [PATCH 069/163] If readed board == 0 or raw data size == 0, skip the loading in LAPPDLoadStore, or there will be a seg fault Changes to be committed: modified: UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp --- UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp index 893331435..a3aa5872d 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp @@ -359,6 +359,12 @@ bool LAPPDLoadStore::Execute() // cout << "ReadedBoards loaded with " << *it << endl; } + if(Raw_buffer.size() == 0 || ReadBoards.size() == 0) + { + m_data->CStore.Set("LAPPDana",false); + cout<<"LAPPD Load Store, find Raw buffer size == 0 or ReadBoards size == 0"<(Raw_buffer.size() / ReadBoards.size()); if (frametype != num_vector_data) { From ac729d824f5d892eebde90c86b7c1fce49f28852 Mon Sep 17 00:00:00 2001 From: Yue Date: Wed, 17 Jul 2024 15:54:37 -0500 Subject: [PATCH 070/163] Changes to be committed: modified: DataModel/LAPPDHit.h modified: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp modified: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h modified: UserTools/LAPPDThresReco/LAPPDThresReco.cpp --- DataModel/LAPPDHit.h | 169 +++++++++++------- .../ANNIEEventTreeMaker.cpp | 29 ++- .../ANNIEEventTreeMaker/ANNIEEventTreeMaker.h | 6 + UserTools/LAPPDThresReco/LAPPDThresReco.cpp | 6 +- 4 files changed, 137 insertions(+), 73 deletions(-) diff --git a/DataModel/LAPPDHit.h b/DataModel/LAPPDHit.h index 5dd752126..7e34c8d7f 100755 --- a/DataModel/LAPPDHit.h +++ b/DataModel/LAPPDHit.h @@ -2,54 +2,81 @@ #ifndef LAPPDHITCLASS_H #define LAPPDHITCLASS_H -#include -#include +#include +#include "LAPPDPulse.h" +#include using std::cout; using std::endl; -class LAPPDHit : public Hit{ - +class LAPPDHit : public Hit +{ + friend class boost::serialization::access; - - public: - LAPPDHit() : Hit(), Position(0), LocalPosition(0) {serialise=true;} - LAPPDHit(int thetubeid, double thetime, double thecharge, std::vector theposition, std::vector thelocalposition) : Hit(thetubeid,thetime,thecharge), Position(theposition), LocalPosition(thelocalposition) {serialise=true;} - LAPPDHit(int thetubeid, double thetime, double thecharge, std::vector theposition, std::vector thelocalposition, double pulse1LastTime, double pulse2LastTime, double pulse1StartTime, double pulse2StartTime) : Hit(thetubeid,thetime,thecharge), Position(theposition), LocalPosition(thelocalposition) {serialise=true; Pulse1LastTime = pulse1LastTime; Pulse2LastTime = pulse2LastTime; Pulse1StartTime = pulse1StartTime; Pulse2StartTime = pulse2StartTime;} + +public: + LAPPDHit() : Hit(), Position(0), LocalPosition(0) { serialise = true; } + LAPPDHit(int thetubeid, double thetime, double thecharge, std::vector theposition, std::vector thelocalposition) : Hit(thetubeid, thetime, thecharge), Position(theposition), LocalPosition(thelocalposition) { serialise = true; } + LAPPDHit(int thetubeid, double thetime, double thecharge, std::vector theposition, std::vector thelocalposition, double pulse1LastTime, double pulse2LastTime, double pulse1StartTime, double pulse2StartTime) : Hit(thetubeid, thetime, thecharge), Position(theposition), LocalPosition(thelocalposition) + { + serialise = true; + Pulse1LastTime = pulse1LastTime; + Pulse2LastTime = pulse2LastTime; + Pulse1StartTime = pulse1StartTime; + Pulse2StartTime = pulse2StartTime; + } + LAPPDHit(int thetubeid, double thetime, double thecharge, std::vector theposition, std::vector thelocalposition, double pulse1LastTime, double pulse2LastTime, double pulse1StartTime, double pulse2StartTime, LAPPDPulse p1, LAPPDPulse p2) : Hit(thetubeid, thetime, thecharge), Position(theposition), LocalPosition(thelocalposition) + { + serialise = true; + Pulse1LastTime = pulse1LastTime; + Pulse2LastTime = pulse2LastTime; + Pulse1StartTime = pulse1StartTime; + Pulse2StartTime = pulse2StartTime; + pulse1 = p1; + pulse2 = p2; + } virtual ~LAPPDHit(){}; - - inline std::vector GetPosition() const {return Position;} - inline std::vector GetLocalPosition() const {return LocalPosition;} - inline void SetPosition(std::vector pos){Position=pos;} - inline void SetLocalPosition(std::vector locpos){LocalPosition=locpos;} - inline double GetPulse1LastTime() const {return Pulse1LastTime;} - inline double GetPulse2LastTime() const {return Pulse2LastTime;} - inline double GetPulse1StartTime() const {return Pulse1StartTime;} - inline double GetPulse2StartTime() const {return Pulse2StartTime;} - - bool Print() { - cout<<"TubeId : "< GetPosition() const { return Position; } + inline std::vector GetLocalPosition() const { return LocalPosition; } + inline void SetPosition(std::vector pos) { Position = pos; } + inline void SetLocalPosition(std::vector locpos) { LocalPosition = locpos; } + inline double GetPulse1LastTime() const { return Pulse1LastTime; } + inline double GetPulse2LastTime() const { return Pulse2LastTime; } + inline double GetPulse1StartTime() const { return Pulse1StartTime; } + inline double GetPulse2StartTime() const { return Pulse2StartTime; } + inline LAPPDPulse GetPulse1() const { return pulse1; } + inline LAPPDPulse GetPulse2() const { return pulse2; } + + bool Print() + { + cout << "TubeId : " << TubeId << endl; + cout << "Time : " << Time << endl; + cout << "X Pos : " << Position.at(0) << endl; + cout << "Y Pos : " << Position.at(1) << endl; + cout << "Z Pos : " << Position.at(2) << endl; + cout << "Parallel Pos : " << LocalPosition.at(0) << endl; + cout << "Transverse Pos : " << LocalPosition.at(1) << endl; + cout << "Charge : " << Charge << endl; return true; } - - protected: + +protected: std::vector Position; std::vector LocalPosition; double Pulse1LastTime; double Pulse2LastTime; double Pulse1StartTime; double Pulse2StartTime; - - template void serialize(Archive & ar, const unsigned int version){ - if(serialise){ + LAPPDPulse pulse1; + LAPPDPulse pulse2; + + template + void serialize(Archive &ar, const unsigned int version) + { + if (serialise) + { ar & TubeId; ar & Time; ar & Position; @@ -60,52 +87,62 @@ class LAPPDHit : public Hit{ }; // Derived classes -class MCLAPPDHit : public LAPPDHit{ - +class MCLAPPDHit : public LAPPDHit +{ + friend class boost::serialization::access; - - public: - MCLAPPDHit() : LAPPDHit(), Parents(std::vector{}) {serialise=true;} - MCLAPPDHit(int thetubeid, double thetime, double thecharge, std::vector theposition, std::vector thelocalposition, std::vector theparents) : LAPPDHit(thetubeid, thetime, thecharge,theposition,thelocalposition), Parents(theparents) {serialise=true;} - - const std::vector* GetParents() const { return &Parents; } - void SetParents(std::vector parentsin){ Parents = parentsin; } - - bool Print() { - cout<<"TubeId : "<{}) { serialise = true; } + MCLAPPDHit(int thetubeid, double thetime, double thecharge, std::vector theposition, std::vector thelocalposition, std::vector theparents) : LAPPDHit(thetubeid, thetime, thecharge, theposition, thelocalposition), Parents(theparents) { serialise = true; } + + const std::vector *GetParents() const { return &Parents; } + void SetParents(std::vector parentsin) { Parents = parentsin; } + + bool Print() + { + cout << "TubeId : " << TubeId << endl; + cout << "Time : " << Time << endl; + cout << "X Pos : " << Position.at(0) << endl; + cout << "Y Pos : " << Position.at(1) << endl; + cout << "Z Pos : " << Position.at(2) << endl; + cout << "Parallel Pos : " << LocalPosition.at(0) << endl; + cout << "Transverse Pos : " << LocalPosition.at(1) << endl; + cout << "Charge : " << Charge << endl; + if (Parents.size()) + { + cout << "Parent MCPartice indices: {"; + for (int parenti = 0; parenti < (int)Parents.size(); ++parenti) + { + cout << Parents.at(parenti); + if ((parenti + 1) < (int)Parents.size()) + cout << ", "; } - cout<<"}"< void serialize(Archive & ar, const unsigned int version){ - if(serialise){ + + template + void serialize(Archive &ar, const unsigned int version) + { + if (serialise) + { ar & TubeId; ar & Time; ar & Position; ar & LocalPosition; ar & Charge; // n.b. at time of writing MCHit stores no additional persistent members - // - it only adds parent MCParticle indices, and these aren't saved... + // - it only adds parent MCParticle indices, and these aren't saved... } } - - protected: + +protected: std::vector Parents; }; diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index a3e01236a..00de87ba3 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -203,6 +203,11 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) fANNIETree->Branch("LAPPDHitP1EndTime", &fLAPPDHitP1EndTime); fANNIETree->Branch("LAPPDHitP2EndTime", &fLAPPDHitP2EndTime); + fANNIETree->Branch("LAPPDHitP1PeakTime", &fLAPPDHitP1PeakTime); + fANNIETree->Branch("LAPPDHitP2PeakTime", &fLAPPDHitP2PeakTime); + fANNIETree->Branch("LAPPDHitP1PeakAmp", &fLAPPDHitP1PeakAmp); + fANNIETree->Branch("LAPPDHitP2PeakAmp", &fLAPPDHitP2PeakAmp); + /* fANNIETree->Branch("LAPPDWaveformChankey", &LAPPDWaveformChankey, "LAPPDWaveformChankey/I"); fANNIETree->Branch("WaveformMax", &waveformMaxValue, "WaveformMax/D"); @@ -616,6 +621,10 @@ void ANNIEEventTreeMaker::ResetVariables() fLAPPDHitP2StartTime.clear(); fLAPPDHitP1EndTime.clear(); fLAPPDHitP2EndTime.clear(); + fLAPPDHitP1PeakTime.clear(); + fLAPPDHitP2PeakTime.clear(); + fLAPPDHitP1PeakAmp.clear(); + fLAPPDHitP2PeakAmp.clear(); LAPPDWaveformChankey.clear(); waveformMaxValue.clear(); @@ -1230,6 +1239,8 @@ void ANNIEEventTreeMaker::FillLAPPDHit() for (int i = 0; i < stripHits.size(); i++) { LAPPDHit thisHit = stripHits.at(i); + LAPPDPulse p1 = thisHit.GetPulse1(); + LAPPDPulse p2 = thisHit.GetPulse2(); fLAPPDHit_IDs.push_back(thisHit.GetTubeId()); fLAPPDHitStrip.push_back(stripno); fLAPPDHitTime.push_back(thisHit.GetTime()); @@ -1242,10 +1253,20 @@ void ANNIEEventTreeMaker::FillLAPPDHit() vector localPosition = thisHit.GetLocalPosition(); fLAPPDHitParallelPos.push_back(localPosition.at(0)); fLAPPDHitTransversePos.push_back(localPosition.at(1)); - fLAPPDHitP1StartTime.push_back(thisHit.GetPulse1StartTime()); - fLAPPDHitP2StartTime.push_back(thisHit.GetPulse2StartTime()); - fLAPPDHitP1EndTime.push_back(thisHit.GetPulse1LastTime()); - fLAPPDHitP2EndTime.push_back(thisHit.GetPulse2LastTime()); + //fLAPPDHitP1StartTime.push_back(thisHit.GetPulse1StartTime()); + //fLAPPDHitP2StartTime.push_back(thisHit.GetPulse2StartTime()); + //fLAPPDHitP1EndTime.push_back(thisHit.GetPulse1LastTime()); + //fLAPPDHitP2EndTime.push_back(thisHit.GetPulse2LastTime()); + + fLAPPDHitP1StartTime.push_back(p1.GetLowRange()); + fLAPPDHitP2StartTime.push_back(p2.GetLowRange()); + fLAPPDHitP1EndTime.push_back(p1.GetHiRange()); + fLAPPDHitP2EndTime.push_back(p2.GetHiRange()); + + fLAPPDHitP1PeakTime.push_back(p1.GetTime()); + fLAPPDHitP2PeakTime.push_back(p2.GetTime()); + fLAPPDHitP1PeakAmp.push_back(p1.GetPeak()); + fLAPPDHitP2PeakAmp.push_back(p2.GetPeak()); } } } diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h index 9e8823690..f653a9350 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h @@ -227,6 +227,12 @@ class ANNIEEventTreeMaker : public Tool vector fLAPPDHitP2StartTime; vector fLAPPDHitP1EndTime; vector fLAPPDHitP2EndTime; + vector fLAPPDHitP1PeakTime; + vector fLAPPDHitP2PeakTime; + vector fLAPPDHitP1PeakAmp; + vector fLAPPDHitP2PeakAmp; + + // waveform vector LAPPDWaveformChankey; diff --git a/UserTools/LAPPDThresReco/LAPPDThresReco.cpp b/UserTools/LAPPDThresReco/LAPPDThresReco.cpp index 29605957e..72cfa41d3 100644 --- a/UserTools/LAPPDThresReco/LAPPDThresReco.cpp +++ b/UserTools/LAPPDThresReco/LAPPDThresReco.cpp @@ -630,17 +630,17 @@ LAPPDHit LAPPDThresReco::MakeHit(LAPPDPulse pulse0, LAPPDPulse pulse1) } if (useRange == -1) { - LAPPDHit hit(tubeID, averageTime, averageAmp, positionInTank, positionOnLAPPD, pulse1LastTime, pulse2LastTime, pulse1StartTime, pulse2StartTime); + LAPPDHit hit(tubeID, averageTime, averageAmp, positionInTank, positionOnLAPPD, pulse1LastTime, pulse2LastTime, pulse1StartTime, pulse2StartTime, pulse0, pulse1); return hit; } else if (useRange == 0) { - LAPPDHit hit(tubeID, averageTimeLow, averageAmp, positionInTank, positionOnLAPPD, pulse1LastTime, pulse2LastTime, pulse1StartTime, pulse2StartTime); + LAPPDHit hit(tubeID, averageTimeLow, averageAmp, positionInTank, positionOnLAPPD, pulse1LastTime, pulse2LastTime, pulse1StartTime, pulse2StartTime, pulse0, pulse1); return hit; } else if (useRange == 1) { - LAPPDHit hit(tubeID, averageTimeHi, averageAmp, positionInTank, positionOnLAPPD, pulse1LastTime, pulse2LastTime, pulse1StartTime, pulse2StartTime); + LAPPDHit hit(tubeID, averageTimeHi, averageAmp, positionInTank, positionOnLAPPD, pulse1LastTime, pulse2LastTime, pulse1StartTime, pulse2StartTime, pulse0, pulse1); return hit; } else From d4eb66d22731f183311ac48a81d7b9a68d2ab3e2 Mon Sep 17 00:00:00 2001 From: Yue Date: Thu, 18 Jul 2024 14:25:46 -0500 Subject: [PATCH 071/163] Fix a small bug in LAPPDLoadStore. When there is no data in Raw_buffer, the tool was supposed to skip, but shouldn't return. Using return will cause the executing speed to be extreamly slow. Changes to be committed: modified: UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp --- UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp index a3aa5872d..339afef46 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp @@ -339,6 +339,14 @@ bool LAPPDLoadStore::Execute() LAPPD_ID = dat.LAPPD_ID; if (LAPPD_ID != SelectedLAPPD && SelectSingleLAPPD) continue; + + if (Raw_buffer.size() == 0 || ReadBoards.size() == 0) + { + m_data->CStore.Set("LAPPDana", false); + cout << "LAPPD Load Store, find Raw buffer size == 0 or ReadBoards size == 0" << endl; + continue; + // return true; + } if (LAPPDStoreReadInVerbosity > 0) { @@ -359,12 +367,6 @@ bool LAPPDLoadStore::Execute() // cout << "ReadedBoards loaded with " << *it << endl; } - if(Raw_buffer.size() == 0 || ReadBoards.size() == 0) - { - m_data->CStore.Set("LAPPDana",false); - cout<<"LAPPD Load Store, find Raw buffer size == 0 or ReadBoards size == 0"<(Raw_buffer.size() / ReadBoards.size()); if (frametype != num_vector_data) { From ee658d3ea858da03d9be405d7c50caeb487b4d5f Mon Sep 17 00:00:00 2001 From: Yue Date: Fri, 26 Jul 2024 18:36:11 -0500 Subject: [PATCH 072/163] add functions about LAPPD PPS information to EventBuilder add tools to get information of RWM and BRF add RWM, BRF, LAPPD PPS information to TreeMaker --- .../ANNIEEventTreeMaker.cpp | 97 ++++- .../ANNIEEventTreeMaker/ANNIEEventTreeMaker.h | 33 +- UserTools/EBLAPPD/EBLAPPD.cpp | 75 +++- UserTools/EBLAPPD/EBLAPPD.h | 17 + UserTools/EBPMT/EBPMT.cpp | 66 ++- UserTools/EBPMT/EBPMT.h | 25 +- UserTools/EBSaver/EBSaver.cpp | 127 ++++++ UserTools/EBSaver/EBSaver.h | 21 +- UserTools/Factory/Factory.cpp | 1 + UserTools/FitRWMWaveform/FitRWMWaveform.cpp | 406 ++++++++++++++++++ UserTools/FitRWMWaveform/FitRWMWaveform.h | 63 +++ UserTools/FitRWMWaveform/README.md | 20 + UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp | 204 ++++++++- UserTools/LAPPDLoadStore/LAPPDLoadStore.h | 27 ++ UserTools/PMTDataDecoder/PMTDataDecoder.cpp | 46 ++ UserTools/PMTDataDecoder/PMTDataDecoder.h | 8 + .../ProcessedLAPPDFilter.cpp | 34 ++ UserTools/Unity.h | 1 + .../ANNIEEventTreeMakerConfig | 1 + .../BeamClusterAnalysis/FitRWMWaveformConfig | 4 + configfiles/BeamClusterAnalysis/ToolsConfig | 9 +- configfiles/EventBuilderV2/EBSaverConfig | 2 +- configfiles/LAPPDProcessedAna/Configs | 2 +- 23 files changed, 1238 insertions(+), 51 deletions(-) create mode 100644 UserTools/FitRWMWaveform/FitRWMWaveform.cpp create mode 100644 UserTools/FitRWMWaveform/FitRWMWaveform.h create mode 100644 UserTools/FitRWMWaveform/README.md create mode 100644 configfiles/BeamClusterAnalysis/FitRWMWaveformConfig diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index 00de87ba3..0017fe987 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -32,6 +32,7 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) m_variables.Get("TankCluster_fill", TankCluster_fill); m_variables.Get("cluster_TankHitInfo_fill", cluster_TankHitInfo_fill); m_variables.Get("MRDHitInfo_fill", MRDHitInfo_fill); + m_variables.Get("RWMBRF_fill", RWMBRF_fill); m_variables.Get("MCTruth_fill", MCTruth_fill); m_variables.Get("MRDReco_fill", MRDReco_fill); @@ -105,6 +106,19 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) fANNIETree->Branch("BeamInfoTimeToTriggerDiff", &fBeamInfoTimeToTriggerDiff, "BeamInfoTimeToTriggerDiff/G"); } + if (RWMBRF_fill) + { + fANNIETree->Branch("RWMRisingStart", &fRWMRisingStart, "fRWMRisingStart/D"); + fANNIETree->Branch("RWMRisingEnd", &fRWMRisingEnd, "fRWMRisingEnd/D"); + fANNIETree->Branch("RWMHalfRising", &fRWMHalfRising, "fRWMHalfRising/D"); + fANNIETree->Branch("RWMFHWM", &fRWMFHWM, "fRWMFHWM/D"); + fANNIETree->Branch("RWMFirstPeak", &fRWMFirstPeak, "fRWMFirstPeak/D"); + + fANNIETree->Branch("BRFFirstPeak", &fBRFFirstPeak, "fBRFFirstPeak/D"); + fANNIETree->Branch("BRFAveragePeak", &fBRFAveragePeak, "fBRFAveragePeak/D"); + fANNIETree->Branch("BRFFirstPeakFit", &fBRFFirstPeakFit, "fBRFFirstPeakFit/D"); + } + //********************************************************// // Tank cluster information @@ -166,6 +180,14 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) fANNIETree->Branch("LAPPD_TSCorrection", &fLAPPD_TSCorrection); fANNIETree->Branch("LAPPD_BGCorrection", &fLAPPD_BGCorrection); fANNIETree->Branch("LAPPD_OSInMinusPS", &fLAPPD_OSInMinusPS); + fANNIETree->Branch("LAPPD_BGPPSBefore", &fLAPPD_BGPPSBefore); + fANNIETree->Branch("LAPPD_BGPPSAfter", &fLAPPD_BGPPSAfter); + fANNIETree->Branch("LAPPD_BGPPSDiff", &fLAPPD_BGPPSDiff); + fANNIETree->Branch("LAPPD_BGPPSMissing", &fLAPPD_BGPPSMissing); + fANNIETree->Branch("LAPPD_TSPPSBefore", &fLAPPD_TSPPSBefore); + fANNIETree->Branch("LAPPD_TSPPSAfter", &fLAPPD_TSPPSAfter); + fANNIETree->Branch("LAPPD_TSPPSDiff", &fLAPPD_TSPPSDiff); + fANNIETree->Branch("LAPPD_TSPPSMissing", &fLAPPD_TSPPSMissing); } // LAPPD reconstruction information @@ -446,6 +468,12 @@ bool ANNIEEventTreeMaker::Execute() LoadBeamInfo(); // done + //****************************** Fill RWM BRF Info *************************************// + if (RWMBRF_fill) + { + LoadRWMBRFInfo(); + } + //****************************** Fill Hit Info *************************************// if (TankHitInfo_fill) { @@ -559,6 +587,16 @@ void ANNIEEventTreeMaker::ResetVariables() fBeamInfoTime = 0; fBeamInfoTimeToTriggerDiff = -9999; + // RWM BRF info + fRWMRisingStart = -9999; + fRWMRisingEnd = -9999; + fRWMHalfRising = -9999; + fRWMFHWM = -9999; + fRWMFirstPeak = -9999; + fBRFFirstPeak = -9999; + fBRFAveragePeak = -9999; + fBRFFirstPeakFit = -9999; + // TankHitInfo fNHits = 0; fIsFiltered.clear(); @@ -592,6 +630,14 @@ void ANNIEEventTreeMaker::ResetVariables() fLAPPD_TSCorrection.clear(); fLAPPD_BGCorrection.clear(); fLAPPD_OSInMinusPS.clear(); + fLAPPD_BGPPSBefore.clear(); + fLAPPD_BGPPSAfter.clear(); + fLAPPD_BGPPSDiff.clear(); + fLAPPD_BGPPSMissing.clear(); + fLAPPD_TSPPSBefore.clear(); + fLAPPD_TSPPSAfter.clear(); + fLAPPD_TSPPSDiff.clear(); + fLAPPD_TSPPSMissing.clear(); // LAPPD Reco Fill fLAPPDPulseTimeStampUL.clear(); @@ -850,6 +896,14 @@ void ANNIEEventTreeMaker::ResetVariables() LAPPDTSCorrection.clear(); LAPPDBGCorrection.clear(); LAPPDOSInMinusPS.clear(); + LAPPDBG_PPSBefore.clear(); + LAPPDBG_PPSAfter.clear(); + LAPPDBG_PPSDiff.clear(); + LAPPDBG_PPSMissing.clear(); + LAPPDTS_PPSBefore.clear(); + LAPPDTS_PPSAfter.clear(); + LAPPDTS_PPSDiff.clear(); + LAPPDTS_PPSMissing.clear(); // LAPPD Reco Fill lappdPulses.clear(); @@ -928,7 +982,6 @@ bool ANNIEEventTreeMaker::LoadEventInfo() if (!gotETMRD) fEventTimeMRD = 0; - if (fillAllTriggers) return true; else if (fill_singleTrigger) @@ -949,7 +1002,6 @@ bool ANNIEEventTreeMaker::LoadEventInfo() } else return true; - } void ANNIEEventTreeMaker::LoadBeamInfo() @@ -975,6 +1027,20 @@ void ANNIEEventTreeMaker::LoadBeamInfo() m_data->Stores["ANNIEEvent"]->Get("BeamInfoTimeToTriggerDiff", fBeamInfoTimeToTriggerDiff); } +void ANNIEEventTreeMaker::LoadRWMBRFInfo() +{ + Log("ANNIEEventTreeMaker Tool: LoadRWMBRFInfo", v_debug, ANNIEEventTreeMakerVerbosity); + m_data->Stores["ANNIEEvent"]->Get("RWMRisingStart", fRWMRisingStart); + m_data->Stores["ANNIEEvent"]->Get("RWMRisingEnd", fRWMRisingEnd); + m_data->Stores["ANNIEEvent"]->Get("RWMHalfRising", fRWMHalfRising); + m_data->Stores["ANNIEEvent"]->Get("RWMFHWM", fRWMFHWM); + m_data->Stores["ANNIEEvent"]->Get("RWMFirstPeak", fRWMFirstPeak); + + m_data->Stores["ANNIEEvent"]->Get("BRFFirstPeak", fBRFFirstPeak); + m_data->Stores["ANNIEEvent"]->Get("BRFAveragePeak", fBRFAveragePeak); + m_data->Stores["ANNIEEvent"]->Get("BRFFirstPeakFit", fBRFFirstPeakFit); +} + void ANNIEEventTreeMaker::LoadAllTankHits() { Log("ANNIEEventTreeMaker Tool: LoadAllTankHits", v_debug, ANNIEEventTreeMakerVerbosity); @@ -1147,6 +1213,15 @@ void ANNIEEventTreeMaker::LoadLAPPDInfo() m_data->Stores["ANNIEEvent"]->Get("LAPPDTSCorrection", LAPPDTSCorrection); m_data->Stores["ANNIEEvent"]->Get("LAPPDBGCorrection", LAPPDBGCorrection); m_data->Stores["ANNIEEvent"]->Get("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSBefore", LAPPDBG_PPSBefore); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSAfter", LAPPDBG_PPSAfter); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSDiff", LAPPDBG_PPSDiff); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSMissing", LAPPDBG_PPSMissing); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSBefore", LAPPDTS_PPSBefore); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSAfter", LAPPDTS_PPSAfter); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSDiff", LAPPDTS_PPSDiff); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSMissing", LAPPDTS_PPSMissing); + if (LAPPDDataMap.size() != 0) { FillLAPPDInfo(); @@ -1176,6 +1251,14 @@ void ANNIEEventTreeMaker::FillLAPPDInfo() fLAPPD_TSCorrection.push_back(LAPPDTSCorrection[key]); fLAPPD_BGCorrection.push_back(LAPPDBGCorrection[key]); fLAPPD_OSInMinusPS.push_back(LAPPDOSInMinusPS[key]); + fLAPPD_BGPPSBefore.push_back(LAPPDBG_PPSBefore[key]); + fLAPPD_BGPPSAfter.push_back(LAPPDBG_PPSAfter[key]); + fLAPPD_BGPPSDiff.push_back(LAPPDBG_PPSDiff[key]); + fLAPPD_BGPPSMissing.push_back(LAPPDBG_PPSMissing[key]); + fLAPPD_TSPPSBefore.push_back(LAPPDTS_PPSBefore[key]); + fLAPPD_TSPPSAfter.push_back(LAPPDTS_PPSAfter[key]); + fLAPPD_TSPPSDiff.push_back(LAPPDTS_PPSDiff[key]); + fLAPPD_TSPPSMissing.push_back(LAPPDTS_PPSMissing[key]); } } @@ -1253,11 +1336,11 @@ void ANNIEEventTreeMaker::FillLAPPDHit() vector localPosition = thisHit.GetLocalPosition(); fLAPPDHitParallelPos.push_back(localPosition.at(0)); fLAPPDHitTransversePos.push_back(localPosition.at(1)); - //fLAPPDHitP1StartTime.push_back(thisHit.GetPulse1StartTime()); - //fLAPPDHitP2StartTime.push_back(thisHit.GetPulse2StartTime()); - //fLAPPDHitP1EndTime.push_back(thisHit.GetPulse1LastTime()); - //fLAPPDHitP2EndTime.push_back(thisHit.GetPulse2LastTime()); - + // fLAPPDHitP1StartTime.push_back(thisHit.GetPulse1StartTime()); + // fLAPPDHitP2StartTime.push_back(thisHit.GetPulse2StartTime()); + // fLAPPDHitP1EndTime.push_back(thisHit.GetPulse1LastTime()); + // fLAPPDHitP2EndTime.push_back(thisHit.GetPulse2LastTime()); + fLAPPDHitP1StartTime.push_back(p1.GetLowRange()); fLAPPDHitP2StartTime.push_back(p2.GetLowRange()); fLAPPDHitP1EndTime.push_back(p1.GetHiRange()); diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h index f653a9350..1a7a4505f 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h @@ -46,6 +46,8 @@ class ANNIEEventTreeMaker : public Tool bool LoadEventInfo(); void LoadBeamInfo(); + void LoadRWMBRFInfo(); + void LoadAllTankHits(); void LoadSiPMHits(); @@ -107,6 +109,7 @@ class ANNIEEventTreeMaker : public Tool bool cluster_TankHitInfo_fill = 1; bool MRDHitInfo_fill = 1; bool LAPPDData_fill = 1; + bool RWMBRF_fill = 1; // What reco information will be filled bool MCTruth_fill = 0; // Output the MC truth information @@ -165,6 +168,17 @@ class ANNIEEventTreeMaker : public Tool uint64_t fBeamInfoTime; int64_t fBeamInfoTimeToTriggerDiff; + // RWM and BRF information + double fRWMRisingStart; // start of the rising of the waveform + double fRWMRisingEnd; // maximum of the rising of the waveform + double fRWMHalfRising; // half of the rising of the waveform, from start to maximum + double fRWMFHWM; // full width at half maximum of the waveform + double fRWMFirstPeak; // first peak of the waveform + + double fBRFFirstPeak; // first peak of the waveform + double fBRFAveragePeak; // average peak of the waveform + double fBRFFirstPeakFit; // first peak of the waveform, Gaussian fit + // TankHitInfo_fill int fNHits = 0; std::vector fIsFiltered; @@ -198,6 +212,14 @@ class ANNIEEventTreeMaker : public Tool vector fLAPPD_TSCorrection; vector fLAPPD_BGCorrection; vector fLAPPD_OSInMinusPS; + vector fLAPPD_BGPPSBefore; + vector fLAPPD_BGPPSAfter; + vector fLAPPD_BGPPSDiff; + vector fLAPPD_BGPPSMissing; + vector fLAPPD_TSPPSBefore; + vector fLAPPD_TSPPSAfter; + vector fLAPPD_TSPPSDiff; + vector fLAPPD_TSPPSMissing; // LAPPD Reco Fill vector fLAPPDPulseTimeStampUL; @@ -232,8 +254,6 @@ class ANNIEEventTreeMaker : public Tool vector fLAPPDHitP1PeakAmp; vector fLAPPDHitP2PeakAmp; - - // waveform vector LAPPDWaveformChankey; vector waveformMaxValue; @@ -470,6 +490,14 @@ class ANNIEEventTreeMaker : public Tool std::map LAPPDTSCorrection; std::map LAPPDBGCorrection; std::map LAPPDOSInMinusPS; + std::map LAPPDBG_PPSBefore; + std::map LAPPDBG_PPSAfter; + std::map LAPPDBG_PPSDiff; + std::map LAPPDBG_PPSMissing; + std::map LAPPDTS_PPSBefore; + std::map LAPPDTS_PPSAfter; + std::map LAPPDTS_PPSDiff; + std::map LAPPDTS_PPSMissing; std::map>> lappdPulses; std::map> lappdHits; @@ -504,7 +532,6 @@ class ANNIEEventTreeMaker : public Tool std::map> waveformMaxLast; std::map> waveformMaxNearing; std::map> waveformMaxTimeBin; - }; #endif diff --git a/UserTools/EBLAPPD/EBLAPPD.cpp b/UserTools/EBLAPPD/EBLAPPD.cpp index 6cf335d23..6875774fb 100644 --- a/UserTools/EBLAPPD/EBLAPPD.cpp +++ b/UserTools/EBLAPPD/EBLAPPD.cpp @@ -41,7 +41,16 @@ bool EBLAPPD::Execute() m_data->CStore.Get("Buffer_LAPPDTSCorrection", Buffer_LAPPDTSCorrection); m_data->CStore.Get("Buffer_LAPPDOffset_minus_ps", Buffer_LAPPDOffset_minus_ps); m_data->CStore.Get("Buffer_LAPPDRunCode", Buffer_RunCode); - + + m_data->CStore.Get("Buffer_LAPPDBG_PPSBefore", Buffer_LAPPDBG_PPSBefore); + m_data->CStore.Get("Buffer_LAPPDBG_PPSAfter", Buffer_LAPPDBG_PPSAfter); + m_data->CStore.Get("Buffer_LAPPDBG_PPSDiff", Buffer_LAPPDBG_PPSDiff); + m_data->CStore.Get("Buffer_LAPPDBG_PPSMissing", Buffer_LAPPDBG_PPSMissing); + m_data->CStore.Get("Buffer_LAPPDTS_PPSBefore", Buffer_LAPPDTS_PPSBefore); + m_data->CStore.Get("Buffer_LAPPDTS_PPSAfter", Buffer_LAPPDTS_PPSAfter); + m_data->CStore.Get("Buffer_LAPPDTS_PPSDiff", Buffer_LAPPDTS_PPSDiff); + m_data->CStore.Get("Buffer_LAPPDTS_PPSMissing", Buffer_LAPPDTS_PPSMissing); + Log("EBLAPPD: Got pairing information from CStore, PairedLAPPDTimeStamps[14] size = " + std::to_string(PairedLAPPDTimeStamps[14].size()), v_message, verbosityEBLAPPD); CleanData(); @@ -80,7 +89,7 @@ bool EBLAPPD::Execute() Matching(14, 14); else Log("EBLAPPD: BeamTriggerGroupped is false, no beam trigger groupped in the grouper, stop matching", v_message, verbosityEBLAPPD); - + bool LaserTriggerGroupped = false; m_data->CStore.Get("LaserTriggerGroupped", LaserTriggerGroupped); if (LaserTriggerGroupped) @@ -101,7 +110,7 @@ bool EBLAPPD::Execute() Matching(31, 46); else Log("EBLAPPD: LEDTriggerGroupped is false, no LED trigger groupped in the grouper, stop matching", v_message, verbosityEBLAPPD); - + bool NuMITriggerGroupped = false; m_data->CStore.Get("NuMITriggerGroupped", NuMITriggerGroupped); if (NuMITriggerGroupped) @@ -132,6 +141,15 @@ bool EBLAPPD::Execute() m_data->CStore.Set("Buffer_LAPPDOffset_minus_ps", Buffer_LAPPDOffset_minus_ps); m_data->CStore.Set("Buffer_LAPPDRunCode", Buffer_RunCode); + m_data->CStore.Set("Buffer_LAPPDBG_PPSBefore", Buffer_LAPPDBG_PPSBefore); + m_data->CStore.Set("Buffer_LAPPDBG_PPSAfter", Buffer_LAPPDBG_PPSAfter); + m_data->CStore.Set("Buffer_LAPPDBG_PPSDiff", Buffer_LAPPDBG_PPSDiff); + m_data->CStore.Set("Buffer_LAPPDBG_PPSMissing", Buffer_LAPPDBG_PPSMissing); + m_data->CStore.Set("Buffer_LAPPDTS_PPSBefore", Buffer_LAPPDTS_PPSBefore); + m_data->CStore.Set("Buffer_LAPPDTS_PPSAfter", Buffer_LAPPDTS_PPSAfter); + m_data->CStore.Set("Buffer_LAPPDTS_PPSDiff", Buffer_LAPPDTS_PPSDiff); + m_data->CStore.Set("Buffer_LAPPDTS_PPSMissing", Buffer_LAPPDTS_PPSMissing); + exeNum++; return true; @@ -156,6 +174,15 @@ bool EBLAPPD::CleanData() LAPPDTSCorrection = 0; LAPPDOffset_minus_ps = 0; + LAPPDBG_PPSBefore = 0; + LAPPDBG_PPSAfter = 0; + LAPPDBG_PPSDiff = 0; + LAPPDBG_PPSMissing = 0; + LAPPDTS_PPSBefore = 0; + LAPPDTS_PPSAfter = 0; + LAPPDTS_PPSDiff = 0; + LAPPDTS_PPSMissing = 0; + return true; } @@ -182,10 +209,27 @@ bool EBLAPPD::LoadLAPPDData() LAPPDBeamgate_ns = LAPPDBeamgate_ns + LAPPDBGCorrection + LAPPDOffset; LAPPDTimestamp_ns = LAPPDTimestamp_ns + LAPPDTSCorrection + LAPPDOffset; + LAPPDBG_PPSBefore = 0; + LAPPDBG_PPSAfter = 0; + LAPPDBG_PPSDiff = 0; + LAPPDBG_PPSMissing = 0; + LAPPDTS_PPSBefore = 0; + LAPPDTS_PPSAfter = 0; + LAPPDTS_PPSDiff = 0; + LAPPDTS_PPSMissing = 0; + m_data->CStore.Get("BG_PPSBefore", LAPPDBG_PPSBefore); + m_data->CStore.Get("BG_PPSAfter", LAPPDBG_PPSAfter); + m_data->CStore.Get("BG_PPSDiff", LAPPDBG_PPSDiff); + m_data->CStore.Get("BG_PPSMissing", LAPPDBG_PPSMissing); + m_data->CStore.Get("TS_PPSBefore", LAPPDTS_PPSBefore); + m_data->CStore.Get("TS_PPSAfter", LAPPDTS_PPSAfter); + m_data->CStore.Get("TS_PPSDiff", LAPPDTS_PPSDiff); + m_data->CStore.Get("TS_PPSMissing", LAPPDTS_PPSMissing); + if (verbosityEBLAPPD > 1) { cout << "Processing new LAPPD data from store" << endl; - cout << "Got info: LAPPDBeamgate_Raw: " << LAPPDBeamgate_Raw << ", LAPPDTimestamp_Raw: " << LAPPDTimestamp_Raw << ", LAPPDBGCorrection: " << LAPPDBGCorrection << ", LAPPDTSCorrection: " << LAPPDTSCorrection << ", LAPPDOffset: " << LAPPDOffset << ", LAPPDOffset_minus_ps: " << LAPPDOffset_minus_ps << endl; + cout << "Got info: LAPPDBeamgate_Raw: " << LAPPDBeamgate_Raw << ", LAPPDTimestamp_Raw: " << LAPPDTimestamp_Raw << ", LAPPDBGCorrection: " << LAPPDBGCorrection << ", LAPPDTSCorrection: " << LAPPDTSCorrection << ", LAPPDOffset: " << LAPPDOffset << ", LAPPDOffset_minus_ps: " << LAPPDOffset_minus_ps << ", LAPPDBG_PPSBefore: " << LAPPDBG_PPSBefore << ", LAPPDBG_PPSAfter: " << LAPPDBG_PPSAfter << ", LAPPDBG_PPSDiff: " << LAPPDBG_PPSDiff << ", LAPPDBG_PPSMissing: " << LAPPDBG_PPSMissing << ", LAPPDTS_PPSBefore: " << LAPPDTS_PPSBefore << ", LAPPDTS_PPSAfter: " << LAPPDTS_PPSAfter << ", LAPPDTS_PPSDiff: " << LAPPDTS_PPSDiff << ", LAPPDTS_PPSMissing: " << LAPPDTS_PPSMissing << endl; cout << "LAPPDBeamgate_ns: " << LAPPDBeamgate_ns << endl; cout << "LAPPDTimestamp_ns: " << LAPPDTimestamp_ns << endl; } @@ -206,8 +250,20 @@ bool EBLAPPD::LoadLAPPDData() Buffer_LAPPDOffset_minus_ps.push_back(LAPPDOffset_minus_ps); Buffer_RunCode.push_back(currentRunCode); + Buffer_LAPPDBG_PPSBefore.push_back(LAPPDBG_PPSBefore); + Buffer_LAPPDBG_PPSAfter.push_back(LAPPDBG_PPSAfter); + Buffer_LAPPDBG_PPSDiff.push_back(LAPPDBG_PPSDiff); + Buffer_LAPPDBG_PPSMissing.push_back(LAPPDBG_PPSMissing); + Buffer_LAPPDTS_PPSBefore.push_back(LAPPDTS_PPSBefore); + Buffer_LAPPDTS_PPSAfter.push_back(LAPPDTS_PPSAfter); + Buffer_LAPPDTS_PPSDiff.push_back(LAPPDTS_PPSDiff); + Buffer_LAPPDTS_PPSMissing.push_back(LAPPDTS_PPSMissing); + MatchBuffer_LAPPDTimestamp_ns.push_back(LAPPDTimestamp_ns); + if (LAPPDTS_PPSMissing != LAPPDBG_PPSMissing) + Log("EBLAPPD: PPS missing in BG and TS are different, BG: " + std::to_string(LAPPDBG_PPSMissing) + ", TS: " + std::to_string(LAPPDTS_PPSMissing), v_warning, verbosityEBLAPPD); + Log("EBLAPPD: Loaded LAPPD data to buffer, Buffer_LAPPDData size after this load is now " + std::to_string(Buffer_LAPPDData.size()), v_message, verbosityEBLAPPD); } @@ -221,7 +277,7 @@ bool EBLAPPD::Matching(int targetTrigger, int matchToTrack) std::map>> GroupedTriggersInTotal; // each map is a group of triggers, with the key is the target trigger word m_data->CStore.Get("GroupedTriggersInTotal", GroupedTriggersInTotal); - //print how many trigger groups in each track + // print how many trigger groups in each track vector matchedLAPPDTimes; vector indexToRemove; @@ -251,11 +307,11 @@ bool EBLAPPD::Matching(int targetTrigger, int matchToTrack) for (std::pair>> pair : GroupedTriggersInTotal) { int TrackTriggerWord = pair.first; - if(matchedNumberInTrack.find(TrackTriggerWord) == matchedNumberInTrack.end()) + if (matchedNumberInTrack.find(TrackTriggerWord) == matchedNumberInTrack.end()) matchedNumberInTrack.emplace(TrackTriggerWord, 0); if (TrackTriggerWord != matchToTrack && !matchToAllTriggers) { - //Log("EBLAPPD: Skipping TrackTriggerWord " + std::to_string(TrackTriggerWord), v_debug, verbosityEBLAPPD); + // Log("EBLAPPD: Skipping TrackTriggerWord " + std::to_string(TrackTriggerWord), v_debug, verbosityEBLAPPD); continue; } vector> GroupedTriggers = pair.second; @@ -312,12 +368,11 @@ bool EBLAPPD::Matching(int targetTrigger, int matchToTrack) } Log("EBLAPPD: Finished removing paired LAPPD data from match buffer, MatchBuffer_LAPPDTimestamp_ns size is now " + std::to_string(MatchBuffer_LAPPDTimestamp_ns.size()), v_message, verbosityEBLAPPD); - //print all elements in matchedNumberInTrack with key and value - for(std::pair pair : matchedNumberInTrack) + // print all elements in matchedNumberInTrack with key and value + for (std::pair pair : matchedNumberInTrack) { Log("EBLAPPD: Match finished, matched number in Track " + std::to_string(pair.first) + " is = " + std::to_string(pair.second), v_message, verbosityEBLAPPD); } - return true; } \ No newline at end of file diff --git a/UserTools/EBLAPPD/EBLAPPD.h b/UserTools/EBLAPPD/EBLAPPD.h index fa5326200..03fa49b97 100644 --- a/UserTools/EBLAPPD/EBLAPPD.h +++ b/UserTools/EBLAPPD/EBLAPPD.h @@ -43,6 +43,15 @@ class EBLAPPD : public Tool int LAPPDBGCorrection; int LAPPDTSCorrection; int LAPPDOffset_minus_ps; + uint64_t LAPPDBG_PPSBefore; + uint64_t LAPPDBG_PPSAfter; + uint64_t LAPPDBG_PPSDiff; + int LAPPDBG_PPSMissing; + uint64_t LAPPDTS_PPSBefore; + uint64_t LAPPDTS_PPSAfter; + uint64_t LAPPDTS_PPSDiff; + int LAPPDTS_PPSMissing; + vector MatchBuffer_LAPPDTimestamp_ns; // used to indexing data for unmatched @@ -57,6 +66,14 @@ class EBLAPPD : public Tool vector Buffer_LAPPDTSCorrection; vector Buffer_LAPPDOffset_minus_ps; vector Buffer_RunCode; + vector Buffer_LAPPDBG_PPSBefore; + vector Buffer_LAPPDBG_PPSAfter; + vector Buffer_LAPPDBG_PPSDiff; + vector Buffer_LAPPDBG_PPSMissing; + vector Buffer_LAPPDTS_PPSBefore; + vector Buffer_LAPPDTS_PPSAfter; + vector Buffer_LAPPDTS_PPSDiff; + vector Buffer_LAPPDTS_PPSMissing; std::map> PairedCTCTimeStamps; std::map> PairedLAPPD_TriggerIndex; diff --git a/UserTools/EBPMT/EBPMT.cpp b/UserTools/EBPMT/EBPMT.cpp index b0cd4dd53..ba6c9469e 100644 --- a/UserTools/EBPMT/EBPMT.cpp +++ b/UserTools/EBPMT/EBPMT.cpp @@ -26,6 +26,13 @@ bool EBPMT::Initialise(std::string configfile, DataModel &data) NumWavesInCompleteSet = 140; FinishedHits = new std::map> *>(); + RWMRawWaveforms = new std::map>(); + BRFRawWaveforms = new std::map>(); + + saveRWMWaveforms = true; + saveBRFWaveforms = true; + m_variables.Get("saveRWMWaveforms", saveRWMWaveforms); + m_variables.Get("saveBRFWaveforms", saveBRFWaveforms); return true; } @@ -36,20 +43,28 @@ bool EBPMT::Execute() bool gotHits = m_data->CStore.Get("InProgressHits", InProgressHits); bool gotChkey = m_data->CStore.Get("InProgressChkey", InProgressChkey); - if (exeNum % 80 == 0 && exeNum!=0) + m_data->CStore.Get("RWMRawWaveforms", RWMRawWaveforms); + m_data->CStore.Get("BRFRawWaveforms", BRFRawWaveforms); + Log("EBPMT: Got RWMRawWaveforms size: " + std::to_string(RWMRawWaveforms->size()), v_message, verbosityEBPMT); + Log("EBPMT: Got BRFRawWaveforms size: " + std::to_string(BRFRawWaveforms->size()), v_message, verbosityEBPMT); + + if (exeNum % 80 == 0 && exeNum != 0) { - //80 is arbitrary, because 6*80 = 480 around, close, and smaller than the pairing exe number, exePerMatch default 500 + // 80 is arbitrary, because 6*80 = 480 around, close, and smaller than the pairing exe number, exePerMatch default 500 Log("EBPMT: exeNum: " + std::to_string(exeNum) + " Before loading, apply a VMEOffset correction", v_message, verbosityEBPMT); Log("EBPMT: before apply the VME offset correction, the size of FinishedHits is " + std::to_string(FinishedHits->size()), v_message, verbosityEBPMT); m_data->CStore.Get("InProgressHitsAux", InProgressHitsAux); m_data->CStore.Get("InProgressRecoADCHits", InProgressRecoADCHits); m_data->CStore.Get("InProgressRecoADCHitsAux", InProgressRecoADCHitsAux); + CorrectVMEOffset(); m_data->CStore.Set("InProgressHits", InProgressHits); m_data->CStore.Set("InProgressChkey", InProgressChkey); m_data->CStore.Set("InProgressHitsAux", InProgressHitsAux); m_data->CStore.Set("InProgressRecoADCHits", InProgressRecoADCHits); m_data->CStore.Set("InProgressRecoADCHitsAux", InProgressRecoADCHitsAux); + m_data->CStore.Set("RWMRawWaveforms", RWMRawWaveforms); + m_data->CStore.Set("BRFRawWaveforms", BRFRawWaveforms); } m_data->CStore.Get("PairedPMTTriggerTimestamp", PairedCTCTimeStamps); @@ -67,6 +82,8 @@ bool EBPMT::Execute() Log("EBPMT: got inprogress hits and chkey with size " + std::to_string(InProgressHits->size()) + " and " + std::to_string(InProgressChkey->size()), v_message, verbosityEBPMT); vector PMTEmplacedHitTimes; + vector RWMEmplacedTimes; + vector BRFEmplacedTimes; for (std::pair> *> p : *InProgressHits) { @@ -175,7 +192,6 @@ bool EBPMT::Execute() Log("EBPMT: after apply the VME offset correction and loading, the size of FinishedHits is " + std::to_string(FinishedHits->size()), v_message, verbosityEBPMT); } - exeNum++; if (exeNum % 50 == 0) @@ -317,6 +333,24 @@ bool EBPMT::Matching(int targetTrigger, int matchToTrack) for (uint64_t PMTCounterTimeNs : matchedHitTimes) { FinishedHits->erase(PMTCounterTimeNs); + + if (saveRWMWaveforms) + { + // check does RWMRawWaveforms have key PMTCounterTimeNs, if not, print a log waring and skip + if (RWMRawWaveforms->find(PMTCounterTimeNs) == RWMRawWaveforms->end()) + { + Log("EBPMT: After matching, RWMRawWaveforms does not have key PMTCounterTimeNs: " + std::to_string(PMTCounterTimeNs), v_warning, verbosityEBPMT); + } + } + + if (saveBRFWaveforms) + { + // check does BRFRawWaveforms have key PMTCounterTimeNs, if not, print a log waring and skip + if (BRFRawWaveforms->find(PMTCounterTimeNs) == BRFRawWaveforms->end()) + { + Log("EBPMT: After matching, BRFRawWaveforms does not have key PMTCounterTimeNs: " + std::to_string(PMTCounterTimeNs), v_warning, verbosityEBPMT); + } + } } Log("EBPMT: after erase, left number of unfinished hitmaps in FinishedHits: " + std::to_string(FinishedHits->size()), v_message, verbosityEBPMT); @@ -329,14 +363,14 @@ void EBPMT::CorrectVMEOffset() vector timestamps; // all current timestamps std::map timestamps_to_shift; // timestamps need to be shifted - //if InProgressHits size is 0, return + // if InProgressHits size is 0, return if (InProgressHits->size() == 0) { Log("EBPMT: InProgressHits size is 0, return", v_message, verbosityEBPMT); return; } - //insert the key of std::map> *> *InProgressHits; to timestamps + // insert the key of std::map> *> *InProgressHits; to timestamps for (std::pair> *> p : *InProgressHits) { timestamps.push_back(p.first); @@ -377,6 +411,7 @@ void EBPMT::CorrectVMEOffset() Log("EBPMT: Found " + std::to_string(timestamps_to_shift.size()) + " timestamps to shift", v_message, verbosityEBPMT); // go through timestamps_to_shift, for each pair, shift the hit map in the first smaller timestamp to the second larger timestamp // apply on InProgressHits, InProgressHitsAux, InProgressChkey, InProgressRecoADCHits, InProgressRecoADCHitsAux + // also need to apply on RWMRawWaveforms and BRFRawWaveforms if (InProgressHitsAux != NULL && InProgressRecoADCHitsAux != NULL) { // InProgressHitsAux,InProgressRecoADCHitsAux may not exist yet for (std::map::iterator it = timestamps_to_shift.begin(); it != timestamps_to_shift.end(); it++) @@ -418,7 +453,26 @@ void EBPMT::CorrectVMEOffset() (*InProgressRecoADCHitsAux)[LargerMapTS] = SecondRecoADCHitsAux; InProgressRecoADCHitsAux->erase(SmallerMapTS); - correctionApplied++; + if (saveRWMWaveforms) + { + // if found SmallerMapTS in RWMRawWaveforms, then change it to LargerMapTS + if (RWMRawWaveforms->find(SmallerMapTS) != RWMRawWaveforms->end()) + { + (*RWMRawWaveforms)[LargerMapTS] = (*RWMRawWaveforms)[SmallerMapTS]; + RWMRawWaveforms->erase(SmallerMapTS); + } + } + if (saveBRFWaveforms) + { + // if found SmallerMapTS in BRFRawWaveforms, then change it to LargerMapTS + if (BRFRawWaveforms->find(SmallerMapTS) != BRFRawWaveforms->end()) + { + (*BRFRawWaveforms)[LargerMapTS] = (*BRFRawWaveforms)[SmallerMapTS]; + BRFRawWaveforms->erase(SmallerMapTS); + } + + correctionApplied++; + } } } Log("EBPMT: Corrected VME Offset for " + std::to_string(correctionApplied) + " timestamps", v_message, verbosityEBPMT); diff --git a/UserTools/EBPMT/EBPMT.h b/UserTools/EBPMT/EBPMT.h index 0a6242f7a..90d04f8c4 100644 --- a/UserTools/EBPMT/EBPMT.h +++ b/UserTools/EBPMT/EBPMT.h @@ -34,25 +34,27 @@ class EBPMT : public Tool uint64_t matchTolerance_ns; int currentRunCode; - - std::map>*> *FinishedHits; //Key: {MTCTime}, value: map of Hit distributions - std::map AlmostCompleteWaveforms; + std::map> *> *FinishedHits; // Key: {MTCTime}, value: map of Hit distributions + std::map> *FinishedRWMWaveforms; // Key: {MTCTime}, value: RWM waveform + std::map> *FinishedBRFWaveforms; // Key: {MTCTime}, value: BRF waveform + + std::map AlmostCompleteWaveforms; std::map> *> *InProgressHits; // Key: {MTCTime}, value: map of Hit distributions std::map> *InProgressChkey; // Key: {MTCTime}, value: vector of in progress chankeys - //only used for VME offset correction + // only used for VME offset correction std::map> *> *InProgressHitsAux; // Key: {MTCTime}, value: map of Hit distributions std::map>>> *InProgressRecoADCHits; // Key: {MTCTime}, value: map of found pulses std::map>>> *InProgressRecoADCHitsAux; // Key: {MTCTime}, value: map of found pulses + std::map> *RWMRawWaveforms; // Key: MTCTime, Value: RWM waveform + std::map> *BRFRawWaveforms; // Key: MTCTime, Value: BRF waveform - - std::map> PairedCTCTimeStamps; - std::map> PairedPMT_TriggerIndex; - std::map> PairedPMTTimeStamps; - std::map PMTHitmapRunCode; // Key: {MTCTime}, value: RunCode - + std::map> PairedCTCTimeStamps; + std::map> PairedPMT_TriggerIndex; + std::map> PairedPMTTimeStamps; + std::map PMTHitmapRunCode; // Key: {MTCTime}, value: RunCode int v_message = 1; int v_warning = 2; @@ -68,6 +70,9 @@ class EBPMT : public Tool int thisRunNum; int exePerMatch = 500; bool matchToAllTriggers; + + bool saveRWMWaveforms; + bool saveBRFWaveforms; }; #endif diff --git a/UserTools/EBSaver/EBSaver.cpp b/UserTools/EBSaver/EBSaver.cpp index 705570555..11f2ce8ec 100644 --- a/UserTools/EBSaver/EBSaver.cpp +++ b/UserTools/EBSaver/EBSaver.cpp @@ -35,6 +35,11 @@ bool EBSaver::Initialise(std::string configfile, DataModel &data) saveBeamInfo = true; m_variables.Get("saveBeamInfo", saveBeamInfo); + saveRawBRFWaveform = true; + m_variables.Get("saveRawBRFWaveform", saveRawBRFWaveform); + saveRawRWMWaveform = true; + m_variables.Get("saveRawRWMWaveform", saveRawRWMWaveform); + ANNIEEvent = new BoostStore(false, 2); exeNumber = 0; @@ -66,6 +71,9 @@ bool EBSaver::Initialise(std::string configfile, DataModel &data) InProgressHitsAux = new std::map> *>; FinishedRawAcqSize = new std::map>>; + RWMRawWaveforms = new std::map>; + BRFRawWaveforms = new std::map>; + if (saveBeamInfo) { Log("EBSaver: saveBeamInfo is true, loading Beam Info", v_message, verbosityEBSaver); @@ -753,6 +761,41 @@ bool EBSaver::SavePMTData(uint64_t PMTTime) ANNIEEvent->Set("RecoAuxADCData", PMTRecoADCHitsAux); ANNIEEvent->Set("RawAcqSize", PMTRawAcqSize); + if(saveRawRWMWaveform) + { + //find PMTTime as key in RWMRawWaveforms, if found, save it, if not, save an empty vector + if (RWMRawWaveforms->find(PMTTime) != RWMRawWaveforms->end() && RWMRawWaveforms->at(PMTTime).size() > 0) + { + std::vector RWMRawWaveform = RWMRawWaveforms->at(PMTTime); + ANNIEEvent->Set("RWMRawWaveform", RWMRawWaveform); + Log("EBSaver: Saved RWM data with PMTTime " + std::to_string(PMTTime), v_debug, verbosityEBSaver); + RWMRawWaveforms->erase(PMTTime); + } + else + { + std::vector RWMRawWaveform; + ANNIEEvent->Set("RWMRawWaveform", RWMRawWaveform); + Log("EBSaver: Saved empty RWM data with PMTTime " + std::to_string(PMTTime), v_debug, verbosityEBSaver); + } + } + if(saveRawBRFWaveform) + { + //find PMTTime as key in BRFRawWaveforms, if found, save it, if not, save an empty vector + if (BRFRawWaveforms->find(PMTTime) != BRFRawWaveforms->end() && BRFRawWaveforms->at(PMTTime).size() > 0) + { + std::vector BRFRawWaveform = BRFRawWaveforms->at(PMTTime); + ANNIEEvent->Set("BRFRawWaveform", BRFRawWaveform); + Log("EBSaver: Saved BRF data with PMTTime " + std::to_string(PMTTime), v_debug, verbosityEBSaver); + BRFRawWaveforms->erase(PMTTime); + } + else + { + std::vector BRFRawWaveform; + ANNIEEvent->Set("BRFRawWaveform", BRFRawWaveform); + Log("EBSaver: Saved empty BRF data with PMTTime " + std::to_string(PMTTime), v_debug, verbosityEBSaver); + } + } + savedPMTHitMapNumber++; // erase the built data from original data buffer @@ -859,6 +902,14 @@ bool EBSaver::SaveLAPPDData(uint64_t LAPPDTime) std::map LAPPDTSCorrection; std::map LAPPDBGCorrection; std::map LAPPDOSInMinusPS; + std::map LAPPDBG_PPSBefore; + std::map LAPPDBG_PPSAfter; + std::map LAPPDBG_PPSDiff; + std::map LAPPDBG_PPSMissing; + std::map LAPPDTS_PPSBefore; + std::map LAPPDTS_PPSAfter; + std::map LAPPDTS_PPSDiff; + std::map LAPPDTS_PPSMissing; bool gotMap = ANNIEEvent->Get("LAPPDDataMap", LAPPDDataMap); bool gotBeamgates_ns = ANNIEEvent->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); @@ -869,6 +920,14 @@ bool EBSaver::SaveLAPPDData(uint64_t LAPPDTime) bool gotTSCorrection = ANNIEEvent->Get("LAPPDTSCorrection", LAPPDTSCorrection); bool gotDBGCorrection = ANNIEEvent->Get("LAPPDBGCorrection", LAPPDBGCorrection); bool gotOSInMinusPS = ANNIEEvent->Get("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + bool gotBG_PPSBefore = ANNIEEvent->Get("LAPPDBG_PPSBefore", LAPPDBG_PPSBefore); + bool gotBG_PPSAfter = ANNIEEvent->Get("LAPPDBG_PPSAfter", LAPPDBG_PPSAfter); + bool gotBG_PPSDiff = ANNIEEvent->Get("LAPPDBG_PPSDiff", LAPPDBG_PPSDiff); + bool gotBG_PPSMissing = ANNIEEvent->Get("LAPPDBG_PPSMissing", LAPPDBG_PPSMissing); + bool gotTS_PPSBefore = ANNIEEvent->Get("LAPPDTS_PPSBefore", LAPPDTS_PPSBefore); + bool gotTS_PPSAfter = ANNIEEvent->Get("LAPPDTS_PPSAfter", LAPPDTS_PPSAfter); + bool gotTS_PPSDiff = ANNIEEvent->Get("LAPPDTS_PPSDiff", LAPPDTS_PPSDiff); + bool gotTS_PPSMissing = ANNIEEvent->Get("LAPPDTS_PPSMissing", LAPPDTS_PPSMissing); LAPPDDataMap.emplace(LAPPDTime, Buffer_LAPPDData.at(index)); LAPPDBeamgate_ns.emplace(LAPPDTime, Buffer_LAPPDBeamgate_ns.at(index)); @@ -879,6 +938,19 @@ bool EBSaver::SaveLAPPDData(uint64_t LAPPDTime) LAPPDTSCorrection.emplace(LAPPDTime, Buffer_LAPPDTSCorrection.at(index)); LAPPDBGCorrection.emplace(LAPPDTime, Buffer_LAPPDBGCorrection.at(index)); LAPPDOSInMinusPS.emplace(LAPPDTime, Buffer_LAPPDOffset_minus_ps.at(index)); + LAPPDBG_PPSBefore.emplace(LAPPDTime, Buffer_LAPPDBG_PPSBefore.at(index)); + LAPPDBG_PPSAfter.emplace(LAPPDTime, Buffer_LAPPDBG_PPSAfter.at(index)); + LAPPDBG_PPSDiff.emplace(LAPPDTime, Buffer_LAPPDBG_PPSDiff.at(index)); + LAPPDBG_PPSMissing.emplace(LAPPDTime, Buffer_LAPPDBG_PPSMissing.at(index)); + LAPPDTS_PPSBefore.emplace(LAPPDTime, Buffer_LAPPDTS_PPSBefore.at(index)); + LAPPDTS_PPSAfter.emplace(LAPPDTime, Buffer_LAPPDTS_PPSAfter.at(index)); + LAPPDTS_PPSDiff.emplace(LAPPDTime, Buffer_LAPPDTS_PPSDiff.at(index)); + LAPPDTS_PPSMissing.emplace(LAPPDTime, Buffer_LAPPDTS_PPSMissing.at(index)); + + if(Buffer_LAPPDTS_PPSMissing.at(index)!= Buffer_LAPPDBG_PPSMissing.at(index)) + { + Log("EBSaver: LAPPDTS_PPSMissing is different from LAPPDBG_PPSMissing, LAPPDTS_PPSMissing " + std::to_string(Buffer_LAPPDTS_PPSMissing.at(index)) + " LAPPDBG_PPSMissing " + std::to_string(Buffer_LAPPDBG_PPSMissing.at(index)), v_message, verbosityEBSaver); + } ANNIEEvent->Set("LAPPDDataMap", LAPPDDataMap); ANNIEEvent->Set("LAPPDBeamgate_ns", LAPPDBeamgate_ns); @@ -889,6 +961,14 @@ bool EBSaver::SaveLAPPDData(uint64_t LAPPDTime) ANNIEEvent->Set("LAPPDTSCorrection", LAPPDTSCorrection); ANNIEEvent->Set("LAPPDBGCorrection", LAPPDBGCorrection); ANNIEEvent->Set("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + ANNIEEvent->Set("LAPPDBG_PPSBefore", LAPPDBG_PPSBefore); + ANNIEEvent->Set("LAPPDBG_PPSAfter", LAPPDBG_PPSAfter); + ANNIEEvent->Set("LAPPDBG_PPSDiff", LAPPDBG_PPSDiff); + ANNIEEvent->Set("LAPPDBG_PPSMissing", LAPPDBG_PPSMissing); + ANNIEEvent->Set("LAPPDTS_PPSBefore", LAPPDTS_PPSBefore); + ANNIEEvent->Set("LAPPDTS_PPSAfter", LAPPDTS_PPSAfter); + ANNIEEvent->Set("LAPPDTS_PPSDiff", LAPPDTS_PPSDiff); + ANNIEEvent->Set("LAPPDTS_PPSMissing", LAPPDTS_PPSMissing); savedLAPPDNumber++; @@ -902,6 +982,14 @@ bool EBSaver::SaveLAPPDData(uint64_t LAPPDTime) Buffer_LAPPDTSCorrection.erase(Buffer_LAPPDTSCorrection.begin() + index); Buffer_LAPPDBGCorrection.erase(Buffer_LAPPDBGCorrection.begin() + index); Buffer_LAPPDOffset_minus_ps.erase(Buffer_LAPPDOffset_minus_ps.begin() + index); + Buffer_LAPPDBG_PPSBefore.erase(Buffer_LAPPDBG_PPSBefore.begin() + index); + Buffer_LAPPDBG_PPSAfter.erase(Buffer_LAPPDBG_PPSAfter.begin() + index); + Buffer_LAPPDBG_PPSDiff.erase(Buffer_LAPPDBG_PPSDiff.begin() + index); + Buffer_LAPPDBG_PPSMissing.erase(Buffer_LAPPDBG_PPSMissing.begin() + index); + Buffer_LAPPDTS_PPSBefore.erase(Buffer_LAPPDTS_PPSBefore.begin() + index); + Buffer_LAPPDTS_PPSAfter.erase(Buffer_LAPPDTS_PPSAfter.begin() + index); + Buffer_LAPPDTS_PPSDiff.erase(Buffer_LAPPDTS_PPSDiff.begin() + index); + Buffer_LAPPDTS_PPSMissing.erase(Buffer_LAPPDTS_PPSMissing.begin() + index); Log("EBSaver: Saved LAPPD data with LAPPDTime " + std::to_string(LAPPDTime), v_debug, verbosityEBSaver); return true; @@ -957,6 +1045,8 @@ bool EBSaver::GotAllDataFromOriginalBuffer() bool gotIPHitsAux = m_data->CStore.Get("InProgressHitsAux", InProgressHitsAux); bool gotIPRADCH = m_data->CStore.Get("InProgressRecoADCHitsAux", InProgressRecoADCHitsAux); bool gotFRAS = m_data->CStore.Get("FinishedRawAcqSize", FinishedRawAcqSize); // Filled in PhaseIIADCCalibrator + bool gotRWM = m_data->CStore.Get("RWMRawWaveforms", RWMRawWaveforms); + bool gotBRF = m_data->CStore.Get("BRFRawWaveforms", BRFRawWaveforms); if (!gotPMTHits || !gotPMTChkey || !gotIPRecoADCHits || !gotIPHitsAux || !gotIPRADCH || !gotFRAS) { @@ -1021,6 +1111,17 @@ bool EBSaver::GotAllDataFromOriginalBuffer() bool gotBuffer_LAPPDOffset_minus_ps = m_data->CStore.Get("Buffer_LAPPDOffset_minus_ps", Buffer_LAPPDOffset_minus_ps); if (!gotBuffer_LAPPDTimestamp_ns || !gotBuffer_LAPPDData || !gotBuffer_LAPPDBeamgate_ns || !gotBuffer_LAPPDOffset || !gotBuffer_LAPPDBeamgate_Raw || !gotBuffer_LAPPDTimestamp_Raw || !gotBuffer_LAPPDBGCorrection || !gotBuffer_LAPPDTSCorrection || !gotBuffer_LAPPDOffset_minus_ps) Log("EBSaver: Failed to get some LAPPD data from buffer", v_message, verbosityEBSaver); + bool gotBuffer_LAPPDBG_PPSBefore = m_data->CStore.Get("Buffer_LAPPDBG_PPSBefore", Buffer_LAPPDBG_PPSBefore); + bool gotBuffer_LAPPDBG_PPSAfter = m_data->CStore.Get("Buffer_LAPPDBG_PPSAfter", Buffer_LAPPDBG_PPSAfter); + bool gotBuffer_LAPPDBG_PPSDiff = m_data->CStore.Get("Buffer_LAPPDBG_PPSDiff", Buffer_LAPPDBG_PPSDiff); + bool gotBuffer_LAPPDBG_PPSMissing = m_data->CStore.Get("Buffer_LAPPDBG_PPSMissing", Buffer_LAPPDBG_PPSMissing); + bool gotBuffer_LAPPDTS_PPSBefore = m_data->CStore.Get("Buffer_LAPPDTS_PPSBefore", Buffer_LAPPDTS_PPSBefore); + bool gotBuffer_LAPPDTS_PPSAfter = m_data->CStore.Get("Buffer_LAPPDTS_PPSAfter", Buffer_LAPPDTS_PPSAfter); + bool gotBuffer_LAPPDTS_PPSDiff = m_data->CStore.Get("Buffer_LAPPDTS_PPSDiff", Buffer_LAPPDTS_PPSDiff); + bool gotBuffer_LAPPDTS_PPSMissing = m_data->CStore.Get("Buffer_LAPPDTS_PPSMissing", Buffer_LAPPDTS_PPSMissing); + if(!gotBuffer_LAPPDBG_PPSBefore || !gotBuffer_LAPPDBG_PPSAfter || !gotBuffer_LAPPDBG_PPSDiff || !gotBuffer_LAPPDBG_PPSMissing || !gotBuffer_LAPPDTS_PPSBefore || !gotBuffer_LAPPDTS_PPSAfter || !gotBuffer_LAPPDTS_PPSDiff || !gotBuffer_LAPPDTS_PPSMissing) + Log("EBSaver: Failed to get LAPPD PPS data from buffer", v_message, verbosityEBSaver); + // got LAPPD match info bool gotPairedLAPPDTriggerTimestamp = m_data->CStore.Get("PairedLAPPDTriggerTimestamp", PairedLAPPDTriggerTimestamp); bool gotPairedLAPPDTimeStamps = m_data->CStore.Get("PairedLAPPDTimeStamps", PairedLAPPDTimeStamps); @@ -1094,6 +1195,8 @@ void EBSaver::SetDataObjects() m_data->CStore.Set("InProgressHitsAux", InProgressHitsAux); m_data->CStore.Set("InProgressRecoADCHitsAux", InProgressRecoADCHitsAux); m_data->CStore.Set("FinishedRawAcqSize", FinishedRawAcqSize); + m_data->CStore.Set("RWMRawWaveforms", RWMRawWaveforms); + m_data->CStore.Set("BRFRawWaveforms", BRFRawWaveforms); // set PMT match info m_data->CStore.Set("PairedPMTTriggerTimestamp", PairedPMTTriggerTimestamp); m_data->CStore.Set("PairedPMTTimeStamps", PairedPMTTimeStamps); @@ -1119,6 +1222,14 @@ void EBSaver::SetDataObjects() m_data->CStore.Set("Buffer_LAPPDBGCorrection", Buffer_LAPPDBGCorrection); m_data->CStore.Set("Buffer_LAPPDTSCorrection", Buffer_LAPPDTSCorrection); m_data->CStore.Set("Buffer_LAPPDOffset_minus_ps", Buffer_LAPPDOffset_minus_ps); + m_data->CStore.Set("Buffer_LAPPDBG_PPSBefore", Buffer_LAPPDBG_PPSBefore); + m_data->CStore.Set("Buffer_LAPPDBG_PPSAfter", Buffer_LAPPDBG_PPSAfter); + m_data->CStore.Set("Buffer_LAPPDBG_PPSDiff", Buffer_LAPPDBG_PPSDiff); + m_data->CStore.Set("Buffer_LAPPDBG_PPSMissing", Buffer_LAPPDBG_PPSMissing); + m_data->CStore.Set("Buffer_LAPPDTS_PPSBefore", Buffer_LAPPDTS_PPSBefore); + m_data->CStore.Set("Buffer_LAPPDTS_PPSAfter", Buffer_LAPPDTS_PPSAfter); + m_data->CStore.Set("Buffer_LAPPDTS_PPSDiff", Buffer_LAPPDTS_PPSDiff); + m_data->CStore.Set("Buffer_LAPPDTS_PPSMissing", Buffer_LAPPDTS_PPSMissing); // set LAPPD match info m_data->CStore.Set("PairedLAPPDTriggerTimestamp", PairedLAPPDTriggerTimestamp); m_data->CStore.Set("PairedLAPPDTimeStamps", PairedLAPPDTimeStamps); @@ -1165,6 +1276,14 @@ void EBSaver::BuildEmptyLAPPDData() std::map LAPPDTSCorrection; std::map LAPPDBGCorrection; std::map LAPPDOSInMinusPS; + std::map LAPPDBG_PPSBefore; + std::map LAPPDBG_PPSAfter; + std::map LAPPDBG_PPSDiff; + std::map LAPPDBG_PPSMissing; + std::map LAPPDTS_PPSBefore; + std::map LAPPDTS_PPSAfter; + std::map LAPPDTS_PPSDiff; + std::map LAPPDTS_PPSMissing; ANNIEEvent->Set("LAPPDDataMap", LAPPDDataMap); ANNIEEvent->Set("LAPPDBeamgate_ns", LAPPDBeamgate_ns); @@ -1175,6 +1294,14 @@ void EBSaver::BuildEmptyLAPPDData() ANNIEEvent->Set("LAPPDTSCorrection", LAPPDTSCorrection); ANNIEEvent->Set("LAPPDBGCorrection", LAPPDBGCorrection); ANNIEEvent->Set("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + ANNIEEvent->Set("LAPPDBG_PPSBefore", LAPPDBG_PPSBefore); + ANNIEEvent->Set("LAPPDBG_PPSAfter", LAPPDBG_PPSAfter); + ANNIEEvent->Set("LAPPDBG_PPSDiff", LAPPDBG_PPSDiff); + ANNIEEvent->Set("LAPPDBG_PPSMissing", LAPPDBG_PPSMissing); + ANNIEEvent->Set("LAPPDTS_PPSBefore", LAPPDTS_PPSBefore); + ANNIEEvent->Set("LAPPDTS_PPSAfter", LAPPDTS_PPSAfter); + ANNIEEvent->Set("LAPPDTS_PPSDiff", LAPPDTS_PPSDiff); + ANNIEEvent->Set("LAPPDTS_PPSMissing", LAPPDTS_PPSMissing); } void EBSaver::LoadBeamInfo() diff --git a/UserTools/EBSaver/EBSaver.h b/UserTools/EBSaver/EBSaver.h index a9ad3dcee..06cc5cb9e 100644 --- a/UserTools/EBSaver/EBSaver.h +++ b/UserTools/EBSaver/EBSaver.h @@ -75,6 +75,9 @@ class EBSaver : public Tool bool saveOrphan; bool saveBeamInfo; + bool saveRawRWMWaveform; + bool saveRawBRFWaveform; + string savePath; string saveName; @@ -93,8 +96,8 @@ class EBSaver : public Tool int savedPMTHitMapNumber; int savedMRDNumber; int savedLAPPDNumber; - - std::map TriggerTimeWithoutMRD; //trigger time, 8 or 36 + + std::map TriggerTimeWithoutMRD; // trigger time, 8 or 36 int thisRunNum; int thisSubrunNum; @@ -117,7 +120,6 @@ class EBSaver : public Tool std::map> MRDPairInfoToRemoveTime; std::map> LAPPDPairInfoToRemoveTime; - std::map>> GroupedTriggersInTotal; // each map is a group of triggers, with the key is the target trigger word std::map> RunCodeInTotal; @@ -136,6 +138,9 @@ class EBSaver : public Tool std::map> *> *InProgressHitsAux; // Key: {MTCTime}, value: map of Hit distributions std::map>> *FinishedRawAcqSize; // Key: {MTCTime}, value: map of acquisition time window sizes + std::map> *RWMRawWaveforms; // Key: MTCTime, Value: RWM waveform + std::map> *BRFRawWaveforms; // Key: MTCTime, Value: BRF waveform + std::map> PairedPMTTriggerTimestamp; std::map> PairedPMT_TriggerIndex; std::map> PairedPMTTimeStamps; @@ -164,6 +169,14 @@ class EBSaver : public Tool vector Buffer_LAPPDBGCorrection; vector Buffer_LAPPDTSCorrection; vector Buffer_LAPPDOffset_minus_ps; + vector Buffer_LAPPDBG_PPSBefore; + vector Buffer_LAPPDBG_PPSAfter; + vector Buffer_LAPPDBG_PPSDiff; + vector Buffer_LAPPDBG_PPSMissing; + vector Buffer_LAPPDTS_PPSBefore; + vector Buffer_LAPPDTS_PPSAfter; + vector Buffer_LAPPDTS_PPSDiff; + vector Buffer_LAPPDTS_PPSMissing; vector Buffer_LAPPDRunCode; @@ -171,7 +184,6 @@ class EBSaver : public Tool std::map> PairedLAPPD_TriggerIndex; std::map> PairedLAPPDTimeStamps; - // beam info related objects vector BeamInfoTimestamps; std::map E_TOR860_map; @@ -185,7 +197,6 @@ class EBSaver : public Tool std::map HPTG2_map; std::map VPTG2_map; std::map BTH2T2_map; - }; #endif diff --git a/UserTools/Factory/Factory.cpp b/UserTools/Factory/Factory.cpp index 6a34eb012..cd4bd1685 100644 --- a/UserTools/Factory/Factory.cpp +++ b/UserTools/Factory/Factory.cpp @@ -183,5 +183,6 @@ if (tool=="EBSaver") ret=new EBSaver; if (tool=="ANNIEEventTreeMaker") ret=new ANNIEEventTreeMaker; if (tool=="ProcessedLAPPDFilter") ret=new ProcessedLAPPDFilter; if (tool=="BeamQuality") ret=new BeamQuality; +if (tool=="FitRWMWaveform") ret=new FitRWMWaveform; return ret; } diff --git a/UserTools/FitRWMWaveform/FitRWMWaveform.cpp b/UserTools/FitRWMWaveform/FitRWMWaveform.cpp new file mode 100644 index 000000000..22220ac21 --- /dev/null +++ b/UserTools/FitRWMWaveform/FitRWMWaveform.cpp @@ -0,0 +1,406 @@ +#include "FitRWMWaveform.h" + +FitRWMWaveform::FitRWMWaveform() : Tool() {} + +bool FitRWMWaveform::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + m_variables.Get("verbosityFitRWMWaveform", verbosityFitRWMWaveform); + m_variables.Get("printToRootFile", printToRootFile); + + maxPrintNumber = 100; + m_variables.Get("maxPrintNumber", maxPrintNumber); + + output_filename = "RWMBRFWaveforms.root"; + m_variables.Get("output_filename", output_filename); + + return true; +} + +bool FitRWMWaveform::Execute() +{ + + Log("FitRWMWaveform: Execute()", v_debug, verbosityFitRWMWaveform); + m_data->Stores["ANNIEEvent"]->Get("RWMRawWaveform", RWMRawWaveform); + m_data->Stores["ANNIEEvent"]->Get("BRFRawWaveform", BRFRawWaveform); + + uint64_t WaveformTime = 0; + m_data->Stores["ANNIEEvent"]->Get("EventTimeTank", WaveformTime); + + if (printToRootFile && ToBePrintedRWMWaveforms.size() < maxPrintNumber) + { + + ToBePrintedRWMWaveforms.emplace(WaveformTime, RWMRawWaveform); + ToBePrintedBRFWaveforms.emplace(WaveformTime, BRFRawWaveform); + Log("FitRWMWaveform: Execute(): Added RWM and BRF waveforms to be printed to root file", v_debug, verbosityFitRWMWaveform); + } + + RWMRisingStart = 0; + RWMRisingEnd = 0; + RWMHalfRising = 0; + RWMFHWM = 0; + RWMFirstPeak = 0; + + BRFFirstPeak = 0; + BRFAveragePeak = 0; + BRFFirstPeakFit = 0; + + // Fit the RWM waveform, find the rising start, rising end and half rising time + FitRWM(); + + FitBRF(); + + m_data->Stores["ANNIEEvent"]->Set("RWMRisingStart", RWMRisingStart); + m_data->Stores["ANNIEEvent"]->Set("RWMRisingEnd", RWMRisingEnd); + m_data->Stores["ANNIEEvent"]->Set("RWMHalfRising", RWMHalfRising); + m_data->Stores["ANNIEEvent"]->Set("RWMFHWM", RWMFHWM); + m_data->Stores["ANNIEEvent"]->Set("RWMFirstPeak", RWMFirstPeak); + + m_data->Stores["ANNIEEvent"]->Set("BRFFirstPeak", BRFFirstPeak); + m_data->Stores["ANNIEEvent"]->Set("BRFAveragePeak", BRFAveragePeak); + m_data->Stores["ANNIEEvent"]->Set("BRFFirstPeakFit", BRFFirstPeakFit); + + return true; +} +bool FitRWMWaveform::Finalise() +{ + if (printToRootFile) + { + TFile *fOutput_tfile = new TFile(output_filename.c_str(), "recreate"); + + // Loop ToBePrintedRWMWaveforms and ToBePrintedBRFWaveforms, fill each waveform to a histogram and save it to the root file + // Use the RWM+event number + key as the name of the histogram + int RWMCount = 0; + for (const auto &kv : ToBePrintedRWMWaveforms) + { + const auto &key = kv.first; + const auto &val = kv.second; + TH1D *hRWM = new TH1D(Form("RWM_%d_%lu", RWMCount, key), Form("RWM_%d_%lu", RWMCount, key), val.size(), 0, val.size()); + for (int i = 0; i < val.size(); i++) + { + hRWM->SetBinContent(i + 1, val[i]); // Note the 1-based index + } + hRWM->Write(); + RWMCount++; + } + + int BRFCount = 0; + for (const auto &kv : ToBePrintedBRFWaveforms) + { + const auto &key = kv.first; + const auto &val = kv.second; + TH1D *hBRF = new TH1D(Form("BRF_%d_%lu", BRFCount, key), Form("BRF_%d_%lu", BRFCount, key), val.size(), 0, val.size()); + for (int i = 0; i < val.size(); i++) + { + hBRF->SetBinContent(i + 1, val[i]); // Note the 1-based index + } + hBRF->Write(); + BRFCount++; + } + + fOutput_tfile->Close(); + } + + return true; +} + +void FitRWMWaveform::FitRWM() +{ + Log("FitRWMWaveform: FitRWM()", v_debug, verbosityFitRWMWaveform); + if (RWMRawWaveform.size() == 0) + { + Log("FitRWMWaveform: FitRWM(): RWMRawWaveform is empty", v_message, verbosityFitRWMWaveform); + return; + } + int threshold = 50; + int bin_size = 2; // 2ns per bin + int max_bin_RWM = RWMRawWaveform.size(); + + // RWM + RWMRisingStart = 300; + for (int i = 300; i < max_bin_RWM; ++i) + { + if (RWMRawWaveform[i] > 400 && RWMRawWaveform[i] - RWMRawWaveform[i - 1] > threshold) + { + RWMRisingStart = i - 1; + break; + } + } + + RWMRisingEnd = RWMRisingStart; + for (int i = RWMRisingStart; i < RWMRisingStart + 60 && i < max_bin_RWM; ++i) + { + if (RWMRawWaveform[i] > RWMRawWaveform[RWMRisingEnd]) + { + RWMRisingEnd = i; + } + } + if (!(RWMRisingStart > 200 && RWMRisingStart < 600) || !(RWMRisingEnd > 200 && RWMRisingEnd < 600)) + { + Log("FitRWMWaveform: FitRWM(): RWMRisingStart or RWMRisingEnd out of range, found at " + std::to_string(RWMRisingStart) + " and " + std::to_string(RWMRisingEnd), v_message, verbosityFitRWMWaveform); + return; + } + + Log("FitRWMWaveform: FitRWM(): Found rising start and end at " + std::to_string(RWMRisingStart) + " and " + std::to_string(RWMRisingEnd) + " with rising start value " + std::to_string(RWMRawWaveform[RWMRisingStart]), v_debug, verbosityFitRWMWaveform); + double RWMBottom = std::accumulate(RWMRawWaveform.begin(), RWMRawWaveform.begin() + RWMRisingStart, 0.0) / RWMRisingStart; + double RWMTop = std::accumulate(RWMRawWaveform.begin() + RWMRisingEnd + 50, RWMRawWaveform.begin() + RWMRisingEnd + 400, 0.0) / 350; + double RWMHalf = (RWMBottom + RWMTop) / 2; + + int best_bin_RWM = RWMRisingStart; + double best_diff_RWM = std::abs(RWMRawWaveform[RWMRisingStart] - RWMHalf); + + for (int i = RWMRisingStart; i <= RWMRisingEnd; ++i) + { + double diff = std::abs(RWMRawWaveform[i] - RWMHalf); + if (diff < best_diff_RWM) + { + best_bin_RWM = i; + best_diff_RWM = diff; + } + } + + int best_interval_RWM = 0; + double interval_size = 1.0 / 400; + double min_diff_RWM = std::numeric_limits::max(); + Log("FitRWMWaveform: FitRWM(): Found best bin at " + std::to_string(best_bin_RWM), v_debug, verbosityFitRWMWaveform); + + for (int i = -200; i < 200; ++i) + { + // Log("FitRWMWaveform: FitRWM(): Interpolating value at " + std::to_string(i),v_debug, verbosityFitRWMWaveform); + double interpolated_value = RWMRawWaveform[best_bin_RWM] + (RWMRawWaveform[best_bin_RWM + (i < 0 ? -1 : 1)] - RWMRawWaveform[best_bin_RWM]) * (std::abs(i) * interval_size); + double diff = std::abs(interpolated_value - RWMHalf); + if (diff < min_diff_RWM) + { + min_diff_RWM = diff; + best_interval_RWM = i; + } + } + + double RWMHalfTimeInPs = (best_bin_RWM + best_interval_RWM * interval_size) * 10 + RWMRisingStart * 2000; + + RWMHalfRising = RWMHalfTimeInPs; + Log("FitRWMWaveform: FitRWM(): Found RWMHalfRising = " + std::to_string(RWMHalfRising), v_debug, verbosityFitRWMWaveform); + // finding the falling half + // Finding the falling end + int RWMFallingStart = RWMRisingEnd; + for (int i = RWMRisingEnd; i < max_bin_RWM; ++i) + { + if (RWMRawWaveform[i] < 1000) + { + RWMFallingStart = i; + break; + } + } + Log("FitRWMWaveform: FitRWM(): Found falling start", v_debug, verbosityFitRWMWaveform); + int bin_close = RWMFallingStart; + double best_diff_fall = std::abs(RWMRawWaveform[RWMFallingStart] - RWMHalf); + + for (int i = RWMFallingStart - 20; i <= RWMFallingStart + 20 && i < max_bin_RWM; ++i) + { + double diff = std::abs(RWMRawWaveform[i] - RWMHalf); + if (diff < best_diff_fall) + { + bin_close = i; + best_diff_fall = diff; + } + } + if (!(bin_close < 950)) + { + Log("FitRWMWaveform: FitRWM(): falling bin out of range, found at " + std::to_string(bin_close), v_message, verbosityFitRWMWaveform); + return; + } + Log("FitRWMWaveform: FitRWM(): Found falling close", v_debug, verbosityFitRWMWaveform); + + best_interval_RWM = 0; + min_diff_RWM = std::numeric_limits::max(); + + for (int i = -200; i < 200; ++i) + { + double interpolated_value = RWMRawWaveform[bin_close] + (RWMRawWaveform[bin_close + (i < 0 ? -1 : 1)] - RWMRawWaveform[bin_close]) * (std::abs(i) * interval_size); + double diff = std::abs(interpolated_value - RWMHalf); + if (diff < min_diff_RWM) + { + min_diff_RWM = diff; + best_interval_RWM = i; + } + } + Log("FitRWMWaveform: FitRWM(): Found falling end", v_debug, verbosityFitRWMWaveform); + double RWMHalfEnd = (bin_close * 2000) + (best_interval_RWM * 10); + RWMFHWM = RWMHalfEnd - RWMHalfRising; + + int RWMFirstPeakBin = -1; + for (int i = 0; i < RWMRawWaveform.size(); ++i) + { + if (RWMRawWaveform[i] > 1600) + { + RWMFirstPeakBin = i; + break; + } + } + + // change the unit from bin number to ns or ps + RWMRisingStart = RWMRisingStart * 2; + RWMRisingEnd = RWMRisingEnd * 2; + RWMFirstPeak = RWMFirstPeakBin * 2; +} + +void FitRWMWaveform::FitBRF() +{ + // fit the first peak, and the average of peaks of std::vector BRFRawWaveform. + // find the size of the vector, in the first 10 bin interval, find the bin with highest value, as the first peak + // for each 10 bin interval, find the highest value bin position in each interval, and minus the beginning of the interval, and average them. + double maximum = 0; + double first_peak = 0; + double average = 0; + int bin_size = 2; // 2ns per bin + + if (BRFRawWaveform.size() == 0) + { + Log("FitRWMWaveform: FitBRF(): BRFRawWaveform is empty", v_message, verbosityFitRWMWaveform); + return; + } + + int max_bin_BRF = BRFRawWaveform.size(); + + // Find the first peak in the first 10 bin interval + for (int i = 0; i < 10 && i < max_bin_BRF; ++i) + { + if (BRFRawWaveform[i] > maximum) + { + maximum = BRFRawWaveform[i]; + first_peak = i; + } + } + + // Find the highest value bin position in each 10 bin interval and calculate the average + int interval_count = 0; + for (int i = 0; i <= max_bin_BRF - 10; i += 10) + { + double max = 0; + int max_bin = 0; + for (int j = i; j < i + 10; ++j) + { + if (BRFRawWaveform[j] > max) + { + max = BRFRawWaveform[j]; + max_bin = j; + } + } + average += (max_bin - i); + ++interval_count; + } + + if (interval_count > 0) + { + average /= interval_count; + } + + // Logging results + Log("FitRWMWaveform: FitBRF(): First peak at bin = " + std::to_string(first_peak), v_debug, verbosityFitRWMWaveform); + Log("FitRWMWaveform: FitBRF(): Average peak position = " + std::to_string(average), v_debug, verbosityFitRWMWaveform); + + BRFFirstPeak = first_peak * bin_size; + BRFAveragePeak = average * bin_size; + + BRFFirstPeakFit = 0; + // now, we use a simple Gaussian fit to find the first peak in the first 10 bins (before understanding the Booster RF properties) + // first, in the first 10 bins, find the maximum value and its position, if the maximum value is smaller than 3050, return + // then check the side bins. check from the max bin to zero, find the first bin with value less than 2920, or until the first bin, save this bin as fitting start bin + // then check from the max bin to the 10th bin, find the first bin with value less than 3020. check if the next bin has value less than this bin, if yes, set next bin as the fitting end, if not, set this bin as fitting end. + // in the fitting range, fit the waveform with a Gaussian function, and find the peak position. + // save the peak position as BRFFirstPeakFit + + if (maximum < 3050) + return; + + int fit_start_bin = 0; + for (int i = first_peak; i >= 0; --i) + { + if (BRFRawWaveform[i] < 2920) + { + fit_start_bin = i; + break; + } + } + + int fit_end_bin = first_peak; + for (int i = first_peak; i < 10 && i < max_bin_BRF; ++i) + { + if (BRFRawWaveform[i] < 3020) + { + if (BRFRawWaveform[i + 1] < BRFRawWaveform[i]) + { + fit_end_bin = i + 1; + } + else + { + fit_end_bin = i; + } + break; + } + } + + if (fit_end_bin <= fit_start_bin) + return; + + std::vector x_vals, y_vals; + for (int i = fit_start_bin; i <= fit_end_bin; ++i) + { + x_vals.push_back(i * bin_size); + y_vals.push_back(BRFRawWaveform[i]); + } + + //TGraph graph(x_vals.size(), &x_vals[0], &y_vals[0]); + //TF1 gaus("gaus", "gaus", fit_start_bin * bin_size, fit_end_bin * bin_size); + + //graph.Fit(&gaus, "Q"); + + //BRFFirstPeakFit = gaus.GetParameter(1); // Mean value of the Gaussian fit + //Log("FitRWMWaveform: FitBRF(): First peak fit at " + std::to_string(BRFFirstPeakFit), v_debug, verbosityFitRWMWaveform); + + + + + // Find the bin with the minimum value between the 5th and 15th bins + auto min_it = std::min_element(BRFRawWaveform.begin() + 4, BRFRawWaveform.begin() + 15); + int bin_minimum = std::distance(BRFRawWaveform.begin(), min_it); + + // Find the bin with the maximum value between bin_minimum + 2 and bin_minimum + 4 + auto max_it = std::max_element(BRFRawWaveform.begin() + bin_minimum + 2, BRFRawWaveform.begin() + bin_minimum + 5); + int bin_maximum = std::distance(BRFRawWaveform.begin(), max_it); + + // Calculate the half height + double half_height = (BRFRawWaveform[bin_minimum] + BRFRawWaveform[bin_maximum]) / 2.0; + + // Perform linear interpolation + const int intervals_per_bin = 2000; + double min_difference = std::numeric_limits::max(); + int min_difference_bin = -1; + + for (int bin = bin_minimum; bin < bin_maximum; ++bin) + { + for (int interval = 0; interval < intervals_per_bin; ++interval) + { + double fraction = interval / static_cast(intervals_per_bin); + double interpolated_value = BRFRawWaveform[bin] + fraction * (BRFRawWaveform[bin + 1] - BRFRawWaveform[bin]); + double difference = std::abs(interpolated_value - half_height); + + if (difference < min_difference) + { + min_difference = difference; + min_difference_bin = bin * intervals_per_bin + interval; + } + } + } + + double BRFRisingHalfLinearFit = min_difference_bin; // in ps + BRFFirstPeakFit = BRFRisingHalfLinearFit; +} diff --git a/UserTools/FitRWMWaveform/FitRWMWaveform.h b/UserTools/FitRWMWaveform/FitRWMWaveform.h new file mode 100644 index 000000000..629b81883 --- /dev/null +++ b/UserTools/FitRWMWaveform/FitRWMWaveform.h @@ -0,0 +1,63 @@ +#ifndef FitRWMWaveform_H +#define FitRWMWaveform_H + +#include +#include + +#include "Tool.h" +#include "TFile.h" +#include "TH1D.h" +#include // for std::accumulate +#include +#include + +/** + * \class FitRWMWaveform + * + * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. + * + * $Author: B.Richards $ + * $Date: 2019/05/28 10:44:00 $ + * Contact: b.richards@qmul.ac.uk + */ +class FitRWMWaveform : public Tool +{ + +public: + FitRWMWaveform(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + + void FitRWM(); + void FitBRF(); + +private: + int verbosityFitRWMWaveform; + int v_message = 1; + int v_warning = 2; + int v_error = 3; + int v_debug = 4; + + bool printToRootFile; + int maxPrintNumber; + std::string output_filename; + + std::vector RWMRawWaveform; + std::vector BRFRawWaveform; + + std::map> ToBePrintedRWMWaveforms; + std::map> ToBePrintedBRFWaveforms; + + double RWMRisingStart; + double RWMRisingEnd; + double RWMHalfRising; + double RWMFHWM; + double RWMFirstPeak; + + double BRFFirstPeak; + double BRFAveragePeak; + double BRFFirstPeakFit; +}; + +#endif diff --git a/UserTools/FitRWMWaveform/README.md b/UserTools/FitRWMWaveform/README.md new file mode 100644 index 000000000..0c3f851ef --- /dev/null +++ b/UserTools/FitRWMWaveform/README.md @@ -0,0 +1,20 @@ +# FitRWMWaveform + +FitRWMWaveform + +## Data + +Describe any data formats FitRWMWaveform creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for FitRWMWaveform. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp index 339afef46..b74d8b62c 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp @@ -186,7 +186,7 @@ bool LAPPDLoadStore::Execute() { bool gotDataStream = m_data->Stores.at("ANNIEEvent")->Get("DataStreams", DataStreams); bool getMap = m_data->Stores["ANNIEEvent"]->Get("LAPPDDataMap", LAPPDDataMap); - if (getMap) + if (getMap && DataStreams["LAPPD"]==true && LAPPDDataMap.size() > 0) { // cout << "Outside, size of LAPPDDatamap = " << LAPPDDataMap.size() << endl; bool gotBeamgates_ns = m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); @@ -197,6 +197,25 @@ bool LAPPDLoadStore::Execute() bool gotTSCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDTSCorrection", LAPPDTSCorrection); bool gotDBGCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDBGCorrection", LAPPDBGCorrection); bool gotOSInMinusPS = m_data->Stores["ANNIEEvent"]->Get("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + + bool gotBG_PPSBefore = m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSBefore", LAPPDBG_PPSBefore); + bool gotBG_PPSAfter = m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSAfter", LAPPDBG_PPSAfter); + bool gotBG_PPSDiff = m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSDiff", LAPPDBG_PPSDiff); + bool gotBG_PPSMissing = m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSMissing", LAPPDBG_PPSMissing); + bool gotTS_PPSBefore = m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSBefore", LAPPDTS_PPSBefore); + bool gotTS_PPSAfter = m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSAfter", LAPPDTS_PPSAfter); + bool gotTS_PPSDiff = m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSDiff", LAPPDTS_PPSDiff); + bool gotTS_PPSMissing = m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSMissing", LAPPDTS_PPSMissing); + if (LAPPDStoreReadInVerbosity > 3) + { + cout << "LAPPDLoadStore: gotOffsets = " << gotOffsets << ", gotBG_PPSBefore = " << gotBG_PPSBefore << ", gotTS_PPSBefore = " << gotTS_PPSBefore << endl; + cout << "Size of LAPPDDataMap = " << LAPPDDataMap.size() << ", LAPPDOffsets = " << LAPPDOffsets.size() << ", LAPPDBG_PPSBefore = " << LAPPDBG_PPSBefore.size() << ", LAPPDTS_PPSBefore = " << LAPPDTS_PPSBefore.size() << endl; + + cout << "gotBG_PPSBefore = " << gotBG_PPSBefore << ", gotBG_PPSAfter = " << gotBG_PPSAfter << ", gotBG_PPSDiff = " << gotBG_PPSDiff << ", gotBG_PPSMissing = " << gotBG_PPSMissing << endl; + cout << "gotTS_PPSBefore = " << gotTS_PPSBefore << ", gotTS_PPSAfter = " << gotTS_PPSAfter << ", gotTS_PPSDiff = " << gotTS_PPSDiff << ", gotTS_PPSMissing = " << gotTS_PPSMissing << endl; + } + }else{ + return true; } } @@ -339,7 +358,7 @@ bool LAPPDLoadStore::Execute() LAPPD_ID = dat.LAPPD_ID; if (LAPPD_ID != SelectedLAPPD && SelectSingleLAPPD) continue; - + if (Raw_buffer.size() == 0 || ReadBoards.size() == 0) { m_data->CStore.Set("LAPPDana", false); @@ -429,9 +448,23 @@ bool LAPPDLoadStore::Execute() LAPPDLoadedTSCorrections.push_back(LAPPDTSCorrection.at(time)); LAPPDLoadedBGCorrections.push_back(LAPPDBGCorrection.at(time)); LAPPDLoadedOSInMinusPS.push_back(LAPPDOSInMinusPS.at(time)); + LAPPDLoadedBG_PPSBefore.push_back(LAPPDBG_PPSBefore.at(time)); + LAPPDLoadedBG_PPSAfter.push_back(LAPPDBG_PPSAfter.at(time)); + LAPPDLoadedBG_PPSDiff.push_back(LAPPDBG_PPSDiff.at(time)); + LAPPDLoadedBG_PPSMissing.push_back(LAPPDBG_PPSMissing.at(time)); + LAPPDLoadedTS_PPSBefore.push_back(LAPPDTS_PPSBefore.at(time)); + LAPPDLoadedTS_PPSAfter.push_back(LAPPDTS_PPSAfter.at(time)); + LAPPDLoadedTS_PPSDiff.push_back(LAPPDTS_PPSDiff.at(time)); + LAPPDLoadedTS_PPSMissing.push_back(LAPPDTS_PPSMissing.at(time)); if (LAPPDStoreReadInVerbosity > 2) cout << "parsing finished for LAPPD_ID " << LAPPD_ID << " at time " << time << endl; + + if (LAPPDTS_PPSMissing.at(time) != LAPPDBG_PPSMissing.at(time) && ((LAPPDTS_PPSMissing.at(time) > -100 && LAPPDTS_PPSMissing.at(time) < 100) || (LAPPDBG_PPSMissing.at(time) > -100 && LAPPDBG_PPSMissing.at(time) < 100))) + { + cout << "LAPPDLoadStore: PPS missing number is not the same on BG and TS for LAPPD_ID " << LAPPD_ID << " at time " << time << ", BG: " << LAPPDBG_PPSMissing.at(time) << ", TS: " << LAPPDTS_PPSMissing.at(time) << endl; + cout << "LAPPDLoadStore: BG_PPSDiff: " << LAPPDBG_PPSDiff.at(time) << ", TS_PPSDiff: " << LAPPDTS_PPSDiff.at(time) << endl; + } } NonEmptyEvents += 1; NonEmptyDataEvents += 1; @@ -459,6 +492,15 @@ bool LAPPDLoadStore::Execute() m_data->Stores["ANNIEEvent"]->Set("LAPPDBGCorrection", LAPPDBGCorrection); m_data->Stores["ANNIEEvent"]->Set("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + m_data->Stores["ANNIEEvent"]->Set("LAPPDBG_PPSBefore", LAPPDBG_PPSBefore); + m_data->Stores["ANNIEEvent"]->Set("LAPPDBG_PPSAfter", LAPPDBG_PPSAfter); + m_data->Stores["ANNIEEvent"]->Set("LAPPDBG_PPSDiff", LAPPDBG_PPSDiff); + m_data->Stores["ANNIEEvent"]->Set("LAPPDBG_PPSMissing", LAPPDBG_PPSMissing); + m_data->Stores["ANNIEEvent"]->Set("LAPPDTS_PPSBefore", LAPPDTS_PPSBefore); + m_data->Stores["ANNIEEvent"]->Set("LAPPDTS_PPSAfter", LAPPDTS_PPSAfter); + m_data->Stores["ANNIEEvent"]->Set("LAPPDTS_PPSDiff", LAPPDTS_PPSDiff); + m_data->Stores["ANNIEEvent"]->Set("LAPPDTS_PPSMissing", LAPPDTS_PPSMissing); + // TODO: save other timestamps, variables and metadata for later use if (eventNo % 100 == 0) @@ -1243,6 +1285,15 @@ void LAPPDLoadStore::SaveOffsets() int LAPPDOffset_minus_ps = 0; uint64_t LAPPDOffset = 0; + uint64_t BG_PPSBefore = 0; + uint64_t BG_PPSAfter = 0; + uint64_t BG_PPSDiff = 0; + uint64_t TS_PPSBefore = 0; + uint64_t TS_PPSAfter = 0; + uint64_t TS_PPSDiff = 0; + int BG_PPSMissing = 0; + int TS_PPSMissing = 0; + // Check if the key exists and the index is within range for BGCorrections if (BGCorrections.find(key) != BGCorrections.end() && eventNumberInPF < BGCorrections[key].size()) { @@ -1309,13 +1360,123 @@ void LAPPDLoadStore::SaveOffsets() } } + if (BG_PPSBefore_loaded.find(key) != BG_PPSBefore_loaded.end() && eventNumberInPF < BG_PPSBefore_loaded[key].size()) + { + BG_PPSBefore = BG_PPSBefore_loaded[key][eventNumberInPF]; + } + else + { + if (BG_PPSBefore_loaded.find(key) == BG_PPSBefore_loaded.end()) + std::cerr << "Error: Key not found in BG_PPSBefore_loaded: " << key << std::endl; + else + std::cerr << "Error: eventNumberInPF out of range for BG_PPSBefore_loaded with key: " << key << std::endl; + } + + if (BG_PPSAfter_loaded.find(key) != BG_PPSAfter_loaded.end() && eventNumberInPF < BG_PPSAfter_loaded[key].size()) + { + BG_PPSAfter = BG_PPSAfter_loaded[key][eventNumberInPF]; + } + else + { + if (BG_PPSAfter_loaded.find(key) == BG_PPSAfter_loaded.end()) + std::cerr << "Error: Key not found in BG_PPSAfter_loaded: " << key << std::endl; + else + std::cerr << "Error: eventNumberInPF out of range for BG_PPSAfter_loaded with key: " << key << std::endl; + } + + if (BG_PPSDiff_loaded.find(key) != BG_PPSDiff_loaded.end() && eventNumberInPF < BG_PPSDiff_loaded[key].size()) + { + BG_PPSDiff = BG_PPSDiff_loaded[key][eventNumberInPF]; + } + else + { + if (BG_PPSDiff_loaded.find(key) == BG_PPSDiff_loaded.end()) + std::cerr << "Error: Key not found in BG_PPSDiff_loaded: " << key << std::endl; + else + std::cerr << "Error: eventNumberInPF out of range for BG_PPSDiff_loaded with key: " << key << std::endl; + } + + if (BG_PPSMissing_loaded.find(key) != BG_PPSMissing_loaded.end() && eventNumberInPF < BG_PPSMissing_loaded[key].size()) + { + BG_PPSMissing = BG_PPSMissing_loaded[key][eventNumberInPF]; + } + else + { + if (BG_PPSMissing_loaded.find(key) == BG_PPSMissing_loaded.end()) + std::cerr << "Error: Key not found in BG_PPSMissing_loaded: " << key << std::endl; + else + std::cerr << "Error: eventNumberInPF out of range for BG_PPSMissing_loaded with key: " << key << std::endl; + } + + if (TS_PPSBefore_loaded.find(key) != TS_PPSBefore_loaded.end() && eventNumberInPF < TS_PPSBefore_loaded[key].size()) + { + TS_PPSBefore = TS_PPSBefore_loaded[key][eventNumberInPF]; + } + else + { + if (TS_PPSBefore_loaded.find(key) == TS_PPSBefore_loaded.end()) + std::cerr << "Error: Key not found in TS_PPSBefore_loaded: " << key << std::endl; + else + std::cerr << "Error: eventNumberInPF out of range for TS_PPSBefore_loaded with key: " << key << std::endl; + } + + if (TS_PPSAfter_loaded.find(key) != TS_PPSAfter_loaded.end() && eventNumberInPF < TS_PPSAfter_loaded[key].size()) + { + TS_PPSAfter = TS_PPSAfter_loaded[key][eventNumberInPF]; + } + else + { + if (TS_PPSAfter_loaded.find(key) == TS_PPSAfter_loaded.end()) + std::cerr << "Error: Key not found in TS_PPSAfter_loaded: " << key << std::endl; + else + std::cerr << "Error: eventNumberInPF out of range for TS_PPSAfter_loaded with key: " << key << std::endl; + } + + if (TS_PPSDiff_loaded.find(key) != TS_PPSDiff_loaded.end() && eventNumberInPF < TS_PPSDiff_loaded[key].size()) + { + TS_PPSDiff = TS_PPSDiff_loaded[key][eventNumberInPF]; + } + else + { + if (TS_PPSDiff_loaded.find(key) == TS_PPSDiff_loaded.end()) + std::cerr << "Error: Key not found in TS_PPSDiff_loaded: " << key << std::endl; + else + std::cerr << "Error: eventNumberInPF out of range for TS_PPSDiff_loaded with key: " << key << std::endl; + } + + if (TS_PPSMissing_loaded.find(key) != TS_PPSMissing_loaded.end() && eventNumberInPF < TS_PPSMissing_loaded[key].size()) + { + TS_PPSMissing = TS_PPSMissing_loaded[key][eventNumberInPF]; + } + else + { + if (TS_PPSMissing_loaded.find(key) == TS_PPSMissing_loaded.end()) + std::cerr << "Error: Key not found in TS_PPSMissing_loaded: " << key << std::endl; + else + std::cerr << "Error: eventNumberInPF out of range for TS_PPSMissing_loaded with key: " << key << std::endl; + } + // start to fill data m_data->CStore.Set("LAPPDBGCorrection", LAPPDBGCorrection); m_data->CStore.Set("LAPPDTSCorrection", LAPPDTSCorrection); m_data->CStore.Set("LAPPDOffset", LAPPDOffset); m_data->CStore.Set("LAPPDOffset_minus_ps", LAPPDOffset_minus_ps); - cout << "LAPPDStoreReadIn, Saving offsets and corrections, key: " << key << ", LAPPDOffset: " << LAPPDOffset << ", LAPPDOffset_minus_ps: " << LAPPDOffset_minus_ps << ", LAPPDBGCorrection: " << LAPPDBGCorrection << ", LAPPDTSCorrection: " << LAPPDTSCorrection << endl; + m_data->CStore.Set("BG_PPSBefore", BG_PPSBefore); + m_data->CStore.Set("BG_PPSAfter", BG_PPSAfter); + m_data->CStore.Set("BG_PPSDiff", BG_PPSDiff); + m_data->CStore.Set("BG_PPSMissing", BG_PPSMissing); + m_data->CStore.Set("TS_PPSBefore", TS_PPSBefore); + m_data->CStore.Set("TS_PPSAfter", TS_PPSAfter); + m_data->CStore.Set("TS_PPSDiff", TS_PPSDiff); + m_data->CStore.Set("TS_PPSMissing", TS_PPSMissing); + + if (TS_PPSMissing != BG_PPSMissing) + { + cout << "LAPPDLoadStore: BG_PPSMissing != TS_PPSMissing, BG_PPSMissing: " << BG_PPSMissing << ", TS_PPSMissing: " << TS_PPSMissing << endl; + } + + // cout << "LAPPDStoreReadIn, Saving offsets and corrections, key: " << key << ", LAPPDOffset: " << LAPPDOffset << ", LAPPDOffset_minus_ps: " << LAPPDOffset_minus_ps << ", LAPPDBGCorrection: " << LAPPDBGCorrection << ", LAPPDTSCorrection: " << LAPPDTSCorrection << ", BG_PPSBefore: " << BG_PPSBefore << ", BG_PPSAfter: " << BG_PPSAfter << ", BG_PPSDiff: " << BG_PPSDiff << ", BG_PPSMissing: " << BG_PPSMissing << ", TS_PPSBefore: " << TS_PPSBefore << ", TS_PPSAfter: " << TS_PPSAfter << ", TS_PPSDiff: " << TS_PPSDiff << ", TS_PPSMissing: " << TS_PPSMissing << endl; if (LAPPDStoreReadInVerbosity > 11) debugStoreReadIn << eventNo << "+LAPPDStoreReadIn, Saving offsets and corrections, key: " << key << ", LAPPDOffset: " << LAPPDOffset << ", LAPPDOffset_minus_ps: " << LAPPDOffset_minus_ps << ", LAPPDBGCorrection: " << LAPPDBGCorrection << ", LAPPDTSCorrection: " << LAPPDTSCorrection << endl; @@ -1344,6 +1505,16 @@ void LAPPDLoadStore::LoadOffsetsAndCorrections() int runNumber, subRunNumber, partFileNumber, LAPPD_ID; ULong64_t final_offset_ns_0, final_offset_ps_negative_0, EventIndex; ULong64_t BGCorrection_tick, TSCorrection_tick; + + ULong64_t BG_PPSBefore_tick; + ULong64_t BG_PPSAfter_tick; + ULong64_t BG_PPSDiff_tick; + ULong64_t BG_PPSMissing_tick; + ULong64_t TS_PPSBefore_tick; + ULong64_t TS_PPSAfter_tick; + ULong64_t TS_PPSDiff_tick; + ULong64_t TS_PPSMissing_tick; + tree->SetBranchAddress("runNumber", &runNumber); tree->SetBranchAddress("subRunNumber", &subRunNumber); tree->SetBranchAddress("partFileNumber", &partFileNumber); @@ -1353,6 +1524,14 @@ void LAPPDLoadStore::LoadOffsetsAndCorrections() tree->SetBranchAddress("final_offset_ps_negative_0", &final_offset_ps_negative_0); tree->SetBranchAddress("BGCorrection_tick", &BGCorrection_tick); tree->SetBranchAddress("TSCorrection_tick", &TSCorrection_tick); + tree->SetBranchAddress("BG_PPSBefore_tick", &BG_PPSBefore_tick); + tree->SetBranchAddress("BG_PPSAfter_tick", &BG_PPSAfter_tick); + tree->SetBranchAddress("BG_PPSDiff_tick", &BG_PPSDiff_tick); + tree->SetBranchAddress("BG_PPSMissing_tick", &BG_PPSMissing_tick); + tree->SetBranchAddress("TS_PPSBefore_tick", &TS_PPSBefore_tick); + tree->SetBranchAddress("TS_PPSAfter_tick", &TS_PPSAfter_tick); + tree->SetBranchAddress("TS_PPSDiff_tick", &TS_PPSDiff_tick); + tree->SetBranchAddress("TS_PPSMissing_tick", &TS_PPSMissing_tick); Long64_t nentries = tree->GetEntries(); cout << "LAPPDStoreReadIn Loading offsets and corrections, total entries: " << nentries << endl; @@ -1369,6 +1548,14 @@ void LAPPDLoadStore::LoadOffsetsAndCorrections() Offsets_minus_ps[key].resize(EventIndex + 1); BGCorrections[key].resize(EventIndex + 1); TSCorrections[key].resize(EventIndex + 1); + BG_PPSBefore_loaded[key].resize(EventIndex + 1); + BG_PPSAfter_loaded[key].resize(EventIndex + 1); + BG_PPSDiff_loaded[key].resize(EventIndex + 1); + BG_PPSMissing_loaded[key].resize(EventIndex + 1); + TS_PPSBefore_loaded[key].resize(EventIndex + 1); + TS_PPSAfter_loaded[key].resize(EventIndex + 1); + TS_PPSDiff_loaded[key].resize(EventIndex + 1); + TS_PPSMissing_loaded[key].resize(EventIndex + 1); } // Now using EventIndex to place each event correctly @@ -1377,10 +1564,19 @@ void LAPPDLoadStore::LoadOffsetsAndCorrections() BGCorrections[key][EventIndex] = static_cast(BGCorrection_tick) - 1000; TSCorrections[key][EventIndex] = static_cast(TSCorrection_tick) - 1000; + BG_PPSBefore_loaded[key][EventIndex] = BG_PPSBefore_tick; + BG_PPSAfter_loaded[key][EventIndex] = BG_PPSAfter_tick; + BG_PPSDiff_loaded[key][EventIndex] = BG_PPSDiff_tick; + BG_PPSMissing_loaded[key][EventIndex] = static_cast(BG_PPSMissing_tick) - 1000; + TS_PPSBefore_loaded[key][EventIndex] = TS_PPSBefore_tick; + TS_PPSAfter_loaded[key][EventIndex] = TS_PPSAfter_tick; + TS_PPSDiff_loaded[key][EventIndex] = TS_PPSDiff_tick; + TS_PPSMissing_loaded[key][EventIndex] = static_cast(TS_PPSMissing_tick) - 1000; + if (nentries > 10 && i % (static_cast(nentries / 10)) == 0) { cout << "LAPPDStoreReadIn Loading offsets and corrections, " << i << " entries loaded" << endl; - cout << "Printing key: " << key << ", EventIndex: " << EventIndex << ", final_offset_ns_0: " << final_offset_ns_0 << ", final_offset_ps_negative_0: " << final_offset_ps_negative_0 << ", BGCorrection_tick: " << BGCorrection_tick << ", TSCorrection_tick: " << TSCorrection_tick << endl; + cout << "Printing key: " << key << ", EventIndex: " << EventIndex << ", final_offset_ns_0: " << final_offset_ns_0 << ", final_offset_ps_negative_0: " << final_offset_ps_negative_0 << ", BGCorrection_tick: " << BGCorrection_tick << ", TSCorrection_tick: " << TSCorrection_tick << ", BG_PPSMissing_tick: " << BG_PPSMissing_tick << ", TS_PPSMissing_tick: " << TS_PPSMissing_tick << endl; } } diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.h b/UserTools/LAPPDLoadStore/LAPPDLoadStore.h index a6f28e5d1..c3bb8c3be 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.h +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.h @@ -105,6 +105,14 @@ class LAPPDLoadStore : public Tool vector LAPPDLoadedTSCorrections; vector LAPPDLoadedBGCorrections; vector LAPPDLoadedOSInMinusPS; + vector LAPPDLoadedBG_PPSBefore; + vector LAPPDLoadedBG_PPSAfter; + vector LAPPDLoadedBG_PPSDiff; + vector LAPPDLoadedBG_PPSMissing; + vector LAPPDLoadedTS_PPSBefore; + vector LAPPDLoadedTS_PPSAfter; + vector LAPPDLoadedTS_PPSDiff; + vector LAPPDLoadedTS_PPSMissing; vector ParaBoards; // save the board index for this PsecData std::map>> LAPPDWaveforms; @@ -131,6 +139,15 @@ class LAPPDLoadStore : public Tool std::map LAPPDBGCorrection; std::map LAPPDOSInMinusPS; std::map DataStreams; + // save PPS info for the second order correction + std::map LAPPDBG_PPSBefore; + std::map LAPPDBG_PPSAfter; + std::map LAPPDBG_PPSDiff; + std::map LAPPDBG_PPSMissing; + std::map LAPPDTS_PPSBefore; + std::map LAPPDTS_PPSAfter; + std::map LAPPDTS_PPSDiff; + std::map LAPPDTS_PPSMissing; // data variables don't need to be cleared in each loop // these are loaded offset for event building @@ -138,6 +155,16 @@ class LAPPDLoadStore : public Tool std::map> Offsets_minus_ps; // offset in ps, use offset - this/1e3 as the real offset std::map> BGCorrections; // Loaded BGcorrections, same key as Offsets, but offset saved on event by event basis in that part file, in unit of ticks std::map> TSCorrections; // TS corrections, in unit of ticks + std::map> BG_PPSBefore_loaded; // BG PPS before, in unit of ticks + std::map> BG_PPSAfter_loaded; // BG PPS after, in unit of ticks + std::map> BG_PPSDiff_loaded; // BG PPS Diff + std::map> BG_PPSMissing_loaded; // BG PPS Missing + std::map> TS_PPSBefore_loaded; // TS PPS before, in unit of ticks + std::map> TS_PPSAfter_loaded; // TS PPS after, in unit of ticks + std::map> TS_PPSDiff_loaded; // TS PPS Diff + std::map> TS_PPSMissing_loaded; // TS PPS Missing + + int runNumber; int subRunNumber; int partFileNumber; diff --git a/UserTools/PMTDataDecoder/PMTDataDecoder.cpp b/UserTools/PMTDataDecoder/PMTDataDecoder.cpp index ee4629f5b..6d6d50343 100644 --- a/UserTools/PMTDataDecoder/PMTDataDecoder.cpp +++ b/UserTools/PMTDataDecoder/PMTDataDecoder.cpp @@ -46,6 +46,14 @@ bool PMTDataDecoder::Initialise(std::string configfile, DataModel &data){ m_data->CStore.Set("FIFOError1",fifo1); m_data->CStore.Set("FIFOError2",fifo2); + saveRWMRaw = true; + saveBRFRaw = true; + m_variables.Get("saveRWMRaw",saveRWMRaw); + m_variables.Get("saveBRFRaw",saveBRFRaw); + RWMRawWaveforms = new std::map>; + BRFRawWaveforms = new std::map>; + + std::cout << "PMTDataDecoder Tool: Initialized successfully" << std::endl; return true; } @@ -305,6 +313,44 @@ bool PMTDataDecoder::Execute(){ m_data->CStore.Set("FIFOPMTWaves",FIFOPMTWaves); m_data->CStore.Set("TimestampsFromTheFuture",TimestampsFromTheFuture); + // loop the FinishedPMTWaves, for each timestamp, put the RWM and BRF waveform to RWMRawWaveforms and BRFRawWaveforms + if(saveBRFRaw || saveRWMRaw) + { + for (std::map, std::vector>>::iterator it = FinishedPMTWaves->begin(); it != FinishedPMTWaves->end(); it++) + { + uint64_t timestamp = it->first; + std::map, std::vector> afinishedPMTWaves = FinishedPMTWaves->at(timestamp); + for (std::pair, std::vector> apair : afinishedPMTWaves) + { + int CardID = apair.first.at(0); + int ChannelID = apair.first.at(1); + int SlotNum = CardID % 100; + int CrateNum = CardID / 1000; + unsigned int uCrateNum = (unsigned int)CrateNum; + unsigned int uSlotNum = (unsigned int)SlotNum; + unsigned int uChannelID = (unsigned int)ChannelID; + + //in MonitorTankTime tool, it load a file about active slot and crate, if not active, don't find the waveform in it. not sure do we need it or not + if(saveBRFRaw){ + if(uCrateNum == 1 && uSlotNum == 15 && ChannelID == 1) + { + std::vector BRFWaveform = apair.second; + (*BRFRawWaveforms)[timestamp] = BRFWaveform; + } + } + if(saveRWMRaw){ + if(uCrateNum == 1 && uSlotNum == 15 && ChannelID == 2) + { + std::vector RWMWaveform = apair.second; + (*RWMRawWaveforms)[timestamp] = RWMWaveform; + } + } + } + } + } + m_data->CStore.Set("RWMRawWaveforms",RWMRawWaveforms); + m_data->CStore.Set("BRFRawWaveforms",BRFRawWaveforms); + //Check the size of the WaveBank to see if things are bloating Log("PMTDataDecoder Tool: Size of WaveBank (# waveforms partially built): " + to_string(WaveBank.size()),v_message, verbosity); diff --git a/UserTools/PMTDataDecoder/PMTDataDecoder.h b/UserTools/PMTDataDecoder/PMTDataDecoder.h index 0e3274a57..6963f7af2 100644 --- a/UserTools/PMTDataDecoder/PMTDataDecoder.h +++ b/UserTools/PMTDataDecoder/PMTDataDecoder.h @@ -132,6 +132,14 @@ class PMTDataDecoder: public Tool { int vv_debug=4; std::string logmessage; + + //option about whether to save raw RWM and BRF waveforms + bool saveRWMRaw; + bool saveBRFRaw; + + std::map>* RWMRawWaveforms; //Key: MTCTime, Value: RWM waveform + std::map>* BRFRawWaveforms; //Key: MTCTime, Value: BRF waveform + }; diff --git a/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp index 0454415d9..c782f598e 100644 --- a/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp +++ b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp @@ -437,6 +437,40 @@ bool ProcessedLAPPDFilter::GotANNIEEventAndSave(BoostStore *BS, string savePath) m_data->Stores["ANNIEEvent"]->Get("beam_good", beam_good); BS->Set("beam_good", beam_good); + std::vector RWMRawWaveform; + std::vector BRFRawWaveform; + + m_data->Stores["ANNIEEvent"]->Get("RWMRawWaveform", RWMRawWaveform); + BS->Set("RWMRawWaveform", RWMRawWaveform); + m_data->Stores["ANNIEEvent"]->Get("BRFRawWaveform", BRFRawWaveform); + BS->Set("BRFRawWaveform", BRFRawWaveform); + + std::map LAPPDBG_PPSBefore; + std::map LAPPDBG_PPSAfter; + std::map LAPPDBG_PPSDiff; + std::map LAPPDBG_PPSMissing; + std::map LAPPDTS_PPSBefore; + std::map LAPPDTS_PPSAfter; + std::map LAPPDTS_PPSDiff; + std::map LAPPDTS_PPSMissing; + + m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSBefore", LAPPDBG_PPSBefore); + BS->Set("LAPPDBG_PPSBefore", LAPPDBG_PPSBefore); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSAfter", LAPPDBG_PPSAfter); + BS->Set("LAPPDBG_PPSAfter", LAPPDBG_PPSAfter); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSDiff", LAPPDBG_PPSDiff); + BS->Set("LAPPDBG_PPSDiff", LAPPDBG_PPSDiff); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSMissing", LAPPDBG_PPSMissing); + BS->Set("LAPPDBG_PPSMissing", LAPPDBG_PPSMissing); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSBefore", LAPPDTS_PPSBefore); + BS->Set("LAPPDTS_PPSBefore", LAPPDTS_PPSBefore); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSAfter", LAPPDTS_PPSAfter); + BS->Set("LAPPDTS_PPSAfter", LAPPDTS_PPSAfter); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSDiff", LAPPDTS_PPSDiff); + BS->Set("LAPPDTS_PPSDiff", LAPPDTS_PPSDiff); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSMissing", LAPPDTS_PPSMissing); + BS->Set("LAPPDTS_PPSMissing", LAPPDTS_PPSMissing); + BS->Save(savePath); if (FilterVerbosity > 2) cout << "Saved to " << savePath << " successfully" << endl; diff --git a/UserTools/Unity.h b/UserTools/Unity.h index 2d7d9305d..a24befea3 100644 --- a/UserTools/Unity.h +++ b/UserTools/Unity.h @@ -191,3 +191,4 @@ #include "ANNIEEventTreeMaker.h" #include "ProcessedLAPPDFilter.h" #include "BeamQuality.h" +#include "FitRWMWaveform.h" diff --git a/configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig b/configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig index 2912a96e6..c34f5e446 100644 --- a/configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig +++ b/configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig @@ -26,3 +26,4 @@ HasGenie 0 LAPPDData_fill 1 LAPPDReco_fill 1 +RWMBRF_fill 1 diff --git a/configfiles/BeamClusterAnalysis/FitRWMWaveformConfig b/configfiles/BeamClusterAnalysis/FitRWMWaveformConfig new file mode 100644 index 000000000..0a724adf4 --- /dev/null +++ b/configfiles/BeamClusterAnalysis/FitRWMWaveformConfig @@ -0,0 +1,4 @@ +verbosityFitRWMWaveform 1 +printToRootFile 1 + + diff --git a/configfiles/BeamClusterAnalysis/ToolsConfig b/configfiles/BeamClusterAnalysis/ToolsConfig index 4d2282e93..acd57e65e 100644 --- a/configfiles/BeamClusterAnalysis/ToolsConfig +++ b/configfiles/BeamClusterAnalysis/ToolsConfig @@ -9,11 +9,12 @@ myClusterClassifiers ClusterClassifiers ./configfiles/BeamClusterAnalysis/Cluste myEventSelector EventSelector ./configfiles/BeamClusterAnalysis/EventSelectorConfig LAPPDLoadStore LAPPDLoadStore configfiles/LAPPDProcessedAna/Configs -LAPPDStoreReorder LAPPDStoreReorder configfiles/LAPPDProcessedAna/ConfigStoreReadIn -LAPPDTimeAlignment LAPPDTimeAlignment configfiles/LAPPDProcessedAna/ConfigPreProcess -LAPPDBaseline LAPPDBaseline configfiles/LAPPDProcessedAna/ConfigPreProcess -LAPPDThresReco LAPPDThresReco configfiles/LAPPDProcessedAna/ConfigPlot +#LAPPDStoreReorder LAPPDStoreReorder configfiles/LAPPDProcessedAna/ConfigStoreReadIn +#LAPPDTimeAlignment LAPPDTimeAlignment configfiles/LAPPDProcessedAna/ConfigPreProcess +#LAPPDBaseline LAPPDBaseline configfiles/LAPPDProcessedAna/ConfigPreProcess +#LAPPDThresReco LAPPDThresReco configfiles/LAPPDProcessedAna/ConfigPlot +FitRWMWaveform FitRWMWaveform ./configfiles/BeamClusterAnalysis/FitRWMWaveformConfig ANNIEEventTreeMaker ANNIEEventTreeMaker ./configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig #myPhaseIITreeMaker PhaseIITreeMaker ./configfiles/BeamClusterAnalysis/PhaseIITreeMakerConfig diff --git a/configfiles/EventBuilderV2/EBSaverConfig b/configfiles/EventBuilderV2/EBSaverConfig index 781d748e2..90f5ca4ae 100644 --- a/configfiles/EventBuilderV2/EBSaverConfig +++ b/configfiles/EventBuilderV2/EBSaverConfig @@ -1,4 +1,4 @@ -verbosityEBSaver 1 +verbosityEBSaver 4 savePMT 1 saveMRD 1 diff --git a/configfiles/LAPPDProcessedAna/Configs b/configfiles/LAPPDProcessedAna/Configs index 472ab885f..0772b6901 100644 --- a/configfiles/LAPPDProcessedAna/Configs +++ b/configfiles/LAPPDProcessedAna/Configs @@ -1,4 +1,4 @@ - General Parameters +#General Parameters Nsamples 256 #Number of samples in a waveform SampleSize 100 #Sample size for baseline substraction TrigChannel 5 #Specified channel the trigger signal will be on From 2e9b5814ab610bc220fa6e6d5a69b8945843d7cb Mon Sep 17 00:00:00 2001 From: Yue Date: Fri, 26 Jul 2024 18:37:50 -0500 Subject: [PATCH 073/163] add LAPPD offset Fit script modifications --- offsetFit_MultipleLAPPD.cpp | 160 ++++++++++++++++++++++++++++++++++-- 1 file changed, 152 insertions(+), 8 deletions(-) diff --git a/offsetFit_MultipleLAPPD.cpp b/offsetFit_MultipleLAPPD.cpp index 7cad5de6b..3c5932981 100644 --- a/offsetFit_MultipleLAPPD.cpp +++ b/offsetFit_MultipleLAPPD.cpp @@ -381,6 +381,15 @@ vector> fitInThisReset( vector LAPPD_PPS_missing_ticks; vector LAPPD_PPS_interval_ticks; + vector BG_PPSBefore; + vector BG_PPSAfter; + vector BG_PPSDiff; + vector BG_PPSMiss; + vector TS_PPSBefore; + vector TS_PPSAfter; + vector TS_PPSDiff; + vector TS_PPSMiss; + // calculate the missing ticks for each LAPPD PPS PPS_tick_correction.push_back(0); LAPPD_PPS_missing_ticks.push_back(0); @@ -466,6 +475,11 @@ vector> fitInThisReset( // loop all data events, plus the offset, save the event time and beamgate time // fing the closest CTC trigger, also save all information + cout << "Start saving results. PPS size: " << LAPPD_PPS.size() << ", beamgate size: " << LAPPDDataBeamgateUL.size() << endl; + cout << "First PPS: " << LAPPD_PPS.at(0) / 3125 << ", Last PPS: " << LAPPD_PPS.at(LAPPD_PPS.size() - 1) / 3125 << endl; + cout << "First BG: " << LAPPDDataBeamgateUL.at(0) / 3125 << ", Last BG: " << LAPPDDataBeamgateUL.at(LAPPDDataBeamgateUL.size() - 1) / 3125 << endl; + cout << "First TS: " << LAPPDDataTimeStampUL.at(0) / 3125 << ", Last TS: " << LAPPDDataTimeStampUL.at(LAPPDDataTimeStampUL.size() - 1) / 3125 << endl; + for (int l = 0; l < LAPPDDataTimeStampUL.size(); l++) { ULong64_t TS_ns = LAPPDDataTimeStampUL.at(l) / 1000; @@ -571,6 +585,100 @@ vector> fitInThisReset( cout << "TimeStamp_correction_tick at " << l << ": " << TimeStamp_correction_tick.at(l) << endl; */ + // for this LAPPDDataBeamgateUL.at(l), in the LAPPD_PPS vector, find it's closest PPS before and after, and also calculate the time difference between them, and the missing tick between them. + // save as BG_PPSBefore_tick, BG_PPSAfter_tick, BG_PPSDiff_tick, BG_PPSMissing_tick + // Do the same thing for LAPPDDataTimeStampUL.at(l), save as TS_PPSBefore_tick, TS_PPSAfter_tick, TS_PPSDiff_tick, TS_PPSMissing_tick + + ULong64_t BG_PPSBefore_tick = 0; + ULong64_t BG_PPSAfter_tick = 0; + ULong64_t BG_PPSDiff_tick = 0; + ULong64_t BG_PPSMissing_tick = 0; + + ULong64_t TS_PPSBefore_tick = 0; + ULong64_t TS_PPSAfter_tick = 0; + ULong64_t TS_PPSDiff_tick = 0; + ULong64_t TS_PPSMissing_tick = 0; + // if the first PPS is later than beamgate, then set before = 0, after is the first, diff is the first, missing is the first + + cout << "Start finding PPS before and after the beamgate" << endl; + + if ((LAPPD_PPS.at(0) / 3125 > LAPPDDataBeamgateUL.at(l) / 3125) || (LAPPD_PPS.at(LAPPD_PPS.size() - 1) / 3125 < LAPPDDataBeamgateUL.at(l) / 3125)) + { + if (LAPPD_PPS.at(0) / 3125 > LAPPDDataBeamgateUL.at(l) / 3125) + { + BG_PPSBefore_tick = 0; + BG_PPSAfter_tick = LAPPD_PPS.at(0) / 3125; + BG_PPSDiff_tick = LAPPD_PPS.at(0) / 3125; + BG_PPSMissing_tick = LAPPD_PPS.at(0) / 3125; + cout << "First PPS is later than beamgate, before is 0, after is the first, diff is the first, missing is the first" << endl; + } + // if the last PPS is earlier than beamgate, then set before is the last, after = 0, diff is the last, missing is the last + if (LAPPD_PPS.at(LAPPD_PPS.size() - 1) / 3125 < LAPPDDataBeamgateUL.at(l) / 3125) + { + BG_PPSBefore_tick = LAPPD_PPS.at(LAPPD_PPS.size() - 1) / 3125; + BG_PPSAfter_tick = 0; + BG_PPSDiff_tick = LAPPD_PPS.at(LAPPD_PPS.size() - 1) / 3125; + BG_PPSMissing_tick = LAPPD_PPS.at(LAPPD_PPS.size() - 1) / 3125; + cout << "Last PPS is earlier than beamgate, before is the last, after is 0, diff is the last, missing is the last" << endl; + } + } + else + { + // if the first PPS is earlier than beamgate, and the last PPS is later than beamgate, then find the closest PPS before and after + for (int i = 0; i < LAPPD_PPS.size() - 1; i++) + { + if (LAPPD_PPS.at(i) / 3125 < LAPPDDataBeamgateUL.at(l) / 3125 && LAPPD_PPS.at(i + 1) / 3125 > LAPPDDataBeamgateUL.at(l) / 3125) + { + BG_PPSBefore_tick = LAPPD_PPS.at(i) / 3125; + BG_PPSAfter_tick = LAPPD_PPS.at(i + 1) / 3125; + BG_PPSDiff_tick = LAPPD_PPS.at(i + 1) / 3125 - LAPPD_PPS.at(i) / 3125; + ULong64_t DiffTick = (LAPPD_PPS.at(i + 1) - LAPPD_PPS.at(i)) / 3125 - 1000; + BG_PPSMissing_tick = 3200000000 - DiffTick; + cout << "Found PPS before and after the beamgate, before: " << BG_PPSBefore_tick << ", after: " << BG_PPSAfter_tick << ", diff: " << BG_PPSDiff_tick << ", missing: " << BG_PPSMissing_tick << endl; + break; + } + } + } + + // do the samething for timestamp + cout << "Start finding PPS before and after the timestamp" << endl; + + if ((LAPPD_PPS.at(0) / 3125 > LAPPDDataTimeStampUL.at(l) / 3125) || (LAPPD_PPS.at(LAPPD_PPS.size() - 1) / 3125 < LAPPDDataTimeStampUL.at(l) / 3125)) + { + if (LAPPD_PPS.at(0) / 3125 > LAPPDDataTimeStampUL.at(l) / 3125) + { + TS_PPSBefore_tick = 0; + TS_PPSAfter_tick = LAPPD_PPS.at(0) / 3125; + TS_PPSDiff_tick = LAPPD_PPS.at(0) / 3125; + TS_PPSMissing_tick = LAPPD_PPS.at(0) / 3125; + cout << "First PPS is later than timestamp, before is 0, after is the first, diff is the first, missing is the first" << endl; + } + if (LAPPD_PPS.at(LAPPD_PPS.size() - 1) / 3125 < LAPPDDataTimeStampUL.at(l) / 3125) + { + TS_PPSBefore_tick = LAPPD_PPS.at(LAPPD_PPS.size() - 1) / 3125; + TS_PPSAfter_tick = 0; + TS_PPSDiff_tick = LAPPD_PPS.at(LAPPD_PPS.size() - 1) / 3125; + TS_PPSMissing_tick = LAPPD_PPS.at(LAPPD_PPS.size() - 1) / 3125; + cout << "Last PPS is earlier than timestamp, before is the last, after is 0, diff is the last, missing is the last" << endl; + } + } + else + { + for (int i = 0; i < LAPPD_PPS.size() - 1; i++) + { + if (LAPPD_PPS.at(i) / 3125 < LAPPDDataTimeStampUL.at(l) / 3125 && LAPPD_PPS.at(i + 1) / 3125 > LAPPDDataTimeStampUL.at(l) / 3125) + { + TS_PPSBefore_tick = LAPPD_PPS.at(i) / 3125; + TS_PPSAfter_tick = LAPPD_PPS.at(i + 1) / 3125; + TS_PPSDiff_tick = LAPPD_PPS.at(i + 1) / 3125 - LAPPD_PPS.at(i) / 3125; + ULong64_t DiffTick = (LAPPD_PPS.at(i + 1) - LAPPD_PPS.at(i)) / 3125 - 1000; + TS_PPSMissing_tick = 3200000000 - DiffTick; + cout << "Found PPS before and after the timestamp, before: " << TS_PPSBefore_tick << ", after: " << TS_PPSAfter_tick << ", diff: " << TS_PPSDiff_tick << ", missing: " << TS_PPSMissing_tick << endl; + break; + } + } + } + TimeStampRaw.push_back(LAPPDDataTimeStampUL.at(l) / 3125); BeamGateRaw.push_back(LAPPDDataBeamgateUL.at(l) / 3125); TimeStamp_ns.push_back(DriftCorrectedTS_ns); @@ -582,6 +690,15 @@ vector> fitInThisReset( // to get ps, should minus the TS_truncated_ps CTCTriggerIndex.push_back(matchedIndex); CTCTriggerTimeStamp_ns.push_back(CTCTrigger.at(matchedIndex)); + + BG_PPSBefore.push_back(BG_PPSBefore_tick); + BG_PPSAfter.push_back(BG_PPSAfter_tick); + BG_PPSDiff.push_back(BG_PPSDiff_tick); + BG_PPSMiss.push_back(BG_PPSMissing_tick); + TS_PPSBefore.push_back(TS_PPSBefore_tick); + TS_PPSAfter.push_back(TS_PPSAfter_tick); + TS_PPSDiff.push_back(TS_PPSDiff_tick); + TS_PPSMiss.push_back(TS_PPSMissing_tick); } ULong64_t totalEventNumber = LAPPDDataTimeStampUL.size(); ULong64_t gotOrphanCount_out = gotOrphanCount; @@ -594,7 +711,7 @@ vector> fitInThisReset( vector FitInfo = {final_offset_ns, final_offset_ps_negative, gotOrphanCount_out, gotMin_mean_dev_noOrphan_out, increament_times_out, min_mean_dev_out, final_i_out, final_j_out, totalEventNumber, drift_out}; - vector> Result = {FitInfo, TimeStampRaw, BeamGateRaw, TimeStamp_ns, BeamGate_ns, TimeStamp_ps, BeamGate_ps, EventIndex, EventDeviation_ns, CTCTriggerIndex, CTCTriggerTimeStamp_ns, BeamGate_correction_tick, TimeStamp_correction_tick, LAPPD_PPS_interval_ticks}; + vector> Result = {FitInfo, TimeStampRaw, BeamGateRaw, TimeStamp_ns, BeamGate_ns, TimeStamp_ps, BeamGate_ps, EventIndex, EventDeviation_ns, CTCTriggerIndex, CTCTriggerTimeStamp_ns, BeamGate_correction_tick, TimeStamp_correction_tick, LAPPD_PPS_interval_ticks, BG_PPSBefore, BG_PPSAfter, BG_PPSDiff, BG_PPSMiss, TS_PPSBefore, TS_PPSAfter, TS_PPSDiff, TS_PPSMiss}; return Result; } @@ -993,6 +1110,14 @@ void offsetFit_MultipleLAPPD(string fileName, int fitTargetTriggerWord, bool tri long long BGCorrection_tick; long long TSCorrection_tick; ULong64_t LAPPD_PPS_interval_ticks; + ULong64_t BG_PPSBefore_tick; + ULong64_t BG_PPSAfter_tick; + ULong64_t BG_PPSDiff_tick; + ULong64_t BG_PPSMissing_tick; + ULong64_t TS_PPSBefore_tick; + ULong64_t TS_PPSAfter_tick; + ULong64_t TS_PPSDiff_tick; + ULong64_t TS_PPSMissing_tick; tOut->Branch("runNumber", &runNumber_out, "runNumber/I"); tOut->Branch("subRunNumber", &subRunNumber_out, "subRunNumber/I"); tOut->Branch("partFileNumber", &partFileNumber_out, "partFileNumber/I"); @@ -1025,6 +1150,14 @@ void offsetFit_MultipleLAPPD(string fileName, int fitTargetTriggerWord, bool tri tOut->Branch("BGCorrection_tick", &BGCorrection_tick, "BGCorrection_tick/l"); tOut->Branch("TSCorrection_tick", &TSCorrection_tick, "TSCorrection_tick/l"); tOut->Branch("LAPPD_PPS_interval_ticks", &LAPPD_PPS_interval_ticks, "LAPPD_PPS_interval_ticks/l"); + tOut->Branch("BG_PPSBefore_tick", &BG_PPSBefore_tick, "BG_PPSBefore_tick/l"); + tOut->Branch("BG_PPSAfter_tick", &BG_PPSAfter_tick, "BG_PPSAfter_tick/l"); + tOut->Branch("BG_PPSDiff_tick", &BG_PPSDiff_tick, "BG_PPSDiff_tick/l"); + tOut->Branch("BG_PPSMissing_tick", &BG_PPSMissing_tick, "BG_PPSMissing_tick/l"); + tOut->Branch("TS_PPSBefore_tick", &TS_PPSBefore_tick, "TS_PPSBefore_tick/l"); + tOut->Branch("TS_PPSAfter_tick", &TS_PPSAfter_tick, "TS_PPSAfter_tick/l"); + tOut->Branch("TS_PPSDiff_tick", &TS_PPSDiff_tick, "TS_PPSDiff_tick/l"); + tOut->Branch("TS_PPSMissing_tick", &TS_PPSMissing_tick, "TS_PPSMissing_tick/l"); std::ofstream outputEvents("outputEvents.txt"); for (auto it = ResultMap.begin(); it != ResultMap.end(); it++) { @@ -1039,19 +1172,22 @@ void offsetFit_MultipleLAPPD(string fileName, int fitTargetTriggerWord, bool tri partFileNumber_out = std::stoi(key.substr(key.find("_", key.find("_") + 1) + 1, key.find("_", key.find("_", key.find("_") + 1) + 1) - key.find("_", key.find("_") + 1) - 1)); LAPPD_ID_out = std::stoi(key.substr(key.find("_", key.find("_", key.find("_") + 1) + 1) + 1, key.size() - key.find("_", key.find("_", key.find("_") + 1) + 1) - 1)); final_offset_ns_0 = Result[0][0]; - final_offset_ns_1 = Result[14][0]; + final_offset_ns_1 = Result[22][0]; final_offset_ps_negative_0 = Result[0][1]; - final_offset_ps_negative_1 = Result[14][1]; + final_offset_ps_negative_1 = Result[22][1]; gotOrphanCount_0 = Result[0][2]; - gotOrphanCount_1 = Result[14][2]; + gotOrphanCount_1 = Result[22][2]; gotMin_mean_dev_noOrphan_0 = Result[0][3]; - gotMin_mean_dev_noOrphan_1 = Result[14][3]; + gotMin_mean_dev_noOrphan_1 = Result[22][3]; increament_times_0 = Result[0][4]; - increament_times_1 = Result[14][4]; + increament_times_1 = Result[22][4]; min_mean_dev_0 = Result[0][5]; - min_mean_dev_1 = Result[14][5]; + min_mean_dev_1 = Result[22][5]; EventNumberInThisPartFile = Result[0][8]; + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 + // vector> Result = {FitInfo, TimeStampRaw, BeamGateRaw, TimeStamp_ns, BeamGate_ns, TimeStamp_ps, BeamGate_ps, EventIndex, EventDeviation_ns, CTCTriggerIndex, CTCTriggerTimeStamp_ns, BeamGate_correction_tick, TimeStamp_correction_tick, LAPPD_PPS_interval_ticks, BG_PPSBefore, BG_PPSAfter, BG_PPSDiff, BG_PPSMiss, TS_PPSBefore, TS_PPSAfter, TS_PPSDiff, TS_PPSMiss}; + // any Result[x] , if x>13, x = x + 8 for (int j = 0; j < Result[1].size(); j++) { long long BGTdiff = Result[4][j] - Result[10][j] - 325250; @@ -1068,11 +1204,19 @@ void offsetFit_MultipleLAPPD(string fileName, int fitTargetTriggerWord, bool tri CTCTriggerIndex = Result[9][j]; CTCTriggerTimeStamp_ns = Result[10][j]; EventDeviation_ns_0 = Result[8][j]; - EventDeviation_ns_1 = Result[20][j]; + EventDeviation_ns_1 = Result[28][j]; BGMinusTrigger_ns = BGTdiff; BGCorrection_tick = Result[11][j]; TSCorrection_tick = Result[12][j]; LAPPD_PPS_interval_ticks = Result[13][j]; + BG_PPSBefore_tick = Result[14][j]; + BG_PPSAfter_tick = Result[15][j]; + BG_PPSDiff_tick = Result[16][j]; + BG_PPSMissing_tick = Result[17][j]; + TS_PPSBefore_tick = Result[18][j]; + TS_PPSAfter_tick = Result[19][j]; + TS_PPSDiff_tick = Result[20][j]; + TS_PPSMissing_tick = Result[21][j]; tOut->Fill(); } outputOffset << runNumber_out << "\t" << subRunNumber_out << "\t" << partFileNumber_out << "\t" << 0 << "\t" << LAPPD_ID_out << "\t" << final_offset_ns_0 << "\t" << final_offset_ns_1 << "\t" << final_offset_ps_negative_0 << "\t" << final_offset_ps_negative_1 << "\t" << gotOrphanCount_0 << "\t" << gotOrphanCount_1 << "\t" << EventNumberInThisPartFile << "\t" << gotMin_mean_dev_noOrphan_0 << "\t" << gotMin_mean_dev_noOrphan_1 << "\t" << increament_times_0 << "\t" << increament_times_1 << "\t" << min_mean_dev_0 << "\t" << min_mean_dev_1 << std::endl; From f615bfd9251f56c9eebe65337679c38420046adc Mon Sep 17 00:00:00 2001 From: Yue Date: Fri, 26 Jul 2024 20:00:53 -0500 Subject: [PATCH 074/163] add pulse information in LAPPDHit, save the pulse information for hits in the Tree Maker Changes to be committed: modified: DataModel/LAPPDHit.h modified: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp --- DataModel/LAPPDHit.h | 7 +++++++ UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/DataModel/LAPPDHit.h b/DataModel/LAPPDHit.h index 7e34c8d7f..251ac38b8 100755 --- a/DataModel/LAPPDHit.h +++ b/DataModel/LAPPDHit.h @@ -82,6 +82,13 @@ class LAPPDHit : public Hit ar & Position; ar & LocalPosition; ar & Charge; + + ar & Pulse1LastTime; + ar & Pulse2LastTime; + ar & Pulse1StartTime; + ar & Pulse2StartTime; + ar & pulse1; + ar & pulse2; } } }; diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index 0017fe987..e8a4c2e81 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -1329,6 +1329,8 @@ void ANNIEEventTreeMaker::FillLAPPDHit() fLAPPDHitTime.push_back(thisHit.GetTime()); fLAPPDHitAmp.push_back(thisHit.GetCharge()); vector position = thisHit.GetPosition(); + p1.Print(); + p2.Print(); /* XPosTank = position.at(0); YPosTank = position.at(1); @@ -1340,7 +1342,7 @@ void ANNIEEventTreeMaker::FillLAPPDHit() // fLAPPDHitP2StartTime.push_back(thisHit.GetPulse2StartTime()); // fLAPPDHitP1EndTime.push_back(thisHit.GetPulse1LastTime()); // fLAPPDHitP2EndTime.push_back(thisHit.GetPulse2LastTime()); - + cout<<"Pulse 1 start time: "< Date: Fri, 26 Jul 2024 20:03:13 -0500 Subject: [PATCH 075/163] Remove the pulse info printing in the tree maker --- UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index e8a4c2e81..40e2ee80e 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -1329,8 +1329,6 @@ void ANNIEEventTreeMaker::FillLAPPDHit() fLAPPDHitTime.push_back(thisHit.GetTime()); fLAPPDHitAmp.push_back(thisHit.GetCharge()); vector position = thisHit.GetPosition(); - p1.Print(); - p2.Print(); /* XPosTank = position.at(0); YPosTank = position.at(1); From c9835ca1892e725043c05255ff5a79dcb06e7d3e Mon Sep 17 00:00:00 2001 From: Yue Date: Sat, 27 Jul 2024 00:17:05 -0500 Subject: [PATCH 076/163] Changes to be committed: modified: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp modified: configfiles/BeamClusterAnalysis/ToolsConfig --- UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp | 2 +- configfiles/BeamClusterAnalysis/ToolsConfig | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index 40e2ee80e..c21eca4ae 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -1340,7 +1340,7 @@ void ANNIEEventTreeMaker::FillLAPPDHit() // fLAPPDHitP2StartTime.push_back(thisHit.GetPulse2StartTime()); // fLAPPDHitP1EndTime.push_back(thisHit.GetPulse1LastTime()); // fLAPPDHitP2EndTime.push_back(thisHit.GetPulse2LastTime()); - cout<<"Pulse 1 start time: "< Date: Mon, 29 Jul 2024 16:39:36 -0500 Subject: [PATCH 077/163] Add an option to not load PPS infor in the LAPPDLoadStore and tree make for preprocessed data without PPS Changes to be committed: modified: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp modified: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h modified: UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp modified: UserTools/LAPPDLoadStore/LAPPDLoadStore.h modified: configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig modified: configfiles/LAPPDProcessedAna/Configs --- .../ANNIEEventTreeMaker.cpp | 5 ++ .../ANNIEEventTreeMaker/ANNIEEventTreeMaker.h | 1 + UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp | 85 +++++++++++-------- UserTools/LAPPDLoadStore/LAPPDLoadStore.h | 34 ++++---- .../ANNIEEventTreeMakerConfig | 1 + configfiles/LAPPDProcessedAna/Configs | 1 + 6 files changed, 71 insertions(+), 56 deletions(-) diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index c21eca4ae..b0a0746ca 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -42,6 +42,7 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) m_variables.Get("LAPPDData_fill", LAPPDData_fill); m_variables.Get("SiPMPulseInfo_fill", SiPMPulseInfo_fill); m_variables.Get("LAPPDReco_fill", LAPPDReco_fill); + m_variables.Get("LAPPD_PPS_fill", LAPPD_PPS_fill); std::string output_filename = "ANNIEEventTree.root"; m_variables.Get("OutputFile", output_filename); @@ -180,6 +181,7 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) fANNIETree->Branch("LAPPD_TSCorrection", &fLAPPD_TSCorrection); fANNIETree->Branch("LAPPD_BGCorrection", &fLAPPD_BGCorrection); fANNIETree->Branch("LAPPD_OSInMinusPS", &fLAPPD_OSInMinusPS); + if(LAPPD_PPS_fill){ fANNIETree->Branch("LAPPD_BGPPSBefore", &fLAPPD_BGPPSBefore); fANNIETree->Branch("LAPPD_BGPPSAfter", &fLAPPD_BGPPSAfter); fANNIETree->Branch("LAPPD_BGPPSDiff", &fLAPPD_BGPPSDiff); @@ -188,6 +190,7 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) fANNIETree->Branch("LAPPD_TSPPSAfter", &fLAPPD_TSPPSAfter); fANNIETree->Branch("LAPPD_TSPPSDiff", &fLAPPD_TSPPSDiff); fANNIETree->Branch("LAPPD_TSPPSMissing", &fLAPPD_TSPPSMissing); + } } // LAPPD reconstruction information @@ -630,6 +633,7 @@ void ANNIEEventTreeMaker::ResetVariables() fLAPPD_TSCorrection.clear(); fLAPPD_BGCorrection.clear(); fLAPPD_OSInMinusPS.clear(); + // LAPPD_PPS_fill fLAPPD_BGPPSBefore.clear(); fLAPPD_BGPPSAfter.clear(); fLAPPD_BGPPSDiff.clear(); @@ -896,6 +900,7 @@ void ANNIEEventTreeMaker::ResetVariables() LAPPDTSCorrection.clear(); LAPPDBGCorrection.clear(); LAPPDOSInMinusPS.clear(); + // LAPPD_PPS_fill LAPPDBG_PPSBefore.clear(); LAPPDBG_PPSAfter.clear(); LAPPDBG_PPSDiff.clear(); diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h index 1a7a4505f..bef8821b4 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h @@ -110,6 +110,7 @@ class ANNIEEventTreeMaker : public Tool bool MRDHitInfo_fill = 1; bool LAPPDData_fill = 1; bool RWMBRF_fill = 1; + bool LAPPD_PPS_fill = 1; // What reco information will be filled bool MCTruth_fill = 0; // Output the MC truth information diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp index b74d8b62c..3d0eda87f 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp @@ -41,6 +41,8 @@ bool LAPPDLoadStore::Initialise(std::string configfile, DataModel &data) m_variables.Get("loadPPS", loadPPS); loadOffsets = false; m_variables.Get("loadOffsets", loadOffsets); + LoadBuiltPPSInfo = true; + m_variables.Get("LoadBuiltPPSInfo", LoadBuiltPPSInfo); // Control variables in this tool, initialized in this tool NonEmptyEvents = 0; NonEmptyDataEvents = 0; @@ -186,7 +188,7 @@ bool LAPPDLoadStore::Execute() { bool gotDataStream = m_data->Stores.at("ANNIEEvent")->Get("DataStreams", DataStreams); bool getMap = m_data->Stores["ANNIEEvent"]->Get("LAPPDDataMap", LAPPDDataMap); - if (getMap && DataStreams["LAPPD"]==true && LAPPDDataMap.size() > 0) + if (getMap && DataStreams["LAPPD"] == true && LAPPDDataMap.size() > 0) { // cout << "Outside, size of LAPPDDatamap = " << LAPPDDataMap.size() << endl; bool gotBeamgates_ns = m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); @@ -197,24 +199,28 @@ bool LAPPDLoadStore::Execute() bool gotTSCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDTSCorrection", LAPPDTSCorrection); bool gotDBGCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDBGCorrection", LAPPDBGCorrection); bool gotOSInMinusPS = m_data->Stores["ANNIEEvent"]->Get("LAPPDOSInMinusPS", LAPPDOSInMinusPS); - - bool gotBG_PPSBefore = m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSBefore", LAPPDBG_PPSBefore); - bool gotBG_PPSAfter = m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSAfter", LAPPDBG_PPSAfter); - bool gotBG_PPSDiff = m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSDiff", LAPPDBG_PPSDiff); - bool gotBG_PPSMissing = m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSMissing", LAPPDBG_PPSMissing); - bool gotTS_PPSBefore = m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSBefore", LAPPDTS_PPSBefore); - bool gotTS_PPSAfter = m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSAfter", LAPPDTS_PPSAfter); - bool gotTS_PPSDiff = m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSDiff", LAPPDTS_PPSDiff); - bool gotTS_PPSMissing = m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSMissing", LAPPDTS_PPSMissing); - if (LAPPDStoreReadInVerbosity > 3) + if (LoadBuiltPPSInfo) { - cout << "LAPPDLoadStore: gotOffsets = " << gotOffsets << ", gotBG_PPSBefore = " << gotBG_PPSBefore << ", gotTS_PPSBefore = " << gotTS_PPSBefore << endl; - cout << "Size of LAPPDDataMap = " << LAPPDDataMap.size() << ", LAPPDOffsets = " << LAPPDOffsets.size() << ", LAPPDBG_PPSBefore = " << LAPPDBG_PPSBefore.size() << ", LAPPDTS_PPSBefore = " << LAPPDTS_PPSBefore.size() << endl; + bool gotBG_PPSBefore = m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSBefore", LAPPDBG_PPSBefore); + bool gotBG_PPSAfter = m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSAfter", LAPPDBG_PPSAfter); + bool gotBG_PPSDiff = m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSDiff", LAPPDBG_PPSDiff); + bool gotBG_PPSMissing = m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSMissing", LAPPDBG_PPSMissing); + bool gotTS_PPSBefore = m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSBefore", LAPPDTS_PPSBefore); + bool gotTS_PPSAfter = m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSAfter", LAPPDTS_PPSAfter); + bool gotTS_PPSDiff = m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSDiff", LAPPDTS_PPSDiff); + bool gotTS_PPSMissing = m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSMissing", LAPPDTS_PPSMissing); + if (LAPPDStoreReadInVerbosity > 3) + { + cout << "LAPPDLoadStore: gotOffsets = " << gotOffsets << ", gotBG_PPSBefore = " << gotBG_PPSBefore << ", gotTS_PPSBefore = " << gotTS_PPSBefore << endl; + cout << "Size of LAPPDDataMap = " << LAPPDDataMap.size() << ", LAPPDOffsets = " << LAPPDOffsets.size() << ", LAPPDBG_PPSBefore = " << LAPPDBG_PPSBefore.size() << ", LAPPDTS_PPSBefore = " << LAPPDTS_PPSBefore.size() << endl; - cout << "gotBG_PPSBefore = " << gotBG_PPSBefore << ", gotBG_PPSAfter = " << gotBG_PPSAfter << ", gotBG_PPSDiff = " << gotBG_PPSDiff << ", gotBG_PPSMissing = " << gotBG_PPSMissing << endl; - cout << "gotTS_PPSBefore = " << gotTS_PPSBefore << ", gotTS_PPSAfter = " << gotTS_PPSAfter << ", gotTS_PPSDiff = " << gotTS_PPSDiff << ", gotTS_PPSMissing = " << gotTS_PPSMissing << endl; + cout << "gotBG_PPSBefore = " << gotBG_PPSBefore << ", gotBG_PPSAfter = " << gotBG_PPSAfter << ", gotBG_PPSDiff = " << gotBG_PPSDiff << ", gotBG_PPSMissing = " << gotBG_PPSMissing << endl; + cout << "gotTS_PPSBefore = " << gotTS_PPSBefore << ", gotTS_PPSAfter = " << gotTS_PPSAfter << ", gotTS_PPSDiff = " << gotTS_PPSDiff << ", gotTS_PPSMissing = " << gotTS_PPSMissing << endl; + } } - }else{ + } + else + { return true; } } @@ -448,22 +454,26 @@ bool LAPPDLoadStore::Execute() LAPPDLoadedTSCorrections.push_back(LAPPDTSCorrection.at(time)); LAPPDLoadedBGCorrections.push_back(LAPPDBGCorrection.at(time)); LAPPDLoadedOSInMinusPS.push_back(LAPPDOSInMinusPS.at(time)); - LAPPDLoadedBG_PPSBefore.push_back(LAPPDBG_PPSBefore.at(time)); - LAPPDLoadedBG_PPSAfter.push_back(LAPPDBG_PPSAfter.at(time)); - LAPPDLoadedBG_PPSDiff.push_back(LAPPDBG_PPSDiff.at(time)); - LAPPDLoadedBG_PPSMissing.push_back(LAPPDBG_PPSMissing.at(time)); - LAPPDLoadedTS_PPSBefore.push_back(LAPPDTS_PPSBefore.at(time)); - LAPPDLoadedTS_PPSAfter.push_back(LAPPDTS_PPSAfter.at(time)); - LAPPDLoadedTS_PPSDiff.push_back(LAPPDTS_PPSDiff.at(time)); - LAPPDLoadedTS_PPSMissing.push_back(LAPPDTS_PPSMissing.at(time)); if (LAPPDStoreReadInVerbosity > 2) cout << "parsing finished for LAPPD_ID " << LAPPD_ID << " at time " << time << endl; - if (LAPPDTS_PPSMissing.at(time) != LAPPDBG_PPSMissing.at(time) && ((LAPPDTS_PPSMissing.at(time) > -100 && LAPPDTS_PPSMissing.at(time) < 100) || (LAPPDBG_PPSMissing.at(time) > -100 && LAPPDBG_PPSMissing.at(time) < 100))) + if (LoadBuiltPPSInfo) { - cout << "LAPPDLoadStore: PPS missing number is not the same on BG and TS for LAPPD_ID " << LAPPD_ID << " at time " << time << ", BG: " << LAPPDBG_PPSMissing.at(time) << ", TS: " << LAPPDTS_PPSMissing.at(time) << endl; - cout << "LAPPDLoadStore: BG_PPSDiff: " << LAPPDBG_PPSDiff.at(time) << ", TS_PPSDiff: " << LAPPDTS_PPSDiff.at(time) << endl; + LAPPDLoadedBG_PPSBefore.push_back(LAPPDBG_PPSBefore.at(time)); + LAPPDLoadedBG_PPSAfter.push_back(LAPPDBG_PPSAfter.at(time)); + LAPPDLoadedBG_PPSDiff.push_back(LAPPDBG_PPSDiff.at(time)); + LAPPDLoadedBG_PPSMissing.push_back(LAPPDBG_PPSMissing.at(time)); + LAPPDLoadedTS_PPSBefore.push_back(LAPPDTS_PPSBefore.at(time)); + LAPPDLoadedTS_PPSAfter.push_back(LAPPDTS_PPSAfter.at(time)); + LAPPDLoadedTS_PPSDiff.push_back(LAPPDTS_PPSDiff.at(time)); + LAPPDLoadedTS_PPSMissing.push_back(LAPPDTS_PPSMissing.at(time)); + + if (LAPPDTS_PPSMissing.at(time) != LAPPDBG_PPSMissing.at(time) && ((LAPPDTS_PPSMissing.at(time) > -100 && LAPPDTS_PPSMissing.at(time) < 100) || (LAPPDBG_PPSMissing.at(time) > -100 && LAPPDBG_PPSMissing.at(time) < 100))) + { + cout << "LAPPDLoadStore: PPS missing number is not the same on BG and TS for LAPPD_ID " << LAPPD_ID << " at time " << time << ", BG: " << LAPPDBG_PPSMissing.at(time) << ", TS: " << LAPPDTS_PPSMissing.at(time) << endl; + cout << "LAPPDLoadStore: BG_PPSDiff: " << LAPPDBG_PPSDiff.at(time) << ", TS_PPSDiff: " << LAPPDTS_PPSDiff.at(time) << endl; + } } } NonEmptyEvents += 1; @@ -491,16 +501,17 @@ bool LAPPDLoadStore::Execute() m_data->Stores["ANNIEEvent"]->Set("LAPPDTSCorrection", LAPPDTSCorrection); m_data->Stores["ANNIEEvent"]->Set("LAPPDBGCorrection", LAPPDBGCorrection); m_data->Stores["ANNIEEvent"]->Set("LAPPDOSInMinusPS", LAPPDOSInMinusPS); - - m_data->Stores["ANNIEEvent"]->Set("LAPPDBG_PPSBefore", LAPPDBG_PPSBefore); - m_data->Stores["ANNIEEvent"]->Set("LAPPDBG_PPSAfter", LAPPDBG_PPSAfter); - m_data->Stores["ANNIEEvent"]->Set("LAPPDBG_PPSDiff", LAPPDBG_PPSDiff); - m_data->Stores["ANNIEEvent"]->Set("LAPPDBG_PPSMissing", LAPPDBG_PPSMissing); - m_data->Stores["ANNIEEvent"]->Set("LAPPDTS_PPSBefore", LAPPDTS_PPSBefore); - m_data->Stores["ANNIEEvent"]->Set("LAPPDTS_PPSAfter", LAPPDTS_PPSAfter); - m_data->Stores["ANNIEEvent"]->Set("LAPPDTS_PPSDiff", LAPPDTS_PPSDiff); - m_data->Stores["ANNIEEvent"]->Set("LAPPDTS_PPSMissing", LAPPDTS_PPSMissing); - + if (LoadBuiltPPSInfo) + { + m_data->Stores["ANNIEEvent"]->Set("LAPPDBG_PPSBefore", LAPPDBG_PPSBefore); + m_data->Stores["ANNIEEvent"]->Set("LAPPDBG_PPSAfter", LAPPDBG_PPSAfter); + m_data->Stores["ANNIEEvent"]->Set("LAPPDBG_PPSDiff", LAPPDBG_PPSDiff); + m_data->Stores["ANNIEEvent"]->Set("LAPPDBG_PPSMissing", LAPPDBG_PPSMissing); + m_data->Stores["ANNIEEvent"]->Set("LAPPDTS_PPSBefore", LAPPDTS_PPSBefore); + m_data->Stores["ANNIEEvent"]->Set("LAPPDTS_PPSAfter", LAPPDTS_PPSAfter); + m_data->Stores["ANNIEEvent"]->Set("LAPPDTS_PPSDiff", LAPPDTS_PPSDiff); + m_data->Stores["ANNIEEvent"]->Set("LAPPDTS_PPSMissing", LAPPDTS_PPSMissing); + } // TODO: save other timestamps, variables and metadata for later use if (eventNo % 100 == 0) diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.h b/UserTools/LAPPDLoadStore/LAPPDLoadStore.h index c3bb8c3be..4a89b3512 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.h +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.h @@ -26,7 +26,7 @@ class LAPPDLoadStore : public Tool { public: - LAPPDLoadStore(); ///< Simple constructor + LAPPDLoadStore(); ///< Simple constructor bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. bool Execute(); ///< Execute function used to perform Tool purpose. bool Finalise(); ///< Finalise function used to clean up resources. @@ -63,20 +63,20 @@ class LAPPDLoadStore : public Tool bool ReadStorePdeFile; bool MultiLAPPDMap; // loading map of multiple LAPPDs from ANNIEEvent bool loadOffsets; + bool LoadBuiltPPSInfo; // Variables that you need in the tool int retval; // track the data parsing and meta parsing status int eventNo; double CLOCK_to_NSEC; int errorEventsNumber; bool runInfoLoaded; - // LAPPD tool chain, control variables (Will be shared in multiple LAPPD tools to show the state of the tool chain in each loop) // Variables that you get from the config file - int stopEntries; // stop tool chain after loading this number of PSEC data events - int NonEmptyEvents; // count how many non empty data events were loaded + int stopEntries; // stop tool chain after loading this number of PSEC data events + int NonEmptyEvents; // count how many non empty data events were loaded int NonEmptyDataEvents; // count how many non empty data events were loaded - bool PsecReceiveMode; // Get PSEC data from CStore or Stores["ANNIEEvent"]. 1: CStore, 0: Stores["ANNIEEvent"] + bool PsecReceiveMode; // Get PSEC data from CStore or Stores["ANNIEEvent"]. 1: CStore, 0: Stores["ANNIEEvent"] string OutputWavLabel; string InputWavLabel; int NChannels; @@ -151,28 +151,24 @@ class LAPPDLoadStore : public Tool // data variables don't need to be cleared in each loop // these are loaded offset for event building - std::map> Offsets; // Loaded offset, use string = run number + sub run number + partfile number as key. - std::map> Offsets_minus_ps; // offset in ps, use offset - this/1e3 as the real offset - std::map> BGCorrections; // Loaded BGcorrections, same key as Offsets, but offset saved on event by event basis in that part file, in unit of ticks - std::map> TSCorrections; // TS corrections, in unit of ticks - std::map> BG_PPSBefore_loaded; // BG PPS before, in unit of ticks - std::map> BG_PPSAfter_loaded; // BG PPS after, in unit of ticks + std::map> Offsets; // Loaded offset, use string = run number + sub run number + partfile number as key. + std::map> Offsets_minus_ps; // offset in ps, use offset - this/1e3 as the real offset + std::map> BGCorrections; // Loaded BGcorrections, same key as Offsets, but offset saved on event by event basis in that part file, in unit of ticks + std::map> TSCorrections; // TS corrections, in unit of ticks + std::map> BG_PPSBefore_loaded; // BG PPS before, in unit of ticks + std::map> BG_PPSAfter_loaded; // BG PPS after, in unit of ticks std::map> BG_PPSDiff_loaded; // BG PPS Diff - std::map> BG_PPSMissing_loaded; // BG PPS Missing - std::map> TS_PPSBefore_loaded; // TS PPS before, in unit of ticks - std::map> TS_PPSAfter_loaded; // TS PPS after, in unit of ticks + std::map> BG_PPSMissing_loaded; // BG PPS Missing + std::map> TS_PPSBefore_loaded; // TS PPS before, in unit of ticks + std::map> TS_PPSAfter_loaded; // TS PPS after, in unit of ticks std::map> TS_PPSDiff_loaded; // TS PPS Diff - std::map> TS_PPSMissing_loaded; // TS PPS Missing - + std::map> TS_PPSMissing_loaded; // TS PPS Missing int runNumber; int subRunNumber; int partFileNumber; int eventNumberInPF; std::ofstream debugStoreReadIn; - - - }; #endif diff --git a/configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig b/configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig index c34f5e446..3828160fe 100644 --- a/configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig +++ b/configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig @@ -27,3 +27,4 @@ HasGenie 0 LAPPDData_fill 1 LAPPDReco_fill 1 RWMBRF_fill 1 +LAPPD_PPS_fill 1 diff --git a/configfiles/LAPPDProcessedAna/Configs b/configfiles/LAPPDProcessedAna/Configs index 0772b6901..95d3663c7 100644 --- a/configfiles/LAPPDProcessedAna/Configs +++ b/configfiles/LAPPDProcessedAna/Configs @@ -45,6 +45,7 @@ SelectedLAPPD 0 loadPSEC 1 loadPPS 0 loadOffsets 0 +LoadBuiltPPSInfo 1 num_vector_data 7795 num_vector_pps 16 From 8b0d021bdba65af4385a75661143215a73819389 Mon Sep 17 00:00:00 2001 From: Yue Date: Thu, 1 Aug 2024 14:07:09 -0500 Subject: [PATCH 078/163] Changes to be committed: modified: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp modified: UserTools/EBSaver/EBSaver.cpp modified: UserTools/FindMrdTracks/FindMrdTracks.cpp modified: configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig --- UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp | 2 +- UserTools/EBSaver/EBSaver.cpp | 9 +++++---- UserTools/FindMrdTracks/FindMrdTracks.cpp | 3 ++- .../LAPPDProcessedFilter/ProcessedLAPPDFilterConfig | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index b0a0746ca..1ff9ce46e 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -104,7 +104,7 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) fANNIETree->Branch("beam_VPTG2", &beam_VPTG2, "beam_VPTG2/D"); fANNIETree->Branch("beam_BTH2T2", &beam_BTH2T2, "beam_BTH2T2/D"); fANNIETree->Branch("BeamInfoTime", &fBeamInfoTime, "BeamInfoTime/l"); - fANNIETree->Branch("BeamInfoTimeToTriggerDiff", &fBeamInfoTimeToTriggerDiff, "BeamInfoTimeToTriggerDiff/G"); + fANNIETree->Branch("BeamInfoTimeToTriggerDiff", &fBeamInfoTimeToTriggerDiff, "BeamInfoTimeToTriggerDiff/L"); } if (RWMBRF_fill) diff --git a/UserTools/EBSaver/EBSaver.cpp b/UserTools/EBSaver/EBSaver.cpp index 11f2ce8ec..b07780d2c 100644 --- a/UserTools/EBSaver/EBSaver.cpp +++ b/UserTools/EBSaver/EBSaver.cpp @@ -1420,11 +1420,11 @@ bool EBSaver::SaveBeamInfo(uint64_t TriggerTime) { Log("EBSaver: Failed to find the closest beam info timestamp to trigger time", v_message, verbosityEBSaver); - uint64_t beamInfoTime = 0; + uint64_t beamInfoTime_long = 0; int64_t timeDiff = -9999; double defaultVal = -9999.; int beam_good = 0; - ANNIEEvent->Set("BeamInfoTime", beamInfoTime); + ANNIEEvent->Set("BeamInfoTime", beamInfoTime_long); ANNIEEvent->Set("BeamInfoTimeToTriggerDiff", timeDiff); ANNIEEvent->Set("beam_E_TOR860", defaultVal); ANNIEEvent->Set("beam_E_TOR875", defaultVal); @@ -1447,7 +1447,8 @@ bool EBSaver::SaveBeamInfo(uint64_t TriggerTime) // get the precise difference uint64_t beamInfoTime = BeamInfoTimestamps.at(minIndex); - int64_t timeDiff = (beamInfoTime > TriggerTime) ? beamInfoTime - TriggerTime : -static_cast(TriggerTime - beamInfoTime); + ULong64_t beamInfoTime_long = beamInfoTime * 1e6; + int64_t timeDiff = beamInfoTime_long - TriggerTime; // check if the map has the key E_TOR860 = E_TOR860_map.at(beamInfoTime); @@ -1462,7 +1463,7 @@ bool EBSaver::SaveBeamInfo(uint64_t TriggerTime) VPTG2 = VPTG2_map.at(beamInfoTime); BTH2T2 = BTH2T2_map.at(beamInfoTime); - ANNIEEvent->Set("BeamInfoTime", beamInfoTime * 1e6); + ANNIEEvent->Set("BeamInfoTime", beamInfoTime); ANNIEEvent->Set("BeamInfoTimeToTriggerDiff", timeDiff); ANNIEEvent->Set("beam_E_TOR860", E_TOR860); diff --git a/UserTools/FindMrdTracks/FindMrdTracks.cpp b/UserTools/FindMrdTracks/FindMrdTracks.cpp index bf344cafe..cad0d47ff 100755 --- a/UserTools/FindMrdTracks/FindMrdTracks.cpp +++ b/UserTools/FindMrdTracks/FindMrdTracks.cpp @@ -104,7 +104,8 @@ bool FindMrdTracks::Execute(){ get_ok = m_data->Stores.at("ANNIEEvent")->Get("MRDTriggerType",MRDTriggertype); if (not get_ok){ Log("FindMrdTracks: Did not find MRDTriggerType in ANNIEEvent. Please check the settings in MRDDataDecoder+BuildANNIEEvent/LoadWCSim?",v_error,verbosity); - m_data->vars.Set("StopLoop",1); + //m_data->vars.Set("StopLoop",1); + Log("FindMrdTracks tool was supposed to stop the loop, but will continue anyway",0,verbosity); } } Log("FindMrdTracks tool: MRDTriggertype is "+MRDTriggertype+" (from ANNIEEvent store)",v_debug,verbosity); diff --git a/configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig b/configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig index 5ed787c9c..242a2d558 100644 --- a/configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig +++ b/configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig @@ -1,7 +1,7 @@ FilterVerbosity 0 saveAllLAPPDEvents 1 -savePMTClusterEvents 1 +savePMTClusterEvents 0 filterType MRDtrack From dfe309c9855dd37aeda773b2f36fb235731c8ce0 Mon Sep 17 00:00:00 2001 From: Yue Date: Sat, 3 Aug 2024 17:36:17 -0500 Subject: [PATCH 079/163] Add LAPPD pulse half height timing and half end timing to tree Add LAPPD beamgate stop tick in 40 MHz clock information to tree Fixed a bug in LAPPDLoadStore. This bug will cause discrepancy between loading data that all have LAPPD info and data that only part have LAPPD info. It will refresh the ANNIEEvent booststore. Changes to be committed: modified: DataModel/LAPPDPulse.h modified: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp modified: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h modified: UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp modified: UserTools/LAPPDLoadStore/LAPPDLoadStore.h modified: UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp modified: UserTools/LAPPDThresReco/LAPPDThresReco.cpp modified: UserTools/LoadANNIEEvent/LoadANNIEEvent.cpp modified: configfiles/BeamClusterAnalysis/ToolsConfig modified: configfiles/LAPPDProcessedAna/ConfigStoreReadIn modified: configfiles/LAPPDProcessedAna/Configs --- DataModel/LAPPDPulse.h | 15 ++++ .../ANNIEEventTreeMaker.cpp | 67 ++++++++++++++--- .../ANNIEEventTreeMaker/ANNIEEventTreeMaker.h | 8 +++ UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp | 36 +++------- UserTools/LAPPDLoadStore/LAPPDLoadStore.h | 1 + .../LAPPDStoreReorder/LAPPDStoreReorder.cpp | 50 ++++++++++--- UserTools/LAPPDThresReco/LAPPDThresReco.cpp | 72 ++++++++++++++++++- UserTools/LoadANNIEEvent/LoadANNIEEvent.cpp | 4 +- configfiles/BeamClusterAnalysis/ToolsConfig | 3 - .../LAPPDProcessedAna/ConfigStoreReadIn | 1 - configfiles/LAPPDProcessedAna/Configs | 2 + 11 files changed, 205 insertions(+), 54 deletions(-) diff --git a/DataModel/LAPPDPulse.h b/DataModel/LAPPDPulse.h index e18dfcfa5..8aff68195 100755 --- a/DataModel/LAPPDPulse.h +++ b/DataModel/LAPPDPulse.h @@ -22,12 +22,20 @@ class LAPPDPulse : public Hit{ inline void SetChannelID(int channelid){ChannelID=channelid;} inline void SetPeak(double peak){Peak=peak;} inline void SetRange(double low, double hi){LowRange=low; HiRange=hi;} + inline void SetHalfHeightTime(double half){halfHeightTime=half;} + inline double GetHalfHeightTime(){return halfHeightTime;} + inline void SetHalfEndTime(double half){halfEndTime=half;} + inline double GetHalfEndTime(){return halfEndTime;} + inline void SetBaseline(double base){baseline=base;} + inline double GetBaseline(){return baseline;} bool Print() { cout<<"TubeId : "< void serialize(Archive & ar, const unsigned int version){ @@ -47,6 +59,9 @@ class LAPPDPulse : public Hit{ ar & Peak; ar & LowRange; ar & HiRange; + ar & halfHeightTime; + ar & halfEndTime; + ar & baseline; } } }; diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index 1ff9ce46e..6682187d3 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -181,16 +181,19 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) fANNIETree->Branch("LAPPD_TSCorrection", &fLAPPD_TSCorrection); fANNIETree->Branch("LAPPD_BGCorrection", &fLAPPD_BGCorrection); fANNIETree->Branch("LAPPD_OSInMinusPS", &fLAPPD_OSInMinusPS); - if(LAPPD_PPS_fill){ - fANNIETree->Branch("LAPPD_BGPPSBefore", &fLAPPD_BGPPSBefore); - fANNIETree->Branch("LAPPD_BGPPSAfter", &fLAPPD_BGPPSAfter); - fANNIETree->Branch("LAPPD_BGPPSDiff", &fLAPPD_BGPPSDiff); - fANNIETree->Branch("LAPPD_BGPPSMissing", &fLAPPD_BGPPSMissing); - fANNIETree->Branch("LAPPD_TSPPSBefore", &fLAPPD_TSPPSBefore); - fANNIETree->Branch("LAPPD_TSPPSAfter", &fLAPPD_TSPPSAfter); - fANNIETree->Branch("LAPPD_TSPPSDiff", &fLAPPD_TSPPSDiff); - fANNIETree->Branch("LAPPD_TSPPSMissing", &fLAPPD_TSPPSMissing); + if (LAPPD_PPS_fill) + { + fANNIETree->Branch("LAPPD_BGPPSBefore", &fLAPPD_BGPPSBefore); + fANNIETree->Branch("LAPPD_BGPPSAfter", &fLAPPD_BGPPSAfter); + fANNIETree->Branch("LAPPD_BGPPSDiff", &fLAPPD_BGPPSDiff); + fANNIETree->Branch("LAPPD_BGPPSMissing", &fLAPPD_BGPPSMissing); + fANNIETree->Branch("LAPPD_TSPPSBefore", &fLAPPD_TSPPSBefore); + fANNIETree->Branch("LAPPD_TSPPSAfter", &fLAPPD_TSPPSAfter); + fANNIETree->Branch("LAPPD_TSPPSDiff", &fLAPPD_TSPPSDiff); + fANNIETree->Branch("LAPPD_TSPPSMissing", &fLAPPD_TSPPSMissing); } + fANNIETree->Branch("LAPPD_BG_switchBit0", &fLAPPD_BG_switchBit0); + fANNIETree->Branch("LAPPD_BG_switchBit1", &fLAPPD_BG_switchBit1); } // LAPPD reconstruction information @@ -205,6 +208,7 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) fANNIETree->Branch("LAPPD_PulseIDs", &fLAPPD_IDs); fANNIETree->Branch("LAPPD_ChannelID", &fChannelID); fANNIETree->Branch("LAPPD_PeakTime", &fPulsePeakTime); + fANNIETree->Branch("LAPPD_PulseHalfHeightTime", &fPulseHalfHeightTime); fANNIETree->Branch("LAPPD_PeakAmp", &fPulsePeakAmp); fANNIETree->Branch("LAPPD_Charge", &fPulseCharge); fANNIETree->Branch("LAPPD_PulseStart", &fPulseStart); @@ -232,6 +236,10 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) fANNIETree->Branch("LAPPDHitP2PeakTime", &fLAPPDHitP2PeakTime); fANNIETree->Branch("LAPPDHitP1PeakAmp", &fLAPPDHitP1PeakAmp); fANNIETree->Branch("LAPPDHitP2PeakAmp", &fLAPPDHitP2PeakAmp); + fANNIETree->Branch("LAPPDHitP1HalfHeightTime", &fLAPPDHitP1HalfHeightTime); + fANNIETree->Branch("LAPPDHitP2HalfHeightTime", &fLAPPDHitP2HalfHeightTime); + fANNIETree->Branch("LAPPDHitP1HalfEndTime", &fLAPPDHitP1HalfEndTime); + fANNIETree->Branch("LAPPDHitP2HalfEndTime", &fLAPPDHitP2HalfEndTime); /* fANNIETree->Branch("LAPPDWaveformChankey", &LAPPDWaveformChankey, "LAPPDWaveformChankey/I"); @@ -633,6 +641,8 @@ void ANNIEEventTreeMaker::ResetVariables() fLAPPD_TSCorrection.clear(); fLAPPD_BGCorrection.clear(); fLAPPD_OSInMinusPS.clear(); + fLAPPD_BG_switchBit0.clear(); + fLAPPD_BG_switchBit1.clear(); // LAPPD_PPS_fill fLAPPD_BGPPSBefore.clear(); fLAPPD_BGPPSAfter.clear(); @@ -649,6 +659,7 @@ void ANNIEEventTreeMaker::ResetVariables() fLAPPD_IDs.clear(); fChannelID.clear(); fPulsePeakTime.clear(); + fPulseHalfHeightTime.clear(); fPulseCharge.clear(); fPulsePeakAmp.clear(); fPulseStart.clear(); @@ -675,6 +686,10 @@ void ANNIEEventTreeMaker::ResetVariables() fLAPPDHitP2PeakTime.clear(); fLAPPDHitP1PeakAmp.clear(); fLAPPDHitP2PeakAmp.clear(); + fLAPPDHitP1HalfHeightTime.clear(); + fLAPPDHitP2HalfHeightTime.clear(); + fLAPPDHitP1HalfEndTime.clear(); + fLAPPDHitP2HalfEndTime.clear(); LAPPDWaveformChankey.clear(); waveformMaxValue.clear(); @@ -900,6 +915,7 @@ void ANNIEEventTreeMaker::ResetVariables() LAPPDTSCorrection.clear(); LAPPDBGCorrection.clear(); LAPPDOSInMinusPS.clear(); + SwitchBitBG.clear(); // LAPPD_PPS_fill LAPPDBG_PPSBefore.clear(); LAPPDBG_PPSAfter.clear(); @@ -927,7 +943,15 @@ bool ANNIEEventTreeMaker::LoadEventInfo() m_data->Stores["ANNIEEvent"]->Get("RunNumber", fRunNumber); m_data->Stores["ANNIEEvent"]->Get("SubRunNumber", fSubrunNumber); m_data->Stores["ANNIEEvent"]->Get("PartNumber", fPartFileNumber); - m_data->Stores["ANNIEEvent"]->Get("EventNumber", fEventNumber); + bool gotEventNumber = m_data->Stores["ANNIEEvent"]->Get("EventNumber", fEventNumber); + if (!gotEventNumber) + { + uint32_t enm = 9998; + m_data->CStore.Get("EventNumberTree", enm); + cout << "ANNIEEventTreeMaker Tool: Not get the event number from ANNIEEvent, get from CStore: " << enm << endl; + fEventNumber = static_cast(enm); + } + m_data->Stores["ANNIEEvent"]->Get("PrimaryTriggerWord", fPrimaryTriggerWord); if (fPrimaryTriggerWord == 14) trigword = 5; @@ -1226,6 +1250,7 @@ void ANNIEEventTreeMaker::LoadLAPPDInfo() m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSAfter", LAPPDTS_PPSAfter); m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSDiff", LAPPDTS_PPSDiff); m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSMissing", LAPPDTS_PPSMissing); + m_data->Stores["ANNIEEvent"]->Get("SwitchBitBG", SwitchBitBG); if (LAPPDDataMap.size() != 0) { @@ -1264,6 +1289,18 @@ void ANNIEEventTreeMaker::FillLAPPDInfo() fLAPPD_TSPPSAfter.push_back(LAPPDTS_PPSAfter[key]); fLAPPD_TSPPSDiff.push_back(LAPPDTS_PPSDiff[key]); fLAPPD_TSPPSMissing.push_back(LAPPDTS_PPSMissing[key]); + // check if SwitchBitBG has the key + if (SwitchBitBG.find(psecData.LAPPD_ID) != SwitchBitBG.end()) + { + if(SwitchBitBG[psecData.LAPPD_ID].size() != 2) + { + cout<<"ANNIEEventTreeMaker: SwitchBitBG size is not 2, LAPPD_ID: "< fLAPPD_TSPPSAfter; vector fLAPPD_TSPPSDiff; vector fLAPPD_TSPPSMissing; + vector fLAPPD_BG_switchBit0; + vector fLAPPD_BG_switchBit1; // LAPPD Reco Fill vector fLAPPDPulseTimeStampUL; @@ -228,6 +230,7 @@ class ANNIEEventTreeMaker : public Tool vector fLAPPD_IDs; vector fChannelID; vector fPulsePeakTime; + vector fPulseHalfHeightTime; vector fPulseCharge; vector fPulsePeakAmp; vector fPulseStart; @@ -254,6 +257,10 @@ class ANNIEEventTreeMaker : public Tool vector fLAPPDHitP2PeakTime; vector fLAPPDHitP1PeakAmp; vector fLAPPDHitP2PeakAmp; + vector fLAPPDHitP1HalfHeightTime; + vector fLAPPDHitP2HalfHeightTime; + vector fLAPPDHitP1HalfEndTime; + vector fLAPPDHitP2HalfEndTime; // waveform vector LAPPDWaveformChankey; @@ -499,6 +506,7 @@ class ANNIEEventTreeMaker : public Tool std::map LAPPDTS_PPSAfter; std::map LAPPDTS_PPSDiff; std::map LAPPDTS_PPSMissing; + std::map> SwitchBitBG; std::map>> lappdPulses; std::map> lappdHits; diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp index c3fa44248..edd7ca0c5 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp @@ -43,6 +43,8 @@ bool LAPPDLoadStore::Initialise(std::string configfile, DataModel &data) m_variables.Get("loadOffsets", loadOffsets); LoadBuiltPPSInfo = true; m_variables.Get("LoadBuiltPPSInfo", LoadBuiltPPSInfo); + loadFromStoreDirectly = false; + m_variables.Get("loadFromStoreDirectly", loadFromStoreDirectly); // Control variables in this tool, initialized in this tool NonEmptyEvents = 0; NonEmptyDataEvents = 0; @@ -78,6 +80,7 @@ bool LAPPDLoadStore::Initialise(std::string configfile, DataModel &data) ReadStore = 0; // get data file + /* if (ReadStore == 1) { // get data from a StoreFile in ANNIEEvent format @@ -88,12 +91,12 @@ bool LAPPDLoadStore::Initialise(std::string configfile, DataModel &data) else if (ReadStore == 0) { // get data from previous chain, or m_data cout << "LAPPDStoreReadIn Using ANNIEevent or CStore" << endl; - } + }*/ // Grab all pedestal files and prepare the map channel|pedestal-vector for substraction if (DoPedSubtract == 1) { PedestalValues = new std::map>; - if (ReadStorePdeFile) + /*if (ReadStorePdeFile) { m_data->Stores["PedestalFile"] = new BoostStore(false, 2); bool ret = false; @@ -113,7 +116,7 @@ bool LAPPDLoadStore::Initialise(std::string configfile, DataModel &data) m_data->Stores["PedestalFile"]->Get("PedestalMap", PedestalValues); } } - else + else*/ { for (int i = 0; i < Nboards; i++) { @@ -186,7 +189,7 @@ bool LAPPDLoadStore::Execute() if (MultiLAPPDMap) { - bool gotDataStream = m_data->Stores.at("ANNIEEvent")->Get("DataStreams", DataStreams); + bool gotDataStream = m_data->Stores["ANNIEEvent"]->Get("DataStreams", DataStreams); bool getMap = m_data->Stores["ANNIEEvent"]->Get("LAPPDDataMap", LAPPDDataMap); if (getMap && DataStreams["LAPPD"] == true && LAPPDDataMap.size() > 0) { @@ -332,19 +335,6 @@ bool LAPPDLoadStore::Execute() // loop the map, for each PSEC data, do the same loading and parsing. // load the waveform by using LAPPD_ID * board_number * channel_number as the key - /* - the format saved in the processed data file of ANNIEEvent is: - std::map LAPPDDataMap; - std::map LAPPDBeamgate_ns; - std::map LAPPDTimeStamps_ns; // data and key are the same - std::map LAPPDTimeStampsRaw; - std::map LAPPDBeamgatesRaw; - std::map LAPPDOffsets; - std::map LAPPDTSCorrection; - std::map LAPPDBGCorrection; - std::map LAPPDOSInMinusPS; - */ - // data was already loaded in the LoadData() vector ReadedBoards; @@ -802,7 +792,8 @@ bool LAPPDLoadStore::LoadData() // so we need to loop the map to get all data and waveforms, using the LAPPD_ID, board number, channel number to form a global channel-waveform map // then loop all waveforms based on channel number - m_data->Stores["ANNIEEvent"]->GetEntry(eventNo); + if (loadFromStoreDirectly) + m_data->Stores["ANNIEEvent"]->GetEntry(eventNo); if (LAPPDStoreReadInVerbosity > 2) cout << "Got eventNo " << eventNo << endl; @@ -815,14 +806,6 @@ bool LAPPDLoadStore::LoadData() return false; } - // bool gotDataStream = m_data->Stores.at("ANNIEEvent")->Get("DataStreams", DataStreams); - // cout << "Inside, Got DataStreams = " << gotDataStream << ", "; - /*for (auto it = DataStreams.begin(); it != DataStreams.end(); ++it) - { - cout << "DataStream: " << it->first << " " << it->second << ", "; - } - cout << endl;*/ - // if (mergedEvent) // DataStreams["LAPPD"] = true; @@ -1575,7 +1558,6 @@ void LAPPDLoadStore::LoadOffsetsAndCorrections() BGCorrections[key][EventIndex] = static_cast(BGCorrection_tick) - 1000; TSCorrections[key][EventIndex] = static_cast(TSCorrection_tick) - 1000; - BG_PPSBefore_loaded[key][EventIndex] = BG_PPSBefore_tick; BG_PPSAfter_loaded[key][EventIndex] = BG_PPSAfter_tick; BG_PPSDiff_loaded[key][EventIndex] = BG_PPSDiff_tick; diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.h b/UserTools/LAPPDLoadStore/LAPPDLoadStore.h index 4a89b3512..3f0a91140 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.h +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.h @@ -64,6 +64,7 @@ class LAPPDLoadStore : public Tool bool MultiLAPPDMap; // loading map of multiple LAPPDs from ANNIEEvent bool loadOffsets; bool LoadBuiltPPSInfo; + bool loadFromStoreDirectly; // Variables that you need in the tool int retval; // track the data parsing and meta parsing status int eventNo; diff --git a/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp b/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp index c9dccae76..e89652e5b 100644 --- a/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp +++ b/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp @@ -96,6 +96,21 @@ bool LAPPDStoreReorder::DoReorder() cout << "pushed meta26 = " << meta26 << ", with value at " << (meta26 * NUM_VECTOR_METADATA) + 10 << " is " << acdcmetadata.at((meta26 * NUM_VECTOR_METADATA) + 10) << endl; } } + + vector Smeta_BG; + for (int meta_bg = 0; meta_bg < NReadBoards.size(); meta_bg++) + { + unsigned short metaBG = acdcmetadata.at((meta_bg * NUM_VECTOR_METADATA) + 67); + Smeta_BG.push_back((metaBG & 0x7)); + if (LAPPDReorderVerbosityLevel > 1) + { + cout << "Metaword entry " << meta_bg << " is " << Smeta_BG[meta_bg] << endl; + cout << "pushed meta_bg = " << meta_bg << ", with value at " << (meta_bg * NUM_VECTOR_METADATA) + 67 << " is " << acdcmetadata.at((meta_bg * NUM_VECTOR_METADATA) + 67) << endl; + } + } + + std::map> Smeta_BG_map; // key is id, value is the switch bit for beamgate + if (LAPPDReorderVerbosityLevel > 2) cout << "REORDER TIME!!!! " << acdcmetadata.size() << " " << acdcmetadata.at(10) << " " << acdcmetadata.at(102) << " lappd data size is " << lappddata.size() << ", reordereddata size is " << reordereddata.size() << endl; map>>::iterator itr; @@ -119,24 +134,33 @@ bool LAPPDStoreReorder::DoReorder() // Get the current board and the respective meta word int bi = (int)channelno / 30; int LAPPDID = static_cast((channelno % 1000) / 60); - // if (LoadLAPPDMap) - // { - int beginningBoardIDofThisLAPPDID = NReadBoards.at(std::distance(ACDCReadedLAPPDID.begin(), std::find(ACDCReadedLAPPDID.begin(), ACDCReadedLAPPDID.end(), LAPPDID))); - bi = beginningBoardIDofThisLAPPDID + bi % 2; - // }else{ - // bi = bi%2; - // } - if(LAPPDReorderVerbosityLevel>5) + // if (LoadLAPPDMap) + // { + int beginningBoardIDofThisLAPPDID = NReadBoards.at(std::distance(ACDCReadedLAPPDID.begin(), std::find(ACDCReadedLAPPDID.begin(), ACDCReadedLAPPDID.end(), LAPPDID))); + bi = beginningBoardIDofThisLAPPDID + bi % 2; + // }else{ + // bi = bi%2; + // } + if (LAPPDReorderVerbosityLevel > 5) { - //print the elements in NReadBoards, print LAPPDID; + // print the elements in NReadBoards, print LAPPDID; cout << "NReadBoards size is " << NReadBoards.size() << endl; - for(int i = 0; i < NReadBoards.size(); i++) + for (int i = 0; i < NReadBoards.size(); i++) { cout << "NReadBoards[" << i << "] = " << NReadBoards[i] << endl; } cout << "LAPPDID = " << LAPPDID << endl; } unsigned short switchword = Smeta26[std::distance(NReadBoards.begin(), std::find(NReadBoards.begin(), NReadBoards.end(), bi))]; + int switchBitBG = Smeta_BG[std::distance(NReadBoards.begin(), std::find(NReadBoards.begin(), NReadBoards.end(), bi))]; + + //check if key LAPPDID is already exist in Smeta_BG_map, if not, resize that vector to size 2 + if (Smeta_BG_map.find(LAPPDID) == Smeta_BG_map.end()) + { + Smeta_BG_map[LAPPDID] = vector(2); + } + Smeta_BG_map[LAPPDID][bi%2] = switchBitBG; + // Smeta26, 0 or 1, so switchword is the first timestmap or the second // Set the switchbit switchbit = (switchword & 0x7) * 32; @@ -185,6 +209,12 @@ bool LAPPDStoreReorder::DoReorder() cout << "LAPPDStoreReorder, reordered data size is " << reordereddata.size() << endl; } + m_data->Stores["ANNIEEvent"]->Set("SwitchBitBG", Smeta_BG_map); + if(LAPPDReorderVerbosityLevel>0) + { + cout << "LAPPDStoreReorder:: insert SwitchBitBG map size is " << Smeta_BG_map.size() << endl; + } + return true; } diff --git a/UserTools/LAPPDThresReco/LAPPDThresReco.cpp b/UserTools/LAPPDThresReco/LAPPDThresReco.cpp index 72cfa41d3..214d36ca8 100644 --- a/UserTools/LAPPDThresReco/LAPPDThresReco.cpp +++ b/UserTools/LAPPDThresReco/LAPPDThresReco.cpp @@ -263,7 +263,7 @@ void LAPPDThresReco::FillLAPPDPulse() if (LoadLAPPDMapInfo) LAPPD_ID = static_cast((channel - 1000) / 60); - //cout << "FillLAPPDPulse LAPPD_ID: " << LAPPD_ID << " channel: " << channel << endl; + // cout << "FillLAPPDPulse LAPPD_ID: " << LAPPD_ID << " channel: " << channel << endl; // for this channel, find the pulses vector pulses = FindPulses(wave, LAPPD_ID, channel); @@ -409,17 +409,87 @@ vector LAPPDThresReco::FindPulses(vector wave, int LAPPD_ID, if (pulseSize > minPulseWidth) { // if the pulse is long enough double peakBinGaus = GaussianFit(binNumbers, amplitudes); + // use a linear interpolation to find the half peak time, from wave.at(pulseStart) to wave.at(peakBin), divide each bin 0.1 ns to 100 parts, 1ps per bin,find the bin number that the amplitude is half of the peakAmp + double halfPeakBin = pulseStart; + if (pulseStart > 10) + halfPeakBin = pulseStart - 10; + else + halfPeakBin = 0; + double targetAmp = peakAmp / 2; + for (int j = halfPeakBin; j < peakBin + 1; j++) + { + if (wave.at(j + 1) > targetAmp) + { + halfPeakBin = j; + break; + } + } + int halfPeak_ps = 0; + for (int j = 1; j < 100; j++) + { + double interpAmp = wave.at(halfPeakBin) + (wave.at(halfPeakBin + 1) - wave.at(halfPeakBin)) * (j / 100.0); + if (interpAmp > targetAmp) + { + double prevInterAmp = wave.at(halfPeakBin) + (wave.at(halfPeakBin + 1) - wave.at(halfPeakBin)) * ((j - 1) / 100.0); + if (abs(interpAmp - targetAmp) < abs(prevInterAmp - targetAmp)) + { + halfPeak_ps = j; + break; + } + else + { + halfPeak_ps = j - 1; + break; + } + } + } + + //from the peak bin, find half end time + double halfEndBin = peakBin; + for (int j = peakBin; j < wave.size(); j++) + { + if (wave.at(j) < targetAmp) + { + halfEndBin = j; + break; + } + } + int halfEnd_ps = 0; + for(int j = 1; j < 100; j++) + { + double interpAmp = wave.at(halfEndBin) + (wave.at(halfEndBin + 1) - wave.at(halfEndBin)) * (j / 100.0); + if (interpAmp < targetAmp) + { + double prevInterAmp = wave.at(halfEndBin) + (wave.at(halfEndBin + 1) - wave.at(halfEndBin)) * ((j - 1) / 100.0); + if (abs(interpAmp - targetAmp) < abs(prevInterAmp - targetAmp)) + { + halfEnd_ps = j; + break; + } + else + { + halfEnd_ps = j - 1; + break; + } + } + } if (LAPPDThresRecoVerbosity > 1) cout << "inserting pulse on LAPPD ID =" << LAPPD_ID << " at time: " << peakBin * (25. / 256.) << "(" << peakBinGaus << ") with peakAmp: " << peakAmp << " from " << pulseStart << " to " << pulseStart + pulseSize << endl; if (useMaxTime) { LAPPDPulse thisPulse(LAPPD_ID, channel, peakBin * (25. / 256.), Q, peakAmp, pulseStart, pulseStart + pulseSize); + thisPulse.SetHalfHeightTime(halfPeakBin * (25. / 256.) + halfPeak_ps * 0.001 * 25 / 25.6); + thisPulse.SetHalfEndTime(halfEndBin * (25. / 256.) + halfEnd_ps * 0.001 * 25 / 25.6); + thisPulse.SetBaseline(0); pulses.push_back(thisPulse); } else { LAPPDPulse thisPulse(LAPPD_ID, channel, peakBinGaus * (25. / 256.), Q, peakAmp, pulseStart, pulseStart + pulseSize); + thisPulse.SetHalfHeightTime(halfPeakBin * (25. / 256.) + halfPeak_ps * 0.001 * 25 / 25.6); + thisPulse.SetHalfEndTime(halfEndBin * (25. / 256.) + halfEnd_ps * 0.001 * 25 / 25.6); + thisPulse.SetBaseline(0); pulses.push_back(thisPulse); } // tube ID: LAPPD_ID diff --git a/UserTools/LoadANNIEEvent/LoadANNIEEvent.cpp b/UserTools/LoadANNIEEvent/LoadANNIEEvent.cpp index 9fdcc1668..a2b4537b3 100644 --- a/UserTools/LoadANNIEEvent/LoadANNIEEvent.cpp +++ b/UserTools/LoadANNIEEvent/LoadANNIEEvent.cpp @@ -293,7 +293,9 @@ bool LoadANNIEEvent::Execute() { - if (global_evnr && !has_local){ m_data->Stores["ANNIEEvent"]->Set("EventNumber",global_ev); } + if (global_evnr && !has_local){ m_data->Stores["ANNIEEvent"]->Set("EventNumber",global_ev); + m_data->CStore.Set("EventNumberTree",global_ev); + } global_ev++; if ( current_entry_ >= total_entries_in_file_ ) { diff --git a/configfiles/BeamClusterAnalysis/ToolsConfig b/configfiles/BeamClusterAnalysis/ToolsConfig index 4436c2036..b147e1080 100644 --- a/configfiles/BeamClusterAnalysis/ToolsConfig +++ b/configfiles/BeamClusterAnalysis/ToolsConfig @@ -1,7 +1,5 @@ myLoadANNIEEvent LoadANNIEEvent ./configfiles/BeamClusterAnalysis/LoadANNIEEventConfig myLoadGeometry LoadGeometry ./configfiles/LoadGeometry/LoadGeometryConfig -#myPhaseIIADCCalibrator PhaseIIADCCalibrator ./configfiles/BeamClusterAnalysis/PhaseIIADCCalibratorConfig -#myPhaseIIADCHitFinder PhaseIIADCHitFinder ./configfiles/BeamClusterAnalysis/PhaseIIADCHitFinderConfig myTimeClustering TimeClustering configfiles/BeamClusterAnalysis/TimeClusteringConfig myFindMrdTracks FindMrdTracks configfiles/BeamClusterAnalysis/FindMrdTracksConfig myClusterFinder ClusterFinder ./configfiles/BeamClusterAnalysis/ClusterFinderConfig @@ -17,4 +15,3 @@ LAPPDThresReco LAPPDThresReco configfiles/LAPPDProcessedAna/ConfigPlot FitRWMWaveform FitRWMWaveform ./configfiles/BeamClusterAnalysis/FitRWMWaveformConfig ANNIEEventTreeMaker ANNIEEventTreeMaker ./configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig -#myPhaseIITreeMaker PhaseIITreeMaker ./configfiles/BeamClusterAnalysis/PhaseIITreeMakerConfig diff --git a/configfiles/LAPPDProcessedAna/ConfigStoreReadIn b/configfiles/LAPPDProcessedAna/ConfigStoreReadIn index c6f5ddf1c..79f2d2fa7 100755 --- a/configfiles/LAPPDProcessedAna/ConfigStoreReadIn +++ b/configfiles/LAPPDProcessedAna/ConfigStoreReadIn @@ -28,7 +28,6 @@ Pedinputfile2 ../Pedestals/PEDS_ACDC_board1.txt #LAPPDReorderData LAPPDReorderVerbosityLevel 0 -ReorderVerbosityLevel 0 ReorderInputWavLabel RawLAPPDData ReorderOutputWavLabel LAPPDWaveforms DelayOffset 0 diff --git a/configfiles/LAPPDProcessedAna/Configs b/configfiles/LAPPDProcessedAna/Configs index 95d3663c7..0fa484e4b 100644 --- a/configfiles/LAPPDProcessedAna/Configs +++ b/configfiles/LAPPDProcessedAna/Configs @@ -24,6 +24,8 @@ Nboards 6 #Number of pedestal files to be read in PedinputfileTXT ../Pedestals/LAPPD645839/P PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 +ReadStorePdeFile 0 +loadFromStoreDirectly 0 Pedinputfile1 ../Pedestals/PEDS_ACDC_board0.txt Pedinputfile2 ../Pedestals/PEDS_ACDC_board1.txt From 7ad3dfe68f1b87bd3b9d1934d7e9cd1fa3bb35a0 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Mon, 5 Aug 2024 08:08:43 -0500 Subject: [PATCH 080/163] Update ClusterFinderConfig Adjusted clustering --> min 10 hits in 40ns --- configfiles/BeamClusterAnalysis/ClusterFinderConfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configfiles/BeamClusterAnalysis/ClusterFinderConfig b/configfiles/BeamClusterAnalysis/ClusterFinderConfig index c13622045..c25b028f1 100644 --- a/configfiles/BeamClusterAnalysis/ClusterFinderConfig +++ b/configfiles/BeamClusterAnalysis/ClusterFinderConfig @@ -3,10 +3,10 @@ verbosity 0 HitStore Hits #Either MCHits or Hits (accessed in ANNIEEvent store) OutputFile BeamRun_ClusterFinder_DefaultOutput #Output root prefix name for the current run -ClusterFindingWindow 50 # in ns, size of the window used to "clusterize" +ClusterFindingWindow 40 # in ns, size of the window used to "clusterize" AcqTimeWindow 70000 # in ns, size of the acquisition window -ClusterIntegrationWindow 50 # in ns, all hits with +/- 1/2 of this window are considered in the cluster -MinHitsPerCluster 5 # group of hits are considered clusters above this amount of hits +ClusterIntegrationWindow 40 # in ns, all hits with +/- 1/2 of this window are considered in the cluster +MinHitsPerCluster 10 # group of hits are considered clusters above this amount of hits end_of_window_time_cut 0.95 # from o to 1, length of the window you want to loop over with respect to acq. window (1 for full window, 0.95 for 95% from the start) Plots2D 0 #Draw 2D charge-vs-time plots? ChankeyToPMTIDMap ./configfiles/EventDisplay/Data-RecoEvent/Chankey_WCSimID.dat From ae30e57c3bc2e417554b0e3e4580c75da6164f72 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Mon, 5 Aug 2024 09:38:07 -0500 Subject: [PATCH 081/163] Update ANNIEEventTreeMakerConfig added .ntuple extension --- configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig b/configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig index 3828160fe..aa9484302 100644 --- a/configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig +++ b/configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig @@ -8,7 +8,7 @@ cluster_TankHitInfo_fill 1 TankReco_fill 0 -OutputFile ANNIETree.root +OutputFile ANNIETree.ntuple.root TankClusterProcessing 1 MRDClusterProcessing 1 TriggerProcessing 1 From 7ed190d0c3c8c458dcfbceaea91654ed7eb7793d Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Mon, 5 Aug 2024 13:51:25 -0500 Subject: [PATCH 082/163] Create config.py python script that will generate the ANNIEEventTreeMaker config file on the grid --- configfiles/BeamClusterAnalysis/config.py | 39 +++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 configfiles/BeamClusterAnalysis/config.py diff --git a/configfiles/BeamClusterAnalysis/config.py b/configfiles/BeamClusterAnalysis/config.py new file mode 100644 index 000000000..258a04a7e --- /dev/null +++ b/configfiles/BeamClusterAnalysis/config.py @@ -0,0 +1,39 @@ +import sys + +run = sys.argv[1] +pi = sys.argv[2] +pf = sys.argv[3] + +file = open('ANNIEEventTreeMakerConfig', "w") + +file.write('ANNIEEventTreeMakerVerbosity 0\n') +file.write('\n') +file.write('fillAllTriggers 1\n') +file.write('fill_singleTrigger 0\n') +file.write('fillLAPPDEventsOnly 0\n') +file.write('TankCluster_fill 1\n') +file.write('cluster_TankHitInfo_fill 1\n' +file.write('\n') +file.write('OutputFile BeamCluster_' + str(run) + '_' + str(pi) + '_' + str(pf) + '.ntuple.root\n') +file.write('TankClusterProcessing 1\n') +file.write('MRDClusterProcessing 1\n') +file.write('TriggerProcessing 1\n') +file.write('TankHitInfo_fill 1\n') +file.write('MRDHitInfo_fill 1\n') +file.write('MRDReco_fill 1\n') +file.write('SiPMPulseInfo_fill 0\n') +file.write('fillCleanEventsOnly 0\n') +file.write('MCTruth_fill 0\n') +file.write('Reco_fill 1\n') +file.write('TankReco_fill 0\n') +file.write('RecoDebug_fill 0\n') +file.write('muonTruthRecoDiff_fill 0\n') +file.write('IsData 1\n') +file.write('HasGenie 0') +file.write('\n') +file.write('LAPPDData_fill 1\n') +file.write('LAPPDReco_fill 1\n') +file.write('RWMBRF_fill 1\n') +file.write('LAPPD_PPS_fill 1\n') + +file.close() From 2098168765d6e2cb1ef50e1f39ac47c8288604db Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Tue, 6 Aug 2024 12:29:26 -0500 Subject: [PATCH 083/163] Update CreateMyList.sh --- configfiles/PreProcessTrigOverlap/CreateMyList.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configfiles/PreProcessTrigOverlap/CreateMyList.sh b/configfiles/PreProcessTrigOverlap/CreateMyList.sh index 04e1aa7a5..4ccfef7cc 100644 --- a/configfiles/PreProcessTrigOverlap/CreateMyList.sh +++ b/configfiles/PreProcessTrigOverlap/CreateMyList.sh @@ -1,4 +1,4 @@ -if [ "$#" -ne 2 ]; then +if [ "$#" -ne 1 ]; then echo "Usage: ./CreateMyList.sh RUN" echo "Specified input variable must contain the run number" exit 1 @@ -7,9 +7,9 @@ fi RUN=$1 DIR=/pnfs/annie/persistent/raw/raw/ -NUMFILES=$(ls -1q ${FILEDIR}/RAWDataR${RUN}* | wc -l) +NUMFILES=$(ls -1q ${DIR}${RUN}/RAWDataR${RUN}* | wc -l) -echo "NUMBER OF FILES IN ${FILEDIR}: ${NUMFILES}" +echo "NUMBER OF FILES IN ${DIR}${RUN}: ${NUMFILES}" rm my_files.txt From fb30cece77f659ab49531e67b29ff82da0264998 Mon Sep 17 00:00:00 2001 From: Yue Date: Tue, 6 Aug 2024 12:37:49 -0500 Subject: [PATCH 084/163] Fix a bug in threshold reco for pulse time finding, now it's find correct start and end and won't give error Fix a bug in the filter for if the AuxHit was empty Add 0 as default offset value for PMT 416, which is considered as dead but may give data some time Changes to be committed: modified: UserTools/LAPPDThresReco/LAPPDThresReco.cpp modified: UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp modified: configfiles/LoadGeometry/TankPMTTimingOffsets.csv --- UserTools/LAPPDThresReco/LAPPDThresReco.cpp | 58 +++++++++++-------- .../ProcessedLAPPDFilter.cpp | 21 ++++++- .../LoadGeometry/TankPMTTimingOffsets.csv | 1 + 3 files changed, 54 insertions(+), 26 deletions(-) diff --git a/UserTools/LAPPDThresReco/LAPPDThresReco.cpp b/UserTools/LAPPDThresReco/LAPPDThresReco.cpp index 214d36ca8..c8cc454e7 100644 --- a/UserTools/LAPPDThresReco/LAPPDThresReco.cpp +++ b/UserTools/LAPPDThresReco/LAPPDThresReco.cpp @@ -180,16 +180,16 @@ bool LAPPDThresReco::Execute() // get the input LAPPD Data waveform; m_data->Stores["ANNIEEvent"]->Get(ThresRecoInputWaveLabel, lappdData); - if (LAPPDThresRecoVerbosity > 0) + if (LAPPDThresRecoVerbosity > 1) cout << "Start WaveformMaximaFinding" << endl; WaveformMaximaFinding(); // find the maxima of the waveforms - if (LAPPDThresRecoVerbosity > 0) + if (LAPPDThresRecoVerbosity > 1) cout << "Start FillLAPPDPulse" << endl; FillLAPPDPulse(); // find pulses - if (LAPPDThresRecoVerbosity > 0) + if (LAPPDThresRecoVerbosity > 1) cout << "Start FillLAPPDHit" << endl; FillLAPPDHit(); // find hits - if (LAPPDThresRecoVerbosity > 0) + if (LAPPDThresRecoVerbosity > 1) cout << "Reco Finished, start filling" << endl; m_data->Stores["ANNIEEvent"]->Set(ThresRecoOutputPulseLabel, lappdPulses); @@ -201,7 +201,7 @@ bool LAPPDThresReco::Execute() m_data->Stores["ANNIEEvent"]->Set("waveformMaxTimeBin", waveformMaxTimeBin); eventNumber++; // operation in this loop finished, increase the event number - if (LAPPDThresRecoVerbosity > 0) + if (LAPPDThresRecoVerbosity > 1) cout << "Filling finished, printing to txt" << endl; if (printHitsTXT) PrintHitsToTXT(); // print hits to a txt file @@ -299,7 +299,7 @@ void LAPPDThresReco::FillLAPPDHit() lappdHits[stripno] = lHits; numberOfHits += lHits.size(); } - if (LAPPDThresRecoVerbosity > 0) + if (LAPPDThresRecoVerbosity > 1) cout << "LAPPDThresReco found hits: " << numberOfHits << endl; } @@ -335,7 +335,7 @@ void LAPPDThresReco::PrintMRDinfoToTXT() int fNumClusterTracks = 0; for (int i = 0; i < (int)MrdTimeClusters.size(); i++) fNumClusterTracks += this->LoadMRDTrackReco(i); - if (LAPPDThresRecoVerbosity > 0) + if (LAPPDThresRecoVerbosity > 1) cout << "LAPPDThresReco found MRD tracks: " << fNumClusterTracks << endl; for (int i = 0; i < fMRDTrackAngle.size(); i++) { @@ -371,7 +371,7 @@ vector LAPPDThresReco::FindPulses(vector wave, int LAPPD_ID, vector binNumbers; vector amplitudes; - for (int i = 0; i < wave.size(); i++) + for (int i = 1; i < wave.size(); i++) { currentSig = wave.at(i); if (wave.at(i) > threshold) @@ -379,7 +379,7 @@ vector LAPPDThresReco::FindPulses(vector wave, int LAPPD_ID, if (!inPulse) { inPulse = true; - pulseStart = i; + pulseStart = i - 1; pulseSize = 1; peakBin = i; peakAmp = currentSig; @@ -410,21 +410,27 @@ vector LAPPDThresReco::FindPulses(vector wave, int LAPPD_ID, { // if the pulse is long enough double peakBinGaus = GaussianFit(binNumbers, amplitudes); // use a linear interpolation to find the half peak time, from wave.at(pulseStart) to wave.at(peakBin), divide each bin 0.1 ns to 100 parts, 1ps per bin,find the bin number that the amplitude is half of the peakAmp - double halfPeakBin = pulseStart; + double startBin = pulseStart; if (pulseStart > 10) - halfPeakBin = pulseStart - 10; + startBin = pulseStart - 10; else - halfPeakBin = 0; + startBin = 1; double targetAmp = peakAmp / 2; - for (int j = halfPeakBin; j < peakBin + 1; j++) + int stopBin = wave.size() - 1; + if (peakBin < wave.size() - 1) + stopBin = peakBin; + + double halfPeakBin = startBin; + for (int j = startBin; j < stopBin; j++) { - if (wave.at(j + 1) > targetAmp) + halfPeakBin = j - 1; + if (wave.at(j) > targetAmp) { - halfPeakBin = j; break; } } int halfPeak_ps = 0; + double halfHeightAmp = 0; for (int j = 1; j < 100; j++) { double interpAmp = wave.at(halfPeakBin) + (wave.at(halfPeakBin + 1) - wave.at(halfPeakBin)) * (j / 100.0); @@ -434,28 +440,32 @@ vector LAPPDThresReco::FindPulses(vector wave, int LAPPD_ID, if (abs(interpAmp - targetAmp) < abs(prevInterAmp - targetAmp)) { halfPeak_ps = j; + halfHeightAmp = interpAmp; break; } else { halfPeak_ps = j - 1; + halfHeightAmp = prevInterAmp; break; } } } + if (LAPPDThresRecoVerbosity > 0) + cout << "LAPPDThresReco: thres: " << threshold << " thres Start: " << pulseStart << " pulseStart Amp: " << wave.at(pulseStart) << " halfPeakBin: " << halfPeakBin << " halfPeakBin Amp: " << wave.at(halfPeakBin) << " peakBin: " << peakBin << " peakBin Amp: " << wave.at(peakBin) << " half height time: " << (halfPeakBin * (25. / 256.) + halfPeak_ps * 0.001 * 25 / 25.6) << " halfHeightAmp: " << halfHeightAmp << endl; - //from the peak bin, find half end time + // from the peak bin, find half end time double halfEndBin = peakBin; - for (int j = peakBin; j < wave.size(); j++) + for (int j = peakBin; j < wave.size() - 1; j++) { + halfEndBin = j - 1; if (wave.at(j) < targetAmp) { - halfEndBin = j; break; } } int halfEnd_ps = 0; - for(int j = 1; j < 100; j++) + for (int j = 1; j < 100; j++) { double interpAmp = wave.at(halfEndBin) + (wave.at(halfEndBin + 1) - wave.at(halfEndBin)) * (j / 100.0); if (interpAmp < targetAmp) @@ -621,7 +631,7 @@ LAPPDHit LAPPDThresReco::MakeHit(LAPPDPulse pulse0, LAPPDPulse pulse1) double averageAmp = (pulse1.GetPeak() + pulse0.GetPeak()) / 2; double averageQ = (pulse1.GetCharge() + pulse0.GetCharge()) / 2; - if (LAPPDThresRecoVerbosity > 0) + if (LAPPDThresRecoVerbosity > 1) { cout << "Making Hit: " << endl; cout << "Pulse0: " << endl; @@ -640,7 +650,7 @@ LAPPDHit LAPPDThresReco::MakeHit(LAPPDPulse pulse0, LAPPDPulse pulse1) int stripno1 = chan1->GetStripNum(); if (stripno0 != stripno1) { - if (LAPPDThresRecoVerbosity > 0) + if (LAPPDThresRecoVerbosity > 1) cout << "Error: the two pulses are not on the same strip!" << endl; LAPPDHit hit; return hit; @@ -656,7 +666,7 @@ LAPPDHit LAPPDThresReco::MakeHit(LAPPDPulse pulse0, LAPPDPulse pulse1) double transversePos = LAPPDEdgeWidth + stripWidth * (stripno0); // use the center position of the strip in mm - if (LAPPDThresRecoVerbosity > 0) + if (LAPPDThresRecoVerbosity > 1) { cout << "making hit from pulse0 on channel " << pulse0.GetChannelID() << ", strip " << stripno0 << endl; cout << "making hit from pulse1 on channel " << pulse1.GetChannelID() << ", strip " << stripno1 << endl; @@ -675,7 +685,7 @@ LAPPDHit LAPPDThresReco::MakeHit(LAPPDPulse pulse0, LAPPDPulse pulse1) double arrivalTime = t0 - (t0 - t1 + 1) * 0.5; - if (LAPPDThresRecoVerbosity > 0) + if (LAPPDThresRecoVerbosity > 1) cout << "Position on LAPPD: " << parallelPos << " " << transversePos << endl; vector positionOnLAPPD = {parallelPos, transversePos}; @@ -692,7 +702,7 @@ LAPPDHit LAPPDThresReco::MakeHit(LAPPDPulse pulse0, LAPPDPulse pulse1) double pulse1StartTime = pulse0.GetLowRange(); double pulse2StartTime = pulse1.GetLowRange(); // print tubeID - if (LAPPDThresRecoVerbosity > 0) + if (LAPPDThresRecoVerbosity > 1) { cout << "TubeID: " << tubeID << endl; cout << "average charge is " << averageQ << ", q/amplitude is " << averageQ / averageAmp << endl; diff --git a/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp index c782f598e..180fd9951 100644 --- a/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp +++ b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp @@ -289,8 +289,25 @@ bool ProcessedLAPPDFilter::GotANNIEEventAndSave(BoostStore *BS, string savePath) std::map> *HitsOriginal = nullptr; m_data->Stores["ANNIEEvent"]->Get("AuxHits", AuxHitsOriginal); m_data->Stores["ANNIEEvent"]->Get("Hits", HitsOriginal); - auto AuxHitsCopy = new std::map>(*AuxHitsOriginal); - auto HitsCopy = new std::map>(*HitsOriginal); + + std::map> *AuxHitsCopy = nullptr; + if (!m_data->Stores["ANNIEEvent"]->Get("AuxHits", AuxHitsOriginal) ) + { + std::cerr << "Warning: Could not retrieve AuxHits from ANNIEEvent or AuxHitsOriginal is nullptr. Creating empty AuxHits map." << std::endl; + AuxHitsCopy = new std::map>(); + }else{ + AuxHitsCopy = new std::map>(*AuxHitsOriginal); + } + std::map> *HitsCopy = nullptr; + if (!m_data->Stores["ANNIEEvent"]->Get("Hits", HitsOriginal)) + { + std::cerr << "Warning: Could not retrieve Hits from ANNIEEvent or HitsOriginal is nullptr. Creating empty Hits map." << std::endl; + HitsCopy = new std::map>(); + }else{ + HitsCopy = new std::map>(*HitsOriginal); + } + + BS->Set("AuxHits", AuxHitsCopy); BS->Set("Hits", HitsCopy); diff --git a/configfiles/LoadGeometry/TankPMTTimingOffsets.csv b/configfiles/LoadGeometry/TankPMTTimingOffsets.csv index cdfed43c9..3aca644cb 100644 --- a/configfiles/LoadGeometry/TankPMTTimingOffsets.csv +++ b/configfiles/LoadGeometry/TankPMTTimingOffsets.csv @@ -74,6 +74,7 @@ 413,Barrel,4.1,1.27,ok 414,Barrel,16.84,1.32,ok 415,Barrel,12.67,0.97,ok +416,Barrel,0,0,unreliable 417,Barrel,7.98,1.45,ok 418,Barrel,7.96,2.28,unreliable 419,Barrel,17.9,1.92,ok From 7357cc2024516ca86eddc7c17abf1078630a5cc5 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Tue, 6 Aug 2024 14:54:56 -0500 Subject: [PATCH 085/163] Update config.py --- configfiles/BeamClusterAnalysis/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configfiles/BeamClusterAnalysis/config.py b/configfiles/BeamClusterAnalysis/config.py index 258a04a7e..503d6c38c 100644 --- a/configfiles/BeamClusterAnalysis/config.py +++ b/configfiles/BeamClusterAnalysis/config.py @@ -12,7 +12,7 @@ file.write('fill_singleTrigger 0\n') file.write('fillLAPPDEventsOnly 0\n') file.write('TankCluster_fill 1\n') -file.write('cluster_TankHitInfo_fill 1\n' +file.write('cluster_TankHitInfo_fill 1\n') file.write('\n') file.write('OutputFile BeamCluster_' + str(run) + '_' + str(pi) + '_' + str(pf) + '.ntuple.root\n') file.write('TankClusterProcessing 1\n') From 9a74e79d588fda7bec3fd94579150668407e0492 Mon Sep 17 00:00:00 2001 From: Yue Date: Wed, 7 Aug 2024 19:27:06 -0500 Subject: [PATCH 086/163] For beam data ~2022 and 2023 with LAPPD 40, some time the data waveform is empty but the error code is 0, so the LAPPDLoadStore won't exit and will give error. Fixed. Add pulse charge analysis for tree maker, fix the name in root tree Changes to be committed: modified: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp modified: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h modified: UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp --- UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp | 7 +++++++ UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h | 2 ++ UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp | 5 +++++ 3 files changed, 14 insertions(+) diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index 6682187d3..6c8baca75 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -240,6 +240,8 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) fANNIETree->Branch("LAPPDHitP2HalfHeightTime", &fLAPPDHitP2HalfHeightTime); fANNIETree->Branch("LAPPDHitP1HalfEndTime", &fLAPPDHitP1HalfEndTime); fANNIETree->Branch("LAPPDHitP2HalfEndTime", &fLAPPDHitP2HalfEndTime); + fANNIETree->Branch("LAPPDHitP1Charge", &fLAPPDHitP1Charge); + fANNIETree->Branch("LAPPDHitP2Charge", &fLAPPDHitP2Charge); /* fANNIETree->Branch("LAPPDWaveformChankey", &LAPPDWaveformChankey, "LAPPDWaveformChankey/I"); @@ -690,6 +692,8 @@ void ANNIEEventTreeMaker::ResetVariables() fLAPPDHitP2HalfHeightTime.clear(); fLAPPDHitP1HalfEndTime.clear(); fLAPPDHitP2HalfEndTime.clear(); + fLAPPDHitP1Charge.clear(); + fLAPPDHitP2Charge.clear(); LAPPDWaveformChankey.clear(); waveformMaxValue.clear(); @@ -1400,6 +1404,9 @@ void ANNIEEventTreeMaker::FillLAPPDHit() fLAPPDHitP1HalfEndTime.push_back(p1.GetHalfEndTime()); fLAPPDHitP2HalfEndTime.push_back(p2.GetHalfEndTime()); + + fLAPPDHitP1Charge.push_back(p1.GetCharge()); + fLAPPDHitP2Charge.push_back(p2.GetCharge()); } } } diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h index 34756c54d..6df847a17 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h @@ -261,6 +261,8 @@ class ANNIEEventTreeMaker : public Tool vector fLAPPDHitP2HalfHeightTime; vector fLAPPDHitP1HalfEndTime; vector fLAPPDHitP2HalfEndTime; + vector fLAPPDHitP1Charge; + vector fLAPPDHitP2Charge; // waveform vector LAPPDWaveformChankey; diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp index edd7ca0c5..18b8b301f 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp @@ -870,6 +870,11 @@ bool LAPPDLoadStore::LoadData() } ReadBoards = dat.BoardIndex; Raw_buffer = dat.RawWaveform; + if(Raw_buffer.size() == 0 || ReadBoards.size() == 0) + { + cout << "LAPPD Load Store, find Raw buffer size == 0 or ReadBoards size == 0" << endl; + return false; + } LAPPD_ID = dat.LAPPD_ID; if (LAPPD_ID != SelectedLAPPD && SelectSingleLAPPD) return false; From 82c16e5cbd4cd5bd15463b856bf709bb0bd8d950 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Thu, 8 Aug 2024 15:22:13 -0500 Subject: [PATCH 087/163] Update ClusterFinderConfig --- configfiles/BeamClusterAnalysis/ClusterFinderConfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configfiles/BeamClusterAnalysis/ClusterFinderConfig b/configfiles/BeamClusterAnalysis/ClusterFinderConfig index c25b028f1..53330c25d 100644 --- a/configfiles/BeamClusterAnalysis/ClusterFinderConfig +++ b/configfiles/BeamClusterAnalysis/ClusterFinderConfig @@ -6,7 +6,7 @@ OutputFile BeamRun_ClusterFinder_DefaultOutput #Output root prefix name for the ClusterFindingWindow 40 # in ns, size of the window used to "clusterize" AcqTimeWindow 70000 # in ns, size of the acquisition window ClusterIntegrationWindow 40 # in ns, all hits with +/- 1/2 of this window are considered in the cluster -MinHitsPerCluster 10 # group of hits are considered clusters above this amount of hits +MinHitsPerCluster 5 # group of hits are considered clusters above this amount of hits end_of_window_time_cut 0.95 # from o to 1, length of the window you want to loop over with respect to acq. window (1 for full window, 0.95 for 95% from the start) Plots2D 0 #Draw 2D charge-vs-time plots? ChankeyToPMTIDMap ./configfiles/EventDisplay/Data-RecoEvent/Chankey_WCSimID.dat From cddddcd78e734e02a9782fc1449a7681674f64fa Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Fri, 9 Aug 2024 08:40:24 -0500 Subject: [PATCH 088/163] Update Configs Change Pedestal path --- configfiles/LAPPDProcessedAna/Configs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configfiles/LAPPDProcessedAna/Configs b/configfiles/LAPPDProcessedAna/Configs index 0fa484e4b..417fdf52f 100644 --- a/configfiles/LAPPDProcessedAna/Configs +++ b/configfiles/LAPPDProcessedAna/Configs @@ -21,7 +21,7 @@ stopEntries 10000000000 DoPedSubtraction 1 Nboards 6 #Number of pedestal files to be read in -PedinputfileTXT ../Pedestals/LAPPD645839/P +PedinputfileTXT ./Pedestals/LAPPD645839/P PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 ReadStorePdeFile 0 From 62c4eaed00c98afbf2dfdd4178a9032cc0df3765 Mon Sep 17 00:00:00 2001 From: Yue Date: Wed, 14 Aug 2024 19:48:22 -0500 Subject: [PATCH 089/163] Add modifications to include the LAPPD40 us level drift. The drift was calculated in the offsetFit script and loaded in the LAPPDLoadStore as a part of the offset Changes to be committed: modified: UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp modified: offsetFit_MultipleLAPPD.cpp --- UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp | 9 ++- offsetFit_MultipleLAPPD.cpp | 83 ++++++++++++++++----- 2 files changed, 70 insertions(+), 22 deletions(-) diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp index 18b8b301f..92edebf4d 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp @@ -1513,6 +1513,8 @@ void LAPPDLoadStore::LoadOffsetsAndCorrections() ULong64_t TS_PPSAfter_tick; ULong64_t TS_PPSDiff_tick; ULong64_t TS_PPSMissing_tick; + ULong64_t TS_driftCorrection_ns; + ULong64_t BG_driftCorrection_ns; tree->SetBranchAddress("runNumber", &runNumber); tree->SetBranchAddress("subRunNumber", &subRunNumber); @@ -1531,6 +1533,9 @@ void LAPPDLoadStore::LoadOffsetsAndCorrections() tree->SetBranchAddress("TS_PPSAfter_tick", &TS_PPSAfter_tick); tree->SetBranchAddress("TS_PPSDiff_tick", &TS_PPSDiff_tick); tree->SetBranchAddress("TS_PPSMissing_tick", &TS_PPSMissing_tick); + tree->SetBranchAddress("TS_driftCorrection_ns", &TS_driftCorrection_ns); + tree->SetBranchAddress("BG_driftCorrection_ns", &BG_driftCorrection_ns); + Long64_t nentries = tree->GetEntries(); cout << "LAPPDStoreReadIn Loading offsets and corrections, total entries: " << nentries << endl; @@ -1558,7 +1563,7 @@ void LAPPDLoadStore::LoadOffsetsAndCorrections() } // Now using EventIndex to place each event correctly - Offsets[key][EventIndex] = final_offset_ns_0; + Offsets[key][EventIndex] = final_offset_ns_0 + TS_driftCorrection_ns; Offsets_minus_ps[key][EventIndex] = static_cast(final_offset_ps_negative_0); BGCorrections[key][EventIndex] = static_cast(BGCorrection_tick) - 1000; TSCorrections[key][EventIndex] = static_cast(TSCorrection_tick) - 1000; @@ -1575,7 +1580,7 @@ void LAPPDLoadStore::LoadOffsetsAndCorrections() if (nentries > 10 && i % (static_cast(nentries / 10)) == 0) { cout << "LAPPDStoreReadIn Loading offsets and corrections, " << i << " entries loaded" << endl; - cout << "Printing key: " << key << ", EventIndex: " << EventIndex << ", final_offset_ns_0: " << final_offset_ns_0 << ", final_offset_ps_negative_0: " << final_offset_ps_negative_0 << ", BGCorrection_tick: " << BGCorrection_tick << ", TSCorrection_tick: " << TSCorrection_tick << ", BG_PPSMissing_tick: " << BG_PPSMissing_tick << ", TS_PPSMissing_tick: " << TS_PPSMissing_tick << endl; + cout << "Printing key: " << key << ", EventIndex: " << EventIndex << ", final_offset_ns_0: " << final_offset_ns_0 << ", final_offset_ps_negative_0: " << final_offset_ps_negative_0 << ", BGCorrection_tick: " << BGCorrection_tick << ", TSCorrection_tick: " << TSCorrection_tick << ", BG_PPSMissing_tick: " << BG_PPSMissing_tick << ", TS_PPSMissing_tick: " << TS_PPSMissing_tick << ", TS_driftCorrection_ns: " << TS_driftCorrection_ns << ", BG_driftCorrection_ns: " << BG_driftCorrection_ns << endl; } } diff --git a/offsetFit_MultipleLAPPD.cpp b/offsetFit_MultipleLAPPD.cpp index 3c5932981..769023467 100644 --- a/offsetFit_MultipleLAPPD.cpp +++ b/offsetFit_MultipleLAPPD.cpp @@ -56,7 +56,7 @@ vector> fitInThisReset( cout << "LAPPD_PPS size: " << LAPPD_PPS.size() << endl; cout << "CTCTrigger size: " << CTCTrigger.size() << endl; cout << "CTCPPS size: " << CTCPPS.size() << endl; - cout << "PPSDeltaT: " << PPSDeltaT << endl; + cout << "PPSDeltaT: " << PPSDeltaT << endl; // in ps // for this input PPS, fit an offset // return the offset and other information in order // precedure: @@ -70,12 +70,20 @@ vector> fitInThisReset( { double diff = static_cast(LAPPD_PPS[i] - LAPPD_PPS[i - 1]); + cout<> fitInThisReset( for (int i = 0; i < PPSInterval_ACDC.size(); i++) { // only fill the drift histogram if there is a drift > 2 microseconds - if (PPSInterval_ACDC[i] / 1000 / 1000 > 2) + cout<<"PPSInterval_ACDC["< 2) { - h->Fill(PPSInterval_ACDC[i] / 1000 / 1000); // fill in microseconds - // cout << "Fill histogram: PPSInterval_ACDC[" << i << "]: " << PPSInterval_ACDC[i] / 1000 / 1000 << endl; + h->Fill(PPSInterval_ACDC[i]); // fill in microseconds + cout << "Fill histogram: PPSInterval_ACDC[" << i << "]: " << PPSInterval_ACDC[i] << endl; } } @@ -124,9 +133,12 @@ vector> fitInThisReset( } else { - double driftScaling = LAPPD_PPS_ns / trueInterval / 1000; + double LAPPD_PPS_ns_dd = static_cast(LAPPD_PPS_ns); + double driftScaling = LAPPD_PPS_ns_dd / (trueInterval / 1000); ULong64_t totalDriftedClock = static_cast(drift * driftScaling / 1000); offsetNow_ns = CTCPPS.at(j) - (LAPPD_PPS_ns + totalDriftedClock); + if (i < 3 && j < 3) + cout<<"totalDriftedClock in ns = "<> fitInThisReset( ULong64_t driftCorrectionForTS = 0; if (drift != 0) { - double driftScaling = TS_ns / trueInterval / 1000; + double TS_ns_dd = static_cast(TS_ns); + double driftScaling = TS_ns_dd / (trueInterval / 1000); driftCorrectionForTS = static_cast(drift * driftScaling / 1000); + if(lappdb<3 && i<3 && j<3) + cout<> fitInThisReset( { ULong64_t LAPPD_PPS_ns = LAPPD_PPS.at(final_i) / 1000; ULong64_t LAPPD_PPS_truncated_ps = LAPPD_PPS.at(final_i) % 1000; - double driftScaling = LAPPD_PPS_ns / trueInterval / 1000; // this is the same drift scaling as in the matching loop + double driftScaling = static_cast(LAPPD_PPS_ns) / (trueInterval / 1000); // this is the same drift scaling as in the matching loop ULong64_t totalDriftedClock = static_cast(drift * driftScaling / 1000); + cout<> fitInThisReset( vector TS_PPSDiff; vector TS_PPSMiss; + vector TS_driftCorrection_ns; + vector BG_driftCorrection_ns; + // calculate the missing ticks for each LAPPD PPS PPS_tick_correction.push_back(0); LAPPD_PPS_missing_ticks.push_back(0); @@ -490,13 +511,17 @@ vector> fitInThisReset( ULong64_t driftCorrectionForBG = 0; if (drift != 0) { - double driftScaling = TS_ns / trueInterval / 1000; - driftCorrectionForTS = static_cast(drift * driftScaling / 1000); - double driftScalingBG = BG_ns / trueInterval / 1000; - driftCorrectionForBG = static_cast(drift * driftScalingBG / 1000); + + double driftScaling = static_cast(TS_ns) / (trueInterval / 1000); + driftCorrectionForTS = static_cast(drift/ 1000 * driftScaling ); + double driftScalingBG = static_cast(BG_ns) / (trueInterval / 1000); + driftCorrectionForBG = static_cast(drift/ 1000 * driftScalingBG ); + cout<<"drift = "<Branch("subRunNumber", &subRunNumber_out, "subRunNumber/I"); tOut->Branch("partFileNumber", &partFileNumber_out, "partFileNumber/I"); @@ -1128,6 +1162,8 @@ void offsetFit_MultipleLAPPD(string fileName, int fitTargetTriggerWord, bool tri tOut->Branch("final_offset_ns_1", &final_offset_ns_1, "final_offset_ns_1/l"); tOut->Branch("final_offset_ps_negative_0", &final_offset_ps_negative_0, "final_offset_ps_negative_0/l"); tOut->Branch("final_offset_ps_negative_1", &final_offset_ps_negative_1, "final_offset_ps_negative_1/l"); + tOut->Branch("drift0", &drift0, "drift0/D"); + tOut->Branch("drift1", &drift1, "drift1/D"); tOut->Branch("gotOrphanCount_0", &gotOrphanCount_0, "gotOrphanCount_0/l"); tOut->Branch("gotOrphanCount_1", &gotOrphanCount_1, "gotOrphanCount_1/l"); tOut->Branch("gotMin_mean_dev_noOrphan_0", &gotMin_mean_dev_noOrphan_0, "gotMin_mean_dev_noOrphan_0/l"); @@ -1158,6 +1194,9 @@ void offsetFit_MultipleLAPPD(string fileName, int fitTargetTriggerWord, bool tri tOut->Branch("TS_PPSAfter_tick", &TS_PPSAfter_tick, "TS_PPSAfter_tick/l"); tOut->Branch("TS_PPSDiff_tick", &TS_PPSDiff_tick, "TS_PPSDiff_tick/l"); tOut->Branch("TS_PPSMissing_tick", &TS_PPSMissing_tick, "TS_PPSMissing_tick/l"); + tOut->Branch("TS_driftCorrection_ns", &TS_driftCorrection_ns, "TS_driftCorrection_ns/l"); + tOut->Branch("BG_driftCorrection_ns", &BG_driftCorrection_ns, "BG_driftCorrection_ns/l"); + std::ofstream outputEvents("outputEvents.txt"); for (auto it = ResultMap.begin(); it != ResultMap.end(); it++) { @@ -1172,18 +1211,20 @@ void offsetFit_MultipleLAPPD(string fileName, int fitTargetTriggerWord, bool tri partFileNumber_out = std::stoi(key.substr(key.find("_", key.find("_") + 1) + 1, key.find("_", key.find("_", key.find("_") + 1) + 1) - key.find("_", key.find("_") + 1) - 1)); LAPPD_ID_out = std::stoi(key.substr(key.find("_", key.find("_", key.find("_") + 1) + 1) + 1, key.size() - key.find("_", key.find("_", key.find("_") + 1) + 1) - 1)); final_offset_ns_0 = Result[0][0]; - final_offset_ns_1 = Result[22][0]; + final_offset_ns_1 = Result[24][0]; final_offset_ps_negative_0 = Result[0][1]; - final_offset_ps_negative_1 = Result[22][1]; + final_offset_ps_negative_1 = Result[24][1]; gotOrphanCount_0 = Result[0][2]; - gotOrphanCount_1 = Result[22][2]; + gotOrphanCount_1 = Result[24][2]; gotMin_mean_dev_noOrphan_0 = Result[0][3]; - gotMin_mean_dev_noOrphan_1 = Result[22][3]; + gotMin_mean_dev_noOrphan_1 = Result[24][3]; increament_times_0 = Result[0][4]; - increament_times_1 = Result[22][4]; + increament_times_1 = Result[24][4]; min_mean_dev_0 = Result[0][5]; - min_mean_dev_1 = Result[22][5]; + min_mean_dev_1 = Result[24][5]; EventNumberInThisPartFile = Result[0][8]; + drift0 = Result[0][9]; + drift1 = Result[24][9]; // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 // vector> Result = {FitInfo, TimeStampRaw, BeamGateRaw, TimeStamp_ns, BeamGate_ns, TimeStamp_ps, BeamGate_ps, EventIndex, EventDeviation_ns, CTCTriggerIndex, CTCTriggerTimeStamp_ns, BeamGate_correction_tick, TimeStamp_correction_tick, LAPPD_PPS_interval_ticks, BG_PPSBefore, BG_PPSAfter, BG_PPSDiff, BG_PPSMiss, TS_PPSBefore, TS_PPSAfter, TS_PPSDiff, TS_PPSMiss}; @@ -1193,7 +1234,7 @@ void offsetFit_MultipleLAPPD(string fileName, int fitTargetTriggerWord, bool tri long long BGTdiff = Result[4][j] - Result[10][j] - 325250; // cout<<"BGTDiff: "<Fill(); } outputOffset << runNumber_out << "\t" << subRunNumber_out << "\t" << partFileNumber_out << "\t" << 0 << "\t" << LAPPD_ID_out << "\t" << final_offset_ns_0 << "\t" << final_offset_ns_1 << "\t" << final_offset_ps_negative_0 << "\t" << final_offset_ps_negative_1 << "\t" << gotOrphanCount_0 << "\t" << gotOrphanCount_1 << "\t" << EventNumberInThisPartFile << "\t" << gotMin_mean_dev_noOrphan_0 << "\t" << gotMin_mean_dev_noOrphan_1 << "\t" << increament_times_0 << "\t" << increament_times_1 << "\t" << min_mean_dev_0 << "\t" << min_mean_dev_1 << std::endl; From cd65f89b3dda379398dca504313e8983c88d2105 Mon Sep 17 00:00:00 2001 From: Yue Date: Thu, 15 Aug 2024 09:29:18 -0500 Subject: [PATCH 090/163] Add LAPPDLoadTXT to load ASCII data with other LAPPD Tools. Add LAPPDASCIIAna for ASCII analysis with new tools. Most of the config files were copied from LAPPDProcessedAna Changes to be committed: modified: UserTools/Factory/Factory.cpp new file: UserTools/LAPPDLoadTXT/LAPPDLoadTXT.cpp new file: UserTools/LAPPDLoadTXT/LAPPDLoadTXT.h new file: UserTools/LAPPDLoadTXT/README.md modified: UserTools/LAPPDPlots/LAPPDPlots.cpp modified: UserTools/Unity.h new file: configfiles/LAPPDASCIIAna/ConfigGeo new file: configfiles/LAPPDASCIIAna/ConfigPlot new file: configfiles/LAPPDASCIIAna/ConfigPreProcess new file: configfiles/LAPPDASCIIAna/ConfigStoreReadIn new file: configfiles/LAPPDASCIIAna/ConfigTXT new file: configfiles/LAPPDASCIIAna/Configs new file: configfiles/LAPPDASCIIAna/FindMrdTracksConfig new file: configfiles/LAPPDASCIIAna/LoadANNIEEventConfig new file: configfiles/LAPPDASCIIAna/ProcessedLAPPDFilterConfig new file: configfiles/LAPPDASCIIAna/TimeClusteringConfig new file: configfiles/LAPPDASCIIAna/ToolChainConfig new file: configfiles/LAPPDASCIIAna/ToolsConfig new file: configfiles/LAPPDASCIIAna/knownlist --- UserTools/Factory/Factory.cpp | 1 + UserTools/LAPPDLoadTXT/LAPPDLoadTXT.cpp | 264 ++++++++++++++++++ UserTools/LAPPDLoadTXT/LAPPDLoadTXT.h | 67 +++++ UserTools/LAPPDLoadTXT/README.md | 20 ++ UserTools/LAPPDPlots/LAPPDPlots.cpp | 4 +- UserTools/Unity.h | 1 + configfiles/LAPPDASCIIAna/ConfigGeo | 11 + configfiles/LAPPDASCIIAna/ConfigPlot | 139 +++++++++ configfiles/LAPPDASCIIAna/ConfigPreProcess | 65 +++++ configfiles/LAPPDASCIIAna/ConfigStoreReadIn | 42 +++ configfiles/LAPPDASCIIAna/ConfigTXT | 84 ++++++ configfiles/LAPPDASCIIAna/Configs | 74 +++++ configfiles/LAPPDASCIIAna/FindMrdTracksConfig | 12 + .../LAPPDASCIIAna/LoadANNIEEventConfig | 6 + .../LAPPDASCIIAna/ProcessedLAPPDFilterConfig | 1 + .../LAPPDASCIIAna/TimeClusteringConfig | 13 + configfiles/LAPPDASCIIAna/ToolChainConfig | 24 ++ configfiles/LAPPDASCIIAna/ToolsConfig | 14 + configfiles/LAPPDASCIIAna/knownlist | 1 + 19 files changed, 842 insertions(+), 1 deletion(-) create mode 100644 UserTools/LAPPDLoadTXT/LAPPDLoadTXT.cpp create mode 100644 UserTools/LAPPDLoadTXT/LAPPDLoadTXT.h create mode 100644 UserTools/LAPPDLoadTXT/README.md create mode 100644 configfiles/LAPPDASCIIAna/ConfigGeo create mode 100755 configfiles/LAPPDASCIIAna/ConfigPlot create mode 100755 configfiles/LAPPDASCIIAna/ConfigPreProcess create mode 100755 configfiles/LAPPDASCIIAna/ConfigStoreReadIn create mode 100644 configfiles/LAPPDASCIIAna/ConfigTXT create mode 100644 configfiles/LAPPDASCIIAna/Configs create mode 100644 configfiles/LAPPDASCIIAna/FindMrdTracksConfig create mode 100644 configfiles/LAPPDASCIIAna/LoadANNIEEventConfig create mode 100644 configfiles/LAPPDASCIIAna/ProcessedLAPPDFilterConfig create mode 100644 configfiles/LAPPDASCIIAna/TimeClusteringConfig create mode 100644 configfiles/LAPPDASCIIAna/ToolChainConfig create mode 100644 configfiles/LAPPDASCIIAna/ToolsConfig create mode 100644 configfiles/LAPPDASCIIAna/knownlist diff --git a/UserTools/Factory/Factory.cpp b/UserTools/Factory/Factory.cpp index cd4bd1685..82b0c3a3f 100644 --- a/UserTools/Factory/Factory.cpp +++ b/UserTools/Factory/Factory.cpp @@ -184,5 +184,6 @@ if (tool=="ANNIEEventTreeMaker") ret=new ANNIEEventTreeMaker; if (tool=="ProcessedLAPPDFilter") ret=new ProcessedLAPPDFilter; if (tool=="BeamQuality") ret=new BeamQuality; if (tool=="FitRWMWaveform") ret=new FitRWMWaveform; +if (tool=="LAPPDLoadTXT") ret=new LAPPDLoadTXT; return ret; } diff --git a/UserTools/LAPPDLoadTXT/LAPPDLoadTXT.cpp b/UserTools/LAPPDLoadTXT/LAPPDLoadTXT.cpp new file mode 100644 index 000000000..aa2a51c14 --- /dev/null +++ b/UserTools/LAPPDLoadTXT/LAPPDLoadTXT.cpp @@ -0,0 +1,264 @@ +#include "LAPPDLoadTXT.h" + +LAPPDLoadTXT::LAPPDLoadTXT() : Tool() {} + +bool LAPPDLoadTXT::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + LAPPDLoadTXTVerbosity = 0; + m_variables.Get("LAPPDLoadTXTVerbosity", LAPPDLoadTXTVerbosity); + + PedFileNameTXT = "../Pedestals/TXTPdedestals/P"; + m_variables.Get("PedFileNameTXT", PedFileNameTXT); + + NBoards = 2; + m_variables.Get("NBoards", NBoards); + + OutputWavLabel = "RawLAPPDData"; + m_variables.Get("OutputWavLabel", OutputWavLabel); + + DoPedSubtract = true; + m_variables.Get("DoPedSubtract", DoPedSubtract); + + if (DoPedSubtract) + { + PedestalValues = new std::map>; + for (int i = 0; i < NBoards; i++) + { + Log("LAPPDLoadTXT: Loading " + std::to_string(NBoards) + "Pedestal file from " + PedFileNameTXT, 0, LAPPDLoadTXTVerbosity); + ReadPedestal(i); + } + Log("LAPPDLoadTXT: Pedestal file loaded", 0, LAPPDLoadTXTVerbosity); + } + + Nsamples = 256; + m_variables.Get("Nsamples", Nsamples); + NChannels = 30; + m_variables.Get("NChannels", NChannels); + TrigChannel = 5; + m_variables.Get("TrigChannel", TrigChannel); + LAPPDchannelOffset = 1000; + m_variables.Get("LAPPDchannelOffset", LAPPDchannelOffset); + SampleSize = 80; + m_variables.Get("SampleSize", SampleSize); + + m_data->Stores["ANNIEEvent"]->Set("Nsamples", Nsamples); + m_data->Stores["ANNIEEvent"]->Set("NChannels", NChannels); + m_data->Stores["ANNIEEvent"]->Set("TrigChannel", TrigChannel); + m_data->Stores["ANNIEEvent"]->Set("LAPPDchannelOffset", LAPPDchannelOffset); + m_data->Stores["ANNIEEvent"]->Set("SampleSize", SampleSize); + + m_variables.Get("DataFileName", DataFileName); + DataFile.open(DataFileName); + if (!DataFile.is_open()) + { + cout << "LAPPDLoadTXT: Failed to open " << DataFileName << "!" << endl; + return false; + } + + eventNo = 0; + + oldLaser = 0; + m_variables.Get("oldLaser", oldLaser); + + return true; +} + +bool LAPPDLoadTXT::Execute() +{ + Log("LAPPDLoadTXT: Reading data file", v_message, LAPPDLoadTXTVerbosity); + bool isFiltered = false; + m_data->Stores["ANNIEEvent"]->Set("isFiltered", isFiltered); + bool isBLsub = false; + m_data->Stores["ANNIEEvent"]->Set("isBLsubtracted", isBLsub); + bool isCFD = false; + m_data->Stores["ANNIEEvent"]->Set("isCFD", isCFD); + + LAPPDWaveforms = new std::map>>; + + if (eventNo % 50 == 0) + Log("LAPPDLoadTXT: Event " + std::to_string(eventNo), v_message, LAPPDLoadTXTVerbosity); + + // alwasys set LAPPDana to true because we are loading ASCII data, every loop mush has data + bool LAPPDana = true; + m_data->CStore.Set("LAPPDana", LAPPDana); + + ReadData(); + + vector NReadBoards = {0, 1}; + m_data->Stores["ANNIEEvent"]->Set("ACDCboards", NReadBoards); + m_data->Stores["ANNIEEvent"]->Set("SortedBoards", NReadBoards); + + vector ACDCReadedLAPPDID = {0, 0}; + m_data->Stores["ANNIEEvent"]->Set("ACDCReadedLAPPDID", ACDCReadedLAPPDID); + + int LAPPD_ID = 0; + m_data->Stores["ANNIEEvent"]->Set("oldLaser", oldLaser); + m_data->Stores["ANNIEEvent"]->Set("LAPPD_ID", LAPPD_ID); + m_data->Stores["ANNIEEvent"]->Set("TrigChannel", TrigChannel); + m_data->Stores["ANNIEEvent"]->Set("LAPPDchannelOffset", LAPPDchannelOffset); + m_data->Stores["ANNIEEvent"]->Set("SampleSize", SampleSize); + + m_data->Stores["ANNIEEvent"]->Set(OutputWavLabel, LAPPDWaveforms); + m_data->Stores["ANNIEEvent"]->Set("ACDCmetadata", metaData); + LAPPDWaveforms->clear(); + metaData.clear(); + eventNo++; + + return true; +} + +bool LAPPDLoadTXT::Finalise() +{ + DataFile.close(); + Log("LAPPDLoadTXT: Data file closed", v_message, LAPPDLoadTXTVerbosity); + + return true; +} + +bool LAPPDLoadTXT::ReadPedestal(int boardNo) +{ + // copied fomr LAPPDLoadStore + + if (LAPPDLoadTXTVerbosity > 0) + cout << "Getting Pedestals " << boardNo << endl; + + std::string LoadName = PedFileNameTXT; + string nextLine; // temp line to parse + double finalsampleNo; + std::string ext = std::to_string(boardNo); + ext += ".txt"; + LoadName += ext; + ifstream PedFile; + PedFile.open(LoadName); // final name: PedFileNameTXT + boardNo + .txt + if (!PedFile.is_open()) + { + cout << "Failed to open " << LoadName << "!" << endl; + return false; + } + if (LAPPDLoadTXTVerbosity > 0) + cout << "Opened pedestal file: " << LoadName << endl; + + int sampleNo = 0; // sample number + while (getline(PedFile, nextLine)) + { + istringstream iss(nextLine); // copies the current line in the file + int location = -1; // counts the current perameter in the line + string stempValue; // current string in the line + int tempValue; // current int in the line + unsigned long channelNo = boardNo * 30; // channel number + // cout<<"NEW BOARD "<> stempValue) + { + location++; + tempValue = stoi(stempValue, 0, 10); + if (sampleNo == 0) + { + vector tempPed; + tempPed.push_back(tempValue); + PedestalValues->insert(pair>(channelNo, tempPed)); + if (LAPPDLoadTXTVerbosity > 0) + cout << "Inserting pedestal at channelNo " << channelNo << endl; + } + else + { + (((PedestalValues->find(channelNo))->second)).push_back(tempValue); + } + + channelNo++; + } + sampleNo++; + } + if (LAPPDLoadTXTVerbosity > 0) + cout << "FINAL SAMPLE NUMBER: " << PedestalValues->size() << " " << (((PedestalValues->find(0))->second)).size() << endl; + PedFile.close(); + return true; +} + +void LAPPDLoadTXT::ReadData() +{ + string nextLine; // temp line to parse + + map>>::iterator itr; + + int lineNumber = 0; + while (getline(DataFile, nextLine)) + { + int sampleNo = 0; // sample number + unsigned long channelNo = 0; // channel number + istringstream iss(nextLine); // copies the current line in the file + int location = -1; // counts the current perameter in the line + string stempValue; // current string in the line + int tempValue; // current int in the line + + while (iss >> stempValue) + { + location++; + if (location == 0) + { + sampleNo = stoi(stempValue, 0, 10); + Log("LAPPDLoadTXT: at sampleNo " + std::to_string(sampleNo) + " at line " + std::to_string(lineNumber), 5, LAPPDLoadTXTVerbosity); + continue; + } + Log("LAPPDLoadTXT: Parsing 30 channels for sample " + std::to_string(sampleNo) + " at location " + std::to_string(location), 10, LAPPDLoadTXTVerbosity); + + if (location % 31 == 0) + { + metaDataString.push_back(stempValue); + // convert string stempValue to unsigned short + unsigned short tempMeta = (unsigned short)stoi(stempValue, 0, 16); + metaData.push_back(tempMeta); + continue; + } + + int tempValue = stoi(stempValue, 0, 10); + + int theped; + map>::iterator pitr; + if ((PedestalValues->count(channelNo)) > 0) + { + pitr = PedestalValues->find(channelNo); + theped = (pitr->second).at(sampleNo); + } + else + { + theped = 0; + } + + int pedsubValue = tempValue - theped; + if(LAPPDLoadTXTVerbosity>11) + cout<<"LAPPDLoadTXT: data value: "< tempwav; + tempwav.PushSample(0.3 * ((double)pedsubValue)); // what is 0.3? + vector> Vtempwav; + Vtempwav.push_back(tempwav); + LAPPDWaveforms->insert(pair>>(channelNo, Vtempwav)); + Log("LAPPDLoadTXT: Inserting waveform at channel " + std::to_string(channelNo), 5, LAPPDLoadTXTVerbosity); + } + else + { + (((LAPPDWaveforms->find(channelNo))->second).at(0)).PushSample(0.3 * ((double)pedsubValue)); + } + + channelNo++; + } + lineNumber++; + if (sampleNo == 255) + { + Log("LAPPDLoadTXT: Event " + std::to_string(eventNo) + " loaded", v_message, LAPPDLoadTXTVerbosity); + break; + } + } +} diff --git a/UserTools/LAPPDLoadTXT/LAPPDLoadTXT.h b/UserTools/LAPPDLoadTXT/LAPPDLoadTXT.h new file mode 100644 index 000000000..fdf838617 --- /dev/null +++ b/UserTools/LAPPDLoadTXT/LAPPDLoadTXT.h @@ -0,0 +1,67 @@ +#ifndef LAPPDLoadTXT_H +#define LAPPDLoadTXT_H + +#include +#include + +#include "Tool.h" + +#include +#include +#include +#include "Tool.h" + +/** + * \class LAPPDLoadTXT + * + * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. + * + * $Author: B.Richards $ + * $Date: 2019/05/28 10:44:00 $ + * Contact: b.richards@qmul.ac.uk + */ +class LAPPDLoadTXT : public Tool +{ + +public: + LAPPDLoadTXT(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + bool ReadPedestal(int boardNo); ///< Read in the Pedestal Files + void ReadData(); + +private: + int LAPPDLoadTXTVerbosity; + int v_message = 1; + int v_warning = 2; + int v_error = 3; + int v_debug = 4; + + string PedFileNameTXT; + int NBoards; + string DataFileName; + + ifstream DataFile; + + std::map> *PedestalValues; + std::map>> *LAPPDWaveforms; + vector metaData; + vector metaDataString; + + int DoPedSubtract; + + string OutputWavLabel; + + int eventNo; + + int NChannels; + int Nsamples; + int TrigChannel; + double SampleSize; + int LAPPDchannelOffset; + + int oldLaser; +}; + +#endif diff --git a/UserTools/LAPPDLoadTXT/README.md b/UserTools/LAPPDLoadTXT/README.md new file mode 100644 index 000000000..42ba05ec1 --- /dev/null +++ b/UserTools/LAPPDLoadTXT/README.md @@ -0,0 +1,20 @@ +# LAPPDLoadTXT + +LAPPDLoadTXT + +## Data + +Describe any data formats LAPPDLoadTXT creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for LAPPDLoadTXT. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/LAPPDPlots/LAPPDPlots.cpp b/UserTools/LAPPDPlots/LAPPDPlots.cpp index 6bd7d81fb..63341fcee 100644 --- a/UserTools/LAPPDPlots/LAPPDPlots.cpp +++ b/UserTools/LAPPDPlots/LAPPDPlots.cpp @@ -296,7 +296,9 @@ bool LAPPDPlots::Execute() if (!drawTriggerChannel) nstrips = 28; const double BinHistMinConst = BinHistMin; - const double BinHistMaxConst = BinHistMax; + //cout<<"min is "< 3) diff --git a/UserTools/Unity.h b/UserTools/Unity.h index a24befea3..1a77c1d5a 100644 --- a/UserTools/Unity.h +++ b/UserTools/Unity.h @@ -192,3 +192,4 @@ #include "ProcessedLAPPDFilter.h" #include "BeamQuality.h" #include "FitRWMWaveform.h" +#include "LAPPDLoadTXT.h" diff --git a/configfiles/LAPPDASCIIAna/ConfigGeo b/configfiles/LAPPDASCIIAna/ConfigGeo new file mode 100644 index 000000000..ffe0ca918 --- /dev/null +++ b/configfiles/LAPPDASCIIAna/ConfigGeo @@ -0,0 +1,11 @@ +#LoadGeometry +verbosity 0 +LAPPDChannelCount 60 +FACCMRDGeoFile ./configfiles/LoadGeometry/FullMRDGeometry.csv +DetectorGeoFile ./configfiles/LoadGeometry/DetectorGeometrySpecs.csv +LAPPDGeoFile ./configfiles/LAPPDana/LAPPDGeometry.csv +TankPMTGeoFile ./configfiles/LoadGeometry/FullTankPMTGeometry.csv +TankPMTGainFile ./configfiles/LoadGeometry/ChannelSPEGains_BeamRun20192020.csv +AuxiliaryChannelFile ./configfiles/LoadGeometry/AuxChannels.csv +LAPPDMerging 0 + diff --git a/configfiles/LAPPDASCIIAna/ConfigPlot b/configfiles/LAPPDASCIIAna/ConfigPlot new file mode 100755 index 000000000..9f0140893 --- /dev/null +++ b/configfiles/LAPPDASCIIAna/ConfigPlot @@ -0,0 +1,139 @@ +oldLaser 0 #1 for old data, 0 for new trigger boards + +#LAPPDBaselineSubtract +BLSInputWavLabel AlignedLAPPDData +BaselineSubstractVerbosityLevel 0 +TrigChannel 5 #Specified channel the trigger signal will be on +LAPPDchannelOffset 1000 +LowBLfitrange 25; +HiBLfitrange 60; +TrigLowBLfitrange 30 +TrigHiBLfitrange 100 +BLSOutputWavLabel ABLSLAPPDData +oldLaserTrigAmpRange 40 + +#LAPPDFindPeak +FindPeakVerbosity 0 +FiltPeakInputWavLabel FiltLAPPDData +RawPeakInputWavLabel LAPPDWaveforms +BLSPeakInputWavLabel ABLSLAPPDData +FindPeakOutLabel SimpleRecoLAPPDPulses +TotThreshold 15. +MinimumTot 900. +Deltat 100. + +# General Parameters +Nsamples 256 +SampleSize 100 +NChannels 60 + +#LAPPDPlotWaveForms +requireT0signal 0 +SaveByChannel 1 +#PlotWavLabel RawLAPPDData +#PlotWavLabel LAPPDWaveforms +PlotWavLabel BLsubtractedLAPPDData +#PlotWavLabel AlignedLAPPDData +switchBit 0 + +outfile WaveForms_ablsub.root +NHistos 200 +SaveSingleStrip 0 +SingleStripNo 9 +plotLow -10 +plotHigh 20 + +#LAPPDPlotWaveForms2D +outfile2D RawDataWaveForms_2D.root +plot2DrecoPulseInputLabel thresRecoLAPPDPulses +plot2DrecoHitInputLabel thresRecoLAPPDHits +includeRecoPulses 1 +includeRecoHits 1 +plotAdditionalPart 1 +titleSize 0.04 +canvasMargin 0.15 +canvasTitleOffset 1 +#LAPPDSelectPlot2D +LAPPDSelectPlotWaveform2DLabel LAPPDWaveforms +SelectOutfile2D LAPPDSelectPlot.root +MRDTrackExistSelection 0 +verbosityPlot2D 10 +colorContour 255 +useDefaultPalette 1 +colorPalette 112 + + + +#LAPPDThresReco +LAPPDThresRecoVerbosity 0 +verbosity 0 +printHitsTXT 0 +threshold 10 +minPulseWidth 10 +#thresRecoInputWaveLabel AlignedLAPPDData +ThresRecoInputWaveLabel BLsubtractedLAPPDData +#thresRecoInputWaveLabel LAPPDWaveforms + +ThresRecoOutputPulseLabel LAPPDPulses +ThresRecoOutputHitLabel LAPPDHits +useMaxTime 1 # 1: use max bin as pulse time, 0: use gaus fit bin as pulse peak time +#signalSpeedOnStrip 0.6667 +signalSpeedOnStrip 0.567 #1.69982/2.99792 +triggerBoardDelay 0 +loadPrintMRDinfo 1 +useRange 0 #set this to 0 for using pulse start time as the saved pulse time, 1 for high, -1 for using peak time +plusClockBit 0 + +savePositionOnStrip 1 +LoadLAPPDMapInfo 1 + +#LAPPDStackStrip +verbosityStackStrip 0 +StackOutputFileName stacked.root +#StackInputWaveLabel BLsubtractedLAPPDData +StackInputWaveLabel RawLAPPDData +#StackInputWaveLabel LAPPDWaveforms +StackStripNumber 1 +StackStripSide 0 + +#LAPPDPlotWaveForms +NHistos 200 +SaveByChannel 0 +SaveSingleStrip 0 +SingleStripNo 1 +requireT0signal 0 + + +#LAPPDTreeMaker +treeMakerVerbosity 0 +treeMakerInputPulseLabel LAPPDPulses +treeMakerInputHitLabel LAPPDHits +treeMakerOutputFileName LAPPDTree.root + + +#LAPPDPlots +LAPPDPlotInputWaveLabel BLsubtractedLAPPDData +#LAPPDPlotInputWaveLabel LAPPDWaveforms +#LAPPDPlotInputWaveLabel AlignedLAPPDData +#LAPPDPlotInputWaveLabel RawLAPPDData +LAPPDPlotsVerbosity 0 +CanvasXSubPlotNumber 2 +CanvasYSubPlotNumber 2 +canvasMargin 0.1 +drawHighThreshold 200 +drawLowThreshold -50 +BinHistMin -30 +BinHistMax 200 +BinHistNumber 100 + +CanvasWidth 1000 +CanvasHeight 500 + +maxDrawEventNumber 200 + +DrawBinHist 1 +printEventNumber 0 +printLAPPDNumber 1 +printEventWaveform 1 + +LoadLAPPDMap 1 diff --git a/configfiles/LAPPDASCIIAna/ConfigPreProcess b/configfiles/LAPPDASCIIAna/ConfigPreProcess new file mode 100755 index 000000000..11cb9b98a --- /dev/null +++ b/configfiles/LAPPDASCIIAna/ConfigPreProcess @@ -0,0 +1,65 @@ +# General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +LAPPDchannelOffset 1000 +Folder ../Data/3655/ +#Folder ../Data/2022-06-10/ + +#LAPPDBaselineSubtract +BaselineSubstractVerbosityLevel 0 +TrigChannel1 1005 +TrigChannel2 1035 +#BLSInputWavLabel LAPPDWaveforms #LAPPDWaveforms +BLSInputWavLabel AlignedLAPPDData +#BLSInputWavLabel RawLAPPDData + +LowBLfitrange 0 +HiBLfitrange 60 +TrigLowBLfitrange 110 +TrigHiBLfitrange 160 +BLSOutputWavLabel BLsubtractedLAPPDData +oldLaserTrigAmpRange 40 + +#LAPPDFindT0 +FindT0Verbosity 0 +#FindT0InputWavLabel BLsubtractedLAPPDData +#FindT0InputWavLabel RawLAPPDData +FindT0InputWavLabel LAPPDWaveforms +OneBoardShift 0 +OneBoardShiftValue 16 +LoadLAPPDMap 1 + +TrigEarlyCut 20 +TrigLateCut 200 +T0channelNo 1005 +T0channelNo1 1005 +T0channelNo2 1005 +T0signalmax -100. +T0signalthreshold -50. +T0signalmaxOld 50. #Older data uses a positive going signal +T0signalthresholdOld 80. #Older data uses a positive going signal +T0offset 0 +FindT0OutputWavLabel AlignedLAPPDData +GlobalShiftT0 80 +#Added by Marc +Triggerdefault 5 +LAPPDOffset 1000 + +#LAPPDPlotWaveForms +requireT0signal 0 +SaveByChannel 1 +PlotWavLabel BLsubtractedLAPPDData +#PlotWavLabel LAPPDWaveforms +outfile WaveForms_rawblsub.root +NHistos 400 +SaveSingleStrip 0 +SingleStripNo 9 + + + + + + + + diff --git a/configfiles/LAPPDASCIIAna/ConfigStoreReadIn b/configfiles/LAPPDASCIIAna/ConfigStoreReadIn new file mode 100755 index 000000000..79f2d2fa7 --- /dev/null +++ b/configfiles/LAPPDASCIIAna/ConfigStoreReadIn @@ -0,0 +1,42 @@ +# General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +NUM_VECTOR_PPS 16 #Fixed PPS vector size +NUM_VECTOR_DATA 7795 #Fixed DATA vector size +NUM_VECTOR_METADATA 103 #Fixed META vector size +LAPPDchannelOffset 1000 +NChannels 30 +#StoreInputFile /pnfs/annie/persistent/users/redwards/data/filtered_lappd/R3649-R3844/LAPPDEventsBeamgateMRDTrack/FilteredEvents_LAPPDEventsBeamgateMRDTrack_R3649-R3844 + +LAPPDStoreReadInVerbosity 0 + +RawDataInputWavLabel RawWaveform +RawDataOutputWavLabel RawLAPPDData +BoardIndexLabel BoardIndex #Label of the vector of read out boards + +PsecReceiveMode 1 +stopEntries 10000000000 + +DoPedSubtraction 1 +Nboards 6 #Number of pedestal files to be read in +PedinputfileTXT ../Pedestals/swapLAPPD/Pedestal +#PedinputfileTXT ../Pedestals/change/Pedestal + +Pedinputfile1 ../Pedestals/PEDS_ACDC_board0.txt +Pedinputfile2 ../Pedestals/PEDS_ACDC_board1.txt + +#LAPPDReorderData +LAPPDReorderVerbosityLevel 0 +ReorderInputWavLabel RawLAPPDData +ReorderOutputWavLabel LAPPDWaveforms +DelayOffset 0 +GlobalShift 0 + +ReadStore 0 +NUM_VECTOR_DATA 7795 +NUM_VECTOR_PPS 16 +OutputWavLabel RawLAPPDData +SelectSingleLAPPD false +SelectedLAPPD 0 +LoadLAPPDMap 1 diff --git a/configfiles/LAPPDASCIIAna/ConfigTXT b/configfiles/LAPPDASCIIAna/ConfigTXT new file mode 100644 index 000000000..2798088b1 --- /dev/null +++ b/configfiles/LAPPDASCIIAna/ConfigTXT @@ -0,0 +1,84 @@ +#General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +NUM_VECTOR_PPS 16 #Fixed PPS vector size +NUM_VECTOR_DATA 7795 #Fixed DATA vector size +NUM_VECTOR_METADATA 103 #Fixed META vector size +LAPPDchannelOffset 1000 +NChannels 30 + +LAPPDStoreReadInVerbosity 0 + +mergingModeReadIn 0 +RawDataInputWavLabel RawWaveform +RawDataOutputWavLabel RawLAPPDData +BoardIndexLabel BoardIndex #Label of the vector of read out boards + +PsecReceiveMode 0 +MultiLAPPDMap 1 +stopEntries 10000000000 + +DoPedSubtraction 1 +Nboards 6 #Number of pedestal files to be read in +#PedinputfileTXT ../Pedestals/LAPPD645839/P +#PedinputfileTXT ../Pedestals/LAPPD40/P +PedinputfileTXT /pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/Pedestal/2023_LAPPD40/P + + +PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 + +ReadStorePdeFile 0 +loadFromStoreDirectly 0 + + +#LAPPDLoadTXT + +DoPedSubtract 1 +LAPPDLoadTXTVerbosity 0 +#PedFileNameTXT ../Pedestals/LAPPD40/P +PedFileNameTXT /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/PEDS_ACDC_board +#DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2023-10-24/2023-10-24/LaserON_2300V_strip28/Ascii20232410_135201.txt +DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/NDfilterScan_15mV/OD1.0/Ascii20221702_100345.txt +#DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/NDfilterScan_15mV/OD2.0/Ascii20221702_101913.txt +#DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/NDfilterScan_15mV/OD3.0/Ascii20221702_103605.txt +#DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/NDfilterScan_15mV/OD3.5/Ascii20221702_142206.txt + +#LAPPDReorderData +ReorderVerbosityLevel 0 +#ReorderInputWavLabel RawLAPPDData +ReorderInputWavLabel AlignedLAPPDData +ReorderOutputWavLabel LAPPDWaveforms +DelayOffset 0 +GlobalShift 180 + +ReadStore 0 +NUM_VECTOR_DATA 7795 +NUM_VECTOR_PPS 16 +OutputWavLabel RawLAPPDData +SelectSingleLAPPD false +SelectedLAPPD 0 +loadPSEC 1 +loadPPS 0 +loadOffsets 0 +LoadBuiltPPSInfo 1 +num_vector_data 7795 +num_vector_pps 16 + +#LAPPDTreeMaker +LoadPulse 1 +LoadHit 1 +LoadWaveform 1 +LoadLAPPDDataTimeStamp 1 +LoadPPSTimestamp 0 +LoadRunInfoRaw 0 +LoadRunInfoANNIEEvent 1 + +treeMakerVerbosity 0 +MultiLAPPDMapTreeMaker 1 +treeMakerInputPulseLabel LAPPDPulses +treeMakerInputHitLabel LAPPDHits +treeMakerOutputFileName LAPPDTree_processedAna.root +LoadTriggerInfo 0 +LoadGroupOption beam +LoadGroupedTriggerInfo 1 diff --git a/configfiles/LAPPDASCIIAna/Configs b/configfiles/LAPPDASCIIAna/Configs new file mode 100644 index 000000000..1f3cadc0e --- /dev/null +++ b/configfiles/LAPPDASCIIAna/Configs @@ -0,0 +1,74 @@ +#General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +NUM_VECTOR_PPS 16 #Fixed PPS vector size +NUM_VECTOR_DATA 7795 #Fixed DATA vector size +NUM_VECTOR_METADATA 103 #Fixed META vector size +LAPPDchannelOffset 1000 +NChannels 30 + +LAPPDStoreReadInVerbosity 0 + +mergingModeReadIn 0 +RawDataInputWavLabel RawWaveform +RawDataOutputWavLabel RawLAPPDData +BoardIndexLabel BoardIndex #Label of the vector of read out boards + +PsecReceiveMode 0 +MultiLAPPDMap 1 +stopEntries 10000000000 + +DoPedSubtraction 1 +Nboards 6 #Number of pedestal files to be read in +#PedinputfileTXT ../Pedestals/LAPPD645839/P +PedinputfileTXT ../Pedestals/LAPPD40/P + +PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 + +ReadStorePdeFile 0 +loadFromStoreDirectly 0 + +Pedinputfile1 ../Pedestals/PEDS_ACDC_board0.txt +Pedinputfile2 ../Pedestals/PEDS_ACDC_board1.txt + +#LAPPDReorderData +ReorderVerbosityLevel 0 +#ReorderInputWavLabel RawLAPPDData +ReorderInputWavLabel AlignedLAPPDData +ReorderOutputWavLabel LAPPDWaveforms +DelayOffset 0 +GlobalShift 180 + +ReadStore 0 +NUM_VECTOR_DATA 7795 +NUM_VECTOR_PPS 16 +OutputWavLabel RawLAPPDData +SelectSingleLAPPD false +SelectedLAPPD 0 +loadPSEC 1 +loadPPS 0 +loadOffsets 0 +LoadBuiltPPSInfo 1 +num_vector_data 7795 +num_vector_pps 16 + +#LAPPDTreeMaker +LoadPulse 1 +LoadHit 1 +LoadWaveform 1 +LoadLAPPDDataTimeStamp 1 +LoadPPSTimestamp 0 +LoadRunInfoRaw 0 +LoadRunInfoANNIEEvent 1 + +treeMakerVerbosity 0 +MultiLAPPDMapTreeMaker 0 +treeMakerInputPulseLabel LAPPDPulses +treeMakerInputHitLabel LAPPDHits +treeMakerOutputFileName LAPPDTree_ASCIIAna.root +LoadTriggerInfo 0 +LoadGroupOption beam +LoadGroupedTriggerInfo 1 +loadPrintMRDinfo 0 + diff --git a/configfiles/LAPPDASCIIAna/FindMrdTracksConfig b/configfiles/LAPPDASCIIAna/FindMrdTracksConfig new file mode 100644 index 000000000..5ba5e8f77 --- /dev/null +++ b/configfiles/LAPPDASCIIAna/FindMrdTracksConfig @@ -0,0 +1,12 @@ +# FindMrdTracks Config File +# all variables retrieved with m_variables.Get() must be defined here! + +verbosity 0 +IsData 1 +OutputDirectory . +OutputFile STEC_MRDTracks_cluster40ns +DrawTruthTracks 0 # whether to add MC Truth track info for drawing in MrdPaddlePlot Tool + ## note you need to run that tool to actually view the tracks! +WriteTracksToFile 0 # should the track information be written to a ROOT-file? +SelectTriggerType 0 #should the loaded data be filtered by trigger type? +TriggerType Beam #options: Cosmic, Beam, No Loopback diff --git a/configfiles/LAPPDASCIIAna/LoadANNIEEventConfig b/configfiles/LAPPDASCIIAna/LoadANNIEEventConfig new file mode 100644 index 000000000..b7330eecc --- /dev/null +++ b/configfiles/LAPPDASCIIAna/LoadANNIEEventConfig @@ -0,0 +1,6 @@ +verbose 1 + +FileForListOfInputs configfiles/LAPPDProcessedAna/list.txt + +EventOffset 0 +GlobalEvNr 1 diff --git a/configfiles/LAPPDASCIIAna/ProcessedLAPPDFilterConfig b/configfiles/LAPPDASCIIAna/ProcessedLAPPDFilterConfig new file mode 100644 index 000000000..752200268 --- /dev/null +++ b/configfiles/LAPPDASCIIAna/ProcessedLAPPDFilterConfig @@ -0,0 +1 @@ +verbosity 0 diff --git a/configfiles/LAPPDASCIIAna/TimeClusteringConfig b/configfiles/LAPPDASCIIAna/TimeClusteringConfig new file mode 100644 index 000000000..e778247fc --- /dev/null +++ b/configfiles/LAPPDASCIIAna/TimeClusteringConfig @@ -0,0 +1,13 @@ +#TimeClustering config file + +verbosity 0 +MinDigitsForTrack 3 +MaxMrdSubEventDuration 30 +MinSubeventTimeSep 30 +MakeMrdDigitTimePlot 0 +LaunchTApplication 0 +IsData 1 +#OutputROOTFile TimeClustering_MRDTest28_cluster40ns +OutputROOTFile STEC_TimeClusteringOut +MapChankey_WCSimID ./configfiles/SimpleTankEnergyCalibrator/MRD_Chankey_WCSimID.dat + diff --git a/configfiles/LAPPDASCIIAna/ToolChainConfig b/configfiles/LAPPDASCIIAna/ToolChainConfig new file mode 100644 index 000000000..5e3fc0158 --- /dev/null +++ b/configfiles/LAPPDASCIIAna/ToolChainConfig @@ -0,0 +1,24 @@ + +#ToollChain dynamic setup file + +##### Runtime Paramiters ##### +verbose 1 ## Verbosity level of ToolChain +error_level 0 # 0= do not exit, 1= exit on unhandeled errors only, 2= exit on unhandeled errors and handeled errors +attempt_recover 1 ## 1= will attempt to finalise if an execute fails + +###### Logging ##### +log_mode Interactive # Interactive=cout , Remote= remote logging system "serservice_name Remote_Logging" , Local = local file log; +log_local_path ./log +log_service LogStore + +###### Service discovery ##### Ignore these settings for local analysis +service_publish_sec -1 +service_kick_sec -1 + +##### Tools To Add ##### +Tools_File configfiles/LAPPDASCIIAna/ToolsConfig ## list of tools to run and their config files + +##### Run Type ##### +Inline 50 ## number of Execute steps in program, -1 infinite loop that is ended by user +Interactive 0 ## set to 1 if you want to run the code interactively + diff --git a/configfiles/LAPPDASCIIAna/ToolsConfig b/configfiles/LAPPDASCIIAna/ToolsConfig new file mode 100644 index 000000000..19db2afd1 --- /dev/null +++ b/configfiles/LAPPDASCIIAna/ToolsConfig @@ -0,0 +1,14 @@ +LoadGeometry LoadGeometry configfiles/LoadGeometry/LoadGeometryConfig + + +LAPPDLoadTXT LAPPDLoadTXT configfiles/LAPPDASCIIAna/ConfigTXT + +LAPPDStoreReorder LAPPDStoreReorder configfiles/LAPPDASCIIAna/ConfigStoreReadIn + +LAPPDTimeAlignment LAPPDTimeAlignment configfiles/LAPPDASCIIAna/ConfigPreProcess +LAPPDBaseline LAPPDBaseline configfiles/LAPPDASCIIAna/ConfigPreProcess +LAPPDPlots LAPPDPlots configfiles/LAPPDASCIIAna/ConfigPlot + +LAPPDThresReco LAPPDThresReco configfiles/LAPPDASCIIAna/ConfigPlot + +LAPPDTreeMaker LAPPDTreeMaker configfiles/LAPPDASCIIAna/Configs diff --git a/configfiles/LAPPDASCIIAna/knownlist b/configfiles/LAPPDASCIIAna/knownlist new file mode 100644 index 000000000..22c51f858 --- /dev/null +++ b/configfiles/LAPPDASCIIAna/knownlist @@ -0,0 +1 @@ +/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4843/ProcessedData_PMTMRDLAPPD_R4843S0p5 From ff3b708e33e399b6d090c890f823372f170c69cc Mon Sep 17 00:00:00 2001 From: Yue Date: Thu, 15 Aug 2024 09:33:58 -0500 Subject: [PATCH 091/163] Changes to be committed: deleted: configfiles/LAPPDASCIIAna/knownlist --- configfiles/LAPPDASCIIAna/knownlist | 1 - 1 file changed, 1 deletion(-) delete mode 100644 configfiles/LAPPDASCIIAna/knownlist diff --git a/configfiles/LAPPDASCIIAna/knownlist b/configfiles/LAPPDASCIIAna/knownlist deleted file mode 100644 index 22c51f858..000000000 --- a/configfiles/LAPPDASCIIAna/knownlist +++ /dev/null @@ -1 +0,0 @@ -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output/4843/ProcessedData_PMTMRDLAPPD_R4843S0p5 From 9b81f02684d909f03d0b0b539688cbd1878be6d3 Mon Sep 17 00:00:00 2001 From: Yue Date: Thu, 15 Aug 2024 15:35:23 -0500 Subject: [PATCH 092/163] Add branches about information for hits in clusters, and some MRD hit informations Changes to be committed: modified: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp modified: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h --- .../ANNIEEventTreeMaker.cpp | 48 +++++++++++++++---- .../ANNIEEventTreeMaker/ANNIEEventTreeMaker.h | 9 ++-- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index 6c8baca75..9e932b2bd 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -134,13 +134,23 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) fANNIETree->Branch("clusterChargePointZ", &fClusterChargePointZV); fANNIETree->Branch("clusterChargeBalance", &fClusterChargeBalanceV); fANNIETree->Branch("clusterHits", &fClusterHits); + fANNIETree->Branch("Cluster_HitX", &fCluster_HitX); + fANNIETree->Branch("Cluster_HitY", &fCluster_HitY); + fANNIETree->Branch("Cluster_HitZ", &fCluster_HitZ); + fANNIETree->Branch("Cluster_HitT", &fCluster_HitT); + fANNIETree->Branch("Cluster_HitQ", &fCluster_HitQ); + fANNIETree->Branch("Cluster_HitPE", &fCluster_HitPE); + fANNIETree->Branch("Cluster_HitType", &fCluster_HitType); + fANNIETree->Branch("Cluster_HitDetID", &fCluster_HitDetID); + fANNIETree->Branch("Cluster_HitChankey", &fCluster_HitChankey); + fANNIETree->Branch("Cluster_HitChankeyMC", &fCluster_HitChankeyMC); // MRD cluster information fANNIETree->Branch("eventTimeMRD", &fEventTimeMRD_Tree); fANNIETree->Branch("MRDClusterNumber", &fMRDClusterNumber); fANNIETree->Branch("MRDClusterTime", &fMRDClusterTime); fANNIETree->Branch("MRDClusterTimeSigma", &fMRDClusterTimeSigma); - fANNIETree->Branch("MRDClusterHits", &fMRDClusterHits); + fANNIETree->Branch("MRDClusterHitNumber", &fMRDClusterHitNumber); if (TankHitInfo_fill) { @@ -255,7 +265,11 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) if (MRDHitInfo_fill) { + fANNIETree->Branch("MRDHitClusterIndex", &fMRDHitClusterIndex); fANNIETree->Branch("MRDhitT", &fMRDHitT); + fANNIETree->Branch("MRDHitCharge", &fMRDHitCharge); + fANNIETree->Branch("MRDHitDigitPMT", &fMRDHitDigitPMT); + fANNIETree->Branch("MRDhitDetID", &fMRDHitDetID); fANNIETree->Branch("MRDhitChankey", &fMRDHitChankey); fANNIETree->Branch("MRDhitChankeyMC", &fMRDHitChankeyMC); @@ -268,7 +282,7 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) if (MRDReco_fill) { - fANNIETree->Branch("fMRDClusterIndex", &fMRDClusterIndex); + fANNIETree->Branch("MRDClusterIndex", &fMRDClusterIndex); fANNIETree->Branch("NumClusterTracks", &fNumClusterTracks); fANNIETree->Branch("MRDTrackAngle", &fMRDTrackAngle); fANNIETree->Branch("MRDTrackAngleError", &fMRDTrackAngleError); @@ -730,12 +744,15 @@ void ANNIEEventTreeMaker::ResetVariables() // MRD cluster information fEventTimeMRD_Tree = 0; fMRDClusterNumber = 0; - fMRDClusterHits = 0; - fMRDClusterTime = 0; - fMRDClusterTimeSigma = 0; + fMRDClusterHitNumber.clear(); + fMRDClusterTime.clear(); + fMRDClusterTimeSigma.clear(); fVetoHit = 0; + fMRDHitClusterIndex.clear(); fMRDHitT.clear(); + fMRDHitCharge.clear(); + fMRDHitDigitPMT.clear(); fMRDHitDetID.clear(); fMRDHitChankey.clear(); fMRDHitChankeyMC.clear(); @@ -1296,9 +1313,9 @@ void ANNIEEventTreeMaker::FillLAPPDInfo() // check if SwitchBitBG has the key if (SwitchBitBG.find(psecData.LAPPD_ID) != SwitchBitBG.end()) { - if(SwitchBitBG[psecData.LAPPD_ID].size() != 2) + if (SwitchBitBG[psecData.LAPPD_ID].size() != 2) { - cout<<"ANNIEEventTreeMaker: SwitchBitBG size is not 2, LAPPD_ID: "< mrddigittimesthisevent; + std::vector mrddigitchargesthisevent; + ; std::vector mrddigitpmtsthisevent; std::vector mrddigitchankeysthisevent; std::vector> MrdTimeClusters; @@ -1723,6 +1742,8 @@ void ANNIEEventTreeMaker::LoadMRDCluster() m_data->CStore.Get("MrdDigitTimes", mrddigittimesthisevent); m_data->CStore.Get("MrdDigitPmts", mrddigitpmtsthisevent); m_data->CStore.Get("MrdDigitChankeys", mrddigitchankeysthisevent); + m_data->CStore.Get("MrdDigitCharges", mrddigitchargesthisevent); + m_data->CStore.Get("MrdDigitPmts", mrddigitpmtsthisevent); } std::map> *TDCData = nullptr; @@ -1743,7 +1764,7 @@ void ANNIEEventTreeMaker::LoadMRDCluster() for (int i = 0; i < (int)MrdTimeClusters.size(); i++) { int tdcdata_size = (isData) ? TDCData->size() : TDCData_MC->size(); - fMRDClusterHits = 0; + int fMRDClusterHits = 0; if (has_tdc && tdcdata_size > 0) { Log("ANNIEEventTreeMaker tool: Looping over FACC/MRD hits... looking for Veto activity", v_debug, ANNIEEventTreeMakerVerbosity); @@ -1801,6 +1822,9 @@ void ANNIEEventTreeMaker::LoadMRDCluster() unsigned long detkey = thedetector->GetDetectorID(); fMRDHitT.push_back(mrddigittimesthisevent.at(ThisClusterIndices.at(j))); + fMRDHitClusterIndex.push_back(i); + fMRDHitCharge.push_back(mrddigitchargesthisevent.at(ThisClusterIndices.at(j))); + fMRDHitDigitPMT.push_back(mrddigitpmtsthisevent.at(ThisClusterIndices.at(j))); fMRDHitDetID.push_back(detkey); if (isData) fMRDHitChankey.push_back(mrddigitchankeysthisevent.at(ThisClusterIndices.at(j))); @@ -1814,7 +1838,9 @@ void ANNIEEventTreeMaker::LoadMRDCluster() fMRDClusterHits += 1; } - ComputeMeanAndVariance(fMRDHitT, fMRDClusterTime, fMRDClusterTimeSigma); + double MRDThisClusterTime = 0; + double MRDThisClusterTimeSigma = 0; + ComputeMeanAndVariance(fMRDHitT, MRDThisClusterTime, MRDThisClusterTimeSigma); // FIXME: calculate fMRDClusterTime // Standard run level information @@ -1827,6 +1853,10 @@ void ANNIEEventTreeMaker::LoadMRDCluster() // Get the track info } cluster_num++; + + fMRDClusterHitNumber.push_back(fMRDClusterHits); + fMRDClusterTime.push_back(MRDThisClusterTime); + fMRDClusterTimeSigma.push_back(MRDThisClusterTimeSigma); } fMRDClusterNumber = cluster_num; Log("ANNIEEventTreeMaker Tool: MRD cluster, Finished loading MRD cluster info", v_debug, ANNIEEventTreeMakerVerbosity); diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h index 6df847a17..26f4418b6 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h @@ -303,13 +303,16 @@ class ANNIEEventTreeMaker : public Tool // MRD cluster information ULong64_t fEventTimeMRD_Tree; int fMRDClusterNumber; - int fMRDClusterHits; - double fMRDClusterTime; - double fMRDClusterTimeSigma; + std::vector fMRDClusterHitNumber; + std::vector fMRDClusterTime; + std::vector fMRDClusterTimeSigma; // MRDHitInfo_fill int fVetoHit; + std::vector fMRDHitClusterIndex; std::vector fMRDHitT; + std::vector fMRDHitCharge; + std::vector fMRDHitDigitPMT; std::vector fMRDHitDetID; std::vector fMRDHitChankey; std::vector fMRDHitChankeyMC; From e6f456991f9b011ee0b7fbdebc2feb6112bb197d Mon Sep 17 00:00:00 2001 From: Yue Date: Thu, 15 Aug 2024 16:18:59 -0500 Subject: [PATCH 093/163] Add a stop for LAPPDLoadTXT, when reach the end of the txt file tool chain will stop Changes to be committed: modified: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp modified: UserTools/LAPPDLoadTXT/LAPPDLoadTXT.cpp modified: configfiles/LAPPDProcessedAna/Configs --- .../ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp | 14 ++++++-------- UserTools/LAPPDLoadTXT/LAPPDLoadTXT.cpp | 13 +++++++++---- configfiles/LAPPDProcessedAna/Configs | 4 +++- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index 9e932b2bd..5f7f4c6ee 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -302,11 +302,8 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) fANNIETree->Branch("MRDThrough", &fMRDThrough); } - if (fillCleanEventsOnly) - { - fANNIETree->Branch("eventStatusApplied", &fEventStatusApplied, "eventStatusApplied/I"); - fANNIETree->Branch("eventStatusFlagged", &fEventStatusFlagged, "eventStatusFlagged/I"); - } + fANNIETree->Branch("eventStatusApplied", &fEventStatusApplied, "eventStatusApplied/I"); + fANNIETree->Branch("eventStatusFlagged", &fEventStatusFlagged, "eventStatusFlagged/I"); // MC truth information for muons // Output to tree when MCTruth_fill = 1 in config @@ -468,10 +465,11 @@ bool ANNIEEventTreeMaker::Execute() //****************************** fillCleanEventsOnly *************************************// // If only clean events are built, return true for dirty events + auto get_flagsapp = m_data->Stores.at("RecoEvent")->Get("EventFlagApplied", fEventStatusApplied); + auto get_flags = m_data->Stores.at("RecoEvent")->Get("EventFlagged", fEventStatusFlagged); + if (fillCleanEventsOnly) { - auto get_flagsapp = m_data->Stores.at("RecoEvent")->Get("EventFlagApplied", fEventStatusApplied); - auto get_flags = m_data->Stores.at("RecoEvent")->Get("EventFlagged", fEventStatusFlagged); // auto get_cutstatus = m_data->Stores.at("RecoEvent")->Get("EventCutStatus",fEventCutStatus); if (!get_flagsapp || !get_flags) { @@ -1822,7 +1820,7 @@ void ANNIEEventTreeMaker::LoadMRDCluster() unsigned long detkey = thedetector->GetDetectorID(); fMRDHitT.push_back(mrddigittimesthisevent.at(ThisClusterIndices.at(j))); - fMRDHitClusterIndex.push_back(i); + fMRDHitClusterIndex.push_back(i); fMRDHitCharge.push_back(mrddigitchargesthisevent.at(ThisClusterIndices.at(j))); fMRDHitDigitPMT.push_back(mrddigitpmtsthisevent.at(ThisClusterIndices.at(j))); fMRDHitDetID.push_back(detkey); diff --git a/UserTools/LAPPDLoadTXT/LAPPDLoadTXT.cpp b/UserTools/LAPPDLoadTXT/LAPPDLoadTXT.cpp index aa2a51c14..95a96d05a 100644 --- a/UserTools/LAPPDLoadTXT/LAPPDLoadTXT.cpp +++ b/UserTools/LAPPDLoadTXT/LAPPDLoadTXT.cpp @@ -74,7 +74,7 @@ bool LAPPDLoadTXT::Initialise(std::string configfile, DataModel &data) bool LAPPDLoadTXT::Execute() { - Log("LAPPDLoadTXT: Reading data file", v_message, LAPPDLoadTXTVerbosity); + Log("LAPPDLoadTXT: Reading data file", v_debug, LAPPDLoadTXTVerbosity); bool isFiltered = false; m_data->Stores["ANNIEEvent"]->Set("isFiltered", isFiltered); bool isBLsub = false; @@ -235,8 +235,8 @@ void LAPPDLoadTXT::ReadData() } int pedsubValue = tempValue - theped; - if(LAPPDLoadTXTVerbosity>11) - cout<<"LAPPDLoadTXT: data value: "< 11) + cout << "LAPPDLoadTXT: data value: " << tempValue << " pedestal value: " << theped << " pedsub value: " << pedsubValue << ", inserted " << 0.3 * ((double)pedsubValue) << endl; if (sampleNo == 0) { @@ -257,7 +257,12 @@ void LAPPDLoadTXT::ReadData() lineNumber++; if (sampleNo == 255) { - Log("LAPPDLoadTXT: Event " + std::to_string(eventNo) + " loaded", v_message, LAPPDLoadTXTVerbosity); + Log("LAPPDLoadTXT: Event " + std::to_string(eventNo) + " loaded", v_debug, LAPPDLoadTXTVerbosity); + if (DataFile.peek() == EOF) // 检查下一个字符是å¦ä¸ºEOF + { + m_data->vars.Set("StopLoop", 1); + Log("LAPPDLoadTXT: End of data file reached, setting StopLoop to 1", 0, LAPPDLoadTXTVerbosity); + } break; } } diff --git a/configfiles/LAPPDProcessedAna/Configs b/configfiles/LAPPDProcessedAna/Configs index 0fa484e4b..b73178a3f 100644 --- a/configfiles/LAPPDProcessedAna/Configs +++ b/configfiles/LAPPDProcessedAna/Configs @@ -22,6 +22,8 @@ stopEntries 10000000000 DoPedSubtraction 1 Nboards 6 #Number of pedestal files to be read in PedinputfileTXT ../Pedestals/LAPPD645839/P +#PedinputfileTXT ../Pedestals/LAPPD40/P + PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 ReadStorePdeFile 0 @@ -56,7 +58,7 @@ LoadPulse 1 LoadHit 1 LoadWaveform 1 LoadLAPPDDataTimeStamp 1 -LoadPPSTimestamp 1 +LoadPPSTimestamp 0 LoadRunInfoRaw 0 LoadRunInfoANNIEEvent 1 From b51d0930cfd98a785609b59687e8f08d978df374 Mon Sep 17 00:00:00 2001 From: Yue Date: Thu, 15 Aug 2024 16:22:06 -0500 Subject: [PATCH 094/163] modified the ASCIIAna configs --- configfiles/LAPPDASCIIAna/ConfigPlot | 2 +- configfiles/LAPPDASCIIAna/ConfigTXT | 2 +- configfiles/LAPPDASCIIAna/FindMrdTracksConfig | 12 ------------ configfiles/LAPPDASCIIAna/LoadANNIEEventConfig | 6 ------ configfiles/LAPPDASCIIAna/ProcessedLAPPDFilterConfig | 1 - configfiles/LAPPDASCIIAna/ToolChainConfig | 2 +- 6 files changed, 3 insertions(+), 22 deletions(-) delete mode 100644 configfiles/LAPPDASCIIAna/FindMrdTracksConfig delete mode 100644 configfiles/LAPPDASCIIAna/LoadANNIEEventConfig delete mode 100644 configfiles/LAPPDASCIIAna/ProcessedLAPPDFilterConfig diff --git a/configfiles/LAPPDASCIIAna/ConfigPlot b/configfiles/LAPPDASCIIAna/ConfigPlot index 9f0140893..cb2729c47 100755 --- a/configfiles/LAPPDASCIIAna/ConfigPlot +++ b/configfiles/LAPPDASCIIAna/ConfigPlot @@ -129,7 +129,7 @@ BinHistNumber 100 CanvasWidth 1000 CanvasHeight 500 -maxDrawEventNumber 200 +maxDrawEventNumber 100 DrawBinHist 1 printEventNumber 0 diff --git a/configfiles/LAPPDASCIIAna/ConfigTXT b/configfiles/LAPPDASCIIAna/ConfigTXT index 2798088b1..87e82aef8 100644 --- a/configfiles/LAPPDASCIIAna/ConfigTXT +++ b/configfiles/LAPPDASCIIAna/ConfigTXT @@ -35,7 +35,7 @@ loadFromStoreDirectly 0 #LAPPDLoadTXT DoPedSubtract 1 -LAPPDLoadTXTVerbosity 0 +LAPPDLoadTXTVerbosity 1 #PedFileNameTXT ../Pedestals/LAPPD40/P PedFileNameTXT /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/PEDS_ACDC_board #DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2023-10-24/2023-10-24/LaserON_2300V_strip28/Ascii20232410_135201.txt diff --git a/configfiles/LAPPDASCIIAna/FindMrdTracksConfig b/configfiles/LAPPDASCIIAna/FindMrdTracksConfig deleted file mode 100644 index 5ba5e8f77..000000000 --- a/configfiles/LAPPDASCIIAna/FindMrdTracksConfig +++ /dev/null @@ -1,12 +0,0 @@ -# FindMrdTracks Config File -# all variables retrieved with m_variables.Get() must be defined here! - -verbosity 0 -IsData 1 -OutputDirectory . -OutputFile STEC_MRDTracks_cluster40ns -DrawTruthTracks 0 # whether to add MC Truth track info for drawing in MrdPaddlePlot Tool - ## note you need to run that tool to actually view the tracks! -WriteTracksToFile 0 # should the track information be written to a ROOT-file? -SelectTriggerType 0 #should the loaded data be filtered by trigger type? -TriggerType Beam #options: Cosmic, Beam, No Loopback diff --git a/configfiles/LAPPDASCIIAna/LoadANNIEEventConfig b/configfiles/LAPPDASCIIAna/LoadANNIEEventConfig deleted file mode 100644 index b7330eecc..000000000 --- a/configfiles/LAPPDASCIIAna/LoadANNIEEventConfig +++ /dev/null @@ -1,6 +0,0 @@ -verbose 1 - -FileForListOfInputs configfiles/LAPPDProcessedAna/list.txt - -EventOffset 0 -GlobalEvNr 1 diff --git a/configfiles/LAPPDASCIIAna/ProcessedLAPPDFilterConfig b/configfiles/LAPPDASCIIAna/ProcessedLAPPDFilterConfig deleted file mode 100644 index 752200268..000000000 --- a/configfiles/LAPPDASCIIAna/ProcessedLAPPDFilterConfig +++ /dev/null @@ -1 +0,0 @@ -verbosity 0 diff --git a/configfiles/LAPPDASCIIAna/ToolChainConfig b/configfiles/LAPPDASCIIAna/ToolChainConfig index 5e3fc0158..a1791e8d2 100644 --- a/configfiles/LAPPDASCIIAna/ToolChainConfig +++ b/configfiles/LAPPDASCIIAna/ToolChainConfig @@ -19,6 +19,6 @@ service_kick_sec -1 Tools_File configfiles/LAPPDASCIIAna/ToolsConfig ## list of tools to run and their config files ##### Run Type ##### -Inline 50 ## number of Execute steps in program, -1 infinite loop that is ended by user +Inline -1 ## number of Execute steps in program, -1 infinite loop that is ended by user Interactive 0 ## set to 1 if you want to run the code interactively From 4b221ad6219843a8179ddff7e9ab0bde7c38d4dd Mon Sep 17 00:00:00 2001 From: Yue Date: Tue, 20 Aug 2024 15:45:22 -0500 Subject: [PATCH 095/163] correct some config files Changes to be committed: modified: configfiles/LAPPDASCIIAna/ConfigPlot modified: configfiles/LAPPDASCIIAna/ConfigTXT modified: configfiles/LAPPDProcessedAna/ConfigPlot --- configfiles/LAPPDASCIIAna/ConfigPlot | 6 +++--- configfiles/LAPPDASCIIAna/ConfigTXT | 4 ++-- configfiles/LAPPDProcessedAna/ConfigPlot | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/configfiles/LAPPDASCIIAna/ConfigPlot b/configfiles/LAPPDASCIIAna/ConfigPlot index cb2729c47..8588fe083 100755 --- a/configfiles/LAPPDASCIIAna/ConfigPlot +++ b/configfiles/LAPPDASCIIAna/ConfigPlot @@ -80,7 +80,7 @@ useMaxTime 1 # 1: use max bin as pulse time, 0: use gaus fit bin as pulse peak #signalSpeedOnStrip 0.6667 signalSpeedOnStrip 0.567 #1.69982/2.99792 triggerBoardDelay 0 -loadPrintMRDinfo 1 +loadPrintMRDinfo 0 useRange 0 #set this to 0 for using pulse start time as the saved pulse time, 1 for high, -1 for using peak time plusClockBit 0 @@ -129,10 +129,10 @@ BinHistNumber 100 CanvasWidth 1000 CanvasHeight 500 -maxDrawEventNumber 100 +maxDrawEventNumber 1000 DrawBinHist 1 -printEventNumber 0 +printEventNumber 1000 printLAPPDNumber 1 printEventWaveform 1 diff --git a/configfiles/LAPPDASCIIAna/ConfigTXT b/configfiles/LAPPDASCIIAna/ConfigTXT index 87e82aef8..eda75e045 100644 --- a/configfiles/LAPPDASCIIAna/ConfigTXT +++ b/configfiles/LAPPDASCIIAna/ConfigTXT @@ -39,10 +39,10 @@ LAPPDLoadTXTVerbosity 1 #PedFileNameTXT ../Pedestals/LAPPD40/P PedFileNameTXT /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/PEDS_ACDC_board #DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2023-10-24/2023-10-24/LaserON_2300V_strip28/Ascii20232410_135201.txt -DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/NDfilterScan_15mV/OD1.0/Ascii20221702_100345.txt +#DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/NDfilterScan_15mV/OD1.0/Ascii20221702_100345.txt #DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/NDfilterScan_15mV/OD2.0/Ascii20221702_101913.txt #DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/NDfilterScan_15mV/OD3.0/Ascii20221702_103605.txt -#DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/NDfilterScan_15mV/OD3.5/Ascii20221702_142206.txt +DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/NDfilterScan_15mV/OD3.5/Ascii20221702_142206.txt #LAPPDReorderData ReorderVerbosityLevel 0 diff --git a/configfiles/LAPPDProcessedAna/ConfigPlot b/configfiles/LAPPDProcessedAna/ConfigPlot index d42ca22d3..73c090663 100755 --- a/configfiles/LAPPDProcessedAna/ConfigPlot +++ b/configfiles/LAPPDProcessedAna/ConfigPlot @@ -80,7 +80,7 @@ useMaxTime 1 # 1: use max bin as pulse time, 0: use gaus fit bin as pulse peak #signalSpeedOnStrip 0.6667 signalSpeedOnStrip 0.567 #1.69982/2.99792 triggerBoardDelay 0 -loadPrintMRDinfo 1 +loadPrintMRDinfo 0 useRange 0 #set this to 0 for using pulse start time as the saved pulse time, 1 for high, -1 for using peak time plusClockBit 0 From 0bd451588411eeef4fc6719fd5736d8fddbd2048 Mon Sep 17 00:00:00 2001 From: Yue Date: Fri, 30 Aug 2024 13:19:34 -0500 Subject: [PATCH 096/163] Fix a bug in the event builder. In the previous version, the EBPMT will do matching per 500 loops, and the force matching doesn't work at the end of each part file. Now there is a flag shows if the PMT was completely loaded in EBLoadRaw, and EBPMT will do matching if that flag was found. Also, some configs was changed, a new tool chain for LAPPD151 analysis was added. --- UserTools/EBLoadRaw/EBLoadRaw.cpp | 10 + UserTools/EBPMT/EBPMT.cpp | 13 +- UserTools/Factory/Factory.cpp | 1 + UserTools/LAPPDBSCharging/LAPPDBSCharging.cpp | 28 ++ UserTools/LAPPDBSCharging/LAPPDBSCharging.h | 39 +++ UserTools/LAPPDBSCharging/README.md | 20 ++ .../LAPPDStoreReorder/LAPPDStoreReorder.cpp | 14 +- .../LAPPDTimeAlignment/LAPPDTimeAlignment.cpp | 29 +- .../ProcessedLAPPDFilter.cpp | 15 +- UserTools/Unity.h | 1 + configfiles/BeamClusterAnalysis/ToolsConfig | 1 + configfiles/LAPPDASCIIAna/ConfigTXT | 11 +- configfiles/LAPPDASCIIAnaFor151/ConfigGeo | 11 + configfiles/LAPPDASCIIAnaFor151/ConfigPlot | 133 ++++++++ .../LAPPDASCIIAnaFor151/ConfigPreProcess | 48 +++ .../LAPPDASCIIAnaFor151/ConfigPreProcess2 | 68 ++++ .../LAPPDASCIIAnaFor151/ConfigStoreReadIn | 23 ++ configfiles/LAPPDASCIIAnaFor151/ConfigTXT | 93 ++++++ configfiles/LAPPDASCIIAnaFor151/Configs | 74 +++++ .../LAPPDASCIIAnaFor151/TimeClusteringConfig | 13 + .../LAPPDASCIIAnaFor151/ToolChainConfig | 24 ++ configfiles/LAPPDASCIIAnaFor151/ToolsConfig | 18 ++ configfiles/LAPPDProcessedAna/ConfigPlot | 4 +- .../LAPPDProcessedAna/ConfigPreProcess | 4 +- configfiles/LAPPDProcessedAna/ConfigTXT | 72 +++++ configfiles/LAPPDProcessedAna/Configs | 6 +- configfiles/LAPPDProcessedAna/ToolChainConfig | 2 +- configfiles/LAPPDProcessedAna/list.txt | 26 +- .../ProcessedLAPPDFilterConfig | 4 +- configfiles/LAPPDProcessedFilter/list.txt | 302 +----------------- 30 files changed, 767 insertions(+), 340 deletions(-) create mode 100644 UserTools/LAPPDBSCharging/LAPPDBSCharging.cpp create mode 100644 UserTools/LAPPDBSCharging/LAPPDBSCharging.h create mode 100644 UserTools/LAPPDBSCharging/README.md create mode 100644 configfiles/LAPPDASCIIAnaFor151/ConfigGeo create mode 100755 configfiles/LAPPDASCIIAnaFor151/ConfigPlot create mode 100755 configfiles/LAPPDASCIIAnaFor151/ConfigPreProcess create mode 100755 configfiles/LAPPDASCIIAnaFor151/ConfigPreProcess2 create mode 100755 configfiles/LAPPDASCIIAnaFor151/ConfigStoreReadIn create mode 100644 configfiles/LAPPDASCIIAnaFor151/ConfigTXT create mode 100644 configfiles/LAPPDASCIIAnaFor151/Configs create mode 100644 configfiles/LAPPDASCIIAnaFor151/TimeClusteringConfig create mode 100644 configfiles/LAPPDASCIIAnaFor151/ToolChainConfig create mode 100644 configfiles/LAPPDASCIIAnaFor151/ToolsConfig create mode 100644 configfiles/LAPPDProcessedAna/ConfigTXT diff --git a/UserTools/EBLoadRaw/EBLoadRaw.cpp b/UserTools/EBLoadRaw/EBLoadRaw.cpp index abf61c9af..2d601b4fb 100644 --- a/UserTools/EBLoadRaw/EBLoadRaw.cpp +++ b/UserTools/EBLoadRaw/EBLoadRaw.cpp @@ -579,6 +579,16 @@ bool EBLoadRaw::LoadNextPMTData() m_data->CStore.Set("TankEntryNum", PMTEntryNum); PMTEntryNum++; + if(PMTEntryNum == PMTTotalEntries || PMTEntryNum > PMTTotalEntries) + { + Log("EBLoadRaw: PMTEntriesCompleted, force PMT matching", v_message, verbosityEBLoadRaw); + bool ForcePMTMatching = true; + m_data->CStore.Set("ForcePMTMatching", ForcePMTMatching); + }else{ + bool ForcePMTMatching = false; + m_data->CStore.Set("ForcePMTMatching", ForcePMTMatching); + } + return true; } diff --git a/UserTools/EBPMT/EBPMT.cpp b/UserTools/EBPMT/EBPMT.cpp index ba6c9469e..c30edfbac 100644 --- a/UserTools/EBPMT/EBPMT.cpp +++ b/UserTools/EBPMT/EBPMT.cpp @@ -111,7 +111,7 @@ bool EBPMT::Execute() if (ChannelKey.size() == (NumWavesInCompleteSet - 1)) { - Log("EBPMT: ChannelKey.size() = " + std::to_string(ChannelKey.size()) + " == NumWavesInCompleteSet - 1 = " + std::to_string(NumWavesInCompleteSet - 1), v_debug, verbosityEBPMT); + Log("EBPMT: ChannelKey.size() == (NumWavesInCompleteSet - 1), ChannelKey.size() = " + std::to_string(ChannelKey.size()) + " == NumWavesInCompleteSet - 1 = " + std::to_string(NumWavesInCompleteSet - 1), v_debug, verbosityEBPMT); if (AlmostCompleteWaveforms.find(PMTCounterTimeNs) != AlmostCompleteWaveforms.end()) { Log("EBPMT: AlmostCompleteWaveforms size = " + std::to_string(AlmostCompleteWaveforms.size()), v_debug, verbosityEBPMT); @@ -201,9 +201,14 @@ bool EBPMT::Execute() bool stopLoop = false; m_data->vars.Get("StopLoop", stopLoop); - int runNum = thisRunNum; - m_data->vars.Get("RunNumber", thisRunNum); - if (exeNum % exePerMatch == 0 || runNum != thisRunNum || stopLoop) + int runNum = thisRunNum; // run number saved in buffer as the previous run number + //m_data->vars.Get("RunNumber", thisRunNum); + m_data->CStore.Get("runNumber", thisRunNum); + + bool ForcePMTMatching = false; + m_data->CStore.Get("ForcePMTMatching", ForcePMTMatching); + + if (exeNum % exePerMatch == 0 || runNum != thisRunNum || stopLoop || ForcePMTMatching) { Log("EBPMT: exeNum: " + std::to_string(exeNum) + " Doing Matching", v_message, verbosityEBPMT); if (matchToAllTriggers) diff --git a/UserTools/Factory/Factory.cpp b/UserTools/Factory/Factory.cpp index 82b0c3a3f..6bc13642c 100644 --- a/UserTools/Factory/Factory.cpp +++ b/UserTools/Factory/Factory.cpp @@ -185,5 +185,6 @@ if (tool=="ProcessedLAPPDFilter") ret=new ProcessedLAPPDFilter; if (tool=="BeamQuality") ret=new BeamQuality; if (tool=="FitRWMWaveform") ret=new FitRWMWaveform; if (tool=="LAPPDLoadTXT") ret=new LAPPDLoadTXT; +if (tool=="LAPPDBSCharging") ret=new LAPPDBSCharging; return ret; } diff --git a/UserTools/LAPPDBSCharging/LAPPDBSCharging.cpp b/UserTools/LAPPDBSCharging/LAPPDBSCharging.cpp new file mode 100644 index 000000000..878aa77a8 --- /dev/null +++ b/UserTools/LAPPDBSCharging/LAPPDBSCharging.cpp @@ -0,0 +1,28 @@ +#include "LAPPDBSCharging.h" + +LAPPDBSCharging::LAPPDBSCharging():Tool(){} + + +bool LAPPDBSCharging::Initialise(std::string configfile, DataModel &data){ + + /////////////////// Useful header /////////////////////// + if(configfile!="") m_variables.Initialise(configfile); // loading config file + //m_variables.Print(); + + m_data= &data; //assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + return true; +} + + +bool LAPPDBSCharging::Execute(){ + + return true; +} + + +bool LAPPDBSCharging::Finalise(){ + + return true; +} diff --git a/UserTools/LAPPDBSCharging/LAPPDBSCharging.h b/UserTools/LAPPDBSCharging/LAPPDBSCharging.h new file mode 100644 index 000000000..f8c90801c --- /dev/null +++ b/UserTools/LAPPDBSCharging/LAPPDBSCharging.h @@ -0,0 +1,39 @@ +#ifndef LAPPDBSCharging_H +#define LAPPDBSCharging_H + +#include +#include + +#include "Tool.h" + + +/** + * \class LAPPDBSCharging + * + * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. +* +* $Author: B.Richards $ +* $Date: 2019/05/28 10:44:00 $ +* Contact: b.richards@qmul.ac.uk +*/ +class LAPPDBSCharging: public Tool { + + + public: + + LAPPDBSCharging(); ///< Simple constructor + bool Initialise(std::string configfile,DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + + + private: + + + + + +}; + + +#endif diff --git a/UserTools/LAPPDBSCharging/README.md b/UserTools/LAPPDBSCharging/README.md new file mode 100644 index 000000000..af939269b --- /dev/null +++ b/UserTools/LAPPDBSCharging/README.md @@ -0,0 +1,20 @@ +# LAPPDBSCharging + +LAPPDBSCharging + +## Data + +Describe any data formats LAPPDBSCharging creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for LAPPDBSCharging. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp b/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp index e89652e5b..9fd31430e 100644 --- a/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp +++ b/UserTools/LAPPDStoreReorder/LAPPDStoreReorder.cpp @@ -116,7 +116,7 @@ bool LAPPDStoreReorder::DoReorder() map>>::iterator itr; for (itr = lappddata.begin(); itr != lappddata.end(); ++itr) { - if (LAPPDReorderVerbosityLevel > 1) + if (LAPPDReorderVerbosityLevel > 4) cout << "reordering channelno= " << itr->first << endl; unsigned long channelno = itr->first; int channelHere = channelno; @@ -124,7 +124,7 @@ bool LAPPDStoreReorder::DoReorder() Channel *chan = _geom->GetChannel(channelHere); int stripno = chan->GetStripNum(); vector> Vwavs = itr->second; - if (LAPPDReorderVerbosityLevel > 1) + if (LAPPDReorderVerbosityLevel > 5) { cout << "this channel has " << Vwavs.size() << " waveforms" << endl; if (Vwavs.size() > 0) @@ -141,7 +141,7 @@ bool LAPPDStoreReorder::DoReorder() // }else{ // bi = bi%2; // } - if (LAPPDReorderVerbosityLevel > 5) + if (LAPPDReorderVerbosityLevel > 6) { // print the elements in NReadBoards, print LAPPDID; cout << "NReadBoards size is " << NReadBoards.size() << endl; @@ -201,16 +201,16 @@ bool LAPPDStoreReorder::DoReorder() } reordereddata.insert(pair>>(LAPPDchannelOffset + channelno, Vrwav)); - if (LAPPDReorderVerbosityLevel > 2) - cout << "inserted channelno: " << LAPPDchannelOffset + channelno << ", current reorded data size is " << reordereddata.size() << endl; + if (LAPPDReorderVerbosityLevel > 4) + cout << "inserted channelno: " << LAPPDchannelOffset + channelno << ", current reorded data size is " << reordereddata.size() << ", switchword = " << switchword << ", switchbit = " << switchbit << endl; } - if (LAPPDReorderVerbosityLevel > 1) + if (LAPPDReorderVerbosityLevel > 4) { cout << "LAPPDStoreReorder, reordered data size is " << reordereddata.size() << endl; } m_data->Stores["ANNIEEvent"]->Set("SwitchBitBG", Smeta_BG_map); - if(LAPPDReorderVerbosityLevel>0) + if(LAPPDReorderVerbosityLevel>3) { cout << "LAPPDStoreReorder:: insert SwitchBitBG map size is " << Smeta_BG_map.size() << endl; } diff --git a/UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.cpp b/UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.cpp index a6f7dee7b..8185d3bbe 100644 --- a/UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.cpp +++ b/UserTools/LAPPDTimeAlignment/LAPPDTimeAlignment.cpp @@ -282,7 +282,7 @@ double LAPPDTimeAlignment::Tfit(std::vector *wf) if (oldLaser == 1) { - if (firstcross && pvol > T0signalmax && ppre < T0signalmax && i > 5 && i < 250) + if (firstcross && pvol > T0signalmax && ppre < T0signalmax && i > 1 && i < 255) { // trigger up to +200 2020 data if (FindT0VerbosityLevel > 1) cout << "Old t0 bin: " << i << endl; @@ -310,13 +310,37 @@ double LAPPDTimeAlignment::Tfit(std::vector *wf) else { - if (firstcross && pvol < T0signalmax && ppre > T0signalmax && i > 7 && i < 249) + if (firstcross && pvol < T0signalmax && ppre > T0signalmax && i > 1 && i < 255) { if (FindT0VerbosityLevel > 1) cout << "New t0 bin: " << i << endl; TGraph *edge = new TGraph(); + int start = -7; + if(i<7) start = -i; + for (int j = start; j < 1; j++) + { + edge->SetPoint(j -start, (i + j) * 100., (wf->at(i + j))); + } + + bool firstthreshcross = true; + for (int k = (i +start) * 100; k < (i + 1) * 100; k += 10) + { + + if (FindT0VerbosityLevel == 3) + cout << k << " " << (edge->Eval((double)k, 0, "S")) << endl; + + if (((edge->Eval((double)k, 0, "S")) < T0signalthreshold) && firstthreshcross) + { + if (FindT0VerbosityLevel > 2) + cout << "time: " << k << endl; + ttime = (double)k; + firstthreshcross = false; + } + } + + /* for (int j = -7; j < 1; j++) { edge->SetPoint(j + 7, (i + j) * 100., (wf->at(i + j))); @@ -337,6 +361,7 @@ double LAPPDTimeAlignment::Tfit(std::vector *wf) firstthreshcross = false; } } + */ firstcross = false; } diff --git a/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp index 180fd9951..16c00a121 100644 --- a/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp +++ b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp @@ -62,9 +62,18 @@ bool ProcessedLAPPDFilter::Initialise(std::string configfile, DataModel &data) bool ProcessedLAPPDFilter::Execute() { + uint64_t ETT = 0; + bool gotETT = m_data->Stores["ANNIEEvent"]->Get("EventTimeTank", ETT); + int pTW = 0; + bool gotpTW = m_data->Stores["ANNIEEvent"]->Get("PrimaryTriggerWord", pTW); + uint64_t pTT = 0; + bool gotpTT = m_data->Stores["ANNIEEvent"]->Get("PrimaryTriggerTime", pTT); + + Log("ProcessedLAPPDFilter: Got ETT: " + std::to_string(ETT) + "(" + std::to_string(gotETT) + "), pTW: " + std::to_string(pTW) + "(" + std::to_string(gotpTW) + "), pTT: " + std::to_string(pTT) + "(" + std::to_string(gotpTT) + ")", 1, FilterVerbosity); + m_data->Stores.at("ANNIEEvent")->Get("DataStreams", DataStreams); - if (FilterVerbosity > 2) + if (FilterVerbosity > 3) { for (auto it = DataStreams.begin(); it != DataStreams.end(); ++it) { @@ -338,8 +347,12 @@ bool ProcessedLAPPDFilter::GotANNIEEventAndSave(BoostStore *BS, string savePath) BS->Set("TriggerWord", TriggerWord); m_data->Stores["ANNIEEvent"]->Get("EventTimeMRD", EventTimeMRD); BS->Set("EventTimeMRD", EventTimeMRD); + m_data->Stores["ANNIEEvent"]->Get("EventTimeTank", EventTimeTank); + Log("ProcessedLAPPDFilter: Got EventTimeTank: " + std::to_string(EventTimeTank), 1, FilterVerbosity); BS->Set("EventTimeTank", EventTimeTank); + Log("ProcessedLAPPDFilter: Set EventTimeTank: " + std::to_string(EventTimeTank), 1, FilterVerbosity); + m_data->Stores["ANNIEEvent"]->Get("MRDLoopbackTDC", MRDLoopbackTDC); BS->Set("MRDLoopbackTDC", MRDLoopbackTDC); m_data->Stores["ANNIEEvent"]->Get("MRDTriggerType", MRDTriggerType); diff --git a/UserTools/Unity.h b/UserTools/Unity.h index 1a77c1d5a..af90ecca3 100644 --- a/UserTools/Unity.h +++ b/UserTools/Unity.h @@ -193,3 +193,4 @@ #include "BeamQuality.h" #include "FitRWMWaveform.h" #include "LAPPDLoadTXT.h" +#include "LAPPDBSCharging.h" diff --git a/configfiles/BeamClusterAnalysis/ToolsConfig b/configfiles/BeamClusterAnalysis/ToolsConfig index b147e1080..9b7fee419 100644 --- a/configfiles/BeamClusterAnalysis/ToolsConfig +++ b/configfiles/BeamClusterAnalysis/ToolsConfig @@ -11,6 +11,7 @@ LAPPDStoreReorder LAPPDStoreReorder configfiles/LAPPDProcessedAna/ConfigStoreRea LAPPDTimeAlignment LAPPDTimeAlignment configfiles/LAPPDProcessedAna/ConfigPreProcess LAPPDBaseline LAPPDBaseline configfiles/LAPPDProcessedAna/ConfigPreProcess LAPPDThresReco LAPPDThresReco configfiles/LAPPDProcessedAna/ConfigPlot +#LAPPDPlots LAPPDPlots configfiles/LAPPDProcessedAna/ConfigPlot FitRWMWaveform FitRWMWaveform ./configfiles/BeamClusterAnalysis/FitRWMWaveformConfig diff --git a/configfiles/LAPPDASCIIAna/ConfigTXT b/configfiles/LAPPDASCIIAna/ConfigTXT index eda75e045..4cd12102a 100644 --- a/configfiles/LAPPDASCIIAna/ConfigTXT +++ b/configfiles/LAPPDASCIIAna/ConfigTXT @@ -23,11 +23,9 @@ DoPedSubtraction 1 Nboards 6 #Number of pedestal files to be read in #PedinputfileTXT ../Pedestals/LAPPD645839/P #PedinputfileTXT ../Pedestals/LAPPD40/P -PedinputfileTXT /pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/Pedestal/2023_LAPPD40/P +#PedinputfileTXT /pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/Pedestal/2023_LAPPD40/P -PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 - ReadStorePdeFile 0 loadFromStoreDirectly 0 @@ -37,12 +35,15 @@ loadFromStoreDirectly 0 DoPedSubtract 1 LAPPDLoadTXTVerbosity 1 #PedFileNameTXT ../Pedestals/LAPPD40/P -PedFileNameTXT /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/PEDS_ACDC_board +#PedFileNameTXT /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/PEDS_ACDC_board #DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2023-10-24/2023-10-24/LaserON_2300V_strip28/Ascii20232410_135201.txt #DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/NDfilterScan_15mV/OD1.0/Ascii20221702_100345.txt #DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/NDfilterScan_15mV/OD2.0/Ascii20221702_101913.txt #DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/NDfilterScan_15mV/OD3.0/Ascii20221702_103605.txt -DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/NDfilterScan_15mV/OD3.5/Ascii20221702_142206.txt +#DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/NDfilterScan_15mV/OD3.5/Ascii20221702_142206.txt + +PedFileNameTXT /pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/Pedestal/LAPPD151/pedestal_2024_8_15/P +DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD151/2024-08-21/forcedTrigger_nd1p8/Ascii20240408_124303.txt #LAPPDReorderData ReorderVerbosityLevel 0 diff --git a/configfiles/LAPPDASCIIAnaFor151/ConfigGeo b/configfiles/LAPPDASCIIAnaFor151/ConfigGeo new file mode 100644 index 000000000..ffe0ca918 --- /dev/null +++ b/configfiles/LAPPDASCIIAnaFor151/ConfigGeo @@ -0,0 +1,11 @@ +#LoadGeometry +verbosity 0 +LAPPDChannelCount 60 +FACCMRDGeoFile ./configfiles/LoadGeometry/FullMRDGeometry.csv +DetectorGeoFile ./configfiles/LoadGeometry/DetectorGeometrySpecs.csv +LAPPDGeoFile ./configfiles/LAPPDana/LAPPDGeometry.csv +TankPMTGeoFile ./configfiles/LoadGeometry/FullTankPMTGeometry.csv +TankPMTGainFile ./configfiles/LoadGeometry/ChannelSPEGains_BeamRun20192020.csv +AuxiliaryChannelFile ./configfiles/LoadGeometry/AuxChannels.csv +LAPPDMerging 0 + diff --git a/configfiles/LAPPDASCIIAnaFor151/ConfigPlot b/configfiles/LAPPDASCIIAnaFor151/ConfigPlot new file mode 100755 index 000000000..60bb7029d --- /dev/null +++ b/configfiles/LAPPDASCIIAnaFor151/ConfigPlot @@ -0,0 +1,133 @@ +oldLaser 0 #1 for old data, 0 for new trigger boards + +#LAPPDBaselineSubtract +BLSInputWavLabel AlignedLAPPDData +BaselineSubstractVerbosityLevel 0 +TrigChannel 5 #Specified channel the trigger signal will be on +LAPPDchannelOffset 1000 +LowBLfitrange 25; +HiBLfitrange 60; +TrigLowBLfitrange 30 +TrigHiBLfitrange 100 +BLSOutputWavLabel ABLSLAPPDData +oldLaserTrigAmpRange 40 + +#LAPPDFindPeak +FindPeakVerbosity 0 +FiltPeakInputWavLabel FiltLAPPDData +RawPeakInputWavLabel LAPPDWaveforms +BLSPeakInputWavLabel ABLSLAPPDData +FindPeakOutLabel SimpleRecoLAPPDPulses +TotThreshold 15. +MinimumTot 900. +Deltat 100. + +# General Parameters +Nsamples 256 +SampleSize 100 +NChannels 60 + + +outfile WaveForms_ablsub.root +NHistos 200 +SaveSingleStrip 0 +SingleStripNo 9 +plotLow -10 +plotHigh 20 + +#LAPPDPlotWaveForms2D +outfile2D RawDataWaveForms_2D.root +plot2DrecoPulseInputLabel thresRecoLAPPDPulses +plot2DrecoHitInputLabel thresRecoLAPPDHits +includeRecoPulses 1 +includeRecoHits 1 +plotAdditionalPart 1 +titleSize 0.04 +canvasMargin 0.15 +canvasTitleOffset 1 +#LAPPDSelectPlot2D +LAPPDSelectPlotWaveform2DLabel LAPPDWaveforms +SelectOutfile2D LAPPDSelectPlot.root +MRDTrackExistSelection 0 +verbosityPlot2D 10 +colorContour 255 +useDefaultPalette 1 +colorPalette 112 + + + +#LAPPDThresReco +LAPPDThresRecoVerbosity 0 +verbosity 0 +printHitsTXT 0 +threshold 10 +minPulseWidth 10 +#thresRecoInputWaveLabel AlignedLAPPDData +ThresRecoInputWaveLabel BLsubtractedLAPPDData +#thresRecoInputWaveLabel LAPPDWaveforms + +ThresRecoOutputPulseLabel LAPPDPulses +ThresRecoOutputHitLabel LAPPDHits +useMaxTime 1 # 1: use max bin as pulse time, 0: use gaus fit bin as pulse peak time +#signalSpeedOnStrip 0.6667 +signalSpeedOnStrip 0.567 #1.69982/2.99792 +triggerBoardDelay 0 +loadPrintMRDinfo 0 +useRange 0 #set this to 0 for using pulse start time as the saved pulse time, 1 for high, -1 for using peak time +plusClockBit 0 + +savePositionOnStrip 1 +LoadLAPPDMapInfo 1 + +#LAPPDStackStrip +verbosityStackStrip 0 +StackOutputFileName stacked.root +#StackInputWaveLabel BLsubtractedLAPPDData +StackInputWaveLabel RawLAPPDData +#StackInputWaveLabel LAPPDWaveforms +StackStripNumber 1 +StackStripSide 0 + +#LAPPDPlotWaveForms +NHistos 200 +SaveByChannel 0 +SaveSingleStrip 0 +SingleStripNo 1 +requireT0signal 0 + + +#LAPPDTreeMaker +treeMakerVerbosity 0 +treeMakerInputPulseLabel LAPPDPulses +treeMakerInputHitLabel LAPPDHits +treeMakerOutputFileName LAPPDTree.root + + +#LAPPDPlots +#LAPPDPlotInputWaveLabel BLsubtractedLAPPDData +#LAPPDPlotInputWaveLabel LAPPDWaveforms +#LAPPDPlotInputWaveLabel AlignedLAPPDData +#LAPPDPlotInputWaveLabel RawLAPPDData +LAPPDPlotInputWaveLabel BLandTALAPPDData + +LAPPDPlotsVerbosity 0 +CanvasXSubPlotNumber 2 +CanvasYSubPlotNumber 2 +canvasMargin 0.1 +drawHighThreshold 50 +drawLowThreshold -20 +BinHistMin -30 +BinHistMax 200 +BinHistNumber 100 + +CanvasWidth 1000 +CanvasHeight 500 + +maxDrawEventNumber 1000 + +DrawBinHist 1 +printEventNumber 1000 +printLAPPDNumber 1 +printEventWaveform 1 + +LoadLAPPDMap 1 diff --git a/configfiles/LAPPDASCIIAnaFor151/ConfigPreProcess b/configfiles/LAPPDASCIIAnaFor151/ConfigPreProcess new file mode 100755 index 000000000..d637eadcb --- /dev/null +++ b/configfiles/LAPPDASCIIAnaFor151/ConfigPreProcess @@ -0,0 +1,48 @@ +# General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +LAPPDchannelOffset 1000 +Folder ../Data/3655/ +#Folder ../Data/2022-06-10/ + +#LAPPDBaselineSubtract +BaselineSubstractVerbosityLevel 0 +TrigChannel1 1005 +TrigChannel2 1035 +#BLSInputWavLabel LAPPDWaveforms #LAPPDWaveforms +BLSInputWavLabel AlignedLAPPDData +#BLSInputWavLabel RawLAPPDData + +LowBLfitrange 50 +HiBLfitrange 100 +TrigLowBLfitrange 50 +TrigHiBLfitrange 100 +BLSOutputWavLabel BLsubtractedLAPPDData +oldLaserTrigAmpRange 40 + +#LAPPDFindT0 +FindT0Verbosity 0 +#FindT0InputWavLabel BLsubtractedLAPPDData +#FindT0InputWavLabel RawLAPPDData +FindT0InputWavLabel LAPPDWaveforms +OneBoardShift 0 +OneBoardShiftValue 16 +LoadLAPPDMap 1 + +TrigEarlyCut 20 +TrigLateCut 200 +T0channelNo 1005 +T0channelNo1 1005 +T0channelNo2 1005 +T0signalmax -130. +T0signalthreshold -50. +T0signalmaxOld 50. #Older data uses a positive going signal +T0signalthresholdOld 80. #Older data uses a positive going signal +T0offset 0 +FindT0OutputWavLabel AlignedLAPPDData +GlobalShiftT0 80 +#Added by Marc +Triggerdefault 5 +LAPPDOffset 1000 + diff --git a/configfiles/LAPPDASCIIAnaFor151/ConfigPreProcess2 b/configfiles/LAPPDASCIIAnaFor151/ConfigPreProcess2 new file mode 100755 index 000000000..b639f3d31 --- /dev/null +++ b/configfiles/LAPPDASCIIAnaFor151/ConfigPreProcess2 @@ -0,0 +1,68 @@ +# General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +LAPPDchannelOffset 1000 +Folder ../Data/3655/ +#Folder ../Data/2022-06-10/ + +#LAPPDBaselineSubtract +BaselineSubstractVerbosityLevel 0 +TrigChannel1 1005 +TrigChannel2 1035 +#BLSInputWavLabel LAPPDWaveforms #LAPPDWaveforms +BLSInputWavLabel AlignedLAPPDData +#BLSInputWavLabel RawLAPPDData + +LowBLfitrange 0 +HiBLfitrange 60 +TrigLowBLfitrange 50 +TrigHiBLfitrange 150 +BLSOutputWavLabel BLsubtractedLAPPDData +oldLaserTrigAmpRange 40 + +#LAPPDFindT0 +FindT0Verbosity 0 +FindT0InputWavLabel BLsubtractedLAPPDData +#FindT0InputWavLabel RawLAPPDData +#FindT0InputWavLabel LAPPDWaveforms + +OneBoardShift 0 +OneBoardShiftValue 16 +LoadLAPPDMap 1 + +TrigEarlyCut 20 +TrigLateCut 200 +T0channelNo 1005 +T0channelNo1 1005 +T0channelNo2 1005 +T0signalmax -100. +T0signalthreshold -50. +T0signalmaxOld 50. #Older data uses a positive going signal +T0signalthresholdOld 80. #Older data uses a positive going signal +T0offset 0 +#FindT0OutputWavLabel AlignedLAPPDData +FindT0OutputWavLabel BLandTALAPPDData + +GlobalShiftT0 80 +#Added by Marc +Triggerdefault 5 +LAPPDOffset 1000 + +#LAPPDPlotWaveForms +requireT0signal 0 +SaveByChannel 1 +PlotWavLabel BLsubtractedLAPPDData +#PlotWavLabel LAPPDWaveforms +outfile WaveForms_rawblsub.root +NHistos 400 +SaveSingleStrip 0 +SingleStripNo 9 + + + + + + + + diff --git a/configfiles/LAPPDASCIIAnaFor151/ConfigStoreReadIn b/configfiles/LAPPDASCIIAnaFor151/ConfigStoreReadIn new file mode 100755 index 000000000..52521f447 --- /dev/null +++ b/configfiles/LAPPDASCIIAnaFor151/ConfigStoreReadIn @@ -0,0 +1,23 @@ +# General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +NUM_VECTOR_PPS 16 #Fixed PPS vector size +NUM_VECTOR_DATA 7795 #Fixed DATA vector size +NUM_VECTOR_METADATA 103 #Fixed META vector size +LAPPDchannelOffset 1000 +NChannels 30 + + + +#LAPPDReorderData +LAPPDReorderVerbosityLevel 0 +ReorderInputWavLabel RawLAPPDData +ReorderOutputWavLabel LAPPDWaveforms +DelayOffset 0 +GlobalShift 0 + +NUM_VECTOR_DATA 7795 +NUM_VECTOR_PPS 16 +SelectSingleLAPPD false +SelectedLAPPD 0 diff --git a/configfiles/LAPPDASCIIAnaFor151/ConfigTXT b/configfiles/LAPPDASCIIAnaFor151/ConfigTXT new file mode 100644 index 000000000..2514c8b44 --- /dev/null +++ b/configfiles/LAPPDASCIIAnaFor151/ConfigTXT @@ -0,0 +1,93 @@ +#General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +NUM_VECTOR_PPS 16 #Fixed PPS vector size +NUM_VECTOR_DATA 7795 #Fixed DATA vector size +NUM_VECTOR_METADATA 103 #Fixed META vector size +LAPPDchannelOffset 1000 +NChannels 30 + +LAPPDStoreReadInVerbosity 0 + +mergingModeReadIn 0 +RawDataInputWavLabel RawWaveform +RawDataOutputWavLabel RawLAPPDData +BoardIndexLabel BoardIndex #Label of the vector of read out boards + +PsecReceiveMode 0 +MultiLAPPDMap 1 +stopEntries 10000000000 + +DoPedSubtraction 1 +Nboards 6 #Number of pedestal files to be read in +#PedinputfileTXT ../Pedestals/LAPPD645839/P +#PedinputfileTXT ../Pedestals/LAPPD40/P +#PedinputfileTXT /pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/Pedestal/2023_LAPPD40/P + + +ReadStorePdeFile 0 +loadFromStoreDirectly 0 + + +#LAPPDLoadTXT + +DoPedSubtract 1 +LAPPDLoadTXTVerbosity 1 +#PedFileNameTXT ../Pedestals/LAPPD40/P +#PedFileNameTXT /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/PEDS_ACDC_board +#DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2023-10-24/2023-10-24/LaserON_2300V_strip28/Ascii20232410_135201.txt +#DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/NDfilterScan_15mV/OD1.0/Ascii20221702_100345.txt +#DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/NDfilterScan_15mV/OD2.0/Ascii20221702_101913.txt +#DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/NDfilterScan_15mV/OD3.0/Ascii20221702_103605.txt +#DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD40/2022-02-17_LaserNDfilterScan/NDfilterScan_15mV/OD3.5/Ascii20221702_142206.txt + + +# LAPPD 151 +PedFileNameTXT /pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/Pedestal/LAPPD151/pedestal_2024_8_15/P +#DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD151/2024-08-21/forcedTrigger_nd1p8/Ascii20240408_124303.txt +#DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD151/2024-08-21/forcedTrigger_nd2p2/Ascii20240408_112022.txt +#DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD151/2024-08-21/forcedTrigger_nd2p0/Ascii20240408_114859.txt +DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD151/2024-08-22/forcedTrigger_nd3p5/Ascii20240508_144350.txt +#DataFileName /pnfs/annie/persistent/LAPPDData/LAPPD151/2024-08-22/forcedTrigger_nd4p5/Ascii20240508_153057.txt + +oldLaser 0 + +#LAPPDReorderData +ReorderVerbosityLevel 0 +#ReorderInputWavLabel RawLAPPDData +ReorderInputWavLabel AlignedLAPPDData +ReorderOutputWavLabel LAPPDWaveforms +DelayOffset 0 +GlobalShift 180 + +ReadStore 0 +NUM_VECTOR_DATA 7795 +NUM_VECTOR_PPS 16 +OutputWavLabel RawLAPPDData +SelectSingleLAPPD false +SelectedLAPPD 0 +loadPSEC 1 +loadPPS 0 +loadOffsets 0 +LoadBuiltPPSInfo 1 +num_vector_data 7795 +num_vector_pps 16 + +#LAPPDTreeMaker +LoadPulse 1 +LoadHit 1 +LoadWaveform 1 +LoadLAPPDDataTimeStamp 1 +LoadPPSTimestamp 0 +LoadRunInfoRaw 0 +LoadRunInfoANNIEEvent 1 + +treeMakerVerbosity 0 +MultiLAPPDMapTreeMaker 1 +treeMakerInputPulseLabel LAPPDPulses +treeMakerInputHitLabel LAPPDHits +treeMakerOutputFileName LAPPDTree_processedAna.root +LoadTriggerInfo 0 +LoadGroupOption beam +LoadGroupedTriggerInfo 1 diff --git a/configfiles/LAPPDASCIIAnaFor151/Configs b/configfiles/LAPPDASCIIAnaFor151/Configs new file mode 100644 index 000000000..1f3cadc0e --- /dev/null +++ b/configfiles/LAPPDASCIIAnaFor151/Configs @@ -0,0 +1,74 @@ +#General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +NUM_VECTOR_PPS 16 #Fixed PPS vector size +NUM_VECTOR_DATA 7795 #Fixed DATA vector size +NUM_VECTOR_METADATA 103 #Fixed META vector size +LAPPDchannelOffset 1000 +NChannels 30 + +LAPPDStoreReadInVerbosity 0 + +mergingModeReadIn 0 +RawDataInputWavLabel RawWaveform +RawDataOutputWavLabel RawLAPPDData +BoardIndexLabel BoardIndex #Label of the vector of read out boards + +PsecReceiveMode 0 +MultiLAPPDMap 1 +stopEntries 10000000000 + +DoPedSubtraction 1 +Nboards 6 #Number of pedestal files to be read in +#PedinputfileTXT ../Pedestals/LAPPD645839/P +PedinputfileTXT ../Pedestals/LAPPD40/P + +PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 + +ReadStorePdeFile 0 +loadFromStoreDirectly 0 + +Pedinputfile1 ../Pedestals/PEDS_ACDC_board0.txt +Pedinputfile2 ../Pedestals/PEDS_ACDC_board1.txt + +#LAPPDReorderData +ReorderVerbosityLevel 0 +#ReorderInputWavLabel RawLAPPDData +ReorderInputWavLabel AlignedLAPPDData +ReorderOutputWavLabel LAPPDWaveforms +DelayOffset 0 +GlobalShift 180 + +ReadStore 0 +NUM_VECTOR_DATA 7795 +NUM_VECTOR_PPS 16 +OutputWavLabel RawLAPPDData +SelectSingleLAPPD false +SelectedLAPPD 0 +loadPSEC 1 +loadPPS 0 +loadOffsets 0 +LoadBuiltPPSInfo 1 +num_vector_data 7795 +num_vector_pps 16 + +#LAPPDTreeMaker +LoadPulse 1 +LoadHit 1 +LoadWaveform 1 +LoadLAPPDDataTimeStamp 1 +LoadPPSTimestamp 0 +LoadRunInfoRaw 0 +LoadRunInfoANNIEEvent 1 + +treeMakerVerbosity 0 +MultiLAPPDMapTreeMaker 0 +treeMakerInputPulseLabel LAPPDPulses +treeMakerInputHitLabel LAPPDHits +treeMakerOutputFileName LAPPDTree_ASCIIAna.root +LoadTriggerInfo 0 +LoadGroupOption beam +LoadGroupedTriggerInfo 1 +loadPrintMRDinfo 0 + diff --git a/configfiles/LAPPDASCIIAnaFor151/TimeClusteringConfig b/configfiles/LAPPDASCIIAnaFor151/TimeClusteringConfig new file mode 100644 index 000000000..e778247fc --- /dev/null +++ b/configfiles/LAPPDASCIIAnaFor151/TimeClusteringConfig @@ -0,0 +1,13 @@ +#TimeClustering config file + +verbosity 0 +MinDigitsForTrack 3 +MaxMrdSubEventDuration 30 +MinSubeventTimeSep 30 +MakeMrdDigitTimePlot 0 +LaunchTApplication 0 +IsData 1 +#OutputROOTFile TimeClustering_MRDTest28_cluster40ns +OutputROOTFile STEC_TimeClusteringOut +MapChankey_WCSimID ./configfiles/SimpleTankEnergyCalibrator/MRD_Chankey_WCSimID.dat + diff --git a/configfiles/LAPPDASCIIAnaFor151/ToolChainConfig b/configfiles/LAPPDASCIIAnaFor151/ToolChainConfig new file mode 100644 index 000000000..83eadfc77 --- /dev/null +++ b/configfiles/LAPPDASCIIAnaFor151/ToolChainConfig @@ -0,0 +1,24 @@ + +#ToollChain dynamic setup file + +##### Runtime Paramiters ##### +verbose 1 ## Verbosity level of ToolChain +error_level 0 # 0= do not exit, 1= exit on unhandeled errors only, 2= exit on unhandeled errors and handeled errors +attempt_recover 1 ## 1= will attempt to finalise if an execute fails + +###### Logging ##### +log_mode Interactive # Interactive=cout , Remote= remote logging system "serservice_name Remote_Logging" , Local = local file log; +log_local_path ./log +log_service LogStore + +###### Service discovery ##### Ignore these settings for local analysis +service_publish_sec -1 +service_kick_sec -1 + +##### Tools To Add ##### +Tools_File configfiles/LAPPDASCIIAnaFor151/ToolsConfig ## list of tools to run and their config files + +##### Run Type ##### +Inline -1 ## number of Execute steps in program, -1 infinite loop that is ended by user +Interactive 0 ## set to 1 if you want to run the code interactively + diff --git a/configfiles/LAPPDASCIIAnaFor151/ToolsConfig b/configfiles/LAPPDASCIIAnaFor151/ToolsConfig new file mode 100644 index 000000000..f2f465487 --- /dev/null +++ b/configfiles/LAPPDASCIIAnaFor151/ToolsConfig @@ -0,0 +1,18 @@ +LoadGeometry LoadGeometry configfiles/LoadGeometry/LoadGeometryConfig + + +LAPPDLoadTXT LAPPDLoadTXT configfiles/LAPPDASCIIAnaFor151/ConfigTXT + +LAPPDStoreReorder LAPPDStoreReorder configfiles/LAPPDASCIIAnaFor151/ConfigStoreReadIn + +LAPPDTimeAlignment LAPPDTimeAlignment configfiles/LAPPDASCIIAnaFor151/ConfigPreProcess +LAPPDBaseline LAPPDBaseline configfiles/LAPPDASCIIAnaFor151/ConfigPreProcess + +secondLAPPDTimeAlignment LAPPDTimeAlignment configfiles/LAPPDASCIIAnaFor151/ConfigPreProcess2 + +LAPPDPlots LAPPDPlots configfiles/LAPPDASCIIAnaFor151/ConfigPlot + + +LAPPDThresReco LAPPDThresReco configfiles/LAPPDASCIIAnaFor151/ConfigPlot + +LAPPDTreeMaker LAPPDTreeMaker configfiles/LAPPDASCIIAnaFor151/Configs diff --git a/configfiles/LAPPDProcessedAna/ConfigPlot b/configfiles/LAPPDProcessedAna/ConfigPlot index 73c090663..5156f6b55 100755 --- a/configfiles/LAPPDProcessedAna/ConfigPlot +++ b/configfiles/LAPPDProcessedAna/ConfigPlot @@ -18,7 +18,7 @@ FiltPeakInputWavLabel FiltLAPPDData RawPeakInputWavLabel LAPPDWaveforms BLSPeakInputWavLabel ABLSLAPPDData FindPeakOutLabel SimpleRecoLAPPDPulses -TotThreshold 15. +TotThreshold 7. MinimumTot 900. Deltat 100. @@ -69,7 +69,7 @@ LAPPDThresRecoVerbosity 0 verbosity 0 printHitsTXT 0 threshold 10 -minPulseWidth 10 +minPulseWidth 5 #thresRecoInputWaveLabel AlignedLAPPDData ThresRecoInputWaveLabel BLsubtractedLAPPDData #thresRecoInputWaveLabel LAPPDWaveforms diff --git a/configfiles/LAPPDProcessedAna/ConfigPreProcess b/configfiles/LAPPDProcessedAna/ConfigPreProcess index 11cb9b98a..c1a0a8830 100755 --- a/configfiles/LAPPDProcessedAna/ConfigPreProcess +++ b/configfiles/LAPPDProcessedAna/ConfigPreProcess @@ -41,7 +41,9 @@ T0signalmaxOld 50. #Older data uses a positive going signal T0signalthresholdOld 80. #Older data uses a positive going signal T0offset 0 FindT0OutputWavLabel AlignedLAPPDData -GlobalShiftT0 80 +GlobalShiftT0 0 # for 2023 data +#GlobalShiftT0 80 # for 2024 data + #Added by Marc Triggerdefault 5 LAPPDOffset 1000 diff --git a/configfiles/LAPPDProcessedAna/ConfigTXT b/configfiles/LAPPDProcessedAna/ConfigTXT new file mode 100644 index 000000000..a982c4278 --- /dev/null +++ b/configfiles/LAPPDProcessedAna/ConfigTXT @@ -0,0 +1,72 @@ +#General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +NUM_VECTOR_PPS 16 #Fixed PPS vector size +NUM_VECTOR_DATA 7795 #Fixed DATA vector size +NUM_VECTOR_METADATA 103 #Fixed META vector size +LAPPDchannelOffset 1000 +NChannels 30 + +LAPPDStoreReadInVerbosity 0 + +mergingModeReadIn 0 +RawDataInputWavLabel RawWaveform +RawDataOutputWavLabel RawLAPPDData +BoardIndexLabel BoardIndex #Label of the vector of read out boards + +PsecReceiveMode 0 +MultiLAPPDMap 1 +stopEntries 10000000000 + +DoPedSubtraction 1 +Nboards 6 #Number of pedestal files to be read in +#PedinputfileTXT ../Pedestals/LAPPD645839/P +PedinputfileTXT ../Pedestals/LAPPD40/P + +PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 + +ReadStorePdeFile 0 +loadFromStoreDirectly 0 + +Pedinputfile1 ../Pedestals/PEDS_ACDC_board0.txt +Pedinputfile2 ../Pedestals/PEDS_ACDC_board1.txt + +#LAPPDReorderData +ReorderVerbosityLevel 0 +#ReorderInputWavLabel RawLAPPDData +ReorderInputWavLabel AlignedLAPPDData +ReorderOutputWavLabel LAPPDWaveforms +DelayOffset 0 +GlobalShift 180 + +ReadStore 0 +NUM_VECTOR_DATA 7795 +NUM_VECTOR_PPS 16 +OutputWavLabel RawLAPPDData +SelectSingleLAPPD false +SelectedLAPPD 0 +loadPSEC 1 +loadPPS 0 +loadOffsets 0 +LoadBuiltPPSInfo 1 +num_vector_data 7795 +num_vector_pps 16 + +#LAPPDTreeMaker +LoadPulse 1 +LoadHit 1 +LoadWaveform 1 +LoadLAPPDDataTimeStamp 1 +LoadPPSTimestamp 0 +LoadRunInfoRaw 0 +LoadRunInfoANNIEEvent 1 + +treeMakerVerbosity 0 +MultiLAPPDMapTreeMaker 1 +treeMakerInputPulseLabel LAPPDPulses +treeMakerInputHitLabel LAPPDHits +treeMakerOutputFileName LAPPDTree_processedAna.root +LoadTriggerInfo 0 +LoadGroupOption beam +LoadGroupedTriggerInfo 1 diff --git a/configfiles/LAPPDProcessedAna/Configs b/configfiles/LAPPDProcessedAna/Configs index 24cc40ec3..e8ad7c851 100644 --- a/configfiles/LAPPDProcessedAna/Configs +++ b/configfiles/LAPPDProcessedAna/Configs @@ -21,13 +21,11 @@ stopEntries 10000000000 DoPedSubtraction 1 Nboards 6 #Number of pedestal files to be read in - -PedinputfileTXT ../Pedestals/LAPPD645839/P +#PedinputfileTXT ../Pedestals/LAPPD645839/P #PedinputfileTXT ../Pedestals/LAPPD40/P +PedinputfileTXT /pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/Pedestal/2022_LAPPD40/P -PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 - ReadStorePdeFile 0 loadFromStoreDirectly 0 diff --git a/configfiles/LAPPDProcessedAna/ToolChainConfig b/configfiles/LAPPDProcessedAna/ToolChainConfig index 577961b75..3c8060cf1 100644 --- a/configfiles/LAPPDProcessedAna/ToolChainConfig +++ b/configfiles/LAPPDProcessedAna/ToolChainConfig @@ -19,6 +19,6 @@ service_kick_sec -1 Tools_File configfiles/LAPPDProcessedAna/ToolsConfig ## list of tools to run and their config files ##### Run Type ##### -Inline 50 ## number of Execute steps in program, -1 infinite loop that is ended by user +Inline 20 ## number of Execute steps in program, -1 infinite loop that is ended by user Interactive 0 ## set to 1 if you want to run the code interactively diff --git a/configfiles/LAPPDProcessedAna/list.txt b/configfiles/LAPPDProcessedAna/list.txt index c202b69e1..8894dadb6 100644 --- a/configfiles/LAPPDProcessedAna/list.txt +++ b/configfiles/LAPPDProcessedAna/list.txt @@ -1,11 +1,15 @@ -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4804 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4805 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4825 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4831 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4839 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4843 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4852 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4856 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4880 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4890 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/combined_v2/FilteredData/FilteredAllLAPPDData_4897 +/pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/2023_LAPPD40/AllLAPPD/FilteredAllLAPPDData_4200_0_106 +/pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/2023_LAPPD40/AllLAPPD/FilteredAllLAPPDData_4208_0_15 +/pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/2023_LAPPD40/AllLAPPD/FilteredAllLAPPDData_4210_0_275 +/pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/2023_LAPPD40/AllLAPPD/FilteredAllLAPPDData_4213_0_499 +/pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/2023_LAPPD40/AllLAPPD/FilteredAllLAPPDData_4213_500_903 +/pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/2023_LAPPD40/AllLAPPD/FilteredAllLAPPDData_4215_0_42 +/pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/2023_LAPPD40/AllLAPPD/FilteredAllLAPPDData_4217_0_499 +/pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/2023_LAPPD40/AllLAPPD/FilteredAllLAPPDData_4217_500_507 +/pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/2023_LAPPD40/AllLAPPD/FilteredAllLAPPDData_4218_0_262 +/pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/2023_LAPPD40/AllLAPPD/FilteredAllLAPPDData_4222_0_381 +/pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/2023_LAPPD40/AllLAPPD/FilteredAllLAPPDData_4223_0_499 +/pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/2023_LAPPD40/AllLAPPD/FilteredAllLAPPDData_4223_500_870 +/pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/2023_LAPPD40/AllLAPPD/FilteredAllLAPPDData_4224_0_337 +/pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/2023_LAPPD40/AllLAPPD/FilteredAllLAPPDData_4228_0_175 +/pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/2023_LAPPD40/AllLAPPD/FilteredAllLAPPDData_4229_0_345 diff --git a/configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig b/configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig index 242a2d558..7c98f485e 100644 --- a/configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig +++ b/configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig @@ -1,7 +1,7 @@ -FilterVerbosity 0 +FilterVerbosity 2 saveAllLAPPDEvents 1 -savePMTClusterEvents 0 +savePMTClusterEvents 1 filterType MRDtrack diff --git a/configfiles/LAPPDProcessedFilter/list.txt b/configfiles/LAPPDProcessedFilter/list.txt index dc3e96f2e..f4444db72 100644 --- a/configfiles/LAPPDProcessedFilter/list.txt +++ b/configfiles/LAPPDProcessedFilter/list.txt @@ -1,300 +1,2 @@ -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p2 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p3 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p4 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p5 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p6 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p7 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p8 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p9 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p10 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p11 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p12 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p13 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p14 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p15 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p16 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p17 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p18 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p19 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p20 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p21 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p22 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p23 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p24 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p25 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p26 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p27 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p28 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p29 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p30 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p31 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p32 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p33 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p34 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p35 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p36 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p37 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p38 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p39 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p40 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p41 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p42 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p43 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p44 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p45 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p46 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p47 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p48 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p49 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p50 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p51 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p52 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p53 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p54 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p55 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p56 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p57 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p58 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p59 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p60 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p61 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p62 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p63 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p64 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p65 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p66 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p67 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p68 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p69 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p70 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p71 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p72 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p73 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p74 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p75 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p76 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p77 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p78 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p79 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p80 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p81 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p82 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p83 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p84 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p85 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p86 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p87 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p88 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p89 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p90 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p91 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p92 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p93 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p94 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p95 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p96 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p97 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p98 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p99 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p100 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p101 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p102 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p103 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p104 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p105 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p106 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p107 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p108 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p109 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p110 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p111 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p112 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p113 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p114 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p115 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p116 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p117 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p118 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p119 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p120 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p121 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p122 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p123 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p124 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p125 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p126 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p127 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p128 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p129 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p130 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p131 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p132 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p133 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p134 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p135 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p136 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p137 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p138 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p139 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p140 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p141 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p142 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p143 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p144 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p145 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p146 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p147 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p148 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p149 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p150 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p151 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p152 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p153 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p154 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p155 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p156 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p157 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p158 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p159 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p160 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p161 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p162 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p163 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p164 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p165 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p166 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p167 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p168 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p169 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p170 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p171 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p172 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p173 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p174 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p175 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p176 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p177 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p179 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p180 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p181 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p182 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p183 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p184 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p185 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p186 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p191 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p192 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p193 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p194 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p195 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p196 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p197 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p198 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p203 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p204 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p205 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p206 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p207 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p209 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p210 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p211 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p212 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p213 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p214 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p215 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p216 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p221 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p222 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p223 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p224 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p225 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p227 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p228 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p229 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p230 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p231 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p233 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p234 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p235 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p236 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p237 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p257 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p258 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p259 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p260 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p261 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p263 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p264 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p265 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p266 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p267 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p268 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p269 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p270 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p278 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p279 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p280 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p281 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p282 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p283 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p284 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p285 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p286 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p287 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p288 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p290 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p291 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p292 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p293 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p294 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p299 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p300 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p301 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p302 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p303 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p308 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p309 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p310 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p311 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p312 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p326 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p327 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p328 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p329 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p330 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p338 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p339 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p340 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p341 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p342 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p343 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p344 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p345 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p347 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p348 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p349 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p350 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p351 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p353 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p354 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p355 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p356 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p357 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p358 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p359 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p360 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p368 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p369 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p370 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p371 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p372 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p374 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p375 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p376 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p377 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p378 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p380 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p381 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p382 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p383 -/pnfs/annie/persistent/users/yuefeng/EventBuildingV2/output_v2/4843/ProcessedData_PMTMRDLAPPD_R4843S0p384 +/exp/annie/app/users/yuefeng/MyForkANNIE/MyForkRewiriting/testPRTA/ToolAnalysis/ProcessedData_PMTMRDLAPPD_R3832S0p131 +/exp/annie/app/users/yuefeng/MyForkANNIE/MyForkRewiriting/testPRTA/ToolAnalysis/ProcessedData_PMTMRDLAPPD_R3832S0p132 From 9340b0ade4762e4387c5b552674e525e94623861 Mon Sep 17 00:00:00 2001 From: Yue Date: Sat, 31 Aug 2024 00:25:58 -0500 Subject: [PATCH 097/163] Don't use mask file, save all triggers Changes to be committed: modified: configfiles/PreProcessTrigOverlap/TriggerDataDecoderConfig --- configfiles/PreProcessTrigOverlap/TriggerDataDecoderConfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configfiles/PreProcessTrigOverlap/TriggerDataDecoderConfig b/configfiles/PreProcessTrigOverlap/TriggerDataDecoderConfig index 00b6bc1e6..96bc8670a 100644 --- a/configfiles/PreProcessTrigOverlap/TriggerDataDecoderConfig +++ b/configfiles/PreProcessTrigOverlap/TriggerDataDecoderConfig @@ -1,5 +1,5 @@ -verbosity 2 -TriggerMaskFile ./configfiles/EventBuilder/DefaultTriggerMask.txt +verbosity 0 +#TriggerMaskFile ./configfiles/EventBuilder/DefaultTriggerMask.txt StoreTrigOverlap 1 ReadTrigOverlap 0 UseCStore 0 From 7f935be34e2c671d550fd6229708b2e1a185e2fa Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Tue, 22 Oct 2024 12:35:17 -0500 Subject: [PATCH 098/163] Update PhaseIIADCHitFinder.cpp dumb fix --- UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp b/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp index 103c67fdc..4b0d1ab25 100755 --- a/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp +++ b/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp @@ -949,7 +949,7 @@ std::vector PhaseIIADCHitFinder::find_pulses_bythreshold( // Store the freshly made pulse in the vector of found pulses pulses.emplace_back(channel_key, ( pulse_start_sample * NS_PER_ADC_SAMPLE )-timing_offset, - (peak_sample * NS_PER_ADC_SAMPLE)-timing_offset, + (hit_time * NS_PER_ADC_SAMPLE)-timing_offset, calibrated_minibuffer_data.GetBaseline(), calibrated_minibuffer_data.GetSigmaBaseline(), raw_area, max_ADC, calibrated_amplitude, charge); From d65adbe97665d7fcac90ed37c7260e7e93deecd9 Mon Sep 17 00:00:00 2001 From: Yue Date: Wed, 23 Oct 2024 12:24:02 -0500 Subject: [PATCH 099/163] Add LAPPD waveform to ANNIEEventTreeMaker Force matching of MRD and LAPPD ad the end of a part file for AmBe runs Update the trigger grouping --- FilterLAPPDEvents | 1 - .../ANNIEEventTreeMaker.cpp | 64 ++++++ .../ANNIEEventTreeMaker/ANNIEEventTreeMaker.h | 14 +- UserTools/EBLAPPD/EBLAPPD.cpp | 5 +- UserTools/EBLAPPD/EBLAPPD.h | 11 +- UserTools/EBLAPPD/README.md | 35 +++- UserTools/EBLoadRaw/EBLoadRaw.cpp | 37 +++- UserTools/EBLoadRaw/EBLoadRaw.h | 11 +- UserTools/EBLoadRaw/README.md | 22 +-- UserTools/EBMRD/EBMRD.cpp | 4 +- UserTools/EBMRD/EBMRD.h | 20 +- UserTools/EBMRD/README.md | 35 +++- UserTools/EBPMT/EBPMT.cpp | 4 +- UserTools/EBPMT/EBPMT.h | 12 +- UserTools/EBPMT/README.md | 43 +++- UserTools/EBSaver/EBSaver.h | 10 +- UserTools/EBSaver/README.md | 29 ++- .../EBTriggerGrouper/EBTriggerGrouper.cpp | 16 +- UserTools/EBTriggerGrouper/EBTriggerGrouper.h | 16 +- UserTools/EBTriggerGrouper/README.md | 32 ++- .../ProcessedLAPPDFilter.cpp | 184 +++++++++++++++++- .../ProcessedLAPPDFilter.h | 3 + .../TriggerDataDecoder/TriggerDataDecoder.cpp | 1 + .../ANNIEEventTreeMakerConfig | 3 +- .../ANNIEEventTreeMakerConfig_cosmic | 30 +++ .../BeamClusterAnalysis/configLAPPD.py | 39 ++++ configfiles/BeamClusterAnalysis/my_inputs.txt | 12 +- configfiles/EventBuilderV2/EBMRDConfig | 3 +- configfiles/EventBuilderV2/EBPMTConfig | 6 +- .../EventBuilderV2/EBTriggerGrouperConfig | 5 +- configfiles/EventBuilderV2/ToolsConfig | 2 +- configfiles/EventBuilderV2/my_files.txt | 4 +- configfiles/LAPPDASCIIAna/ConfigPlot | 12 +- configfiles/LAPPDASCIIAna/ConfigPreProcess | 2 +- configfiles/LAPPDASCIIAna/ConfigTXT | 21 +- configfiles/LAPPDASCIIAna/ToolChainConfig | 2 +- configfiles/LAPPDASCIIAnaFor151/ConfigPlot | 2 +- configfiles/LAPPDASCIIAnaFor151/ConfigTXT | 19 +- configfiles/LAPPDProcessedAna/ConfigPlot | 4 +- .../ProcessedLAPPDFilterConfig | 12 +- configfiles/LAPPDProcessedFilter/list.txt | 3 +- configfiles/LAPPD_EB/Configs | 2 +- configfiles/LAPPD_EB/my_files.txt | 56 +----- .../PreProcessTrigOverlap/CreateMyList.sh | 0 .../PreProcessTrigOverlap/LoadRawDataConfig | 2 +- .../PreProcessTrigOverlap/my_files.txt | 15 +- configfiles/PrintANNIEEvent/ToolChainConfig | 2 +- configfiles/PrintANNIEEvent/my_inputs.txt | 2 +- 48 files changed, 635 insertions(+), 234 deletions(-) delete mode 120000 FilterLAPPDEvents create mode 100644 configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig_cosmic create mode 100644 configfiles/BeamClusterAnalysis/configLAPPD.py mode change 100644 => 100755 configfiles/PreProcessTrigOverlap/CreateMyList.sh diff --git a/FilterLAPPDEvents b/FilterLAPPDEvents deleted file mode 120000 index a369f0f49..000000000 --- a/FilterLAPPDEvents +++ /dev/null @@ -1 +0,0 @@ -configfiles/FilterLAPPDEvents/ToolChainConfig \ No newline at end of file diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index 5f7f4c6ee..9674cd231 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -43,6 +43,7 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) m_variables.Get("SiPMPulseInfo_fill", SiPMPulseInfo_fill); m_variables.Get("LAPPDReco_fill", LAPPDReco_fill); m_variables.Get("LAPPD_PPS_fill", LAPPD_PPS_fill); + m_variables.Get("LAPPD_Waveform_fill", LAPPD_Waveform_fill); std::string output_filename = "ANNIEEventTree.root"; m_variables.Get("OutputFile", output_filename); @@ -263,6 +264,14 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) */ } + LAPPDWaveformInputLabel = "BLsubtractedLAPPDData"; + m_variables.Get("LAPPDWaveformInputLabel", LAPPDWaveformInputLabel); + if (LAPPD_Waveform_fill) + { + //Log("ANNIEEventTreeMaker Tool: LAPPDWaveformInputLabel = " + LAPPDWaveformInputLabel, 0, ANNIEEventTreeMakerVerbosity); + fANNIETree->Branch("LAPPDWaveform", &fLAPPDWaveforms); + } + if (MRDHitInfo_fill) { fANNIETree->Branch("MRDHitClusterIndex", &fMRDHitClusterIndex); @@ -521,6 +530,10 @@ bool ANNIEEventTreeMaker::Execute() { LoadLAPPDInfo(); } + if (LAPPD_Waveform_fill) + { + FillLAPPDWaveform(); + } //****************************** Fill MRD Info *************************************// if (MRDHitInfo_fill) @@ -2407,3 +2420,54 @@ void ANNIEEventTreeMaker::RecoSummary() std::cout << " RecoStatus = " << fRecoStatus << std::endl; std::cout << std::endl; } + +void ANNIEEventTreeMaker::FillLAPPDWaveform() +{ + //Log("ANNIEEventTreeMaker: Filling LAPPD Waveform", 0, ANNIEEventTreeMakerVerbosity); + + fLAPPDWaveforms.clear(); + + fLAPPDWaveforms = std::vector>(60*3, std::vector(256, 0.0)); + + // m_data->Stores["ANNIEEvent"]->Print(false); + + // cout<<"LAPPDWaveformInputLabel: "<>> lappdData; // waveform data + m_data->Stores["ANNIEEvent"]->Get(LAPPDWaveformInputLabel, lappdData); + + std::map>>::iterator it; + for (it = lappdData.begin(); it != lappdData.end(); it++) + { + + // get the waveforms from channel number + unsigned long channel = it->first; + channel = channel % 1000 + 1000; + if ((channel % 1000) % 30 == 5) + continue; + Waveform waveforms = it->second.at(0); + vector wav = *waveforms.GetSamples(); + vector wave = wav; + if (wave.size() != 256) + { + cout << "ANNIEEventTreeMaker: Found a bug waveform at channel " << channel << ", size is " << wave.size() << endl; + continue; + } + + for (int i = 0; i < wave.size(); i++) + { + wave.at(i) = -wave.at(i); + } + + int LAPPD_ID = static_cast((channel - 1000) / 60); + Channel *chan = geom->GetChannel(channel); + int stripno = chan->GetStripNum(); + int stripSide = chan->GetStripSide(); + + // fill this waveform to fLAPPDWaveforms[LAPPD_ID][stripno+stripSide*30][n] + for (int n = 0; n < 256; n++) + { + fLAPPDWaveforms[LAPPD_ID*60+stripno + stripSide * 30][n] = wave.at(n); + } + } +} diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h index 26f4418b6..8a5f3604c 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h @@ -24,15 +24,15 @@ #include "PsecData.h" #include "LAPPDPulse.h" #include "LAPPDHit.h" +#include "Geometry.h" /** * \class ANNIEEventTreeMaker * - * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. * - * $Author: B.Richards $ - * $Date: 2019/05/28 10:44:00 $ - * Contact: b.richards@qmul.ac.uk + * $Author: Yue Feng $ + * $Date: 2024/8 $ + * Contact: yuef@iastate.edu */ class ANNIEEventTreeMaker : public Tool { @@ -63,6 +63,7 @@ class ANNIEEventTreeMaker : public Tool void LoadMRDInfo(); void LoadLAPPDRecoInfo(); void FillLAPPDRecoInfo(); + void FillLAPPDWaveform(); bool FillMCTruthInfo(); bool FillTankRecoInfo(); @@ -111,6 +112,7 @@ class ANNIEEventTreeMaker : public Tool bool LAPPDData_fill = 1; bool RWMBRF_fill = 1; bool LAPPD_PPS_fill = 1; + bool LAPPD_Waveform_fill = 1; // What reco information will be filled bool MCTruth_fill = 0; // Output the MC truth information @@ -272,6 +274,10 @@ class ANNIEEventTreeMaker : public Tool vector waveformMaxNearingValue; vector waveformMaxTimeBinValue; + // LAPPD waveform Fill + string LAPPDWaveformInputLabel; + vector> fLAPPDWaveforms; + // finished **************************************************** // tank cluster information diff --git a/UserTools/EBLAPPD/EBLAPPD.cpp b/UserTools/EBLAPPD/EBLAPPD.cpp index 6875774fb..97c657453 100644 --- a/UserTools/EBLAPPD/EBLAPPD.cpp +++ b/UserTools/EBLAPPD/EBLAPPD.cpp @@ -74,7 +74,10 @@ bool EBLAPPD::Execute() m_data->vars.Get("StopLoop", stopLoop); int runNum = thisRunNum; m_data->vars.Get("RunNumber", thisRunNum); - if (stopLoop || runNum != thisRunNum || exeNum % exePerMatch == 0) + bool ForceLAPPDMatching = false; + m_data->CStore.Get("ForceLAPPDMatching", ForceLAPPDMatching); + + if (stopLoop || runNum != thisRunNum || exeNum % exePerMatch == 0 || ForceLAPPDMatching) { Log("EBLAPPD: exeNum = " + std::to_string(exeNum) + ". Doing matching", v_message, verbosityEBLAPPD); if (matchToAllTriggers) diff --git a/UserTools/EBLAPPD/EBLAPPD.h b/UserTools/EBLAPPD/EBLAPPD.h index 03fa49b97..a1dd6cfa3 100644 --- a/UserTools/EBLAPPD/EBLAPPD.h +++ b/UserTools/EBLAPPD/EBLAPPD.h @@ -9,14 +9,14 @@ #include "BoostStore.h" /** - * \class EBLAPPD + * \class EBPMT * - * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. + * $Author: Yue Feng $ + * $Date: 2024/04 $ + * Contact: yuef@iaistate.edu * - * $Author: B.Richards $ - * $Date: 2019/05/28 10:44:00 $ - * Contact: b.richards@qmul.ac.uk */ + class EBLAPPD : public Tool { @@ -52,7 +52,6 @@ class EBLAPPD : public Tool uint64_t LAPPDTS_PPSDiff; int LAPPDTS_PPSMissing; - vector MatchBuffer_LAPPDTimestamp_ns; // used to indexing data for unmatched // TODO, maybe make a new "LAPPDBuildData" class? diff --git a/UserTools/EBLAPPD/README.md b/UserTools/EBLAPPD/README.md index b8d0bb8d0..c8b4796ae 100644 --- a/UserTools/EBLAPPD/README.md +++ b/UserTools/EBLAPPD/README.md @@ -1,20 +1,35 @@ # EBLAPPD -EBLAPPD +EBLAPPD tool is a part of Event Building version 2 tool chain. +For reference slides, see: +https://annie-docdb.fnal.gov/cgi-bin/sso/ShowDocument?docid=5633 + +EBLAPPD match the LAPPD beamgate + LAPPD offset to grouped trigger, and save the matching results to CStore for EBSaver. ## Data -Describe any data formats EBLAPPD creates, destroys, changes, or analyzes. E.G. +**PairedCTCTimeStamps** +After matching, the matched trigger timestamp will be saved here. The key is the main trigger word for each run type. +Saved as PairedLAPPDTriggerTimestamp in CStore. + +**PairedLAPPDTimeStamps** +After matching, the matched LAPPD beamgate + offset will be saved here. The key is the main trigger word for each run type. +This and PairedCTCTimeStamps have the same index. A little bit dangerous, but overall works well. +Saved as PairedLAPPDTimeStamps in CStore -**RawLAPPDData** `map>>` -* Takes this data from the `ANNIEEvent` store and finds the number of peaks - ## Configuration -Describe any configuration variables for EBLAPPD. +**matchTargetTrigger** +This gives which trigger word that the LAPPD beamgate + offset should be matched to. + +**matchTolerance_ns** +This gives the maximum allowed time tolerance between the LAPPD beamgate + offset and the target trigger timestamp. + +**exePerMatch** +This gives how many loops need to be past for one matching between MLAPPD beamgate + offset and target trigger timestamps. +500 is generally fine with beam runs. + +**matchToAllTriggers** +1 or 0. 1 means match to all possible triggers, 0 means only match to the target trigger. -``` -param1 value1 -param2 value2 -``` diff --git a/UserTools/EBLoadRaw/EBLoadRaw.cpp b/UserTools/EBLoadRaw/EBLoadRaw.cpp index 2d601b4fb..17685138d 100644 --- a/UserTools/EBLoadRaw/EBLoadRaw.cpp +++ b/UserTools/EBLoadRaw/EBLoadRaw.cpp @@ -153,9 +153,9 @@ bool EBLoadRaw::Execute() // this is an old option, why? if (MRDTotalEntries > PMTTotalEntries) { - //FileCompleted = true; + // FileCompleted = true; Log("EBLoadRaw: Jumping to next file due to MRD entry is more than PMT entry.", v_message, verbosityEBLoadRaw); - //return true; + // return true; } if (LoadPMT && PMTEntryNum == PMTTotalEntries) @@ -579,12 +579,15 @@ bool EBLoadRaw::LoadNextPMTData() m_data->CStore.Set("TankEntryNum", PMTEntryNum); PMTEntryNum++; - if(PMTEntryNum == PMTTotalEntries || PMTEntryNum > PMTTotalEntries) + if (PMTEntryNum == PMTTotalEntries) { + // force the PMT matching when all PMT entries are completed or PMTEntryNum is greater than PMTTotalEntries Log("EBLoadRaw: PMTEntriesCompleted, force PMT matching", v_message, verbosityEBLoadRaw); bool ForcePMTMatching = true; m_data->CStore.Set("ForcePMTMatching", ForcePMTMatching); - }else{ + } + else + { bool ForcePMTMatching = false; m_data->CStore.Set("ForcePMTMatching", ForcePMTMatching); } @@ -600,6 +603,19 @@ bool EBLoadRaw::LoadNextMRDData() m_data->CStore.Set("MRDData", MData, true); m_data->CStore.Set("MRDEntryNum", MRDEntryNum); MRDEntryNum++; + + if (MRDEntryNum == MRDTotalEntries) + { + Log("EBLoadRaw: MRDEntriesCompleted, force MRD matching", v_message, verbosityEBLoadRaw); + bool ForceMRDMatching = true; + m_data->CStore.Set("ForceMRDMatching", ForceMRDMatching); + } + else + { + bool ForceMRDMatching = false; + m_data->CStore.Set("ForceMRDMatching", ForceMRDMatching); + } + return true; } @@ -612,6 +628,19 @@ bool EBLoadRaw::LoadNextLAPPDData() m_data->CStore.Set("LAPPDEntryNum", LAPPDEntryNum); m_data->CStore.Set("LAPPDanaData", true); LAPPDEntryNum++; + + if (LAPPDEntryNum == LAPPDTotalEntries) + { + Log("EBLoadRaw: LAPPDEntriesCompleted, force LAPPD matching", v_message, verbosityEBLoadRaw); + bool ForceLAPPDMatching = true; + m_data->CStore.Set("ForceLAPPDMatching", ForceLAPPDMatching); + } + else + { + bool ForceLAPPDMatching = false; + m_data->CStore.Set("ForceLAPPDMatching", ForceLAPPDMatching); + } + return true; } diff --git a/UserTools/EBLoadRaw/EBLoadRaw.h b/UserTools/EBLoadRaw/EBLoadRaw.h index 296e697da..4d5059b53 100644 --- a/UserTools/EBLoadRaw/EBLoadRaw.h +++ b/UserTools/EBLoadRaw/EBLoadRaw.h @@ -12,14 +12,14 @@ #include "Store.h" /** - * \class EBLoadRaw + * \class EBPMT * - * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. + * $Author: Yue Feng $ + * $Date: 2024/04 $ + * Contact: yuef@iaistate.edu * - * $Author: B.Richards $ - * $Date: 2019/05/28 10:44:00 $ - * Contact: b.richards@qmul.ac.uk */ + class EBLoadRaw : public Tool { @@ -75,7 +75,6 @@ class EBLoadRaw : public Tool bool CTCEntriesCompleted; bool usingTriggerOverlap; - int CTCEntryNum; int PMTEntryNum; int MRDEntryNum; diff --git a/UserTools/EBLoadRaw/README.md b/UserTools/EBLoadRaw/README.md index 12f285dc2..957f68e36 100644 --- a/UserTools/EBLoadRaw/README.md +++ b/UserTools/EBLoadRaw/README.md @@ -1,20 +1,20 @@ # EBLoadRaw -EBLoadRaw +EBLoadRaw tool is a part of Event Building version 2 tool chain. +For reference slides, see: +https://annie-docdb.fnal.gov/cgi-bin/sso/ShowDocument?docid=5633 +It basically follows the logic of LoadRawData, but reorganized to a different format and abort the BuileType option. If you need to load PMT and CTC data flow, just choose LoadCTC = true and LoadPMT = true, and use false for others. ## Data -Describe any data formats EBLoadRaw creates, destroys, changes, or analyzes. E.G. - -**RawLAPPDData** `map>>` -* Takes this data from the `ANNIEEvent` store and finds the number of peaks - +need a list of raw part file as input, set the loaded entry to CStore. +Check Load*Data functions for each data flow. ## Configuration -Describe any configuration variables for EBLoadRaw. +**InputFile** is the name of txt file which has the raw part file list in it. +**ReadTriggerOverlap** will control load the overlap file or not. It's necessary for beam runs, not really necessary for source runs because lost a few events is not unacceptable for source run. + +**LoadCTC, LoadPMT, LoadMRD, LoadLAPPD** These tells the tool to load the data flow or not. Usually true for all of them. + -``` -param1 value1 -param2 value2 -``` diff --git a/UserTools/EBMRD/EBMRD.cpp b/UserTools/EBMRD/EBMRD.cpp index 373533102..c00047144 100644 --- a/UserTools/EBMRD/EBMRD.cpp +++ b/UserTools/EBMRD/EBMRD.cpp @@ -81,8 +81,10 @@ bool EBMRD::Execute() m_data->vars.Get("StopLoop", stopLoop); int runNum = thisRunNum; m_data->vars.Get("RunNumber", thisRunNum); + bool ForceMRDMatching = false; + m_data->CStore.Get("ForceMRDMatching", ForceMRDMatching); - if (exeNum % exePerMatch == 0 || runNum != thisRunNum || stopLoop) + if (exeNum % exePerMatch == 0 || runNum != thisRunNum || stopLoop || ForceMRDMatching) { Log("EBMRD: exeNum = " + std::to_string(exeNum) + ". Doing matching now", v_message, verbosityEBMRD); if (matchToAllTriggers) diff --git a/UserTools/EBMRD/EBMRD.h b/UserTools/EBMRD/EBMRD.h index aa53269ab..0722d5ae3 100644 --- a/UserTools/EBMRD/EBMRD.h +++ b/UserTools/EBMRD/EBMRD.h @@ -7,14 +7,14 @@ #include "Tool.h" /** - * \class EBMRD + * \class EBPMT * - * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. + * $Author: Yue Feng $ + * $Date: 2024/04 $ + * Contact: yuef@iaistate.edu * - * $Author: B.Richards $ - * $Date: 2019/05/28 10:44:00 $ - * Contact: b.richards@qmul.ac.uk */ + class EBMRD : public Tool { @@ -42,20 +42,18 @@ class EBMRD : public Tool std::map>> MRDEvents; // Key: {MTCTime}, value: "WaveMap" with key (CardID,ChannelID), value FinishedWaveform std::map MRDEventTriggerTypes; // Key: {MTCTime}, value: string noting what type of trigger occured for the event - std::map MRDBeamLoopback; // Key: {MTCTime}, value: string noting what type of trigger occured for the event + std::map MRDBeamLoopback; // Key: {MTCTime}, value: string noting what type of trigger occured for the event std::map MRDCosmicLoopback; // KEY: {MTCTime}, value: Cosmic loopback TDC value std::map>> MRDEventsBuffer; bool NewMRDDataAvailable; - std::map> PairedCTCTimeStamps; - std::map> PairedMRD_TriggerIndex; - std::map> PairedMRDTimeStamps; + std::map> PairedCTCTimeStamps; + std::map> PairedMRD_TriggerIndex; + std::map> PairedMRDTimeStamps; std::map MRDHitMapRunCode; // Key: {MTCTime}, value: RunCode - - bool matchToAllTriggers; int thisRunNum; diff --git a/UserTools/EBMRD/README.md b/UserTools/EBMRD/README.md index 693dd242f..3aed04355 100644 --- a/UserTools/EBMRD/README.md +++ b/UserTools/EBMRD/README.md @@ -1,20 +1,35 @@ # EBMRD -EBMRD +EBMRD tool is a part of Event Building version 2 tool chain. +For reference slides, see: +https://annie-docdb.fnal.gov/cgi-bin/sso/ShowDocument?docid=5633 + +EBMRD match the MRD timestamp to grouped trigger, and save the matching results to CStore for EBSaver. ## Data -Describe any data formats EBMRD creates, destroys, changes, or analyzes. E.G. -**RawLAPPDData** `map>>` -* Takes this data from the `ANNIEEvent` store and finds the number of peaks - +**PairedCTCTimeStamps** +After matching, the matched trigger timestamp will be saved here. The key is the main trigger word for each run type. +Saved as PairedMRDTriggerTimestamp in CStore. + +**PairedMRDTimeStamps** +After matching, the matched MRD timestamp will be saved here. The key is the main trigger word for each run type. +This and PairedCTCTimeStamps have the same index. A little bit dangerous, but overall works well. +Saved as PairedMRDTimeStamps in CStore + ## Configuration -Describe any configuration variables for EBMRD. +**matchTargetTrigger** +This gives which trigger word that the MRD timestamps should be matched to. + +**matchTolerance_ns** +This gives the maximum allowed time tolerance between the MRD timestmap and the target trigger timestamp. + +**exePerMatch** +This gives how many loops need to be past for one matching between MRD timestmaps and target trigger timestamps. +500 is generally fine with beam runs. 100 would be better for AmBe runs -``` -param1 value1 -param2 value2 -``` +**matchToAllTriggers** +1 or 0. 1 means match MRD timestamps to all possible triggers, 0 means only match to the target trigger. diff --git a/UserTools/EBPMT/EBPMT.cpp b/UserTools/EBPMT/EBPMT.cpp index c30edfbac..641507833 100644 --- a/UserTools/EBPMT/EBPMT.cpp +++ b/UserTools/EBPMT/EBPMT.cpp @@ -202,12 +202,12 @@ bool EBPMT::Execute() bool stopLoop = false; m_data->vars.Get("StopLoop", stopLoop); int runNum = thisRunNum; // run number saved in buffer as the previous run number - //m_data->vars.Get("RunNumber", thisRunNum); + // m_data->vars.Get("RunNumber", thisRunNum); m_data->CStore.Get("runNumber", thisRunNum); bool ForcePMTMatching = false; m_data->CStore.Get("ForcePMTMatching", ForcePMTMatching); - + if (exeNum % exePerMatch == 0 || runNum != thisRunNum || stopLoop || ForcePMTMatching) { Log("EBPMT: exeNum: " + std::to_string(exeNum) + " Doing Matching", v_message, verbosityEBPMT); diff --git a/UserTools/EBPMT/EBPMT.h b/UserTools/EBPMT/EBPMT.h index 90d04f8c4..9065ef439 100644 --- a/UserTools/EBPMT/EBPMT.h +++ b/UserTools/EBPMT/EBPMT.h @@ -11,12 +11,12 @@ /** * \class EBPMT * - * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. + * $Author: Yue Feng $ + * $Date: 2024/04 $ + * Contact: yuef@iaistate.edu * - * $Author: B.Richards $ - * $Date: 2019/05/28 10:44:00 $ - * Contact: b.richards@qmul.ac.uk */ + class EBPMT : public Tool { @@ -36,8 +36,8 @@ class EBPMT : public Tool int currentRunCode; std::map> *> *FinishedHits; // Key: {MTCTime}, value: map of Hit distributions - std::map> *FinishedRWMWaveforms; // Key: {MTCTime}, value: RWM waveform - std::map> *FinishedBRFWaveforms; // Key: {MTCTime}, value: BRF waveform + std::map> *FinishedRWMWaveforms; // Key: {MTCTime}, value: RWM waveform + std::map> *FinishedBRFWaveforms; // Key: {MTCTime}, value: BRF waveform std::map AlmostCompleteWaveforms; diff --git a/UserTools/EBPMT/README.md b/UserTools/EBPMT/README.md index 131118613..cfb62496a 100644 --- a/UserTools/EBPMT/README.md +++ b/UserTools/EBPMT/README.md @@ -1,20 +1,43 @@ # EBPMT -EBPMT +EBPMT tool is a part of Event Building version 2 tool chain. +For reference slides, see: +https://annie-docdb.fnal.gov/cgi-bin/sso/ShowDocument?docid=5633 +EBPMT match the ADC timestamps to grouped trigger, and save the matching results to CStore for EBSaver. + ## Data -Describe any data formats EBPMT creates, destroys, changes, or analyzes. E.G. +**FinishedHits** +The PMT hits on each PMT are decoded from the PMTDataDecoder. While there are enough number of PMT loaded for a (ADC) PMT timestamp, the timestamp will be pushed to FinishedHits. The name was taken from ANNIEEventBuilder. + + +**RWMRawWaveforms** +**BRFRawWaveforms** +These two behaves like FinishedHits, but for raw RWM and BRF waveforms. +The slides for BRF and RWM waveforms: https://annie-docdb.fnal.gov/cgi-bin/sso/ShowDocument?docid=5756 + + +**PairedCTCTimeStamps** +After matching, the matched trigger timestamp will be saved here. The key is the main trigger word for each run type. + +**PairedPMTTimeStamps** +After matching, the matched PMT timestamp will be saved here. The key is the main trigger word for each run type. +This and PairedCTCTimeStamps have the same index. A little bit dangerous, but overall works well. + -**RawLAPPDData** `map>>` -* Takes this data from the `ANNIEEvent` store and finds the number of peaks - ## Configuration -Describe any configuration variables for EBPMT. +**matchTargetTrigger** +This gives which trigger word that the PMT timestamps should be matched to. + +**matchTolerance_ns** +This gives the maximum allowed time tolerance between the PMT timestmap and the target trigger timestamp. + +**exePerMatch** +This gives how many loops need to be past for one matching between PMT timestmaps and target trigger timestamps. +500 is generally fine with beam runs -``` -param1 value1 -param2 value2 -``` +**matchToAllTriggers** +1 or 0. 1 means match PMT timestamps to all possible triggers, 0 means only match to the target trigger. diff --git a/UserTools/EBSaver/EBSaver.h b/UserTools/EBSaver/EBSaver.h index 06cc5cb9e..57a960f7d 100644 --- a/UserTools/EBSaver/EBSaver.h +++ b/UserTools/EBSaver/EBSaver.h @@ -18,14 +18,14 @@ #include "TTree.h" /** - * \class EBSaver + * \class EBPMT * - * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. + * $Author: Yue Feng $ + * $Date: 2024/04 $ + * Contact: yuef@iaistate.edu * - * $Author: B.Richards $ - * $Date: 2019/05/28 10:44:00 $ - * Contact: b.richards@qmul.ac.uk */ + class EBSaver : public Tool { diff --git a/UserTools/EBSaver/README.md b/UserTools/EBSaver/README.md index a96d57ce3..a05a2dc7c 100644 --- a/UserTools/EBSaver/README.md +++ b/UserTools/EBSaver/README.md @@ -1,20 +1,29 @@ # EBSaver -EBSaver +EBSaver is a part of Event Building version 2 tool chain. +For reference slides, see: +https://annie-docdb.fnal.gov/cgi-bin/sso/ShowDocument?docid=5633 + +For a group of trigger with it's main trigger in part file x, that event will be saved as processed file x. +There shouldn't be any error if the file is correctly processed, the stat info will be printed out at Finalise. +Processing one part file usually just take a few minutes. The time of processing multiple files will be increased quick because of the trigger grouping. There is a limit but more than 7 beam files are not recommended. + ## Data -Describe any data formats EBSaver creates, destroys, changes, or analyzes. E.G. +EBSaver take four cataogeies of inputs +1. Beam Info. (From beam fetcher) +2. Grouped triggers. (from EBTriggerGrouper) + GroupedTriggersInTotal +3. Data from subsystems. (PMT, MRD, LAPPD, from data decoders) + In GotAllDataFromOriginalBuffer function +4. Matched pairs of data timestamps and grouped triggers. (from EBPMT, EBMRD, EBLAPPD) + Also in GotAllDataFromOriginalBuffer function -**RawLAPPDData** `map>>` -* Takes this data from the `ANNIEEvent` store and finds the number of peaks - ## Configuration -Describe any configuration variables for EBSaver. +beamInfoFileName: name of the beam info file generated by beam fetcher V2 -``` -param1 value1 -param2 value2 -``` +Other configs are set by defalut +Save Orphan is not implemented right now. \ No newline at end of file diff --git a/UserTools/EBTriggerGrouper/EBTriggerGrouper.cpp b/UserTools/EBTriggerGrouper/EBTriggerGrouper.cpp index 755c1cacf..afd2b0946 100644 --- a/UserTools/EBTriggerGrouper/EBTriggerGrouper.cpp +++ b/UserTools/EBTriggerGrouper/EBTriggerGrouper.cpp @@ -72,18 +72,18 @@ bool EBTriggerGrouper::Initialise(std::string configfile, DataModel &data) LEDTriggers = {33, 22, 31, 43, 46}; // in run 4792 [[22, 33], [4160001224, 4160001664]] m_data->CStore.Set("LEDTriggersUsedForGroupping", LEDTriggers); - AmBeTriggerMain = 15; // TODO: need to check + AmBeTriggerMain = 11; // TODO: need to check m_variables.Get("AmBeTriggerMain", AmBeTriggerMain); AmBeTolerance = 5000; // 2336 in Ambe run 4707 m_variables.Get("AmBeTolerance", AmBeTolerance); - AmBeTriggers = {11, 12, 15, 19}; // in run 4707 [[19, 12, 15, 11], [21275647928, 21275647936, 21275647952, 21275650264]] + AmBeTriggers = {11, 12, 15, 19, 46}; // in run 4707 [[19, 12, 15, 11], [21275647928, 21275647936, 21275647952, 21275650264]] m_data->CStore.Set("AmBeTriggersUsedForGroupping", AmBeTriggers); NuMITriggerMain = 42; m_variables.Get("NuMITriggerMain", NuMITriggerMain); NuMITolerance = 100; // 100ns m_variables.Get("NuMITolerance", NuMITolerance); - NuMITriggers = {42, 46}; // + NuMITriggers = {42, 46}; // m_data->CStore.Set("NuMITriggersUsedForGroupping", NuMITriggers); StoreTotalEntry = 0; @@ -629,8 +629,8 @@ int EBTriggerGrouper::GroupByTrigWord(uint32_t mainTrigWord, vector Tr cout << "EBTG: saving grouped trigger with currentRunCode = " << currentRunCode << endl; if (!trackTriggerExist) RunCodeInTotal[mainTrigWord].push_back(currentRunCode); - else - Log("EBTG: Found a duplicated main trigger with word " + std::to_string(mainTrigWord) + " and time " + std::to_string(trackTriggerTime) + ", so skip adding run code vector", v_message, verbosityEBTG); + else + Log("EBTG: Found a duplicated main trigger with word " + std::to_string(mainTrigWord) + " and time " + std::to_string(trackTriggerTime) + ", so skip adding run code vector", v_message, verbosityEBTG); totalGroupedTriggerNumber += ThisGroup.size(); ThisGroup.clear(); found = false; @@ -730,9 +730,9 @@ int EBTriggerGrouper::FillByTrigWord(uint32_t mainTrigWord, vector Tri int EBTriggerGrouper::CleanTriggerBuffer() { - //remove very early trigger in TrigTimeForGroup and TrigWordForGroup - //only leave the latest maxNumAllowedInBuffer elements - int removedNumber = 0; + // remove very early trigger in TrigTimeForGroup and TrigWordForGroup + // only leave the latest maxNumAllowedInBuffer elements + int removedNumber = 0; if (TrigTimeForGroup.size() > maxNumAllowedInBuffer) { removedNumber = TrigTimeForGroup.size() - maxNumAllowedInBuffer; diff --git a/UserTools/EBTriggerGrouper/EBTriggerGrouper.h b/UserTools/EBTriggerGrouper/EBTriggerGrouper.h index b98cba127..3d573259b 100644 --- a/UserTools/EBTriggerGrouper/EBTriggerGrouper.h +++ b/UserTools/EBTriggerGrouper/EBTriggerGrouper.h @@ -7,14 +7,14 @@ #include "Tool.h" /** - * \class EBTriggerGrouper + * \class EBPMT * - * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. + * $Author: Yue Feng $ + * $Date: 2024/04 $ + * Contact: yuef@iaistate.edu * - * $Author: B.Richards $ - * $Date: 2019/05/28 10:44:00 $ - * Contact: b.richards@qmul.ac.uk */ + class EBTriggerGrouper : public Tool { @@ -41,8 +41,8 @@ class EBTriggerGrouper : public Tool // for all triggers in the buffer, if the trigger word is in the vector, and in the range of main TrigWord - the tolerance // push the trigger into the map - int CleanTriggerBuffer(); //remove very early trigger in TrigTimeForGroup and TrigWordForGroup - //only leave the latest maxNumAllowedInBuffer elements + int CleanTriggerBuffer(); // remove very early trigger in TrigTimeForGroup and TrigWordForGroup + // only leave the latest maxNumAllowedInBuffer elements private: string savePath; @@ -63,7 +63,7 @@ class EBTriggerGrouper : public Tool std::map>> GroupedTriggersInTotal; // each map is a group of triggers, with the key is the target trigger word std::map> RunCodeInTotal; //!! RunCode goes with each group, always modify them together - std::map SkippedDuplicateTriggers; //if the trigger was duplicated in multiple entries, skip it. this record the skipped number of groups + std::map SkippedDuplicateTriggers; // if the trigger was duplicated in multiple entries, skip it. this record the skipped number of groups int verbosityEBTG; diff --git a/UserTools/EBTriggerGrouper/README.md b/UserTools/EBTriggerGrouper/README.md index 417e352e7..3f84b6468 100644 --- a/UserTools/EBTriggerGrouper/README.md +++ b/UserTools/EBTriggerGrouper/README.md @@ -1,20 +1,32 @@ # EBTriggerGrouper -EBTriggerGrouper +EBTriggerGrouper is a part of the Event Builder V2 tool chain. +For reference slides, see: +https://annie-docdb.fnal.gov/cgi-bin/sso/ShowDocument?docid=5633 + + +This tool take TimeToTriggerWordMap from the trigger data decoder as input, push the triggers and trigger words into TrigTimeForGroup and TrigWordForGroup, then use the pre defined trigger groups like BeamTriggers to group the triggers based on time tolorance. Finally save the grouped triggers to GroupedTriggersInTotal in CStore. ## Data -Describe any data formats EBTriggerGrouper creates, destroys, changes, or analyzes. E.G. +**TimeToTriggerWordMap** `std::map>` +**TimeToTriggerWordMapComplete** `std::map>` +Take from TriggerDataDecoder. This tool will push the info to + +**TrigTimeForGroup** `vector` +**TrigWordForGroup** `vector` +Buffer for timestamps. Only be used in this tool. + -**RawLAPPDData** `map>>` -* Takes this data from the `ANNIEEvent` store and finds the number of peaks - +**GroupedTriggersInTotal** `std::map>>` +Groupped triggers, will be passed to other tools for matching. ## Configuration +For one group type, you need one option, and two configs from the config file, one config hard coded in the cpp file. +groupBeam: tell the tool group this run type or not +BeamTriggerMain: the main trigger of a run type. For instance, main beam trigger is 14 +BeamTolerance: the time tolerance that you allow other triggers in this run type to be paired with a main trigger. +BeamTriggers: hard coded in the cpp file for safety. This vector contains all trigger word that allowed to be grouped as beam. +They are sent to GroupByTrigWord function for each run type. In case there will be more run types in the future. -Describe any configuration variables for EBTriggerGrouper. -``` -param1 value1 -param2 value2 -``` diff --git a/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp index 16c00a121..7b0d64deb 100644 --- a/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp +++ b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp @@ -39,6 +39,11 @@ bool ProcessedLAPPDFilter::Initialise(std::string configfile, DataModel &data) // filterType = "PMTCluster"; // pmt cluster only m_variables.Get("filterType", filterType); + RequireNoVeto = false; + m_variables.Get("RequireNoVeto", RequireNoVeto); + RequireCherenkovCover = false; + m_variables.Get("RequireCherenkovCover", RequireCherenkovCover); + FilteredMRD = new BoostStore(false, 2); // all events with MRD in it //if gotEventMRD = true; FilteredMRDNoVeto = new BoostStore(false, 2); // all events with MRD but no veto// if gotEventMRD && gotEventMRDNoVeto = true FilteredAllLAPPD = new BoostStore(false, 2); // all events with LAPPD data @@ -56,6 +61,8 @@ bool ProcessedLAPPDFilter::Initialise(std::string configfile, DataModel &data) PsecDataNumber = 0; PMTClusterEventNum = 0; + passCutEventNumber = 0; + return true; } @@ -68,8 +75,8 @@ bool ProcessedLAPPDFilter::Execute() bool gotpTW = m_data->Stores["ANNIEEvent"]->Get("PrimaryTriggerWord", pTW); uint64_t pTT = 0; bool gotpTT = m_data->Stores["ANNIEEvent"]->Get("PrimaryTriggerTime", pTT); - - Log("ProcessedLAPPDFilter: Got ETT: " + std::to_string(ETT) + "(" + std::to_string(gotETT) + "), pTW: " + std::to_string(pTW) + "(" + std::to_string(gotpTW) + "), pTT: " + std::to_string(pTT) + "(" + std::to_string(gotpTT) + ")", 1, FilterVerbosity); + + Log("ProcessedLAPPDFilter: Got ETT: " + std::to_string(ETT) + "(" + std::to_string(gotETT) + "), pTW: " + std::to_string(pTW) + "(" + std::to_string(gotpTW) + "), pTT: " + std::to_string(pTT) + "(" + std::to_string(gotpTT) + ")", 5, FilterVerbosity); m_data->Stores.at("ANNIEEvent")->Get("DataStreams", DataStreams); @@ -81,6 +88,156 @@ bool ProcessedLAPPDFilter::Execute() } cout << endl; } + CurrentExeNumber += 1; + + if (filterType == "BeamSelection") + { + + if (CurrentExeNumber % 1000 == 0) + { + cout << "ProcessedLAPPDFilter: CurrentExeNumber: " << CurrentExeNumber << ", passCutEventNumber: " << passCutEventNumber << endl; + } + + // require beam_good + int beam_good = 0; + bool gotBeamGood = m_data->Stores["ANNIEEvent"]->Get("beam_good", beam_good); + if (!gotBeamGood || beam_good != 1) + { + Log("ProcessedLAPPDFilter: not good beam" + std::to_string(beam_good), 2, FilterVerbosity); + return true; + } + // require there is PMT cluster + std::map> *m_all_clusters = nullptr; + bool get_clusters = m_data->CStore.Get("ClusterMap", m_all_clusters); + if (!get_clusters) + { + std::cout << "ProcessedLAPPDFilter tool: No clusters!" << std::endl; + return false; + } + if (!(static_cast(m_all_clusters->size()) > 0)) + { + Log("ProcessedLAPPDFilter: No PMT cluster found!", 4, FilterVerbosity); + return true; + } + // require there is a cluster in the prompt window (2us) + vector clusterTimes; + std::map>::iterator it_cluster_pair; + it_cluster_pair = (*m_all_clusters).begin(); + bool loop_map = true; + while (loop_map) + { + std::vector cluster_hits = it_cluster_pair->second; + double thisClusterTime = it_cluster_pair->first; + clusterTimes.push_back(thisClusterTime); + + it_cluster_pair++; + if (it_cluster_pair == (*m_all_clusters).end()) + loop_map = false; + } + // loop clusterTimes, if there is not any element < 2000, return true + bool found = false; + for (auto it = clusterTimes.begin(); it != clusterTimes.end(); ++it) + { + if (*it < 2000) + { + found = true; + break; + } + } + if (!found) + { + Log("ProcessedLAPPDFilter: No cluster in the prompt window!", 2, FilterVerbosity); + return true; + } + + // require the brightest cluster in the prompt window have charge balance < 0.2 + std::map ClusterChargeBalances; + std::map ClusterMaxPEs; + + bool got_ccb = m_data->Stores.at("ANNIEEvent")->Get("ClusterChargeBalances", ClusterChargeBalances); + bool got_cmpe = m_data->Stores.at("ANNIEEvent")->Get("ClusterMaxPEs", ClusterMaxPEs); + + double max_charge = 0; + double max_charge_cluster_time = 0; + double max_charge_cluster_CB = 1; + for (auto it = ClusterMaxPEs.begin(); it != ClusterMaxPEs.end(); ++it) + { + double cluster_time = it->first; + double charge_balance = ClusterChargeBalances.at(cluster_time); + + if (it->second > max_charge) + { + max_charge = it->second; + max_charge_cluster_time = cluster_time; + max_charge_cluster_CB = charge_balance; + } + } + if (max_charge_cluster_CB > 0.2) + { + Log("ProcessedLAPPDFilter: The brightest cluster in the prompt window has charge balance > 0.2", 2, FilterVerbosity); + return true; + } + + // require there is a MRD track, and the MRD coincidence is true + int numtracksinev = m_data->Stores["MRDTracks"]->Get("NumMrdTracks", numtracksinev); + if (numtracksinev < 1) + { + Log("ProcessedLAPPDFilter: No MRD track!", 2, FilterVerbosity); + return true; + } + + bool pmtmrdcoinc; + bool gotCoinc = m_data->Stores["RecoEvent"]->Get("PMTMRDCoinc", pmtmrdcoinc); + if (!gotCoinc || !pmtmrdcoinc) + { + Log("ProcessedLAPPDFilter: No PMT MRD coincidence!", 2, FilterVerbosity); + return true; + } + + // require there is no veto + if (RequireNoVeto) + { + bool noVeto = false; + bool gotNoVeto = m_data->Stores.at("RecoEvent")->Get("NoVeto", noVeto); + if (!gotNoVeto || !noVeto) + { + Log("ProcessedLAPPDFilter: There is veto!", 2, FilterVerbosity); + return true; + } + } + + // require the Cherenkov light cover the center LAPPD + if (RequireCherenkovCover) + { + vector> PMT_ChannelKeys = {{462, 428, 406, 412}}; + std::vector brightestCluster = m_all_clusters->at(max_charge_cluster_time); + vector PMTKeys; + int coveredPMT = 0; + for (int i = 0; i < brightestCluster.size(); i++) + { + int channel_key = brightestCluster.at(i).GetTubeId(); + PMTKeys.push_back(channel_key); + // check if channel_key is in PMT_ChannelKeys + for (int j = 0; j < PMT_ChannelKeys.size(); j++) + { + if (std::find(PMT_ChannelKeys[j].begin(), PMT_ChannelKeys[j].end(), channel_key) != PMT_ChannelKeys[j].end()) + { + coveredPMT += 1; + break; + } + } + } + if (coveredPMT < 3) + { + Log("ProcessedLAPPDFilter: The Cherenkov light doesn't cover the center LAPPD!", 2, FilterVerbosity); + return true; + } + } + + + GotANNIEEventAndSave(FilteredPMTCluster, PMTClusterDataName); + passCutEventNumber += 1; + } if (filterType == "MRDtrack") { @@ -108,7 +265,7 @@ bool ProcessedLAPPDFilter::Execute() return true; } - CurrentExeNumber += 1; + std::map LAPPDBeamgate_ns; m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); @@ -168,7 +325,6 @@ bool ProcessedLAPPDFilter::Execute() if (filterType == "PMTCluster") { - CurrentExeNumber += 1; std::map LAPPDBeamgate_ns; m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); PsecDataNumber += LAPPDBeamgate_ns.size(); @@ -249,6 +405,13 @@ bool ProcessedLAPPDFilter::Finalise() FilteredAllLAPPD->Delete(); FilteredPMTCluster->Delete(); + if (filterType == "BeamSelection") + { + cout << " ProcessedLAPPDFilter: Finalise" << endl; + cout << "Current exe number: " << CurrentExeNumber << endl; + cout << "Got number of Event: " << passCutEventNumber << endl; + } + if (filterType == "MRDtrack") { cout << "Current Run " << currentRunNumber << endl; @@ -300,11 +463,13 @@ bool ProcessedLAPPDFilter::GotANNIEEventAndSave(BoostStore *BS, string savePath) m_data->Stores["ANNIEEvent"]->Get("Hits", HitsOriginal); std::map> *AuxHitsCopy = nullptr; - if (!m_data->Stores["ANNIEEvent"]->Get("AuxHits", AuxHitsOriginal) ) + if (!m_data->Stores["ANNIEEvent"]->Get("AuxHits", AuxHitsOriginal)) { std::cerr << "Warning: Could not retrieve AuxHits from ANNIEEvent or AuxHitsOriginal is nullptr. Creating empty AuxHits map." << std::endl; AuxHitsCopy = new std::map>(); - }else{ + } + else + { AuxHitsCopy = new std::map>(*AuxHitsOriginal); } std::map> *HitsCopy = nullptr; @@ -312,11 +477,12 @@ bool ProcessedLAPPDFilter::GotANNIEEventAndSave(BoostStore *BS, string savePath) { std::cerr << "Warning: Could not retrieve Hits from ANNIEEvent or HitsOriginal is nullptr. Creating empty Hits map." << std::endl; HitsCopy = new std::map>(); - }else{ + } + else + { HitsCopy = new std::map>(*HitsOriginal); } - BS->Set("AuxHits", AuxHitsCopy); BS->Set("Hits", HitsCopy); @@ -352,7 +518,7 @@ bool ProcessedLAPPDFilter::GotANNIEEventAndSave(BoostStore *BS, string savePath) Log("ProcessedLAPPDFilter: Got EventTimeTank: " + std::to_string(EventTimeTank), 1, FilterVerbosity); BS->Set("EventTimeTank", EventTimeTank); Log("ProcessedLAPPDFilter: Set EventTimeTank: " + std::to_string(EventTimeTank), 1, FilterVerbosity); - + m_data->Stores["ANNIEEvent"]->Get("MRDLoopbackTDC", MRDLoopbackTDC); BS->Set("MRDLoopbackTDC", MRDLoopbackTDC); m_data->Stores["ANNIEEvent"]->Get("MRDTriggerType", MRDTriggerType); diff --git a/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.h b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.h index eae7f0e1d..f2eb31ca9 100644 --- a/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.h +++ b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.h @@ -75,7 +75,10 @@ class ProcessedLAPPDFilter : public Tool double requirePulsedAmp; int requirePulsedStripNumber; + int passCutEventNumber; int PMTClusterEventNum; + bool RequireNoVeto; + bool RequireCherenkovCover; }; diff --git a/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp b/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp index d68fa65a4..33dd2fc76 100644 --- a/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp +++ b/UserTools/TriggerDataDecoder/TriggerDataDecoder.cpp @@ -316,6 +316,7 @@ void TriggerDataDecoder::CheckForRunChange() std::stringstream ss_trig_overlap; ss_trig_overlap << "TrigOverlap_R"< Date: Fri, 25 Oct 2024 16:39:52 -0500 Subject: [PATCH 100/163] Modify ANNIEEventTreeMaker for MC file. Change the configs in the BeamClusterAnalysisMC for using ANNIEEventTreeMaker --- .../ANNIEEventTreeMaker.cpp | 91 +++++++++++++++++-- .../ANNIEEventTreeMaker/ANNIEEventTreeMaker.h | 13 +++ .../ANNIEEventTreeMakerConfig | 34 +++++++ .../LoadGenieEventConfig | 3 +- .../BeamClusterAnalysisMC/LoadWCSimConfig | 6 +- .../LoadWCSimLAPPDConfig | 5 +- .../PhaseIITreeMakerConfig | 6 +- configfiles/BeamClusterAnalysisMC/ToolsConfig | 3 +- 8 files changed, 149 insertions(+), 12 deletions(-) create mode 100644 configfiles/BeamClusterAnalysisMC/ANNIEEventTreeMakerConfig diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index 9674cd231..7be583730 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -44,6 +44,7 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) m_variables.Get("LAPPDReco_fill", LAPPDReco_fill); m_variables.Get("LAPPD_PPS_fill", LAPPD_PPS_fill); m_variables.Get("LAPPD_Waveform_fill", LAPPD_Waveform_fill); + m_variables.Get("LAPPD_MC_fill", LAPPD_MC_fill); std::string output_filename = "ANNIEEventTree.root"; m_variables.Get("OutputFile", output_filename); @@ -268,10 +269,23 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) m_variables.Get("LAPPDWaveformInputLabel", LAPPDWaveformInputLabel); if (LAPPD_Waveform_fill) { - //Log("ANNIEEventTreeMaker Tool: LAPPDWaveformInputLabel = " + LAPPDWaveformInputLabel, 0, ANNIEEventTreeMakerVerbosity); + // Log("ANNIEEventTreeMaker Tool: LAPPDWaveformInputLabel = " + LAPPDWaveformInputLabel, 0, ANNIEEventTreeMakerVerbosity); fANNIETree->Branch("LAPPDWaveform", &fLAPPDWaveforms); } + if (LAPPD_MC_fill) + { + fANNIETree->Branch("LAPPDMCHitTubeIDs", &fLAPPDMCHitTubeIDs); + fANNIETree->Branch("LAPPDMCHitChankeys", &fLAPPDMCHitChankeys); + fANNIETree->Branch("LAPPDMCHitTime", &fLAPPDMCHitTime); + fANNIETree->Branch("LAPPDMCHitCharge", &fLAPPDMCHitCharge); + fANNIETree->Branch("LAPPDMCHitX", &fLAPPDMCHitX); + fANNIETree->Branch("LAPPDMCHitY", &fLAPPDMCHitY); + fANNIETree->Branch("LAPPDMCHitZ", &fLAPPDMCHitZ); + fANNIETree->Branch("LAPPDMCHitParallelPos", &fLAPPDMCHitParallelPos); + fANNIETree->Branch("LAPPDMCHitTransversePos", &fLAPPDMCHitTransversePos); + } + if (MRDHitInfo_fill) { fANNIETree->Branch("MRDHitClusterIndex", &fMRDHitClusterIndex); @@ -535,6 +549,11 @@ bool ANNIEEventTreeMaker::Execute() FillLAPPDWaveform(); } + if (LAPPD_MC_fill) + { + FillLAPPDMCHitInfo(); + } + //****************************** Fill MRD Info *************************************// if (MRDHitInfo_fill) { @@ -727,6 +746,20 @@ void ANNIEEventTreeMaker::ResetVariables() waveformMaxNearingValue.clear(); waveformMaxTimeBinValue.clear(); + // LAPPD waveform fill + fLAPPDWaveforms.clear(); + + // LAPPD MC fill + fLAPPDMCHitTubeIDs.clear(); + fLAPPDMCHitChankeys.clear(); + fLAPPDMCHitTime.clear(); + fLAPPDMCHitCharge.clear(); + fLAPPDMCHitX.clear(); + fLAPPDMCHitY.clear(); + fLAPPDMCHitZ.clear(); + fLAPPDMCHitParallelPos.clear(); + fLAPPDMCHitTransversePos.clear(); + // tank cluster information fNumberOfClusters = 0; @@ -2423,11 +2456,9 @@ void ANNIEEventTreeMaker::RecoSummary() void ANNIEEventTreeMaker::FillLAPPDWaveform() { - //Log("ANNIEEventTreeMaker: Filling LAPPD Waveform", 0, ANNIEEventTreeMakerVerbosity); - - fLAPPDWaveforms.clear(); + // Log("ANNIEEventTreeMaker: Filling LAPPD Waveform", 0, ANNIEEventTreeMakerVerbosity); - fLAPPDWaveforms = std::vector>(60*3, std::vector(256, 0.0)); + fLAPPDWaveforms = std::vector>(60 * 3, std::vector(256, 0.0)); // m_data->Stores["ANNIEEvent"]->Print(false); @@ -2467,7 +2498,55 @@ void ANNIEEventTreeMaker::FillLAPPDWaveform() // fill this waveform to fLAPPDWaveforms[LAPPD_ID][stripno+stripSide*30][n] for (int n = 0; n < 256; n++) { - fLAPPDWaveforms[LAPPD_ID*60+stripno + stripSide * 30][n] = wave.at(n); + fLAPPDWaveforms[LAPPD_ID * 60 + stripno + stripSide * 30][n] = wave.at(n); } } } + +void ANNIEEventTreeMaker::FillLAPPDMCHitInfo() +{ + std::map> *MCLAPPDHits = nullptr; + m_data->Stores.at("ANNIEEvent")->Get("MCLAPPDHits", MCLAPPDHits); + + int HitCount = MCLAPPDHits->size(); + Log("ANNIEEventTreeMaker: Filling LAPPD MC Hit Info, got " + to_string(HitCount) + " MC hits", v_message, ANNIEEventTreeMakerVerbosity); + + Position detector_center = geom->GetTankCentre(); + double tank_center_x = detector_center.X(); + double tank_center_y = detector_center.Y(); + double tank_center_z = detector_center.Z(); + + for (std::pair> &&apair : *MCLAPPDHits) + { + unsigned long chankey = apair.first; + std::vector hits = apair.second; + + for (MCLAPPDHit &ahit : hits) + { + std::vector pos = ahit.GetPosition(); + double x = pos.at(0) - tank_center_x; + double y = pos.at(1) - tank_center_y; + double z = pos.at(2) - tank_center_z; + + std::vector local_pos = ahit.GetLocalPosition(); + // double local_x = local_pos.at(1); + // double local_y = local_pos.at(0); + double parallel = local_pos.at(0); + double transverse = local_pos.at(1); + + int tubeID = ahit.GetTubeId(); + double hitTime = ahit.GetTime(); + double hitCharge = ahit.GetCharge(); + + fLAPPDMCHitTubeIDs.push_back(tubeID); + fLAPPDMCHitChankeys.push_back(chankey); + fLAPPDMCHitTime.push_back(hitTime); + fLAPPDMCHitCharge.push_back(hitCharge); + fLAPPDMCHitX.push_back(x); + fLAPPDMCHitY.push_back(y); + fLAPPDMCHitZ.push_back(z); + fLAPPDMCHitParallelPos.push_back(parallel); + fLAPPDMCHitTransversePos.push_back(transverse); + } + } +} \ No newline at end of file diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h index 8a5f3604c..52c4c8f4d 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h @@ -64,6 +64,7 @@ class ANNIEEventTreeMaker : public Tool void LoadLAPPDRecoInfo(); void FillLAPPDRecoInfo(); void FillLAPPDWaveform(); + void FillLAPPDMCHitInfo(); bool FillMCTruthInfo(); bool FillTankRecoInfo(); @@ -113,6 +114,7 @@ class ANNIEEventTreeMaker : public Tool bool RWMBRF_fill = 1; bool LAPPD_PPS_fill = 1; bool LAPPD_Waveform_fill = 1; + bool LAPPD_MC_fill = 0; // What reco information will be filled bool MCTruth_fill = 0; // Output the MC truth information @@ -278,6 +280,17 @@ class ANNIEEventTreeMaker : public Tool string LAPPDWaveformInputLabel; vector> fLAPPDWaveforms; + // LAPPD MC Hit info, loaded from WCSim + vector fLAPPDMCHitTubeIDs; + vector fLAPPDMCHitChankeys; + vector fLAPPDMCHitTime; + vector fLAPPDMCHitCharge; + vector fLAPPDMCHitX; + vector fLAPPDMCHitY; + vector fLAPPDMCHitZ; + vector fLAPPDMCHitParallelPos; + vector fLAPPDMCHitTransversePos; + // finished **************************************************** // tank cluster information diff --git a/configfiles/BeamClusterAnalysisMC/ANNIEEventTreeMakerConfig b/configfiles/BeamClusterAnalysisMC/ANNIEEventTreeMakerConfig new file mode 100644 index 000000000..0be15bed6 --- /dev/null +++ b/configfiles/BeamClusterAnalysisMC/ANNIEEventTreeMakerConfig @@ -0,0 +1,34 @@ +ANNIEEventTreeMakerVerbosity 0 + +OutputFile ANNIETree_MC.root + + +fillAllTriggers 1 +fill_singleTrigger 0 +fillLAPPDEventsOnly 0 +TankCluster_fill 1 +cluster_TankHitInfo_fill 1 + +TankReco_fill 0 + +TankClusterProcessing 1 +MRDClusterProcessing 1 +TriggerProcessing 1 +TankHitInfo_fill 1 +MRDHitInfo_fill 1 +MRDReco_fill 1 +SiPMPulseInfo_fill 0 +fillCleanEventsOnly 0 +MCTruth_fill 1 +Reco_fill 0 +RecoDebug_fill 0 +muonTruthRecoDiff_fill 0 +isData 0 +HasGenie 1 + +LAPPDData_fill 0 +LAPPDReco_fill 0 +RWMBRF_fill 0 +LAPPD_PPS_fill 0 +LAPPD_Waveform_fill 0 +LAPPD_MC_fill 1 diff --git a/configfiles/BeamClusterAnalysisMC/LoadGenieEventConfig b/configfiles/BeamClusterAnalysisMC/LoadGenieEventConfig index 4bd3619c4..ec5d38669 100644 --- a/configfiles/BeamClusterAnalysisMC/LoadGenieEventConfig +++ b/configfiles/BeamClusterAnalysisMC/LoadGenieEventConfig @@ -8,7 +8,8 @@ FluxVersion 1 # use 0 to load genie files based on bnb_annie_00 # Path to directory of GENIE files #FileDir NA # special option to load path from associated WCSim (Not recommended) #FileDir /pnfs/annie/persistent/simulations/genie3/G1810a0211a/standard/ -FileDir /pnfs/annie/persistent/users/vfischer/genie_files/BNB_Water_10k_22-05-17 +#FileDir /pnfs/annie/persistent/users/vfischer/genie_files/BNB_Water_10k_22-05-17 +FileDir /pnfs/annie/persistent/simulations/genie3/G1810a0211a/standard/tank # Name of GENIE file to open FilePattern gntp.99.ghep.root # gntp.[run_number].ghep.root diff --git a/configfiles/BeamClusterAnalysisMC/LoadWCSimConfig b/configfiles/BeamClusterAnalysisMC/LoadWCSimConfig index a25d47f59..73042ed42 100644 --- a/configfiles/BeamClusterAnalysisMC/LoadWCSimConfig +++ b/configfiles/BeamClusterAnalysisMC/LoadWCSimConfig @@ -7,7 +7,11 @@ verbose 1 # where X = run number for the corresponding GENIE file (gntp.X.ghep.root) # Y = offset multiple for GENIE event number -InputFile /pnfs/annie/persistent/users/moflaher/wcsim/multipmt/tankonly/wcsim_25_04_19_ANNIEp2v6_nodigit_BNB_Water_10k_22-05-17/wcsim_0.1.9.root +#InputFile /pnfs/annie/persistent/users/moflaher/wcsim/multipmt/tankonly/wcsim_25_04_19_ANNIEp2v6_nodigit_BNB_Water_10k_22-05-17/wcsim_0.1.9.root + +#InputFile /pnfs/annie/persistent/simulations/wcsim/wcsim_ANNIEp2v7_beam/pmt-files/wcsim_beam_gst_1_99_0.199.root + +InputFile /pnfs/annie/persistent/simulations/wcsim/G1810a0211a/standard/tank/pmt/wcsim_0.99.1.root WCSimVersion 3 ## should reflect the WCSim version of the files being loaded HistoricTriggeroffset 0 ## time offset of digits relative to the trigger diff --git a/configfiles/BeamClusterAnalysisMC/LoadWCSimLAPPDConfig b/configfiles/BeamClusterAnalysisMC/LoadWCSimLAPPDConfig index 8548f52d4..6a3051ae5 100644 --- a/configfiles/BeamClusterAnalysisMC/LoadWCSimLAPPDConfig +++ b/configfiles/BeamClusterAnalysisMC/LoadWCSimLAPPDConfig @@ -4,11 +4,14 @@ verbose 1 #InputFile /pnfs/annie/persistent/users/moflaher/wcsim/multipmt/tankonly/wcsim_25_04_19_ANNIEp2v6_nodigit_BNB_Water_10k_22-05-17/wcsim_lappd_0.1.9.root #InputFile /annie/app/users/mnieslon/WCSim_build/wcsim_ambe_port5_z0_lappd_0.root -InputFile /pnfs/annie/persistent/users/mnieslon/wcsim/output/tankonly/wcsim_ANNIEp2v7_beam/lappd-files/LAPPD_wcsim_beam_gst_1046_38_0.5438.root +#InputFile /pnfs/annie/persistent/users/mnieslon/wcsim/output/tankonly/wcsim_ANNIEp2v7_beam/lappd-files/LAPPD_wcsim_beam_gst_1046_38_0.5438.root #InputFile /pnfs/annie/persistent/users/mnieslon/wcsim/output/tankonly/wcsim_ANNIEp2v7_beam/lappd-files/LAPPD_wcsim_beam_gst_1079_9_0.9009.root #InputFile /annie/app/users/mnieslon/WCSim_build/wcsim_michel_1000_lappd_0.root #/pnfs/annie/persistent/users/mnieslon/wcsim/output/tankonly/wcsim_ANNIEp2v7_throughgoing/wcsim_throughgoing_muon_R2614_lappd_0.0.root +#InputFile /pnfs/annie/persistent/simulations/wcsim/wcsim_ANNIEp2v7_beam/lappd-files/LAPPD_wcsim_beam_gst_1_99_0.199.root +InputFile /pnfs/annie/persistent/simulations/wcsim/G1810a0211a/standard/tank/lappd/wcsim_lappd_0.99.1.root + WCSimVersion 3 ## should reflect the WCSim version of the files being loaded InnerStructureRadius 1.3545 ## octagonal inner structure radius in m (from drawings 106.64") DrawDebugGraphs 0 ## whether to draw TPolyMarker3D's of hits diff --git a/configfiles/BeamClusterAnalysisMC/PhaseIITreeMakerConfig b/configfiles/BeamClusterAnalysisMC/PhaseIITreeMakerConfig index 138764f15..2accbd34a 100644 --- a/configfiles/BeamClusterAnalysisMC/PhaseIITreeMakerConfig +++ b/configfiles/BeamClusterAnalysisMC/PhaseIITreeMakerConfig @@ -1,6 +1,8 @@ verbose 5 -OutputFile MCBeam_Gst_new_Run9000_NoSplitSubTriggers.ntuple.root +#OutputFile MCBeam_Gst_new_Run9000_NoSplitSubTriggers.ntuple.root +OutputFile MCBeam_Gst_G1810a0211a_ntuple.root + TankClusterProcessing 1 MRDClusterProcessing 1 TriggerProcessing 1 @@ -15,4 +17,4 @@ TankReco_fill 0 RecoDebug_fill 0 muonTruthRecoDiff_fill 0 IsData 0 -HasGenie 0 +HasGenie 1 diff --git a/configfiles/BeamClusterAnalysisMC/ToolsConfig b/configfiles/BeamClusterAnalysisMC/ToolsConfig index 55400ce09..6f40936a7 100644 --- a/configfiles/BeamClusterAnalysisMC/ToolsConfig +++ b/configfiles/BeamClusterAnalysisMC/ToolsConfig @@ -9,4 +9,5 @@ myFindMrdTracks FindMrdTracks configfiles/BeamClusterAnalysisMC/FindMrdTracksCon myClusterFinder ClusterFinder ./configfiles/BeamClusterAnalysisMC/ClusterFinderConfig myClusterClassifiers ClusterClassifiers ./configfiles/BeamClusterAnalysisMC/ClusterClassifiersConfig myEventSelector EventSelector ./configfiles/BeamClusterAnalysisMC/EventSelectorConfig -myPhaseIITreeMaker PhaseIITreeMaker ./configfiles/BeamClusterAnalysisMC/PhaseIITreeMakerConfig +#myPhaseIITreeMaker PhaseIITreeMaker ./configfiles/BeamClusterAnalysisMC/PhaseIITreeMakerConfig +myANNIEEventTreeMaker ANNIEEventTreeMaker ./configfiles/BeamClusterAnalysisMC/ANNIEEventTreeMakerConfig From 4f8e0afe8343a6ce0bf2ff166180c89ed04389cc Mon Sep 17 00:00:00 2001 From: Yue Date: Fri, 25 Oct 2024 17:08:18 -0500 Subject: [PATCH 101/163] Add verbosity for print out when load genie samples --- .../ANNIEEventTreeMaker.cpp | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index 7be583730..4c6242b49 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -2155,9 +2155,12 @@ bool ANNIEEventTreeMaker::FillMCTruthInfo() for (int i_cap = 0; i_cap < (int)mcneutgammas.size(); i_cap++) { std::vector capgammas = mcneutgammas.at(i_cap); - for (int i_gamma = 0; i_gamma < (int)capgammas.size(); i_gamma++) + if (ANNIEEventTreeMakerVerbosity > 1) { - std::cout << "gamma # " << i_gamma << ", energy: " << capgammas.at(i_gamma) << std::endl; + for (int i_gamma = 0; i_gamma < (int)capgammas.size(); i_gamma++) + { + std::cout << "gamma # " << i_gamma << ", energy: " << capgammas.at(i_gamma) << std::endl; + } } } } @@ -2291,16 +2294,19 @@ bool ANNIEEventTreeMaker::FillMCTruthInfo() } } - std::cout << "MCNeutCapGammas count CaptGammas: " << MCNeutCapGammas.count("CaptGammas") << std::endl; + if (ANNIEEventTreeMakerVerbosity > 1) + std::cout << "MCNeutCapGammas count CaptGammas: " << MCNeutCapGammas.count("CaptGammas") << std::endl; if (MCNeutCapGammas.count("CaptGammas") > 0) { std::vector> cap_energies = MCNeutCapGammas["CaptGammas"]; - std::cout << "cap_energies size: " << cap_energies.size() << std::endl; + if (ANNIEEventTreeMakerVerbosity > 1) + std::cout << "cap_energies size: " << cap_energies.size() << std::endl; for (int i_cap = 0; i_cap < (int)cap_energies.size(); i_cap++) { for (int i_gamma = 0; i_gamma < cap_energies.at(i_cap).size(); i_gamma++) { - std::cout << "gamma energy: " << cap_energies.at(i_cap).at(i_gamma) << std::endl; + if (ANNIEEventTreeMakerVerbosity > 1) + std::cout << "gamma energy: " << cap_energies.at(i_cap).at(i_gamma) << std::endl; fTrueNeutCapGammaE->push_back(cap_energies.at(i_cap).at(i_gamma)); } } @@ -2348,10 +2354,13 @@ bool ANNIEEventTreeMaker::FillMCTruthInfo() bool get_fsl_mass = m_data->Stores["GenieInfo"]->Get("FSLeptonMass", TrueFSLeptonMass); bool get_fsl_pdg = m_data->Stores["GenieInfo"]->Get("FSLeptonPdg", TrueFSLeptonPdg); bool get_fsl_energy = m_data->Stores["GenieInfo"]->Get("FSLeptonEnergy", TrueFSLeptonEnergy); - std::cout << "get_neutrino_energy: " << get_neutrino_energy << "get_neutrino_vtxx: " << get_neutrino_vtxx << "get_neutrino_vtxy: " << get_neutrino_vtxy << "get_neutrino_vtxz: " << get_neutrino_vtxz << "get_neutrino_time: " << get_neutrino_vtxt << std::endl; - std::cout << "get_q2: " << get_q2 << ", get_cc: " << get_cc << ", get_qel: " << get_qel << ", get_res: " << get_res << ", get_dis: " << get_dis << ", get_coh: " << get_coh << ", get_mec: " << get_mec << std::endl; - std::cout << "get_n: " << get_n << ", get_p: " << get_p << ", get_pi0: " << get_pi0 << ", get_piplus: " << get_piplus << ", get_pipluscher: " << get_pipluscher << ", get_piminus: " << get_piminus << ", get_piminuscher: " << get_piminuscher << ", get_kplus: " << get_kplus << ", get_kpluscher: " << get_kpluscher << ", get_kminus: " << get_kminus << ", get_kminuscher: " << get_kminuscher << std::endl; - std::cout << "get_fsl_vtx: " << get_fsl_vtx << ", get_fsl_momentum: " << get_fsl_momentum << ", get_fsl_time: " << get_fsl_time << ", get_fsl_mass: " << get_fsl_mass << ", get_fsl_pdg: " << get_fsl_pdg << ", get_fsl_energy: " << get_fsl_energy << std::endl; + if (ANNIEEventTreeMakerVerbosity > 1) + { + std::cout << "get_neutrino_energy: " << get_neutrino_energy << "get_neutrino_vtxx: " << get_neutrino_vtxx << "get_neutrino_vtxy: " << get_neutrino_vtxy << "get_neutrino_vtxz: " << get_neutrino_vtxz << "get_neutrino_time: " << get_neutrino_vtxt << std::endl; + std::cout << "get_q2: " << get_q2 << ", get_cc: " << get_cc << ", get_qel: " << get_qel << ", get_res: " << get_res << ", get_dis: " << get_dis << ", get_coh: " << get_coh << ", get_mec: " << get_mec << std::endl; + std::cout << "get_n: " << get_n << ", get_p: " << get_p << ", get_pi0: " << get_pi0 << ", get_piplus: " << get_piplus << ", get_pipluscher: " << get_pipluscher << ", get_piminus: " << get_piminus << ", get_piminuscher: " << get_piminuscher << ", get_kplus: " << get_kplus << ", get_kpluscher: " << get_kpluscher << ", get_kminus: " << get_kminus << ", get_kminuscher: " << get_kminuscher << std::endl; + std::cout << "get_fsl_vtx: " << get_fsl_vtx << ", get_fsl_momentum: " << get_fsl_momentum << ", get_fsl_time: " << get_fsl_time << ", get_fsl_mass: " << get_fsl_mass << ", get_fsl_pdg: " << get_fsl_pdg << ", get_fsl_energy: " << get_fsl_energy << std::endl; + } if (get_neutrino_energy && get_neutrino_mom && get_neutrino_vtxx && get_neutrino_vtxy && get_neutrino_vtxz && get_neutrino_vtxt && get_q2 && get_cc && get_nc && get_qel && get_res && get_dis && get_coh && get_mec && get_n && get_p && get_pi0 && get_piplus && get_pipluscher && get_piminus && get_piminuscher && get_kplus && get_kpluscher && get_kminus && get_kminuscher && get_fsl_vtx && get_fsl_momentum && get_fsl_time && get_fsl_mass && get_fsl_pdg && get_fsl_energy) { fTrueNeutrinoEnergy = TrueNeutrinoEnergy; From cab69ede1b30c8955f9f8144c4ce19c7b1ee9b42 Mon Sep 17 00:00:00 2001 From: Yue Date: Mon, 28 Oct 2024 15:04:37 -0500 Subject: [PATCH 102/163] force matching for MRD, PMT, LAPPD correctly by adding force matched bool to EBLoadRaw. The matching should only happen once when the loading of that data flow reach to the end in that part file. change verbosities in BCA-MC --- UserTools/EBLoadRaw/EBLoadRaw.cpp | 17 ++++++++++++++--- UserTools/EBLoadRaw/EBLoadRaw.h | 4 ++++ .../BeamClusterAnalysisMC/EventSelectorConfig | 2 +- .../BeamClusterAnalysisMC/LoadGenieEventConfig | 2 +- .../BeamClusterAnalysisMC/LoadWCSimConfig | 2 +- .../BeamClusterAnalysisMC/LoadWCSimLAPPDConfig | 2 +- .../MCParticlePropertiesConfig | 2 +- .../MCRecoEventLoaderConfig | 2 +- .../BeamClusterAnalysisMC/TimeClusteringConfig | 2 +- 9 files changed, 25 insertions(+), 10 deletions(-) diff --git a/UserTools/EBLoadRaw/EBLoadRaw.cpp b/UserTools/EBLoadRaw/EBLoadRaw.cpp index 17685138d..255b008b7 100644 --- a/UserTools/EBLoadRaw/EBLoadRaw.cpp +++ b/UserTools/EBLoadRaw/EBLoadRaw.cpp @@ -60,6 +60,10 @@ bool EBLoadRaw::Initialise(std::string configfile, DataModel &data) LoadedLAPPDTotalEntries = 0; LoadedCTCTotalEntries = 0; + PMTMatchingForced = false; + MRDMatchingForced = false; + LAPPDMatchingForced = false; + RawData = new BoostStore(false, 0); PMTData = new BoostStore(false, 2); MRDData = new BoostStore(false, 2); @@ -134,6 +138,10 @@ bool EBLoadRaw::Execute() LoadMRDData(); LoadCTCData(); LoadLAPPDData(); + + PMTMatchingForced = false; + MRDMatchingForced = false; + LAPPDMatchingForced = false; } else { @@ -579,12 +587,13 @@ bool EBLoadRaw::LoadNextPMTData() m_data->CStore.Set("TankEntryNum", PMTEntryNum); PMTEntryNum++; - if (PMTEntryNum == PMTTotalEntries) + if (PMTEntryNum == PMTTotalEntries && !PMTMatchingForced) { // force the PMT matching when all PMT entries are completed or PMTEntryNum is greater than PMTTotalEntries Log("EBLoadRaw: PMTEntriesCompleted, force PMT matching", v_message, verbosityEBLoadRaw); bool ForcePMTMatching = true; m_data->CStore.Set("ForcePMTMatching", ForcePMTMatching); + PMTMatchingForced = true; } else { @@ -604,11 +613,12 @@ bool EBLoadRaw::LoadNextMRDData() m_data->CStore.Set("MRDEntryNum", MRDEntryNum); MRDEntryNum++; - if (MRDEntryNum == MRDTotalEntries) + if (MRDEntryNum == MRDTotalEntries && !MRDMatchingForced) { Log("EBLoadRaw: MRDEntriesCompleted, force MRD matching", v_message, verbosityEBLoadRaw); bool ForceMRDMatching = true; m_data->CStore.Set("ForceMRDMatching", ForceMRDMatching); + MRDMatchingForced = true; } else { @@ -629,11 +639,12 @@ bool EBLoadRaw::LoadNextLAPPDData() m_data->CStore.Set("LAPPDanaData", true); LAPPDEntryNum++; - if (LAPPDEntryNum == LAPPDTotalEntries) + if (LAPPDEntryNum == LAPPDTotalEntries && !LAPPDMatchingForced) { Log("EBLoadRaw: LAPPDEntriesCompleted, force LAPPD matching", v_message, verbosityEBLoadRaw); bool ForceLAPPDMatching = true; m_data->CStore.Set("ForceLAPPDMatching", ForceLAPPDMatching); + LAPPDMatchingForced = true; } else { diff --git a/UserTools/EBLoadRaw/EBLoadRaw.h b/UserTools/EBLoadRaw/EBLoadRaw.h index 4d5059b53..34c8257a8 100644 --- a/UserTools/EBLoadRaw/EBLoadRaw.h +++ b/UserTools/EBLoadRaw/EBLoadRaw.h @@ -90,6 +90,10 @@ class EBLoadRaw : public Tool bool LAPPDPaused; bool CTCPaused; + bool PMTMatchingForced; + bool MRDMatchingForced; + bool LAPPDMatchingForced; + BoostStore *RawData = nullptr; BoostStore *PMTData = nullptr; BoostStore *MRDData = nullptr; diff --git a/configfiles/BeamClusterAnalysisMC/EventSelectorConfig b/configfiles/BeamClusterAnalysisMC/EventSelectorConfig index ed6a89cdc..bdd72f2f2 100644 --- a/configfiles/BeamClusterAnalysisMC/EventSelectorConfig +++ b/configfiles/BeamClusterAnalysisMC/EventSelectorConfig @@ -1,6 +1,6 @@ # EventSelector config file -verbosity 5 +verbosity 0 MCPMTVolCut 0 MCFVCut 0 MCMRDCut 0 diff --git a/configfiles/BeamClusterAnalysisMC/LoadGenieEventConfig b/configfiles/BeamClusterAnalysisMC/LoadGenieEventConfig index ec5d38669..23799a691 100644 --- a/configfiles/BeamClusterAnalysisMC/LoadGenieEventConfig +++ b/configfiles/BeamClusterAnalysisMC/LoadGenieEventConfig @@ -1,4 +1,4 @@ -verbosity 2 +verbosity 0 # Refers to format of flux file used to generate GENIE sample (bnb or gsimple) FluxVersion 1 # use 0 to load genie files based on bnb_annie_0000.root etc files (bnb/redecay/dk2nu flux format) diff --git a/configfiles/BeamClusterAnalysisMC/LoadWCSimConfig b/configfiles/BeamClusterAnalysisMC/LoadWCSimConfig index 73042ed42..27f6a4070 100644 --- a/configfiles/BeamClusterAnalysisMC/LoadWCSimConfig +++ b/configfiles/BeamClusterAnalysisMC/LoadWCSimConfig @@ -1,6 +1,6 @@ #LoadWCSim Config File # all variables retrieved with m_variables.Get() must be defined here! -verbose 1 +verbose 0 # WCSim collaboration samples using GENIE (from James): #InputFile /pnfs/annie/persistent/simulations/wcsim/G1810a0211a/standard//pmt/wcsim_0.X.Y.root diff --git a/configfiles/BeamClusterAnalysisMC/LoadWCSimLAPPDConfig b/configfiles/BeamClusterAnalysisMC/LoadWCSimLAPPDConfig index 6a3051ae5..4655cb1f0 100644 --- a/configfiles/BeamClusterAnalysisMC/LoadWCSimLAPPDConfig +++ b/configfiles/BeamClusterAnalysisMC/LoadWCSimLAPPDConfig @@ -1,6 +1,6 @@ #LoadWCSimLAPPD Config File # all variables retrieved with m_variables.Get() must be defined here! -verbose 1 +verbose 0 #InputFile /pnfs/annie/persistent/users/moflaher/wcsim/multipmt/tankonly/wcsim_25_04_19_ANNIEp2v6_nodigit_BNB_Water_10k_22-05-17/wcsim_lappd_0.1.9.root #InputFile /annie/app/users/mnieslon/WCSim_build/wcsim_ambe_port5_z0_lappd_0.root diff --git a/configfiles/BeamClusterAnalysisMC/MCParticlePropertiesConfig b/configfiles/BeamClusterAnalysisMC/MCParticlePropertiesConfig index 4313fccdf..019526011 100644 --- a/configfiles/BeamClusterAnalysisMC/MCParticlePropertiesConfig +++ b/configfiles/BeamClusterAnalysisMC/MCParticlePropertiesConfig @@ -1,3 +1,3 @@ # MCParticleProperties configuration file -verbosity 1 +verbosity 0 diff --git a/configfiles/BeamClusterAnalysisMC/MCRecoEventLoaderConfig b/configfiles/BeamClusterAnalysisMC/MCRecoEventLoaderConfig index 2a6cadb72..96923c44a 100644 --- a/configfiles/BeamClusterAnalysisMC/MCRecoEventLoaderConfig +++ b/configfiles/BeamClusterAnalysisMC/MCRecoEventLoaderConfig @@ -1,6 +1,6 @@ # MCRecoEventLoader config file -verbosity 1 +verbosity 0 GetPionKaonInfo 1 GetNRings 1 ParticleID 13 diff --git a/configfiles/BeamClusterAnalysisMC/TimeClusteringConfig b/configfiles/BeamClusterAnalysisMC/TimeClusteringConfig index 82798f033..6eb6634f4 100644 --- a/configfiles/BeamClusterAnalysisMC/TimeClusteringConfig +++ b/configfiles/BeamClusterAnalysisMC/TimeClusteringConfig @@ -1,6 +1,6 @@ #TimeClustering config file -verbosity 1 +verbosity 0 MinDigitsForTrack 4 MaxMrdSubEventDuration 40 MinSubeventTimeSep 40 From bad419193953162a1d00546fbc4b0b7ef3141ef4 Mon Sep 17 00:00:00 2001 From: Yue Date: Tue, 29 Oct 2024 15:27:56 -0500 Subject: [PATCH 103/163] Add debug information in EBLAPPD Correctly stop the ForceMatching for EBMRD and EBLAPPD change the configs in EBMRD and TriggerGrouper There are more triggers from MRD so more CTC entries, so I reduce the trigger grouper buffer from 30k to 20k to reduce the looping time. The grouper buffer is only for debugging unmatched triggers. --- UserTools/EBLAPPD/EBLAPPD.cpp | 1 + UserTools/EBLoadRaw/EBLoadRaw.cpp | 13 +++++++++++++ configfiles/EventBuilderV2/EBMRDConfig | 4 ++-- configfiles/EventBuilderV2/EBTriggerGrouperConfig | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/UserTools/EBLAPPD/EBLAPPD.cpp b/UserTools/EBLAPPD/EBLAPPD.cpp index 97c657453..4658d96d1 100644 --- a/UserTools/EBLAPPD/EBLAPPD.cpp +++ b/UserTools/EBLAPPD/EBLAPPD.cpp @@ -80,6 +80,7 @@ bool EBLAPPD::Execute() if (stopLoop || runNum != thisRunNum || exeNum % exePerMatch == 0 || ForceLAPPDMatching) { Log("EBLAPPD: exeNum = " + std::to_string(exeNum) + ". Doing matching", v_message, verbosityEBLAPPD); + Log("EBLAPPD: Matching reason is stopLoop = " + std::to_string(stopLoop) + ", runNum = " + std::to_string(runNum) + ", exeNum = " + std::to_string(exeNum) + ", ForceLAPPDMatching = " + std::to_string(ForceLAPPDMatching), v_message, verbosityEBLAPPD); if (matchToAllTriggers) { Matching(0, 0); diff --git a/UserTools/EBLoadRaw/EBLoadRaw.cpp b/UserTools/EBLoadRaw/EBLoadRaw.cpp index 255b008b7..bb3c53fd6 100644 --- a/UserTools/EBLoadRaw/EBLoadRaw.cpp +++ b/UserTools/EBLoadRaw/EBLoadRaw.cpp @@ -210,6 +210,17 @@ bool EBLoadRaw::Execute() if (LoadLAPPD && !LAPPDPaused && !LAPPDEntriesCompleted) LoadNextLAPPDData(); + if (LoadMRD && MRDEntriesCompleted) + { + bool ForceMRDMatching = false; + m_data->CStore.Set("ForceMRDMatching", ForceMRDMatching); + } + if (LoadLAPPD && LAPPDEntriesCompleted) + { + bool ForceLAPPDMatching = false; + m_data->CStore.Set("ForceLAPPDMatching", ForceLAPPDMatching); + } + // if all required data is loaded, set filecompleted flag to true if ((!LoadPMT || PMTEntriesCompleted) && (!LoadMRD || MRDEntriesCompleted) && (!LoadCTC || CTCEntriesCompleted) && (!LoadLAPPD || LAPPDEntriesCompleted)) { @@ -613,6 +624,7 @@ bool EBLoadRaw::LoadNextMRDData() m_data->CStore.Set("MRDEntryNum", MRDEntryNum); MRDEntryNum++; + Log("EBLoadRaw: Loaded MRDData entry " + std::to_string(MRDEntryNum) + ", MRDTotalEntries " + std::to_string(MRDTotalEntries) + ", MRDMatchingForced " + std::to_string(MRDMatchingForced), v_warning, verbosityEBLoadRaw); if (MRDEntryNum == MRDTotalEntries && !MRDMatchingForced) { Log("EBLoadRaw: MRDEntriesCompleted, force MRD matching", v_message, verbosityEBLoadRaw); @@ -639,6 +651,7 @@ bool EBLoadRaw::LoadNextLAPPDData() m_data->CStore.Set("LAPPDanaData", true); LAPPDEntryNum++; + Log("EBLoadRaw: Loaded LAPPDData entry " + std::to_string(LAPPDEntryNum) + ", LAPPDTotalEntries " + std::to_string(LAPPDTotalEntries) + ", LAPPDMatchingForced " + std::to_string(LAPPDMatchingForced), v_warning, verbosityEBLoadRaw); if (LAPPDEntryNum == LAPPDTotalEntries && !LAPPDMatchingForced) { Log("EBLoadRaw: LAPPDEntriesCompleted, force LAPPD matching", v_message, verbosityEBLoadRaw); diff --git a/configfiles/EventBuilderV2/EBMRDConfig b/configfiles/EventBuilderV2/EBMRDConfig index f85123020..d6f7dcf89 100644 --- a/configfiles/EventBuilderV2/EBMRDConfig +++ b/configfiles/EventBuilderV2/EBMRDConfig @@ -1,5 +1,5 @@ verbosityEBMRD 1 matchTargetTrigger 8 matchTolerance_ns 3000000 -matchToAllTriggers 1 -exePerMatch 100 +matchToAllTriggers 0 +exePerMatch 500 diff --git a/configfiles/EventBuilderV2/EBTriggerGrouperConfig b/configfiles/EventBuilderV2/EBTriggerGrouperConfig index f5328aaa4..58694560d 100644 --- a/configfiles/EventBuilderV2/EBTriggerGrouperConfig +++ b/configfiles/EventBuilderV2/EBTriggerGrouperConfig @@ -24,5 +24,5 @@ groupPPS 0 groupNuMI 1 -maxNumAllowedInBuffer 30000 +maxNumAllowedInBuffer 20000 From 218c92109b5ef9b0a0747d6c63f07d469232850e Mon Sep 17 00:00:00 2001 From: Yue Date: Wed, 30 Oct 2024 14:18:35 -0500 Subject: [PATCH 104/163] Add MRD trigger type to the root tree because there are more MRD Cosmic triggers now. This will help to avoid mismatching Changes to be committed: modified: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp modified: UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h --- .../ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp | 16 ++++++++++++++++ .../ANNIEEventTreeMaker/ANNIEEventTreeMaker.h | 2 ++ 2 files changed, 18 insertions(+) diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index 4c6242b49..7c469d014 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -84,6 +84,8 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) fANNIETree->Branch("HasLAPPD", &fHasLAPPD, "HasLAPPD/I"); fANNIETree->Branch("TankMRDCoinc", &fTankMRDCoinc, "TankMRDCoinc/I"); fANNIETree->Branch("NoVeto", &fNoVeto, "NoVeto/I"); + fANNIETree->Branch("MRDTriggerType", &fMRDTriggerTypeInt, "MRDTriggerType/I"); + //fANNIETree->Branch("MRDTriggerTypeString", &fMRDTriggerType); // event information of data fANNIETree->Branch("eventTimeTank", &fEventTimeTank, "eventTimeTank/l"); @@ -626,6 +628,8 @@ void ANNIEEventTreeMaker::ResetVariables() fDataStreams.clear(); fEventTimeTank = 0; fEventTimeMRD = 0; + fMRDTriggerType = ""; + fMRDTriggerTypeInt = -9999; // beam info fPot = -9999; @@ -1047,7 +1051,19 @@ bool ANNIEEventTreeMaker::LoadEventInfo() fHasTank = 0; if (fDataStreams["MRD"] == 1) + { fHasMRD = 1; + m_data->Stores["ANNIEEvent"]->Get("MRDTriggerType", fMRDTriggerType); + Log("ANNIEEventTreeMaker Tool: MRD Trigger Type: " + fMRDTriggerType, v_debug, ANNIEEventTreeMakerVerbosity); + bool cosmic = fMRDTriggerType == "Cosmic"; + Log("ANNIEEventTreeMaker Tool: Cosmic Trigger: " + std::to_string(cosmic), v_debug, ANNIEEventTreeMakerVerbosity); + if (fMRDTriggerType == "Beam") + fMRDTriggerTypeInt = 1; + else if (fMRDTriggerType == "Cosmic") + fMRDTriggerTypeInt = 2; + else + fMRDTriggerTypeInt = 0; + } else fHasMRD = 0; diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h index 52c4c8f4d..c6243def4 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h @@ -152,6 +152,8 @@ class ANNIEEventTreeMaker : public Tool int fHasTank; int fHasMRD; int fHasLAPPD; + std::string fMRDTriggerType; + int fMRDTriggerTypeInt; ULong64_t fEventTimeTank; ULong64_t fEventTimeMRD; From c6a354492731a8818123950f0233ff23199ec65b Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 6 Nov 2024 10:19:13 -0600 Subject: [PATCH 105/163] Update ToolsConfig add SaveConfig tool --- configfiles/EventBuilderV2/ToolsConfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configfiles/EventBuilderV2/ToolsConfig b/configfiles/EventBuilderV2/ToolsConfig index 43802b4c0..007d55c76 100644 --- a/configfiles/EventBuilderV2/ToolsConfig +++ b/configfiles/EventBuilderV2/ToolsConfig @@ -17,7 +17,7 @@ EBPMT EBPMT ./configfiles/EventBuilderV2/EBPMTConfig EBMRD EBMRD ./configfiles/EventBuilderV2/EBMRDConfig EBLAPPD EBLAPPD ./configfiles/EventBuilderV2/EBLAPPDConfig -#SaveConfigInfo SaveConfigInfo ./configfiles/EventBuilderV2/SaveConfigInfoConfig +SaveConfigInfo SaveConfigInfo ./configfiles/EventBuilderV2/SaveConfigInfoConfig EBSaver EBSaver ./configfiles/EventBuilderV2/EBSaverConfig From 986035898e055690b4e1a92d2a961678867059bf Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 6 Nov 2024 10:20:23 -0600 Subject: [PATCH 106/163] Update TriggerDataDecoderConfig this shouldnt make a difference but the traditional tools had this variable as 0, and set it as 1 in the LoadRawData tool --- configfiles/PreProcessTrigOverlap/TriggerDataDecoderConfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configfiles/PreProcessTrigOverlap/TriggerDataDecoderConfig b/configfiles/PreProcessTrigOverlap/TriggerDataDecoderConfig index 96bc8670a..dd31e177e 100644 --- a/configfiles/PreProcessTrigOverlap/TriggerDataDecoderConfig +++ b/configfiles/PreProcessTrigOverlap/TriggerDataDecoderConfig @@ -1,5 +1,5 @@ verbosity 0 #TriggerMaskFile ./configfiles/EventBuilder/DefaultTriggerMask.txt -StoreTrigOverlap 1 +StoreTrigOverlap 0 ReadTrigOverlap 0 UseCStore 0 From 037d7c89f4b02c2e5e3c30bf2c548f71f864612d Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Mon, 11 Nov 2024 09:50:50 -0600 Subject: [PATCH 107/163] EventBuilderV2 toolchains for sources modified some config files, but added different toolchains for each source type. --- configfiles/EventBuilderV2/EBLAPPDConfig | 2 +- configfiles/EventBuilderV2/EBMRDConfig | 2 +- configfiles/EventBuilderV2/EBPMTConfig | 2 +- configfiles/EventBuilderV2/EBSaverConfig | 2 +- .../EventBuilderV2/EBTriggerGrouperConfig | 4 +- configfiles/EventBuilderV2/my_files.txt | 5 ++- configfiles/EventBuilderV2_AmBe/EBLAPPDConfig | 7 ++++ .../EventBuilderV2_AmBe/EBLoadRawConfig | 10 +++++ configfiles/EventBuilderV2_AmBe/EBMRDConfig | 5 +++ configfiles/EventBuilderV2_AmBe/EBPMTConfig | 4 ++ configfiles/EventBuilderV2_AmBe/EBSaverConfig | 10 +++++ .../EBTriggerGrouperConfig | 28 +++++++++++++ .../EventBuilderV2_AmBe/LAPPDLoadStoreConfig | 39 +++++++++++++++++++ .../EventBuilderV2_AmBe/MRDDataDecoderConfig | 2 + .../EventBuilderV2_AmBe/PMTDataDecoderConfig | 5 +++ .../PhaseIIADCCalibratorConfig | 15 +++++++ .../PhaseIIADCHitFinderConfig | 10 +++++ .../EventBuilderV2_AmBe/SaveConfigInfoConfig | 3 ++ .../EventBuilderV2_AmBe/ToolChainConfig | 23 +++++++++++ configfiles/EventBuilderV2_AmBe/ToolsConfig | 21 ++++++++++ .../TriggerDataDecoderConfig | 3 ++ configfiles/EventBuilderV2_AmBe/my_files.txt | 3 ++ .../EventBuilderV2_cosmic/EBLAPPDConfig | 7 ++++ .../EventBuilderV2_cosmic/EBLoadRawConfig | 10 +++++ configfiles/EventBuilderV2_cosmic/EBMRDConfig | 5 +++ configfiles/EventBuilderV2_cosmic/EBPMTConfig | 4 ++ .../EventBuilderV2_cosmic/EBSaverConfig | 10 +++++ .../EBTriggerGrouperConfig | 28 +++++++++++++ .../LAPPDLoadStoreConfig | 39 +++++++++++++++++++ .../MRDDataDecoderConfig | 2 + .../PMTDataDecoderConfig | 5 +++ .../PhaseIIADCCalibratorConfig | 15 +++++++ .../PhaseIIADCHitFinderConfig | 10 +++++ .../SaveConfigInfoConfig | 3 ++ .../EventBuilderV2_cosmic/ToolChainConfig | 23 +++++++++++ configfiles/EventBuilderV2_cosmic/ToolsConfig | 24 ++++++++++++ .../TriggerDataDecoderConfig | 3 ++ .../EventBuilderV2_cosmic/my_files.txt | 14 +++++++ .../EventBuilderV2_laser/EBLAPPDConfig | 7 ++++ .../EventBuilderV2_laser/EBLoadRawConfig | 10 +++++ configfiles/EventBuilderV2_laser/EBMRDConfig | 5 +++ configfiles/EventBuilderV2_laser/EBPMTConfig | 4 ++ .../EventBuilderV2_laser/EBSaverConfig | 10 +++++ .../EBTriggerGrouperConfig | 30 ++++++++++++++ .../EventBuilderV2_laser/LAPPDLoadStoreConfig | 39 +++++++++++++++++++ .../EventBuilderV2_laser/MRDDataDecoderConfig | 2 + .../EventBuilderV2_laser/PMTDataDecoderConfig | 5 +++ .../PhaseIIADCCalibratorConfig | 15 +++++++ .../PhaseIIADCHitFinderConfig | 10 +++++ .../EventBuilderV2_laser/SaveConfigInfoConfig | 3 ++ .../EventBuilderV2_laser/ToolChainConfig | 23 +++++++++++ configfiles/EventBuilderV2_laser/ToolsConfig | 24 ++++++++++++ .../TriggerDataDecoderConfig | 3 ++ configfiles/EventBuilderV2_laser/my_files.txt | 3 ++ 54 files changed, 593 insertions(+), 7 deletions(-) create mode 100644 configfiles/EventBuilderV2_AmBe/EBLAPPDConfig create mode 100644 configfiles/EventBuilderV2_AmBe/EBLoadRawConfig create mode 100644 configfiles/EventBuilderV2_AmBe/EBMRDConfig create mode 100644 configfiles/EventBuilderV2_AmBe/EBPMTConfig create mode 100644 configfiles/EventBuilderV2_AmBe/EBSaverConfig create mode 100644 configfiles/EventBuilderV2_AmBe/EBTriggerGrouperConfig create mode 100644 configfiles/EventBuilderV2_AmBe/LAPPDLoadStoreConfig create mode 100644 configfiles/EventBuilderV2_AmBe/MRDDataDecoderConfig create mode 100644 configfiles/EventBuilderV2_AmBe/PMTDataDecoderConfig create mode 100644 configfiles/EventBuilderV2_AmBe/PhaseIIADCCalibratorConfig create mode 100644 configfiles/EventBuilderV2_AmBe/PhaseIIADCHitFinderConfig create mode 100644 configfiles/EventBuilderV2_AmBe/SaveConfigInfoConfig create mode 100644 configfiles/EventBuilderV2_AmBe/ToolChainConfig create mode 100644 configfiles/EventBuilderV2_AmBe/ToolsConfig create mode 100644 configfiles/EventBuilderV2_AmBe/TriggerDataDecoderConfig create mode 100644 configfiles/EventBuilderV2_AmBe/my_files.txt create mode 100644 configfiles/EventBuilderV2_cosmic/EBLAPPDConfig create mode 100644 configfiles/EventBuilderV2_cosmic/EBLoadRawConfig create mode 100644 configfiles/EventBuilderV2_cosmic/EBMRDConfig create mode 100644 configfiles/EventBuilderV2_cosmic/EBPMTConfig create mode 100644 configfiles/EventBuilderV2_cosmic/EBSaverConfig create mode 100644 configfiles/EventBuilderV2_cosmic/EBTriggerGrouperConfig create mode 100644 configfiles/EventBuilderV2_cosmic/LAPPDLoadStoreConfig create mode 100644 configfiles/EventBuilderV2_cosmic/MRDDataDecoderConfig create mode 100644 configfiles/EventBuilderV2_cosmic/PMTDataDecoderConfig create mode 100644 configfiles/EventBuilderV2_cosmic/PhaseIIADCCalibratorConfig create mode 100644 configfiles/EventBuilderV2_cosmic/PhaseIIADCHitFinderConfig create mode 100644 configfiles/EventBuilderV2_cosmic/SaveConfigInfoConfig create mode 100644 configfiles/EventBuilderV2_cosmic/ToolChainConfig create mode 100644 configfiles/EventBuilderV2_cosmic/ToolsConfig create mode 100644 configfiles/EventBuilderV2_cosmic/TriggerDataDecoderConfig create mode 100644 configfiles/EventBuilderV2_cosmic/my_files.txt create mode 100644 configfiles/EventBuilderV2_laser/EBLAPPDConfig create mode 100644 configfiles/EventBuilderV2_laser/EBLoadRawConfig create mode 100644 configfiles/EventBuilderV2_laser/EBMRDConfig create mode 100644 configfiles/EventBuilderV2_laser/EBPMTConfig create mode 100644 configfiles/EventBuilderV2_laser/EBSaverConfig create mode 100644 configfiles/EventBuilderV2_laser/EBTriggerGrouperConfig create mode 100644 configfiles/EventBuilderV2_laser/LAPPDLoadStoreConfig create mode 100644 configfiles/EventBuilderV2_laser/MRDDataDecoderConfig create mode 100644 configfiles/EventBuilderV2_laser/PMTDataDecoderConfig create mode 100644 configfiles/EventBuilderV2_laser/PhaseIIADCCalibratorConfig create mode 100644 configfiles/EventBuilderV2_laser/PhaseIIADCHitFinderConfig create mode 100644 configfiles/EventBuilderV2_laser/SaveConfigInfoConfig create mode 100644 configfiles/EventBuilderV2_laser/ToolChainConfig create mode 100644 configfiles/EventBuilderV2_laser/ToolsConfig create mode 100644 configfiles/EventBuilderV2_laser/TriggerDataDecoderConfig create mode 100644 configfiles/EventBuilderV2_laser/my_files.txt diff --git a/configfiles/EventBuilderV2/EBLAPPDConfig b/configfiles/EventBuilderV2/EBLAPPDConfig index b6981cdec..a81b1ce94 100644 --- a/configfiles/EventBuilderV2/EBLAPPDConfig +++ b/configfiles/EventBuilderV2/EBLAPPDConfig @@ -1,4 +1,4 @@ -verbosityEBLAPPD 5 +verbosityEBLAPPD 0 matchTargetTrigger 14 matchTolerance_ns 400000 #matchTolerance_ns 10000 diff --git a/configfiles/EventBuilderV2/EBMRDConfig b/configfiles/EventBuilderV2/EBMRDConfig index d6f7dcf89..a4797b1f1 100644 --- a/configfiles/EventBuilderV2/EBMRDConfig +++ b/configfiles/EventBuilderV2/EBMRDConfig @@ -1,4 +1,4 @@ -verbosityEBMRD 1 +verbosityEBMRD 0 matchTargetTrigger 8 matchTolerance_ns 3000000 matchToAllTriggers 0 diff --git a/configfiles/EventBuilderV2/EBPMTConfig b/configfiles/EventBuilderV2/EBPMTConfig index dc89bf3fc..57bb72693 100644 --- a/configfiles/EventBuilderV2/EBPMTConfig +++ b/configfiles/EventBuilderV2/EBPMTConfig @@ -1,4 +1,4 @@ -verbosityEBPMT 3 +verbosityEBPMT 0 matchTargetTrigger 46 matchTolerance_ns 1000 matchToAllTriggers 1 diff --git a/configfiles/EventBuilderV2/EBSaverConfig b/configfiles/EventBuilderV2/EBSaverConfig index bb1637547..7cf77b14f 100644 --- a/configfiles/EventBuilderV2/EBSaverConfig +++ b/configfiles/EventBuilderV2/EBSaverConfig @@ -1,4 +1,4 @@ -verbosityEBSaver 4 +verbosityEBSaver 1 savePMT 1 saveMRD 1 diff --git a/configfiles/EventBuilderV2/EBTriggerGrouperConfig b/configfiles/EventBuilderV2/EBTriggerGrouperConfig index 58694560d..22535618a 100644 --- a/configfiles/EventBuilderV2/EBTriggerGrouperConfig +++ b/configfiles/EventBuilderV2/EBTriggerGrouperConfig @@ -1,4 +1,6 @@ -verbosityEBTG 5 +verbosityEBTG 0 + +# beam triggers are always there, even in AmBe runs. We know they are meaningless to group beam trigger when we know there is 100% no beam, but again redundancy is not bad if it's not harmful GroupMode beam GroupTolerance 3000000 GroupTrigWord 14 //undelayed beam diff --git a/configfiles/EventBuilderV2/my_files.txt b/configfiles/EventBuilderV2/my_files.txt index 1a62fc0e1..7697d0d84 100644 --- a/configfiles/EventBuilderV2/my_files.txt +++ b/configfiles/EventBuilderV2/my_files.txt @@ -1,2 +1,3 @@ -/pnfs/annie/persistent/raw/raw/5039/RAWDataR5039S0p2 -/pnfs/annie/persistent/raw/raw/5039/RAWDataR5039S0p3 +/pnfs/annie/persistent/raw/raw/4499/RAWDataR4499S0p0 +/pnfs/annie/persistent/raw/raw/4499/RAWDataR4499S0p1 +/pnfs/annie/persistent/raw/raw/4499/RAWDataR4499S0p2 diff --git a/configfiles/EventBuilderV2_AmBe/EBLAPPDConfig b/configfiles/EventBuilderV2_AmBe/EBLAPPDConfig new file mode 100644 index 000000000..a81b1ce94 --- /dev/null +++ b/configfiles/EventBuilderV2_AmBe/EBLAPPDConfig @@ -0,0 +1,7 @@ +verbosityEBLAPPD 0 +matchTargetTrigger 14 +matchTolerance_ns 400000 +#matchTolerance_ns 10000 +exePerMatch 500 + +matchToAllTriggers 0 diff --git a/configfiles/EventBuilderV2_AmBe/EBLoadRawConfig b/configfiles/EventBuilderV2_AmBe/EBLoadRawConfig new file mode 100644 index 000000000..422353c62 --- /dev/null +++ b/configfiles/EventBuilderV2_AmBe/EBLoadRawConfig @@ -0,0 +1,10 @@ +verbosityEBLoadRaw 2 +ReadTriggerOverlap 1 + +InputFile ./configfiles/EventBuilderV2_AmBe/my_files.txt + +LoadPMT 1 +LoadMRD 0 +LoadCTC 1 +LoadLAPPD 0 + diff --git a/configfiles/EventBuilderV2_AmBe/EBMRDConfig b/configfiles/EventBuilderV2_AmBe/EBMRDConfig new file mode 100644 index 000000000..a4797b1f1 --- /dev/null +++ b/configfiles/EventBuilderV2_AmBe/EBMRDConfig @@ -0,0 +1,5 @@ +verbosityEBMRD 0 +matchTargetTrigger 8 +matchTolerance_ns 3000000 +matchToAllTriggers 0 +exePerMatch 500 diff --git a/configfiles/EventBuilderV2_AmBe/EBPMTConfig b/configfiles/EventBuilderV2_AmBe/EBPMTConfig new file mode 100644 index 000000000..57bb72693 --- /dev/null +++ b/configfiles/EventBuilderV2_AmBe/EBPMTConfig @@ -0,0 +1,4 @@ +verbosityEBPMT 0 +matchTargetTrigger 46 +matchTolerance_ns 1000 +matchToAllTriggers 1 diff --git a/configfiles/EventBuilderV2_AmBe/EBSaverConfig b/configfiles/EventBuilderV2_AmBe/EBSaverConfig new file mode 100644 index 000000000..d3e1e75c7 --- /dev/null +++ b/configfiles/EventBuilderV2_AmBe/EBSaverConfig @@ -0,0 +1,10 @@ +verbosityEBSaver 1 + +savePMT 1 +saveMRD 0 +saveCTC 1 +saveLAPPD 0 +saveRunInfo 1 +saveBeamInfo 0 + +beamInfoFileName beamfetcher_tree.root diff --git a/configfiles/EventBuilderV2_AmBe/EBTriggerGrouperConfig b/configfiles/EventBuilderV2_AmBe/EBTriggerGrouperConfig new file mode 100644 index 000000000..b00af8388 --- /dev/null +++ b/configfiles/EventBuilderV2_AmBe/EBTriggerGrouperConfig @@ -0,0 +1,28 @@ +verbosityEBTG 0 +GroupMode beam +GroupTolerance 3000000 +GroupTrigWord 14 //undelayed beam + +groupBeam 0 +BeamTolerance 25000000 + +groupCosmic 0 +CosmicTriggerMain 36 + +groupLaser 0 +LaserTolerance 10000 + +groupLED 0 +#LEDTriggerMain 31 +#LEDTolerance 10000 + +groupAmBe 1 +AmBeTolerance 10000 # 10us for testing +AmBeTriggerMain 11 + +groupPPS 0 + +groupNuMI 0 + +maxNumAllowedInBuffer 20000 + diff --git a/configfiles/EventBuilderV2_AmBe/LAPPDLoadStoreConfig b/configfiles/EventBuilderV2_AmBe/LAPPDLoadStoreConfig new file mode 100644 index 000000000..daa420ebe --- /dev/null +++ b/configfiles/EventBuilderV2_AmBe/LAPPDLoadStoreConfig @@ -0,0 +1,39 @@ + General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +NUM_VECTOR_METADATA 103 #Fixed META vector size +LAPPDchannelOffset 1000 +NChannels 30 + +LAPPDStoreReadInVerbosity 0 + +mergingModeReadIn 0 +RawDataInputWavLabel RawWaveform +RawDataOutputWavLabel RawLAPPDData +BoardIndexLabel BoardIndex #Label of the vector of read out boards + +PsecReceiveMode 1 +stopEntries 10000000000 + +DoPedSubtraction 0 +Nboards 6 #Number of pedestal files to be read in +PedinputfileTXT ../Pedestals/Laser2024Feb/P +PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 + + +Pedinputfile1 ../Pedestals/PEDS_ACDC_board0.txt +Pedinputfile2 ../Pedestals/PEDS_ACDC_board1.txt + + +ReadStore 0 +num_vector_data 7795 +num_vector_pps 16 +OutputWavLabel RawLAPPDData +SelectSingleLAPPD false +SelectedLAPPD 0 +loadPSEC 1 +loadPPS 1 +loadOffsets 1 + + diff --git a/configfiles/EventBuilderV2_AmBe/MRDDataDecoderConfig b/configfiles/EventBuilderV2_AmBe/MRDDataDecoderConfig new file mode 100644 index 000000000..d9937ca9a --- /dev/null +++ b/configfiles/EventBuilderV2_AmBe/MRDDataDecoderConfig @@ -0,0 +1,2 @@ +verbosity 0 +DaylightSavingsSpring 1 diff --git a/configfiles/EventBuilderV2_AmBe/PMTDataDecoderConfig b/configfiles/EventBuilderV2_AmBe/PMTDataDecoderConfig new file mode 100644 index 000000000..cca7bb6b5 --- /dev/null +++ b/configfiles/EventBuilderV2_AmBe/PMTDataDecoderConfig @@ -0,0 +1,5 @@ +verbosity 1 +ADCCountsToBuildWaves 0 +Mode Offline +OffsetVME03 0 +OffsetVME01 0 diff --git a/configfiles/EventBuilderV2_AmBe/PhaseIIADCCalibratorConfig b/configfiles/EventBuilderV2_AmBe/PhaseIIADCCalibratorConfig new file mode 100644 index 000000000..158dc6ed1 --- /dev/null +++ b/configfiles/EventBuilderV2_AmBe/PhaseIIADCCalibratorConfig @@ -0,0 +1,15 @@ +# PhaseIIADCCalibrator config file + +verbosity 0 + +BaselineEstimationType ze3ra_multi +NumBaselineSamples 15 +NumSubWaveforms 10 + +SamplesPerBaselineEstimate 2000 +BaselineUncertaintyTolerance 2 +PCritical 0.01 +MakeCalLEDWaveforms 0 + +EventBuilding 1 +ExecutesPerBuild 10 diff --git a/configfiles/EventBuilderV2_AmBe/PhaseIIADCHitFinderConfig b/configfiles/EventBuilderV2_AmBe/PhaseIIADCHitFinderConfig new file mode 100644 index 000000000..d183b7b27 --- /dev/null +++ b/configfiles/EventBuilderV2_AmBe/PhaseIIADCHitFinderConfig @@ -0,0 +1,10 @@ +verbosity 0 + +UseLEDWaveforms 0 + +PulseFindingApproach threshold +PulseWindowType dynamic +DefaultADCThreshold 7 +DefaultThresholdType relative + +EventBuilding 1 diff --git a/configfiles/EventBuilderV2_AmBe/SaveConfigInfoConfig b/configfiles/EventBuilderV2_AmBe/SaveConfigInfoConfig new file mode 100644 index 000000000..569dcf758 --- /dev/null +++ b/configfiles/EventBuilderV2_AmBe/SaveConfigInfoConfig @@ -0,0 +1,3 @@ +verbosity 5 +OutFileName config_info.txt +FullDepth 0 diff --git a/configfiles/EventBuilderV2_AmBe/ToolChainConfig b/configfiles/EventBuilderV2_AmBe/ToolChainConfig new file mode 100644 index 000000000..f3b457d9c --- /dev/null +++ b/configfiles/EventBuilderV2_AmBe/ToolChainConfig @@ -0,0 +1,23 @@ +#ToolChain dynamic setup file + +##### Runtime Paramiters ##### +verbose 1 +error_level 0 # 0= do not exit, 1= exit on unhandeled errors only, 2= exit on unhandeled errors and handeled errors +attempt_recover 1 + +###### Logging ##### +log_mode Interactive # Interactive=cout , Remote= remote logging system "serservice_name Remote_Logging" , Local = local file log; +log_local_path ./log +log_service LogStore + +###### Service discovery ##### +service_publish_sec -1 +service_kick_sec -1 + +##### Tools To Add ##### +Tools_File ./configfiles/EventBuilderV2_AmBe/ToolsConfig + +##### Run Type ##### +Inline -1 +Interactive 0 + diff --git a/configfiles/EventBuilderV2_AmBe/ToolsConfig b/configfiles/EventBuilderV2_AmBe/ToolsConfig new file mode 100644 index 000000000..47ef4d26f --- /dev/null +++ b/configfiles/EventBuilderV2_AmBe/ToolsConfig @@ -0,0 +1,21 @@ +LoadGeometry LoadGeometry ./configfiles/LoadGeometry/LoadGeometryConfig +EBLoadRaw EBLoadRaw ./configfiles/EventBuilderV2_AmBe/EBLoadRawConfig + +PMTDataDecoder PMTDataDecoder ./configfiles/EventBuilderV2_AmBe/PMTDataDecoderConfig +#MRDDataDecoder MRDDataDecoder ./configfiles/EventBuilderV2_AmBe/MRDDataDecoderConfig +TriggerDataDecoder TriggerDataDecoder ./configfiles/EventBuilderV2_AmBe/TriggerDataDecoderConfig +#LAPPDLoadStore LAPPDLoadStore ./configfiles/EventBuilderV2_AmBe/LAPPDLoadStoreConfig + +PhaseIIADCCalibrator PhaseIIADCCalibrator ./configfiles/EventBuilderV2_AmBe/PhaseIIADCCalibratorConfig +PhaseIIADCHitFinder PhaseIIADCHitFinder ./configfiles/EventBuilderV2_AmBe/PhaseIIADCHitFinderConfig + +EBTriggerGrouper EBTriggerGrouper ./configfiles/EventBuilderV2_AmBe/EBTriggerGrouperConfig +EBPMT EBPMT ./configfiles/EventBuilderV2_AmBe/EBPMTConfig +#EBMRD EBMRD ./configfiles/EventBuilderV2_AmBe/EBMRDConfig +#EBLAPPD EBLAPPD ./configfiles/EventBuilderV2_AmBe/EBLAPPDConfig + +SaveConfigInfo SaveConfigInfo ./configfiles/EventBuilderV2_AmBe/SaveConfigInfoConfig + +EBSaver EBSaver ./configfiles/EventBuilderV2_AmBe/EBSaverConfig + + diff --git a/configfiles/EventBuilderV2_AmBe/TriggerDataDecoderConfig b/configfiles/EventBuilderV2_AmBe/TriggerDataDecoderConfig new file mode 100644 index 000000000..a8ef6641f --- /dev/null +++ b/configfiles/EventBuilderV2_AmBe/TriggerDataDecoderConfig @@ -0,0 +1,3 @@ +verbosity 0 +StoreTrigOverlap 0 +ReadTrigOverlap 0 diff --git a/configfiles/EventBuilderV2_AmBe/my_files.txt b/configfiles/EventBuilderV2_AmBe/my_files.txt new file mode 100644 index 000000000..7697d0d84 --- /dev/null +++ b/configfiles/EventBuilderV2_AmBe/my_files.txt @@ -0,0 +1,3 @@ +/pnfs/annie/persistent/raw/raw/4499/RAWDataR4499S0p0 +/pnfs/annie/persistent/raw/raw/4499/RAWDataR4499S0p1 +/pnfs/annie/persistent/raw/raw/4499/RAWDataR4499S0p2 diff --git a/configfiles/EventBuilderV2_cosmic/EBLAPPDConfig b/configfiles/EventBuilderV2_cosmic/EBLAPPDConfig new file mode 100644 index 000000000..a81b1ce94 --- /dev/null +++ b/configfiles/EventBuilderV2_cosmic/EBLAPPDConfig @@ -0,0 +1,7 @@ +verbosityEBLAPPD 0 +matchTargetTrigger 14 +matchTolerance_ns 400000 +#matchTolerance_ns 10000 +exePerMatch 500 + +matchToAllTriggers 0 diff --git a/configfiles/EventBuilderV2_cosmic/EBLoadRawConfig b/configfiles/EventBuilderV2_cosmic/EBLoadRawConfig new file mode 100644 index 000000000..e7567be01 --- /dev/null +++ b/configfiles/EventBuilderV2_cosmic/EBLoadRawConfig @@ -0,0 +1,10 @@ +verbosityEBLoadRaw 2 +ReadTriggerOverlap 1 + +InputFile ./configfiles/EventBuilderV2_cosmic/my_files.txt + +LoadPMT 1 +LoadMRD 1 +LoadCTC 1 +LoadLAPPD 0 + diff --git a/configfiles/EventBuilderV2_cosmic/EBMRDConfig b/configfiles/EventBuilderV2_cosmic/EBMRDConfig new file mode 100644 index 000000000..5edc61080 --- /dev/null +++ b/configfiles/EventBuilderV2_cosmic/EBMRDConfig @@ -0,0 +1,5 @@ +verbosityEBMRD 0 +matchTargetTrigger 36 +matchTolerance_ns 3000000 +matchToAllTriggers 0 +exePerMatch 500 diff --git a/configfiles/EventBuilderV2_cosmic/EBPMTConfig b/configfiles/EventBuilderV2_cosmic/EBPMTConfig new file mode 100644 index 000000000..57bb72693 --- /dev/null +++ b/configfiles/EventBuilderV2_cosmic/EBPMTConfig @@ -0,0 +1,4 @@ +verbosityEBPMT 0 +matchTargetTrigger 46 +matchTolerance_ns 1000 +matchToAllTriggers 1 diff --git a/configfiles/EventBuilderV2_cosmic/EBSaverConfig b/configfiles/EventBuilderV2_cosmic/EBSaverConfig new file mode 100644 index 000000000..09378e248 --- /dev/null +++ b/configfiles/EventBuilderV2_cosmic/EBSaverConfig @@ -0,0 +1,10 @@ +verbosityEBSaver 1 + +savePMT 1 +saveMRD 1 +saveCTC 1 +saveLAPPD 0 +saveRunInfo 1 +saveBeamInfo 0 + +beamInfoFileName beamfetcher_tree.root diff --git a/configfiles/EventBuilderV2_cosmic/EBTriggerGrouperConfig b/configfiles/EventBuilderV2_cosmic/EBTriggerGrouperConfig new file mode 100644 index 000000000..0d8a2cae2 --- /dev/null +++ b/configfiles/EventBuilderV2_cosmic/EBTriggerGrouperConfig @@ -0,0 +1,28 @@ +verbosityEBTG 0 +GroupMode beam +GroupTolerance 3000000 +GroupTrigWord 14 //undelayed beam + +groupBeam 0 +BeamTolerance 25000000 + +groupCosmic 1 +CosmicTriggerMain 36 + +groupLaser 0 +LaserTolerance 10000 + +groupLED 0 +#LEDTriggerMain 31 +#LEDTolerance 10000 + +groupAmBe 0 +AmBeTolerance 10000 # 10us for testing +AmBeTriggerMain 11 + +groupPPS 0 + +groupNuMI 0 + +maxNumAllowedInBuffer 20000 + diff --git a/configfiles/EventBuilderV2_cosmic/LAPPDLoadStoreConfig b/configfiles/EventBuilderV2_cosmic/LAPPDLoadStoreConfig new file mode 100644 index 000000000..daa420ebe --- /dev/null +++ b/configfiles/EventBuilderV2_cosmic/LAPPDLoadStoreConfig @@ -0,0 +1,39 @@ + General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +NUM_VECTOR_METADATA 103 #Fixed META vector size +LAPPDchannelOffset 1000 +NChannels 30 + +LAPPDStoreReadInVerbosity 0 + +mergingModeReadIn 0 +RawDataInputWavLabel RawWaveform +RawDataOutputWavLabel RawLAPPDData +BoardIndexLabel BoardIndex #Label of the vector of read out boards + +PsecReceiveMode 1 +stopEntries 10000000000 + +DoPedSubtraction 0 +Nboards 6 #Number of pedestal files to be read in +PedinputfileTXT ../Pedestals/Laser2024Feb/P +PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 + + +Pedinputfile1 ../Pedestals/PEDS_ACDC_board0.txt +Pedinputfile2 ../Pedestals/PEDS_ACDC_board1.txt + + +ReadStore 0 +num_vector_data 7795 +num_vector_pps 16 +OutputWavLabel RawLAPPDData +SelectSingleLAPPD false +SelectedLAPPD 0 +loadPSEC 1 +loadPPS 1 +loadOffsets 1 + + diff --git a/configfiles/EventBuilderV2_cosmic/MRDDataDecoderConfig b/configfiles/EventBuilderV2_cosmic/MRDDataDecoderConfig new file mode 100644 index 000000000..d9937ca9a --- /dev/null +++ b/configfiles/EventBuilderV2_cosmic/MRDDataDecoderConfig @@ -0,0 +1,2 @@ +verbosity 0 +DaylightSavingsSpring 1 diff --git a/configfiles/EventBuilderV2_cosmic/PMTDataDecoderConfig b/configfiles/EventBuilderV2_cosmic/PMTDataDecoderConfig new file mode 100644 index 000000000..cca7bb6b5 --- /dev/null +++ b/configfiles/EventBuilderV2_cosmic/PMTDataDecoderConfig @@ -0,0 +1,5 @@ +verbosity 1 +ADCCountsToBuildWaves 0 +Mode Offline +OffsetVME03 0 +OffsetVME01 0 diff --git a/configfiles/EventBuilderV2_cosmic/PhaseIIADCCalibratorConfig b/configfiles/EventBuilderV2_cosmic/PhaseIIADCCalibratorConfig new file mode 100644 index 000000000..158dc6ed1 --- /dev/null +++ b/configfiles/EventBuilderV2_cosmic/PhaseIIADCCalibratorConfig @@ -0,0 +1,15 @@ +# PhaseIIADCCalibrator config file + +verbosity 0 + +BaselineEstimationType ze3ra_multi +NumBaselineSamples 15 +NumSubWaveforms 10 + +SamplesPerBaselineEstimate 2000 +BaselineUncertaintyTolerance 2 +PCritical 0.01 +MakeCalLEDWaveforms 0 + +EventBuilding 1 +ExecutesPerBuild 10 diff --git a/configfiles/EventBuilderV2_cosmic/PhaseIIADCHitFinderConfig b/configfiles/EventBuilderV2_cosmic/PhaseIIADCHitFinderConfig new file mode 100644 index 000000000..d183b7b27 --- /dev/null +++ b/configfiles/EventBuilderV2_cosmic/PhaseIIADCHitFinderConfig @@ -0,0 +1,10 @@ +verbosity 0 + +UseLEDWaveforms 0 + +PulseFindingApproach threshold +PulseWindowType dynamic +DefaultADCThreshold 7 +DefaultThresholdType relative + +EventBuilding 1 diff --git a/configfiles/EventBuilderV2_cosmic/SaveConfigInfoConfig b/configfiles/EventBuilderV2_cosmic/SaveConfigInfoConfig new file mode 100644 index 000000000..569dcf758 --- /dev/null +++ b/configfiles/EventBuilderV2_cosmic/SaveConfigInfoConfig @@ -0,0 +1,3 @@ +verbosity 5 +OutFileName config_info.txt +FullDepth 0 diff --git a/configfiles/EventBuilderV2_cosmic/ToolChainConfig b/configfiles/EventBuilderV2_cosmic/ToolChainConfig new file mode 100644 index 000000000..03ab2dfe1 --- /dev/null +++ b/configfiles/EventBuilderV2_cosmic/ToolChainConfig @@ -0,0 +1,23 @@ +#ToolChain dynamic setup file + +##### Runtime Paramiters ##### +verbose 1 +error_level 0 # 0= do not exit, 1= exit on unhandeled errors only, 2= exit on unhandeled errors and handeled errors +attempt_recover 1 + +###### Logging ##### +log_mode Interactive # Interactive=cout , Remote= remote logging system "serservice_name Remote_Logging" , Local = local file log; +log_local_path ./log +log_service LogStore + +###### Service discovery ##### +service_publish_sec -1 +service_kick_sec -1 + +##### Tools To Add ##### +Tools_File ./configfiles/EventBuilderV2_cosmic/ToolsConfig + +##### Run Type ##### +Inline -1 +Interactive 0 + diff --git a/configfiles/EventBuilderV2_cosmic/ToolsConfig b/configfiles/EventBuilderV2_cosmic/ToolsConfig new file mode 100644 index 000000000..22adf1923 --- /dev/null +++ b/configfiles/EventBuilderV2_cosmic/ToolsConfig @@ -0,0 +1,24 @@ +LoadGeometry LoadGeometry ./configfiles/LoadGeometry/LoadGeometryConfig +EBLoadRaw EBLoadRaw ./configfiles/EventBuilderV2_cosmic/EBLoadRawConfig + + +PMTDataDecoder PMTDataDecoder ./configfiles/EventBuilderV2_cosmic/PMTDataDecoderConfig +MRDDataDecoder MRDDataDecoder ./configfiles/EventBuilderV2_cosmic/MRDDataDecoderConfig +TriggerDataDecoder TriggerDataDecoder ./configfiles/EventBuilderV2_cosmic/TriggerDataDecoderConfig +#LAPPDLoadStore LAPPDLoadStore ./configfiles/EventBuilderV2_cosmic/LAPPDLoadStoreConfig + + +PhaseIIADCCalibrator PhaseIIADCCalibrator ./configfiles/EventBuilderV2_cosmic/PhaseIIADCCalibratorConfig +PhaseIIADCHitFinder PhaseIIADCHitFinder ./configfiles/EventBuilderV2_cosmic/PhaseIIADCHitFinderConfig + + +EBTriggerGrouper EBTriggerGrouper ./configfiles/EventBuilderV2_cosmic/EBTriggerGrouperConfig +EBPMT EBPMT ./configfiles/EventBuilderV2_cosmic/EBPMTConfig +EBMRD EBMRD ./configfiles/EventBuilderV2_cosmic/EBMRDConfig +#EBLAPPD EBLAPPD ./configfiles/EventBuilderV2_cosmic/EBLAPPDConfig + +SaveConfigInfo SaveConfigInfo ./configfiles/EventBuilderV2_cosmic/SaveConfigInfoConfig + +EBSaver EBSaver ./configfiles/EventBuilderV2_cosmic/EBSaverConfig + + diff --git a/configfiles/EventBuilderV2_cosmic/TriggerDataDecoderConfig b/configfiles/EventBuilderV2_cosmic/TriggerDataDecoderConfig new file mode 100644 index 000000000..a8ef6641f --- /dev/null +++ b/configfiles/EventBuilderV2_cosmic/TriggerDataDecoderConfig @@ -0,0 +1,3 @@ +verbosity 0 +StoreTrigOverlap 0 +ReadTrigOverlap 0 diff --git a/configfiles/EventBuilderV2_cosmic/my_files.txt b/configfiles/EventBuilderV2_cosmic/my_files.txt new file mode 100644 index 000000000..2792b0b48 --- /dev/null +++ b/configfiles/EventBuilderV2_cosmic/my_files.txt @@ -0,0 +1,14 @@ +/pnfs/annie/persistent/raw/raw/5088/RAWDataR5088S0p0 +/pnfs/annie/persistent/raw/raw/5088/RAWDataR5088S0p1 +/pnfs/annie/persistent/raw/raw/5088/RAWDataR5088S0p2 +/pnfs/annie/persistent/raw/raw/5088/RAWDataR5088S0p3 +/pnfs/annie/persistent/raw/raw/5088/RAWDataR5088S0p4 +/pnfs/annie/persistent/raw/raw/5088/RAWDataR5088S0p5 +/pnfs/annie/persistent/raw/raw/5088/RAWDataR5088S0p6 +/pnfs/annie/persistent/raw/raw/5088/RAWDataR5088S0p7 +/pnfs/annie/persistent/raw/raw/5088/RAWDataR5088S0p8 +/pnfs/annie/persistent/raw/raw/5088/RAWDataR5088S0p9 +/pnfs/annie/persistent/raw/raw/5088/RAWDataR5088S0p10 +/pnfs/annie/persistent/raw/raw/5088/RAWDataR5088S0p11 +/pnfs/annie/persistent/raw/raw/5088/RAWDataR5088S0p12 +/pnfs/annie/persistent/raw/raw/5088/RAWDataR5088S0p13 diff --git a/configfiles/EventBuilderV2_laser/EBLAPPDConfig b/configfiles/EventBuilderV2_laser/EBLAPPDConfig new file mode 100644 index 000000000..a81b1ce94 --- /dev/null +++ b/configfiles/EventBuilderV2_laser/EBLAPPDConfig @@ -0,0 +1,7 @@ +verbosityEBLAPPD 0 +matchTargetTrigger 14 +matchTolerance_ns 400000 +#matchTolerance_ns 10000 +exePerMatch 500 + +matchToAllTriggers 0 diff --git a/configfiles/EventBuilderV2_laser/EBLoadRawConfig b/configfiles/EventBuilderV2_laser/EBLoadRawConfig new file mode 100644 index 000000000..63966d0cb --- /dev/null +++ b/configfiles/EventBuilderV2_laser/EBLoadRawConfig @@ -0,0 +1,10 @@ +verbosityEBLoadRaw 2 +ReadTriggerOverlap 1 + +InputFile ./configfiles/EventBuilderV2/my_files.txt + +LoadPMT 1 +LoadMRD 0 +LoadCTC 1 +LoadLAPPD 1 + diff --git a/configfiles/EventBuilderV2_laser/EBMRDConfig b/configfiles/EventBuilderV2_laser/EBMRDConfig new file mode 100644 index 000000000..a4797b1f1 --- /dev/null +++ b/configfiles/EventBuilderV2_laser/EBMRDConfig @@ -0,0 +1,5 @@ +verbosityEBMRD 0 +matchTargetTrigger 8 +matchTolerance_ns 3000000 +matchToAllTriggers 0 +exePerMatch 500 diff --git a/configfiles/EventBuilderV2_laser/EBPMTConfig b/configfiles/EventBuilderV2_laser/EBPMTConfig new file mode 100644 index 000000000..57bb72693 --- /dev/null +++ b/configfiles/EventBuilderV2_laser/EBPMTConfig @@ -0,0 +1,4 @@ +verbosityEBPMT 0 +matchTargetTrigger 46 +matchTolerance_ns 1000 +matchToAllTriggers 1 diff --git a/configfiles/EventBuilderV2_laser/EBSaverConfig b/configfiles/EventBuilderV2_laser/EBSaverConfig new file mode 100644 index 000000000..4753d1a76 --- /dev/null +++ b/configfiles/EventBuilderV2_laser/EBSaverConfig @@ -0,0 +1,10 @@ +verbosityEBSaver 1 + +savePMT 1 +saveMRD 0 +saveCTC 1 +saveLAPPD 1 +saveRunInfo 1 +saveBeamInfo 1 + +beamInfoFileName beamfetcher_tree.root diff --git a/configfiles/EventBuilderV2_laser/EBTriggerGrouperConfig b/configfiles/EventBuilderV2_laser/EBTriggerGrouperConfig new file mode 100644 index 000000000..87e6e3976 --- /dev/null +++ b/configfiles/EventBuilderV2_laser/EBTriggerGrouperConfig @@ -0,0 +1,30 @@ +verbosityEBTG 0 + +# beam triggers are always there, even in AmBe runs. We know they are meaningless to group beam trigger when we know there is 100% no beam, but again redundancy is not bad if it's not harmful +GroupMode beam +GroupTolerance 3000000 +GroupTrigWord 14 //undelayed beam + +groupBeam 0 +BeamTolerance 25000000 + +groupCosmic 0 +CosmicTriggerMain 36 + +groupLaser 1 +LaserTolerance 10000 + +groupLED 0 +#LEDTriggerMain 31 +#LEDTolerance 10000 + +groupAmBe 0 +AmBeTolerance 10000 # 10us for testing +AmBeTriggerMain 11 + +groupPPS 0 + +groupNuMI 0 + +maxNumAllowedInBuffer 20000 + diff --git a/configfiles/EventBuilderV2_laser/LAPPDLoadStoreConfig b/configfiles/EventBuilderV2_laser/LAPPDLoadStoreConfig new file mode 100644 index 000000000..daa420ebe --- /dev/null +++ b/configfiles/EventBuilderV2_laser/LAPPDLoadStoreConfig @@ -0,0 +1,39 @@ + General Parameters +Nsamples 256 #Number of samples in a waveform +SampleSize 100 #Sample size for baseline substraction +TrigChannel 5 #Specified channel the trigger signal will be on +NUM_VECTOR_METADATA 103 #Fixed META vector size +LAPPDchannelOffset 1000 +NChannels 30 + +LAPPDStoreReadInVerbosity 0 + +mergingModeReadIn 0 +RawDataInputWavLabel RawWaveform +RawDataOutputWavLabel RawLAPPDData +BoardIndexLabel BoardIndex #Label of the vector of read out boards + +PsecReceiveMode 1 +stopEntries 10000000000 + +DoPedSubtraction 0 +Nboards 6 #Number of pedestal files to be read in +PedinputfileTXT ../Pedestals/Laser2024Feb/P +PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 + + +Pedinputfile1 ../Pedestals/PEDS_ACDC_board0.txt +Pedinputfile2 ../Pedestals/PEDS_ACDC_board1.txt + + +ReadStore 0 +num_vector_data 7795 +num_vector_pps 16 +OutputWavLabel RawLAPPDData +SelectSingleLAPPD false +SelectedLAPPD 0 +loadPSEC 1 +loadPPS 1 +loadOffsets 1 + + diff --git a/configfiles/EventBuilderV2_laser/MRDDataDecoderConfig b/configfiles/EventBuilderV2_laser/MRDDataDecoderConfig new file mode 100644 index 000000000..d9937ca9a --- /dev/null +++ b/configfiles/EventBuilderV2_laser/MRDDataDecoderConfig @@ -0,0 +1,2 @@ +verbosity 0 +DaylightSavingsSpring 1 diff --git a/configfiles/EventBuilderV2_laser/PMTDataDecoderConfig b/configfiles/EventBuilderV2_laser/PMTDataDecoderConfig new file mode 100644 index 000000000..cca7bb6b5 --- /dev/null +++ b/configfiles/EventBuilderV2_laser/PMTDataDecoderConfig @@ -0,0 +1,5 @@ +verbosity 1 +ADCCountsToBuildWaves 0 +Mode Offline +OffsetVME03 0 +OffsetVME01 0 diff --git a/configfiles/EventBuilderV2_laser/PhaseIIADCCalibratorConfig b/configfiles/EventBuilderV2_laser/PhaseIIADCCalibratorConfig new file mode 100644 index 000000000..158dc6ed1 --- /dev/null +++ b/configfiles/EventBuilderV2_laser/PhaseIIADCCalibratorConfig @@ -0,0 +1,15 @@ +# PhaseIIADCCalibrator config file + +verbosity 0 + +BaselineEstimationType ze3ra_multi +NumBaselineSamples 15 +NumSubWaveforms 10 + +SamplesPerBaselineEstimate 2000 +BaselineUncertaintyTolerance 2 +PCritical 0.01 +MakeCalLEDWaveforms 0 + +EventBuilding 1 +ExecutesPerBuild 10 diff --git a/configfiles/EventBuilderV2_laser/PhaseIIADCHitFinderConfig b/configfiles/EventBuilderV2_laser/PhaseIIADCHitFinderConfig new file mode 100644 index 000000000..d183b7b27 --- /dev/null +++ b/configfiles/EventBuilderV2_laser/PhaseIIADCHitFinderConfig @@ -0,0 +1,10 @@ +verbosity 0 + +UseLEDWaveforms 0 + +PulseFindingApproach threshold +PulseWindowType dynamic +DefaultADCThreshold 7 +DefaultThresholdType relative + +EventBuilding 1 diff --git a/configfiles/EventBuilderV2_laser/SaveConfigInfoConfig b/configfiles/EventBuilderV2_laser/SaveConfigInfoConfig new file mode 100644 index 000000000..569dcf758 --- /dev/null +++ b/configfiles/EventBuilderV2_laser/SaveConfigInfoConfig @@ -0,0 +1,3 @@ +verbosity 5 +OutFileName config_info.txt +FullDepth 0 diff --git a/configfiles/EventBuilderV2_laser/ToolChainConfig b/configfiles/EventBuilderV2_laser/ToolChainConfig new file mode 100644 index 000000000..51af536df --- /dev/null +++ b/configfiles/EventBuilderV2_laser/ToolChainConfig @@ -0,0 +1,23 @@ +#ToolChain dynamic setup file + +##### Runtime Paramiters ##### +verbose 1 +error_level 0 # 0= do not exit, 1= exit on unhandeled errors only, 2= exit on unhandeled errors and handeled errors +attempt_recover 1 + +###### Logging ##### +log_mode Interactive # Interactive=cout , Remote= remote logging system "serservice_name Remote_Logging" , Local = local file log; +log_local_path ./log +log_service LogStore + +###### Service discovery ##### +service_publish_sec -1 +service_kick_sec -1 + +##### Tools To Add ##### +Tools_File ./configfiles/EventBuilderV2_laser/ToolsConfig + +##### Run Type ##### +Inline -1 +Interactive 0 + diff --git a/configfiles/EventBuilderV2_laser/ToolsConfig b/configfiles/EventBuilderV2_laser/ToolsConfig new file mode 100644 index 000000000..47a99a73a --- /dev/null +++ b/configfiles/EventBuilderV2_laser/ToolsConfig @@ -0,0 +1,24 @@ +LoadGeometry LoadGeometry ./configfiles/LoadGeometry/LoadGeometryConfig +EBLoadRaw EBLoadRaw ./configfiles/EventBuilderV2_laser/EBLoadRawConfig + + +PMTDataDecoder PMTDataDecoder ./configfiles/EventBuilderV2_laser/PMTDataDecoderConfig +#MRDDataDecoder MRDDataDecoder ./configfiles/EventBuilderV2_laser/MRDDataDecoderConfig +TriggerDataDecoder TriggerDataDecoder ./configfiles/EventBuilderV2_laser/TriggerDataDecoderConfig +LAPPDLoadStore LAPPDLoadStore ./configfiles/EventBuilderV2_laser/LAPPDLoadStoreConfig + + +PhaseIIADCCalibrator PhaseIIADCCalibrator ./configfiles/EventBuilderV2_laser/PhaseIIADCCalibratorConfig +PhaseIIADCHitFinder PhaseIIADCHitFinder ./configfiles/EventBuilderV2_laser/PhaseIIADCHitFinderConfig + + +EBTriggerGrouper EBTriggerGrouper ./configfiles/EventBuilderV2_laser/EBTriggerGrouperConfig +EBPMT EBPMT ./configfiles/EventBuilderV2_laser/EBPMTConfig +#EBMRD EBMRD ./configfiles/EventBuilderV2_laser/EBMRDConfig +EBLAPPD EBLAPPD ./configfiles/EventBuilderV2_laser/EBLAPPDConfig + +SaveConfigInfo SaveConfigInfo ./configfiles/EventBuilderV2_laser/SaveConfigInfoConfig + +EBSaver EBSaver ./configfiles/EventBuilderV2_laser/EBSaverConfig + + diff --git a/configfiles/EventBuilderV2_laser/TriggerDataDecoderConfig b/configfiles/EventBuilderV2_laser/TriggerDataDecoderConfig new file mode 100644 index 000000000..a8ef6641f --- /dev/null +++ b/configfiles/EventBuilderV2_laser/TriggerDataDecoderConfig @@ -0,0 +1,3 @@ +verbosity 0 +StoreTrigOverlap 0 +ReadTrigOverlap 0 diff --git a/configfiles/EventBuilderV2_laser/my_files.txt b/configfiles/EventBuilderV2_laser/my_files.txt new file mode 100644 index 000000000..7697d0d84 --- /dev/null +++ b/configfiles/EventBuilderV2_laser/my_files.txt @@ -0,0 +1,3 @@ +/pnfs/annie/persistent/raw/raw/4499/RAWDataR4499S0p0 +/pnfs/annie/persistent/raw/raw/4499/RAWDataR4499S0p1 +/pnfs/annie/persistent/raw/raw/4499/RAWDataR4499S0p2 From 1377e0ecaf1e4b01472a25e7e5b36dced9242d55 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:24:38 -0600 Subject: [PATCH 108/163] ANNIEEventTreeMaker Config file creation scripts Adjusted the python scripts that generate the Config file to include run type, avoiding the need to have separate toolchains for different run types --- configfiles/BeamClusterAnalysis/config.py | 40 +++++++++++++++---- .../BeamClusterAnalysis/configLAPPD.py | 29 +++++++++++--- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/configfiles/BeamClusterAnalysis/config.py b/configfiles/BeamClusterAnalysis/config.py index 503d6c38c..a32c21ee7 100644 --- a/configfiles/BeamClusterAnalysis/config.py +++ b/configfiles/BeamClusterAnalysis/config.py @@ -3,6 +3,7 @@ run = sys.argv[1] pi = sys.argv[2] pf = sys.argv[3] +run_type = sys.argv[4] file = open('ANNIEEventTreeMakerConfig', "w") @@ -10,17 +11,27 @@ file.write('\n') file.write('fillAllTriggers 1\n') file.write('fill_singleTrigger 0\n') +file.write('fill_singleTriggerWord 0\n') file.write('fillLAPPDEventsOnly 0\n') file.write('TankCluster_fill 1\n') file.write('cluster_TankHitInfo_fill 1\n') file.write('\n') file.write('OutputFile BeamCluster_' + str(run) + '_' + str(pi) + '_' + str(pf) + '.ntuple.root\n') file.write('TankClusterProcessing 1\n') -file.write('MRDClusterProcessing 1\n') file.write('TriggerProcessing 1\n') file.write('TankHitInfo_fill 1\n') -file.write('MRDHitInfo_fill 1\n') -file.write('MRDReco_fill 1\n') +file.write('\n') + +if run_type == 'beam' or run_type == 'cosmic': + file.write('MRDClusterProcessing 1\n') + file.write('MRDHitInfo_fill 1\n') + file.write('MRDReco_fill 1\n') +else: + file.write('MRDClusterProcessing 0\n') + file.write('MRDHitInfo_fill 0\n') + file.write('MRDReco_fill 0\n') +file.write('\n') + file.write('SiPMPulseInfo_fill 0\n') file.write('fillCleanEventsOnly 0\n') file.write('MCTruth_fill 0\n') @@ -28,12 +39,25 @@ file.write('TankReco_fill 0\n') file.write('RecoDebug_fill 0\n') file.write('muonTruthRecoDiff_fill 0\n') -file.write('IsData 1\n') +file.write('isData 1\n') file.write('HasGenie 0') +file.write('LAPPD_MC_fill 0\n') file.write('\n') -file.write('LAPPDData_fill 1\n') -file.write('LAPPDReco_fill 1\n') -file.write('RWMBRF_fill 1\n') -file.write('LAPPD_PPS_fill 1\n') + +if run_type == 'beam' or run_type == 'laser': + file.write('LAPPDData_fill 1\n') + file.write('LAPPDReco_fill 1\n') + file.write('LAPPD_PPS_fill 1\n') + file.write('LAPPD_Waveform_fill 1\n') +else: + file.write('LAPPDData_fill 0\n') + file.write('LAPPDReco_fill 0\n') + file.write('LAPPD_PPS_fill 0\n') + file.write('LAPPD_Waveform_fill 0\n') + +if run_type == 'beam': + file.write('RWMBRF_fill 1\n') +else: + file.write('RWMBRF_fill 0\n') file.close() diff --git a/configfiles/BeamClusterAnalysis/configLAPPD.py b/configfiles/BeamClusterAnalysis/configLAPPD.py index ebc81f50d..108b577ce 100644 --- a/configfiles/BeamClusterAnalysis/configLAPPD.py +++ b/configfiles/BeamClusterAnalysis/configLAPPD.py @@ -3,6 +3,7 @@ run = sys.argv[1] pi = sys.argv[2] pf = sys.argv[3] +run_type = sys.argv[4] file = open('ANNIEEventTreeMakerConfig', "w") @@ -10,17 +11,28 @@ file.write('\n') file.write('fillAllTriggers 1\n') file.write('fill_singleTrigger 0\n') +file.write('fill_singleTriggerWord 0\n') file.write('fillLAPPDEventsOnly 0\n') file.write('TankCluster_fill 1\n') file.write('cluster_TankHitInfo_fill 1\n') file.write('\n') file.write('OutputFile BeamCluster_LAPPD_' + str(run) + '_' + str(pi) + '_' + str(pf) + '.ntuple.root\n') file.write('TankClusterProcessing 1\n') -file.write('MRDClusterProcessing 1\n') file.write('TriggerProcessing 1\n') file.write('TankHitInfo_fill 1\n') -file.write('MRDHitInfo_fill 1\n') -file.write('MRDReco_fill 1\n') +file.write('\n') + +# if we are running the LAPPDs at this stage, it is either a laser or beam run. Only beam runs need MRD info +if run_type == 'beam': + file.write('MRDClusterProcessing 1\n') + file.write('MRDHitInfo_fill 1\n') + file.write('MRDReco_fill 1\n') +else: + file.write('MRDClusterProcessing 0\n') + file.write('MRDHitInfo_fill 0\n') + file.write('MRDReco_fill 0\n') +file.write('\n') + file.write('SiPMPulseInfo_fill 0\n') file.write('fillCleanEventsOnly 0\n') file.write('MCTruth_fill 0\n') @@ -28,12 +40,19 @@ file.write('TankReco_fill 0\n') file.write('RecoDebug_fill 0\n') file.write('muonTruthRecoDiff_fill 0\n') -file.write('IsData 1\n') +file.write('isData 1\n') file.write('HasGenie 0') +file.write('LAPPD_MC_fill 0\n') file.write('\n') + file.write('LAPPDData_fill 1\n') file.write('LAPPDReco_fill 1\n') -file.write('RWMBRF_fill 1\n') file.write('LAPPD_PPS_fill 1\n') +file.write('LAPPD_Waveform_fill 1\n') + +if run_type == 'beam': + file.write('RWMBRF_fill 1\n') +else: + file.write('RWMBRF_fill 0\n') file.close() From 4974d574fd4e5440281e70958945b23b183e4253 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 18 Dec 2024 09:11:04 -0600 Subject: [PATCH 109/163] Update EBSaver.h Marvin has recommended to initialize this to 0 to remedy the inconsistent printed total number of events we sometimes see, depending if you do `make` or `make -jn`. --- UserTools/EBSaver/EBSaver.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UserTools/EBSaver/EBSaver.h b/UserTools/EBSaver/EBSaver.h index 57a960f7d..f2dedb5f6 100644 --- a/UserTools/EBSaver/EBSaver.h +++ b/UserTools/EBSaver/EBSaver.h @@ -105,7 +105,7 @@ class EBSaver : public Tool int savePerExe; - int TotalBuiltEventsNumber; + int TotalBuiltEventsNumber = 0; int TotalBuiltPMTNumber; int TotalBuiltMRDNumber; int TotalBuiltLAPPDNumber; From 8719960bda7dc57b28d9d30f36a65a185f99fc97 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Mon, 13 Jan 2025 13:35:07 -0600 Subject: [PATCH 110/163] Config script creator update Added an additional step to generate the ToolsConfig, which will help in running the toolchain over different run types --- configfiles/BeamClusterAnalysis/config.py | 38 +++++++++++++++++-- .../BeamClusterAnalysis/configLAPPD.py | 4 +- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/configfiles/BeamClusterAnalysis/config.py b/configfiles/BeamClusterAnalysis/config.py index a32c21ee7..59b316b2f 100644 --- a/configfiles/BeamClusterAnalysis/config.py +++ b/configfiles/BeamClusterAnalysis/config.py @@ -5,6 +5,9 @@ pf = sys.argv[3] run_type = sys.argv[4] +# Create TreeMaker config and ToolsConfig based on run type + +# ------------------------------------------- file = open('ANNIEEventTreeMakerConfig', "w") file.write('ANNIEEventTreeMakerVerbosity 0\n') @@ -22,7 +25,7 @@ file.write('TankHitInfo_fill 1\n') file.write('\n') -if run_type == 'beam' or run_type == 'cosmic': +if run_type == 'beam' or run_type == 'cosmic' or run_type == 'beam_39': file.write('MRDClusterProcessing 1\n') file.write('MRDHitInfo_fill 1\n') file.write('MRDReco_fill 1\n') @@ -44,7 +47,7 @@ file.write('LAPPD_MC_fill 0\n') file.write('\n') -if run_type == 'beam' or run_type == 'laser': +if run_type == 'beam' or run_type == 'laser' or run_type == 'beam_39': file.write('LAPPDData_fill 1\n') file.write('LAPPDReco_fill 1\n') file.write('LAPPD_PPS_fill 1\n') @@ -55,9 +58,38 @@ file.write('LAPPD_PPS_fill 0\n') file.write('LAPPD_Waveform_fill 0\n') -if run_type == 'beam': +if run_type == 'beam' or run_type == 'beam_39': file.write('RWMBRF_fill 1\n') else: file.write('RWMBRF_fill 0\n') file.close() + + +# ------------------------------------------- +file2 = open('ToolsConfig', "w") + +file2.write('myLoadANNIEEvent LoadANNIEEvent ./configfiles/BeamClusterAnalysis/LoadANNIEEventConfig\n') +file2.write('myLoadGeometry LoadGeometry ./configfiles/LoadGeometry/LoadGeometryConfig\n') + +if run_type == 'beam' or run_type == 'cosmic' or run_type == 'beam_39': + file2.write('myTimeClustering TimeClustering configfiles/BeamClusterAnalysis/TimeClusteringConfig\n') + file2.write('myFindMrdTracks FindMrdTracks configfiles/BeamClusterAnalysis/FindMrdTracksConfig\n') + +file2.write('myClusterFinder ClusterFinder ./configfiles/BeamClusterAnalysis/ClusterFinderConfig\n') +file2.write('myClusterClassifiers ClusterClassifiers ./configfiles/BeamClusterAnalysis/ClusterClassifiersConfig\n') +file2.write('myEventSelector EventSelector ./configfiles/BeamClusterAnalysis/EventSelectorConfig\n') + +if run_type == 'beam' or run_type == 'laser' or run_type == 'beam_39': + file2.write('LAPPDLoadStore LAPPDLoadStore configfiles/LAPPDProcessedAna/Configs\n') + file2.write('LAPPDStoreReorder LAPPDStoreReorder configfiles/LAPPDProcessedAna/ConfigStoreReadIn\n') + file2.write('LAPPDTimeAlignment LAPPDTimeAlignment configfiles/LAPPDProcessedAna/ConfigPreProcess\n') + file2.write('LAPPDBaseline LAPPDBaseline configfiles/LAPPDProcessedAna/ConfigPreProcess\n') + file2.write('LAPPDThresReco LAPPDThresReco configfiles/LAPPDProcessedAna/ConfigPlot\n') + +if run_type == 'beam' or run_type == 'beam_39': + file2.write('FitRWMWaveform FitRWMWaveform ./configfiles/BeamClusterAnalysis/FitRWMWaveformConfig\n') + +file2.write('ANNIEEventTreeMaker ANNIEEventTreeMaker ./configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig\n') + +file2.close() diff --git a/configfiles/BeamClusterAnalysis/configLAPPD.py b/configfiles/BeamClusterAnalysis/configLAPPD.py index 108b577ce..d30d32010 100644 --- a/configfiles/BeamClusterAnalysis/configLAPPD.py +++ b/configfiles/BeamClusterAnalysis/configLAPPD.py @@ -23,7 +23,7 @@ file.write('\n') # if we are running the LAPPDs at this stage, it is either a laser or beam run. Only beam runs need MRD info -if run_type == 'beam': +if run_type == 'beam' or run_type == 'beam_39': file.write('MRDClusterProcessing 1\n') file.write('MRDHitInfo_fill 1\n') file.write('MRDReco_fill 1\n') @@ -50,7 +50,7 @@ file.write('LAPPD_PPS_fill 1\n') file.write('LAPPD_Waveform_fill 1\n') -if run_type == 'beam': +if run_type == 'beam' or run_type == 'beam_39': file.write('RWMBRF_fill 1\n') else: file.write('RWMBRF_fill 0\n') From eac9b03addf588d92d3ec0c86d25d39699d14598 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Fri, 17 Jan 2025 11:14:58 -0600 Subject: [PATCH 111/163] Update config.py forgot new line --- configfiles/BeamClusterAnalysis/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configfiles/BeamClusterAnalysis/config.py b/configfiles/BeamClusterAnalysis/config.py index 59b316b2f..4db0b0871 100644 --- a/configfiles/BeamClusterAnalysis/config.py +++ b/configfiles/BeamClusterAnalysis/config.py @@ -43,7 +43,7 @@ file.write('RecoDebug_fill 0\n') file.write('muonTruthRecoDiff_fill 0\n') file.write('isData 1\n') -file.write('HasGenie 0') +file.write('HasGenie 0\n') file.write('LAPPD_MC_fill 0\n') file.write('\n') From 04964af09598e07fc6b4b782a724e18a9f694b72 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Fri, 17 Jan 2025 11:15:12 -0600 Subject: [PATCH 112/163] Update configLAPPD.py --- configfiles/BeamClusterAnalysis/configLAPPD.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configfiles/BeamClusterAnalysis/configLAPPD.py b/configfiles/BeamClusterAnalysis/configLAPPD.py index d30d32010..7f9a24efe 100644 --- a/configfiles/BeamClusterAnalysis/configLAPPD.py +++ b/configfiles/BeamClusterAnalysis/configLAPPD.py @@ -41,7 +41,7 @@ file.write('RecoDebug_fill 0\n') file.write('muonTruthRecoDiff_fill 0\n') file.write('isData 1\n') -file.write('HasGenie 0') +file.write('HasGenie 0\n') file.write('LAPPD_MC_fill 0\n') file.write('\n') From f418e6703b28a59052552fc66b21e7fee8c2cd74 Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Sun, 19 Jan 2025 14:50:21 -0600 Subject: [PATCH 113/163] Add debug info to print channel keys, leave them commented for possible debug purpose Add event index for LAPPDLoadStore to correctly load event offsets. If there are multiple LAPPDs in one part file but the frequency of triggering is very different, previous indexing will give unexpected bug --- UserTools/EBPMT/EBPMT.cpp | 12 ++- UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp | 104 +++++++++++++------- UserTools/LAPPDLoadStore/LAPPDLoadStore.h | 4 + 3 files changed, 81 insertions(+), 39 deletions(-) diff --git a/UserTools/EBPMT/EBPMT.cpp b/UserTools/EBPMT/EBPMT.cpp index 641507833..72b21cb3f 100644 --- a/UserTools/EBPMT/EBPMT.cpp +++ b/UserTools/EBPMT/EBPMT.cpp @@ -124,6 +124,16 @@ bool EBPMT::Execute() Log("EBPMT: ChannelKey.size() = " + std::to_string(ChannelKey.size()) + " >= NumWavesInCompleteSet = " + std::to_string(NumWavesInCompleteSet) + " or AlmostCompleteWaveforms.at(PMTCounterTimeNs) = " + std::to_string(AlmostCompleteWaveforms[PMTCounterTimeNs] >= 5), v_debug, verbosityEBPMT); + + // print all elements in vector ChannelKey +// cout<<"EBPMT: ChannelKey: "; +// for (unsigned long ch : ChannelKey) +// { +// cout<= NumWavesInCompleteSet || ((ChannelKey.size() == NumWavesInCompleteSet - 1) && (AlmostCompleteWaveforms[PMTCounterTimeNs] >= 5))) { Log("EBPMT: Emplace hit map to FinishedHits, ChannelKey.size() = " + std::to_string(ChannelKey.size()) + " >= NumWavesInCompleteSet = " + std::to_string(NumWavesInCompleteSet) + " or AlmostCompleteWaveforms.at(PMTCounterTimeNs) = " + std::to_string(AlmostCompleteWaveforms.at(PMTCounterTimeNs) >= 5), v_debug, verbosityEBPMT); @@ -481,4 +491,4 @@ void EBPMT::CorrectVMEOffset() } } Log("EBPMT: Corrected VME Offset for " + std::to_string(correctionApplied) + " timestamps", v_message, verbosityEBPMT); -} \ No newline at end of file +} diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp index 92edebf4d..d41d16ab3 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.cpp @@ -140,6 +140,7 @@ bool LAPPDLoadStore::Initialise(std::string configfile, DataModel &data) m_data->Stores["ANNIEEvent"]->Set("isBLsubtracted", isBLsub); m_data->Stores["ANNIEEvent"]->Set("isCFD", isCFD); + LAPPDEventIndex_ID = {0, 0, 0, 0, 0}; // initialize for five LAPPDs if (loadOffsets) LoadOffsetsAndCorrections(); if (LAPPDStoreReadInVerbosity > 11) @@ -870,7 +871,7 @@ bool LAPPDLoadStore::LoadData() } ReadBoards = dat.BoardIndex; Raw_buffer = dat.RawWaveform; - if(Raw_buffer.size() == 0 || ReadBoards.size() == 0) + if (Raw_buffer.size() == 0 || ReadBoards.size() == 0) { cout << "LAPPD Load Store, find Raw buffer size == 0 or ReadBoards size == 0" << endl; return false; @@ -1131,6 +1132,19 @@ bool LAPPDLoadStore::ParsePSECData() return false; } } + + + LAPPDEventIndex_ID[LAPPD_ID] += 1; + if (LAPPDStoreReadInVerbosity > 1) + { + cout << "Adding one new event with LAPPD_ID = " << LAPPD_ID << " to the LAPPDEventIndex_ID, now it is: " << endl; + for (int i = 0; i < LAPPDEventIndex_ID.size(); i++) + { + cout << LAPPDEventIndex_ID[i] << ", " << endl; + } + cout << endl; + } + if (LAPPDStoreReadInVerbosity > 2) cout << "Parsed all boards for this event finished" << endl; return true; @@ -1140,6 +1154,8 @@ bool LAPPDLoadStore::DoPedestalSubtract() { if (LAPPDStoreReadInVerbosity > 0) cout << "LAPPDLoadStore::DoPedestalSubtract()" << endl; + if (DoPedSubtract == 0) + return true; Waveform tmpWave; vector> VecTmpWave; int pedval, val; @@ -1276,6 +1292,14 @@ void LAPPDLoadStore::SaveTimeStamps() void LAPPDLoadStore::SaveOffsets() { + int LoadingOffsetID = LAPPD_ID; + if(LoadingOffsetID+1 > LAPPDEventIndex_ID.size()) + { + LAPPDEventIndex_ID.resize(LoadingOffsetID+1); + } + int GetOffsetIndex_byID = LAPPDEventIndex_ID[LoadingOffsetID]; + if(LAPPDStoreReadInVerbosity>0) + cout << "LAPPDStoreReadIn, SavingOffsets, LoadingOffset for LAPPD_ID: " << LoadingOffsetID << ", OffsetIndex of this event: " << GetOffsetIndex_byID << endl; std::string key = std::to_string(runNumber) + "_" + std::to_string(subRunNumber) + "_" + std::to_string(partFileNumber) + "_" + std::to_string(LAPPD_ID); @@ -1294,9 +1318,9 @@ void LAPPDLoadStore::SaveOffsets() int TS_PPSMissing = 0; // Check if the key exists and the index is within range for BGCorrections - if (BGCorrections.find(key) != BGCorrections.end() && eventNumberInPF < BGCorrections[key].size()) + if (BGCorrections.find(key) != BGCorrections.end() && GetOffsetIndex_byID < BGCorrections[key].size()) { - LAPPDBGCorrection = BGCorrections[key][eventNumberInPF]; + LAPPDBGCorrection = BGCorrections[key][GetOffsetIndex_byID]; } else { @@ -1306,14 +1330,14 @@ void LAPPDLoadStore::SaveOffsets() } else { - std::cerr << "Error: eventNumberInPF out of range for BGCorrections with key: " << key << std::endl; + std::cerr << "Error: GetOffsetIndex_byID out of range for BGCorrections with key: " << key << std::endl; } } // Repeat the checks for TSCorrections, Offsets_minus_ps, and Offsets - if (TSCorrections.find(key) != TSCorrections.end() && eventNumberInPF < TSCorrections[key].size()) + if (TSCorrections.find(key) != TSCorrections.end() && GetOffsetIndex_byID < TSCorrections[key].size()) { - LAPPDTSCorrection = TSCorrections[key][eventNumberInPF]; + LAPPDTSCorrection = TSCorrections[key][GetOffsetIndex_byID]; } else { @@ -1323,13 +1347,13 @@ void LAPPDLoadStore::SaveOffsets() } else { - std::cerr << "Error: eventNumberInPF out of range for TSCorrections with key: " << key << std::endl; + std::cerr << "Error: GetOffsetIndex_byID out of range for TSCorrections with key: " << key << std::endl; } } - if (Offsets_minus_ps.find(key) != Offsets_minus_ps.end() && eventNumberInPF < Offsets_minus_ps[key].size()) + if (Offsets_minus_ps.find(key) != Offsets_minus_ps.end() && GetOffsetIndex_byID < Offsets_minus_ps[key].size()) { - LAPPDOffset_minus_ps = Offsets_minus_ps[key][eventNumberInPF]; + LAPPDOffset_minus_ps = Offsets_minus_ps[key][GetOffsetIndex_byID]; } else { @@ -1339,13 +1363,13 @@ void LAPPDLoadStore::SaveOffsets() } else { - std::cerr << "Error: eventNumberInPF out of range for Offsets_minus_ps with key: " << key << std::endl; + std::cerr << "Error: GetOffsetIndex_byID out of range for Offsets_minus_ps with key: " << key << std::endl; } } - if (Offsets.find(key) != Offsets.end() && eventNumberInPF < Offsets[key].size()) + if (Offsets.find(key) != Offsets.end() && GetOffsetIndex_byID < Offsets[key].size()) { - LAPPDOffset = Offsets[key][eventNumberInPF]; + LAPPDOffset = Offsets[key][GetOffsetIndex_byID]; } else { @@ -1355,104 +1379,104 @@ void LAPPDLoadStore::SaveOffsets() } else { - std::cerr << "Error: eventNumberInPF out of range for Offsets with key: " << key << std::endl; + std::cerr << "Error: GetOffsetIndex_byID out of range for Offsets with key: " << key << std::endl; } } - if (BG_PPSBefore_loaded.find(key) != BG_PPSBefore_loaded.end() && eventNumberInPF < BG_PPSBefore_loaded[key].size()) + if (BG_PPSBefore_loaded.find(key) != BG_PPSBefore_loaded.end() && GetOffsetIndex_byID < BG_PPSBefore_loaded[key].size()) { - BG_PPSBefore = BG_PPSBefore_loaded[key][eventNumberInPF]; + BG_PPSBefore = BG_PPSBefore_loaded[key][GetOffsetIndex_byID]; } else { if (BG_PPSBefore_loaded.find(key) == BG_PPSBefore_loaded.end()) std::cerr << "Error: Key not found in BG_PPSBefore_loaded: " << key << std::endl; else - std::cerr << "Error: eventNumberInPF out of range for BG_PPSBefore_loaded with key: " << key << std::endl; + std::cerr << "Error: GetOffsetIndex_byID out of range for BG_PPSBefore_loaded with key: " << key << std::endl; } - if (BG_PPSAfter_loaded.find(key) != BG_PPSAfter_loaded.end() && eventNumberInPF < BG_PPSAfter_loaded[key].size()) + if (BG_PPSAfter_loaded.find(key) != BG_PPSAfter_loaded.end() && GetOffsetIndex_byID < BG_PPSAfter_loaded[key].size()) { - BG_PPSAfter = BG_PPSAfter_loaded[key][eventNumberInPF]; + BG_PPSAfter = BG_PPSAfter_loaded[key][GetOffsetIndex_byID]; } else { if (BG_PPSAfter_loaded.find(key) == BG_PPSAfter_loaded.end()) std::cerr << "Error: Key not found in BG_PPSAfter_loaded: " << key << std::endl; else - std::cerr << "Error: eventNumberInPF out of range for BG_PPSAfter_loaded with key: " << key << std::endl; + std::cerr << "Error: GetOffsetIndex_byID out of range for BG_PPSAfter_loaded with key: " << key << std::endl; } - if (BG_PPSDiff_loaded.find(key) != BG_PPSDiff_loaded.end() && eventNumberInPF < BG_PPSDiff_loaded[key].size()) + if (BG_PPSDiff_loaded.find(key) != BG_PPSDiff_loaded.end() && GetOffsetIndex_byID < BG_PPSDiff_loaded[key].size()) { - BG_PPSDiff = BG_PPSDiff_loaded[key][eventNumberInPF]; + BG_PPSDiff = BG_PPSDiff_loaded[key][GetOffsetIndex_byID]; } else { if (BG_PPSDiff_loaded.find(key) == BG_PPSDiff_loaded.end()) std::cerr << "Error: Key not found in BG_PPSDiff_loaded: " << key << std::endl; else - std::cerr << "Error: eventNumberInPF out of range for BG_PPSDiff_loaded with key: " << key << std::endl; + std::cerr << "Error: GetOffsetIndex_byID out of range for BG_PPSDiff_loaded with key: " << key << std::endl; } - if (BG_PPSMissing_loaded.find(key) != BG_PPSMissing_loaded.end() && eventNumberInPF < BG_PPSMissing_loaded[key].size()) + if (BG_PPSMissing_loaded.find(key) != BG_PPSMissing_loaded.end() && GetOffsetIndex_byID < BG_PPSMissing_loaded[key].size()) { - BG_PPSMissing = BG_PPSMissing_loaded[key][eventNumberInPF]; + BG_PPSMissing = BG_PPSMissing_loaded[key][GetOffsetIndex_byID]; } else { if (BG_PPSMissing_loaded.find(key) == BG_PPSMissing_loaded.end()) std::cerr << "Error: Key not found in BG_PPSMissing_loaded: " << key << std::endl; else - std::cerr << "Error: eventNumberInPF out of range for BG_PPSMissing_loaded with key: " << key << std::endl; + std::cerr << "Error: GetOffsetIndex_byID out of range for BG_PPSMissing_loaded with key: " << key << std::endl; } - if (TS_PPSBefore_loaded.find(key) != TS_PPSBefore_loaded.end() && eventNumberInPF < TS_PPSBefore_loaded[key].size()) + if (TS_PPSBefore_loaded.find(key) != TS_PPSBefore_loaded.end() && GetOffsetIndex_byID < TS_PPSBefore_loaded[key].size()) { - TS_PPSBefore = TS_PPSBefore_loaded[key][eventNumberInPF]; + TS_PPSBefore = TS_PPSBefore_loaded[key][GetOffsetIndex_byID]; } else { if (TS_PPSBefore_loaded.find(key) == TS_PPSBefore_loaded.end()) std::cerr << "Error: Key not found in TS_PPSBefore_loaded: " << key << std::endl; else - std::cerr << "Error: eventNumberInPF out of range for TS_PPSBefore_loaded with key: " << key << std::endl; + std::cerr << "Error: GetOffsetIndex_byID out of range for TS_PPSBefore_loaded with key: " << key << std::endl; } - if (TS_PPSAfter_loaded.find(key) != TS_PPSAfter_loaded.end() && eventNumberInPF < TS_PPSAfter_loaded[key].size()) + if (TS_PPSAfter_loaded.find(key) != TS_PPSAfter_loaded.end() && GetOffsetIndex_byID < TS_PPSAfter_loaded[key].size()) { - TS_PPSAfter = TS_PPSAfter_loaded[key][eventNumberInPF]; + TS_PPSAfter = TS_PPSAfter_loaded[key][GetOffsetIndex_byID]; } else { if (TS_PPSAfter_loaded.find(key) == TS_PPSAfter_loaded.end()) std::cerr << "Error: Key not found in TS_PPSAfter_loaded: " << key << std::endl; else - std::cerr << "Error: eventNumberInPF out of range for TS_PPSAfter_loaded with key: " << key << std::endl; + std::cerr << "Error: GetOffsetIndex_byID out of range for TS_PPSAfter_loaded with key: " << key << std::endl; } - if (TS_PPSDiff_loaded.find(key) != TS_PPSDiff_loaded.end() && eventNumberInPF < TS_PPSDiff_loaded[key].size()) + if (TS_PPSDiff_loaded.find(key) != TS_PPSDiff_loaded.end() && GetOffsetIndex_byID < TS_PPSDiff_loaded[key].size()) { - TS_PPSDiff = TS_PPSDiff_loaded[key][eventNumberInPF]; + TS_PPSDiff = TS_PPSDiff_loaded[key][GetOffsetIndex_byID]; } else { if (TS_PPSDiff_loaded.find(key) == TS_PPSDiff_loaded.end()) std::cerr << "Error: Key not found in TS_PPSDiff_loaded: " << key << std::endl; else - std::cerr << "Error: eventNumberInPF out of range for TS_PPSDiff_loaded with key: " << key << std::endl; + std::cerr << "Error: GetOffsetIndex_byID out of range for TS_PPSDiff_loaded with key: " << key << std::endl; } - if (TS_PPSMissing_loaded.find(key) != TS_PPSMissing_loaded.end() && eventNumberInPF < TS_PPSMissing_loaded[key].size()) + if (TS_PPSMissing_loaded.find(key) != TS_PPSMissing_loaded.end() && GetOffsetIndex_byID < TS_PPSMissing_loaded[key].size()) { - TS_PPSMissing = TS_PPSMissing_loaded[key][eventNumberInPF]; + TS_PPSMissing = TS_PPSMissing_loaded[key][GetOffsetIndex_byID]; } else { if (TS_PPSMissing_loaded.find(key) == TS_PPSMissing_loaded.end()) std::cerr << "Error: Key not found in TS_PPSMissing_loaded: " << key << std::endl; else - std::cerr << "Error: eventNumberInPF out of range for TS_PPSMissing_loaded with key: " << key << std::endl; + std::cerr << "Error: GetOffsetIndex_byID out of range for TS_PPSMissing_loaded with key: " << key << std::endl; } // start to fill data @@ -1536,7 +1560,6 @@ void LAPPDLoadStore::LoadOffsetsAndCorrections() tree->SetBranchAddress("TS_driftCorrection_ns", &TS_driftCorrection_ns); tree->SetBranchAddress("BG_driftCorrection_ns", &BG_driftCorrection_ns); - Long64_t nentries = tree->GetEntries(); cout << "LAPPDStoreReadIn Loading offsets and corrections, total entries: " << nentries << endl; for (Long64_t i = 0; i < nentries; ++i) @@ -1602,6 +1625,11 @@ void LAPPDLoadStore::LoadRunInfo() if (partFileNumber != PFNumberBeforeGet) { eventNumberInPF = 0; + // also set all value of LAPPDEventIndex_ID to be 0 + for (int i = 0; i < LAPPDEventIndex_ID.size(); i++) + { + LAPPDEventIndex_ID[i] = 0; + } } else { diff --git a/UserTools/LAPPDLoadStore/LAPPDLoadStore.h b/UserTools/LAPPDLoadStore/LAPPDLoadStore.h index 3f0a91140..3deb5eea4 100644 --- a/UserTools/LAPPDLoadStore/LAPPDLoadStore.h +++ b/UserTools/LAPPDLoadStore/LAPPDLoadStore.h @@ -140,6 +140,10 @@ class LAPPDLoadStore : public Tool std::map LAPPDBGCorrection; std::map LAPPDOSInMinusPS; std::map DataStreams; + std::vector LAPPDEventIndex_ID; // for each LAPPD ID, count the index of current loaded event + // For example, this part file may have a ID=0 event, b ID=1 event, while loading data object c and loaded 3 ID=0 and 4 ID=1, I may have + // LAPPDEventIndex_ID = {3, 4} + // save PPS info for the second order correction std::map LAPPDBG_PPSBefore; std::map LAPPDBG_PPSAfter; From 9852ca03642b32c664391794e3b92ff01b883a7a Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Sun, 19 Jan 2025 22:27:15 -0600 Subject: [PATCH 114/163] Add EBMRD for EventBuildingV2 tool chain --- UserTools/EBMRD/EBMRD.cpp | 237 ++++++++++++++++++++++++++++++++++ UserTools/EBMRD/EBMRD.h | 63 +++++++++ UserTools/EBMRD/README.md | 35 +++++ UserTools/Factory/Factory.cpp | 1 + UserTools/Unity.h | 1 + 5 files changed, 337 insertions(+) create mode 100644 UserTools/EBMRD/EBMRD.cpp create mode 100644 UserTools/EBMRD/EBMRD.h create mode 100644 UserTools/EBMRD/README.md diff --git a/UserTools/EBMRD/EBMRD.cpp b/UserTools/EBMRD/EBMRD.cpp new file mode 100644 index 000000000..c00047144 --- /dev/null +++ b/UserTools/EBMRD/EBMRD.cpp @@ -0,0 +1,237 @@ +#include "EBMRD.h" + +EBMRD::EBMRD() : Tool() {} + +bool EBMRD::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + m_variables.Get("verbosityEBMRD", verbosityEBMRD); + matchTargetTrigger = 8; + m_variables.Get("matchTargetTrigger", matchTargetTrigger); + matchTolerance_ns = 2000000; // default 2ms + m_variables.Get("matchTolerance_ns", matchTolerance_ns); + exePerMatch = 500; + m_variables.Get("exePerMatch", exePerMatch); + matchToAllTriggers = 0; + m_variables.Get("matchToAllTriggers", matchToAllTriggers); + + matchedMRDNumber = 0; + + return true; +} + +bool EBMRD::Execute() +{ + m_data->CStore.Get("RunCode", currentRunCode); + + m_data->CStore.Get("MRDEvents", MRDEvents); + m_data->CStore.Get("MRDEventTriggerTypes", MRDEventTriggerTypes); + m_data->CStore.Get("MRDBeamLoopback", MRDBeamLoopback); + m_data->CStore.Get("MRDCosmicLoopback", MRDCosmicLoopback); + m_data->CStore.Get("NewMRDDataAvailable", NewMRDDataAvailable); + + m_data->CStore.Get("PairedMRDTriggerTimestamp", PairedCTCTimeStamps); + m_data->CStore.Get("PairedMRDTimeStamps", PairedMRDTimeStamps); + + Log("EBMRD: NewMRDDataAvailable = " + std::to_string(NewMRDDataAvailable) + ", Current loaded MRDEvents size is " + std::to_string(MRDEvents.size()), v_message, verbosityEBMRD); + Log("EBMRD: Current buffer size is " + std::to_string(MRDEventsBuffer.size()), v_message, verbosityEBMRD); + // loop the MRDEvents, save every event to MRDEventsBuffer if it's not already in the buffer + int newLoadedEvents = 0; + for (std::pair>> p : MRDEvents) + { + uint64_t MTCtime = p.first; + std::vector> WaveMap = p.second; + // if find the MTCtime in the PairedMRDTimeStamps, then skip + if (PairedMRDTimeStamps.size() > 0) + { + bool skip = false; + for (std::pair> pair : PairedMRDTimeStamps) + { + for (uint64_t t : pair.second) + { + if (t == MTCtime) + { + skip = true; + break; + } + } + if (skip) + break; + } + if (skip) + continue; + } + if (MRDEventsBuffer.find(MTCtime) == MRDEventsBuffer.end()) + { + MRDEventsBuffer.emplace(MTCtime, WaveMap); + newLoadedEvents++; + } + } + Log("EBMRD: Finished loading MRDEvents to buffer, Buffer_MRDEvents size is now " + std::to_string(MRDEventsBuffer.size()) + " new loaded events = " + std::to_string(newLoadedEvents), v_message, verbosityEBMRD); + + bool stopLoop = false; + m_data->vars.Get("StopLoop", stopLoop); + int runNum = thisRunNum; + m_data->vars.Get("RunNumber", thisRunNum); + bool ForceMRDMatching = false; + m_data->CStore.Get("ForceMRDMatching", ForceMRDMatching); + + if (exeNum % exePerMatch == 0 || runNum != thisRunNum || stopLoop || ForceMRDMatching) + { + Log("EBMRD: exeNum = " + std::to_string(exeNum) + ". Doing matching now", v_message, verbosityEBMRD); + if (matchToAllTriggers) + { + Matching(0, 0); + } + else + { + bool BeamTriggerGroupped = false; + m_data->CStore.Get("BeamTriggerGroupped", BeamTriggerGroupped); + bool CosmicTriggerGroupped = false; + m_data->CStore.Get("CosmicTriggerGroupped", CosmicTriggerGroupped); + bool NuMITriggerGroupped = false; + m_data->CStore.Get("NuMITriggerGroupped", NuMITriggerGroupped); + + + if (BeamTriggerGroupped) + Matching(matchTargetTrigger, 14); + if (CosmicTriggerGroupped) + { + Matching(36, 36); + Matching(45, 46); + } + if(NuMITriggerGroupped) + Matching(42, 46); + + if(!BeamTriggerGroupped && !CosmicTriggerGroupped && !NuMITriggerGroupped) + Log("EBMRD: BeamTriggerGroupped and CosmicTriggerGroupped are false, no beam trigger groupped in the grouper, stop matching", v_message, verbosityEBMRD); + } + } + + m_data->CStore.Set("PairedMRDTriggerTimestamp", PairedCTCTimeStamps); + m_data->CStore.Set("PairedMRDTimeStamps", PairedMRDTimeStamps); + m_data->CStore.Set("PairedMRD_TriggerIndex", PairedMRD_TriggerIndex); + m_data->CStore.Set("MRDHitMapRunCode", MRDHitMapRunCode); + + exeNum++; + return true; +} + +bool EBMRD::Finalise() +{ + Log("\033[1;34mEBMRD: Finalising\033[0m", v_message, verbosityEBMRD); + Log("EBMRD: Matched MRD number = " + std::to_string(matchedMRDNumber), v_message, verbosityEBMRD); + Log("EBMRD: Unmatched MRD number = " + std::to_string(MRDEventsBuffer.size()), v_message, verbosityEBMRD); + return true; +} + +bool EBMRD::Matching(int targetTrigger, int matchToTrack) +{ + cout << "\033[1;34m******* EBMRD : Matching *******\033[0m" << endl; + std::map>> GroupedTriggersInTotal; // each map is a group of triggers, with the key is the target trigger word + m_data->CStore.Get("GroupedTriggersInTotal", GroupedTriggersInTotal); + + Log("EBMRD: Got GroupedTriggersInTotal[14] size: " + std::to_string(GroupedTriggersInTotal[14].size()), v_message, verbosityEBMRD); + + vector matchedMRDTimes; + std::map matchedNumberInTrack; + + // loop the MRDEventsBuffer keys, and loop all the grouped triggers + // in each group of trigger, find the target trigger word and it's time + // fine the minimum time difference, if smaller than matchTolerance_ns, then save the time to PairedCTCTimeStamps and PairedMRDTimeStamps + int loopNum = 0; + for (std::pair>> mrdpair : MRDEventsBuffer) + { + if (verbosityEBMRD > 11) + cout << "******************EBMRD: new MRD event: " << loopNum << endl; + uint64_t MTCtime = mrdpair.first; + std::vector> WaveMap = mrdpair.second; + // set minDT to 5 min + uint64_t minDT = 5 * 60 * 1e9; + uint64_t minDTTrigger = 0; + uint64_t dt = 0; + uint32_t matchedTrigWord = 0; + int matchedTrack = 0; + int matchedIndex = 0; + for (std::pair>> pair : GroupedTriggersInTotal) + { + int TrackTriggerWord = pair.first; + if (TrackTriggerWord != matchToTrack && !matchToAllTriggers) + { + Log("EBMRD: Skipping TrackTriggerWord " + std::to_string(TrackTriggerWord), v_debug, verbosityEBMRD); + continue; + } + if (matchedNumberInTrack.find(TrackTriggerWord) == matchedNumberInTrack.end()) + matchedNumberInTrack.emplace(TrackTriggerWord, 0); + + vector> groupedTriggers = pair.second; + + for (int i = 0; i < groupedTriggers.size(); i++) + { + map groupedTrigger = groupedTriggers.at(i); + // itearte over all the grouped triggers, if the value is target trigger, then calculate the time difference + for (std::pair p : groupedTrigger) + { + if (matchToAllTriggers || p.second == targetTrigger) + { + if (MTCtime > p.first) + { + dt = MTCtime - p.first; + } + else + { + dt = p.first - MTCtime; + } + if (dt < minDT) + { + minDT = dt; + minDTTrigger = p.first; + matchedTrigWord = p.second; + matchedIndex = p.second; + matchedTrack = TrackTriggerWord; + + // if(verbosityEBMRD > 11) cout<<"EBMRD: dt: "< pair : matchedNumberInTrack) + { + Log("EBMRD: Match finished, matched number in Track " + std::to_string(pair.first) + " is " + std::to_string(pair.second), v_message, verbosityEBMRD); + } + + return true; +} \ No newline at end of file diff --git a/UserTools/EBMRD/EBMRD.h b/UserTools/EBMRD/EBMRD.h new file mode 100644 index 000000000..0722d5ae3 --- /dev/null +++ b/UserTools/EBMRD/EBMRD.h @@ -0,0 +1,63 @@ +#ifndef EBMRD_H +#define EBMRD_H + +#include +#include + +#include "Tool.h" + +/** + * \class EBPMT + * + * $Author: Yue Feng $ + * $Date: 2024/04 $ + * Contact: yuef@iaistate.edu + * + */ + +class EBMRD : public Tool +{ + +public: + EBMRD(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + bool Matching(int targetTrigger, int matchToTrack); + +private: + int verbosityEBMRD; + int matchTargetTrigger; + uint64_t matchTolerance_ns; + + int currentRunCode; + + int v_message = 1; + int v_warning = 2; + int v_error = 3; + int v_debug = 4; + + int matchedMRDNumber = 0; + int exeNum = 0; + + std::map>> MRDEvents; // Key: {MTCTime}, value: "WaveMap" with key (CardID,ChannelID), value FinishedWaveform + std::map MRDEventTriggerTypes; // Key: {MTCTime}, value: string noting what type of trigger occured for the event + std::map MRDBeamLoopback; // Key: {MTCTime}, value: string noting what type of trigger occured for the event + std::map MRDCosmicLoopback; // KEY: {MTCTime}, value: Cosmic loopback TDC value + + std::map>> MRDEventsBuffer; + + bool NewMRDDataAvailable; + + std::map> PairedCTCTimeStamps; + std::map> PairedMRD_TriggerIndex; + std::map> PairedMRDTimeStamps; + std::map MRDHitMapRunCode; // Key: {MTCTime}, value: RunCode + + bool matchToAllTriggers; + + int thisRunNum; + int exePerMatch; +}; + +#endif diff --git a/UserTools/EBMRD/README.md b/UserTools/EBMRD/README.md new file mode 100644 index 000000000..3aed04355 --- /dev/null +++ b/UserTools/EBMRD/README.md @@ -0,0 +1,35 @@ +# EBMRD + +EBMRD tool is a part of Event Building version 2 tool chain. +For reference slides, see: +https://annie-docdb.fnal.gov/cgi-bin/sso/ShowDocument?docid=5633 + +EBMRD match the MRD timestamp to grouped trigger, and save the matching results to CStore for EBSaver. + +## Data + + +**PairedCTCTimeStamps** +After matching, the matched trigger timestamp will be saved here. The key is the main trigger word for each run type. +Saved as PairedMRDTriggerTimestamp in CStore. + +**PairedMRDTimeStamps** +After matching, the matched MRD timestamp will be saved here. The key is the main trigger word for each run type. +This and PairedCTCTimeStamps have the same index. A little bit dangerous, but overall works well. +Saved as PairedMRDTimeStamps in CStore + + +## Configuration + +**matchTargetTrigger** +This gives which trigger word that the MRD timestamps should be matched to. + +**matchTolerance_ns** +This gives the maximum allowed time tolerance between the MRD timestmap and the target trigger timestamp. + +**exePerMatch** +This gives how many loops need to be past for one matching between MRD timestmaps and target trigger timestamps. +500 is generally fine with beam runs. 100 would be better for AmBe runs + +**matchToAllTriggers** +1 or 0. 1 means match MRD timestamps to all possible triggers, 0 means only match to the target trigger. diff --git a/UserTools/Factory/Factory.cpp b/UserTools/Factory/Factory.cpp index c986c48b7..98ead3503 100644 --- a/UserTools/Factory/Factory.cpp +++ b/UserTools/Factory/Factory.cpp @@ -174,5 +174,6 @@ if (tool=="BackTracker") ret=new BackTracker; if (tool=="PrintDQ") ret=new PrintDQ; if (tool=="AssignBunchTimingMC") ret=new AssignBunchTimingMC; if (tool=="FitRWMWaveform") ret=new FitRWMWaveform; +if (tool=="EBMRD") ret=new EBMRD; return ret; } diff --git a/UserTools/Unity.h b/UserTools/Unity.h index 7e64d4e9b..372300682 100644 --- a/UserTools/Unity.h +++ b/UserTools/Unity.h @@ -182,3 +182,4 @@ #include "PrintDQ.h" #include "AssignBunchTimingMC.h" #include "FitRWMWaveform.h" +#include "EBMRD.h" From 9441e33bedc5e27c84dfc8370541145cfb37be8d Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Sun, 19 Jan 2025 22:57:37 -0600 Subject: [PATCH 115/163] Add EBTriggerGrouper tool for EBV2 --- .../EBTriggerGrouper/EBTriggerGrouper.cpp | 745 ++++++++++++++++++ UserTools/EBTriggerGrouper/EBTriggerGrouper.h | 124 +++ UserTools/EBTriggerGrouper/README.md | 32 + UserTools/Factory/Factory.cpp | 1 + UserTools/Unity.h | 2 + 5 files changed, 904 insertions(+) create mode 100644 UserTools/EBTriggerGrouper/EBTriggerGrouper.cpp create mode 100644 UserTools/EBTriggerGrouper/EBTriggerGrouper.h create mode 100644 UserTools/EBTriggerGrouper/README.md diff --git a/UserTools/EBTriggerGrouper/EBTriggerGrouper.cpp b/UserTools/EBTriggerGrouper/EBTriggerGrouper.cpp new file mode 100644 index 000000000..afd2b0946 --- /dev/null +++ b/UserTools/EBTriggerGrouper/EBTriggerGrouper.cpp @@ -0,0 +1,745 @@ +#include "EBTriggerGrouper.h" + +EBTriggerGrouper::EBTriggerGrouper() : Tool() {} + +bool EBTriggerGrouper::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + m_variables.Get("verbosityEBTG", verbosityEBTG); + savePath = ""; + m_variables.Get("savePath", savePath); + m_variables.Get("GroupMode", GroupMode); + m_variables.Get("GroupTolerance", GroupTolerance); + m_variables.Get("GroupTrigWord", GroupTrigWord); + + TimeToTriggerWordMap = new std::map>; + TimeToTriggerWordMapComplete = new std::map>; + + groupBeam = true; + m_variables.Get("groupBeam", groupBeam); + groupCosmic = false; + m_variables.Get("groupCosmic", groupCosmic); + groupLaser = true; + m_variables.Get("groupLaser", groupLaser); + groupLED = false; + m_variables.Get("groupLED", groupLED); + groupAmBe = false; + m_variables.Get("groupAmBe", groupAmBe); + groupPPS = false; + m_variables.Get("groupPPS", groupPPS); + groupNuMI = true; + m_variables.Get("groupNuMI", groupNuMI); + + BeamTriggerMain = 14; + BeamTolerance = 3000000; // use 3 ms here, the spill time difference is 66ms + m_variables.Get("BeamTolerance", BeamTolerance); + BeamTriggers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 14, 37, 38, 40, 41, 46}; + m_data->CStore.Set("BeamTriggersUsedForGroupping", BeamTriggers); + m_data->CStore.Set("BeamTriggerMain", BeamTriggerMain); + + LaserTriggerMain = 47; + m_variables.Get("LaserTriggerMain", LaserTriggerMain); + LaserTolerance = 1000; // 1us + m_variables.Get("LaserTolerance", LaserTolerance); + LaserTriggers = {47, 46}; // 47 first, then 46, (~232ns in run 4692 data) + m_data->CStore.Set("LaserTriggersUsedForGroupping", LaserTriggers); + + PPSTriggerMain = 32; + PPSTolerance = 30000; // 30 us + m_variables.Get("PPSTolerance", PPSTolerance); + PPSTriggers = {32, 34}; // 32 first, then 34, (~20us in run 4802 data) + m_data->CStore.Set("PPSTriggersUsedForGroupping", PPSTriggers); + + CosmicTriggerMain = 45; // TODO need to check + m_variables.Get("CosmicTriggerMain", CosmicTriggerMain); + CosmicTolerance = 100; // 330000ns, TODO + m_variables.Get("CosmicTolerance", CosmicTolerance); + CosmicTriggers = {44, 45, 36, 27, 28, 29, 30, 46}; // TODO: check the trigger words in cosmic run + m_data->CStore.Set("CosmicTriggersUsedForGroupping", CosmicTriggers); + + LEDTriggerMain = 31; // need to check + m_variables.Get("LEDTriggerMain", LEDTriggerMain); + LEDTolerance = 1000; // 1ms 440ns in LED run 4792 + m_variables.Get("LEDTolerance", LEDTolerance); + LEDTriggers = {33, 22, 31, 43, 46}; // in run 4792 [[22, 33], [4160001224, 4160001664]] + m_data->CStore.Set("LEDTriggersUsedForGroupping", LEDTriggers); + + AmBeTriggerMain = 11; // TODO: need to check + m_variables.Get("AmBeTriggerMain", AmBeTriggerMain); + AmBeTolerance = 5000; // 2336 in Ambe run 4707 + m_variables.Get("AmBeTolerance", AmBeTolerance); + AmBeTriggers = {11, 12, 15, 19, 46}; // in run 4707 [[19, 12, 15, 11], [21275647928, 21275647936, 21275647952, 21275650264]] + m_data->CStore.Set("AmBeTriggersUsedForGroupping", AmBeTriggers); + + NuMITriggerMain = 42; + m_variables.Get("NuMITriggerMain", NuMITriggerMain); + NuMITolerance = 100; // 100ns + m_variables.Get("NuMITolerance", NuMITolerance); + NuMITriggers = {42, 46}; // + m_data->CStore.Set("NuMITriggersUsedForGroupping", NuMITriggers); + + StoreTotalEntry = 0; + + maxNumAllowedInBuffer = 10000; + m_variables.Get("maxNumAllowedInBuffer", maxNumAllowedInBuffer); + Log("EBTG: maxNumAllowedInBuffer = " + std::to_string(maxNumAllowedInBuffer), v_message, verbosityEBTG); + + return true; +} + +bool EBTriggerGrouper::Execute() +{ + bool NewCTCDataAvailable = false; + m_data->CStore.Get("NewCTCDataAvailable", NewCTCDataAvailable); + Log("EBTG: NewCTCDataAvailable = " + std::to_string(NewCTCDataAvailable), v_message, verbosityEBTG); + bool FileProcessingComplete = false; + m_data->CStore.Get("FileProcessingComplete", FileProcessingComplete); + if (FileProcessingComplete) + { + Log("EBTG: FileProcessingComplete = " + std::to_string(FileProcessingComplete), v_message, verbosityEBTG); + return true; + } + if (!NewCTCDataAvailable) + { + Log("EBTG: No new CTC data avaliable", v_message, verbosityEBTG); + return true; + } + Log("EBTG: Get Run information", v_message, verbosityEBTG); + m_data->CStore.Get("RunNumber", CurrentRunNum); + m_data->CStore.Get("SubRunNumber", CurrentSubrunNum); + int CurrentUsingPartNum = CurrentPartNum; + m_data->CStore.Get("PartFileNumber", CurrentPartNum); + m_data->CStore.Get("RunCode", currentRunCode); + + m_data->CStore.Get("usingTriggerOverlap", usingTriggerOverlap); + if (usingTriggerOverlap) + { + CurrentPartNum -= 1; + Log("EBTG: usingTriggerOverlap, CurrentPartNum was minused 1 to be " + std::to_string(CurrentPartNum), v_message, verbosityEBTG); + } + + /* + if (CurrentPartNum != CurrentUsingPartNum) + { + Log("EBTG: PartFileNumber changed from " + std::to_string(CurrentUsingPartNum) + " to " + std::to_string(CurrentPartNum) + " Clear buffer with size " + std::to_string(TrigTimeForGroup.size()), v_message, verbosityEBTG); + TrigTimeForGroup.clear(); + TrigWordForGroup.clear(); + }*/ + + Log("EBTG: Accessing new Trigger data in CStore", v_message, verbosityEBTG); + m_data->CStore.Get("TimeToTriggerWordMap", TimeToTriggerWordMap); + m_data->CStore.Get("TimeToTriggerWordMapComplete", TimeToTriggerWordMapComplete); + + // do grouping in the TimeToTriggerWordMap, remove the groupped triggers from both of them + // 1. load the trigger from TimeToTriggerWordMap to local buffer TrigTimeForGroup and TrigWordForGroup, clean it + // 2. group the triggers in buffer, save to GroupedTriggers, and remove grouped trigger from buffer + // 2.1 group trigger based on trigger word selection or time Tolerance relative to the target trigger + // 2.2 for left triggers, pair them with the grouped trigger using the same Tolerance fo cover triggers before the target trigger + // 2.3 run for different trigger tracks. like pps + + // Finally we should have: + // 1. GroupedTriggers: mutiple grouped trigger tracks + // 2. buffer: left triggers in buffer, not grouped + + vector TriggerToRemove; + for (auto it = TimeToTriggerWordMap->begin(); it != TimeToTriggerWordMap->end(); ++it) + { + uint64_t timestamp = it->first; + std::vector triggers = it->second; + bool stopLoading = false; + + // if found the target trigger in the trigger vector, stop loading to buffer. + if (usingTriggerOverlap) + { + for (auto trig = triggers.begin(); trig != triggers.end(); ++trig) + { + if (*trig == GroupTrigWord) + stopLoading = true; + Log("EBTG: when using TriggerOverlap, met the new target trigger " + std::to_string(GroupTrigWord) + ", stop loading to buffer", v_message, verbosityEBTG); + } + } + if (stopLoading) + break; + + for (auto trig = triggers.begin(); trig != triggers.end(); ++trig) + { + TrigTimeForGroup.push_back(timestamp); + TrigWordForGroup.push_back(*trig); + TriggerToRemove.push_back(timestamp); + StoreTotalEntry++; + if (verbosityEBTG > 11) + cout << "EBTG: TrigTimeForGroup: " << timestamp << " TrigWordForGroup: " << *trig << endl; + } + } + Log("EBTG: finish loading trigger from TimeToTriggerWordMap, buffer TrigTimeForGroup size = " + std::to_string(TrigTimeForGroup.size()) + ", loaded TimeToTriggerWordMap size = " + std::to_string(TimeToTriggerWordMap->size()), v_message, verbosityEBTG); + Log("EBTG: Start erase triggers from TimeToTriggerWordMap and TimeToTriggerWordMapComplete, TimeToTriggerWordMap and TimeToTriggerWordMapComplete size = " + std::to_string(TimeToTriggerWordMap->size()) + ", " + std::to_string(TimeToTriggerWordMapComplete->size()), v_message, verbosityEBTG); + for (int i = 0; i < TriggerToRemove.size(); i++) + { + TimeToTriggerWordMap->erase(TriggerToRemove[i]); + TimeToTriggerWordMapComplete->erase(TriggerToRemove[i]); + } + Log("EBTG: Finish erase triggers from TimeToTriggerWordMap and TimeToTriggerWordMapComplete, TimeToTriggerWordMap and TimeToTriggerWordMapComplete size = " + std::to_string(TimeToTriggerWordMap->size()) + ", " + std::to_string(TimeToTriggerWordMapComplete->size()), v_message, verbosityEBTG); + + /*{ + //TODO: this should be removed after later changes was made + Log("EBTG: Start grouping based on trigger word " + std::to_string(GroupTrigWord), v_message, verbosityEBTG); + + GroupByTolerance(); // remove grouped trigger in the function + FillByTolerance(); + //CleanBuffer(); + + Log("EBTG: grouping and filling finishes, buffer size is " + std::to_string(TrigTimeForGroup.size()) + ", now save to CStore", v_message, verbosityEBTG); + + m_data->CStore.Set("GroupedTriggers", GroupedTriggers); + }*/ + + m_data->CStore.Set("TrigTimeForGroup", TrigTimeForGroup); + m_data->CStore.Set("TrigWordForGroup", TrigWordForGroup); + + Log("EBTG: Start grouping for different trigger tracks", v_message, verbosityEBTG); + if (groupBeam) + { + Log("EBTG: Grouping Beam Triggers", v_message, verbosityEBTG); + int groupNum = GroupByTrigWord(BeamTriggerMain, BeamTriggers, BeamTolerance); + int fillNum = FillByTrigWord(BeamTriggerMain, BeamTriggers, BeamTolerance); + Log("EBTG: Found Beam Trigger group: " + std::to_string(groupNum) + ". Fill additional triggers to group: " + std::to_string(fillNum), v_message, verbosityEBTG); + m_data->CStore.Set("BeamTriggerGroupped", true); + } + else + { + m_data->CStore.Set("BeamTriggerGroupped", false); + } + + if (groupCosmic) + { + Log("EBTG: Grouping Cosmic Triggers", v_message, verbosityEBTG); + int groupNum = GroupByTrigWord(CosmicTriggerMain, CosmicTriggers, CosmicTolerance); + int fillNum = FillByTrigWord(CosmicTriggerMain, CosmicTriggers, CosmicTolerance); + Log("EBTG: Found Cosmic Trigger group: " + std::to_string(groupNum) + ". Fill additional triggers to group: " + std::to_string(fillNum), v_message, verbosityEBTG); + m_data->CStore.Set("CosmicTriggerGroupped", true); + } + else + { + m_data->CStore.Set("CosmicTriggerGroupped", false); + } + + if (groupLaser) + { + Log("EBTG: Grouping Laser Triggers", v_message, verbosityEBTG); + int groupNum = GroupByTrigWord(LaserTriggerMain, LaserTriggers, LaserTolerance); + int fillNum = FillByTrigWord(LaserTriggerMain, LaserTriggers, LaserTolerance); + Log("EBTG: Found Laser Trigger group: " + std::to_string(groupNum) + ". Fill additional triggers to group: " + std::to_string(fillNum), v_message, verbosityEBTG); + m_data->CStore.Set("LaserTriggerGroupped", true); + } + else + { + m_data->CStore.Set("LaserTriggerGroupped", false); + } + + if (groupLED) + { + Log("EBTG: Grouping LED Triggers", v_message, verbosityEBTG); + int groupNum = GroupByTrigWord(LEDTriggerMain, LEDTriggers, LEDTolerance); + int fillNum = FillByTrigWord(LEDTriggerMain, LEDTriggers, LEDTolerance); + Log("EBTG: Found LED Trigger group: " + std::to_string(groupNum) + ". Fill additional triggers to group: " + std::to_string(fillNum), v_message, verbosityEBTG); + m_data->CStore.Set("LEDTriggerGroupped", true); + } + else + { + m_data->CStore.Set("LEDTriggerGroupped", false); + } + + if (groupAmBe) + { + Log("EBTG: Grouping AmBe Triggers", v_message, verbosityEBTG); + int groupNum = GroupByTrigWord(AmBeTriggerMain, AmBeTriggers, AmBeTolerance); + int fillNum = FillByTrigWord(AmBeTriggerMain, AmBeTriggers, AmBeTolerance); + Log("EBTG: Found AmBe Trigger group: " + std::to_string(groupNum) + ". Fill additional triggers to group: " + std::to_string(fillNum), v_message, verbosityEBTG); + m_data->CStore.Set("AmBeTriggerGroupped", true); + } + else + { + m_data->CStore.Set("AmBeTriggerGroupped", false); + } + + if (groupPPS) + { + Log("EBTG: Grouping PPS Triggers", v_message, verbosityEBTG); + int groupNum = GroupByTrigWord(PPSTriggerMain, PPSTriggers, PPSTolerance); + int fillNum = FillByTrigWord(PPSTriggerMain, PPSTriggers, PPSTolerance); + Log("EBTG: Found PPS Trigger group: " + std::to_string(groupNum) + ". Fill additional triggers to group: " + std::to_string(fillNum), v_message, verbosityEBTG); + m_data->CStore.Set("PPSTriggerGroupped", true); + } + else + { + m_data->CStore.Set("PPSTriggerGroupped", false); + } + + if (groupNuMI) + { + Log("EBTG: Grouping NuMI Triggers", v_message, verbosityEBTG); + int groupNum = GroupByTrigWord(NuMITriggerMain, NuMITriggers, NuMITolerance); + int fillNum = FillByTrigWord(NuMITriggerMain, NuMITriggers, NuMITolerance); + Log("EBTG: Found NuMI Trigger group: " + std::to_string(groupNum) + ". Fill additional triggers to group: " + std::to_string(fillNum), v_message, verbosityEBTG); + m_data->CStore.Set("NuMITriggerGroupped", true); + } + else + { + m_data->CStore.Set("NuMITriggerGroupped", false); + } + + Log("EBTG: Grouping for different trigger tracks finishes, save to CStore", v_message, verbosityEBTG); + m_data->CStore.Set("GroupedTriggersInTotal", GroupedTriggersInTotal); + m_data->CStore.Set("RunCodeInTotal", RunCodeInTotal); + + int removedTriggerNumber = CleanTriggerBuffer(); + Log("EBTG: CleanTriggerBuffer finishes, removed " + std::to_string(removedTriggerNumber) + " triggers from buffer, buffer size = " + std::to_string(TrigTimeForGroup.size()), v_message, verbosityEBTG); + + return true; +} + +bool EBTriggerGrouper::Finalise() +{ + Log("\033[1;34mEBTG: Finalising\033[0m", v_message, verbosityEBTG); + Log("EBTG: GroupedTriggersInTotal track number = " + std::to_string(GroupedTriggersInTotal.size()), v_message, verbosityEBTG); + for (auto it = GroupedTriggersInTotal.begin(); it != GroupedTriggersInTotal.end(); ++it) + { + Log("EBTG: GroupedTriggersInTotal track " + std::to_string(it->first) + " size = " + std::to_string(it->second.size()), v_message, verbosityEBTG); + } + Log("EBTG: In configfile, set left trigger number = " + std::to_string(maxNumAllowedInBuffer), v_message, verbosityEBTG); + Log("EBTG: Left Total loaded trigger number to buffer = " + std::to_string(StoreTotalEntry), v_message, verbosityEBTG); + Log("EBTG: Ungrouped triggers in buffer size = " + std::to_string(TrigTimeForGroup.size()), v_message, verbosityEBTG); + // calculate which trigger word left in TrigWordForGroup, and print them + std::map triggerWordCount; + for (int i = 0; i < TrigWordForGroup.size(); i++) + { + triggerWordCount[TrigWordForGroup[i]]++; + } + for (auto it = triggerWordCount.begin(); it != triggerWordCount.end(); ++it) + { + Log("EBTG: Trigger word " + std::to_string(it->first) + " left in buffer " + std::to_string(it->second) + " times", v_message, verbosityEBTG); + } + Log("EBTG: Ungrouped triggers in TimeToTriggerWordMap size = " + std::to_string(TimeToTriggerWordMap->size()), v_message, verbosityEBTG); + Log("EBTG: Ungrouped triggers in TimeToTriggerWordMapComplete size = " + std::to_string(TimeToTriggerWordMapComplete->size()), v_message, verbosityEBTG); + + // print first 10000 triggers to a txt for debug + Log("EBTG: Save first 2000 triggers in each track of GroupedTriggersInTotal to TrigDebugGrouped.txt", v_message, verbosityEBTG); + ofstream trigDebugGrouped; + trigDebugGrouped.open("TrigDebugGrouped.txt"); + trigDebugGrouped << "trackTargetTrigger groupIndex triggerTime triggerWord" << endl; + for (auto it = GroupedTriggersInTotal.begin(); it != GroupedTriggersInTotal.end(); ++it) + { + int i = 0; + for (int j = 0; j < it->second.size(); j++) + { + for (auto trig = it->second[j].begin(); trig != it->second[j].end(); ++trig) + { + if (i > 2000) + break; + trigDebugGrouped << it->first << " " << j << " " << trig->first << " " << trig->second << endl; + i++; + } + if (i > 2000) + break; + } + } + trigDebugGrouped.close(); + Log("EBTG: Save first 10000 triggers in TrigTimeForGroup to TrigDebugBufferLeft.txt", v_message, verbosityEBTG); + ofstream trigDebugBufferLeft; + trigDebugBufferLeft.open("TrigDebugBufferLeft.txt"); + for (int i = 0; i < TrigTimeForGroup.size(); i++) + { + if (i > 10000) + break; + trigDebugBufferLeft << i << " " << TrigTimeForGroup[i] << " " << TrigWordForGroup[i] << endl; + } + Log("EBTG: Save first 2000 triggers in TimeToTriggerWordMap to TrigDebug.txt", v_message, verbosityEBTG); + ofstream trigDebug; + trigDebug.open("TrigDebug.txt"); + int i = 0; + for (auto it = TimeToTriggerWordMap->begin(); it != TimeToTriggerWordMap->end(); ++it) + { + if (i > 2000) + break; + trigDebug << it->first << " "; + for (auto trig = it->second.begin(); trig != it->second.end(); ++trig) + { + trigDebug << *trig << " "; + } + trigDebug << endl; + i++; + } + trigDebug.close(); + + Log("EBTG: Printing SkippedDuplicateTriggers", v_message, verbosityEBTG); + int totalSkipped = 0; + for (auto it = SkippedDuplicateTriggers.begin(); it != SkippedDuplicateTriggers.end(); ++it) + { + Log("EBTG: Skipped " + std::to_string(it->second) + " groups of triggers for trigger track " + std::to_string(it->first), v_message, verbosityEBTG); + totalSkipped += it->second; + } + Log("EBTG: Total skipped groups of triggers = " + std::to_string(totalSkipped), v_message, verbosityEBTG); + + return true; +} + +bool EBTriggerGrouper::GroupByTolerance() +{ + Log("EBTG: GroupByTolerance()", v_warning, verbosityEBTG); + Log("EBTG: Grouping by Tolerance: " + std::to_string(GroupTolerance), v_warning, verbosityEBTG); + Log("EBTG: size of time buffer before grouping is " + std::to_string(TrigTimeForGroup.size()) + ", size of word buffer is " + std::to_string(TrigWordForGroup.size()), v_warning, verbosityEBTG); + bool found = false; + uint64_t prev_target_time = 0; + std::map ThisGroup; + vector toRemove; + int totalGroupedTriggerNumber = 0; + for (int i = 0; i < TrigTimeForGroup.size(); i++) + { + uint64_t dt = 0; + if (TrigTimeForGroup[i] > prev_target_time) + dt = TrigTimeForGroup[i] - prev_target_time; + else if (TrigTimeForGroup[i] < prev_target_time) + dt = prev_target_time - TrigTimeForGroup[i]; + else if (TrigTimeForGroup[i] == prev_target_time) + dt = 0; + + if (!found && TrigWordForGroup[i] == GroupTrigWord) + { + found = true; + ThisGroup.clear(); + prev_target_time = TrigTimeForGroup[i]; + ThisGroup.insert(std::pair(TrigTimeForGroup[i], TrigWordForGroup[i])); + toRemove.push_back(i); + } + else if (found && dt < GroupTolerance) + { + + ThisGroup.insert(std::pair(TrigTimeForGroup[i], TrigWordForGroup[i])); + toRemove.push_back(i); + if (TrigWordForGroup[i] == 10 || TrigWordForGroup[i] == 40 || TrigWordForGroup[i] == 41) + { + ThisGroup.insert(std::pair(TrigTimeForGroup[i] + 1, TrigWordForGroup[i])); + } + ///!!! attention, the trigger word 10 always come with 8 with the same time, so it won't be inserted to the map + // Therefore we add another 1ns to it, but it's not real + } + else if (found && dt > GroupTolerance) + { + if (verbosityEBTG > 9) + { + // print all triggers in this group + cout << "EBTG: GroupByTolerance: ThisGroup size = " << ThisGroup.size() << endl; + for (auto it = ThisGroup.begin(); it != ThisGroup.end(); ++it) + { + cout << it->first << " - " << it->second << ", "; + } + cout << endl; + } + GroupedTriggers.push_back(ThisGroup); + totalGroupedTriggerNumber += ThisGroup.size(); + ThisGroup.clear(); + found = false; + } + } + int totalToRemoveTriggerNumber = toRemove.size(); + // from end to beginning, remove the triggers in buffer based on toRemove index + for (int i = toRemove.size() - 1; i >= 0; i--) + { + TrigTimeForGroup.erase(TrigTimeForGroup.begin() + toRemove[i]); + TrigWordForGroup.erase(TrigWordForGroup.begin() + toRemove[i]); + } + Log("EBTG: GroupByTolerance Finished, accumulated saved " + std::to_string(GroupedTriggers.size()) + " group of triggers", v_warning, verbosityEBTG); + Log("EBTG: buffer TriggersForGroup after grouping size = " + std::to_string(TrigTimeForGroup.size()), v_warning, verbosityEBTG); + Log("EBTG: totalGroupedTriggerNumber in this grouping step is: " + std::to_string(totalGroupedTriggerNumber) + ", totalToRemoveTriggerNumber = " + std::to_string(totalToRemoveTriggerNumber), v_warning, verbosityEBTG); + + return true; +} + +bool EBTriggerGrouper::FillByTolerance() +{ + Log("EBTG: FillByTolerance()", v_warning, verbosityEBTG); + Log("EBTG: Fill by Tolerance: " + std::to_string(GroupTolerance), v_warning, verbosityEBTG); + Log("EBTG: size of time buffer before refilling is " + std::to_string(TrigTimeForGroup.size()) + ", size of word buffer is " + std::to_string(TrigWordForGroup.size()), v_warning, verbosityEBTG); + + int addedTriggerNumber = 0; + + for (int i = TrigTimeForGroup.size() - 1; i >= 0; i--) + { + for (int j = 0; j < GroupedTriggers.size(); j++) + { + + for (auto it = GroupedTriggers[j].begin(); it != GroupedTriggers[j].end(); ++it) + { + if (it->second == GroupTrigWord) + { + uint64_t dt = (TrigTimeForGroup[i] > it->first) ? (TrigTimeForGroup[i] - it->first) : (it->first - TrigTimeForGroup[i]); + if (dt < GroupTolerance) + { + GroupedTriggers[j].insert(std::make_pair(TrigTimeForGroup[i], TrigWordForGroup[i])); + TrigTimeForGroup.erase(TrigTimeForGroup.begin() + i); + TrigWordForGroup.erase(TrigWordForGroup.begin() + i); + addedTriggerNumber++; + break; + } + } + } + } + } + + Log("EBTG: FillByTolerance Finished, addedTriggerNumber = " + std::to_string(addedTriggerNumber), v_warning, verbosityEBTG); + Log("EBTG: buffer TriggersForGroup after refilling size = " + std::to_string(TrigTimeForGroup.size()), v_warning, verbosityEBTG); + + return true; +} + +bool EBTriggerGrouper::CleanBuffer() +{ + Log("EBTG: CleanBuffer()", v_warning, verbosityEBTG); + Log("EBTG: size of time buffer before cleaning is " + std::to_string(TrigTimeForGroup.size()) + ", size of word buffer is " + std::to_string(TrigWordForGroup.size()), v_warning, verbosityEBTG); + // check is there any target trigger word in the buffer + // if yes, print a warning message + // only leave the last 100 triggers in the buffer + int numberOfTargetTriggers = 0; + for (int i = 0; i < TrigWordForGroup.size(); i++) + { + if (TrigWordForGroup[i] == GroupTrigWord) + { + numberOfTargetTriggers++; + } + } + if (numberOfTargetTriggers > 0) + { + Log("EBTG: CleanBuffer: Warning: there are " + std::to_string(numberOfTargetTriggers) + " target trigger words in the buffer", v_warning, verbosityEBTG); + } + else + { + Log("EBTG: CleanBuffer: no target trigger words left in the buffer.", v_warning, verbosityEBTG); + } + if (TrigTimeForGroup.size() > 100) + { + TrigTimeForGroup.erase(TrigTimeForGroup.begin(), TrigTimeForGroup.end() - 100); + TrigWordForGroup.erase(TrigWordForGroup.begin(), TrigWordForGroup.end() - 100); + } + Log("EBTG: CleanBuffer Finished, buffer size = " + std::to_string(TrigTimeForGroup.size()), v_warning, verbosityEBTG); + return true; +} + +int EBTriggerGrouper::GroupByTrigWord(uint32_t mainTrigWord, vector TrigWords, int tolerance) +{ + Log("EBTG: GroupByTrigWord()", v_warning, verbosityEBTG); + Log("EBTG: Grouping by TrigWord: " + std::to_string(mainTrigWord), v_warning, verbosityEBTG); + Log("EBTG: size of time buffer before grouping is " + std::to_string(TrigTimeForGroup.size()) + ", size of word buffer is " + std::to_string(TrigWordForGroup.size()), v_warning, verbosityEBTG); + bool found = false; + uint64_t prev_target_time = 0; + std::map ThisGroup; + vector toRemove; + int totalGroupedTriggerNumber = 0; + uint64_t trackTriggerTime = 0; + uint32_t trackTriggerWord = 0; + + for (int i = 0; i < TrigTimeForGroup.size(); i++) + { + uint64_t dt = 0; + if (TrigTimeForGroup[i] > prev_target_time) + dt = TrigTimeForGroup[i] - prev_target_time; + else if (TrigTimeForGroup[i] < prev_target_time) + dt = prev_target_time - TrigTimeForGroup[i]; + else if (TrigTimeForGroup[i] == prev_target_time) + dt = 0; + + if (!found && TrigWordForGroup[i] == mainTrigWord) + { + found = true; + ThisGroup.clear(); + prev_target_time = TrigTimeForGroup[i]; + ThisGroup.insert(std::pair(TrigTimeForGroup[i], TrigWordForGroup[i])); + trackTriggerTime = TrigTimeForGroup[i]; + trackTriggerWord = TrigWordForGroup[i]; + toRemove.push_back(i); + } + else if (found && dt < tolerance) + { + // if found TrigWordForGroup in TrigWords, insert to ThisGroup + if (std::find(TrigWords.begin(), TrigWords.end(), TrigWordForGroup[i]) != TrigWords.end()) + { + ThisGroup.insert(std::pair(TrigTimeForGroup[i], TrigWordForGroup[i])); + toRemove.push_back(i); + if (mainTrigWord == 14 && (TrigWordForGroup[i] == 10 || TrigWordForGroup[i] == 40 || TrigWordForGroup[i] == 41)) + { + ThisGroup.insert(std::pair(TrigTimeForGroup[i] + 1, TrigWordForGroup[i])); + } + ///!!! attention, the trigger word 10 always come with 8 with the same time, so it won't be inserted to the map + // Therefore we add another 1ns to it, but it's not real + } + } + else if (found && dt > tolerance) + { + if (verbosityEBTG > 9) + { + // print all triggers in this group + cout << "EBTG: GroupByTrigWord: ThisGroup size = " << ThisGroup.size() << endl; + for (auto it = ThisGroup.begin(); it != ThisGroup.end(); ++it) + { + cout << it->first << " - " << it->second << ", "; + } + cout << endl; + } + // check is the current track trigger already exist in GroupedTriggersInTotal, if so, don't add it + // find trackTriggerTime in each element in GroupedTriggersInTotal[mainTrigWord] + bool trackTriggerExist = false; + for (int j = 0; j < GroupedTriggersInTotal[mainTrigWord].size(); j++) + { + for (auto it = GroupedTriggersInTotal[mainTrigWord][j].begin(); it != GroupedTriggersInTotal[mainTrigWord][j].end(); ++it) + { + if (it->first == trackTriggerTime && it->second == trackTriggerWord) + { + trackTriggerExist = true; + break; + } + } + } + if (!trackTriggerExist) + { + GroupedTriggersInTotal[mainTrigWord].push_back(ThisGroup); + } + else + { + // in it's track of SkippedDuplicateTriggers, plus one. if found it, ++, if not, emplace 1 + if (SkippedDuplicateTriggers.find(mainTrigWord) != SkippedDuplicateTriggers.end()) + { + SkippedDuplicateTriggers[mainTrigWord]++; + } + else + { + SkippedDuplicateTriggers.emplace(mainTrigWord, 1); + } + + Log("EBTG: Found a duplicated main trigger with word " + std::to_string(mainTrigWord) + " and time " + std::to_string(trackTriggerTime), v_message, verbosityEBTG); + } + + if (verbosityEBTG > 9) + cout << "EBTG: saving grouped trigger with currentRunCode = " << currentRunCode << endl; + if (!trackTriggerExist) + RunCodeInTotal[mainTrigWord].push_back(currentRunCode); + else + Log("EBTG: Found a duplicated main trigger with word " + std::to_string(mainTrigWord) + " and time " + std::to_string(trackTriggerTime) + ", so skip adding run code vector", v_message, verbosityEBTG); + totalGroupedTriggerNumber += ThisGroup.size(); + ThisGroup.clear(); + found = false; + } + } + int totalToRemoveTriggerNumber = toRemove.size(); + // from end to beginning, remove the triggers in buffer based on toRemove index + for (int i = toRemove.size() - 1; i >= 0; i--) + { + TrigTimeForGroup.erase(TrigTimeForGroup.begin() + toRemove[i]); + TrigWordForGroup.erase(TrigWordForGroup.begin() + toRemove[i]); + } + Log("EBTG: GroupByTrigWord Finished, accumulated saved " + std::to_string(GroupedTriggers.size()) + " group of triggers", v_warning, verbosityEBTG); + Log("EBTG: buffer TriggersForGroup after grouping size = " + std::to_string(TrigTimeForGroup.size()), v_warning, verbosityEBTG); + Log("EBTG: totalGroupedTriggerNumber in this grouping step is: " + std::to_string(totalGroupedTriggerNumber) + ", totalToRemoveTriggerNumber = " + std::to_string(totalToRemoveTriggerNumber), v_warning, verbosityEBTG); + + return totalToRemoveTriggerNumber; +} + +int EBTriggerGrouper::FillByTrigWord(uint32_t mainTrigWord, vector TrigWords, int tolerance) +{ + // Fill the trigger maps at GroupedTriggersInTotal[mainTrigWord] + // for all triggers in the buffer, if the trigger word is in the vector, and in the range of main TrigWord - the tolerance + // push the trigger into the map + + Log("EBTG: FillByTrigWord()", v_warning, verbosityEBTG); + Log("EBTG: Fill by TrigWord: " + std::to_string(mainTrigWord), v_warning, verbosityEBTG); + Log("EBTG: size of time buffer before refilling is " + std::to_string(TrigTimeForGroup.size()) + ", size of word buffer is " + std::to_string(TrigWordForGroup.size()), v_warning, verbosityEBTG); + + int addedTriggerNumber = 0; + vector indexToRemove; + + for (int i = TrigTimeForGroup.size() - 1; i >= 0; i--) + { + if (verbosityEBTG > 11) + cout << "EBTG: FillByTrigWord: mainTrigWord = " << mainTrigWord << ", TrigWordForGroup[i] = " << TrigWordForGroup[i] << ", TrigTimeForGroup[i] = " << TrigTimeForGroup[i] << ", tolerance = " << tolerance << endl; + // check is current trigger word in TrigWords + if (std::find(TrigWords.begin(), TrigWords.end(), TrigWordForGroup[i]) == TrigWords.end()) + continue; + bool triggerToAdd = false; + int insertTrack = 0; + int insertGroupIndex = 0; + uint64_t insertedDT = tolerance; + for (int j = 0; j < GroupedTriggersInTotal[mainTrigWord].size(); j++) + { + for (auto it = GroupedTriggersInTotal[mainTrigWord][j].begin(); it != GroupedTriggersInTotal[mainTrigWord][j].end(); ++it) + { + if (it->second == mainTrigWord) + { + uint64_t dt = (TrigTimeForGroup[i] > it->first) ? (TrigTimeForGroup[i] - it->first) : (it->first - TrigTimeForGroup[i]); + if (dt < tolerance && dt < insertedDT) + { + insertedDT = dt; + insertTrack = mainTrigWord; + insertGroupIndex = j; + triggerToAdd = true; + Log("EBTG: FillByTrigWord: Found trigger to add, insertTrack = " + std::to_string(insertTrack) + ", insertGroupIndex = " + std::to_string(insertGroupIndex) + ", insert DT = " + std::to_string(insertedDT), 9, verbosityEBTG); + break; + } + } + } + } + if (triggerToAdd) + { + GroupedTriggersInTotal[mainTrigWord][insertGroupIndex].insert(std::make_pair(TrigTimeForGroup[i], TrigWordForGroup[i])); + indexToRemove.push_back(i); + if (verbosityEBTG > 11) + cout << "EBTG: FillByTrigWord: add this trigger: " << TrigTimeForGroup[i] << " - " << TrigWordForGroup[i] << endl; + addedTriggerNumber++; + } + } + Log("EBTG: FillByTrigWord Finished, addedTriggerNumber = " + std::to_string(addedTriggerNumber), v_warning, verbosityEBTG); + Log("EBTG: indexToRemove size = " + std::to_string(indexToRemove.size()) + ", buffer size before remove is " + std::to_string(TrigTimeForGroup.size()), v_warning, verbosityEBTG); + + // sort indexToRemove from large to small, then remove the triggers in buffer based on toRemove index + std::sort(indexToRemove.begin(), indexToRemove.end(), std::greater()); + + if (verbosityEBTG > 11) + { + // print all index to remove + cout << "EBTG: FillByTrigWord: indexToRemove: "; + for (int i = 0; i < indexToRemove.size(); i++) + { + cout << indexToRemove[i] << ", "; + } + } + + for (int i = 0; i < indexToRemove.size(); i++) + { + TrigTimeForGroup.erase(TrigTimeForGroup.begin() + indexToRemove[i]); + TrigWordForGroup.erase(TrigWordForGroup.begin() + indexToRemove[i]); + } + Log("EBTG: buffer TriggersForGroup after refilling and removing size = " + std::to_string(TrigTimeForGroup.size()), v_warning, verbosityEBTG); + + return addedTriggerNumber; +} + +int EBTriggerGrouper::CleanTriggerBuffer() +{ + // remove very early trigger in TrigTimeForGroup and TrigWordForGroup + // only leave the latest maxNumAllowedInBuffer elements + int removedNumber = 0; + if (TrigTimeForGroup.size() > maxNumAllowedInBuffer) + { + removedNumber = TrigTimeForGroup.size() - maxNumAllowedInBuffer; + removedTriggerInBuffer += removedNumber; + Log("EBTG: CleanTriggerBuffer, will remove the earliest " + std::to_string(TrigTimeForGroup.size() - maxNumAllowedInBuffer) + " triggers in buffer", v_message, verbosityEBTG); + TrigTimeForGroup.erase(TrigTimeForGroup.begin(), TrigTimeForGroup.end() - maxNumAllowedInBuffer); + TrigWordForGroup.erase(TrigWordForGroup.begin(), TrigWordForGroup.end() - maxNumAllowedInBuffer); + } + return removedNumber; +} \ No newline at end of file diff --git a/UserTools/EBTriggerGrouper/EBTriggerGrouper.h b/UserTools/EBTriggerGrouper/EBTriggerGrouper.h new file mode 100644 index 000000000..3d573259b --- /dev/null +++ b/UserTools/EBTriggerGrouper/EBTriggerGrouper.h @@ -0,0 +1,124 @@ +#ifndef EBTriggerGrouper_H +#define EBTriggerGrouper_H + +#include +#include + +#include "Tool.h" + +/** + * \class EBPMT + * + * $Author: Yue Feng $ + * $Date: 2024/04 $ + * Contact: yuef@iaistate.edu + * + */ + +class EBTriggerGrouper : public Tool +{ + +public: + EBTriggerGrouper(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + + bool GroupByTolerance(); + bool FillByTolerance(); + bool SaveGroupedTriggers(); + bool CleanBuffer(); + + int GroupByTrigWord(uint32_t mainTrigWord, vector TrigWords, int tolerance); + // group and save triggers to GroupedTriggersInTotal and RunCodeInTotal + // input a vector of trigger words in that combination, and a tolerance + // during grouping, select based on the main TrigWord + the tolerance + // in that range, if the trigger word is in the vector, group them together + // push the grouped trigger map into the vector at GroupedTriggersInTotal[mainTrigWord] + + int FillByTrigWord(uint32_t mainTrigWord, vector TrigWords, int tolerance); + // Fill the trigger maps at GroupedTriggersInTotal[mainTrigWord] + // for all triggers in the buffer, if the trigger word is in the vector, and in the range of main TrigWord - the tolerance + // push the trigger into the map + + int CleanTriggerBuffer(); // remove very early trigger in TrigTimeForGroup and TrigWordForGroup + // only leave the latest maxNumAllowedInBuffer elements + +private: + string savePath; + string GroupMode; // beam, Tolerance + double GroupTolerance; + int GroupTrigWord; + + std::map> *TimeToTriggerWordMap; + std::map> *TimeToTriggerWordMapComplete; // Info about all triggerwords + + vector TrigTimeForGroup; + vector TrigWordForGroup; + vector RunCodeBuffer; + + std::vector> GroupedTriggers; // each map is a group of triggers, for the main target trigger + vector RunCode; //!! RunCode goes with each group, always modify them together + + std::map>> GroupedTriggersInTotal; // each map is a group of triggers, with the key is the target trigger word + std::map> RunCodeInTotal; //!! RunCode goes with each group, always modify them together + + std::map SkippedDuplicateTriggers; // if the trigger was duplicated in multiple entries, skip it. this record the skipped number of groups + + int verbosityEBTG; + + int v_message = 1; + int v_warning = 2; + int v_error = 3; + int v_debug = 4; + + int ANNIEEventNum; + int CurrentRunNum; + int CurrentSubrunNum; + int CurrentPartNum; + int currentRunCode; + bool usingTriggerOverlap; + + int StoreTotalEntry; + + int maxNumAllowedInBuffer; + int removedTriggerInBuffer; + + bool groupBeam; + bool groupCosmic; + bool groupLaser; + bool groupLED; + bool groupAmBe; + bool groupPPS; + bool groupNuMI; + + int BeamTriggerMain; + double BeamTolerance; + vector BeamTriggers; + + int CosmicTriggerMain; + double CosmicTolerance; + vector CosmicTriggers; + + int LaserTriggerMain; + double LaserTolerance; + vector LaserTriggers; + + int LEDTriggerMain; + double LEDTolerance; + vector LEDTriggers; + + int AmBeTriggerMain; + double AmBeTolerance; + vector AmBeTriggers; + + int PPSTriggerMain; + double PPSTolerance; + vector PPSTriggers; + + int NuMITriggerMain; + double NuMITolerance; + vector NuMITriggers; +}; + +#endif diff --git a/UserTools/EBTriggerGrouper/README.md b/UserTools/EBTriggerGrouper/README.md new file mode 100644 index 000000000..3f84b6468 --- /dev/null +++ b/UserTools/EBTriggerGrouper/README.md @@ -0,0 +1,32 @@ +# EBTriggerGrouper + +EBTriggerGrouper is a part of the Event Builder V2 tool chain. +For reference slides, see: +https://annie-docdb.fnal.gov/cgi-bin/sso/ShowDocument?docid=5633 + + +This tool take TimeToTriggerWordMap from the trigger data decoder as input, push the triggers and trigger words into TrigTimeForGroup and TrigWordForGroup, then use the pre defined trigger groups like BeamTriggers to group the triggers based on time tolorance. Finally save the grouped triggers to GroupedTriggersInTotal in CStore. + +## Data + +**TimeToTriggerWordMap** `std::map>` +**TimeToTriggerWordMapComplete** `std::map>` +Take from TriggerDataDecoder. This tool will push the info to + +**TrigTimeForGroup** `vector` +**TrigWordForGroup** `vector` +Buffer for timestamps. Only be used in this tool. + + +**GroupedTriggersInTotal** `std::map>>` +Groupped triggers, will be passed to other tools for matching. + +## Configuration +For one group type, you need one option, and two configs from the config file, one config hard coded in the cpp file. +groupBeam: tell the tool group this run type or not +BeamTriggerMain: the main trigger of a run type. For instance, main beam trigger is 14 +BeamTolerance: the time tolerance that you allow other triggers in this run type to be paired with a main trigger. +BeamTriggers: hard coded in the cpp file for safety. This vector contains all trigger word that allowed to be grouped as beam. +They are sent to GroupByTrigWord function for each run type. In case there will be more run types in the future. + + diff --git a/UserTools/Factory/Factory.cpp b/UserTools/Factory/Factory.cpp index c986c48b7..ef0a191bf 100644 --- a/UserTools/Factory/Factory.cpp +++ b/UserTools/Factory/Factory.cpp @@ -174,5 +174,6 @@ if (tool=="BackTracker") ret=new BackTracker; if (tool=="PrintDQ") ret=new PrintDQ; if (tool=="AssignBunchTimingMC") ret=new AssignBunchTimingMC; if (tool=="FitRWMWaveform") ret=new FitRWMWaveform; +if (tool=="EBTriggerGrouper") ret=new EBTriggerGrouper; return ret; } diff --git a/UserTools/Unity.h b/UserTools/Unity.h index 7e64d4e9b..022fea898 100644 --- a/UserTools/Unity.h +++ b/UserTools/Unity.h @@ -182,3 +182,5 @@ #include "PrintDQ.h" #include "AssignBunchTimingMC.h" #include "FitRWMWaveform.h" +#include "EBTriggerGrouper.h" +#include "EBTriggerGrouper.h" From 76fa77141598f8e38118335533bd83133c498ae7 Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Sun, 19 Jan 2025 23:00:49 -0600 Subject: [PATCH 116/163] Add EBLAPPD tool in EBV2 tool chain --- UserTools/EBLAPPD/EBLAPPD.cpp | 382 ++++++++++++++++++++++++++++++++++ UserTools/EBLAPPD/EBLAPPD.h | 95 +++++++++ UserTools/EBLAPPD/README.md | 35 ++++ UserTools/Factory/Factory.cpp | 1 + UserTools/Unity.h | 1 + 5 files changed, 514 insertions(+) create mode 100644 UserTools/EBLAPPD/EBLAPPD.cpp create mode 100644 UserTools/EBLAPPD/EBLAPPD.h create mode 100644 UserTools/EBLAPPD/README.md diff --git a/UserTools/EBLAPPD/EBLAPPD.cpp b/UserTools/EBLAPPD/EBLAPPD.cpp new file mode 100644 index 000000000..4658d96d1 --- /dev/null +++ b/UserTools/EBLAPPD/EBLAPPD.cpp @@ -0,0 +1,382 @@ +#include "EBLAPPD.h" + +EBLAPPD::EBLAPPD() : Tool() {} + +bool EBLAPPD::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + m_variables.Get("verbosityEBLAPPD", verbosityEBLAPPD); + matchTargetTrigger = 14; + m_variables.Get("matchTargetTrigger", matchTargetTrigger); + matchTolerance_ns = 400000; // default 400us + m_variables.Get("matchTolerance_ns", matchTolerance_ns); + matchToAllTriggers = false; + m_variables.Get("matchToAllTriggers", matchToAllTriggers); + exePerMatch = 500; + m_variables.Get("exePerMatch", exePerMatch); + + return true; +} + +bool EBLAPPD::Execute() +{ + m_data->CStore.Get("PairedLAPPDTriggerTimestamp", PairedCTCTimeStamps); + m_data->CStore.Get("PairedLAPPDTimeStamps", PairedLAPPDTimeStamps); + m_data->CStore.Get("PairedLAPPD_TriggerIndex", PairedLAPPD_TriggerIndex); + m_data->CStore.Get("Buffer_LAPPDData", Buffer_LAPPDData); + m_data->CStore.Get("Buffer_LAPPDTimestamp_ns", Buffer_LAPPDTimestamp_ns); + m_data->CStore.Get("Buffer_LAPPDBeamgate_ns", Buffer_LAPPDBeamgate_ns); + m_data->CStore.Get("Buffer_LAPPDOffset", Buffer_LAPPDOffset); + m_data->CStore.Get("Buffer_LAPPDBeamgate_Raw", Buffer_LAPPDBeamgate_Raw); + m_data->CStore.Get("Buffer_LAPPDTimestamp_Raw", Buffer_LAPPDTimestamp_Raw); + m_data->CStore.Get("Buffer_LAPPDBGCorrection", Buffer_LAPPDBGCorrection); + m_data->CStore.Get("Buffer_LAPPDTSCorrection", Buffer_LAPPDTSCorrection); + m_data->CStore.Get("Buffer_LAPPDOffset_minus_ps", Buffer_LAPPDOffset_minus_ps); + m_data->CStore.Get("Buffer_LAPPDRunCode", Buffer_RunCode); + + m_data->CStore.Get("Buffer_LAPPDBG_PPSBefore", Buffer_LAPPDBG_PPSBefore); + m_data->CStore.Get("Buffer_LAPPDBG_PPSAfter", Buffer_LAPPDBG_PPSAfter); + m_data->CStore.Get("Buffer_LAPPDBG_PPSDiff", Buffer_LAPPDBG_PPSDiff); + m_data->CStore.Get("Buffer_LAPPDBG_PPSMissing", Buffer_LAPPDBG_PPSMissing); + m_data->CStore.Get("Buffer_LAPPDTS_PPSBefore", Buffer_LAPPDTS_PPSBefore); + m_data->CStore.Get("Buffer_LAPPDTS_PPSAfter", Buffer_LAPPDTS_PPSAfter); + m_data->CStore.Get("Buffer_LAPPDTS_PPSDiff", Buffer_LAPPDTS_PPSDiff); + m_data->CStore.Get("Buffer_LAPPDTS_PPSMissing", Buffer_LAPPDTS_PPSMissing); + + Log("EBLAPPD: Got pairing information from CStore, PairedLAPPDTimeStamps[14] size = " + std::to_string(PairedLAPPDTimeStamps[14].size()), v_message, verbosityEBLAPPD); + + CleanData(); + m_data->CStore.Get("RunCode", currentRunCode); + + bool IsNewLAPPDData = false; + m_data->CStore.Get("NewLAPPDDataAvailable", IsNewLAPPDData); + Log("EBLAPPD: NewLAPPDDataAvailable = " + std::to_string(IsNewLAPPDData), v_message, verbosityEBLAPPD); + bool LoadingPPS = false; + m_data->CStore.Get("LoadingPPS", LoadingPPS); + + if (IsNewLAPPDData && !LoadingPPS) + LoadLAPPDData(); + + Log("EBLAPPD: Finished Loading LAPPD data to buffer, Buffer_LAPPDData size is now " + std::to_string(Buffer_LAPPDData.size()), v_message, verbosityEBLAPPD); + + string storeFileName; + m_data->CStore.Get("SaveToFileName", storeFileName); + + bool stopLoop = false; + m_data->vars.Get("StopLoop", stopLoop); + int runNum = thisRunNum; + m_data->vars.Get("RunNumber", thisRunNum); + bool ForceLAPPDMatching = false; + m_data->CStore.Get("ForceLAPPDMatching", ForceLAPPDMatching); + + if (stopLoop || runNum != thisRunNum || exeNum % exePerMatch == 0 || ForceLAPPDMatching) + { + Log("EBLAPPD: exeNum = " + std::to_string(exeNum) + ". Doing matching", v_message, verbosityEBLAPPD); + Log("EBLAPPD: Matching reason is stopLoop = " + std::to_string(stopLoop) + ", runNum = " + std::to_string(runNum) + ", exeNum = " + std::to_string(exeNum) + ", ForceLAPPDMatching = " + std::to_string(ForceLAPPDMatching), v_message, verbosityEBLAPPD); + if (matchToAllTriggers) + { + Matching(0, 0); + } + else + { + bool BeamTriggerGroupped = false; + m_data->CStore.Get("BeamTriggerGroupped", BeamTriggerGroupped); + if (BeamTriggerGroupped) + Matching(14, 14); + else + Log("EBLAPPD: BeamTriggerGroupped is false, no beam trigger groupped in the grouper, stop matching", v_message, verbosityEBLAPPD); + + bool LaserTriggerGroupped = false; + m_data->CStore.Get("LaserTriggerGroupped", LaserTriggerGroupped); + if (LaserTriggerGroupped) + Matching(47, 47); + else + Log("EBLAPPD: LaserTriggerGroupped is false, no laser trigger groupped in the grouper, stop matching", v_message, verbosityEBLAPPD); + + bool CosmicTriggerGroupped = false; + m_data->CStore.Get("CosmicTriggerGroupped", CosmicTriggerGroupped); + if (CosmicTriggerGroupped) + Matching(45, 46); + else + Log("EBLAPPD: CosmicTriggerGroupped is false, no cosmic trigger groupped in the grouper, stop matching", v_message, verbosityEBLAPPD); + + bool LEDTriggerGroupped = false; + m_data->CStore.Get("LEDTriggerGroupped", LEDTriggerGroupped); + if (LEDTriggerGroupped) + Matching(31, 46); + else + Log("EBLAPPD: LEDTriggerGroupped is false, no LED trigger groupped in the grouper, stop matching", v_message, verbosityEBLAPPD); + + bool NuMITriggerGroupped = false; + m_data->CStore.Get("NuMITriggerGroupped", NuMITriggerGroupped); + if (NuMITriggerGroupped) + Matching(42, 46); + else + Log("EBLAPPD: NuMITriggerGroupped is false, no NuMI trigger groupped in the grouper, stop matching", v_message, verbosityEBLAPPD); + } + } + + // Set all matching info to CStore + m_data->CStore.Set("PairedLAPPDTriggerTimestamp", PairedCTCTimeStamps); + m_data->CStore.Set("PairedLAPPDTimeStamps", PairedLAPPDTimeStamps); + m_data->CStore.Set("PairedLAPPD_TriggerIndex", PairedLAPPD_TriggerIndex); + Log("EBLAPPD: Set pairing information to CStore, PairedLAPPDTimeStamps[14] size = " + std::to_string(PairedLAPPDTimeStamps[14].size()), v_message, verbosityEBLAPPD); + Log("EBLAPPD: Set pairing information to CStore, PairedLAPPDTimeStamps[47] size = " + std::to_string(PairedLAPPDTimeStamps[47].size()), v_message, verbosityEBLAPPD); + + // Set the indexing of buffer + m_data->CStore.Set("Buffer_LAPPDTimestamp_ns", Buffer_LAPPDTimestamp_ns); + + // Also set all buffers to CStore + m_data->CStore.Set("Buffer_LAPPDData", Buffer_LAPPDData); + m_data->CStore.Set("Buffer_LAPPDBeamgate_ns", Buffer_LAPPDBeamgate_ns); + m_data->CStore.Set("Buffer_LAPPDOffset", Buffer_LAPPDOffset); + m_data->CStore.Set("Buffer_LAPPDBeamgate_Raw", Buffer_LAPPDBeamgate_Raw); + m_data->CStore.Set("Buffer_LAPPDTimestamp_Raw", Buffer_LAPPDTimestamp_Raw); + m_data->CStore.Set("Buffer_LAPPDBGCorrection", Buffer_LAPPDBGCorrection); + m_data->CStore.Set("Buffer_LAPPDTSCorrection", Buffer_LAPPDTSCorrection); + m_data->CStore.Set("Buffer_LAPPDOffset_minus_ps", Buffer_LAPPDOffset_minus_ps); + m_data->CStore.Set("Buffer_LAPPDRunCode", Buffer_RunCode); + + m_data->CStore.Set("Buffer_LAPPDBG_PPSBefore", Buffer_LAPPDBG_PPSBefore); + m_data->CStore.Set("Buffer_LAPPDBG_PPSAfter", Buffer_LAPPDBG_PPSAfter); + m_data->CStore.Set("Buffer_LAPPDBG_PPSDiff", Buffer_LAPPDBG_PPSDiff); + m_data->CStore.Set("Buffer_LAPPDBG_PPSMissing", Buffer_LAPPDBG_PPSMissing); + m_data->CStore.Set("Buffer_LAPPDTS_PPSBefore", Buffer_LAPPDTS_PPSBefore); + m_data->CStore.Set("Buffer_LAPPDTS_PPSAfter", Buffer_LAPPDTS_PPSAfter); + m_data->CStore.Set("Buffer_LAPPDTS_PPSDiff", Buffer_LAPPDTS_PPSDiff); + m_data->CStore.Set("Buffer_LAPPDTS_PPSMissing", Buffer_LAPPDTS_PPSMissing); + + exeNum++; + + return true; +} + +bool EBLAPPD::Finalise() +{ + Log("\033[1;34mEBLAPPD: Finalising\033[0m", v_message, verbosityEBLAPPD); + Log("EBLAPPD: Matched LAPPD number = " + std::to_string(matchedLAPPDNumber), v_message, verbosityEBLAPPD); + Log("EBLAPPD: Unmatched LAPPD number = " + std::to_string(MatchBuffer_LAPPDTimestamp_ns.size()), v_message, verbosityEBLAPPD); + return true; +} + +bool EBLAPPD::CleanData() +{ + LAPPDBeamgate_ns = 0; + LAPPDTimestamp_ns = 0; + LAPPDOffset = 0; + LAPPDBeamgate_Raw = 0; + LAPPDTimestamp_Raw = 0; + LAPPDBGCorrection = 0; + LAPPDTSCorrection = 0; + LAPPDOffset_minus_ps = 0; + + LAPPDBG_PPSBefore = 0; + LAPPDBG_PPSAfter = 0; + LAPPDBG_PPSDiff = 0; + LAPPDBG_PPSMissing = 0; + LAPPDTS_PPSBefore = 0; + LAPPDTS_PPSAfter = 0; + LAPPDTS_PPSDiff = 0; + LAPPDTS_PPSMissing = 0; + + return true; +} + +bool EBLAPPD::LoadLAPPDData() +{ + // get the LAPPD beamgate + LAPPDBeamgate_Raw = 0; + LAPPDTimestamp_Raw = 0; + m_data->CStore.Get("LAPPDBeamgate_Raw", LAPPDBeamgate_Raw); + m_data->CStore.Get("LAPPDTimestamp_Raw", LAPPDTimestamp_Raw); + + LAPPDBeamgate_ns = LAPPDBeamgate_Raw * 3.125; + LAPPDTimestamp_ns = LAPPDTimestamp_Raw * 3.125; + + LAPPDBGCorrection = 0; + LAPPDTSCorrection = 0; + LAPPDOffset_minus_ps = 0; + m_data->CStore.Get("LAPPDBGCorrection", LAPPDBGCorrection); + m_data->CStore.Get("LAPPDTSCorrection", LAPPDTSCorrection); + m_data->CStore.Get("LAPPDOffset_minus_ps", LAPPDOffset_minus_ps); + LAPPDOffset = 0; + m_data->CStore.Get("LAPPDOffset", LAPPDOffset); + + LAPPDBeamgate_ns = LAPPDBeamgate_ns + LAPPDBGCorrection + LAPPDOffset; + LAPPDTimestamp_ns = LAPPDTimestamp_ns + LAPPDTSCorrection + LAPPDOffset; + + LAPPDBG_PPSBefore = 0; + LAPPDBG_PPSAfter = 0; + LAPPDBG_PPSDiff = 0; + LAPPDBG_PPSMissing = 0; + LAPPDTS_PPSBefore = 0; + LAPPDTS_PPSAfter = 0; + LAPPDTS_PPSDiff = 0; + LAPPDTS_PPSMissing = 0; + m_data->CStore.Get("BG_PPSBefore", LAPPDBG_PPSBefore); + m_data->CStore.Get("BG_PPSAfter", LAPPDBG_PPSAfter); + m_data->CStore.Get("BG_PPSDiff", LAPPDBG_PPSDiff); + m_data->CStore.Get("BG_PPSMissing", LAPPDBG_PPSMissing); + m_data->CStore.Get("TS_PPSBefore", LAPPDTS_PPSBefore); + m_data->CStore.Get("TS_PPSAfter", LAPPDTS_PPSAfter); + m_data->CStore.Get("TS_PPSDiff", LAPPDTS_PPSDiff); + m_data->CStore.Get("TS_PPSMissing", LAPPDTS_PPSMissing); + + if (verbosityEBLAPPD > 1) + { + cout << "Processing new LAPPD data from store" << endl; + cout << "Got info: LAPPDBeamgate_Raw: " << LAPPDBeamgate_Raw << ", LAPPDTimestamp_Raw: " << LAPPDTimestamp_Raw << ", LAPPDBGCorrection: " << LAPPDBGCorrection << ", LAPPDTSCorrection: " << LAPPDTSCorrection << ", LAPPDOffset: " << LAPPDOffset << ", LAPPDOffset_minus_ps: " << LAPPDOffset_minus_ps << ", LAPPDBG_PPSBefore: " << LAPPDBG_PPSBefore << ", LAPPDBG_PPSAfter: " << LAPPDBG_PPSAfter << ", LAPPDBG_PPSDiff: " << LAPPDBG_PPSDiff << ", LAPPDBG_PPSMissing: " << LAPPDBG_PPSMissing << ", LAPPDTS_PPSBefore: " << LAPPDTS_PPSBefore << ", LAPPDTS_PPSAfter: " << LAPPDTS_PPSAfter << ", LAPPDTS_PPSDiff: " << LAPPDTS_PPSDiff << ", LAPPDTS_PPSMissing: " << LAPPDTS_PPSMissing << endl; + cout << "LAPPDBeamgate_ns: " << LAPPDBeamgate_ns << endl; + cout << "LAPPDTimestamp_ns: " << LAPPDTimestamp_ns << endl; + } + + bool gotdata = m_data->CStore.Get("StoreLoadedLAPPDData", dat); + + if (gotdata) + { + Buffer_LAPPDTimestamp_ns.push_back(LAPPDTimestamp_ns); + + Buffer_LAPPDData.push_back(dat); + Buffer_LAPPDBeamgate_ns.push_back(LAPPDBeamgate_ns); + Buffer_LAPPDOffset.push_back(LAPPDOffset); + Buffer_LAPPDBeamgate_Raw.push_back(LAPPDBeamgate_Raw); + Buffer_LAPPDTimestamp_Raw.push_back(LAPPDTimestamp_Raw); + Buffer_LAPPDBGCorrection.push_back(LAPPDBGCorrection); + Buffer_LAPPDTSCorrection.push_back(LAPPDTSCorrection); + Buffer_LAPPDOffset_minus_ps.push_back(LAPPDOffset_minus_ps); + Buffer_RunCode.push_back(currentRunCode); + + Buffer_LAPPDBG_PPSBefore.push_back(LAPPDBG_PPSBefore); + Buffer_LAPPDBG_PPSAfter.push_back(LAPPDBG_PPSAfter); + Buffer_LAPPDBG_PPSDiff.push_back(LAPPDBG_PPSDiff); + Buffer_LAPPDBG_PPSMissing.push_back(LAPPDBG_PPSMissing); + Buffer_LAPPDTS_PPSBefore.push_back(LAPPDTS_PPSBefore); + Buffer_LAPPDTS_PPSAfter.push_back(LAPPDTS_PPSAfter); + Buffer_LAPPDTS_PPSDiff.push_back(LAPPDTS_PPSDiff); + Buffer_LAPPDTS_PPSMissing.push_back(LAPPDTS_PPSMissing); + + MatchBuffer_LAPPDTimestamp_ns.push_back(LAPPDTimestamp_ns); + + if (LAPPDTS_PPSMissing != LAPPDBG_PPSMissing) + Log("EBLAPPD: PPS missing in BG and TS are different, BG: " + std::to_string(LAPPDBG_PPSMissing) + ", TS: " + std::to_string(LAPPDTS_PPSMissing), v_warning, verbosityEBLAPPD); + + Log("EBLAPPD: Loaded LAPPD data to buffer, Buffer_LAPPDData size after this load is now " + std::to_string(Buffer_LAPPDData.size()), v_message, verbosityEBLAPPD); + } + + return true; +} + +bool EBLAPPD::Matching(int targetTrigger, int matchToTrack) +{ + cout << "\033[1;34m******* EBLAPPD : Matching *******\033[0m" << endl; + Log("EBLAPPD: Matching LAPPD data with target trigger " + std::to_string(targetTrigger) + " in track " + std::to_string(matchToTrack), v_message, verbosityEBLAPPD); + + std::map>> GroupedTriggersInTotal; // each map is a group of triggers, with the key is the target trigger word + m_data->CStore.Get("GroupedTriggersInTotal", GroupedTriggersInTotal); + // print how many trigger groups in each track + + vector matchedLAPPDTimes; + vector indexToRemove; + std::map matchedNumberInTrack; + + // loop the LAPPDDataBuffer keys, and loop all the grouped triggers + // in each group of trigger, find the target trigger word and it's time + // fine the minimum time difference, if smaller than matchTolerance_ns, then save the time to PairedCTCTimeStamps and PairedLAPPDTimeStamps + for (int i = 0; i < MatchBuffer_LAPPDTimestamp_ns.size(); i++) + { + uint64_t LAPPDtime = MatchBuffer_LAPPDTimestamp_ns.at(i); + // if found LAPPDtime at PairedLAPPDTimeStamps, skip //shouldn't happen + if (std::find(PairedLAPPDTimeStamps[matchToTrack].begin(), PairedLAPPDTimeStamps[matchToTrack].end(), LAPPDtime) != PairedLAPPDTimeStamps[matchToTrack].end()) + { + Log("EBLAPPD: Buffer " + std::to_string(i) + " with time " + std::to_string(Buffer_LAPPDTimestamp_ns.at(i)) + ": Found a match already", v_message, verbosityEBLAPPD); + continue; + } + + // set minDT to 5 min + uint64_t minDT = 5 * 60 * 1e9; + uint64_t minDTTrigger = 0; + uint64_t dt = 0; + uint32_t matchedTrigWord = 0; + int matchedTrack = 0; + int matchedIndex = 0; + + for (std::pair>> pair : GroupedTriggersInTotal) + { + int TrackTriggerWord = pair.first; + if (matchedNumberInTrack.find(TrackTriggerWord) == matchedNumberInTrack.end()) + matchedNumberInTrack.emplace(TrackTriggerWord, 0); + if (TrackTriggerWord != matchToTrack && !matchToAllTriggers) + { + // Log("EBLAPPD: Skipping TrackTriggerWord " + std::to_string(TrackTriggerWord), v_debug, verbosityEBLAPPD); + continue; + } + vector> GroupedTriggers = pair.second; + + for (int j = 0; j < GroupedTriggers.size(); j++) + { + map groupedTrigger = GroupedTriggers.at(j); + // itearte over all the grouped triggers, if the value is target trigger, then calculate the time difference + for (std::pair p : groupedTrigger) + { + if (matchToAllTriggers || p.second == targetTrigger) + { + + if (LAPPDtime > p.first) + { + dt = LAPPDtime - p.first; + } + else + { + dt = p.first - LAPPDtime; + } + if (dt < minDT) + { + minDT = dt; + minDTTrigger = p.first; + matchedTrigWord = p.second; + matchedTrack = TrackTriggerWord; + matchedIndex = j; + } + } + } + } + } + + Log("EBLAPPD: at buffer " + std::to_string(i) + " with time " + std::to_string(Buffer_LAPPDTimestamp_ns.at(i)) + ", minDT: " + std::to_string(minDT), v_debug, verbosityEBLAPPD); + if (minDT < matchTolerance_ns) + { + PairedCTCTimeStamps[matchedTrack].push_back(minDTTrigger); + PairedLAPPDTimeStamps[matchedTrack].push_back(LAPPDtime); + PairedLAPPD_TriggerIndex[matchedTrack].push_back(matchedIndex); + + matchedLAPPDTimes.push_back(LAPPDtime); + indexToRemove.push_back(i); + matchedLAPPDNumber++; + matchedNumberInTrack[matchedTrack]++; + Log("EBLAPPD: Buffer " + std::to_string(i) + " with time " + std::to_string(Buffer_LAPPDTimestamp_ns.at(i)) + ": Found a match for LAPPD data at " + std::to_string(LAPPDtime) + " with target trigger at " + std::to_string(minDTTrigger) + " with minDT " + std::to_string(minDT), v_message, verbosityEBLAPPD); + } + } + Log("EBLAPPD: Finished matching LAPPD data with target triggers, " + std::to_string(matchedLAPPDTimes.size()) + " new matched found, total matchedLAPPDNumber = " + std::to_string(matchedLAPPDNumber) + " in buffer size = " + std::to_string(MatchBuffer_LAPPDTimestamp_ns.size()), v_message, verbosityEBLAPPD); + + for (int i = indexToRemove.size() - 1; i >= 0; i--) + { + MatchBuffer_LAPPDTimestamp_ns.erase(MatchBuffer_LAPPDTimestamp_ns.begin() + indexToRemove.at(i)); + } + + Log("EBLAPPD: Finished removing paired LAPPD data from match buffer, MatchBuffer_LAPPDTimestamp_ns size is now " + std::to_string(MatchBuffer_LAPPDTimestamp_ns.size()), v_message, verbosityEBLAPPD); + // print all elements in matchedNumberInTrack with key and value + for (std::pair pair : matchedNumberInTrack) + { + Log("EBLAPPD: Match finished, matched number in Track " + std::to_string(pair.first) + " is = " + std::to_string(pair.second), v_message, verbosityEBLAPPD); + } + + return true; +} \ No newline at end of file diff --git a/UserTools/EBLAPPD/EBLAPPD.h b/UserTools/EBLAPPD/EBLAPPD.h new file mode 100644 index 000000000..a1dd6cfa3 --- /dev/null +++ b/UserTools/EBLAPPD/EBLAPPD.h @@ -0,0 +1,95 @@ +#ifndef EBLAPPD_H +#define EBLAPPD_H + +#include +#include + +#include "Tool.h" +#include "PsecData.h" +#include "BoostStore.h" + +/** + * \class EBPMT + * + * $Author: Yue Feng $ + * $Date: 2024/04 $ + * Contact: yuef@iaistate.edu + * + */ + +class EBLAPPD : public Tool +{ + +public: + EBLAPPD(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + bool LoadLAPPDData(); + bool CleanData(); + bool Matching(int targetTrigger, int matchToTrack); + +private: + int thisRunNum; + bool matchToAllTriggers; + int exePerMatch; + + PsecData dat; + uint64_t LAPPDBeamgate_ns; + uint64_t LAPPDTimestamp_ns; + uint64_t LAPPDOffset; + unsigned long LAPPDBeamgate_Raw; + unsigned long LAPPDTimestamp_Raw; + int LAPPDBGCorrection; + int LAPPDTSCorrection; + int LAPPDOffset_minus_ps; + uint64_t LAPPDBG_PPSBefore; + uint64_t LAPPDBG_PPSAfter; + uint64_t LAPPDBG_PPSDiff; + int LAPPDBG_PPSMissing; + uint64_t LAPPDTS_PPSBefore; + uint64_t LAPPDTS_PPSAfter; + uint64_t LAPPDTS_PPSDiff; + int LAPPDTS_PPSMissing; + + vector MatchBuffer_LAPPDTimestamp_ns; // used to indexing data for unmatched + + // TODO, maybe make a new "LAPPDBuildData" class? + vector Buffer_LAPPDTimestamp_ns; // used to indexing the data + vector Buffer_LAPPDData; + vector Buffer_LAPPDBeamgate_ns; + vector Buffer_LAPPDOffset; + vector Buffer_LAPPDBeamgate_Raw; + vector Buffer_LAPPDTimestamp_Raw; + vector Buffer_LAPPDBGCorrection; + vector Buffer_LAPPDTSCorrection; + vector Buffer_LAPPDOffset_minus_ps; + vector Buffer_RunCode; + vector Buffer_LAPPDBG_PPSBefore; + vector Buffer_LAPPDBG_PPSAfter; + vector Buffer_LAPPDBG_PPSDiff; + vector Buffer_LAPPDBG_PPSMissing; + vector Buffer_LAPPDTS_PPSBefore; + vector Buffer_LAPPDTS_PPSAfter; + vector Buffer_LAPPDTS_PPSDiff; + vector Buffer_LAPPDTS_PPSMissing; + + std::map> PairedCTCTimeStamps; + std::map> PairedLAPPD_TriggerIndex; + std::map> PairedLAPPDTimeStamps; + + int matchTargetTrigger; + uint64_t matchTolerance_ns; + int verbosityEBLAPPD; + + int matchedLAPPDNumber = 0; + int exeNum = 0; + int currentRunCode; + + int v_message = 1; + int v_warning = 2; + int v_error = 3; + int v_debug = 4; +}; + +#endif diff --git a/UserTools/EBLAPPD/README.md b/UserTools/EBLAPPD/README.md new file mode 100644 index 000000000..c8b4796ae --- /dev/null +++ b/UserTools/EBLAPPD/README.md @@ -0,0 +1,35 @@ +# EBLAPPD + +EBLAPPD tool is a part of Event Building version 2 tool chain. +For reference slides, see: +https://annie-docdb.fnal.gov/cgi-bin/sso/ShowDocument?docid=5633 + +EBLAPPD match the LAPPD beamgate + LAPPD offset to grouped trigger, and save the matching results to CStore for EBSaver. + +## Data + +**PairedCTCTimeStamps** +After matching, the matched trigger timestamp will be saved here. The key is the main trigger word for each run type. +Saved as PairedLAPPDTriggerTimestamp in CStore. + +**PairedLAPPDTimeStamps** +After matching, the matched LAPPD beamgate + offset will be saved here. The key is the main trigger word for each run type. +This and PairedCTCTimeStamps have the same index. A little bit dangerous, but overall works well. +Saved as PairedLAPPDTimeStamps in CStore + + +## Configuration + +**matchTargetTrigger** +This gives which trigger word that the LAPPD beamgate + offset should be matched to. + +**matchTolerance_ns** +This gives the maximum allowed time tolerance between the LAPPD beamgate + offset and the target trigger timestamp. + +**exePerMatch** +This gives how many loops need to be past for one matching between MLAPPD beamgate + offset and target trigger timestamps. +500 is generally fine with beam runs. + +**matchToAllTriggers** +1 or 0. 1 means match to all possible triggers, 0 means only match to the target trigger. + diff --git a/UserTools/Factory/Factory.cpp b/UserTools/Factory/Factory.cpp index c986c48b7..0891d0838 100644 --- a/UserTools/Factory/Factory.cpp +++ b/UserTools/Factory/Factory.cpp @@ -174,5 +174,6 @@ if (tool=="BackTracker") ret=new BackTracker; if (tool=="PrintDQ") ret=new PrintDQ; if (tool=="AssignBunchTimingMC") ret=new AssignBunchTimingMC; if (tool=="FitRWMWaveform") ret=new FitRWMWaveform; +if (tool=="EBLAPPD") ret=new EBLAPPD; return ret; } diff --git a/UserTools/Unity.h b/UserTools/Unity.h index 7e64d4e9b..114074ea5 100644 --- a/UserTools/Unity.h +++ b/UserTools/Unity.h @@ -182,3 +182,4 @@ #include "PrintDQ.h" #include "AssignBunchTimingMC.h" #include "FitRWMWaveform.h" +#include "EBLAPPD.h" From 71ffa81eb299c563db27b17ea04d9dc439981ddd Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Sun, 19 Jan 2025 23:32:55 -0600 Subject: [PATCH 117/163] Add EBSaver for EBV2 tool chain --- UserTools/EBSaver/EBSaver.cpp | 1507 +++++++++++++++++++++++++++++++++ UserTools/EBSaver/EBSaver.h | 202 +++++ UserTools/EBSaver/README.md | 29 + UserTools/Factory/Factory.cpp | 1 + UserTools/Unity.h | 1 + 5 files changed, 1740 insertions(+) create mode 100644 UserTools/EBSaver/EBSaver.cpp create mode 100644 UserTools/EBSaver/EBSaver.h create mode 100644 UserTools/EBSaver/README.md diff --git a/UserTools/EBSaver/EBSaver.cpp b/UserTools/EBSaver/EBSaver.cpp new file mode 100644 index 000000000..f7d459a60 --- /dev/null +++ b/UserTools/EBSaver/EBSaver.cpp @@ -0,0 +1,1507 @@ +#include "EBSaver.h" + +EBSaver::EBSaver() : Tool() {} + +bool EBSaver::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + m_variables.Get("verbosityEBSaver", verbosityEBSaver); + savePath = ""; + m_variables.Get("savePath", savePath); + saveName = "ProcessedData_"; + m_variables.Get("saveName", saveName); + beamInfoFileName = "BeamInfo.root"; + m_variables.Get("beamInfoFileName", beamInfoFileName); + + saveTriggerGroups = true; + savePMT = true; + + saveAllTriggers = false; + m_variables.Get("saveAllTriggers", saveAllTriggers); + saveMRD = true; + m_variables.Get("saveMRD", saveMRD); + saveLAPPD = true; + m_variables.Get("saveLAPPD", saveLAPPD); + saveOrphan = true; + m_variables.Get("saveOrphan", saveOrphan); + saveBeamInfo = true; + m_variables.Get("saveBeamInfo", saveBeamInfo); + + saveRawBRFWaveform = true; + m_variables.Get("saveRawBRFWaveform", saveRawBRFWaveform); + saveRawRWMWaveform = true; + m_variables.Get("saveRawRWMWaveform", saveRawRWMWaveform); + + ANNIEEvent = new BoostStore(false, 2); + + exeNumber = 0; + savedTriggerGroupNumber = 0; + savedPMTHitMapNumber = 0; + savedMRDNumber = 0; + savedLAPPDNumber = 0; + + savePerExe = 2000; + + if (savePMT) + saveName += "PMT"; + if (saveMRD) + saveName += "MRD"; + if (saveLAPPD) + saveName += "LAPPD"; + + m_data->CStore.Get("BeamTriggerMain", BeamTriggerMain); + m_data->CStore.Get("LaserTriggerMain", LaserTriggerMain); + m_data->CStore.Get("CosmicTriggerMain", CosmicTriggerMain); + m_data->CStore.Get("LEDTriggerMain", LEDTriggerMain); + m_data->CStore.Get("AmBeTriggerMain", AmBeTriggerMain); + m_data->CStore.Get("PPSMain", PPSMain); + + InProgressHits = new std::map> *>; + InProgressChkey = new std::map>; + InProgressRecoADCHits = new std::map>>>; + InProgressRecoADCHitsAux = new std::map>>>; + InProgressHitsAux = new std::map> *>; + FinishedRawAcqSize = new std::map>>; + + RWMRawWaveforms = new std::map>; + BRFRawWaveforms = new std::map>; + + if (saveBeamInfo) + { + Log("EBSaver: saveBeamInfo is true, loading Beam Info", v_message, verbosityEBSaver); + LoadBeamInfo(); + } + + return true; +} + +bool EBSaver::Execute() +{ + + bool saveProcessedFile = false; + bool saveEverything = false; + m_data->CStore.Get("SaveProcessedFile", saveProcessedFile); + m_data->CStore.Get("SaveEverything", saveEverything); + if (!saveProcessedFile && !saveEverything) + { + Log("EBSaver: Not saving data in this exe", v_message, verbosityEBSaver); + return true; + } + cout << "\033[1;34m******* EBSaver : Start execute *******\033[0m" << endl; + + m_data->CStore.Get("RunCodeToSave", savingRunCode); + GotAllDataFromOriginalBuffer(); + + Log("EBSaver: Start saving data for run code " + std::to_string(savingRunCode), v_message, verbosityEBSaver); + + // clean the to remove buffer + GroupedTriggerIndexToRemove.clear(); + PMTRunCodeToRemove.clear(); + MRDRunCodeToRemove.clear(); + LAPPDRunCodeToRemove.clear(); + + PMTPairInfoToRemoveTime.clear(); + MRDPairInfoToRemoveTime.clear(); + LAPPDPairInfoToRemoveTime.clear(); + + // get the grouped trigger, save the grouped triggers with the same runcode + cout << "\033[1;34m******* EBSaver : Saving *******\033[0m" << endl; + m_data->CStore.Get("GroupedTriggersInTotal", GroupedTriggersInTotal); + m_data->CStore.Get("RunCodeInTotal", RunCodeInTotal); + + int savedEventNumber = 0; + // loop each track in the RunCodeInTotal; + for (auto const &track : RunCodeInTotal) + { + int triggerTrack = track.first; + std::vector RunCodeVector = track.second; + // check if the RunCodeInTotal[tragetTrigWord] has the same size with GroupedTriggersInTotal[tragetTrigWord] + Log("EBSaver: Looping trigger track " + std::to_string(triggerTrack) + " with RunCodeInTotal size " + std::to_string(RunCodeVector.size()) + " and GroupedTriggersInTotal size " + std::to_string(GroupedTriggersInTotal[triggerTrack].size()), v_message, verbosityEBSaver); + + if (RunCodeVector.size() != GroupedTriggersInTotal[triggerTrack].size()) + { + Log("EBSaver: RunCodeInTotal and GroupedTriggersInTotal size not match, RunCodeVector size " + std::to_string(RunCodeVector.size()) + " and GroupedTriggersInTotal size " + std::to_string(GroupedTriggersInTotal[triggerTrack].size()), v_warning, verbosityEBSaver); + continue; + } + // GroupedTriggersInTotal and RunCodeInTotal have the same size + // same index is the cooresponding data + for (int i = 0; i < RunCodeVector.size(); i++) + { + int runCode = RunCodeVector[i]; + // saving + // if save Everything, in case there might be some mis aligned events not saved to that processed part file correctly and left in buffer, save them to corresponding part file + if (runCode == savingRunCode) + { + Log("\033[1;34m ****EBSaver: Saving a new event with savedEventNumber = " + std::to_string(savedEventNumber) + " ****\033[0m", v_message, verbosityEBSaver); + + std::string saveFileName = savePath + saveName + "_R" + to_string(runCode / 100000) + "S" + to_string((runCode % 100000) / 10000 - 1) + "p" + to_string(runCode % 10000); + Log("EBSaver: Saving to " + saveFileName + " with run code " + std::to_string(runCode) + " at index " + std::to_string(i), v_message, verbosityEBSaver); + + // if in last exe, the runcode for that group of trigger equals to the saving RunCode, save to ANNIEEvent Processed File + SaveToANNIEEvent(saveFileName, runCode, triggerTrack, i); + savedEventNumber++; + } + } + } + + // remove the paired trigger and data timestamp at PairInfoToRemoveIndex from the buffer like PairedLAPPDTimeStamps + for (auto const &track : GroupedTriggerIndexToRemove) + { + int triggerTrack = track.first; + int groupIndex = track.second; + GroupedTriggersInTotal[triggerTrack].erase(GroupedTriggersInTotal[triggerTrack].begin() + groupIndex); + RunCodeInTotal[triggerTrack].erase(RunCodeInTotal[triggerTrack].begin() + groupIndex); + } + int PMTToRemove = 0; + int MRDToRemove = 0; + int LAPPDToRemove = 0; + for (auto const &track : PMTPairInfoToRemoveTime) + { + int triggerTrack = track.first; + std::vector times = track.second; + PMTToRemove += times.size(); + // print the size of times, and all elements in times + Log("EBSaver: PMT PairInfoToRemoveTime at track " + std::to_string(triggerTrack) + " size " + std::to_string(times.size()), v_message, verbosityEBSaver); + if (verbosityEBSaver > v_message) + { + for (int i = 0; i < times.size(); i++) + cout << i << ": " << times[i] << ", "; + } + } + cout << endl; + for (auto const &track : MRDPairInfoToRemoveTime) + { + int triggerTrack = track.first; + std::vector times = track.second; + MRDToRemove += times.size(); + Log("EBSaver: MRD PairInfoToRemoveTime at track " + std::to_string(triggerTrack) + " size " + std::to_string(times.size()), v_message, verbosityEBSaver); + if (verbosityEBSaver > v_message) + { + for (int i = 0; i < times.size(); i++) + cout << i << ": " << times[i] << ", "; + } + } + cout << endl; + for (auto const &track : LAPPDPairInfoToRemoveTime) + { + int triggerTrack = track.first; + std::vector times = track.second; + LAPPDToRemove += times.size(); + Log("EBSaver: LAPPD PairInfoToRemoveTime at track " + std::to_string(triggerTrack) + " size " + std::to_string(times.size()), v_message, verbosityEBSaver); + if (verbosityEBSaver > v_message) + { + for (int i = 0; i < times.size(); i++) + cout << i << ": " << times[i] << ", "; + } + } + cout << endl; + + Log("EBSaver: before remove from pair info buffer, going to remove PMT " + std::to_string(PMTToRemove) + ", MRD " + std::to_string(MRDToRemove) + ", LAPPD " + std::to_string(LAPPDToRemove), v_message, verbosityEBSaver); + + // print everything in PairedLAPPDTimeStamps for debug + for (auto const &track : PairedLAPPDTimeStamps) + { + int triggerTrack = track.first; + std::vector times = track.second; + Log("EBSaver: PairedLAPPDTimeStamps at track " + std::to_string(triggerTrack) + " size " + std::to_string(times.size()), v_message, verbosityEBSaver); + for (int i = 0; i < times.size(); i++) + cout << i << ": " << times[i] << ", "; + } + // print everything in Buffer_LAPPDTimestamp_ns for debug + Log("EBSaver: Buffer_LAPPDTimestamp_ns size " + std::to_string(Buffer_LAPPDTimestamp_ns.size()), v_message, verbosityEBSaver); + for (int i = 0; i < Buffer_LAPPDTimestamp_ns.size(); i++) + cout << i << ": " << Buffer_LAPPDTimestamp_ns[i] << ", "; + cout << endl; + + // delete LAPPD related timestamps + int removedLAPPD = 0; + for (auto const &track : LAPPDPairInfoToRemoveTime) + { + int triggerTrack = track.first; + std::vector indexes = track.second; + for (int i = 0; i < indexes.size(); i++) + { + int foundIndex = -1; + for (int j = 0; j < PairedLAPPDTimeStamps[triggerTrack].size(); j++) + { + if (PairedLAPPDTimeStamps[triggerTrack][j] == indexes[i]) + { + foundIndex = j; + break; + } + } + if (foundIndex != -1) + { + removedLAPPD++; + Log("EBSaver: Remove LAPPD data with LAPPDTime " + std::to_string(indexes[i]) + " at index " + std::to_string(foundIndex), v_message, verbosityEBSaver); + PairedLAPPDTimeStamps[triggerTrack].erase(PairedLAPPDTimeStamps[triggerTrack].begin() + foundIndex); + PairedLAPPDTriggerTimestamp[triggerTrack].erase(PairedLAPPDTriggerTimestamp[triggerTrack].begin() + foundIndex); + } + } + } + + // delete PMT related timestamps + + for (auto const &track : PMTPairInfoToRemoveTime) + { + int triggerTrack = track.first; + std::vector indexes = track.second; + for (int i = 0; i < indexes.size(); i++) + { + int foundIndex = -1; + for (int j = 0; j < PairedPMTTimeStamps[triggerTrack].size(); j++) + { + if (PairedPMTTimeStamps[triggerTrack][j] == indexes[i]) + { + foundIndex = j; + break; + } + } + if (foundIndex != -1) + { + PairedPMTTimeStamps[triggerTrack].erase(PairedPMTTimeStamps[triggerTrack].begin() + foundIndex); + PairedPMTTriggerTimestamp[triggerTrack].erase(PairedPMTTriggerTimestamp[triggerTrack].begin() + foundIndex); + } + } + } + + // delete MRD related timestamps + for (auto const &track : MRDPairInfoToRemoveTime) + { + int triggerTrack = track.first; + std::vector indexes = track.second; + for (int i = 0; i < indexes.size(); i++) + { + int foundIndex = -1; + for (int j = 0; j < PairedMRDTimeStamps[triggerTrack].size(); j++) + { + if (PairedMRDTimeStamps[triggerTrack][j] == indexes[i]) + { + foundIndex = j; + break; + } + } + if (foundIndex != -1) + { + PairedMRDTimeStamps[triggerTrack].erase(PairedMRDTimeStamps[triggerTrack].begin() + foundIndex); + PairedMRDTriggerTimestamp[triggerTrack].erase(PairedMRDTriggerTimestamp[triggerTrack].begin() + foundIndex); + } + } + } + + ANNIEEvent->Close(); + ANNIEEvent->Delete(); + delete ANNIEEvent; + ANNIEEvent = new BoostStore(false, 2); + + if (saveEverything) + { + Log("EBSaver: Save everything", v_message, verbosityEBSaver); + } + + // now save other data left in the data buffer to orphan + // loop the runcode buffer of each data store, find which run code we need to save + // then loop the run code vector, for each run code, loop all data buffers, save the left data with the save run code + + m_data->CStore.Set("GroupedTriggersInTotal", GroupedTriggersInTotal); + m_data->CStore.Set("RunCodeInTotal", RunCodeInTotal); + m_data->CStore.Set("PairedLAPPDTriggerTimestamp", PairedLAPPDTriggerTimestamp); + m_data->CStore.Set("PairedLAPPDTimeStamps", PairedLAPPDTimeStamps); + m_data->CStore.Set("PairedPMTTriggerTimestamp", PairedPMTTriggerTimestamp); + m_data->CStore.Set("PairedPMTTimeStamps", PairedPMTTimeStamps); + m_data->CStore.Set("PairedMRDTriggerTimestamp", PairedMRDTriggerTimestamp); + m_data->CStore.Set("PairedMRDTimeStamps", PairedMRDTimeStamps); + + Log("EBSaver: Execute finished, saved PMT " + std::to_string(savedPMTHitMapNumber) + ", MRD " + std::to_string(savedMRDNumber) + ", LAPPD " + std::to_string(savedLAPPDNumber) + ", trigger group " + std::to_string(savedTriggerGroupNumber), v_message, verbosityEBSaver); + + Log("EBSaver: Set PMT pairing information buffer PairedPMTTimeStamps size " + std::to_string(PairedPMTTimeStamps.size()), v_message, verbosityEBSaver); + // print size of each track + for (auto const &track : PairedPMTTimeStamps) + Log("EBSaver: track " + std::to_string(track.first) + " size " + std::to_string(track.second.size()), v_message, verbosityEBSaver); + Log("EBSaver: Set MRD pairing information buffer PairedMRDTimeStamps size " + std::to_string(PairedMRDTimeStamps.size()), v_message, verbosityEBSaver); + for (auto const &track : PairedMRDTimeStamps) + Log("EBSaver: track " + std::to_string(track.first) + " size " + std::to_string(track.second.size()), v_message, verbosityEBSaver); + Log("EBSaver: Set LAPPD pairing information buffer PairedLAPPDTimeStamps size " + std::to_string(PairedLAPPDTimeStamps.size()), v_message, verbosityEBSaver); + for (auto const &track : PairedLAPPDTimeStamps) + Log("EBSaver: track " + std::to_string(track.first) + " size " + std::to_string(track.second.size()), v_message, verbosityEBSaver); + + SetDataObjects(); + cout << "\033[1;34m******* EBSaver : Finished *******\033[0m" << endl; + + return true; +} + +bool EBSaver::Finalise() +{ + Log("\033[1;34mEBSaver: Finalising\033[0m", v_message, verbosityEBSaver); + ANNIEEvent->Close(); + ANNIEEvent->Delete(); + delete ANNIEEvent; + + Log("EBSaver: Finished built " + std::to_string(TotalBuiltEventsNumber) + " events", v_message, verbosityEBSaver); + Log("EBSaver: Finished built " + std::to_string(savedTriggerGroupNumber) + " trigger groups", v_message, verbosityEBSaver); + Log("EBSaver: Finished built " + std::to_string(savedPMTHitMapNumber) + " PMT hit maps", v_message, verbosityEBSaver); + Log("EBSaver: Finished built " + std::to_string(savedMRDNumber) + " MRD events", v_message, verbosityEBSaver); + Log("EBSaver: Finished built " + std::to_string(savedLAPPDNumber) + " LAPPD events", v_message, verbosityEBSaver); + Log("EBSaver: matched but not built event number: ***********", v_message, verbosityEBSaver); + Log("\033[1;34mEBSaver: left PMT events in pairing info buffer " + std::to_string(PairedPMTTimeStamps.size()) + " \033[0m", v_message, verbosityEBSaver); + // also print the size of each track with track word + + for (auto const &track : PairedPMTTimeStamps) + { + Log("EBSaver: track " + std::to_string(track.first) + ", total left trigger number " + std::to_string(track.second.size()), v_message, verbosityEBSaver); + if (verbosityEBSaver > 9) + { + // count how many events not built for each trigger word + std::map unbuiltEvents; + for (int i = 0; i < track.second.size(); i++) + { + if (PairedPMTTimeStamps[track.first][i] != 0) + unbuiltEvents[PairedPMTTimeStamps[track.first][i]]++; + } + for (auto const &event : unbuiltEvents) + Log("EBSaver: track " + std::to_string(track.first) + ", left trigger " + std::to_string(event.first) + " number " + std::to_string(event.second), v_message, verbosityEBSaver); + } + } + Log("\033[1;34mEBSaver: left MRD events in pairing info buffer " + std::to_string(PairedMRDTimeStamps.size()) + " \033[0m", v_message, verbosityEBSaver); + for (auto const &track : PairedMRDTimeStamps) + { + Log("EBSaver: track " + std::to_string(track.first) + ", left trigger number " + std::to_string(track.second.size()), v_message, verbosityEBSaver); + if (verbosityEBSaver > 9) + { + // count how many events not built for each trigger word + std::map unbuiltEvents; + for (int i = 0; i < track.second.size(); i++) + { + if (PairedMRDTimeStamps[track.first][i] != 0) + unbuiltEvents[PairedMRDTimeStamps[track.first][i]]++; + } + for (auto const &event : unbuiltEvents) + Log("EBSaver: track " + std::to_string(track.first) + ", left trigger " + std::to_string(event.first) + " number " + std::to_string(event.second), v_message, verbosityEBSaver); + } + } + Log("\033[1;34mEBSaver: left LAPPD events in pairing info buffer " + std::to_string(PairedLAPPDTimeStamps.size()) + " \033[0m", v_message, verbosityEBSaver); + for (auto const &track : PairedLAPPDTimeStamps) + { + Log("EBSaver: track " + std::to_string(track.first) + ", left trigger number " + std::to_string(track.second.size()), v_message, verbosityEBSaver); + // count how many events not built for each trigger word + if (verbosityEBSaver > 9) + { + std::map unbuiltEvents; + for (int i = 0; i < track.second.size(); i++) + { + if (PairedLAPPDTimeStamps[track.first][i] != 0) + unbuiltEvents[PairedLAPPDTimeStamps[track.first][i]]++; + } + for (auto const &event : unbuiltEvents) + Log("EBSaver: track " + std::to_string(track.first) + ", left trigger " + std::to_string(event.first) + " number " + std::to_string(event.second), v_message, verbosityEBSaver); + } + } + Log("EBSaver: left event number: ***********", v_message, verbosityEBSaver); + Log("EBSaver: left PMT events in original data buffer " + std::to_string(InProgressHits->size()), v_message, verbosityEBSaver); + Log("EBSaver: left MRD events in original data buffer " + std::to_string(MRDEvents.size()), v_message, verbosityEBSaver); + Log("EBSaver: left LAPPD events in original data buffer " + std::to_string(Buffer_LAPPDTimestamp_ns.size()), v_message, verbosityEBSaver); + // print the size of each track of + + // add debug print for the left MRD, print TriggerTimeWithoutMRD and PairedMRDTimeStamps to two txt file + if (verbosityEBSaver > 9) + { + std::ofstream TriggerTimeWithoutMRDFile; + TriggerTimeWithoutMRDFile.open("EBdebug_TriggerTimeWithoutMRD.txt"); + for (auto const &track : TriggerTimeWithoutMRD) + { + TriggerTimeWithoutMRDFile << track.first << " " << track.second << endl; + } + TriggerTimeWithoutMRDFile.close(); + std::ofstream PairedMRDTimeStampsFile; + PairedMRDTimeStampsFile.open("EBdebug_PairedMRDTimeStamps.txt"); + for (auto const &track : PairedMRDTimeStamps) + { + for (int i = 0; i < track.second.size(); i++) + { + PairedMRDTimeStampsFile << track.first << " " << track.second[i] << endl; + } + } + } + + return true; +} + +bool EBSaver::SaveToANNIEEvent(string saveFileName, int runCode, int triggerTrack, int trackIndex) +{ + SaveRunInfo(runCode); + std::map DataStreams; + DataStreams.emplace("Tank", 0); + DataStreams.emplace("MRD", 0); + DataStreams.emplace("CTC", 1); + DataStreams.emplace("LAPPD", 0); + + SaveGroupedTriggers(triggerTrack, trackIndex); + + bool PMTSaved = false; // incase of multiple 14 found in one group + bool MRDSaved = false; + bool LAPPDSaved = false; + bool beamInfoSaved = false; + + std::map GroupedTrigger = GroupedTriggersInTotal[triggerTrack][trackIndex]; + // For each element in GroupedTrigger, find is it appear in PairedPMTTriggerTimestamp[triggerTrack], + // if yes, got the index, access the same index at PairedPMTTimeStamps[triggerTrack], that uint64_t is the PMTTime + for (auto &trigger : GroupedTrigger) + { + uint64_t triggerTime = trigger.first; + uint32_t triggerType = trigger.second; + if (triggerType == 14) + { + Log("EBSaver: Found undelayed beam trigger with time " + std::to_string(triggerTime) + " in GroupedTrigger", v_debug, verbosityEBSaver); + if (!beamInfoSaved) + { + SaveBeamInfo(triggerTime); + beamInfoSaved = true; + } + } + + if (PairedPMTTriggerTimestamp.find(triggerTrack) != PairedPMTTriggerTimestamp.end()) + { + for (int i = 0; i < PairedPMTTriggerTimestamp.at(triggerTrack).size(); i++) + { + if (PairedPMTTriggerTimestamp.at(triggerTrack).at(i) == triggerTime) + { + uint64_t PMTTime = PairedPMTTimeStamps.at(triggerTrack).at(i); + Log("EBSaver: Found trigger with time " + std::to_string(triggerTime) + " in PairedPMTTriggerTimestamp " + std::to_string(i) + " match with PMTTime " + std::to_string(PMTTime), v_debug, verbosityEBSaver); + + bool saved = SavePMTData(PMTTime); + PMTSaved = saved; + DataStreams["Tank"] = 1; + if (saved) + PMTPairInfoToRemoveTime[triggerTrack].push_back(PMTTime); + Log("EBSaver: Saved " + std::to_string(savedPMTHitMapNumber) + " PMT data with PMTTime " + std::to_string(PMTTime), v_debug, verbosityEBSaver); + // break; + } + } + } + + // check if PairedMRDTriggerTimestamp has element with key = triggerTrack + if (!MRDSaved) + { + Log("Finding trigger track = " + std::to_string(triggerTrack) + " in PairedMRDTriggerTimestamp", v_debug, verbosityEBSaver); + // print PairedMRDTriggerTimestamp with track number and size + for (auto const &track : PairedMRDTriggerTimestamp) + { + Log("EBSaver: in PairedMRDTriggerTimestamp track " + std::to_string(track.first) + ", left trigger number " + std::to_string(track.second.size()), v_debug, verbosityEBSaver); + } + for (auto const &track : PairedMRDTimeStamps) + { + Log("EBSaver: in PairedMRDTimeStamps track " + std::to_string(track.first) + ", left trigger number " + std::to_string(track.second.size()), v_debug, verbosityEBSaver); + } + if (PairedMRDTriggerTimestamp.find(triggerTrack) != PairedMRDTriggerTimestamp.end()) + { + if (triggerTime > PairedMRDTriggerTimestamp.at(triggerTrack).at(0) && triggerTime < PairedMRDTriggerTimestamp.at(triggerTrack).at(PairedMRDTriggerTimestamp.at(triggerTrack).size() - 1)) + { + uint64_t minDiff = 100 * 60 * 1e9; + Log("Found trigger track = " + std::to_string(triggerTrack) + " in PairedMRDTriggerTimestamp with current searching trigger type = " + std::to_string(triggerType) + " and trigger time = " + std::to_string(triggerTime), v_debug, verbosityEBSaver); + // print the size of PairedMRDTriggerTimestamp.at(triggerTrack), print the first and the last timestamp + Log("EBSaver: PairedMRDTriggerTimestamp size " + std::to_string(PairedMRDTriggerTimestamp.at(triggerTrack).size()), v_debug, verbosityEBSaver); + if (PairedMRDTriggerTimestamp.at(triggerTrack).size() > 0) + Log("EBSaver: PairedMRDTriggerTimestamp first " + std::to_string(PairedMRDTriggerTimestamp.at(triggerTrack).at(0)) + ", last " + std::to_string(PairedMRDTriggerTimestamp.at(triggerTrack).at(PairedMRDTriggerTimestamp.at(triggerTrack).size() - 1)), v_debug, verbosityEBSaver); + + for (int i = 0; i < PairedMRDTriggerTimestamp.at(triggerTrack).size(); i++) + { + uint64_t diff = (PairedMRDTriggerTimestamp.at(triggerTrack).at(i) > triggerTime) ? PairedMRDTriggerTimestamp.at(triggerTrack).at(i) - triggerTime : triggerTime - PairedMRDTriggerTimestamp.at(triggerTrack).at(i); + if (diff < minDiff) + minDiff = diff; + + if (PairedMRDTriggerTimestamp.at(triggerTrack).at(i) == triggerTime || (diff < 1e6)) + { + if (diff < 1e6) + { + Log("EBSaver: diff<1e6, is " + std::to_string(diff), v_debug, verbosityEBSaver); + TriggerTimeWithoutMRD.emplace(PairedMRDTriggerTimestamp.at(triggerTrack).at(i), static_cast(diff)); + } + uint64_t MRDTime = PairedMRDTimeStamps.at(triggerTrack).at(i); + bool saved = SaveMRDData(MRDTime); + MRDSaved = saved; + DataStreams["MRD"] = 1; + if (MRDSaved) + MRDPairInfoToRemoveTime[triggerTrack].push_back(MRDTime); + Log("EBSaver: Saved " + std::to_string(savedMRDNumber) + " MRD data with MRDTime " + std::to_string(MRDTime), v_debug, verbosityEBSaver); + Log("EBSaver: Found trigger with time " + std::to_string(triggerTime) + " in PairedMRDTriggerTimestamp " + std::to_string(i) + " match with MRDTime " + std::to_string(MRDTime), v_debug, verbosityEBSaver); + // break; + Log("EBSaver: While saving MRD data, use trigger time " + std::to_string(triggerTime) + " with minDiff " + std::to_string(minDiff), v_debug, verbosityEBSaver); + } + } + } + // Log("EBSaver: MRDData saved", 8, verbosityEBSaver); + } + } + + if (PairedLAPPDTriggerTimestamp.find(triggerTrack) != PairedLAPPDTriggerTimestamp.end()) + { + for (int i = 0; i < PairedLAPPDTriggerTimestamp.at(triggerTrack).size(); i++) + { + if (PairedLAPPDTriggerTimestamp.at(triggerTrack).at(i) == triggerTime) + { + uint64_t LAPPDTime = PairedLAPPDTimeStamps.at(triggerTrack).at(i); + bool saved = SaveLAPPDData(LAPPDTime); + LAPPDSaved = saved; + DataStreams["LAPPD"] = 1; + if (LAPPDSaved) + LAPPDPairInfoToRemoveTime[triggerTrack].push_back(LAPPDTime); + Log("EBSaver: Saved " + std::to_string(savedLAPPDNumber) + " LAPPD data with LAPPDTime " + std::to_string(LAPPDTime), v_debug, verbosityEBSaver); + Log("EBSaver: Found trigger with time " + std::to_string(triggerTime) + " in PairedLAPPDTriggerTimestamp " + std::to_string(i) + " match with LAPPDTime " + std::to_string(LAPPDTime), v_debug, verbosityEBSaver); + // break; + } + } + // Log("EBSaver: LAPPDData saved", 8, verbosityEBSaver); + } + } + + ANNIEEvent->Set("DataStreams", DataStreams); + + // if Datastream is not built, save a default empty data for that into the event + if (DataStreams["Tank"] == 0) + BuildEmptyPMTData(); + if (DataStreams["MRD"] == 0) + { + BuildEmptyMRDData(); + if (triggerTrack == 14) + { + // find the time of trigger 8 in current group + uint64_t triggerTime = 0; + for (auto &trigger : GroupedTrigger) + { + if (trigger.second == 8) + { + triggerTime = trigger.first; + break; + } + } + TriggerTimeWithoutMRD.emplace(triggerTime, triggerTrack); + } + else if (triggerTrack == 36) + { + // find the time of trigger 8 in current group + uint64_t triggerTime = 0; + for (auto &trigger : GroupedTrigger) + { + if (trigger.second == 36) + { + triggerTime = trigger.first; + break; + } + } + TriggerTimeWithoutMRD.emplace(triggerTime, triggerTrack); + } + } + + if (DataStreams["LAPPD"] == 0) + BuildEmptyLAPPDData(); + + Log("EBSaver: Print ANNIEEvent, Saving to " + saveFileName, v_debug, verbosityEBSaver); + if (verbosityEBSaver > 8) + ANNIEEvent->Print(false); + ANNIEEvent->Save(saveFileName); + TotalBuiltEventsNumber++; + ANNIEEvent->Delete(); + + return true; +} + +bool EBSaver::SaveRunInfo(int runCode) +{ + int RunNumber = runCode / 100000; + int SubRunNumber = (runCode % 100000) / 10000 - 1; + int PartFileNumber = runCode % 10000; + + ANNIEEvent->Set("RunNumber", RunNumber); + ANNIEEvent->Set("SubRunNumber", SubRunNumber); + ANNIEEvent->Set("PartNumber", PartFileNumber); + Log("EBSaver: Saving run info with RunNumber " + std::to_string(RunNumber) + " SubRunNumber " + std::to_string(SubRunNumber) + " PartFileNumber " + std::to_string(PartFileNumber), v_debug, verbosityEBSaver); + return true; +} + +bool EBSaver::SaveGroupedTriggers(int triggerTrack, int groupIndex) +{ + Log("EBSaver: Saving grouped triggers for trigger track " + std::to_string(triggerTrack) + " with group index " + std::to_string(groupIndex), v_debug, verbosityEBSaver); + std::map GroupedTrigger = GroupedTriggersInTotal[triggerTrack][groupIndex]; + GroupedTriggerIndexToRemove.emplace(triggerTrack, groupIndex); + + ANNIEEvent->Set("GroupedTrigger", GroupedTrigger); + int matchTriggerType = triggerTrack; + ANNIEEvent->Set("PrimaryTriggerWord", matchTriggerType); + if (matchTriggerType != 14) + { + ANNIEEvent->Set("TriggerWord", matchTriggerType); + } + else + { + ANNIEEvent->Set("TriggerWord", 5); + } + + // find the triggertrack trigger time in GroupedTrigger + uint64_t primaryTrigTime = 0; + for (auto &trigger : GroupedTrigger) + { + if (trigger.second == triggerTrack) + { + primaryTrigTime = trigger.first; + break; + } + } + + ANNIEEvent->Set("PrimaryTriggerTime", primaryTrigTime); + ANNIEEvent->Set("CTCTimestamp", primaryTrigTime); + + bool NCExtended = false; + bool CCExtended = false; + std::string TriggerType = ""; + int CTCWordExtended = 0; + uint64_t ExtendedTriggerTime = 0; + + if (triggerTrack == BeamTriggerMain) + { + TriggerType = "Beam"; + // if found 40 in values of GroupedTrigger, set NCExtended to true + // put the data at that index to ExtendedTriggerTime + for (auto &trigger : GroupedTrigger) + { + if (trigger.second == 41) + { + NCExtended = true; + ExtendedTriggerTime = trigger.first; + CTCWordExtended = 1; + break; + } + } + for (auto &trigger : GroupedTrigger) + { + if (trigger.second == 40) + { + CCExtended = true; + ExtendedTriggerTime = trigger.first; + CTCWordExtended = 2; + break; + } + } + } + else if (triggerTrack == LaserTriggerMain) + TriggerType = "Laser"; + else if (triggerTrack == CosmicTriggerMain) + TriggerType = "Cosmic"; + else if (triggerTrack == LEDTriggerMain) + TriggerType = "LED"; + else if (triggerTrack == AmBeTriggerMain) + TriggerType = "AmBe"; + else if (triggerTrack == PPSMain) + TriggerType = "PPS"; + + ANNIEEvent->Set("NCExtended", NCExtended); + ANNIEEvent->Set("CCExtended", CCExtended); + ANNIEEvent->Set("TriggerType", TriggerType); + ANNIEEvent->Set("TriggerExtended", CTCWordExtended); // 0: normal, 1: NC extended, 2: CC extended + // Notice, in the V1 eventbuilder, there is a requirement that the matched trigger time - extended trigger time <5000, if not the extended will be 0 + // we don't have it here because the PMT was not matched to a single trigger, but a group. + // you may need to select the events based on the time difference in the grouped trigger + + TimeClass TriggerTime(primaryTrigTime); + TriggerClass TriggerData(TriggerType, matchTriggerType, CTCWordExtended, true, TriggerTime); + ANNIEEvent->Set("TriggerData", TriggerData); + + savedTriggerGroupNumber++; + Log("EBSaver: Saved trigger group with trigger type " + TriggerType + " and trigger time " + std::to_string(primaryTrigTime), v_debug, verbosityEBSaver); + return true; +} + +bool EBSaver::SavePMTData(uint64_t PMTTime) +{ + Log("EBSaver: Saving PMT data with PMTTime " + std::to_string(PMTTime), v_debug, verbosityEBSaver); + // find PMTTime in InProgressHits, if not found, return false + if (InProgressHits->find(PMTTime) == InProgressHits->end()) + { + Log("EBSaver: PMT data with PMTTime " + std::to_string(PMTTime) + " not found in InProgressHits", v_debug, verbosityEBSaver); + return false; + } + ANNIEEvent->Set("EventTimeTank", PMTTime); + + std::map> *PMTHits = InProgressHits->at(PMTTime); + std::map>> PMTRecoADCHits = InProgressRecoADCHits->at(PMTTime); + std::map> *PMTHitsAux = InProgressHitsAux->at(PMTTime); + std::map>> PMTRecoADCHitsAux = InProgressRecoADCHitsAux->at(PMTTime); + std::map> PMTRawAcqSize = FinishedRawAcqSize->at(PMTTime); + + Log("EBSaver: Got PMT data, saving", v_debug, verbosityEBSaver); + + // check does the ANNIEEvent already have the key "Hits", if yes, print the size of the vector of each key + // also print the size of the vector of each key in new PMTHits + // Then Merger the two maps + std::map> *OldPMTHits = new std::map>; + bool gotHits = ANNIEEvent->Get("Hits", OldPMTHits); + if (gotHits) + { + Log("EBSaver: ANNIEEvent already has key Hits, size " + std::to_string(OldPMTHits->size()), v_debug, verbosityEBSaver); + for (auto const &time : *OldPMTHits) + Log("EBSaver: OldPMTHits old time " + std::to_string(time.first) + " size " + std::to_string(time.second.size()), v_debug, verbosityEBSaver); + for (auto const &time : *PMTHits) + Log("EBSaver: PMTHits new time " + std::to_string(time.first) + " size " + std::to_string(time.second.size()), v_debug, verbosityEBSaver); + for (auto const &time : *OldPMTHits) + { + if (PMTHits->count(time.first) == 0) + { + PMTHits->emplace(time.first, time.second); + } + else + { + for (auto const &hit : time.second) + { + PMTHits->at(time.first).push_back(hit); + } + } + } + Log("EBSaver: Merged PMT data, PMTHits size " + std::to_string(PMTHits->size()), v_debug, verbosityEBSaver); + } + + ANNIEEvent->Set("Hits", PMTHits, true); + ANNIEEvent->Set("RecoADCData", PMTRecoADCHits); + ANNIEEvent->Set("AuxHits", PMTHitsAux, true); + ANNIEEvent->Set("RecoAuxADCData", PMTRecoADCHitsAux); + ANNIEEvent->Set("RawAcqSize", PMTRawAcqSize); + + if (saveRawRWMWaveform) + { + // find PMTTime as key in RWMRawWaveforms, if found, save it, if not, save an empty vector + if (RWMRawWaveforms->find(PMTTime) != RWMRawWaveforms->end() && RWMRawWaveforms->at(PMTTime).size() > 0) + { + std::vector RWMRawWaveform = RWMRawWaveforms->at(PMTTime); + ANNIEEvent->Set("RWMRawWaveform", RWMRawWaveform); + Log("EBSaver: Saved RWM data with PMTTime " + std::to_string(PMTTime), v_debug, verbosityEBSaver); + RWMRawWaveforms->erase(PMTTime); + } + else + { + std::vector RWMRawWaveform; + ANNIEEvent->Set("RWMRawWaveform", RWMRawWaveform); + Log("EBSaver: Saved empty RWM data with PMTTime " + std::to_string(PMTTime), v_debug, verbosityEBSaver); + } + } + if (saveRawBRFWaveform) + { + // find PMTTime as key in BRFRawWaveforms, if found, save it, if not, save an empty vector + if (BRFRawWaveforms->find(PMTTime) != BRFRawWaveforms->end() && BRFRawWaveforms->at(PMTTime).size() > 0) + { + std::vector BRFRawWaveform = BRFRawWaveforms->at(PMTTime); + ANNIEEvent->Set("BRFRawWaveform", BRFRawWaveform); + Log("EBSaver: Saved BRF data with PMTTime " + std::to_string(PMTTime), v_debug, verbosityEBSaver); + BRFRawWaveforms->erase(PMTTime); + } + else + { + std::vector BRFRawWaveform; + ANNIEEvent->Set("BRFRawWaveform", BRFRawWaveform); + Log("EBSaver: Saved empty BRF data with PMTTime " + std::to_string(PMTTime), v_debug, verbosityEBSaver); + } + } + + savedPMTHitMapNumber++; + + // erase the built data from original data buffer + InProgressHits->erase(PMTTime); + InProgressRecoADCHits->erase(PMTTime); + InProgressHitsAux->erase(PMTTime); + InProgressRecoADCHitsAux->erase(PMTTime); + FinishedRawAcqSize->erase(PMTTime); + + Log("EBSaver: Saved PMT data with PMTTime " + std::to_string(PMTTime), v_debug, verbosityEBSaver); + return true; +} + +bool EBSaver::SaveMRDData(uint64_t MRDTime) +{ + Log("EBSaver: Saving MRD data with MRDTime " + std::to_string(MRDTime), v_debug, verbosityEBSaver); + // find MRDTime in MRDEvents, if not found, return false + if (MRDEvents.find(MRDTime) == MRDEvents.end()) + { + Log("EBSaver: not found MRD data with MRDTime " + std::to_string(MRDTime) + " in MRDEvents", v_debug, verbosityEBSaver); + return false; + } + + // find the index of the MRDTime in PairedMRDTimeStamps + std::vector> MRDHits = MRDEvents.at(MRDTime); + std::string MRDTriggerType = MRDEventTriggerTypes.at(MRDTime); + int beam_tdc = MRDBeamLoopback.at(MRDTime); + int cosmic_tdc = MRDCosmicLoopback.at(MRDTime); + + std::map> *TDCData = new std::map>; + + for (unsigned int i_value = 0; i_value < MRDHits.size(); i_value++) + { + unsigned long channelkey = MRDHits.at(i_value).first; + int hitTimeADC = MRDHits.at(i_value).second; + double hitTime = 4000. - 4. * static_cast(hitTimeADC); + + if (TDCData->count(channelkey) == 0) + { + std::vector newhitvector; + newhitvector.push_back(Hit(0, hitTime, 1.)); + TDCData->emplace(channelkey, newhitvector); + } + else + { + TDCData->at(channelkey).push_back(Hit(0, hitTime, 1.)); + } + } + + std::map mrd_loopback_tdc; + mrd_loopback_tdc.emplace("BeamLoopbackTDC", beam_tdc); + mrd_loopback_tdc.emplace("CosmicLoopbackTDC", cosmic_tdc); + + Log("EBSaver: TDCdata size: " + std::to_string(TDCData->size()), v_warning, verbosityEBSaver); + + ANNIEEvent->Set("TDCData", TDCData, true); + TimeClass t(MRDTime); + ANNIEEvent->Set("EventTimeMRD", t); + ANNIEEvent->Set("MRDTriggerType", MRDTriggerType); + ANNIEEvent->Set("MRDLoopbackTDC", mrd_loopback_tdc); + + savedMRDNumber++; + + // erase the built data from original data buffer + MRDEvents.erase(MRDTime); + MRDEventTriggerTypes.erase(MRDTime); + MRDBeamLoopback.erase(MRDTime); + MRDCosmicLoopback.erase(MRDTime); + + Log("EBSaver: Saved MRD data with MRDTime " + std::to_string(MRDTime), v_debug, verbosityEBSaver); + return true; +} + +bool EBSaver::SaveLAPPDData(uint64_t LAPPDTime) +{ + Log("EBSaver: Saving LAPPD data with LAPPDTime " + std::to_string(LAPPDTime), v_debug, verbosityEBSaver); + // find LAPPDTime in Buffer_LAPPDTimestamp_ns, if not found, return false + if (std::find(Buffer_LAPPDTimestamp_ns.begin(), Buffer_LAPPDTimestamp_ns.end(), LAPPDTime) == Buffer_LAPPDTimestamp_ns.end()) + { + Log("EBSaver: LAPPD data with LAPPDTime " + std::to_string(LAPPDTime) + " not found in Buffer_LAPPDTimestamp_ns", v_debug, verbosityEBSaver); + return false; + } + + // find the index of the LAPPDTime in PairedLAPPDTimeStamps + int index = -1; + for (int i = 0; i < Buffer_LAPPDTimestamp_ns.size(); i++) + { + if (Buffer_LAPPDTimestamp_ns.at(i) == LAPPDTime) + { + index = i; + break; + } + } + + // save the data at index i to ANNIE event, then remove that index from buffer + if (index != -1) + { + std::map LAPPDDataMap; + std::map LAPPDBeamgate_ns; + std::map LAPPDTimeStamps_ns; // data and key are the same + std::map LAPPDTimeStampsRaw; + std::map LAPPDBeamgatesRaw; + std::map LAPPDOffsets; + std::map LAPPDTSCorrection; + std::map LAPPDBGCorrection; + std::map LAPPDOSInMinusPS; + std::map LAPPDBG_PPSBefore; + std::map LAPPDBG_PPSAfter; + std::map LAPPDBG_PPSDiff; + std::map LAPPDBG_PPSMissing; + std::map LAPPDTS_PPSBefore; + std::map LAPPDTS_PPSAfter; + std::map LAPPDTS_PPSDiff; + std::map LAPPDTS_PPSMissing; + + bool gotMap = ANNIEEvent->Get("LAPPDDataMap", LAPPDDataMap); + bool gotBeamgates_ns = ANNIEEvent->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + bool gotTimeStamps_ns = ANNIEEvent->Get("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); + bool gotTimeStampsRaw = ANNIEEvent->Get("LAPPDTimeStampsRaw", LAPPDTimeStampsRaw); + bool gotBeamgatesRaw = ANNIEEvent->Get("LAPPDBeamgatesRaw", LAPPDBeamgatesRaw); + bool gotOffsets = ANNIEEvent->Get("LAPPDOffsets", LAPPDOffsets); + bool gotTSCorrection = ANNIEEvent->Get("LAPPDTSCorrection", LAPPDTSCorrection); + bool gotDBGCorrection = ANNIEEvent->Get("LAPPDBGCorrection", LAPPDBGCorrection); + bool gotOSInMinusPS = ANNIEEvent->Get("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + bool gotBG_PPSBefore = ANNIEEvent->Get("LAPPDBG_PPSBefore", LAPPDBG_PPSBefore); + bool gotBG_PPSAfter = ANNIEEvent->Get("LAPPDBG_PPSAfter", LAPPDBG_PPSAfter); + bool gotBG_PPSDiff = ANNIEEvent->Get("LAPPDBG_PPSDiff", LAPPDBG_PPSDiff); + bool gotBG_PPSMissing = ANNIEEvent->Get("LAPPDBG_PPSMissing", LAPPDBG_PPSMissing); + bool gotTS_PPSBefore = ANNIEEvent->Get("LAPPDTS_PPSBefore", LAPPDTS_PPSBefore); + bool gotTS_PPSAfter = ANNIEEvent->Get("LAPPDTS_PPSAfter", LAPPDTS_PPSAfter); + bool gotTS_PPSDiff = ANNIEEvent->Get("LAPPDTS_PPSDiff", LAPPDTS_PPSDiff); + bool gotTS_PPSMissing = ANNIEEvent->Get("LAPPDTS_PPSMissing", LAPPDTS_PPSMissing); + + LAPPDDataMap.emplace(LAPPDTime, Buffer_LAPPDData.at(index)); + LAPPDBeamgate_ns.emplace(LAPPDTime, Buffer_LAPPDBeamgate_ns.at(index)); + LAPPDTimeStamps_ns.emplace(LAPPDTime, Buffer_LAPPDTimestamp_ns.at(index)); + LAPPDTimeStampsRaw.emplace(LAPPDTime, Buffer_LAPPDTimestamp_Raw.at(index)); + LAPPDBeamgatesRaw.emplace(LAPPDTime, Buffer_LAPPDBeamgate_Raw.at(index)); + LAPPDOffsets.emplace(LAPPDTime, Buffer_LAPPDOffset.at(index)); + LAPPDTSCorrection.emplace(LAPPDTime, Buffer_LAPPDTSCorrection.at(index)); + LAPPDBGCorrection.emplace(LAPPDTime, Buffer_LAPPDBGCorrection.at(index)); + LAPPDOSInMinusPS.emplace(LAPPDTime, Buffer_LAPPDOffset_minus_ps.at(index)); + LAPPDBG_PPSBefore.emplace(LAPPDTime, Buffer_LAPPDBG_PPSBefore.at(index)); + LAPPDBG_PPSAfter.emplace(LAPPDTime, Buffer_LAPPDBG_PPSAfter.at(index)); + LAPPDBG_PPSDiff.emplace(LAPPDTime, Buffer_LAPPDBG_PPSDiff.at(index)); + LAPPDBG_PPSMissing.emplace(LAPPDTime, Buffer_LAPPDBG_PPSMissing.at(index)); + LAPPDTS_PPSBefore.emplace(LAPPDTime, Buffer_LAPPDTS_PPSBefore.at(index)); + LAPPDTS_PPSAfter.emplace(LAPPDTime, Buffer_LAPPDTS_PPSAfter.at(index)); + LAPPDTS_PPSDiff.emplace(LAPPDTime, Buffer_LAPPDTS_PPSDiff.at(index)); + LAPPDTS_PPSMissing.emplace(LAPPDTime, Buffer_LAPPDTS_PPSMissing.at(index)); + + if (Buffer_LAPPDTS_PPSMissing.at(index) != Buffer_LAPPDBG_PPSMissing.at(index)) + { + Log("EBSaver: LAPPDTS_PPSMissing is different from LAPPDBG_PPSMissing, LAPPDTS_PPSMissing " + std::to_string(Buffer_LAPPDTS_PPSMissing.at(index)) + " LAPPDBG_PPSMissing " + std::to_string(Buffer_LAPPDBG_PPSMissing.at(index)), v_message, verbosityEBSaver); + } + + ANNIEEvent->Set("LAPPDDataMap", LAPPDDataMap); + ANNIEEvent->Set("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + ANNIEEvent->Set("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); + ANNIEEvent->Set("LAPPDTimeStampsRaw", LAPPDTimeStampsRaw); + ANNIEEvent->Set("LAPPDBeamgatesRaw", LAPPDBeamgatesRaw); + ANNIEEvent->Set("LAPPDOffsets", LAPPDOffsets); + ANNIEEvent->Set("LAPPDTSCorrection", LAPPDTSCorrection); + ANNIEEvent->Set("LAPPDBGCorrection", LAPPDBGCorrection); + ANNIEEvent->Set("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + ANNIEEvent->Set("LAPPDBG_PPSBefore", LAPPDBG_PPSBefore); + ANNIEEvent->Set("LAPPDBG_PPSAfter", LAPPDBG_PPSAfter); + ANNIEEvent->Set("LAPPDBG_PPSDiff", LAPPDBG_PPSDiff); + ANNIEEvent->Set("LAPPDBG_PPSMissing", LAPPDBG_PPSMissing); + ANNIEEvent->Set("LAPPDTS_PPSBefore", LAPPDTS_PPSBefore); + ANNIEEvent->Set("LAPPDTS_PPSAfter", LAPPDTS_PPSAfter); + ANNIEEvent->Set("LAPPDTS_PPSDiff", LAPPDTS_PPSDiff); + ANNIEEvent->Set("LAPPDTS_PPSMissing", LAPPDTS_PPSMissing); + + savedLAPPDNumber++; + + // erase the built data from original data buffer + Buffer_LAPPDData.erase(Buffer_LAPPDData.begin() + index); + Buffer_LAPPDBeamgate_ns.erase(Buffer_LAPPDBeamgate_ns.begin() + index); + Buffer_LAPPDTimestamp_ns.erase(Buffer_LAPPDTimestamp_ns.begin() + index); + Buffer_LAPPDTimestamp_Raw.erase(Buffer_LAPPDTimestamp_Raw.begin() + index); + Buffer_LAPPDBeamgate_Raw.erase(Buffer_LAPPDBeamgate_Raw.begin() + index); + Buffer_LAPPDOffset.erase(Buffer_LAPPDOffset.begin() + index); + Buffer_LAPPDTSCorrection.erase(Buffer_LAPPDTSCorrection.begin() + index); + Buffer_LAPPDBGCorrection.erase(Buffer_LAPPDBGCorrection.begin() + index); + Buffer_LAPPDOffset_minus_ps.erase(Buffer_LAPPDOffset_minus_ps.begin() + index); + Buffer_LAPPDBG_PPSBefore.erase(Buffer_LAPPDBG_PPSBefore.begin() + index); + Buffer_LAPPDBG_PPSAfter.erase(Buffer_LAPPDBG_PPSAfter.begin() + index); + Buffer_LAPPDBG_PPSDiff.erase(Buffer_LAPPDBG_PPSDiff.begin() + index); + Buffer_LAPPDBG_PPSMissing.erase(Buffer_LAPPDBG_PPSMissing.begin() + index); + Buffer_LAPPDTS_PPSBefore.erase(Buffer_LAPPDTS_PPSBefore.begin() + index); + Buffer_LAPPDTS_PPSAfter.erase(Buffer_LAPPDTS_PPSAfter.begin() + index); + Buffer_LAPPDTS_PPSDiff.erase(Buffer_LAPPDTS_PPSDiff.begin() + index); + Buffer_LAPPDTS_PPSMissing.erase(Buffer_LAPPDTS_PPSMissing.begin() + index); + + Log("EBSaver: Saved LAPPD data with LAPPDTime " + std::to_string(LAPPDTime), v_debug, verbosityEBSaver); + return true; + } + else + { + Log("EBSaver: Failed to find LAPPD data with LAPPDTime " + std::to_string(LAPPDTime), v_debug, verbosityEBSaver); + + return false; + } +} + +bool EBSaver::SaveOrphan(int runCode) +{ + // loop everything in the data buffer, save + SaveOrphanPMT(runCode); + SaveOrphanMRD(runCode); + SaveOrphanLAPPD(runCode); + SaveOrphanCTC(runCode); + return true; +} + +bool EBSaver::SaveOrphanPMT(int runCode) +{ + + return true; +} + +bool EBSaver::SaveOrphanMRD(int runCode) +{ + + return true; +} + +bool EBSaver::SaveOrphanCTC(int runCode) +{ + + return true; +} + +bool EBSaver::SaveOrphanLAPPD(int runCode) +{ + + return true; +} + +bool EBSaver::GotAllDataFromOriginalBuffer() +{ + // got PMT data + bool gotPMTHits = m_data->CStore.Get("InProgressHits", InProgressHits); + bool gotPMTChkey = m_data->CStore.Get("InProgressChkey", InProgressChkey); + bool gotIPRecoADCHits = m_data->CStore.Get("InProgressRecoADCHits", InProgressRecoADCHits); + bool gotIPHitsAux = m_data->CStore.Get("InProgressHitsAux", InProgressHitsAux); + bool gotIPRADCH = m_data->CStore.Get("InProgressRecoADCHitsAux", InProgressRecoADCHitsAux); + bool gotFRAS = m_data->CStore.Get("FinishedRawAcqSize", FinishedRawAcqSize); // Filled in PhaseIIADCCalibrator + bool gotRWM = m_data->CStore.Get("RWMRawWaveforms", RWMRawWaveforms); + bool gotBRF = m_data->CStore.Get("BRFRawWaveforms", BRFRawWaveforms); + + if (!gotPMTHits || !gotPMTChkey || !gotIPRecoADCHits || !gotIPHitsAux || !gotIPRADCH || !gotFRAS) + { + Log("EBSaver: Failed to get some PMT data from buffer", v_message, verbosityEBSaver); + // print which one was failed + if (!gotPMTHits) + Log("EBSaver: Failed to get PMT hits from buffer", v_message, verbosityEBSaver); + if (!gotPMTChkey) + Log("EBSaver: Failed to get PMT chkey from buffer", v_message, verbosityEBSaver); + if (!gotIPRecoADCHits) + Log("EBSaver: Failed to get PMT recoADCHits from buffer", v_message, verbosityEBSaver); + if (!gotIPHitsAux) + Log("EBSaver: Failed to get PMT hits aux from buffer", v_message, verbosityEBSaver); + if (!gotIPRADCH) + Log("EBSaver: Failed to get PMT recoADCHits aux from buffer", v_message, verbosityEBSaver); + if (!gotFRAS) + Log("EBSaver: Failed to get PMT raw acq size from buffer", v_message, verbosityEBSaver); + } + // got PMT match info + bool gotPairedPMTTriggerTimestamp = m_data->CStore.Get("PairedPMTTriggerTimestamp", PairedPMTTriggerTimestamp); + bool gotPairedPMTTimeStamps = m_data->CStore.Get("PairedPMTTimeStamps", PairedPMTTimeStamps); + bool gotPairedPMT_TriggerIndex = m_data->CStore.Get("PairedPMT_TriggerIndex", PairedPMT_TriggerIndex); + bool gotPMTHitmapRunCode = m_data->CStore.Get("PMTHitmapRunCode", PMTHitmapRunCode); + if (!gotPairedPMTTriggerTimestamp || !gotPairedPMTTimeStamps || !gotPairedPMT_TriggerIndex || !gotPMTHitmapRunCode) + { + Log("EBSaver: Failed to get PMT match info from buffer", v_message, verbosityEBSaver); + // print which one was failed + if (!gotPairedPMTTriggerTimestamp) + Log("EBSaver: Failed to get PairedPMTTriggerTimestamp", v_message, verbosityEBSaver); + if (!gotPairedPMTTimeStamps) + Log("EBSaver: Failed to get PairedPMTTimeStamps", v_message, verbosityEBSaver); + if (!gotPairedPMT_TriggerIndex) + Log("EBSaver: Failed to get PairedPMT_TriggerIndex", v_message, verbosityEBSaver); + if (!gotPMTHitmapRunCode) + Log("EBSaver: Failed to get PMTHitmapRunCode", v_message, verbosityEBSaver); + } + // + // got MRD data + bool gotMRDEvents = m_data->CStore.Get("MRDEvents", MRDEvents); + bool gotMRDEventTriggerTypes = m_data->CStore.Get("MRDEventTriggerTypes", MRDEventTriggerTypes); + bool gotMRDBeamLoopback = m_data->CStore.Get("MRDBeamLoopback", MRDBeamLoopback); + bool gotMRDCosmicLoopback = m_data->CStore.Get("MRDCosmicLoopback", MRDCosmicLoopback); + if (!gotMRDEvents || !gotMRDEventTriggerTypes || !gotMRDBeamLoopback || !gotMRDCosmicLoopback) + Log("EBSaver: Failed to get some MRD data from buffer", v_message, verbosityEBSaver); + // got MRD match info + bool gotPairedMRDTriggerTimestamp = m_data->CStore.Get("PairedMRDTriggerTimestamp", PairedMRDTriggerTimestamp); + bool gotPairedMRDTimeStamps = m_data->CStore.Get("PairedMRDTimeStamps", PairedMRDTimeStamps); + bool gotPairedMRD_TriggerIndex = m_data->CStore.Get("PairedMRD_TriggerIndex", PairedMRD_TriggerIndex); + bool gotMRDHitMapRunCode = m_data->CStore.Get("MRDHitMapRunCode", MRDHitMapRunCode); + if (!gotPairedMRDTriggerTimestamp || !gotPairedMRDTimeStamps || !gotPairedMRD_TriggerIndex || !gotMRDHitMapRunCode) + Log("EBSaver: Failed to get MRD match info from buffer", v_message, verbosityEBSaver); + // + // got LAPPD data + bool gotBuffer_LAPPDTimestamp_ns = m_data->CStore.Get("Buffer_LAPPDTimestamp_ns", Buffer_LAPPDTimestamp_ns); + bool gotBuffer_LAPPDData = m_data->CStore.Get("Buffer_LAPPDData", Buffer_LAPPDData); + bool gotBuffer_LAPPDBeamgate_ns = m_data->CStore.Get("Buffer_LAPPDBeamgate_ns", Buffer_LAPPDBeamgate_ns); + bool gotBuffer_LAPPDOffset = m_data->CStore.Get("Buffer_LAPPDOffset", Buffer_LAPPDOffset); + bool gotBuffer_LAPPDBeamgate_Raw = m_data->CStore.Get("Buffer_LAPPDBeamgate_Raw", Buffer_LAPPDBeamgate_Raw); + bool gotBuffer_LAPPDTimestamp_Raw = m_data->CStore.Get("Buffer_LAPPDTimestamp_Raw", Buffer_LAPPDTimestamp_Raw); + bool gotBuffer_LAPPDBGCorrection = m_data->CStore.Get("Buffer_LAPPDBGCorrection", Buffer_LAPPDBGCorrection); + bool gotBuffer_LAPPDTSCorrection = m_data->CStore.Get("Buffer_LAPPDTSCorrection", Buffer_LAPPDTSCorrection); + bool gotBuffer_LAPPDOffset_minus_ps = m_data->CStore.Get("Buffer_LAPPDOffset_minus_ps", Buffer_LAPPDOffset_minus_ps); + if (!gotBuffer_LAPPDTimestamp_ns || !gotBuffer_LAPPDData || !gotBuffer_LAPPDBeamgate_ns || !gotBuffer_LAPPDOffset || !gotBuffer_LAPPDBeamgate_Raw || !gotBuffer_LAPPDTimestamp_Raw || !gotBuffer_LAPPDBGCorrection || !gotBuffer_LAPPDTSCorrection || !gotBuffer_LAPPDOffset_minus_ps) + Log("EBSaver: Failed to get some LAPPD data from buffer", v_message, verbosityEBSaver); + bool gotBuffer_LAPPDBG_PPSBefore = m_data->CStore.Get("Buffer_LAPPDBG_PPSBefore", Buffer_LAPPDBG_PPSBefore); + bool gotBuffer_LAPPDBG_PPSAfter = m_data->CStore.Get("Buffer_LAPPDBG_PPSAfter", Buffer_LAPPDBG_PPSAfter); + bool gotBuffer_LAPPDBG_PPSDiff = m_data->CStore.Get("Buffer_LAPPDBG_PPSDiff", Buffer_LAPPDBG_PPSDiff); + bool gotBuffer_LAPPDBG_PPSMissing = m_data->CStore.Get("Buffer_LAPPDBG_PPSMissing", Buffer_LAPPDBG_PPSMissing); + bool gotBuffer_LAPPDTS_PPSBefore = m_data->CStore.Get("Buffer_LAPPDTS_PPSBefore", Buffer_LAPPDTS_PPSBefore); + bool gotBuffer_LAPPDTS_PPSAfter = m_data->CStore.Get("Buffer_LAPPDTS_PPSAfter", Buffer_LAPPDTS_PPSAfter); + bool gotBuffer_LAPPDTS_PPSDiff = m_data->CStore.Get("Buffer_LAPPDTS_PPSDiff", Buffer_LAPPDTS_PPSDiff); + bool gotBuffer_LAPPDTS_PPSMissing = m_data->CStore.Get("Buffer_LAPPDTS_PPSMissing", Buffer_LAPPDTS_PPSMissing); + if (!gotBuffer_LAPPDBG_PPSBefore || !gotBuffer_LAPPDBG_PPSAfter || !gotBuffer_LAPPDBG_PPSDiff || !gotBuffer_LAPPDBG_PPSMissing || !gotBuffer_LAPPDTS_PPSBefore || !gotBuffer_LAPPDTS_PPSAfter || !gotBuffer_LAPPDTS_PPSDiff || !gotBuffer_LAPPDTS_PPSMissing) + Log("EBSaver: Failed to get LAPPD PPS data from buffer", v_message, verbosityEBSaver); + + // got LAPPD match info + bool gotPairedLAPPDTriggerTimestamp = m_data->CStore.Get("PairedLAPPDTriggerTimestamp", PairedLAPPDTriggerTimestamp); + bool gotPairedLAPPDTimeStamps = m_data->CStore.Get("PairedLAPPDTimeStamps", PairedLAPPDTimeStamps); + bool gotPairedLAPPD_TriggerIndex = m_data->CStore.Get("PairedLAPPD_TriggerIndex", PairedLAPPD_TriggerIndex); + bool gotLAPPDRunCode = m_data->CStore.Get("Buffer_LAPPDRunCode", Buffer_LAPPDRunCode); + if (!gotPairedLAPPDTriggerTimestamp || !gotPairedLAPPDTimeStamps || !gotPairedLAPPD_TriggerIndex || !gotLAPPDRunCode) + { + Log("EBSaver: Failed to get LAPPD match info from buffer", v_message, verbosityEBSaver); + // print which one was failed + if (!gotPairedLAPPDTriggerTimestamp) + Log("EBSaver: Failed to get PairedLAPPDTriggerTimestamp", v_message, verbosityEBSaver); + if (!gotPairedLAPPDTimeStamps) + Log("EBSaver: Failed to get PairedLAPPDTimeStamps", v_message, verbosityEBSaver); + if (!gotPairedLAPPD_TriggerIndex) + Log("EBSaver: Failed to get PairedLAPPD_TriggerIndex", v_message, verbosityEBSaver); + if (!gotLAPPDRunCode) + Log("EBSaver: Failed to get LAPPDRunCode", v_message, verbosityEBSaver); + } + + Log("EBSaver: got PMT pairing information buffer PairedPMTTimeStamps size " + std::to_string(PairedPMTTimeStamps.size()), v_message, verbosityEBSaver); + Log("EBSaver: got MRD pairing information buffer PairedMRDTimeStamps size " + std::to_string(PairedMRDTimeStamps.size()), v_message, verbosityEBSaver); + for (auto const &track : PairedMRDTimeStamps) + { + int triggerTrack = track.first; + std::vector times = track.second; + Log("EBSaver: PairedMRDTimeStamps at track " + std::to_string(triggerTrack) + " size " + std::to_string(times.size()), v_message, verbosityEBSaver); + for (int i = 0; i < times.size(); i++) + cout << i << ": " << times[i] << ", "; + } + cout << endl; + + Log("EBSaver: got LAPPD pairing information buffer PairedLAPPDTimeStamps size " + std::to_string(PairedLAPPDTimeStamps.size()), v_message, verbosityEBSaver); + for (auto const &track : PairedLAPPDTimeStamps) + { + int triggerTrack = track.first; + std::vector times = track.second; + Log("EBSaver: PairedLAPPDTimeStamps at track " + std::to_string(triggerTrack) + " size " + std::to_string(times.size()), v_message, verbosityEBSaver); + for (int i = 0; i < times.size(); i++) + cout << i << ": " << times[i] << ", "; + } + cout << endl; + + // print PairedLAPPD_TriggerIndex + Log("EBSaver: got LAPPD pairing information buffer PairedLAPPD_TriggerIndex size " + std::to_string(PairedLAPPD_TriggerIndex.size()), v_message, verbosityEBSaver); + for (auto const &track : PairedLAPPD_TriggerIndex) + { + int triggerTrack = track.first; + std::vector indexes = track.second; + Log("EBSaver: PairedLAPPD_TriggerIndex at track " + std::to_string(triggerTrack) + " size " + std::to_string(indexes.size()), v_message, verbosityEBSaver); + for (int i = 0; i < indexes.size(); i++) + cout << i << ": " << indexes[i] << ", "; + } + cout << endl; + + // print Buffer_LAPPDBeamgate_ns + Log("EBSaver: got LAPPD pairing information buffer Buffer_LAPPDBeamgate_ns size " + std::to_string(Buffer_LAPPDBeamgate_ns.size()), v_message, verbosityEBSaver); + for (int i = 0; i < Buffer_LAPPDBeamgate_ns.size(); i++) + cout << i << ": " << Buffer_LAPPDBeamgate_ns[i] << ", "; + cout << endl; + + return true; +} + +void EBSaver::SetDataObjects() +{ + // after erase those data, set them back to CStore + // set PMT data + m_data->CStore.Set("InProgressHits", InProgressHits); + m_data->CStore.Set("InProgressChkey", InProgressChkey); + m_data->CStore.Set("InProgressRecoADCHits", InProgressRecoADCHits); + m_data->CStore.Set("InProgressHitsAux", InProgressHitsAux); + m_data->CStore.Set("InProgressRecoADCHitsAux", InProgressRecoADCHitsAux); + m_data->CStore.Set("FinishedRawAcqSize", FinishedRawAcqSize); + m_data->CStore.Set("RWMRawWaveforms", RWMRawWaveforms); + m_data->CStore.Set("BRFRawWaveforms", BRFRawWaveforms); + // set PMT match info + m_data->CStore.Set("PairedPMTTriggerTimestamp", PairedPMTTriggerTimestamp); + m_data->CStore.Set("PairedPMTTimeStamps", PairedPMTTimeStamps); + m_data->CStore.Set("PairedPMT_TriggerIndex", PairedPMT_TriggerIndex); + m_data->CStore.Set("PMTHitmapRunCode", PMTHitmapRunCode); + // set MRD data + m_data->CStore.Set("MRDEvents", MRDEvents); + m_data->CStore.Set("MRDEventTriggerTypes", MRDEventTriggerTypes); + m_data->CStore.Set("MRDBeamLoopback", MRDBeamLoopback); + m_data->CStore.Set("MRDCosmicLoopback", MRDCosmicLoopback); + // set MRD match info + m_data->CStore.Set("PairedMRDTriggerTimestamp", PairedMRDTriggerTimestamp); + m_data->CStore.Set("PairedMRDTimeStamps", PairedMRDTimeStamps); + m_data->CStore.Set("PairedMRD_TriggerIndex", PairedMRD_TriggerIndex); + m_data->CStore.Set("MRDHitMapRunCode", MRDHitMapRunCode); + // set LAPPD data + m_data->CStore.Set("Buffer_LAPPDTimestamp_ns", Buffer_LAPPDTimestamp_ns); + m_data->CStore.Set("Buffer_LAPPDData", Buffer_LAPPDData); + m_data->CStore.Set("Buffer_LAPPDBeamgate_ns", Buffer_LAPPDBeamgate_ns); + m_data->CStore.Set("Buffer_LAPPDOffset", Buffer_LAPPDOffset); + m_data->CStore.Set("Buffer_LAPPDBeamgate_Raw", Buffer_LAPPDBeamgate_Raw); + m_data->CStore.Set("Buffer_LAPPDTimestamp_Raw", Buffer_LAPPDTimestamp_Raw); + m_data->CStore.Set("Buffer_LAPPDBGCorrection", Buffer_LAPPDBGCorrection); + m_data->CStore.Set("Buffer_LAPPDTSCorrection", Buffer_LAPPDTSCorrection); + m_data->CStore.Set("Buffer_LAPPDOffset_minus_ps", Buffer_LAPPDOffset_minus_ps); + m_data->CStore.Set("Buffer_LAPPDBG_PPSBefore", Buffer_LAPPDBG_PPSBefore); + m_data->CStore.Set("Buffer_LAPPDBG_PPSAfter", Buffer_LAPPDBG_PPSAfter); + m_data->CStore.Set("Buffer_LAPPDBG_PPSDiff", Buffer_LAPPDBG_PPSDiff); + m_data->CStore.Set("Buffer_LAPPDBG_PPSMissing", Buffer_LAPPDBG_PPSMissing); + m_data->CStore.Set("Buffer_LAPPDTS_PPSBefore", Buffer_LAPPDTS_PPSBefore); + m_data->CStore.Set("Buffer_LAPPDTS_PPSAfter", Buffer_LAPPDTS_PPSAfter); + m_data->CStore.Set("Buffer_LAPPDTS_PPSDiff", Buffer_LAPPDTS_PPSDiff); + m_data->CStore.Set("Buffer_LAPPDTS_PPSMissing", Buffer_LAPPDTS_PPSMissing); + // set LAPPD match info + m_data->CStore.Set("PairedLAPPDTriggerTimestamp", PairedLAPPDTriggerTimestamp); + m_data->CStore.Set("PairedLAPPDTimeStamps", PairedLAPPDTimeStamps); + m_data->CStore.Set("PairedLAPPD_TriggerIndex", PairedLAPPD_TriggerIndex); + m_data->CStore.Set("Buffer_LAPPDRunCode", Buffer_LAPPDRunCode); +} + +void EBSaver::BuildEmptyPMTData() +{ + std::map> *PMTHits = new std::map>; + std::map>> PMTRecoADCHits; + std::map> *PMTHitsAux = new std::map>; + std::map>> PMTRecoADCHitsAux; + std::map> PMTRawAcqSize; + + ANNIEEvent->Set("Hits", PMTHits, true); + ANNIEEvent->Set("RecoADCData", PMTRecoADCHits); + ANNIEEvent->Set("AuxHits", PMTHitsAux, true); + ANNIEEvent->Set("RecoAuxADCData", PMTRecoADCHitsAux); + ANNIEEvent->Set("RawAcqSize", PMTRawAcqSize); +} + +void EBSaver::BuildEmptyMRDData() +{ + std::map> *TDCData = new std::map>; + std::string MRDTriggerType = ""; + std::map mrd_loopback_tdc; + + ANNIEEvent->Set("TDCData", TDCData, true); + TimeClass t(0); + ANNIEEvent->Set("EventTimeMRD", t); + ANNIEEvent->Set("MRDTriggerType", MRDTriggerType); + ANNIEEvent->Set("MRDLoopbackTDC", mrd_loopback_tdc); +} + +void EBSaver::BuildEmptyLAPPDData() +{ + std::map LAPPDDataMap; + std::map LAPPDBeamgate_ns; + std::map LAPPDTimeStamps_ns; // data and key are the same + std::map LAPPDTimeStampsRaw; + std::map LAPPDBeamgatesRaw; + std::map LAPPDOffsets; + std::map LAPPDTSCorrection; + std::map LAPPDBGCorrection; + std::map LAPPDOSInMinusPS; + std::map LAPPDBG_PPSBefore; + std::map LAPPDBG_PPSAfter; + std::map LAPPDBG_PPSDiff; + std::map LAPPDBG_PPSMissing; + std::map LAPPDTS_PPSBefore; + std::map LAPPDTS_PPSAfter; + std::map LAPPDTS_PPSDiff; + std::map LAPPDTS_PPSMissing; + + ANNIEEvent->Set("LAPPDDataMap", LAPPDDataMap); + ANNIEEvent->Set("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + ANNIEEvent->Set("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); + ANNIEEvent->Set("LAPPDTimeStampsRaw", LAPPDTimeStampsRaw); + ANNIEEvent->Set("LAPPDBeamgatesRaw", LAPPDBeamgatesRaw); + ANNIEEvent->Set("LAPPDOffsets", LAPPDOffsets); + ANNIEEvent->Set("LAPPDTSCorrection", LAPPDTSCorrection); + ANNIEEvent->Set("LAPPDBGCorrection", LAPPDBGCorrection); + ANNIEEvent->Set("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + ANNIEEvent->Set("LAPPDBG_PPSBefore", LAPPDBG_PPSBefore); + ANNIEEvent->Set("LAPPDBG_PPSAfter", LAPPDBG_PPSAfter); + ANNIEEvent->Set("LAPPDBG_PPSDiff", LAPPDBG_PPSDiff); + ANNIEEvent->Set("LAPPDBG_PPSMissing", LAPPDBG_PPSMissing); + ANNIEEvent->Set("LAPPDTS_PPSBefore", LAPPDTS_PPSBefore); + ANNIEEvent->Set("LAPPDTS_PPSAfter", LAPPDTS_PPSAfter); + ANNIEEvent->Set("LAPPDTS_PPSDiff", LAPPDTS_PPSDiff); + ANNIEEvent->Set("LAPPDTS_PPSMissing", LAPPDTS_PPSMissing); +} + +void EBSaver::LoadBeamInfo() +{ + TFile *file = new TFile(beamInfoFileName.c_str(), "READ"); + TTree *tree; + file->GetObject("BeamTree", tree); + + if (!tree) + { + cout << "EBSaver: Failed to load beam info from file with name: " << beamInfoFileName << endl; + return; + } + + // copy from IFBeamDBInterfaceV2.cpp + // Here's some documentation for some of the parameters stored in the beam + // database. It's taken from the MicroBooNE operations wiki: + // http://tinyurl.com/z3c4mxs + // + // The status page shows the present reading of beamline instrumentation. All + // of this data is being stored to IF beam Database. The "IF Beam DB + // dashboard":http://dbweb4.fnal.gov:8080/ifbeam/app/BNBDash/index provides + // another view of beam data. Some of it is redundant to the status page, but + // it verifies that the data is being stored in the database. At present the + // page shows following devices: + // * TOR860, TOR875 - two toroids in BNB measuring beam intensity. TOR860 is + // at the beginning of the beamline, and TOR875 is at the end. + // * THCURR - horn current + // * HWTOUT - horn water temperature coming out of the horn. + // * BTJT2 - target temperature + // * HP875, VP875 - beam horizontal and vertical positions at the 875 + // location, about 4.5 m upstream of the target center. + // * HPTG1, VPTG1 - beam horizontal and vertical positions immediately + // (about 2.5 m) upstream of the target center. + // * HPTG2, VPTG2 - beam horizontal and vertical positions more immediately + // (about 1.5 m) upstream of the target center. + // * Because there are no optics between H/VP875 and H/VPTG2, the movements + // on these monitors should scale with the difference in distances. + // * BTJT2 - target air cooling temperature. Four RTD measure the return + // temperature of the cooling air. This is the one closest to the target. + // * BTH2T2 - target air cooling temperature. This is the temperature of the + // air going into the horn. + + // additionally, the unit of E_TOR860 and E_TOR875 is E12 + + uint64_t timestamp; + double E_TOR860, E_TOR875, THCURR, BTJT2, HP875, VP875, HPTG1, VPTG1, HPTG2, VPTG2, BTH2T2; + + tree->SetBranchAddress("Timestamp", ×tamp); + tree->SetBranchAddress("E_TOR860", &E_TOR860); + tree->SetBranchAddress("E_TOR875", &E_TOR875); + tree->SetBranchAddress("E_THCURR", &THCURR); + tree->SetBranchAddress("E_BTJT2", &BTJT2); + tree->SetBranchAddress("E_HP875", &HP875); + tree->SetBranchAddress("E_VP875", &VP875); + tree->SetBranchAddress("E_HPTG1", &HPTG1); + tree->SetBranchAddress("E_VPTG1", &VPTG1); + tree->SetBranchAddress("E_HPTG2", &HPTG2); + tree->SetBranchAddress("E_VPTG2", &VPTG2); + tree->SetBranchAddress("E_BTH2T2", &BTH2T2); + + Long64_t nentries = tree->GetEntries(); + Log("EBSaver: Loading beam infor, total entries in beam info file: " + std::to_string(nentries), v_message, verbosityEBSaver); + for (Long64_t i = 0; i < nentries; ++i) + { + tree->GetEntry(i); + if (i % (static_cast(nentries / 10)) == 0) + Log("EBSaver: Loading beam info, processed " + std::to_string(i) + " entries", v_message, verbosityEBSaver); + BeamInfoTimestamps.push_back(timestamp); + E_TOR860_map.emplace(timestamp, E_TOR860); + E_TOR875_map.emplace(timestamp, E_TOR875); + THCURR_map.emplace(timestamp, THCURR); + BTJT2_map.emplace(timestamp, BTJT2); + HP875_map.emplace(timestamp, HP875); + VP875_map.emplace(timestamp, VP875); + HPTG1_map.emplace(timestamp, HPTG1); + VPTG1_map.emplace(timestamp, VPTG1); + HPTG2_map.emplace(timestamp, HPTG2); + VPTG2_map.emplace(timestamp, VPTG2); + BTH2T2_map.emplace(timestamp, BTH2T2); + } + + Log("EBSaver: Loaded number of E_TOR860 entries: " + std::to_string(E_TOR860_map.size()), v_message, verbosityEBSaver); + + Log("EBSaver: Finished loading beam info from " + beamInfoFileName, v_message, verbosityEBSaver); + + return; +} + +bool EBSaver::SaveBeamInfo(uint64_t TriggerTime) +{ + double E_TOR860, E_TOR875, THCURR, BTJT2, HP875, VP875, HPTG1, VPTG1, HPTG2, VPTG2, BTH2T2; + // find the closest timestamp in vector BeamInfoTimestamps + + uint64_t closestTimestamp = 0; + double minDiff = 60 * 60 * 1e9; // 60 minutes + int minIndex = -1; + + for (int i = 0; i < BeamInfoTimestamps.size(); i++) + { + uint64_t timestamp = BeamInfoTimestamps.at(i) * 1e6; + double diff = (timestamp > TriggerTime) ? timestamp - TriggerTime : TriggerTime - timestamp; + if (i == 0) + Log("EBSaver: First beam info timestamp is " + std::to_string(timestamp) + " with diff = " + std::to_string(diff), v_warning, verbosityEBSaver); + else if (i == BeamInfoTimestamps.size() - 1) + Log("EBSaver: Last beam info timestamp is " + std::to_string(timestamp) + " with diff = " + std::to_string(diff), v_warning, verbosityEBSaver); + + if (diff < minDiff) + { + minDiff = diff; + minIndex = i; + } + } + + if (minIndex == -1) + { + Log("EBSaver: Failed to find the closest beam info timestamp to trigger time", v_message, verbosityEBSaver); + + uint64_t beamInfoTime_long = 0; + int64_t timeDiff = -9999; + double defaultVal = -9999.; + int beam_good = 0; + ANNIEEvent->Set("BeamInfoTime", beamInfoTime_long); + ANNIEEvent->Set("BeamInfoTimeToTriggerDiff", timeDiff); + ANNIEEvent->Set("beam_E_TOR860", defaultVal); + ANNIEEvent->Set("beam_E_TOR875", defaultVal); + ANNIEEvent->Set("beam_THCURR", defaultVal); + ANNIEEvent->Set("beam_BTJT2", defaultVal); + ANNIEEvent->Set("beam_HP875", defaultVal); + ANNIEEvent->Set("beam_VP875", defaultVal); + ANNIEEvent->Set("beam_HPTG1", defaultVal); + ANNIEEvent->Set("beam_VPTG1", defaultVal); + ANNIEEvent->Set("beam_HPTG2", defaultVal); + ANNIEEvent->Set("beam_VPTG2", defaultVal); + ANNIEEvent->Set("beam_BTH2T2", defaultVal); + ANNIEEvent->Set("beam_good", beam_good); + + Log("EBSaver: Saved beam info with time " + std::to_string(0) + ", pot E_TOR860 = " + std::to_string(-9999) + ", beam_good = " + std::to_string(-9999), v_message, verbosityEBSaver); + } + else + { + Log("Found the closest beam info timestamp to trigger time at index " + std::to_string(minIndex) + " with time " + std::to_string(BeamInfoTimestamps.at(minIndex)) + " and dt = " + std::to_string(minDiff), v_message, verbosityEBSaver); + + // get the precise difference + uint64_t beamInfoTime = BeamInfoTimestamps.at(minIndex); + ULong64_t beamInfoTime_long = beamInfoTime * 1e6; + int64_t timeDiff = beamInfoTime_long - TriggerTime; + + // check if the map has the key + E_TOR860 = E_TOR860_map.at(beamInfoTime); + E_TOR875 = E_TOR875_map.at(beamInfoTime); + THCURR = THCURR_map.at(beamInfoTime); + BTJT2 = BTJT2_map.at(beamInfoTime); + HP875 = HP875_map.at(beamInfoTime); + VP875 = VP875_map.at(beamInfoTime); + HPTG1 = HPTG1_map.at(beamInfoTime); + VPTG1 = VPTG1_map.at(beamInfoTime); + HPTG2 = HPTG2_map.at(beamInfoTime); + VPTG2 = VPTG2_map.at(beamInfoTime); + BTH2T2 = BTH2T2_map.at(beamInfoTime); + + ANNIEEvent->Set("BeamInfoTime", beamInfoTime); + ANNIEEvent->Set("BeamInfoTimeToTriggerDiff", timeDiff); + + ANNIEEvent->Set("beam_E_TOR860", E_TOR860); + ANNIEEvent->Set("beam_E_TOR875", E_TOR875); + ANNIEEvent->Set("beam_THCURR", THCURR); + ANNIEEvent->Set("beam_BTJT2", BTJT2); + ANNIEEvent->Set("beam_HP875", HP875); + ANNIEEvent->Set("beam_VP875", VP875); + ANNIEEvent->Set("beam_HPTG1", HPTG1); + ANNIEEvent->Set("beam_VPTG1", VPTG1); + ANNIEEvent->Set("beam_HPTG2", HPTG2); + ANNIEEvent->Set("beam_VPTG2", VPTG2); + ANNIEEvent->Set("beam_BTH2T2", BTH2T2); + + int beam_good = 0; + + if (THCURR > 172 && THCURR < 176) + { + if (E_TOR860 > 0.5 && E_TOR860 < 8 && E_TOR875 > 0.5 && E_TOR875 < 8 && (E_TOR875 - E_TOR860) / E_TOR860 < 0.05) + beam_good = 1; + } + + ANNIEEvent->Set("beam_good", beam_good); + + Log("EBSaver: Saved beam info with time " + std::to_string(beamInfoTime) + ", pot E_TOR860 = " + std::to_string(E_TOR860) + ", beam_good = " + std::to_string(beam_good), v_message, verbosityEBSaver); + } + + return true; +} \ No newline at end of file diff --git a/UserTools/EBSaver/EBSaver.h b/UserTools/EBSaver/EBSaver.h new file mode 100644 index 000000000..f2dedb5f6 --- /dev/null +++ b/UserTools/EBSaver/EBSaver.h @@ -0,0 +1,202 @@ +#ifndef EBSaver_H +#define EBSaver_H + +#include +#include + +#include "Tool.h" +#include "BoostStore.h" +#include "PsecData.h" +#include "TimeClass.h" +#include "TriggerClass.h" +#include "Waveform.h" +#include "ANNIEalgorithms.h" +#include "ADCPulse.h" +#include "CalibratedADCWaveform.h" +#include "BeamStatus.h" +#include "TFile.h" +#include "TTree.h" + +/** + * \class EBPMT + * + * $Author: Yue Feng $ + * $Date: 2024/04 $ + * Contact: yuef@iaistate.edu + * + */ + +class EBSaver : public Tool +{ + +public: + EBSaver(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + + bool GotAllDataFromOriginalBuffer(); + void SetDataObjects(); + + bool SaveToANNIEEvent(string saveFileName, int runCode, int triggerTrack, int trackIndex); // save the data to the ANNIEEvent, include all other saving functions. + bool SaveRunInfo(int runCode); // get run numbers from the RunCode in trigger grouper + bool SaveGroupedTriggers(int triggerTrack, int groupIndex); + // use the targetTrigWord to get the trigger track, use the groupIndex to get the group of triggers in that track + // save triggers from std::map>> GroupedTriggersInTotal; //each map is a group of triggers, with the key is the target trigger word + + bool SavePMTData(uint64_t PMTTime); + bool SaveMRDData(uint64_t MRDTime); + bool SaveLAPPDData(uint64_t LAPPDTime); + bool SaveBeamInfo(uint64_t TriggerTime); + + bool SaveOrphan(int runCode); + bool SaveOrphanPMT(int runCode); + bool SaveOrphanMRD(int runCode); + bool SaveOrphanCTC(int runCode); + bool SaveOrphanLAPPD(int runCode); + + void BuildEmptyPMTData(); + void BuildEmptyMRDData(); + void BuildEmptyLAPPDData(); + + void LoadBeamInfo(); + +private: + int saveRunNumber; + int saveSubrunNumber; + int savePartFileNumber; + int savingRunCode; + + bool saveTriggerGroups = true; + bool saveAllTriggers; + bool savePMT = true; + bool saveMRD; + bool saveLAPPD; + bool saveOrphan; + bool saveBeamInfo; + + bool saveRawRWMWaveform; + bool saveRawBRFWaveform; + + string savePath; + string saveName; + + string beamInfoFileName; + + int verbosityEBSaver; + int v_message = 1; + int v_warning = 2; + int v_error = 3; + int v_debug = 4; + + BoostStore *ANNIEEvent; + + int exeNumber; + int savedTriggerGroupNumber; + int savedPMTHitMapNumber; + int savedMRDNumber; + int savedLAPPDNumber; + + std::map TriggerTimeWithoutMRD; // trigger time, 8 or 36 + + int thisRunNum; + int thisSubrunNum; + int thisPartFileNum; + + int savePerExe; + + int TotalBuiltEventsNumber = 0; + int TotalBuiltPMTNumber; + int TotalBuiltMRDNumber; + int TotalBuiltLAPPDNumber; + int TotalBuiltTriggerGroupNumber; + + std::map PMTRunCodeToRemove; + std::map MRDRunCodeToRemove; + std::map LAPPDRunCodeToRemove; + std::map GroupedTriggerIndexToRemove; + + std::map> PMTPairInfoToRemoveTime; + std::map> MRDPairInfoToRemoveTime; + std::map> LAPPDPairInfoToRemoveTime; + + std::map>> GroupedTriggersInTotal; // each map is a group of triggers, with the key is the target trigger word + std::map> RunCodeInTotal; + + int BeamTriggerMain; + int LaserTriggerMain; + int CosmicTriggerMain; + int LEDTriggerMain; + int AmBeTriggerMain; + int PPSMain; + + // PMT related data object + std::map> *> *InProgressHits; // Key: {MTCTime}, value: map of Hit distributions + std::map> *InProgressChkey; // Key: {MTCTime}, value: vector of in progress chankeys + std::map>>> *InProgressRecoADCHits; // Key: {MTCTime}, value: map of found pulses + std::map>>> *InProgressRecoADCHitsAux; // Key: {MTCTime}, value: map of found pulses + std::map> *> *InProgressHitsAux; // Key: {MTCTime}, value: map of Hit distributions + std::map>> *FinishedRawAcqSize; // Key: {MTCTime}, value: map of acquisition time window sizes + + std::map> *RWMRawWaveforms; // Key: MTCTime, Value: RWM waveform + std::map> *BRFRawWaveforms; // Key: MTCTime, Value: BRF waveform + + std::map> PairedPMTTriggerTimestamp; + std::map> PairedPMT_TriggerIndex; + std::map> PairedPMTTimeStamps; + std::map PMTHitmapRunCode; // Key: {MTCTime}, value: RunCode + + // MRD related data object + std::map>> MRDEvents; // Key: {MTCTime}, value: "WaveMap" with key (CardID,ChannelID), value FinishedWaveform + std::map MRDEventTriggerTypes; // Key: {MTCTime}, value: string noting what type of trigger occured for the event + std::map MRDBeamLoopback; // Key: {MTCTime}, value: string noting what type of trigger occured for the event + std::map MRDCosmicLoopback; // KEY: {MTCTime}, value: Cosmic loopback TDC value + + std::map> PairedMRDTriggerTimestamp; + std::map> PairedMRD_TriggerIndex; + std::map> PairedMRDTimeStamps; + std::map MRDHitMapRunCode; // Key: {MTCTime}, value: RunCode + + // LAPPD related data object + vector Buffer_IndexOfData; // index of unpaired data + vector Buffer_LAPPDTimestamp_ns; // used to match + + vector Buffer_LAPPDData; + vector Buffer_LAPPDBeamgate_ns; + vector Buffer_LAPPDOffset; + vector Buffer_LAPPDBeamgate_Raw; + vector Buffer_LAPPDTimestamp_Raw; + vector Buffer_LAPPDBGCorrection; + vector Buffer_LAPPDTSCorrection; + vector Buffer_LAPPDOffset_minus_ps; + vector Buffer_LAPPDBG_PPSBefore; + vector Buffer_LAPPDBG_PPSAfter; + vector Buffer_LAPPDBG_PPSDiff; + vector Buffer_LAPPDBG_PPSMissing; + vector Buffer_LAPPDTS_PPSBefore; + vector Buffer_LAPPDTS_PPSAfter; + vector Buffer_LAPPDTS_PPSDiff; + vector Buffer_LAPPDTS_PPSMissing; + + vector Buffer_LAPPDRunCode; + + std::map> PairedLAPPDTriggerTimestamp; + std::map> PairedLAPPD_TriggerIndex; + std::map> PairedLAPPDTimeStamps; + + // beam info related objects + vector BeamInfoTimestamps; + std::map E_TOR860_map; + std::map E_TOR875_map; + std::map THCURR_map; + std::map BTJT2_map; + std::map HP875_map; + std::map VP875_map; + std::map HPTG1_map; + std::map VPTG1_map; + std::map HPTG2_map; + std::map VPTG2_map; + std::map BTH2T2_map; +}; + +#endif diff --git a/UserTools/EBSaver/README.md b/UserTools/EBSaver/README.md new file mode 100644 index 000000000..a05a2dc7c --- /dev/null +++ b/UserTools/EBSaver/README.md @@ -0,0 +1,29 @@ +# EBSaver + +EBSaver is a part of Event Building version 2 tool chain. +For reference slides, see: +https://annie-docdb.fnal.gov/cgi-bin/sso/ShowDocument?docid=5633 + +For a group of trigger with it's main trigger in part file x, that event will be saved as processed file x. +There shouldn't be any error if the file is correctly processed, the stat info will be printed out at Finalise. +Processing one part file usually just take a few minutes. The time of processing multiple files will be increased quick because of the trigger grouping. There is a limit but more than 7 beam files are not recommended. + + +## Data + +EBSaver take four cataogeies of inputs +1. Beam Info. (From beam fetcher) +2. Grouped triggers. (from EBTriggerGrouper) + GroupedTriggersInTotal +3. Data from subsystems. (PMT, MRD, LAPPD, from data decoders) + In GotAllDataFromOriginalBuffer function +4. Matched pairs of data timestamps and grouped triggers. (from EBPMT, EBMRD, EBLAPPD) + Also in GotAllDataFromOriginalBuffer function + + +## Configuration + +beamInfoFileName: name of the beam info file generated by beam fetcher V2 + +Other configs are set by defalut +Save Orphan is not implemented right now. \ No newline at end of file diff --git a/UserTools/Factory/Factory.cpp b/UserTools/Factory/Factory.cpp index c986c48b7..8e14d874d 100644 --- a/UserTools/Factory/Factory.cpp +++ b/UserTools/Factory/Factory.cpp @@ -174,5 +174,6 @@ if (tool=="BackTracker") ret=new BackTracker; if (tool=="PrintDQ") ret=new PrintDQ; if (tool=="AssignBunchTimingMC") ret=new AssignBunchTimingMC; if (tool=="FitRWMWaveform") ret=new FitRWMWaveform; +if (tool=="EBSaver") ret=new EBSaver; return ret; } diff --git a/UserTools/Unity.h b/UserTools/Unity.h index 7e64d4e9b..d4afec38d 100644 --- a/UserTools/Unity.h +++ b/UserTools/Unity.h @@ -182,3 +182,4 @@ #include "PrintDQ.h" #include "AssignBunchTimingMC.h" #include "FitRWMWaveform.h" +#include "EBSaver.h" From 36678dd9acef9beabcd3c6bd14c2b94e23541451 Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Sun, 19 Jan 2025 23:39:59 -0600 Subject: [PATCH 118/163] Add verbosity check for some cout print out --- UserTools/EBSaver/EBSaver.cpp | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/UserTools/EBSaver/EBSaver.cpp b/UserTools/EBSaver/EBSaver.cpp index f7d459a60..b064c809f 100644 --- a/UserTools/EBSaver/EBSaver.cpp +++ b/UserTools/EBSaver/EBSaver.cpp @@ -1160,8 +1160,11 @@ bool EBSaver::GotAllDataFromOriginalBuffer() int triggerTrack = track.first; std::vector times = track.second; Log("EBSaver: PairedMRDTimeStamps at track " + std::to_string(triggerTrack) + " size " + std::to_string(times.size()), v_message, verbosityEBSaver); - for (int i = 0; i < times.size(); i++) - cout << i << ": " << times[i] << ", "; + if (verbosityEBSaver > v_message) + { + for (int i = 0; i < times.size(); i++) + cout << i << ": " << times[i] << ", "; + } } cout << endl; @@ -1171,8 +1174,11 @@ bool EBSaver::GotAllDataFromOriginalBuffer() int triggerTrack = track.first; std::vector times = track.second; Log("EBSaver: PairedLAPPDTimeStamps at track " + std::to_string(triggerTrack) + " size " + std::to_string(times.size()), v_message, verbosityEBSaver); - for (int i = 0; i < times.size(); i++) - cout << i << ": " << times[i] << ", "; + if (verbosityEBSaver > v_message) + { + for (int i = 0; i < times.size(); i++) + cout << i << ": " << times[i] << ", "; + } } cout << endl; @@ -1183,16 +1189,22 @@ bool EBSaver::GotAllDataFromOriginalBuffer() int triggerTrack = track.first; std::vector indexes = track.second; Log("EBSaver: PairedLAPPD_TriggerIndex at track " + std::to_string(triggerTrack) + " size " + std::to_string(indexes.size()), v_message, verbosityEBSaver); - for (int i = 0; i < indexes.size(); i++) - cout << i << ": " << indexes[i] << ", "; + if (verbosityEBSaver > v_message) + { + for (int i = 0; i < indexes.size(); i++) + cout << i << ": " << indexes[i] << ", "; + } } cout << endl; // print Buffer_LAPPDBeamgate_ns Log("EBSaver: got LAPPD pairing information buffer Buffer_LAPPDBeamgate_ns size " + std::to_string(Buffer_LAPPDBeamgate_ns.size()), v_message, verbosityEBSaver); - for (int i = 0; i < Buffer_LAPPDBeamgate_ns.size(); i++) - cout << i << ": " << Buffer_LAPPDBeamgate_ns[i] << ", "; - cout << endl; + if (verbosityEBSaver > v_message) + { + for (int i = 0; i < Buffer_LAPPDBeamgate_ns.size(); i++) + cout << i << ": " << Buffer_LAPPDBeamgate_ns[i] << ", "; + cout << endl; + } return true; } From c1f27d6112861e426f470467462a2f0625aacd21 Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Sun, 19 Jan 2025 23:55:08 -0600 Subject: [PATCH 119/163] Add EBLoadRaw for EBV2 tool chain --- UserTools/EBLoadRaw/EBLoadRaw.cpp | 712 ++++++++++++++++++++++++++++++ UserTools/EBLoadRaw/EBLoadRaw.h | 116 +++++ UserTools/EBLoadRaw/README.md | 20 + UserTools/Factory/Factory.cpp | 1 + UserTools/Unity.h | 1 + 5 files changed, 850 insertions(+) create mode 100644 UserTools/EBLoadRaw/EBLoadRaw.cpp create mode 100644 UserTools/EBLoadRaw/EBLoadRaw.h create mode 100644 UserTools/EBLoadRaw/README.md diff --git a/UserTools/EBLoadRaw/EBLoadRaw.cpp b/UserTools/EBLoadRaw/EBLoadRaw.cpp new file mode 100644 index 000000000..b253be97d --- /dev/null +++ b/UserTools/EBLoadRaw/EBLoadRaw.cpp @@ -0,0 +1,712 @@ +#include "EBLoadRaw.h" + +EBLoadRaw::EBLoadRaw() : Tool() {} + +bool EBLoadRaw::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + m_variables.Get("verbosityEBLoadRaw", verbosityEBLoadRaw); + + ReadTriggerOverlap = false; + m_variables.Get("ReadTriggerOverlap", ReadTriggerOverlap); + m_variables.Get("InputFile", InputFile); + OrganizedFileList = OrganizeRunParts(InputFile); + + LoadCTC = false; + m_variables.Get("LoadCTC", LoadCTC); + LoadPMT = false; + m_variables.Get("LoadPMT", LoadPMT); + LoadMRD = false; + m_variables.Get("LoadMRD", LoadMRD); + LoadLAPPD = false; + m_variables.Get("LoadLAPPD", LoadLAPPD); + + FileCompleted = false; + JumpBecauseLAPPD = false; + ProcessingComplete = false; + PMTPaused = false; + MRDPaused = false; + LAPPDPaused = false; + CTCPaused = false; + usingTriggerOverlap = false; + LoadingFileNumber = 0; + + RunNumber = 0; + SubRunNumber = 0; + PartFileNumber = 0; + + CTCEntryNum = 0; + PMTEntryNum = 0; + MRDEntryNum = 0; + LAPPDEntryNum = 0; + + PMTTotalEntries = 0; + MRDTotalEntries = 0; + LAPPDTotalEntries = 0; + CTCTotalEntries = 0; + PMTEntriesCompleted = false; + MRDEntriesCompleted = false; + LAPPDEntriesCompleted = false; + CTCEntriesCompleted = false; + LoadedPMTTotalEntries = 0; + LoadedMRDTotalEntries = 0; + LoadedLAPPDTotalEntries = 0; + LoadedCTCTotalEntries = 0; + + PMTMatchingForced = false; + MRDMatchingForced = false; + LAPPDMatchingForced = false; + + RawData = new BoostStore(false, 0); + PMTData = new BoostStore(false, 2); + MRDData = new BoostStore(false, 2); + LAPPDData = new BoostStore(false, 2); + CTCData = new BoostStore(false, 2); + CData = new std::vector; + TData = new TriggerData; + MData = new MRDOut; + LData = new PsecData; + + m_data->CStore.Set("FileProcessingComplete", false); + RunCodeToSave = 0; + + return true; +} + +bool EBLoadRaw::Execute() +{ + m_data->CStore.Set("NewRawDataEntryAccessed", false); + m_data->CStore.Set("NewRawDataFileAccessed", false); + m_data->CStore.Set("SaveProcessedFile", false); + + ProcessingComplete = false; + if (FileCompleted) + { + if (CurrentFile != "NONE") + { + RunCodeToSave = RunCode(CurrentFile); + m_data->CStore.Set("RunCodeToSave", RunCodeToSave); + m_data->CStore.Set("SaveProcessedFile", true); + Log("EBLoadRaw: File completed, saving file " + CurrentFile + " with RunCode: " + std::to_string(RunCodeToSave), v_message, verbosityEBLoadRaw); + } + ProcessingComplete = LoadNewFile(); + } + + if (ProcessingComplete) + { + RunCodeToSave = RunCode(CurrentFile); + m_data->CStore.Set("RunCodeToSave", RunCodeToSave); + m_data->CStore.Set("SaveProcessedFile", true); + m_data->CStore.Set("SaveEverything", true); + Log("EBLoadRaw: File completed, saving file " + CurrentFile + " with RunCode: " + std::to_string(RunCodeToSave), v_message, verbosityEBLoadRaw); + + m_data->CStore.Set("FileProcessingComplete", true); + m_data->vars.Set("StopLoop", 1); + Log("EBLoadRaw: All files have been processed, set pause flags, PMT: " + std::to_string(PMTPaused) + ", MRD: " + std::to_string(MRDPaused) + ", CTC: " + std::to_string(CTCPaused) + ", LAPPD: " + std::to_string(LAPPDPaused), v_message, verbosityEBLoadRaw); + return true; + } + + m_data->CStore.Get("PauseTankDecoding", PMTPaused); + m_data->CStore.Get("PauseMRDDecoding", MRDPaused); + m_data->CStore.Get("PauseCTCDecoding", CTCPaused); + m_data->CStore.Get("PauseLAPPDDecoding", LAPPDPaused); + + if (OrganizedFileList.size() == 0) + { + Log("EBLoadRaw: No files to process.", v_warning, verbosityEBLoadRaw); + m_data->vars.Set("StopLoop", 1); + return true; + } + if (FileCompleted || CurrentFile == "NONE") + { + Log("EBLoadRaw: Loading new file. " + OrganizedFileList.at(LoadingFileNumber), v_message, verbosityEBLoadRaw); + CurrentFile = OrganizedFileList.at(LoadingFileNumber); + RawData->Initialise(CurrentFile.c_str()); + Log("EBLoadRaw: File loaded.", v_message, verbosityEBLoadRaw); + m_data->CStore.Set("NewRawDataFileAccessed", true); + if (verbosityEBLoadRaw > 4) + RawData->Print(false); + LoadRunInfo(); + LoadPMTData(); + LoadMRDData(); + LoadCTCData(); + LoadLAPPDData(); + + PMTMatchingForced = false; + MRDMatchingForced = false; + LAPPDMatchingForced = false; + } + else + { + Log("EBLoadRaw: Loading next entry of current file " + CurrentFile, v_message, verbosityEBLoadRaw); + } + + FileCompleted = false; + if (JumpBecauseLAPPD) + { + FileCompleted = true; + JumpBecauseLAPPD = false; + Log("EBLoadRaw: Jumping to next file due to LAPPD data.", v_message, verbosityEBLoadRaw); + return true; + } + + // if more MRD events than VME PMT events, jump to next file + // this is an old option, why? + if (MRDTotalEntries > PMTTotalEntries) + { + // FileCompleted = true; + Log("EBLoadRaw: Jumping to next file due to MRD entry is more than PMT entry.", v_message, verbosityEBLoadRaw); + // return true; + } + + if (LoadPMT && PMTEntryNum == PMTTotalEntries) + { + Log("EBLoadRaw: ALL PMT entries Loaded.", v_message, verbosityEBLoadRaw); + PMTEntriesCompleted = true; + PMTPaused = true; + } + if (LoadMRD && MRDEntryNum == MRDTotalEntries) + { + Log("EBLoadRaw: ALL MRD entries Loaded.", v_message, verbosityEBLoadRaw); + MRDEntriesCompleted = true; + MRDPaused = true; + } + if (LoadCTC && CTCEntryNum == CTCTotalEntries) + { + Log("EBLoadRaw: ALL CTC entries Loaded.", v_message, verbosityEBLoadRaw); + CTCEntriesCompleted = true; + CTCPaused = true; + } + if (LoadLAPPD && LAPPDEntryNum == LAPPDTotalEntries) + { + Log("EBLoadRaw: ALL LAPPD entries Loaded.", v_message, verbosityEBLoadRaw); + LAPPDEntriesCompleted = true; + LAPPDPaused = true; + } + + if (LoadLAPPD && LAPPDTotalEntries < 0) + LAPPDEntriesCompleted = true; + + m_data->CStore.Set("PauseTankDecoding", PMTPaused); + m_data->CStore.Set("PauseMRDDecoding", MRDPaused); + m_data->CStore.Set("PauseCTCDecoding", CTCPaused); + m_data->CStore.Set("PauseLAPPDDecoding", LAPPDPaused); + + Log("EBLoadRaw: Set pause flags, PMT: " + std::to_string(PMTPaused) + ", MRD: " + std::to_string(MRDPaused) + ", CTC: " + std::to_string(CTCPaused) + ", LAPPD: " + std::to_string(LAPPDPaused), v_message, verbosityEBLoadRaw); + + if (LoadPMT && !PMTPaused && !PMTEntriesCompleted) + LoadNextPMTData(); + if (LoadMRD && !MRDPaused && !MRDEntriesCompleted) + LoadNextMRDData(); + if (LoadCTC && !CTCPaused && !CTCEntriesCompleted) + LoadNextCTCData(); + if (LoadLAPPD && !LAPPDPaused && !LAPPDEntriesCompleted) + LoadNextLAPPDData(); + + if (LoadMRD && MRDEntriesCompleted) + { + bool ForceMRDMatching = false; + m_data->CStore.Set("ForceMRDMatching", ForceMRDMatching); + } + if (LoadLAPPD && LAPPDEntriesCompleted) + { + bool ForceLAPPDMatching = false; + m_data->CStore.Set("ForceLAPPDMatching", ForceLAPPDMatching); + } + + // if all required data is loaded, set filecompleted flag to true + if ((!LoadPMT || PMTEntriesCompleted) && (!LoadMRD || MRDEntriesCompleted) && (!LoadCTC || CTCEntriesCompleted) && (!LoadLAPPD || LAPPDEntriesCompleted)) + { + FileCompleted = true; + Log("EBLoadRaw: All data loaded.", v_message, verbosityEBLoadRaw); + } + + if (verbosityEBLoadRaw > v_message) + { + std::cout << "**************************************************EBLoadRaw: Current progress after execute: " << std::endl; + std::cout << "EBLoadRaw: Current file: " << CurrentFile << std::endl; + if (LoadPMT) + std::cout << "EBLoadRaw: PMT entries: " << PMTEntryNum << " / " << PMTTotalEntries << " = " << static_cast(PMTEntryNum) / static_cast(PMTTotalEntries) * 100 << "%" << std::endl; + if (LoadMRD) + std::cout << "EBLoadRaw: MRD entries: " << MRDEntryNum << " / " << MRDTotalEntries << " = " << static_cast(MRDEntryNum) / static_cast(MRDTotalEntries) * 100 << "%" << std::endl; + if (LoadCTC) + std::cout << "EBLoadRaw: CTC entries: " << CTCEntryNum << " / " << CTCTotalEntries << " = " << static_cast(CTCEntryNum) / static_cast(CTCTotalEntries) * 100 << "%" << std::endl; + if (LoadLAPPD) + std::cout << "EBLoadRaw: LAPPD entries: " << LAPPDEntryNum << " / " << LAPPDTotalEntries << " = " << static_cast(LAPPDEntryNum) / static_cast(LAPPDTotalEntries) * 100 << "%" << std::endl; + std::cout << "**********************************************************************************************" << std::endl; + } + + m_data->CStore.Set("MRDEntriesCompleted", MRDEntriesCompleted); + m_data->CStore.Set("PMTEntriesCompleted", PMTEntriesCompleted); + m_data->CStore.Set("CTCEntriesCompleted", CTCEntriesCompleted); + m_data->CStore.Set("LAPPDEntriesCompleted", LAPPDEntriesCompleted); + Log("EBLoadRaw: Set entries completed flags, PMT: " + std::to_string(PMTEntriesCompleted) + ", MRD: " + std::to_string(MRDEntriesCompleted) + ", CTC: " + std::to_string(CTCEntriesCompleted) + ", LAPPD: " + std::to_string(LAPPDEntriesCompleted), v_message, verbosityEBLoadRaw); + + m_data->CStore.Set("NewRawDataEntryAccessed", true); + m_data->CStore.Set("FileCompleted", FileCompleted); + + Log("EBLoadRaw: Finished execution loop.", v_message, verbosityEBLoadRaw); + return true; +} + +bool EBLoadRaw::Finalise() +{ + RawData->Close(); + RawData->Delete(); + delete RawData; + if (LoadPMT) + { + PMTData->Close(); + PMTData->Delete(); + delete PMTData; + } + if (LoadMRD) + { + MRDData->Close(); + MRDData->Delete(); + delete MRDData; + } + if (LoadLAPPD) + { + LAPPDData->Close(); + LAPPDData->Delete(); + delete LAPPDData; + } + if (LoadCTC) + { + CTCData->Close(); + CTCData->Delete(); + delete CTCData; + } + + std::cout << "\033[1;34mEBLoadRaw: Finalising EBLoadRaw\033[0m" << std::endl; + std::cout << "EBLoadRaw: Loaded " << OrganizedFileList.size() << " files " + << " from " << OrganizedFileList.at(0) << " to " << OrganizedFileList.at(OrganizedFileList.size() - 1) << std::endl; + std::cout << "EBLoadRaw: Loaded " << LoadedPMTTotalEntries << " PMT entries. " << std::endl; + std::cout << "EBLoadRaw: Loaded " << LoadedMRDTotalEntries << " MRD entries. " << std::endl; + std::cout << "EBLoadRaw: Loaded " << LoadedCTCTotalEntries << " CTC entries. " << std::endl; + std::cout << "EBLoadRaw: Loaded " << LoadedLAPPDTotalEntries << " LAPPD entries. " << std::endl; + + return true; +} + +std::vector EBLoadRaw::OrganizeRunParts(std::string FileList) +{ + std::vector OrganizedFiles; + std::vector UnorganizedFileList; + std::vector RunCodes; + int ThisRunCode; + // First, parse the lines and get all files. + std::string line; + ifstream myfile(FileList.c_str()); + if (myfile.is_open()) + { + std::cout << "Lines in FileList being printed" << std::endl; // has our stuff; + while (getline(myfile, line)) + { + // if (line.find("#") != std::string::npos) + // continue; + if (line[0] == '#') + continue; + + std::string filename = line; + int RunCodeNumber = RunCode(filename); + + if (RunCodeNumber != -9999) + { + UnorganizedFileList.push_back(filename); + RunCodes.push_back(RunCodeNumber); + } + + } // End parsing each line in file + + // Now, organize files based on the part number array + std::vector> SortingVector; + for (int i = 0; i < (int)UnorganizedFileList.size(); i++) + { + SortingVector.push_back(std::make_pair(RunCodes.at(i), UnorganizedFileList.at(i))); + } + std::sort(SortingVector.begin(), SortingVector.end()); + for (int j = 0; j < (int)SortingVector.size(); j++) + { + OrganizedFiles.push_back(SortingVector.at(j).second); + } + } + // print the OrganizedFiles + for (int i = 0; i < (int)OrganizedFiles.size(); i++) + { + std::cout << OrganizedFiles.at(i) << std::endl; + } + + return OrganizedFiles; +} + +int EBLoadRaw::RunCode(string fileName) +{ + // extract run number and file number from filename + std::regex runNumber_regex("RAWDataR(\\d{4})"); + std::regex subrunNumber_regex("S(\\d{1,4})p"); + std::regex rawFileNumber_regex("p(\\d{1,4})$"); + std::smatch match; + int runNumber = -9999; + int subrunNumber = -9999; + int rawFileNumber = -9999; + bool allmatched = false; + if (std::regex_search(fileName, match, runNumber_regex) && match.size() > 1) + { + runNumber = std::stoi(match.str(1)); + if (verbosityEBLoadRaw > 0) + std::cout << "runNumber: " << runNumber << std::endl; + m_data->CStore.Set("runNumber", runNumber); + allmatched = true; + } + else + { + std::cout << "runNumber not found" << std::endl; + m_data->CStore.Set("rawFileNumber", -9999); + } + + if (std::regex_search(fileName, match, subrunNumber_regex) && match.size() > 1) + { + subrunNumber = std::stoi(match.str(1)); + if (verbosityEBLoadRaw > 0) + std::cout << "subrunNumber: " << subrunNumber << std::endl; + m_data->CStore.Set("subrunNumber", subrunNumber); + allmatched = true; + } + else + { + std::cout << "subrunNumber not found" << std::endl; + m_data->CStore.Set("subrunNumber", -9999); + } + + if (std::regex_search(fileName, match, rawFileNumber_regex) && match.size() > 1) + { + rawFileNumber = std::stoi(match.str(1)); + if (verbosityEBLoadRaw > 0) + std::cout << "rawFileNumber: " << rawFileNumber << std::endl; + m_data->CStore.Set("rawFileNumber", rawFileNumber); + allmatched = true; + } + else + { + std::cout << "rawFileNumber not found" << std::endl; + m_data->CStore.Set("runNumber", -9999); + } + + if (allmatched == true) + { + int runcode = runNumber * 100000 + ((subrunNumber + 1) * 10000) + rawFileNumber; + cout << "EBLoadRaw: RunCode: " << runcode << endl; + return runcode; + } + else + { + return -9999; + } +} + +bool EBLoadRaw::LoadRunInfo() +{ + int runCode = RunCode(CurrentFile); + Log("EBLoadRaw: Loading run information, RunCode: " + std::to_string(runCode), v_message, verbosityEBLoadRaw); + + RunNumber = runCode / 100000; + SubRunNumber = (runCode % 100000) / 10000 - 1; + PartFileNumber = runCode % 10000; + + Store Postgress; + + std::cout << "EBLoadRaw: loading run information, RunNumber: " << RunNumber << ", SubRunNumber: " << SubRunNumber << ", PartFileNumber: " << PartFileNumber << std::endl; + + Postgress.Set("RunNumber", RunNumber); + Postgress.Set("SubRunNumber", SubRunNumber); + Postgress.Set("PartFileNumber", PartFileNumber); + Postgress.Set("RunType", -1); + Postgress.Set("StartTime", -1); + + m_data->CStore.Set("RunInfoPostgress", Postgress); + + m_data->CStore.Set("RunNumber", RunNumber); + m_data->CStore.Set("SubRunNumber", SubRunNumber); + m_data->CStore.Set("PartFileNumber", PartFileNumber); + m_data->CStore.Set("RunCode", runCode); + + return true; +} + +// load new file and it's related boost store +bool EBLoadRaw::LoadNewFile() +{ + bool EndOfProcessing = false; + LoadingFileNumber++; + + RawData->Close(); + RawData->Delete(); + delete RawData; + RawData = new BoostStore(false, 0); + PMTData->Close(); + PMTData->Delete(); + delete PMTData; + PMTData = new BoostStore(false, 2); + MRDData->Close(); + MRDData->Delete(); + delete MRDData; + MRDData = new BoostStore(false, 2); + LAPPDData->Close(); + LAPPDData->Delete(); + delete LAPPDData; + LAPPDData = new BoostStore(false, 2); + CTCData->Close(); + CTCData->Delete(); + delete CTCData; + CTCData = new BoostStore(false, 2); + + PMTEntryNum = 0; + MRDEntryNum = 0; + LAPPDEntryNum = 0; + CTCEntryNum = 0; + + PMTEntriesCompleted = false; + MRDEntriesCompleted = false; + LAPPDEntriesCompleted = false; + CTCEntriesCompleted = false; + + m_data->CStore.Set("PauseTankDecoding", false); + m_data->CStore.Set("PauseMRDDecoding", false); + m_data->CStore.Set("PauseCTCDecoding", false); + m_data->CStore.Set("PauseLAPPDDecoding", false); + + if (LoadingFileNumber == OrganizedFileList.size()) + { + EndOfProcessing = true; + m_data->CStore.Set("PauseTankDecoding", true); + m_data->CStore.Set("PauseMRDDecoding", true); + m_data->CStore.Set("PauseCTCDecoding", true); + m_data->CStore.Set("PauseLAPPDDecoding", true); + } + + return EndOfProcessing; +} + +bool EBLoadRaw::LoadPMTData() +{ + Log("EBLoadRaw: Loading PMTData.", v_message, verbosityEBLoadRaw); + RawData->Get("PMTData", *PMTData); + PMTData->Header->Get("TotalEntries", PMTTotalEntries); + LoadedPMTTotalEntries += PMTTotalEntries; + Log("EBLoadRaw: PMTData loaded, TotalEntries: " + std::to_string(PMTTotalEntries), v_message, verbosityEBLoadRaw); + + if (verbosityEBLoadRaw > 3) + PMTData->Print(false); + if (verbosityEBLoadRaw > 3) + PMTData->Header->Print(false); + return true; +} + +bool EBLoadRaw::LoadMRDData() +{ + Log("EBLoadRaw: Loading MRDData.", v_message, verbosityEBLoadRaw); + RawData->Get("CCData", *MRDData); + MRDData->Header->Get("TotalEntries", MRDTotalEntries); + LoadedMRDTotalEntries += MRDTotalEntries; + Log("EBLoadRaw: MRDData loaded, TotalEntries: " + std::to_string(MRDTotalEntries), v_message, verbosityEBLoadRaw); + if (verbosityEBLoadRaw > 3) + MRDData->Print(false); + return true; +} + +bool EBLoadRaw::LoadCTCData() +{ + Log("EBLoadRaw: Loading CTCData.", v_message, verbosityEBLoadRaw); + RawData->Get("TrigData", *CTCData); + if (verbosityEBLoadRaw > 3) + CTCData->Print(false); + CTCData->Header->Get("TotalEntries", CTCTotalEntries); + LoadedCTCTotalEntries += CTCTotalEntries; + if (verbosityEBLoadRaw > 3) + CTCData->Header->Print(false); + if (ReadTriggerOverlap) + { + std::stringstream ss_trigoverlap; + ss_trigoverlap << "TrigOverlap_R" << RunNumber << "S" << SubRunNumber << "p" << PartFileNumber; + std::cout << "EBLoadRaw: Loading Trigger Overlap data: " << ss_trigoverlap.str() << std::endl; + BoostStore TrigOverlapStore; + bool store_exist = TrigOverlapStore.Initialise(ss_trigoverlap.str().c_str()); + std::cout << "EBLoadRaw: Trigger Overlap store exist: " << store_exist << std::endl; + if (store_exist) + { + CTCTotalEntries++; + std::cout << "EBLoadRaw: total trigger entry with overlap is: " << CTCTotalEntries << std::endl; + } + } + return true; +} + +bool EBLoadRaw::LoadLAPPDData() +{ + Log("EBLoadRaw: Loading LAPPDData.", v_message, verbosityEBLoadRaw); + try + { + RawData->Get("LAPPDData", *LAPPDData); + LAPPDData->Header->Get("TotalEntries", LAPPDTotalEntries); + Log("EBLoadRaw: LAPPDData loaded, TotalEntries: " + std::to_string(LAPPDTotalEntries), v_message, verbosityEBLoadRaw); + if (verbosityEBLoadRaw > 3) + { + LAPPDData->Print(false); + LAPPDData->Header->Print(false); + } + if (LAPPDTotalEntries < 0) + { + + cout << "EBLoadRaw: LAPPDData entry < 0, found " << LAPPDTotalEntries << ", set to 0" << endl; + LAPPDTotalEntries = 0; + LAPPDEntriesCompleted = true; + } + else if (LAPPDTotalEntries > 100000) + { + cout << "EBLoadRaw: LAPPDData entry very large, found " << LAPPDTotalEntries << ", return and set jump because LAPPD = true" << endl; + JumpBecauseLAPPD = true; + return true; + } + LoadedLAPPDTotalEntries += LAPPDTotalEntries; + } + catch (std::exception &e) + { + std::cout << "EBLoadRaw: LAPPDData not found in file." << std::endl; + LAPPDTotalEntries = 0; + LAPPDEntriesCompleted = true; + } + Log("EBLoadRaw: LAPPDData has " + std::to_string(LAPPDTotalEntries) + " entries.", v_message, verbosityEBLoadRaw); + return true; +} + +// load next entry of the current file +bool EBLoadRaw::LoadNextPMTData() +{ + Log("EBLoadRaw: Loading next PMTData entry " + std::to_string(PMTEntryNum) + " of " + std::to_string(PMTTotalEntries), v_warning, verbosityEBLoadRaw); + PMTData->GetEntry(PMTEntryNum); + Log("EBLoadRaw: Getting the PMT card data entry", v_warning, verbosityEBLoadRaw); + PMTData->Get("CardData", *CData); + Log("EBLoadRaw: Setting into CStore", v_warning, verbosityEBLoadRaw); + m_data->CStore.Set("CardData", CData); + Log("EBLoadRaw: Setting PMT entry num to CStore", v_warning, verbosityEBLoadRaw); + m_data->CStore.Set("TankEntryNum", PMTEntryNum); + PMTEntryNum++; + + if (PMTEntryNum == PMTTotalEntries && !PMTMatchingForced) + { + // force the PMT matching when all PMT entries are completed or PMTEntryNum is greater than PMTTotalEntries + Log("EBLoadRaw: PMTEntriesCompleted, force PMT matching", v_message, verbosityEBLoadRaw); + bool ForcePMTMatching = true; + m_data->CStore.Set("ForcePMTMatching", ForcePMTMatching); + PMTMatchingForced = true; + } + else + { + bool ForcePMTMatching = false; + m_data->CStore.Set("ForcePMTMatching", ForcePMTMatching); + } + + return true; +} + +bool EBLoadRaw::LoadNextMRDData() +{ + Log("EBLoadRaw: Loading next MRDData entry " + std::to_string(MRDEntryNum) + " of " + std::to_string(MRDTotalEntries), v_warning, verbosityEBLoadRaw); + MRDData->GetEntry(MRDEntryNum); + MRDData->Get("Data", *MData); + m_data->CStore.Set("MRDData", MData, true); + m_data->CStore.Set("MRDEntryNum", MRDEntryNum); + MRDEntryNum++; + + Log("EBLoadRaw: Loaded MRDData entry " + std::to_string(MRDEntryNum) + ", MRDTotalEntries " + std::to_string(MRDTotalEntries) + ", MRDMatchingForced " + std::to_string(MRDMatchingForced), v_warning, verbosityEBLoadRaw); + if (MRDEntryNum == MRDTotalEntries && !MRDMatchingForced) + { + Log("EBLoadRaw: MRDEntriesCompleted, force MRD matching", v_message, verbosityEBLoadRaw); + bool ForceMRDMatching = true; + m_data->CStore.Set("ForceMRDMatching", ForceMRDMatching); + MRDMatchingForced = true; + } + else + { + bool ForceMRDMatching = false; + m_data->CStore.Set("ForceMRDMatching", ForceMRDMatching); + } + + return true; +} + +bool EBLoadRaw::LoadNextLAPPDData() +{ + Log("EBLoadRaw: Loading next LAPPDData entry " + std::to_string(LAPPDEntryNum) + " of " + std::to_string(LAPPDTotalEntries), v_warning, verbosityEBLoadRaw); + LAPPDData->GetEntry(LAPPDEntryNum); + LAPPDData->Get("LAPPDData", *LData); + m_data->CStore.Set("LAPPDData", LData); + m_data->CStore.Set("LAPPDEntryNum", LAPPDEntryNum); + m_data->CStore.Set("LAPPDanaData", true); + LAPPDEntryNum++; + + Log("EBLoadRaw: Loaded LAPPDData entry " + std::to_string(LAPPDEntryNum) + ", LAPPDTotalEntries " + std::to_string(LAPPDTotalEntries) + ", LAPPDMatchingForced " + std::to_string(LAPPDMatchingForced), v_warning, verbosityEBLoadRaw); + if (LAPPDEntryNum == LAPPDTotalEntries && !LAPPDMatchingForced) + { + Log("EBLoadRaw: LAPPDEntriesCompleted, force LAPPD matching", v_message, verbosityEBLoadRaw); + bool ForceLAPPDMatching = true; + m_data->CStore.Set("ForceLAPPDMatching", ForceLAPPDMatching); + LAPPDMatchingForced = true; + } + else + { + bool ForceLAPPDMatching = false; + m_data->CStore.Set("ForceLAPPDMatching", ForceLAPPDMatching); + } + + return true; +} + +bool EBLoadRaw::LoadNextCTCData() +{ + Log("EBLoadRaw: Loading next CTCData entry " + std::to_string(CTCEntryNum) + " of " + std::to_string(CTCTotalEntries), v_warning, verbosityEBLoadRaw); + if (!ReadTriggerOverlap) + { + CTCData->GetEntry(CTCEntryNum); + CTCData->Get("TrigData", *TData); + Log("EBLoadRaw: Loaded CTCData entry " + std::to_string(CTCEntryNum), v_warning, verbosityEBLoadRaw); + } + else + { + if (CTCEntryNum != CTCTotalEntries - 1) + { + CTCData->GetEntry(CTCEntryNum); + CTCData->Get("TrigData", *TData); + m_data->CStore.Set("usingTriggerOverlap", false); + Log("EBLoadRaw: Loaded CTCData entry " + std::to_string(CTCEntryNum), v_warning, verbosityEBLoadRaw); + } + else + { + BoostStore TrigOverlapStore; + std::stringstream ss_trigoverlap; + ss_trigoverlap << "TrigOverlap_R" << RunNumber << "S" << SubRunNumber << "p" << PartFileNumber; + bool got_trig_o = TrigOverlapStore.Initialise(ss_trigoverlap.str().c_str()); + if (got_trig_o) + { + TrigOverlapStore.Get("TrigData", *TData); + m_data->CStore.Set("usingTriggerOverlap", true); + } + else + std::cout << "EBLoadRaw: Trigger Overlap data not found while loading" << std::endl; + } + m_data->CStore.Set("TrigData", TData); + + Log("EBLoadRaw: Loaded CTCData entry " + std::to_string(CTCEntryNum), v_warning, verbosityEBLoadRaw); + CTCEntryNum++; + } + return true; +} diff --git a/UserTools/EBLoadRaw/EBLoadRaw.h b/UserTools/EBLoadRaw/EBLoadRaw.h new file mode 100644 index 000000000..34c8257a8 --- /dev/null +++ b/UserTools/EBLoadRaw/EBLoadRaw.h @@ -0,0 +1,116 @@ +#ifndef EBLoadRaw_H +#define EBLoadRaw_H + +#include +#include + +#include "Tool.h" +#include "CardData.h" +#include "TriggerData.h" +#include "PsecData.h" +#include "BoostStore.h" +#include "Store.h" + +/** + * \class EBPMT + * + * $Author: Yue Feng $ + * $Date: 2024/04 $ + * Contact: yuef@iaistate.edu + * + */ + +class EBLoadRaw : public Tool +{ + +public: + EBLoadRaw(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + + bool LoadPMTData(); + bool LoadMRDData(); + bool LoadLAPPDData(); + bool LoadCTCData(); + bool LoadRunInfo(); + + bool LoadNextPMTData(); + bool LoadNextMRDData(); + bool LoadNextLAPPDData(); + bool LoadNextCTCData(); + + bool LoadNewFile(); + int RunCode(string fileName); + std::vector OrganizeRunParts(std::string FileList); + +private: + std::string CurrentFile = "NONE"; + std::string InputFile; + std::vector OrganizedFileList; + bool ReadTriggerOverlap; + int RunCodeToSave; + + bool LoadCTC; + bool LoadPMT; + bool LoadMRD; + bool LoadLAPPD; + + int PMTTotalEntries; + int MRDTotalEntries; + int LAPPDTotalEntries; + int CTCTotalEntries; + + int LoadedPMTTotalEntries; + int LoadedMRDTotalEntries; + int LoadedLAPPDTotalEntries; + int LoadedCTCTotalEntries; + + bool ProcessingComplete; + bool FileCompleted; + bool JumpBecauseLAPPD; + bool PMTEntriesCompleted; + bool MRDEntriesCompleted; + bool LAPPDEntriesCompleted; + bool CTCEntriesCompleted; + bool usingTriggerOverlap; + + int CTCEntryNum; + int PMTEntryNum; + int MRDEntryNum; + int LAPPDEntryNum; + int LoadingFileNumber; + + int RunNumber; + int SubRunNumber; + int PartFileNumber; + + bool PMTPaused; + bool MRDPaused; + bool LAPPDPaused; + bool CTCPaused; + + bool PMTMatchingForced; + bool MRDMatchingForced; + bool LAPPDMatchingForced; + + BoostStore *RawData = nullptr; + BoostStore *PMTData = nullptr; + BoostStore *MRDData = nullptr; + BoostStore *LAPPDData = nullptr; + BoostStore *CTCData = nullptr; + + std::vector *CData = nullptr; + TriggerData *TData = nullptr; + MRDOut *MData = nullptr; + PsecData *LData = nullptr; + + int verbosityEBLoadRaw; + + int v_message = 1; + int v_warning = 2; + int v_error = 3; + int v_debug = 4; +}; + +#endif diff --git a/UserTools/EBLoadRaw/README.md b/UserTools/EBLoadRaw/README.md new file mode 100644 index 000000000..957f68e36 --- /dev/null +++ b/UserTools/EBLoadRaw/README.md @@ -0,0 +1,20 @@ +# EBLoadRaw + +EBLoadRaw tool is a part of Event Building version 2 tool chain. +For reference slides, see: +https://annie-docdb.fnal.gov/cgi-bin/sso/ShowDocument?docid=5633 +It basically follows the logic of LoadRawData, but reorganized to a different format and abort the BuileType option. If you need to load PMT and CTC data flow, just choose LoadCTC = true and LoadPMT = true, and use false for others. + +## Data + +need a list of raw part file as input, set the loaded entry to CStore. +Check Load*Data functions for each data flow. + +## Configuration + +**InputFile** is the name of txt file which has the raw part file list in it. +**ReadTriggerOverlap** will control load the overlap file or not. It's necessary for beam runs, not really necessary for source runs because lost a few events is not unacceptable for source run. + +**LoadCTC, LoadPMT, LoadMRD, LoadLAPPD** These tells the tool to load the data flow or not. Usually true for all of them. + + diff --git a/UserTools/Factory/Factory.cpp b/UserTools/Factory/Factory.cpp index c986c48b7..7f284b8d9 100644 --- a/UserTools/Factory/Factory.cpp +++ b/UserTools/Factory/Factory.cpp @@ -174,5 +174,6 @@ if (tool=="BackTracker") ret=new BackTracker; if (tool=="PrintDQ") ret=new PrintDQ; if (tool=="AssignBunchTimingMC") ret=new AssignBunchTimingMC; if (tool=="FitRWMWaveform") ret=new FitRWMWaveform; +if (tool=="EBLoadRaw") ret=new EBLoadRaw; return ret; } diff --git a/UserTools/Unity.h b/UserTools/Unity.h index 7e64d4e9b..6a5c9695d 100644 --- a/UserTools/Unity.h +++ b/UserTools/Unity.h @@ -182,3 +182,4 @@ #include "PrintDQ.h" #include "AssignBunchTimingMC.h" #include "FitRWMWaveform.h" +#include "EBLoadRaw.h" From af0d332d28e951858eafc7279df608a1ac9e4f48 Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Mon, 20 Jan 2025 00:43:00 -0600 Subject: [PATCH 120/163] Add ANNIEEventTreeMaker as the part 2 of EBV2, replace PhaseIITreeMaker This is before updates from comments on #307 PR --- .../ANNIEEventTreeMaker.cpp | 2577 +++++++++++++++++ .../ANNIEEventTreeMaker/ANNIEEventTreeMaker.h | 572 ++++ UserTools/ANNIEEventTreeMaker/README.md | 20 + UserTools/Factory/Factory.cpp | 1 + UserTools/Unity.h | 1 + 5 files changed, 3171 insertions(+) create mode 100644 UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp create mode 100644 UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h create mode 100644 UserTools/ANNIEEventTreeMaker/README.md diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp new file mode 100644 index 000000000..7c469d014 --- /dev/null +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -0,0 +1,2577 @@ +#include "ANNIEEventTreeMaker.h" + +ANNIEEventTreeMaker::ANNIEEventTreeMaker() : Tool() {} + +bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + m_variables.Get("ANNIEEventTreeMakerVerbosity", ANNIEEventTreeMakerVerbosity); + m_variables.Get("isData", isData); + m_variables.Get("HasGenie", hasGenie); + + fillAllTriggers = true; + m_variables.Get("fillAllTriggers", fillAllTriggers); + fill_singleTrigger = true; + m_variables.Get("fill_singleTrigger", fill_singleTrigger); + fill_singleTriggerWord = 14; + m_variables.Get("fill_singleTriggerWord", fill_singleTriggerWord); + fill_TriggerWord = {14, 47}; + + m_variables.Get("fillCleanEventsOnly", fillCleanEventsOnly); + m_variables.Get("fillLAPPDEventsOnly", fillLAPPDEventsOnly); + + m_variables.Get("TankHitInfo_fill", TankHitInfo_fill); + m_variables.Get("TankCluster_fill", TankCluster_fill); + m_variables.Get("cluster_TankHitInfo_fill", cluster_TankHitInfo_fill); + m_variables.Get("MRDHitInfo_fill", MRDHitInfo_fill); + m_variables.Get("RWMBRF_fill", RWMBRF_fill); + + m_variables.Get("MCTruth_fill", MCTruth_fill); + m_variables.Get("MRDReco_fill", MRDReco_fill); + m_variables.Get("TankReco_fill", TankReco_fill); + m_variables.Get("RecoDebug_fill", RecoDebug_fill); + m_variables.Get("muonTruthRecoDiff_fill", muonTruthRecoDiff_fill); + m_variables.Get("LAPPDData_fill", LAPPDData_fill); + m_variables.Get("SiPMPulseInfo_fill", SiPMPulseInfo_fill); + m_variables.Get("LAPPDReco_fill", LAPPDReco_fill); + m_variables.Get("LAPPD_PPS_fill", LAPPD_PPS_fill); + m_variables.Get("LAPPD_Waveform_fill", LAPPD_Waveform_fill); + m_variables.Get("LAPPD_MC_fill", LAPPD_MC_fill); + + std::string output_filename = "ANNIEEventTree.root"; + m_variables.Get("OutputFile", output_filename); + fOutput_tfile = new TFile(output_filename.c_str(), "recreate"); + fANNIETree = new TTree("Event", "ANNIE Phase II Event Tree"); + + m_data->CStore.Get("AuxChannelNumToTypeMap", AuxChannelNumToTypeMap); + m_data->CStore.Get("ChannelNumToTankPMTSPEChargeMap", ChannelKeyToSPEMap); + m_data->CStore.Get("pmt_tubeid_to_channelkey_data", pmtid_to_channelkey); + m_data->CStore.Get("channelkey_to_pmtid", channelkey_to_pmtid); + m_data->CStore.Get("channelkey_to_mrdpmtid", channelkey_to_mrdpmtid); + m_data->CStore.Get("mrdpmtid_to_channelkey_data", mrdpmtid_to_channelkey_data); + m_data->CStore.Get("channelkey_to_faccpmtid", channelkey_to_faccpmtid); + + auto get_geometry = m_data->Stores.at("ANNIEEvent")->Header->Get("AnnieGeometry", geom); + if (!get_geometry) + { + Log("ANNIEEventTreeMaker Tool: Error retrieving Geometry from ANNIEEvent!", v_error, ANNIEEventTreeMakerVerbosity); + return false; + } + + // general information in an event + fANNIETree->Branch("runNumber", &fRunNumber, "runNumber/I"); + fANNIETree->Branch("subrunNumber", &fSubrunNumber, "subrunNumber/I"); + fANNIETree->Branch("partFileNumber", &fPartFileNumber, "partFileNumber/I"); + fANNIETree->Branch("runType", &fRunType, "runType/I"); + fANNIETree->Branch("eventNumber", &fEventNumber, "eventNumber/I"); // + fANNIETree->Branch("PrimaryTriggerWord", &fPrimaryTriggerWord, "PrimaryTriggerWord/I"); + fANNIETree->Branch("GroupedTriggerTime", &fGroupedTriggerTime); + fANNIETree->Branch("GroupedTriggerWord", &fGroupedTriggerWord); + fANNIETree->Branch("trigword", &fTriggerword, "trigword/I"); // keep for trigger 5 or 14 + + // flags from event selector + fANNIETree->Branch("Extended", &fExtended, "Extended/I"); + fANNIETree->Branch("HasTank", &fHasTank, "HasTank/I"); + fANNIETree->Branch("HasMRD", &fHasMRD, "HasMRD/I"); + fANNIETree->Branch("HasLAPPD", &fHasLAPPD, "HasLAPPD/I"); + fANNIETree->Branch("TankMRDCoinc", &fTankMRDCoinc, "TankMRDCoinc/I"); + fANNIETree->Branch("NoVeto", &fNoVeto, "NoVeto/I"); + fANNIETree->Branch("MRDTriggerType", &fMRDTriggerTypeInt, "MRDTriggerType/I"); + //fANNIETree->Branch("MRDTriggerTypeString", &fMRDTriggerType); + + // event information of data + fANNIETree->Branch("eventTimeTank", &fEventTimeTank, "eventTimeTank/l"); + fANNIETree->Branch("eventTimeMRD", &fEventTimeMRD, "eventTimeMRD/l"); + + // beam information + if (BeamInfo_fill) + { + fANNIETree->Branch("beam_pot_875", &fPot, "beam_pot_875/D"); + fANNIETree->Branch("beam_ok", &fBeamok, "beam_ok/I"); + fANNIETree->Branch("beam_E_TOR860", &beam_E_TOR860, "beam_E_TOR860/D"); + fANNIETree->Branch("beam_E_TOR875", &beam_E_TOR875, "beam_E_TOR875/D"); + fANNIETree->Branch("beam_THCURR", &beam_THCURR, "beam_THCURR/D"); + fANNIETree->Branch("beam_BTJT2", &beam_BTJT2, "beam_BTJT2/D"); + fANNIETree->Branch("beam_HP875", &beam_HP875, "beam_HP875/D"); + fANNIETree->Branch("beam_VP875", &beam_VP875, "beam_VP875/D"); + fANNIETree->Branch("beam_HPTG1", &beam_HPTG1, "beam_HPTG1/D"); + fANNIETree->Branch("beam_VPTG1", &beam_VPTG1, "beam_VPTG1/D"); + fANNIETree->Branch("beam_HPTG2", &beam_HPTG2, "beam_HPTG2/D"); + fANNIETree->Branch("beam_VPTG2", &beam_VPTG2, "beam_VPTG2/D"); + fANNIETree->Branch("beam_BTH2T2", &beam_BTH2T2, "beam_BTH2T2/D"); + fANNIETree->Branch("BeamInfoTime", &fBeamInfoTime, "BeamInfoTime/l"); + fANNIETree->Branch("BeamInfoTimeToTriggerDiff", &fBeamInfoTimeToTriggerDiff, "BeamInfoTimeToTriggerDiff/L"); + } + + if (RWMBRF_fill) + { + fANNIETree->Branch("RWMRisingStart", &fRWMRisingStart, "fRWMRisingStart/D"); + fANNIETree->Branch("RWMRisingEnd", &fRWMRisingEnd, "fRWMRisingEnd/D"); + fANNIETree->Branch("RWMHalfRising", &fRWMHalfRising, "fRWMHalfRising/D"); + fANNIETree->Branch("RWMFHWM", &fRWMFHWM, "fRWMFHWM/D"); + fANNIETree->Branch("RWMFirstPeak", &fRWMFirstPeak, "fRWMFirstPeak/D"); + + fANNIETree->Branch("BRFFirstPeak", &fBRFFirstPeak, "fBRFFirstPeak/D"); + fANNIETree->Branch("BRFAveragePeak", &fBRFAveragePeak, "fBRFAveragePeak/D"); + fANNIETree->Branch("BRFFirstPeakFit", &fBRFFirstPeakFit, "fBRFFirstPeakFit/D"); + } + + //********************************************************// + + // Tank cluster information + + fANNIETree->Branch("numberOfClusters", &fNumberOfClusters, "fNumberOfClusters/I"); + fANNIETree->Branch("clusterTime", &fClusterTimeV); + fANNIETree->Branch("clusterCharge", &fClusterChargeV); + fANNIETree->Branch("clusterPE", &fClusterPEV); + fANNIETree->Branch("clusterMaxPE", &fClusterMaxPEV); + fANNIETree->Branch("clusterChargePointX", &fClusterChargePointXV); + fANNIETree->Branch("clusterChargePointY", &fClusterChargePointYV); + fANNIETree->Branch("clusterChargePointZ", &fClusterChargePointZV); + fANNIETree->Branch("clusterChargeBalance", &fClusterChargeBalanceV); + fANNIETree->Branch("clusterHits", &fClusterHits); + fANNIETree->Branch("Cluster_HitX", &fCluster_HitX); + fANNIETree->Branch("Cluster_HitY", &fCluster_HitY); + fANNIETree->Branch("Cluster_HitZ", &fCluster_HitZ); + fANNIETree->Branch("Cluster_HitT", &fCluster_HitT); + fANNIETree->Branch("Cluster_HitQ", &fCluster_HitQ); + fANNIETree->Branch("Cluster_HitPE", &fCluster_HitPE); + fANNIETree->Branch("Cluster_HitType", &fCluster_HitType); + fANNIETree->Branch("Cluster_HitDetID", &fCluster_HitDetID); + fANNIETree->Branch("Cluster_HitChankey", &fCluster_HitChankey); + fANNIETree->Branch("Cluster_HitChankeyMC", &fCluster_HitChankeyMC); + + // MRD cluster information + fANNIETree->Branch("eventTimeMRD", &fEventTimeMRD_Tree); + fANNIETree->Branch("MRDClusterNumber", &fMRDClusterNumber); + fANNIETree->Branch("MRDClusterTime", &fMRDClusterTime); + fANNIETree->Branch("MRDClusterTimeSigma", &fMRDClusterTimeSigma); + fANNIETree->Branch("MRDClusterHitNumber", &fMRDClusterHitNumber); + + if (TankHitInfo_fill) + { + // Tank Hit information + fANNIETree->Branch("nhits", &fNHits, "nhits/I"); + fANNIETree->Branch("filter", &fIsFiltered); + fANNIETree->Branch("hitX", &fHitX); + fANNIETree->Branch("hitY", &fHitY); + fANNIETree->Branch("hitZ", &fHitZ); + fANNIETree->Branch("hitT", &fHitT); + fANNIETree->Branch("hitQ", &fHitQ); + fANNIETree->Branch("hitPE", &fHitPE); + fANNIETree->Branch("hitType", &fHitType); + fANNIETree->Branch("hitDetID", &fHitDetID); + fANNIETree->Branch("hitChankey", &fHitChankey); + fANNIETree->Branch("hitChankeyMC", &fHitChankeyMC); + } + + if (SiPMPulseInfo_fill) + { + fANNIETree->Branch("SiPMhitQ", &fSiPMHitQ); + fANNIETree->Branch("SiPMhitT", &fSiPMHitT); + fANNIETree->Branch("SiPMhitAmplitude", &fSiPMHitAmplitude); + fANNIETree->Branch("SiPMNum", &fSiPMNum); + fANNIETree->Branch("SiPM1NPulses", &fSiPM1NPulses, "SiPM1NPulses/I"); + fANNIETree->Branch("SiPM2NPulses", &fSiPM2NPulses, "SiPM2NPulses/I"); + } + + if (LAPPDData_fill) + { + fANNIETree->Branch("LAPPD_ID", &fLAPPD_ID); + fANNIETree->Branch("fLAPPD_Count", &fLAPPD_Count); + fANNIETree->Branch("LAPPD_Beamgate_ns", &fLAPPD_Beamgate_ns); + fANNIETree->Branch("LAPPD_Timestamp_ns", &fLAPPD_Timestamp_ns); + fANNIETree->Branch("LAPPD_Beamgate_Raw", &fLAPPD_Beamgate_Raw); + fANNIETree->Branch("LAPPD_Timestamp_Raw", &fLAPPD_Timestamp_Raw); + fANNIETree->Branch("LAPPD_Offset", &fLAPPD_Offset); + fANNIETree->Branch("LAPPD_TSCorrection", &fLAPPD_TSCorrection); + fANNIETree->Branch("LAPPD_BGCorrection", &fLAPPD_BGCorrection); + fANNIETree->Branch("LAPPD_OSInMinusPS", &fLAPPD_OSInMinusPS); + if (LAPPD_PPS_fill) + { + fANNIETree->Branch("LAPPD_BGPPSBefore", &fLAPPD_BGPPSBefore); + fANNIETree->Branch("LAPPD_BGPPSAfter", &fLAPPD_BGPPSAfter); + fANNIETree->Branch("LAPPD_BGPPSDiff", &fLAPPD_BGPPSDiff); + fANNIETree->Branch("LAPPD_BGPPSMissing", &fLAPPD_BGPPSMissing); + fANNIETree->Branch("LAPPD_TSPPSBefore", &fLAPPD_TSPPSBefore); + fANNIETree->Branch("LAPPD_TSPPSAfter", &fLAPPD_TSPPSAfter); + fANNIETree->Branch("LAPPD_TSPPSDiff", &fLAPPD_TSPPSDiff); + fANNIETree->Branch("LAPPD_TSPPSMissing", &fLAPPD_TSPPSMissing); + } + fANNIETree->Branch("LAPPD_BG_switchBit0", &fLAPPD_BG_switchBit0); + fANNIETree->Branch("LAPPD_BG_switchBit1", &fLAPPD_BG_switchBit1); + } + + // LAPPD reconstruction information + if (LAPPDReco_fill) + { + // fANNIETree->Branch("LAPPDPulseTimeStampUL", &fLAPPDPulseTimeStampUL, "LAPPDPulseTimeStampUL/l"); + // fANNIETree->Branch("LAPPDPulseBeamgateUL", &fLAPPDPulseBeamgateUL, "LAPPDPulseBeamgateUL/l"); + // actually we don't need these two for pulse and hit, because it is impossible to have multiple events from one LAPPD in one ANNIEEvent due to the dead time and the trigger scheme + // LAPPD ID is enough to find the corresponding unix timestamp + // but leave them there in case + + fANNIETree->Branch("LAPPD_PulseIDs", &fLAPPD_IDs); + fANNIETree->Branch("LAPPD_ChannelID", &fChannelID); + fANNIETree->Branch("LAPPD_PeakTime", &fPulsePeakTime); + fANNIETree->Branch("LAPPD_PulseHalfHeightTime", &fPulseHalfHeightTime); + fANNIETree->Branch("LAPPD_PeakAmp", &fPulsePeakAmp); + fANNIETree->Branch("LAPPD_Charge", &fPulseCharge); + fANNIETree->Branch("LAPPD_PulseStart", &fPulseStart); + fANNIETree->Branch("LAPPD_PulseEnd", &fPulseEnd); + fANNIETree->Branch("LAPPD_PulseWidth", &fPulseWidth); + fANNIETree->Branch("LAPPD_PulseSide", &fPulseSide); + fANNIETree->Branch("LAPPD_PulseStripNum", &fPulseStripNum); + + // fANNIETree->Branch("LAPPDHitTimeStampUL", &fLAPPDHitTimeStampUL, "LAPPDHitTimeStampUL/l"); + // fANNIETree->Branch("LAPPDHitBeamgateUL", &fLAPPDHitBeamgateUL, "LAPPDHitBeamgateUL/l"); + + fANNIETree->Branch("LAPPDID_Hit", &fLAPPDHit_IDs); + fANNIETree->Branch("LAPPDHitChannel", &fLAPPDHitChannel); + fANNIETree->Branch("LAPPDHitStrip", &fLAPPDHitStrip); + fANNIETree->Branch("LAPPDHitTime", &fLAPPDHitTime); + fANNIETree->Branch("LAPPDHitAmp", &fLAPPDHitAmp); + fANNIETree->Branch("LAPPDHitParallelPos", &fLAPPDHitParallelPos); + fANNIETree->Branch("LAPPDHitTransversePos", &fLAPPDHitTransversePos); + fANNIETree->Branch("LAPPDHitP1StartTime", &fLAPPDHitP1StartTime); + fANNIETree->Branch("LAPPDHitP2StartTime", &fLAPPDHitP2StartTime); + fANNIETree->Branch("LAPPDHitP1EndTime", &fLAPPDHitP1EndTime); + fANNIETree->Branch("LAPPDHitP2EndTime", &fLAPPDHitP2EndTime); + + fANNIETree->Branch("LAPPDHitP1PeakTime", &fLAPPDHitP1PeakTime); + fANNIETree->Branch("LAPPDHitP2PeakTime", &fLAPPDHitP2PeakTime); + fANNIETree->Branch("LAPPDHitP1PeakAmp", &fLAPPDHitP1PeakAmp); + fANNIETree->Branch("LAPPDHitP2PeakAmp", &fLAPPDHitP2PeakAmp); + fANNIETree->Branch("LAPPDHitP1HalfHeightTime", &fLAPPDHitP1HalfHeightTime); + fANNIETree->Branch("LAPPDHitP2HalfHeightTime", &fLAPPDHitP2HalfHeightTime); + fANNIETree->Branch("LAPPDHitP1HalfEndTime", &fLAPPDHitP1HalfEndTime); + fANNIETree->Branch("LAPPDHitP2HalfEndTime", &fLAPPDHitP2HalfEndTime); + fANNIETree->Branch("LAPPDHitP1Charge", &fLAPPDHitP1Charge); + fANNIETree->Branch("LAPPDHitP2Charge", &fLAPPDHitP2Charge); + + /* + fANNIETree->Branch("LAPPDWaveformChankey", &LAPPDWaveformChankey, "LAPPDWaveformChankey/I"); + fANNIETree->Branch("WaveformMax", &waveformMaxValue, "WaveformMax/D"); + fANNIETree->Branch("WaveformRMS", &waveformRMSValue, "WaveformRMS/D"); + fANNIETree->Branch("WaveformMaxTimeBin", &waveformMaxTimeBinValue, "WaveformMaxTimeBin/I"); + fANNIETree->Branch("waveformMaxFoundNear", &waveformMaxFoundNear, "waveformMaxFoundNear/O"); // O is boolean + fANNIETree->Branch("WaveformMaxNearing", &waveformMaxNearingValue, "WaveformMaxNearing/D"); + */ + } + + LAPPDWaveformInputLabel = "BLsubtractedLAPPDData"; + m_variables.Get("LAPPDWaveformInputLabel", LAPPDWaveformInputLabel); + if (LAPPD_Waveform_fill) + { + // Log("ANNIEEventTreeMaker Tool: LAPPDWaveformInputLabel = " + LAPPDWaveformInputLabel, 0, ANNIEEventTreeMakerVerbosity); + fANNIETree->Branch("LAPPDWaveform", &fLAPPDWaveforms); + } + + if (LAPPD_MC_fill) + { + fANNIETree->Branch("LAPPDMCHitTubeIDs", &fLAPPDMCHitTubeIDs); + fANNIETree->Branch("LAPPDMCHitChankeys", &fLAPPDMCHitChankeys); + fANNIETree->Branch("LAPPDMCHitTime", &fLAPPDMCHitTime); + fANNIETree->Branch("LAPPDMCHitCharge", &fLAPPDMCHitCharge); + fANNIETree->Branch("LAPPDMCHitX", &fLAPPDMCHitX); + fANNIETree->Branch("LAPPDMCHitY", &fLAPPDMCHitY); + fANNIETree->Branch("LAPPDMCHitZ", &fLAPPDMCHitZ); + fANNIETree->Branch("LAPPDMCHitParallelPos", &fLAPPDMCHitParallelPos); + fANNIETree->Branch("LAPPDMCHitTransversePos", &fLAPPDMCHitTransversePos); + } + + if (MRDHitInfo_fill) + { + fANNIETree->Branch("MRDHitClusterIndex", &fMRDHitClusterIndex); + fANNIETree->Branch("MRDhitT", &fMRDHitT); + fANNIETree->Branch("MRDHitCharge", &fMRDHitCharge); + fANNIETree->Branch("MRDHitDigitPMT", &fMRDHitDigitPMT); + + fANNIETree->Branch("MRDhitDetID", &fMRDHitDetID); + fANNIETree->Branch("MRDhitChankey", &fMRDHitChankey); + fANNIETree->Branch("MRDhitChankeyMC", &fMRDHitChankeyMC); + fANNIETree->Branch("FMVhitT", &fFMVHitT); + fANNIETree->Branch("FMVhitDetID", &fFMVHitDetID); + fANNIETree->Branch("FMVhitChankey", &fFMVHitChankey); + fANNIETree->Branch("FMVhitChankeyMC", &fFMVHitChankeyMC); + fANNIETree->Branch("vetoHit", &fVetoHit, "vetoHit/I"); + } + + if (MRDReco_fill) + { + fANNIETree->Branch("MRDClusterIndex", &fMRDClusterIndex); + fANNIETree->Branch("NumClusterTracks", &fNumClusterTracks); + fANNIETree->Branch("MRDTrackAngle", &fMRDTrackAngle); + fANNIETree->Branch("MRDTrackAngleError", &fMRDTrackAngleError); + fANNIETree->Branch("MRDPenetrationDepth", &fMRDPenetrationDepth); + fANNIETree->Branch("MRDTrackLength", &fMRDTrackLength); + fANNIETree->Branch("MRDEntryPointRadius", &fMRDEntryPointRadius); + fANNIETree->Branch("MRDEnergyLoss", &fMRDEnergyLoss); + fANNIETree->Branch("MRDEnergyLossError", &fMRDEnergyLossError); + fANNIETree->Branch("MRDTrackStartX", &fMRDTrackStartX); + fANNIETree->Branch("MRDTrackStartY", &fMRDTrackStartY); + fANNIETree->Branch("MRDTrackStartZ", &fMRDTrackStartZ); + fANNIETree->Branch("MRDTrackStopX", &fMRDTrackStopX); + fANNIETree->Branch("MRDTrackStopY", &fMRDTrackStopY); + fANNIETree->Branch("MRDTrackStopZ", &fMRDTrackStopZ); + fANNIETree->Branch("MRDSide", &fMRDSide); + fANNIETree->Branch("MRDStop", &fMRDStop); + fANNIETree->Branch("MRDThrough", &fMRDThrough); + } + + fANNIETree->Branch("eventStatusApplied", &fEventStatusApplied, "eventStatusApplied/I"); + fANNIETree->Branch("eventStatusFlagged", &fEventStatusFlagged, "eventStatusFlagged/I"); + + // MC truth information for muons + // Output to tree when MCTruth_fill = 1 in config + if (MCTruth_fill) + { + fTrueNeutCapVtxX = new std::vector; + fTrueNeutCapVtxY = new std::vector; + fTrueNeutCapVtxZ = new std::vector; + fTrueNeutCapNucleus = new std::vector; + fTrueNeutCapTime = new std::vector; + fTrueNeutCapGammas = new std::vector; + fTrueNeutCapE = new std::vector; + fTrueNeutCapGammaE = new std::vector; + fTruePrimaryPdgs = new std::vector; + fANNIETree->Branch("triggerNumber", &fiMCTriggerNum, "triggerNumber/I"); + fANNIETree->Branch("mcEntryNumber", &fMCEventNum, "mcEntryNumber/I"); + fANNIETree->Branch("trueVtxX", &fTrueVtxX, "trueVtxX/D"); + fANNIETree->Branch("trueVtxY", &fTrueVtxY, "trueVtxY/D"); + fANNIETree->Branch("trueVtxZ", &fTrueVtxZ, "trueVtxZ/D"); + fANNIETree->Branch("trueVtxTime", &fTrueVtxTime, "trueVtxTime/D"); + fANNIETree->Branch("trueDirX", &fTrueDirX, "trueDirX/D"); + fANNIETree->Branch("trueDirY", &fTrueDirY, "trueDirY/D"); + fANNIETree->Branch("trueDirZ", &fTrueDirZ, "trueDirZ/D"); + fANNIETree->Branch("trueAngle", &fTrueAngle, "trueAngle/D"); + fANNIETree->Branch("truePhi", &fTruePhi, "truePhi/D"); + fANNIETree->Branch("trueMuonEnergy", &fTrueMuonEnergy, "trueMuonEnergy/D"); + fANNIETree->Branch("truePrimaryPdg", &fTruePrimaryPdg, "truePrimaryPdg/I"); + fANNIETree->Branch("trueTrackLengthInWater", &fTrueTrackLengthInWater, "trueTrackLengthInWater/D"); + fANNIETree->Branch("trueTrackLengthInMRD", &fTrueTrackLengthInMRD, "trueTrackLengthInMRD/D"); + fANNIETree->Branch("trueMultiRing", &fTrueMultiRing, "trueMultiRing/I"); + fANNIETree->Branch("Pi0Count", &fPi0Count, "Pi0Count/I"); + fANNIETree->Branch("PiPlusCount", &fPiPlusCount, "PiPlusCount/I"); + fANNIETree->Branch("PiMinusCount", &fPiMinusCount, "PiMinusCount/I"); + fANNIETree->Branch("K0Count", &fK0Count, "K0Count/I"); + fANNIETree->Branch("KPlusCount", &fKPlusCount, "KPlusCount/I"); + fANNIETree->Branch("KMinusCount", &fKMinusCount, "KMinusCount/I"); + fANNIETree->Branch("truePrimaryPdgs", &fTruePrimaryPdgs); + fANNIETree->Branch("trueNeutCapVtxX", &fTrueNeutCapVtxX); + fANNIETree->Branch("trueNeutCapVtxY", &fTrueNeutCapVtxY); + fANNIETree->Branch("trueNeutCapVtxZ", &fTrueNeutCapVtxZ); + fANNIETree->Branch("trueNeutCapNucleus", &fTrueNeutCapNucleus); + fANNIETree->Branch("trueNeutCapTime", &fTrueNeutCapTime); + fANNIETree->Branch("trueNeutCapGammas", &fTrueNeutCapGammas); + fANNIETree->Branch("trueNeutCapE", &fTrueNeutCapE); + fANNIETree->Branch("trueNeutCapGammaE", &fTrueNeutCapGammaE); + fANNIETree->Branch("trueNeutrinoEnergy", &fTrueNeutrinoEnergy, "trueNeutrinoEnergy/D"); + fANNIETree->Branch("trueNeutrinoMomentum_X", &fTrueNeutrinoMomentum_X, "trueNeutrinoMomentum_X/D"); + fANNIETree->Branch("trueNeutrinoMomentum_Y", &fTrueNeutrinoMomentum_Y, "trueNeutrinoMomentum_Y/D"); + fANNIETree->Branch("trueNeutrinoMomentum_Z", &fTrueNeutrinoMomentum_Z, "trueNeutrinoMomentum_Z/D"); + fANNIETree->Branch("trueNuIntxVtx_X", &fTrueNuIntxVtx_X, "trueNuIntxVtx_X/D"); + fANNIETree->Branch("trueNuIntxVtx_Y", &fTrueNuIntxVtx_Y, "trueNuIntxVtx_Y/D"); + fANNIETree->Branch("trueNuIntxVtx_Z", &fTrueNuIntxVtx_Z, "trueNuIntxVtx_Z/D"); + fANNIETree->Branch("trueNuIntxVtx_T", &fTrueNuIntxVtx_T, "trueNuIntxVtx_T/D"); + fANNIETree->Branch("trueFSLVtx_X", &fTrueFSLVtx_X, "trueFSLVtx_X/D"); + fANNIETree->Branch("trueFSLVtx_Y", &fTrueFSLVtx_Y, "trueFSLVtx_Y/D"); + fANNIETree->Branch("trueFSLVtx_Z", &fTrueFSLVtx_Z, "trueFSLVtx_Z/D"); + fANNIETree->Branch("trueFSLMomentum_X", &fTrueFSLMomentum_X, "trueFSLMomentum_X/D"); + fANNIETree->Branch("trueFSLMomentum_Y", &fTrueFSLMomentum_Y, "trueFSLMomentum_Y/D"); + fANNIETree->Branch("trueFSLMomentum_Z", &fTrueFSLMomentum_Z, "trueFSLMomentum_Z/D"); + fANNIETree->Branch("trueFSLTime", &fTrueFSLTime, "trueFSLTime/D"); + fANNIETree->Branch("trueFSLMass", &fTrueFSLMass, "trueFSLMass/D"); + fANNIETree->Branch("trueFSLPdg", &fTrueFSLPdg, "trueFSLPdg/I"); + fANNIETree->Branch("trueFSLEnergy", &fTrueFSLEnergy, "trueFSLEnergy/D"); + fANNIETree->Branch("trueQ2", &fTrueQ2, "trueQ2/D"); + fANNIETree->Branch("trueCC", &fTrueCC, "trueCC/I"); + fANNIETree->Branch("trueNC", &fTrueNC, "trueNC/I"); + fANNIETree->Branch("trueQEL", &fTrueQEL, "trueQEL/I"); + fANNIETree->Branch("trueRES", &fTrueRES, "trueRES/I"); + fANNIETree->Branch("trueDIS", &fTrueDIS, "trueDIS/I"); + fANNIETree->Branch("trueCOH", &fTrueCOH, "trueCOH/I"); + fANNIETree->Branch("trueMEC", &fTrueMEC, "trueMEC/I"); + fANNIETree->Branch("trueNeutrons", &fTrueNeutrons, "trueNeutrons/I"); + fANNIETree->Branch("trueProtons", &fTrueProtons, "trueProtons/I"); + fANNIETree->Branch("truePi0", &fTruePi0, "truePi0/I"); + fANNIETree->Branch("truePiPlus", &fTruePiPlus, "truePiPlus/I"); + fANNIETree->Branch("truePiPlusCher", &fTruePiPlusCher, "truePiPlusCher/I"); + fANNIETree->Branch("truePiMinus", &fTruePiMinus, "truePiMinus/I"); + fANNIETree->Branch("truePiMinusCher", &fTruePiMinusCher, "truePiMinusCher/I"); + fANNIETree->Branch("trueKPlus", &fTrueKPlus, "trueKPlus/I"); + fANNIETree->Branch("trueKPlusCher", &fTrueKPlusCher, "trueKPlusCher/I"); + fANNIETree->Branch("trueKMinus", &fTrueKMinus, "trueKMinus/I"); + fANNIETree->Branch("trueKMinusCher", &fTrueKMinusCher, "trueKMinusCher/I"); + } + + // Reconstructed variables after full Muon Reco Analysis + if (TankReco_fill) + { + fANNIETree->Branch("recoVtxX", &fRecoVtxX, "recoVtxX/D"); + fANNIETree->Branch("recoVtxY", &fRecoVtxY, "recoVtxY/D"); + fANNIETree->Branch("recoVtxZ", &fRecoVtxZ, "recoVtxZ/D"); + fANNIETree->Branch("recoVtxTime", &fRecoVtxTime, "recoVtxTime/D"); + fANNIETree->Branch("recoDirX", &fRecoDirX, "recoDirX/D"); + fANNIETree->Branch("recoDirY", &fRecoDirY, "recoDirY/D"); + fANNIETree->Branch("recoDirZ", &fRecoDirZ, "recoDirZ/D"); + fANNIETree->Branch("recoAngle", &fRecoAngle, "recoAngle/D"); + fANNIETree->Branch("recoPhi", &fRecoPhi, "recoPhi/D"); + fANNIETree->Branch("recoVtxFOM", &fRecoVtxFOM, "recoVtxFOM/D"); + fANNIETree->Branch("recoStatus", &fRecoStatus, "recoStatus/I"); + } + + // Reconstructed variables from each step in Muon Reco Analysis + // Currently output when RecoDebug_fill = 1 in config + if (RecoDebug_fill) + { + fANNIETree->Branch("seedVtxX", &fSeedVtxX); + fANNIETree->Branch("seedVtxY", &fSeedVtxY); + fANNIETree->Branch("seedVtxZ", &fSeedVtxZ); + fANNIETree->Branch("seedVtxFOM", &fSeedVtxFOM); + fANNIETree->Branch("seedVtxTime", &fSeedVtxTime, "seedVtxTime/D"); + + fANNIETree->Branch("pointPosX", &fPointPosX, "pointPosX/D"); + fANNIETree->Branch("pointPosY", &fPointPosY, "pointPosY/D"); + fANNIETree->Branch("pointPosZ", &fPointPosZ, "pointPosZ/D"); + fANNIETree->Branch("pointPosTime", &fPointPosTime, "pointPosTime/D"); + fANNIETree->Branch("pointPosFOM", &fPointPosFOM, "pointPosFOM/D"); + fANNIETree->Branch("pointPosStatus", &fPointPosStatus, "pointPosStatus/I"); + + fANNIETree->Branch("pointDirX", &fPointDirX, "pointDirX/D"); + fANNIETree->Branch("pointDirY", &fPointDirY, "pointDirY/D"); + fANNIETree->Branch("pointDirZ", &fPointDirZ, "pointDirZ/D"); + fANNIETree->Branch("pointDirTime", &fPointDirTime, "pointDirTime/D"); + fANNIETree->Branch("pointDirStatus", &fPointDirStatus, "pointDirStatus/I"); + fANNIETree->Branch("pointDirFOM", &fPointDirFOM, "pointDirFOM/D"); + + fANNIETree->Branch("pointVtxPosX", &fPointVtxPosX, "pointVtxPosX/D"); + fANNIETree->Branch("pointVtxPosY", &fPointVtxPosY, "pointVtxPosY/D"); + fANNIETree->Branch("pointVtxPosZ", &fPointVtxPosZ, "pointVtxPosZ/D"); + fANNIETree->Branch("pointVtxTime", &fPointVtxTime, "pointVtxTime/D"); + fANNIETree->Branch("pointVtxDirX", &fPointVtxDirX, "pointVtxDirX/D"); + fANNIETree->Branch("pointVtxDirY", &fPointVtxDirY, "pointVtxDirY/D"); + fANNIETree->Branch("pointVtxDirZ", &fPointVtxDirZ, "pointVtxDirZ/D"); + fANNIETree->Branch("pointVtxFOM", &fPointVtxFOM, "pointVtxFOM/D"); + fANNIETree->Branch("pointVtxStatus", &fPointVtxStatus, "pointVtxStatus/I"); + } + + // Difference in MC Truth and Muon Reconstruction Analysis + // Output to tree when muonTruthRecoDiff_fill = 1 in config + if (muonTruthRecoDiff_fill) + { + fANNIETree->Branch("deltaVtxX", &fDeltaVtxX, "deltaVtxX/D"); + fANNIETree->Branch("deltaVtxY", &fDeltaVtxY, "deltaVtxY/D"); + fANNIETree->Branch("deltaVtxZ", &fDeltaVtxZ, "deltaVtxZ/D"); + fANNIETree->Branch("deltaVtxR", &fDeltaVtxR, "deltaVtxR/D"); + fANNIETree->Branch("deltaVtxT", &fDeltaVtxT, "deltaVtxT/D"); + fANNIETree->Branch("deltaParallel", &fDeltaParallel, "deltaParallel/D"); + fANNIETree->Branch("deltaPerpendicular", &fDeltaPerpendicular, "deltaPerpendicular/D"); + fANNIETree->Branch("deltaAzimuth", &fDeltaAzimuth, "deltaAzimuth/D"); + fANNIETree->Branch("deltaZenith", &fDeltaZenith, "deltaZenith/D"); + fANNIETree->Branch("deltaAngle", &fDeltaAngle, "deltaAngle/D"); + } + + return true; +} + +bool ANNIEEventTreeMaker::Execute() +{ + //****************************** Reset Variables *************************************// + ResetVariables(); + + //****************************** fillCleanEventsOnly *************************************// + // If only clean events are built, return true for dirty events + auto get_flagsapp = m_data->Stores.at("RecoEvent")->Get("EventFlagApplied", fEventStatusApplied); + auto get_flags = m_data->Stores.at("RecoEvent")->Get("EventFlagged", fEventStatusFlagged); + + if (fillCleanEventsOnly) + { + // auto get_cutstatus = m_data->Stores.at("RecoEvent")->Get("EventCutStatus",fEventCutStatus); + if (!get_flagsapp || !get_flags) + { + Log("PhaseITreeMaker tool: No Event status applied or flagged bitmask!!", v_error, ANNIEEventTreeMakerVerbosity); + return false; + } + // check if event passes the cut + if ((fEventStatusFlagged) != 0) + { + // if (!fEventCutStatus){ + Log("ANNIEEventTreeMaker Tool: Event was flagged with one of the active cuts.", v_debug, ANNIEEventTreeMakerVerbosity); + return true; + } + } + // done + + //****************************** Fill Event Info *************************************// + bool keepLoading = LoadEventInfo(); + if (!keepLoading) + return false; + LoadBeamInfo(); + // done + + //****************************** Fill RWM BRF Info *************************************// + if (RWMBRF_fill) + { + LoadRWMBRFInfo(); + } + + //****************************** Fill Hit Info *************************************// + if (TankHitInfo_fill) + { + // this will fill all hits in this event + LoadAllTankHits(); + } + if (SiPMPulseInfo_fill) + { + LoadSiPMHits(); + } + // done + //****************************** Fill Cluster Info *************************************// + if (TankCluster_fill) + { + LoadClusterInfo(); + } + + //****************************** Fill LAPPD Info *************************************// + if (LAPPDData_fill) + { + LoadLAPPDInfo(); + } + if (LAPPD_Waveform_fill) + { + FillLAPPDWaveform(); + } + + if (LAPPD_MC_fill) + { + FillLAPPDMCHitInfo(); + } + + //****************************** Fill MRD Info *************************************// + if (MRDHitInfo_fill) + { + LoadMRDCluster(); + } + + //****************************** Fill Reco Info *************************************// + bool got_reco = false; + if (TankReco_fill) + { + got_reco = FillTankRecoInfo(); + } + + if (RecoDebug_fill) + FillRecoDebugInfo(); + + //****************************** Fill MCTruth Info *************************************// + bool gotmctruth = false; + if (MCTruth_fill) + { + gotmctruth = FillMCTruthInfo(); // todo + } + if (muonTruthRecoDiff_fill) + this->FillTruthRecoDiffInfo(gotmctruth, got_reco); + + //****************************** Fill Reco Summary *************************************// + if (got_reco && gotmctruth && (ANNIEEventTreeMakerVerbosity > 4)) + { + RecoSummary(); + } + + //****************************** Fill Tree *************************************// + fANNIETree->Fill(); + + processedEvents++; + return true; +} + +bool ANNIEEventTreeMaker::Finalise() +{ + Log("ANNIEEventTreeMaker Tool: Got " + std::to_string(processedEvents) + " events", 0, ANNIEEventTreeMakerVerbosity); + fOutput_tfile->cd(); + fANNIETree->Write(); + fOutput_tfile->Close(); + Log("ANNIEEventTreeMaker Tool: Tree written to file", 0, ANNIEEventTreeMakerVerbosity); + + return true; +} + +void ANNIEEventTreeMaker::ResetVariables() +{ + // Reset all variables + + // Event Info + fRunNumber = 0; + fSubrunNumber = 0; + fPartFileNumber = 0; + fEventNumber = 0; + fPrimaryTriggerWord = 0; + fPrimaryTriggerTime = 0; + fTriggerword = 0; + fExtended = 0; + fTankMRDCoinc = 0; + fNoVeto = 0; + fHasTank = 0; + fHasMRD = 0; + fHasLAPPD = 0; + fGroupedTriggerTime.clear(); + fGroupedTriggerWord.clear(); + fDataStreams.clear(); + fEventTimeTank = 0; + fEventTimeMRD = 0; + fMRDTriggerType = ""; + fMRDTriggerTypeInt = -9999; + + // beam info + fPot = -9999; + fBeamok = 0; + beam_E_TOR860 = -9999; + beam_E_TOR875 = -9999; + beam_THCURR = -9999; + beam_BTJT2 = -9999; + beam_HP875 = -9999; + beam_VP875 = -9999; + beam_HPTG1 = -9999; + beam_VPTG1 = -9999; + beam_HPTG2 = -9999; + beam_VPTG2 = -9999; + beam_BTH2T2 = -9999; + fBeamInfoTime = 0; + fBeamInfoTimeToTriggerDiff = -9999; + + // RWM BRF info + fRWMRisingStart = -9999; + fRWMRisingEnd = -9999; + fRWMHalfRising = -9999; + fRWMFHWM = -9999; + fRWMFirstPeak = -9999; + fBRFFirstPeak = -9999; + fBRFAveragePeak = -9999; + fBRFFirstPeakFit = -9999; + + // TankHitInfo + fNHits = 0; + fIsFiltered.clear(); + fHitX.clear(); + fHitY.clear(); + fHitZ.clear(); + fHitT.clear(); + fHitQ.clear(); + fHitPE.clear(); + fHitType.clear(); + fHitDetID.clear(); + fHitChankey.clear(); + fHitChankeyMC.clear(); + + // SiPMPulse Info + fSiPM1NPulses = 0; + fSiPM2NPulses = 0; + fSiPMHitQ.clear(); + fSiPMHitT.clear(); + fSiPMHitAmplitude.clear(); + fSiPMNum.clear(); + + // LAPPDData_fill + fLAPPD_Count = 0; + fLAPPD_ID.clear(); + fLAPPD_Beamgate_ns.clear(); + fLAPPD_Timestamp_ns.clear(); + fLAPPD_Beamgate_Raw.clear(); + fLAPPD_Timestamp_Raw.clear(); + fLAPPD_Offset.clear(); + fLAPPD_TSCorrection.clear(); + fLAPPD_BGCorrection.clear(); + fLAPPD_OSInMinusPS.clear(); + fLAPPD_BG_switchBit0.clear(); + fLAPPD_BG_switchBit1.clear(); + // LAPPD_PPS_fill + fLAPPD_BGPPSBefore.clear(); + fLAPPD_BGPPSAfter.clear(); + fLAPPD_BGPPSDiff.clear(); + fLAPPD_BGPPSMissing.clear(); + fLAPPD_TSPPSBefore.clear(); + fLAPPD_TSPPSAfter.clear(); + fLAPPD_TSPPSDiff.clear(); + fLAPPD_TSPPSMissing.clear(); + + // LAPPD Reco Fill + fLAPPDPulseTimeStampUL.clear(); + fLAPPDPulseBeamgateUL.clear(); + fLAPPD_IDs.clear(); + fChannelID.clear(); + fPulsePeakTime.clear(); + fPulseHalfHeightTime.clear(); + fPulseCharge.clear(); + fPulsePeakAmp.clear(); + fPulseStart.clear(); + fPulseEnd.clear(); + fPulseWidth.clear(); + fPulseSide.clear(); + fPulseStripNum.clear(); + fChannelBaseline.clear(); + + fLAPPDHitTimeStampUL.clear(); + fLAPPDHitBeamgateUL.clear(); + fLAPPDHit_IDs.clear(); + fLAPPDHitChannel.clear(); + fLAPPDHitStrip.clear(); + fLAPPDHitTime.clear(); + fLAPPDHitAmp.clear(); + fLAPPDHitParallelPos.clear(); + fLAPPDHitTransversePos.clear(); + fLAPPDHitP1StartTime.clear(); + fLAPPDHitP2StartTime.clear(); + fLAPPDHitP1EndTime.clear(); + fLAPPDHitP2EndTime.clear(); + fLAPPDHitP1PeakTime.clear(); + fLAPPDHitP2PeakTime.clear(); + fLAPPDHitP1PeakAmp.clear(); + fLAPPDHitP2PeakAmp.clear(); + fLAPPDHitP1HalfHeightTime.clear(); + fLAPPDHitP2HalfHeightTime.clear(); + fLAPPDHitP1HalfEndTime.clear(); + fLAPPDHitP2HalfEndTime.clear(); + fLAPPDHitP1Charge.clear(); + fLAPPDHitP2Charge.clear(); + + LAPPDWaveformChankey.clear(); + waveformMaxValue.clear(); + waveformRMSValue.clear(); + waveformMaxFoundNear.clear(); + waveformMaxNearingValue.clear(); + waveformMaxTimeBinValue.clear(); + + // LAPPD waveform fill + fLAPPDWaveforms.clear(); + + // LAPPD MC fill + fLAPPDMCHitTubeIDs.clear(); + fLAPPDMCHitChankeys.clear(); + fLAPPDMCHitTime.clear(); + fLAPPDMCHitCharge.clear(); + fLAPPDMCHitX.clear(); + fLAPPDMCHitY.clear(); + fLAPPDMCHitZ.clear(); + fLAPPDMCHitParallelPos.clear(); + fLAPPDMCHitTransversePos.clear(); + + // tank cluster information + fNumberOfClusters = 0; + + fClusterHits.clear(); + fClusterChargeV.clear(); + fClusterTimeV.clear(); + fClusterPEV.clear(); + + fCluster_HitX.clear(); + fCluster_HitY.clear(); + fCluster_HitZ.clear(); + fCluster_HitT.clear(); + fCluster_HitQ.clear(); + fCluster_HitPE.clear(); + fCluster_HitType.clear(); + fCluster_HitDetID.clear(); + fCluster_HitChankey.clear(); + fCluster_HitChankeyMC.clear(); + + fClusterMaxPEV.clear(); + fClusterChargePointXV.clear(); + fClusterChargePointYV.clear(); + fClusterChargePointZV.clear(); + fClusterChargeBalanceV.clear(); + + // MRD cluster information + fEventTimeMRD_Tree = 0; + fMRDClusterNumber = 0; + fMRDClusterHitNumber.clear(); + fMRDClusterTime.clear(); + fMRDClusterTimeSigma.clear(); + + fVetoHit = 0; + fMRDHitClusterIndex.clear(); + fMRDHitT.clear(); + fMRDHitCharge.clear(); + fMRDHitDigitPMT.clear(); + fMRDHitDetID.clear(); + fMRDHitChankey.clear(); + fMRDHitChankeyMC.clear(); + fFMVHitT.clear(); + fFMVHitDetID.clear(); + fFMVHitChankey.clear(); + fFMVHitChankeyMC.clear(); + + fNumMRDClusterTracks = 0; + fMRDTrackAngle.clear(); + fMRDTrackAngleError.clear(); + fMRDPenetrationDepth.clear(); + fMRDTrackLength.clear(); + fMRDEntryPointRadius.clear(); + fMRDEnergyLoss.clear(); + fMRDEnergyLossError.clear(); + fMRDTrackStartX.clear(); + fMRDTrackStartY.clear(); + fMRDTrackStartZ.clear(); + fMRDTrackStopX.clear(); + fMRDTrackStopY.clear(); + fMRDTrackStopZ.clear(); + fMRDSide.clear(); + fMRDStop.clear(); + fMRDThrough.clear(); + fMRDClusterIndex.clear(); + fNumClusterTracks.clear(); + + // fillCleanEventsOnly + fEventStatusApplied = 0; + fEventStatusFlagged = 0; + + // MCTruth_fill + if (MCTruth_fill) + { + fMCEventNum = 0; + fMCTriggerNum = 0; + fiMCTriggerNum = -9999; + + fTrueVtxX = -9999; + fTrueVtxY = -9999; + fTrueVtxZ = -9999; + fTrueVtxTime = -9999; + fTrueDirX = -9999; + fTrueDirY = -9999; + fTrueDirZ = -9999; + fTrueAngle = -9999; + fTruePhi = -9999; + fTrueMuonEnergy = -9999; + fTruePrimaryPdg = -9999; + fTrueTrackLengthInWater = -9999; + fTrueTrackLengthInMRD = -9999; + fTruePrimaryPdgs->clear(); + fTrueNeutCapVtxX->clear(); + fTrueNeutCapVtxY->clear(); + fTrueNeutCapVtxZ->clear(); + fTrueNeutCapNucleus->clear(); + fTrueNeutCapTime->clear(); + fTrueNeutCapGammas->clear(); + fTrueNeutCapE->clear(); + fTrueNeutCapGammaE->clear(); + fTrueMultiRing = -9999; + } + + // Genie information for event + fTrueNeutrinoEnergy = -9999; + fTrueNeutrinoMomentum_X = -9999; + fTrueNeutrinoMomentum_Y = -9999; + fTrueNeutrinoMomentum_Z = -9999; + fTrueNuIntxVtx_X = -9999; + fTrueNuIntxVtx_Y = -9999; + fTrueNuIntxVtx_Z = -9999; + fTrueNuIntxVtx_T = -9999; + fTrueFSLVtx_X = -9999; + fTrueFSLVtx_Y = -9999; + fTrueFSLVtx_Z = -9999; + fTrueFSLMomentum_X = -9999; + fTrueFSLMomentum_Y = -9999; + fTrueFSLMomentum_Z = -9999; + fTrueFSLTime = -9999; + fTrueFSLMass = -9999; + fTrueFSLPdg = -9999; + fTrueFSLEnergy = -9999; + fTrueQ2 = -9999; + fTrueCC = -9999; + fTrueNC = -9999; + fTrueQEL = -9999; + fTrueRES = -9999; + fTrueDIS = -9999; + fTrueCOH = -9999; + fTrueMEC = -9999; + fTrueNeutrons = -9999; + fTrueProtons = -9999; + fTruePi0 = -9999; + fTruePiPlus = -9999; + fTruePiPlusCher = -9999; + fTruePiMinus = -9999; + fTruePiMinusCher = -9999; + fTrueKPlus = -9999; + fTrueKPlusCher = -9999; + fTrueKMinus = -9999; + fTrueKMinusCher = -9999; + + // TankReco_fill + fRecoVtxX = -9999; + fRecoVtxY = -9999; + fRecoVtxZ = -9999; + fRecoVtxTime = -9999; + fRecoVtxFOM = -9999; + fRecoDirX = -9999; + fRecoDirY = -9999; + fRecoDirZ = -9999; + fRecoAngle = -9999; + fRecoPhi = -9999; + fRecoStatus = -9999; + + // RecoDebug_fill + fSeedVtxX.clear(); + fSeedVtxY.clear(); + fSeedVtxZ.clear(); + fSeedVtxFOM.clear(); + fSeedVtxTime = -9999; + + // Reco vertex + // Point Position Vertex + fPointVtxPosX = -9999; + fPointVtxPosY = -9999; + fPointVtxPosZ = -9999; + fPointVtxTime = -9999; + fPointPosFOM = -9999; + fPointPosStatus = -9999; + fPointVtxDirX = -9999; + fPointVtxDirY = -9999; + fPointVtxDirZ = -9999; + fPointDirTime = -9999; + fPointDirFOM = -9999; + fPointDirStatus = -9999; + + // Point Vertex Finder + fPointVtxPosX = -9999; + fPointVtxPosY = -9999; + fPointVtxPosZ = -9999; + fPointVtxTime = -9999; + fPointVtxDirX = -9999; + fPointVtxDirY = -9999; + fPointVtxDirZ = -9999; + fPointVtxFOM = -9999; + fPointVtxStatus = -9999; + + // Difference between MC and Truth + fDeltaVtxX = -9999; + fDeltaVtxY = -9999; + fDeltaVtxZ = -9999; + fDeltaVtxR = -9999; + fDeltaVtxT = -9999; + fDeltaParallel = -9999; + fDeltaPerpendicular = -9999; + fDeltaAzimuth = -9999; + fDeltaZenith = -9999; + fDeltaAngle = -9999; + + // Pion and kaon counts for event + fPi0Count = 0; + fPiPlusCount = 0; + fPiMinusCount = 0; + fK0Count = 0; + fKPlusCount = 0; + fKMinusCount = 0; + + // Event Info + fDataStreams.clear(); + GroupedTrigger.clear(); + + // LAPPDData_fill + LAPPDDataMap.clear(); + LAPPDBeamgate_ns.clear(); + LAPPDTimeStamps_ns.clear(); + LAPPDTimeStampsRaw.clear(); + LAPPDBeamgatesRaw.clear(); + LAPPDOffsets.clear(); + LAPPDTSCorrection.clear(); + LAPPDBGCorrection.clear(); + LAPPDOSInMinusPS.clear(); + SwitchBitBG.clear(); + // LAPPD_PPS_fill + LAPPDBG_PPSBefore.clear(); + LAPPDBG_PPSAfter.clear(); + LAPPDBG_PPSDiff.clear(); + LAPPDBG_PPSMissing.clear(); + LAPPDTS_PPSBefore.clear(); + LAPPDTS_PPSAfter.clear(); + LAPPDTS_PPSDiff.clear(); + LAPPDTS_PPSMissing.clear(); + + // LAPPD Reco Fill + lappdPulses.clear(); + lappdHits.clear(); + + waveformMax.clear(); + waveformRMS.clear(); + waveformMaxLast.clear(); + waveformMaxNearing.clear(); + waveformMaxTimeBin.clear(); +} + +bool ANNIEEventTreeMaker::LoadEventInfo() +{ + Log("ANNIEEventTreeMaker Tool: LoadEventInfo", v_warning, ANNIEEventTreeMakerVerbosity); + m_data->Stores["ANNIEEvent"]->Get("RunNumber", fRunNumber); + m_data->Stores["ANNIEEvent"]->Get("SubRunNumber", fSubrunNumber); + m_data->Stores["ANNIEEvent"]->Get("PartNumber", fPartFileNumber); + bool gotEventNumber = m_data->Stores["ANNIEEvent"]->Get("EventNumber", fEventNumber); + if (!gotEventNumber) + { + uint32_t enm = 9998; + m_data->CStore.Get("EventNumberTree", enm); + cout << "ANNIEEventTreeMaker Tool: Not get the event number from ANNIEEvent, get from CStore: " << enm << endl; + fEventNumber = static_cast(enm); + } + + m_data->Stores["ANNIEEvent"]->Get("PrimaryTriggerWord", fPrimaryTriggerWord); + if (fPrimaryTriggerWord == 14) + trigword = 5; + else + trigword = fPrimaryTriggerWord; + m_data->Stores["ANNIEEvent"]->Get("PrimaryTriggerTime", fPrimaryTriggerTime); + m_data->Stores["ANNIEEvent"]->Get("GroupedTrigger", GroupedTrigger); + m_data->Stores["ANNIEEvent"]->Get("TriggerWord", fTriggerword); + m_data->Stores["ANNIEEvent"]->Get("TriggerExtended", fExtended); + m_data->Stores["ANNIEEvent"]->Get("DataStreams", fDataStreams); + + bool pmtmrdcoinc, noveto; + m_data->Stores["RecoEvent"]->Get("PMTMRDCoinc", pmtmrdcoinc); + m_data->Stores["RecoEvent"]->Get("NoVeto", noveto); + if (pmtmrdcoinc) + fTankMRDCoinc = 1; + else + fTankMRDCoinc = 0; + + if (noveto) + fNoVeto = 1; + else + fNoVeto = 0; + + if (fDataStreams["Tank"] == 1) + fHasTank = 1; + else + fHasTank = 0; + + if (fDataStreams["MRD"] == 1) + { + fHasMRD = 1; + m_data->Stores["ANNIEEvent"]->Get("MRDTriggerType", fMRDTriggerType); + Log("ANNIEEventTreeMaker Tool: MRD Trigger Type: " + fMRDTriggerType, v_debug, ANNIEEventTreeMakerVerbosity); + bool cosmic = fMRDTriggerType == "Cosmic"; + Log("ANNIEEventTreeMaker Tool: Cosmic Trigger: " + std::to_string(cosmic), v_debug, ANNIEEventTreeMakerVerbosity); + if (fMRDTriggerType == "Beam") + fMRDTriggerTypeInt = 1; + else if (fMRDTriggerType == "Cosmic") + fMRDTriggerTypeInt = 2; + else + fMRDTriggerTypeInt = 0; + } + else + fHasMRD = 0; + + if (fDataStreams["LAPPD"] == 1) + fHasLAPPD = 1; + else + fHasLAPPD = 0; + + for (std::map::iterator it = GroupedTrigger.begin(); it != GroupedTrigger.end(); ++it) + { + uint64_t key = it->first; + uint32_t value = it->second; + + fGroupedTriggerTime.push_back(key); + fGroupedTriggerWord.push_back(value); + } + + bool gotETT = m_data->Stores["ANNIEEvent"]->Get("EventTimeTank", fEventTimeTank); + if (!gotETT) + fEventTimeTank = 0; + + TimeClass tm; + bool gotETMRD = m_data->Stores["ANNIEEvent"]->Get("EventTimeMRD", tm); + fEventTimeMRD = (ULong64_t)tm.GetNs(); + + if (!gotETMRD) + fEventTimeMRD = 0; + + if (fillAllTriggers) + return true; + else if (fill_singleTrigger) + { + if (fPrimaryTriggerWord == fill_singleTriggerWord) + return true; + else + return false; + } + else if (fill_TriggerWord.size() > 0) + { + for (auto trig : fill_TriggerWord) + { + if (fPrimaryTriggerWord == trig) + return true; + } + return false; + } + else + return true; +} + +void ANNIEEventTreeMaker::LoadBeamInfo() +{ + Log("ANNIEEventTreeMaker Tool: LoadBeamInfo", v_debug, ANNIEEventTreeMakerVerbosity); + + m_data->Stores["ANNIEEvent"]->Get("beam_E_TOR860", beam_E_TOR860); + m_data->Stores["ANNIEEvent"]->Get("beam_E_TOR875", beam_E_TOR875); + m_data->Stores["ANNIEEvent"]->Get("beam_THCURR", beam_THCURR); + m_data->Stores["ANNIEEvent"]->Get("beam_BTJT2", beam_BTJT2); + m_data->Stores["ANNIEEvent"]->Get("beam_HP875", beam_HP875); + m_data->Stores["ANNIEEvent"]->Get("beam_VP875", beam_VP875); + m_data->Stores["ANNIEEvent"]->Get("beam_HPTG1", beam_HPTG1); + m_data->Stores["ANNIEEvent"]->Get("beam_VPTG1", beam_VPTG1); + m_data->Stores["ANNIEEvent"]->Get("beam_HPTG2", beam_HPTG2); + m_data->Stores["ANNIEEvent"]->Get("beam_VPTG2", beam_VPTG2); + m_data->Stores["ANNIEEvent"]->Get("beam_BTH2T2", beam_BTH2T2); + + m_data->Stores["ANNIEEvent"]->Get("beam_E_TOR875", fPot); + m_data->Stores["ANNIEEvent"]->Get("beam_good", fBeamok); + + m_data->Stores["ANNIEEvent"]->Get("BeamInfoTime", fBeamInfoTime); + m_data->Stores["ANNIEEvent"]->Get("BeamInfoTimeToTriggerDiff", fBeamInfoTimeToTriggerDiff); +} + +void ANNIEEventTreeMaker::LoadRWMBRFInfo() +{ + Log("ANNIEEventTreeMaker Tool: LoadRWMBRFInfo", v_debug, ANNIEEventTreeMakerVerbosity); + m_data->Stores["ANNIEEvent"]->Get("RWMRisingStart", fRWMRisingStart); + m_data->Stores["ANNIEEvent"]->Get("RWMRisingEnd", fRWMRisingEnd); + m_data->Stores["ANNIEEvent"]->Get("RWMHalfRising", fRWMHalfRising); + m_data->Stores["ANNIEEvent"]->Get("RWMFHWM", fRWMFHWM); + m_data->Stores["ANNIEEvent"]->Get("RWMFirstPeak", fRWMFirstPeak); + + m_data->Stores["ANNIEEvent"]->Get("BRFFirstPeak", fBRFFirstPeak); + m_data->Stores["ANNIEEvent"]->Get("BRFAveragePeak", fBRFAveragePeak); + m_data->Stores["ANNIEEvent"]->Get("BRFFirstPeakFit", fBRFFirstPeakFit); +} + +void ANNIEEventTreeMaker::LoadAllTankHits() +{ + Log("ANNIEEventTreeMaker Tool: LoadAllTankHits", v_debug, ANNIEEventTreeMakerVerbosity); + std::map> *Hits = nullptr; + std::map> *MCHits = nullptr; + bool got_hits = false; + if (isData) + got_hits = m_data->Stores["ANNIEEvent"]->Get("Hits", Hits); + else + got_hits = m_data->Stores["ANNIEEvent"]->Get("MCHits", MCHits); + if (!got_hits) + { + std::cout << "No Hits store in ANNIEEvent. Continuing to build tree " << std::endl; + return; + } + + Position detector_center = geom->GetTankCentre(); + double tank_center_x = detector_center.X(); + double tank_center_y = detector_center.Y(); + double tank_center_z = detector_center.Z(); + fNHits = 0; + + std::map>::iterator it_tank_data; + std::map>::iterator it_tank_mc; + if (isData) + it_tank_data = (*Hits).begin(); + else + it_tank_mc = (*MCHits).begin(); + bool loop_tank = true; + int hits_size = (isData) ? Hits->size() : MCHits->size(); + if (hits_size == 0) + loop_tank = false; + + while (loop_tank) + { + // start to fill tank info to vectors + unsigned long channel_key; + if (isData) + channel_key = it_tank_data->first; + else + channel_key = it_tank_mc->first; + Detector *this_detector = geom->ChannelToDetector(channel_key); + Position det_position = this_detector->GetDetectorPosition(); + unsigned long detkey = this_detector->GetDetectorID(); + unsigned long channel_key_data = channel_key; + if (!isData) + { + int wcsimid = channelkey_to_pmtid.at(channel_key); + channel_key_data = pmtid_to_channelkey[wcsimid]; + } + std::map::iterator it = ChannelKeyToSPEMap.find(channel_key); + std::map::iterator it_mc = ChannelKeyToSPEMap.find(channel_key_data); + bool SPE_available = true; + if (isData) + SPE_available = (it != ChannelKeyToSPEMap.end()); + else + SPE_available = (it_mc != ChannelKeyToSPEMap.end()); + if (SPE_available) + { // Charge to SPE conversion is available + if (isData) + { + std::vector ThisPMTHits = it_tank_data->second; + fNHits += ThisPMTHits.size(); + for (Hit &ahit : ThisPMTHits) + { + double hit_charge = ahit.GetCharge(); + double hit_PE = hit_charge / ChannelKeyToSPEMap.at(channel_key); + fHitX.push_back((det_position.X() - tank_center_x)); + fHitY.push_back((det_position.Y() - tank_center_y)); + fHitZ.push_back((det_position.Z() - tank_center_z)); + fHitT.push_back(ahit.GetTime()); + fHitQ.push_back(hit_charge); + fHitPE.push_back(hit_PE); + fHitDetID.push_back(detkey); + fHitChankey.push_back(channel_key); + fHitChankeyMC.push_back(channel_key); + fHitType.push_back(RecoDigit::PMT8inch); // 0 For PMTs + } + } + else + { + std::vector ThisPMTHits = it_tank_mc->second; + fNHits += ThisPMTHits.size(); + for (MCHit &ahit : ThisPMTHits) + { + double hit_PE = ahit.GetCharge(); + double hit_charge = hit_PE * ChannelKeyToSPEMap.at(channel_key_data); + fHitX.push_back((det_position.X() - tank_center_x)); + fHitY.push_back((det_position.Y() - tank_center_y)); + fHitZ.push_back((det_position.Z() - tank_center_z)); + fHitT.push_back(ahit.GetTime()); + fHitQ.push_back(hit_charge); + fHitPE.push_back(hit_PE); + fHitDetID.push_back(detkey); + fHitChankey.push_back(channel_key_data); + fHitChankeyMC.push_back(channel_key); + fHitType.push_back(RecoDigit::PMT8inch); // 0 For PMTs + } + } + } + + if (isData) + { + it_tank_data++; + if (it_tank_data == (*Hits).end()) + loop_tank = false; + } + else + { + it_tank_mc++; + if (it_tank_mc == (*MCHits).end()) + loop_tank = false; + } + } + return; +} + +void ANNIEEventTreeMaker::LoadSiPMHits() +{ + Log("ANNIEEventTreeMaker Tool: LoadSiPMHits", v_debug, ANNIEEventTreeMakerVerbosity); + std::map>> aux_pulse_map; + m_data->Stores.at("ANNIEEvent")->Get("RecoADCAuxHits", aux_pulse_map); + fSiPM1NPulses = 0; + fSiPM2NPulses = 0; + for (const auto &temp_pair : aux_pulse_map) + { + const auto &channel_key = temp_pair.first; + // For now, only calibrate the SiPM waveforms + int sipm_number = -1; + if (AuxChannelNumToTypeMap->at(channel_key) == "SiPM1") + { + sipm_number = 1; + } + else if (AuxChannelNumToTypeMap->at(channel_key) == "SiPM2") + { + sipm_number = 2; + } + else + continue; + + std::vector> sipm_minibuffers = temp_pair.second; + size_t num_minibuffers = sipm_minibuffers.size(); // Should be size 1 in FrankDAQ mode + for (size_t mb = 0; mb < num_minibuffers; ++mb) + { + std::vector thisbuffer_pulses = sipm_minibuffers.at(mb); + if (sipm_number == 1) + fSiPM1NPulses += thisbuffer_pulses.size(); + if (sipm_number == 2) + fSiPM2NPulses += thisbuffer_pulses.size(); + for (size_t i = 0; i < thisbuffer_pulses.size(); i++) + { + ADCPulse apulse = thisbuffer_pulses.at(i); + fSiPMHitAmplitude.push_back(apulse.amplitude()); + fSiPMHitT.push_back(apulse.peak_time()); + fSiPMHitQ.push_back(apulse.charge()); + fSiPMNum.push_back(sipm_number); + } + } + } +} + +void ANNIEEventTreeMaker::LoadLAPPDInfo() +{ + m_data->Stores["ANNIEEvent"]->Get("LAPPDDataMap", LAPPDDataMap); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStampsRaw", LAPPDTimeStampsRaw); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgatesRaw", LAPPDBeamgatesRaw); + m_data->Stores["ANNIEEvent"]->Get("LAPPDOffsets", LAPPDOffsets); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTSCorrection", LAPPDTSCorrection); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBGCorrection", LAPPDBGCorrection); + m_data->Stores["ANNIEEvent"]->Get("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSBefore", LAPPDBG_PPSBefore); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSAfter", LAPPDBG_PPSAfter); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSDiff", LAPPDBG_PPSDiff); + m_data->Stores["ANNIEEvent"]->Get("LAPPDBG_PPSMissing", LAPPDBG_PPSMissing); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSBefore", LAPPDTS_PPSBefore); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSAfter", LAPPDTS_PPSAfter); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSDiff", LAPPDTS_PPSDiff); + m_data->Stores["ANNIEEvent"]->Get("LAPPDTS_PPSMissing", LAPPDTS_PPSMissing); + m_data->Stores["ANNIEEvent"]->Get("SwitchBitBG", SwitchBitBG); + + if (LAPPDDataMap.size() != 0) + { + FillLAPPDInfo(); + // print the content of fDataStreams, and the size of data map + // cout<<"Found LAPPDData, LAPPDDataMap Size: "<::iterator it = LAPPDDataMap.begin(); it != LAPPDDataMap.end(); ++it) + { + uint64_t key = it->first; + PsecData psecData = it->second; + fLAPPD_ID.push_back(psecData.LAPPD_ID); + fLAPPD_Beamgate_ns.push_back(LAPPDBeamgate_ns[key]); + fLAPPD_Timestamp_ns.push_back(LAPPDTimeStamps_ns[key]); + fLAPPD_Beamgate_Raw.push_back(LAPPDBeamgatesRaw[key]); + fLAPPD_Timestamp_Raw.push_back(LAPPDTimeStampsRaw[key]); + fLAPPD_Offset.push_back(LAPPDOffsets[key]); + fLAPPD_TSCorrection.push_back(LAPPDTSCorrection[key]); + fLAPPD_BGCorrection.push_back(LAPPDBGCorrection[key]); + fLAPPD_OSInMinusPS.push_back(LAPPDOSInMinusPS[key]); + fLAPPD_BGPPSBefore.push_back(LAPPDBG_PPSBefore[key]); + fLAPPD_BGPPSAfter.push_back(LAPPDBG_PPSAfter[key]); + fLAPPD_BGPPSDiff.push_back(LAPPDBG_PPSDiff[key]); + fLAPPD_BGPPSMissing.push_back(LAPPDBG_PPSMissing[key]); + fLAPPD_TSPPSBefore.push_back(LAPPDTS_PPSBefore[key]); + fLAPPD_TSPPSAfter.push_back(LAPPDTS_PPSAfter[key]); + fLAPPD_TSPPSDiff.push_back(LAPPDTS_PPSDiff[key]); + fLAPPD_TSPPSMissing.push_back(LAPPDTS_PPSMissing[key]); + // check if SwitchBitBG has the key + if (SwitchBitBG.find(psecData.LAPPD_ID) != SwitchBitBG.end()) + { + if (SwitchBitBG[psecData.LAPPD_ID].size() != 2) + { + cout << "ANNIEEventTreeMaker: SwitchBitBG size is not 2, LAPPD_ID: " << psecData.LAPPD_ID << ", size: " << SwitchBitBG[psecData.LAPPD_ID].size() << endl; + continue; + } + fLAPPD_BG_switchBit0.push_back(SwitchBitBG[psecData.LAPPD_ID][0]); + fLAPPD_BG_switchBit1.push_back(SwitchBitBG[psecData.LAPPD_ID][1]); + continue; + } + } +} + +void ANNIEEventTreeMaker::FillLAPPDPulse() +{ + bool gotPulse = m_data->Stores["ANNIEEvent"]->Get("LAPPDPulses", lappdPulses); + if (gotPulse) + { + + std::map>>::iterator it; + for (it = lappdPulses.begin(); it != lappdPulses.end(); it++) + { + int stripno = it->first; + vector> stripPulses = it->second; + + vector pulse0 = stripPulses.at(0); + vector pulse1 = stripPulses.at(1); + for (int i = 0; i < pulse0.size(); i++) + { + fPulseSide.push_back(0); + LAPPDPulse thisPulse = pulse0.at(i); + fLAPPD_IDs.push_back(thisPulse.GetTubeId()); + fChannelID.push_back(thisPulse.GetChannelID()); + fPulseStripNum.push_back(stripno); + fPulsePeakTime.push_back(thisPulse.GetTime()); + fPulseHalfHeightTime.push_back(thisPulse.GetHalfHeightTime()); + fPulseCharge.push_back(thisPulse.GetCharge()); + fPulsePeakAmp.push_back(thisPulse.GetPeak()); + fPulseStart.push_back(thisPulse.GetLowRange()); + fPulseEnd.push_back(thisPulse.GetHiRange()); + fPulseWidth.push_back(thisPulse.GetHiRange() - thisPulse.GetLowRange()); + } + for (int i = 0; i < pulse1.size(); i++) + { + fPulseSide.push_back(1); + LAPPDPulse thisPulse = pulse1.at(i); + fLAPPD_IDs.push_back(thisPulse.GetTubeId()); + fChannelID.push_back(thisPulse.GetChannelID()); + fPulseStripNum.push_back(stripno); + fPulsePeakTime.push_back(thisPulse.GetTime()); + fPulseHalfHeightTime.push_back(thisPulse.GetHalfHeightTime()); + fPulseCharge.push_back(thisPulse.GetCharge()); + fPulsePeakAmp.push_back(thisPulse.GetPeak()); + fPulseStart.push_back(thisPulse.GetLowRange()); + fPulseEnd.push_back(thisPulse.GetHiRange()); + fPulseWidth.push_back(thisPulse.GetHiRange() - thisPulse.GetLowRange()); + } + } + } +} + +void ANNIEEventTreeMaker::FillLAPPDHit() +{ + bool gotHit = m_data->Stores["ANNIEEvent"]->Get("LAPPDHits", lappdHits); + + if (gotHit) + { + std::map>::iterator it; + for (it = lappdHits.begin(); it != lappdHits.end(); it++) + { + int stripno = it->first; + vector stripHits = it->second; + for (int i = 0; i < stripHits.size(); i++) + { + LAPPDHit thisHit = stripHits.at(i); + LAPPDPulse p1 = thisHit.GetPulse1(); + LAPPDPulse p2 = thisHit.GetPulse2(); + fLAPPDHit_IDs.push_back(thisHit.GetTubeId()); + fLAPPDHitStrip.push_back(stripno); + fLAPPDHitTime.push_back(thisHit.GetTime()); + fLAPPDHitAmp.push_back(thisHit.GetCharge()); + vector position = thisHit.GetPosition(); + /* + XPosTank = position.at(0); + YPosTank = position.at(1); + ZPosTank = position.at(2);*/ + vector localPosition = thisHit.GetLocalPosition(); + fLAPPDHitParallelPos.push_back(localPosition.at(0)); + fLAPPDHitTransversePos.push_back(localPosition.at(1)); + // fLAPPDHitP1StartTime.push_back(thisHit.GetPulse1StartTime()); + // fLAPPDHitP2StartTime.push_back(thisHit.GetPulse2StartTime()); + // fLAPPDHitP1EndTime.push_back(thisHit.GetPulse1LastTime()); + // fLAPPDHitP2EndTime.push_back(thisHit.GetPulse2LastTime()); + // cout<<"Pulse 1 start time: "<> *m_all_clusters = nullptr; + std::map> *m_all_clusters_MC = nullptr; + std::map> *m_all_clusters_detkeys = nullptr; + + bool get_clusters = false; + if (isData) + { + get_clusters = m_data->CStore.Get("ClusterMap", m_all_clusters); + if (!get_clusters) + { + std::cout << "ANNIEEventTreeMaker tool: No clusters found!" << std::endl; + return false; + } + } + else + { + get_clusters = m_data->CStore.Get("ClusterMapMC", m_all_clusters_MC); + if (!get_clusters) + { + std::cout << "ANNIEEventTreeMaker tool: No clusters found (MC)!" << std::endl; + return false; + } + } + get_clusters = m_data->CStore.Get("ClusterMapDetkey", m_all_clusters_detkeys); + if (!get_clusters) + { + std::cout << "ANNIEEventTreeMaker tool: No cluster detkeys found!" << std::endl; + return false; + } + Log("ANNIEEventTreeMaker Tool: Accessing pairs in all_clusters map", v_debug, ANNIEEventTreeMakerVerbosity); + + int cluster_num = 0; + int cluster_size = 0; + if (isData) + cluster_size = (int)m_all_clusters->size(); + else + cluster_size = (int)m_all_clusters_MC->size(); + + std::map>::iterator it_cluster_pair; + std::map>::iterator it_cluster_pair_mc; + bool loop_map = true; + if (isData) + it_cluster_pair = (*m_all_clusters).begin(); + else + it_cluster_pair_mc = (*m_all_clusters_MC).begin(); + if (cluster_size == 0) + loop_map = false; + + fNumberOfClusters = cluster_size; + while (loop_map) + { + if (isData) + { + std::vector cluster_hits = it_cluster_pair->second; + double thisClusterTime = it_cluster_pair->first; + if (cluster_TankHitInfo_fill) + { + Log("ANNIEEventTreeMaker Tool: Loading tank cluster hits into cluster tree", v_debug, ANNIEEventTreeMakerVerbosity); + fClusterTimeV.push_back(thisClusterTime); + this->LoadTankClusterHits(cluster_hits); + } + + bool good_class = this->LoadTankClusterClassifiers(it_cluster_pair->first); + if (!good_class) + { + if (ANNIEEventTreeMakerVerbosity > 3) + Log("ANNIEEventTreeMaker Tool: No cluster classifiers. Continuing tree", v_debug, ANNIEEventTreeMakerVerbosity); + } + } + else + { + std::vector cluster_hits = it_cluster_pair_mc->second; + double thisClusterTime = it_cluster_pair_mc->first; + std::vector cluster_detkeys = m_all_clusters_detkeys->at(it_cluster_pair_mc->first); + if (cluster_TankHitInfo_fill) + { + Log("ANNIEEventTreeMaker Tool: Loading tank cluster hits into cluster tree", v_debug, ANNIEEventTreeMakerVerbosity); + fClusterTimeV.push_back(thisClusterTime); + this->LoadTankClusterHitsMC(cluster_hits, cluster_detkeys); + } + bool good_class = this->LoadTankClusterClassifiers(it_cluster_pair_mc->first); + if (!good_class) + { + if (ANNIEEventTreeMakerVerbosity > 3) + Log("ANNIEEventTreeMaker Tool: No cluster classifiers. Continuing tree", v_debug, ANNIEEventTreeMakerVerbosity); + } + } + + if (isData) + { + it_cluster_pair++; + if (it_cluster_pair == (*m_all_clusters).end()) + loop_map = false; + } + else + { + it_cluster_pair_mc++; + if (it_cluster_pair_mc == (*m_all_clusters_MC).end()) + loop_map = false; + } + } + + return true; +} + +void ANNIEEventTreeMaker::LoadTankClusterHits(std::vector cluster_hits) +{ + Position detector_center = geom->GetTankCentre(); + double tank_center_x = detector_center.X(); + double tank_center_y = detector_center.Y(); + double tank_center_z = detector_center.Z(); + + double ClusterCharge = 0; + double ClusterPE = 0; + int ClusterHitNum = 0; + vector HitXV; + vector HitYV; + vector HitZV; + vector HitTV; + vector HitQV; + vector HitPEV; + vector HitTypeV; + vector HitDetIDV; + vector HitChankeyV; + vector HitCKMC; + + for (int i = 0; i < (int)cluster_hits.size(); i++) + { + int channel_key = cluster_hits.at(i).GetTubeId(); + std::map::iterator it = ChannelKeyToSPEMap.find(channel_key); + if (it != ChannelKeyToSPEMap.end()) + { // Charge to SPE conversion is available + Detector *this_detector = geom->ChannelToDetector(channel_key); + unsigned long detkey = this_detector->GetDetectorID(); + Position det_position = this_detector->GetDetectorPosition(); + double hit_charge = cluster_hits.at(i).GetCharge(); + double hit_PE = hit_charge / ChannelKeyToSPEMap.at(channel_key); + HitXV.push_back((det_position.X() - tank_center_x)); + HitYV.push_back((det_position.Y() - tank_center_y)); + HitZV.push_back((det_position.Z() - tank_center_z)); + HitQV.push_back(hit_charge); + HitPEV.push_back(hit_PE); + HitTV.push_back(cluster_hits.at(i).GetTime()); + HitDetIDV.push_back(detkey); + + HitChankeyV.push_back(channel_key); + HitCKMC.push_back(channel_key); + HitTypeV.push_back(RecoDigit::PMT8inch); + ClusterCharge += hit_charge; + ClusterPE += hit_PE; + ClusterHitNum += 1; + } + else + { + if (ANNIEEventTreeMakerVerbosity > 4) + { + std::cout << "FOUND A HIT FOR CHANNELKEY " << channel_key << "BUT NO CONVERSION " << "TO PE AVAILABLE. SKIPPING PE." << std::endl; + } + } + } + fClusterHits.push_back(ClusterHitNum); + fClusterChargeV.push_back(ClusterCharge); + fClusterPEV.push_back(ClusterPE); + + fCluster_HitX.push_back(HitXV); + fCluster_HitY.push_back(HitYV); + fCluster_HitZ.push_back(HitZV); + fCluster_HitT.push_back(HitTV); + fCluster_HitQ.push_back(HitQV); + fCluster_HitPE.push_back(HitPEV); + fCluster_HitType.push_back(HitTypeV); + fCluster_HitDetID.push_back(HitDetIDV); + fCluster_HitChankey.push_back(HitChankeyV); + fCluster_HitChankeyMC.push_back(HitCKMC); + + return; +} + +void ANNIEEventTreeMaker::LoadTankClusterHitsMC(std::vector cluster_hits, std::vector cluster_detkeys) +{ + Position detector_center = geom->GetTankCentre(); + double tank_center_x = detector_center.X(); + double tank_center_y = detector_center.Y(); + double tank_center_z = detector_center.Z(); + + double ClusterCharge = 0; + double ClusterPE = 0; + int ClusterHitNum = 0; + vector HitXV; + vector HitYV; + vector HitZV; + vector HitTV; + vector HitQV; + vector HitPEV; + vector HitTypeV; + vector HitDetIDV; + vector HitChankeyV; + vector HitCKMC; + + for (int i = 0; i < (int)cluster_hits.size(); i++) + { + unsigned long detkey = cluster_detkeys.at(i); + int channel_key = (int)detkey; + int tubeid = cluster_hits.at(i).GetTubeId(); + unsigned long utubeid = (unsigned long)tubeid; + int wcsimid = channelkey_to_pmtid.at(utubeid); + unsigned long detkey_data = pmtid_to_channelkey[wcsimid]; + int channel_key_data = (int)detkey_data; + std::map::iterator it = ChannelKeyToSPEMap.find(channel_key_data); + if (it != ChannelKeyToSPEMap.end()) + { // Charge to SPE conversion is available + Detector *this_detector = geom->ChannelToDetector(tubeid); + Position det_position = this_detector->GetDetectorPosition(); + unsigned long detkey = this_detector->GetDetectorID(); + double hit_PE = cluster_hits.at(i).GetCharge(); + double hit_charge = hit_PE * ChannelKeyToSPEMap.at(channel_key_data); + HitXV.push_back((det_position.X() - tank_center_x)); + HitYV.push_back((det_position.Y() - tank_center_y)); + HitZV.push_back((det_position.Z() - tank_center_z)); + HitQV.push_back(hit_charge); + HitPEV.push_back(hit_PE); + HitTV.push_back(cluster_hits.at(i).GetTime()); + HitDetIDV.push_back(detkey); + HitChankeyV.push_back(channel_key_data); + HitCKMC.push_back(channel_key); + HitTypeV.push_back(RecoDigit::PMT8inch); + ClusterCharge += hit_charge; + ClusterPE += hit_PE; + ClusterHitNum += 1; + } + else + { + if (ANNIEEventTreeMakerVerbosity > 4) + { + std::cout << "FOUND A HIT FOR CHANNELKEY " << channel_key_data << "(MC detkey: " << channel_key << ", chankey = " << utubeid << ", wcsimid = " << wcsimid << ") BUT NO CONVERSION " << "TO PE AVAILABLE. SKIPPING PE." << std::endl; + } + } + } + fClusterHits.push_back(ClusterHitNum); + fClusterChargeV.push_back(ClusterCharge); + fClusterPEV.push_back(ClusterPE); + + fCluster_HitX.push_back(HitXV); + fCluster_HitY.push_back(HitYV); + fCluster_HitZ.push_back(HitZV); + fCluster_HitT.push_back(HitTV); + fCluster_HitQ.push_back(HitQV); + fCluster_HitPE.push_back(HitPEV); + fCluster_HitType.push_back(HitTypeV); + fCluster_HitDetID.push_back(HitDetIDV); + fCluster_HitChankey.push_back(HitChankeyV); + fCluster_HitChankeyMC.push_back(HitCKMC); + + return; +} + +bool ANNIEEventTreeMaker::LoadTankClusterClassifiers(double cluster_time) +{ + // Save classifiers to ANNIEEvent + Log("PhaseITreeMaker tool: Getting cluster classifiers", v_debug, ANNIEEventTreeMakerVerbosity); + std::map ClusterMaxPEs; + std::map ClusterChargePoints; + std::map ClusterChargeBalances; + + bool got_ccp = m_data->Stores.at("ANNIEEvent")->Get("ClusterChargePoints", ClusterChargePoints); + bool got_ccb = m_data->Stores.at("ANNIEEvent")->Get("ClusterChargeBalances", ClusterChargeBalances); + bool got_cmpe = m_data->Stores.at("ANNIEEvent")->Get("ClusterMaxPEs", ClusterMaxPEs); + bool good_classifiers = got_ccp && got_ccb && got_cmpe; + if (!good_classifiers) + { + Log("PhaseITreeMaker tool: One of the charge cluster classifiers is not available", v_debug, ANNIEEventTreeMakerVerbosity); + } + else + { + Log("PhaseITreeMaker tool: Setting fCluster variables to classifier parameters", v_debug, ANNIEEventTreeMakerVerbosity); + fClusterMaxPEV.push_back(ClusterMaxPEs.at(cluster_time)); + Position ClusterChargePoint = ClusterChargePoints.at(cluster_time); + fClusterChargePointXV.push_back(ClusterChargePoint.X()); + fClusterChargePointYV.push_back(ClusterChargePoint.Y()); + fClusterChargePointZV.push_back(ClusterChargePoint.Z()); + fClusterChargeBalanceV.push_back(ClusterChargeBalances.at(cluster_time)); + } + return good_classifiers; +} + +void ANNIEEventTreeMaker::LoadMRDCluster() +{ + std::vector mrddigittimesthisevent; + std::vector mrddigitchargesthisevent; + ; + std::vector mrddigitpmtsthisevent; + std::vector mrddigitchankeysthisevent; + std::vector> MrdTimeClusters; + + bool get_clusters = m_data->CStore.Get("MrdTimeClusters", MrdTimeClusters); + if (!get_clusters) + { + std::cout << "ANNIEEventTreeMaker tool: No MRD clusters found! Did you run the TimeClustering tool?" << std::endl; + return; + } + + int num_mrd_clusters; + m_data->CStore.Get("NumMrdTimeClusters", num_mrd_clusters); + + if (num_mrd_clusters > 0) + { + m_data->CStore.Get("MrdDigitTimes", mrddigittimesthisevent); + m_data->CStore.Get("MrdDigitPmts", mrddigitpmtsthisevent); + m_data->CStore.Get("MrdDigitChankeys", mrddigitchankeysthisevent); + m_data->CStore.Get("MrdDigitCharges", mrddigitchargesthisevent); + m_data->CStore.Get("MrdDigitPmts", mrddigitpmtsthisevent); + } + + std::map> *TDCData = nullptr; + std::map> *TDCData_MC = nullptr; + + int TrigHasVetoHit = 0; + bool has_tdc = false; + if (isData) + has_tdc = m_data->Stores["ANNIEEvent"]->Get("TDCData", TDCData); // a std::map> + else + has_tdc = m_data->Stores["ANNIEEvent"]->Get("TDCData", TDCData_MC); + if (!has_tdc) + { + std::cout << "No TDCData store in ANNIEEvent." << std::endl; + } + + int cluster_num = 0; + for (int i = 0; i < (int)MrdTimeClusters.size(); i++) + { + int tdcdata_size = (isData) ? TDCData->size() : TDCData_MC->size(); + int fMRDClusterHits = 0; + if (has_tdc && tdcdata_size > 0) + { + Log("ANNIEEventTreeMaker tool: Looping over FACC/MRD hits... looking for Veto activity", v_debug, ANNIEEventTreeMakerVerbosity); + if (isData) + { + for (auto &&anmrdpmt : (*TDCData)) + { + unsigned long chankey = anmrdpmt.first; + std::vector mrdhits = anmrdpmt.second; + Detector *thedetector = geom->ChannelToDetector(chankey); + unsigned long detkey = thedetector->GetDetectorID(); + if (thedetector->GetDetectorElement() == "Veto") + { + TrigHasVetoHit = 1; // this is a veto hit, not an MRD hit. + for (int j = 0; j < (int)mrdhits.size(); j++) + { + fFMVHitT.push_back(mrdhits.at(j).GetTime()); + fFMVHitDetID.push_back(detkey); + fFMVHitChankey.push_back(chankey); + fFMVHitChankeyMC.push_back(chankey); + } + } + } + } + else + { + for (auto &&anmrdpmt : (*TDCData_MC)) + { + unsigned long chankey = anmrdpmt.first; + Detector *thedetector = geom->ChannelToDetector(chankey); + unsigned long detkey = thedetector->GetDetectorID(); + if (thedetector->GetDetectorElement() == "Veto") + { + TrigHasVetoHit = 1; // this is a veto hit, not an MRD hit. + int wcsimid = channelkey_to_faccpmtid.at(chankey) - 1; + unsigned long chankey_data = wcsimid; + std::vector mrdhits = anmrdpmt.second; + for (int j = 0; j < (int)mrdhits.size(); j++) + { + fFMVHitT.push_back(mrdhits.at(j).GetTime()); + fFMVHitDetID.push_back(detkey); + fFMVHitChankey.push_back(chankey_data); + fFMVHitChankeyMC.push_back(chankey); + } + } + } + } + } + + fVetoHit = TrigHasVetoHit; + std::vector ThisClusterIndices = MrdTimeClusters.at(i); + for (int j = 0; j < (int)ThisClusterIndices.size(); j++) + { + Detector *thedetector = geom->ChannelToDetector(mrddigitchankeysthisevent.at(ThisClusterIndices.at(j))); + unsigned long detkey = thedetector->GetDetectorID(); + + fMRDHitT.push_back(mrddigittimesthisevent.at(ThisClusterIndices.at(j))); + fMRDHitClusterIndex.push_back(i); + fMRDHitCharge.push_back(mrddigitchargesthisevent.at(ThisClusterIndices.at(j))); + fMRDHitDigitPMT.push_back(mrddigitpmtsthisevent.at(ThisClusterIndices.at(j))); + fMRDHitDetID.push_back(detkey); + if (isData) + fMRDHitChankey.push_back(mrddigitchankeysthisevent.at(ThisClusterIndices.at(j))); + else + { + int wcsimid = channelkey_to_mrdpmtid.at(mrddigitchankeysthisevent.at(ThisClusterIndices.at(j))) - 1; + unsigned long chankey_data = mrdpmtid_to_channelkey_data[wcsimid]; + fMRDHitChankey.push_back(chankey_data); + } + fMRDHitChankeyMC.push_back(mrddigitchankeysthisevent.at(ThisClusterIndices.at(j))); + fMRDClusterHits += 1; + } + + double MRDThisClusterTime = 0; + double MRDThisClusterTimeSigma = 0; + ComputeMeanAndVariance(fMRDHitT, MRDThisClusterTime, MRDThisClusterTimeSigma); + // FIXME: calculate fMRDClusterTime + + // Standard run level information + Log("ANNIEEventTreeMaker Tool: MRD cluster, Getting run level information from ANNIEEvent", v_debug, ANNIEEventTreeMakerVerbosity); + + if (MRDReco_fill) + { + int ThisMRDClusterTrackNum = this->LoadMRDTrackReco(i); + fNumClusterTracks.push_back(ThisMRDClusterTrackNum); + // Get the track info + } + cluster_num++; + + fMRDClusterHitNumber.push_back(fMRDClusterHits); + fMRDClusterTime.push_back(MRDThisClusterTime); + fMRDClusterTimeSigma.push_back(MRDThisClusterTimeSigma); + } + fMRDClusterNumber = cluster_num; + Log("ANNIEEventTreeMaker Tool: MRD cluster, Finished loading MRD cluster info", v_debug, ANNIEEventTreeMakerVerbosity); +} + +int ANNIEEventTreeMaker::LoadMRDTrackReco(int SubEventID) +{ + std::vector *theMrdTracks; // the reconstructed tracks + int numtracksinev; + + // Check for valid track criteria + m_data->Stores["MRDTracks"]->Get("MRDTracks", theMrdTracks); + m_data->Stores["MRDTracks"]->Get("NumMrdTracks", numtracksinev); + // Loop over reconstructed tracks + + Position StartVertex; + Position StopVertex; + double TrackLength = -9999; + double TrackAngle = -9999; + double TrackAngleError = -9999; + double PenetrationDepth = -9999; + Position MrdEntryPoint; + double EnergyLoss = -9999; // in MeV + double EnergyLossError = -9999; + double EntryPointRadius = -9999; + bool IsMrdPenetrating; + bool IsMrdStopped; + bool IsMrdSideExit; + + int NumClusterTracks = 0; + for (int tracki = 0; tracki < numtracksinev; tracki++) + { + BoostStore *thisTrackAsBoostStore = &(theMrdTracks->at(tracki)); + int TrackEventID = -1; + // get track properties that are needed for the through-going muon selection + thisTrackAsBoostStore->Get("MrdSubEventID", TrackEventID); + if (TrackEventID != SubEventID) + continue; + + // If we're here, this track is associated with this cluster + thisTrackAsBoostStore->Get("StartVertex", StartVertex); + thisTrackAsBoostStore->Get("StopVertex", StopVertex); + thisTrackAsBoostStore->Get("TrackAngle", TrackAngle); + thisTrackAsBoostStore->Get("TrackAngleError", TrackAngleError); + thisTrackAsBoostStore->Get("PenetrationDepth", PenetrationDepth); + thisTrackAsBoostStore->Get("MrdEntryPoint", MrdEntryPoint); + thisTrackAsBoostStore->Get("EnergyLoss", EnergyLoss); + thisTrackAsBoostStore->Get("EnergyLossError", EnergyLossError); + thisTrackAsBoostStore->Get("IsMrdPenetrating", IsMrdPenetrating); // bool + thisTrackAsBoostStore->Get("IsMrdStopped", IsMrdStopped); // bool + thisTrackAsBoostStore->Get("IsMrdSideExit", IsMrdSideExit); + TrackLength = sqrt(pow((StopVertex.X() - StartVertex.X()), 2) + pow(StopVertex.Y() - StartVertex.Y(), 2) + pow(StopVertex.Z() - StartVertex.Z(), 2)) * 100.0; + EntryPointRadius = sqrt(pow(MrdEntryPoint.X(), 2) + pow(MrdEntryPoint.Y(), 2)) * 100.0; // convert to cm + PenetrationDepth = PenetrationDepth * 100.0; + + // Push back some properties + fMRDTrackAngle.push_back(TrackAngle); + fMRDTrackAngleError.push_back(TrackAngleError); + fMRDTrackLength.push_back(TrackLength); + fMRDPenetrationDepth.push_back(PenetrationDepth); + fMRDEntryPointRadius.push_back(EntryPointRadius); + fMRDEnergyLoss.push_back(EnergyLoss); + fMRDEnergyLossError.push_back(EnergyLossError); + fMRDTrackStartX.push_back(StartVertex.X()); + fMRDTrackStartY.push_back(StartVertex.Y()); + fMRDTrackStartZ.push_back(StartVertex.Z()); + fMRDTrackStopX.push_back(StopVertex.X()); + fMRDTrackStopY.push_back(StopVertex.Y()); + fMRDTrackStopZ.push_back(StopVertex.Z()); + fMRDStop.push_back(IsMrdStopped); + fMRDSide.push_back(IsMrdSideExit); + fMRDThrough.push_back(IsMrdPenetrating); + NumClusterTracks += 1; + fMRDClusterIndex.push_back(SubEventID); + } + return NumClusterTracks; +} + +// MC and tank reco information below + +bool ANNIEEventTreeMaker::FillTankRecoInfo() +{ + bool got_reco_info = true; + auto *reco_event = m_data->Stores["RecoEvent"]; + if (!reco_event) + { + Log("Error: The PhaseITreeMaker tool could not find the RecoEvent Store", v_error, ANNIEEventTreeMakerVerbosity); + got_reco_info = false; + } + // Read reconstructed Vertex + RecoVertex *recovtx = 0; + auto get_extendedvtx = m_data->Stores.at("RecoEvent")->Get("ExtendedVertex", recovtx); + if (!get_extendedvtx) + { + Log("Warning: The PhaseITreeMaker tool could not find ExtendedVertex. Continuing to build tree", v_message, ANNIEEventTreeMakerVerbosity); + got_reco_info = false; + } + else + { + fRecoVtxX = recovtx->GetPosition().X(); + fRecoVtxY = recovtx->GetPosition().Y(); + fRecoVtxZ = recovtx->GetPosition().Z(); + fRecoVtxTime = recovtx->GetTime(); + fRecoVtxFOM = recovtx->GetFOM(); + fRecoDirX = recovtx->GetDirection().X(); + fRecoDirY = recovtx->GetDirection().Y(); + fRecoDirZ = recovtx->GetDirection().Z(); + fRecoAngle = TMath::ACos(fRecoDirZ); + if (fRecoDirX > 0.0) + { + fRecoPhi = atan(fRecoDirY / fRecoDirX); + } + if (fRecoDirX < 0.0) + { + fRecoPhi = atan(fRecoDirY / fRecoDirX); + if (fRecoDirY > 0.0) + fRecoPhi += TMath::Pi(); + if (fRecoDirY <= 0.0) + fRecoPhi -= TMath::Pi(); + } + if (fRecoDirX == 0.0) + { + if (fRecoDirY > 0.0) + fRecoPhi = 0.5 * TMath::Pi(); + else if (fRecoDirY < 0.0) + fRecoPhi = -0.5 * TMath::Pi(); + else + fRecoPhi = 0; + } + fRecoStatus = recovtx->GetStatus(); + } + return got_reco_info; +} + +void ANNIEEventTreeMaker::FillRecoDebugInfo() +{ + // Read Seed candidates + std::vector *seedvtxlist = 0; + auto get_seedvtxlist = m_data->Stores.at("RecoEvent")->Get("vSeedVtxList", seedvtxlist); ///> Get List of seeds from "RecoEvent" + if (get_seedvtxlist) + { + for (auto &seed : *seedvtxlist) + { + fSeedVtxX.push_back(seed.GetPosition().X()); + fSeedVtxY.push_back(seed.GetPosition().Y()); + fSeedVtxZ.push_back(seed.GetPosition().Z()); + fSeedVtxTime = seed.GetTime(); + } + } + else + { + Log("ANNIEEventTreeMaker Tool: No Seed List found. Continuing to build tree ", v_message, ANNIEEventTreeMakerVerbosity); + } + std::vector *seedfomlist = 0; + auto get_seedfomlist = m_data->Stores.at("RecoEvent")->Get("vSeedFOMList", seedfomlist); ///> Get List of seed FOMs from "RecoEvent" + if (get_seedfomlist) + { + for (auto &seedFOM : *seedfomlist) + { + fSeedVtxFOM.push_back(seedFOM); + } + } + else + { + Log("ANNIEEventTreeMaker Tool: No Seed FOM List found. Continuing to build tree ", v_message, ANNIEEventTreeMakerVerbosity); + } + + // Read PointPosition-fitted Vertex + RecoVertex *pointposvtx = 0; + auto get_pointposdata = m_data->Stores.at("RecoEvent")->Get("PointPosition", pointposvtx); + if (get_pointposdata) + { + fPointPosX = pointposvtx->GetPosition().X(); + fPointPosY = pointposvtx->GetPosition().Y(); + fPointPosZ = pointposvtx->GetPosition().Z(); + fPointPosTime = pointposvtx->GetTime(); + fPointPosFOM = pointposvtx->GetFOM(); + fPointPosStatus = pointposvtx->GetStatus(); + } + else + { + Log("ANNIEEventTreeMaker Tool: No PointPosition Tool data found. Continuing to build remaining tree", v_message, ANNIEEventTreeMakerVerbosity); + } + + // Read PointDirection-fitted Vertex + RecoVertex *pointdirvtx = 0; + auto get_pointdirdata = m_data->Stores.at("RecoEvent")->Get("PointDirection", pointdirvtx); + if (get_pointdirdata) + { + fPointDirX = pointdirvtx->GetDirection().X(); + fPointDirY = pointdirvtx->GetDirection().Y(); + fPointDirZ = pointdirvtx->GetDirection().Z(); + fPointDirTime = pointdirvtx->GetTime(); + fPointDirFOM = pointdirvtx->GetFOM(); + fPointDirStatus = pointdirvtx->GetStatus(); + } + else + { + Log("ANNIEEventTreeMaker Tool: No PointDirection Tool data found. Continuing to build remaining tree", v_message, ANNIEEventTreeMakerVerbosity); + } + + // Read PointVertex Tool's fitted Vertex + RecoVertex *pointvtx = 0; + auto get_pointvtxdata = m_data->Stores.at("RecoEvent")->Get("PointVertex", pointvtx); + if (get_pointvtxdata) + { + fPointVtxPosX = pointvtx->GetPosition().X(); + fPointVtxPosY = pointvtx->GetPosition().Y(); + fPointVtxPosZ = pointvtx->GetPosition().Z(); + fPointVtxDirX = pointvtx->GetDirection().X(); + fPointVtxDirY = pointvtx->GetDirection().Y(); + fPointVtxDirZ = pointvtx->GetDirection().Z(); + fPointVtxTime = pointvtx->GetTime(); + fPointVtxFOM = pointvtx->GetFOM(); + fPointVtxStatus = pointvtx->GetStatus(); + } + else + { + Log("ANNIEEventTreeMaker Tool: No PointVertex Tool data found. Continuing to build remaining tree", v_message, ANNIEEventTreeMakerVerbosity); + } +} + +bool ANNIEEventTreeMaker::FillMCTruthInfo() +{ + bool successful_load = true; + // MC entry number + m_data->Stores.at("ANNIEEvent")->Get("MCEventNum", fMCEventNum); + // MC trigger number + m_data->Stores.at("ANNIEEvent")->Get("MCTriggernum", fMCTriggerNum); + std::string logmessage = " Retriving information for MCEntry " + to_string(fMCEventNum) + + ", MCTrigger " + to_string(fMCTriggerNum) + ", EventNumber " + to_string(fEventNumber); + Log(logmessage, v_message, ANNIEEventTreeMakerVerbosity); + + fiMCTriggerNum = (int)fMCTriggerNum; + + std::map> MCNeutCap; + bool get_neutcap = m_data->Stores.at("ANNIEEvent")->Get("MCNeutCap", MCNeutCap); + if (!get_neutcap) + { + Log("ANNIEEventTreeMaker: Did not find MCNeutCap in ANNIEEvent Store!", v_warning, ANNIEEventTreeMakerVerbosity); + } + std::map>> MCNeutCapGammas; + bool get_neutcap_gammas = m_data->Stores.at("ANNIEEvent")->Get("MCNeutCapGammas", MCNeutCapGammas); + if (!get_neutcap_gammas) + { + Log("ANNIEEventTreeMaker: Did not find MCNeutCapGammas in ANNIEEvent Store!", v_warning, ANNIEEventTreeMakerVerbosity); + } + + for (std::map>>::iterator it = MCNeutCapGammas.begin(); it != MCNeutCapGammas.end(); it++) + { + std::vector> mcneutgammas = it->second; + for (int i_cap = 0; i_cap < (int)mcneutgammas.size(); i_cap++) + { + std::vector capgammas = mcneutgammas.at(i_cap); + if (ANNIEEventTreeMakerVerbosity > 1) + { + for (int i_gamma = 0; i_gamma < (int)capgammas.size(); i_gamma++) + { + std::cout << "gamma # " << i_gamma << ", energy: " << capgammas.at(i_gamma) << std::endl; + } + } + } + } + + RecoVertex *truevtx = 0; + auto get_muonMC = m_data->Stores.at("RecoEvent")->Get("TrueVertex", truevtx); + auto get_muonMCEnergy = m_data->Stores.at("RecoEvent")->Get("TrueMuonEnergy", fTrueMuonEnergy); + auto get_pdg = m_data->Stores.at("RecoEvent")->Get("PdgPrimary", fTruePrimaryPdg); + if (get_muonMC && get_muonMCEnergy) + { + fTrueVtxX = truevtx->GetPosition().X(); + fTrueVtxY = truevtx->GetPosition().Y(); + fTrueVtxZ = truevtx->GetPosition().Z(); + fTrueVtxTime = truevtx->GetTime(); + fTrueDirX = truevtx->GetDirection().X(); + fTrueDirY = truevtx->GetDirection().Y(); + fTrueDirZ = truevtx->GetDirection().Z(); + double TrueAngRad = TMath::ACos(fTrueDirZ); + fTrueAngle = TrueAngRad / (TMath::Pi() / 180.0); // radians->degrees + if (fTrueDirX > 0.0) + { + fTruePhi = atan(fTrueDirY / fTrueDirX); + } + if (fTrueDirX < 0.0) + { + fTruePhi = atan(fTrueDirY / fTrueDirX); + if (fTrueDirY > 0.0) + fTruePhi += TMath::Pi(); + if (fTrueDirY <= 0.0) + fTruePhi -= TMath::Pi(); + } + if (fTrueDirX == 0.0) + { + if (fTrueDirY > 0.0) + fTruePhi = 0.5 * TMath::Pi(); + else if (fTrueDirY < 0.0) + fTruePhi = -0.5 * TMath::Pi(); + else + fTruePhi = 0; + } + } + else + { + Log("ANNIEEventTreeMaker Tool: Missing MC Energy/Vertex info; is this MC? Continuing to build remaining tree", v_message, ANNIEEventTreeMakerVerbosity); + successful_load = false; + } + double waterT, MRDT; + auto get_tankTrackLength = m_data->Stores.at("RecoEvent")->Get("TrueTrackLengthInWater", waterT); + auto get_MRDTrackLength = m_data->Stores.at("RecoEvent")->Get("TrueTrackLengthInMRD", MRDT); + if (get_tankTrackLength && get_MRDTrackLength) + { + fTrueTrackLengthInWater = waterT; + fTrueTrackLengthInMRD = MRDT; + } + else + { + Log("ANNIEEventTreeMaker Tool: True track lengths missing. Continuing to build tree", v_message, ANNIEEventTreeMakerVerbosity); + successful_load = false; + } + + bool IsMultiRing = false; + bool get_multi = m_data->Stores.at("RecoEvent")->Get("MCMultiRingEvent", IsMultiRing); + if (get_multi) + { + fTrueMultiRing = (IsMultiRing) ? 1 : 0; + } + else + { + Log("ANNIEEventTreeMaker Tool: True Multi Ring information missing. Continuing to build tree", v_message, ANNIEEventTreeMakerVerbosity); + successful_load = false; + } + + std::vector primary_pdgs; + bool has_primaries = m_data->Stores.at("RecoEvent")->Get("PrimaryPdgs", primary_pdgs); + if (has_primaries) + { + for (int i_part = 0; i_part < (int)primary_pdgs.size(); i_part++) + { + fTruePrimaryPdgs->push_back(primary_pdgs.at(i_part)); + } + } + else + { + Log("ANNIEEventTreeMaker Tool: Primary Pdgs information missing. Continuing to build tree", v_message, ANNIEEventTreeMakerVerbosity); + successful_load = false; + } + + int pi0count, pipcount, pimcount, K0count, Kpcount, Kmcount; + auto get_pi0 = m_data->Stores.at("RecoEvent")->Get("MCPi0Count", pi0count); + auto get_pim = m_data->Stores.at("RecoEvent")->Get("MCPiMinusCount", pimcount); + auto get_pip = m_data->Stores.at("RecoEvent")->Get("MCPiPlusCount", pipcount); + auto get_k0 = m_data->Stores.at("RecoEvent")->Get("MCK0Count", K0count); + auto get_km = m_data->Stores.at("RecoEvent")->Get("MCKMinusCount", Kmcount); + auto get_kp = m_data->Stores.at("RecoEvent")->Get("MCKPlusCount", Kpcount); + if (get_pi0 && get_pim && get_pip && get_k0 && get_km && get_kp) + { + // set values in tree to thouse grabbed from the RecoEvent Store + fPi0Count = pi0count; + fPiPlusCount = pipcount; + fPiMinusCount = pimcount; + fK0Count = K0count; + fKPlusCount = Kpcount; + fKMinusCount = Kmcount; + } + else + { + Log("ANNIEEventTreeMaker Tool: Missing MC Pion/Kaon count information. Continuing to build remaining tree", v_message, ANNIEEventTreeMakerVerbosity); + successful_load = false; + } + + if (MCNeutCap.count("CaptVtxX") > 0) + { + std::vector n_vtxx = MCNeutCap["CaptVtxX"]; + std::vector n_vtxy = MCNeutCap["CaptVtxY"]; + std::vector n_vtxz = MCNeutCap["CaptVtxZ"]; + std::vector n_parent = MCNeutCap["CaptParent"]; + std::vector n_ngamma = MCNeutCap["CaptNGamma"]; + std::vector n_totale = MCNeutCap["CaptTotalE"]; + std::vector n_time = MCNeutCap["CaptTime"]; + std::vector n_nuc = MCNeutCap["CaptNucleus"]; + + for (int i_cap = 0; i_cap < (int)n_vtxx.size(); i_cap++) + { + fTrueNeutCapVtxX->push_back(n_vtxx.at(i_cap)); + fTrueNeutCapVtxY->push_back(n_vtxy.at(i_cap)); + fTrueNeutCapVtxZ->push_back(n_vtxz.at(i_cap)); + fTrueNeutCapNucleus->push_back(n_nuc.at(i_cap)); + fTrueNeutCapTime->push_back(n_time.at(i_cap)); + fTrueNeutCapGammas->push_back(n_ngamma.at(i_cap)); + fTrueNeutCapE->push_back(n_totale.at(i_cap)); + } + } + + if (ANNIEEventTreeMakerVerbosity > 1) + std::cout << "MCNeutCapGammas count CaptGammas: " << MCNeutCapGammas.count("CaptGammas") << std::endl; + if (MCNeutCapGammas.count("CaptGammas") > 0) + { + std::vector> cap_energies = MCNeutCapGammas["CaptGammas"]; + if (ANNIEEventTreeMakerVerbosity > 1) + std::cout << "cap_energies size: " << cap_energies.size() << std::endl; + for (int i_cap = 0; i_cap < (int)cap_energies.size(); i_cap++) + { + for (int i_gamma = 0; i_gamma < cap_energies.at(i_cap).size(); i_gamma++) + { + if (ANNIEEventTreeMakerVerbosity > 1) + std::cout << "gamma energy: " << cap_energies.at(i_cap).at(i_gamma) << std::endl; + fTrueNeutCapGammaE->push_back(cap_energies.at(i_cap).at(i_gamma)); + } + } + } + + // Load genie information + if (hasGenie) + { + double TrueNeutrinoEnergy, TrueQ2, TrueNuIntxVtx_X, TrueNuIntxVtx_Y, TrueNuIntxVtx_Z, TrueNuIntxVtx_T; + double TrueFSLeptonMass, TrueFSLeptonEnergy, TrueFSLeptonTime; + bool TrueCC, TrueNC, TrueQEL, TrueDIS, TrueCOH, TrueMEC, TrueRES; + int fsNeutrons, fsProtons, fsPi0, fsPiPlus, fsPiPlusCher, fsPiMinus, fsPiMinusCher; + int fsKPlus, fsKPlusCher, fsKMinus, fsKMinusCher, TrueNuPDG, TrueFSLeptonPdg; + Position TrueFSLeptonVtx; + Direction TrueFSLeptonMomentum; + Direction TrueNeutrinoMomentum; + bool get_neutrino_energy = m_data->Stores["GenieInfo"]->Get("NeutrinoEnergy", TrueNeutrinoEnergy); + bool get_neutrino_mom = m_data->Stores["GenieInfo"]->Get("NeutrinoMomentum", TrueNeutrinoMomentum); + bool get_neutrino_vtxx = m_data->Stores["GenieInfo"]->Get("NuIntxVtx_X", TrueNuIntxVtx_X); + bool get_neutrino_vtxy = m_data->Stores["GenieInfo"]->Get("NuIntxVtx_Y", TrueNuIntxVtx_Y); + bool get_neutrino_vtxz = m_data->Stores["GenieInfo"]->Get("NuIntxVtx_Z", TrueNuIntxVtx_Z); + bool get_neutrino_vtxt = m_data->Stores["GenieInfo"]->Get("NuIntxVtx_T", TrueNuIntxVtx_T); + bool get_q2 = m_data->Stores["GenieInfo"]->Get("EventQ2", TrueQ2); + bool get_cc = m_data->Stores["GenieInfo"]->Get("IsWeakCC", TrueCC); + bool get_nc = m_data->Stores["GenieInfo"]->Get("IsWeakNC", TrueNC); + bool get_qel = m_data->Stores["GenieInfo"]->Get("IsQuasiElastic", TrueQEL); + bool get_res = m_data->Stores["GenieInfo"]->Get("IsResonant", TrueRES); + bool get_dis = m_data->Stores["GenieInfo"]->Get("IsDeepInelastic", TrueDIS); + bool get_coh = m_data->Stores["GenieInfo"]->Get("IsCoherent", TrueCOH); + bool get_mec = m_data->Stores["GenieInfo"]->Get("IsMEC", TrueMEC); + bool get_n = m_data->Stores["GenieInfo"]->Get("NumFSNeutrons", fsNeutrons); + bool get_p = m_data->Stores["GenieInfo"]->Get("NumFSProtons", fsProtons); + bool get_pi0 = m_data->Stores["GenieInfo"]->Get("NumFSPi0", fsPi0); + bool get_piplus = m_data->Stores["GenieInfo"]->Get("NumFSPiPlus", fsPiPlus); + bool get_pipluscher = m_data->Stores["GenieInfo"]->Get("NumFSPiPlusCher", fsPiPlusCher); + bool get_piminus = m_data->Stores["GenieInfo"]->Get("NumFSPiMinus", fsPiMinus); + bool get_piminuscher = m_data->Stores["GenieInfo"]->Get("NumFSPiMinusCher", fsPiMinusCher); + bool get_kplus = m_data->Stores["GenieInfo"]->Get("NumFSKPlus", fsKPlus); + bool get_kpluscher = m_data->Stores["GenieInfo"]->Get("NumFSKPlusCher", fsKPlusCher); + bool get_kminus = m_data->Stores["GenieInfo"]->Get("NumFSKMinus", fsKMinus); + bool get_kminuscher = m_data->Stores["GenieInfo"]->Get("NumFSKMinusCher", fsKMinusCher); + bool get_fsl_vtx = m_data->Stores["GenieInfo"]->Get("FSLeptonVertex", TrueFSLeptonVtx); + bool get_fsl_momentum = m_data->Stores["GenieInfo"]->Get("FSLeptonMomentum", TrueFSLeptonMomentum); + bool get_fsl_time = m_data->Stores["GenieInfo"]->Get("FSLeptonTime", TrueFSLeptonTime); + bool get_fsl_mass = m_data->Stores["GenieInfo"]->Get("FSLeptonMass", TrueFSLeptonMass); + bool get_fsl_pdg = m_data->Stores["GenieInfo"]->Get("FSLeptonPdg", TrueFSLeptonPdg); + bool get_fsl_energy = m_data->Stores["GenieInfo"]->Get("FSLeptonEnergy", TrueFSLeptonEnergy); + if (ANNIEEventTreeMakerVerbosity > 1) + { + std::cout << "get_neutrino_energy: " << get_neutrino_energy << "get_neutrino_vtxx: " << get_neutrino_vtxx << "get_neutrino_vtxy: " << get_neutrino_vtxy << "get_neutrino_vtxz: " << get_neutrino_vtxz << "get_neutrino_time: " << get_neutrino_vtxt << std::endl; + std::cout << "get_q2: " << get_q2 << ", get_cc: " << get_cc << ", get_qel: " << get_qel << ", get_res: " << get_res << ", get_dis: " << get_dis << ", get_coh: " << get_coh << ", get_mec: " << get_mec << std::endl; + std::cout << "get_n: " << get_n << ", get_p: " << get_p << ", get_pi0: " << get_pi0 << ", get_piplus: " << get_piplus << ", get_pipluscher: " << get_pipluscher << ", get_piminus: " << get_piminus << ", get_piminuscher: " << get_piminuscher << ", get_kplus: " << get_kplus << ", get_kpluscher: " << get_kpluscher << ", get_kminus: " << get_kminus << ", get_kminuscher: " << get_kminuscher << std::endl; + std::cout << "get_fsl_vtx: " << get_fsl_vtx << ", get_fsl_momentum: " << get_fsl_momentum << ", get_fsl_time: " << get_fsl_time << ", get_fsl_mass: " << get_fsl_mass << ", get_fsl_pdg: " << get_fsl_pdg << ", get_fsl_energy: " << get_fsl_energy << std::endl; + } + if (get_neutrino_energy && get_neutrino_mom && get_neutrino_vtxx && get_neutrino_vtxy && get_neutrino_vtxz && get_neutrino_vtxt && get_q2 && get_cc && get_nc && get_qel && get_res && get_dis && get_coh && get_mec && get_n && get_p && get_pi0 && get_piplus && get_pipluscher && get_piminus && get_piminuscher && get_kplus && get_kpluscher && get_kminus && get_kminuscher && get_fsl_vtx && get_fsl_momentum && get_fsl_time && get_fsl_mass && get_fsl_pdg && get_fsl_energy) + { + fTrueNeutrinoEnergy = TrueNeutrinoEnergy; + fTrueNeutrinoMomentum_X = TrueNeutrinoMomentum.X(); + fTrueNeutrinoMomentum_Y = TrueNeutrinoMomentum.Y(); + fTrueNeutrinoMomentum_Z = TrueNeutrinoMomentum.Z(); + fTrueNuIntxVtx_X = TrueNuIntxVtx_X; + fTrueNuIntxVtx_Y = TrueNuIntxVtx_Y; + fTrueNuIntxVtx_Z = TrueNuIntxVtx_Z; + fTrueNuIntxVtx_T = TrueNuIntxVtx_T; + fTrueFSLVtx_X = TrueFSLeptonVtx.X(); + fTrueFSLVtx_Y = TrueFSLeptonVtx.Y(); + fTrueFSLVtx_Z = TrueFSLeptonVtx.Z(); + fTrueFSLMomentum_X = TrueFSLeptonMomentum.X(); + fTrueFSLMomentum_Y = TrueFSLeptonMomentum.Y(); + fTrueFSLMomentum_Z = TrueFSLeptonMomentum.Z(); + fTrueFSLTime = TrueFSLeptonTime; + fTrueFSLMass = TrueFSLeptonMass; + fTrueFSLPdg = TrueFSLeptonPdg; + fTrueFSLEnergy = TrueFSLeptonEnergy; + fTrueQ2 = TrueQ2; + fTrueCC = (TrueCC) ? 1 : 0; + fTrueNC = (TrueNC) ? 1 : 0; + fTrueQEL = (TrueQEL) ? 1 : 0; + fTrueRES = (TrueRES) ? 1 : 0; + fTrueDIS = (TrueDIS) ? 1 : 0; + fTrueCOH = (TrueCOH) ? 1 : 0; + fTrueMEC = (TrueMEC) ? 1 : 0; + fTrueNeutrons = fsNeutrons; + fTrueProtons = fsProtons; + fTruePi0 = fsPi0; + fTruePiPlus = fsPiPlus; + fTruePiPlusCher = fsPiPlusCher; + fTruePiMinus = fsPiMinus; + fTruePiMinusCher = fsPiMinusCher; + fTrueKPlus = fsKPlus; + fTrueKPlusCher = fsKPlusCher; + fTrueKMinus = fsKMinus; + fTrueKMinusCher = fsKMinusCher; + } + else + { + Log("ANNIEEventTreeMaker tool: Did not find GENIE information. Continuing building remaining tree", v_message, ANNIEEventTreeMakerVerbosity); + successful_load = false; + } + } // end if hasGenie + + return successful_load; +} + +void ANNIEEventTreeMaker::FillTruthRecoDiffInfo(bool successful_mcload, bool successful_recoload) +{ + if (!successful_mcload || !successful_recoload) + { + Log("ANNIEEventTreeMaker Tool: Error loading True Muon Vertex or Extended Vertex information. Continuing to build remaining tree", v_message, ANNIEEventTreeMakerVerbosity); + } + else + { + // Make sure MCTruth Information is loaded from store + // Let's fill in stuff from the RecoSummary + fDeltaVtxX = fRecoVtxX - fTrueVtxX; + fDeltaVtxY = fRecoVtxY - fTrueVtxY; + fDeltaVtxZ = fRecoVtxZ - fTrueVtxZ; + fDeltaVtxT = fRecoVtxTime - fTrueVtxTime; + fDeltaVtxR = sqrt(pow(fDeltaVtxX, 2) + pow(fDeltaVtxY, 2) + pow(fDeltaVtxZ, 2)); + fDeltaParallel = fDeltaVtxX * fRecoDirX + fDeltaVtxY * fRecoDirY + fDeltaVtxZ * fRecoDirZ; + fDeltaPerpendicular = sqrt(pow(fDeltaVtxR, 2) - pow(fDeltaParallel, 2)); + fDeltaAzimuth = (fRecoAngle - fTrueAngle) / (TMath::Pi() / 180.0); + fDeltaZenith = (fRecoPhi - fTruePhi) / (TMath::Pi() / 180.0); + double cosphi = fTrueDirX * fRecoDirX + fTrueDirY * fRecoDirY + fTrueDirZ * fRecoDirZ; + double phi = TMath::ACos(cosphi); // radians + double TheAngle = phi / (TMath::Pi() / 180.0); // radians->degrees + fDeltaAngle = TheAngle; + } +} + +void ANNIEEventTreeMaker::RecoSummary() +{ + + // get reconstruction output + double dx = fRecoVtxX - fTrueVtxX; + double dy = fRecoVtxY - fTrueVtxY; + double dz = fRecoVtxZ - fTrueVtxZ; + double dt = fRecoVtxTime - fTrueVtxTime; + double deltaR = sqrt(dx * dx + dy * dy + dz * dz); + double cosphi = 0., phi = 0., DeltaAngle = 0.; + cosphi = fTrueDirX * fRecoDirX + fTrueDirY * fRecoDirY + fTrueDirZ * fRecoDirZ; + phi = TMath::ACos(cosphi); // radians + DeltaAngle = phi / (TMath::Pi() / 180.0); // radians->degrees + std::cout << "============================================================================" << std::endl; + std::cout << " Event number " << fEventNumber << std::endl; + std::cout << " trueVtx=(" << fTrueVtxX << ", " << fTrueVtxY << ", " << fTrueVtxZ << ", " << fTrueVtxTime << std::endl + << " TrueMuonEnergy= " << fTrueMuonEnergy << " Primary Pdg = " << fTruePrimaryPdg << std::endl + << " " << fTrueDirX << ", " << fTrueDirY << ", " << fTrueDirZ << ") " << std::endl; + std::cout << " recoVtx=(" << fRecoVtxX << ", " << fRecoVtxY << ", " << fRecoVtxZ << ", " << fRecoVtxTime << std::endl + << " " << fRecoDirX << ", " << fRecoDirY << ", " << fRecoDirZ << ") " << std::endl; + std::cout << " DeltaR = " << deltaR << "[cm]" << "\t" << " DeltaAngle = " << DeltaAngle << " [degree]" << std::endl; + std::cout << " FOM = " << fRecoVtxFOM << std::endl; + std::cout << " RecoStatus = " << fRecoStatus << std::endl; + std::cout << std::endl; +} + +void ANNIEEventTreeMaker::FillLAPPDWaveform() +{ + // Log("ANNIEEventTreeMaker: Filling LAPPD Waveform", 0, ANNIEEventTreeMakerVerbosity); + + fLAPPDWaveforms = std::vector>(60 * 3, std::vector(256, 0.0)); + + // m_data->Stores["ANNIEEvent"]->Print(false); + + // cout<<"LAPPDWaveformInputLabel: "<>> lappdData; // waveform data + m_data->Stores["ANNIEEvent"]->Get(LAPPDWaveformInputLabel, lappdData); + + std::map>>::iterator it; + for (it = lappdData.begin(); it != lappdData.end(); it++) + { + + // get the waveforms from channel number + unsigned long channel = it->first; + channel = channel % 1000 + 1000; + if ((channel % 1000) % 30 == 5) + continue; + Waveform waveforms = it->second.at(0); + vector wav = *waveforms.GetSamples(); + vector wave = wav; + if (wave.size() != 256) + { + cout << "ANNIEEventTreeMaker: Found a bug waveform at channel " << channel << ", size is " << wave.size() << endl; + continue; + } + + for (int i = 0; i < wave.size(); i++) + { + wave.at(i) = -wave.at(i); + } + + int LAPPD_ID = static_cast((channel - 1000) / 60); + Channel *chan = geom->GetChannel(channel); + int stripno = chan->GetStripNum(); + int stripSide = chan->GetStripSide(); + + // fill this waveform to fLAPPDWaveforms[LAPPD_ID][stripno+stripSide*30][n] + for (int n = 0; n < 256; n++) + { + fLAPPDWaveforms[LAPPD_ID * 60 + stripno + stripSide * 30][n] = wave.at(n); + } + } +} + +void ANNIEEventTreeMaker::FillLAPPDMCHitInfo() +{ + std::map> *MCLAPPDHits = nullptr; + m_data->Stores.at("ANNIEEvent")->Get("MCLAPPDHits", MCLAPPDHits); + + int HitCount = MCLAPPDHits->size(); + Log("ANNIEEventTreeMaker: Filling LAPPD MC Hit Info, got " + to_string(HitCount) + " MC hits", v_message, ANNIEEventTreeMakerVerbosity); + + Position detector_center = geom->GetTankCentre(); + double tank_center_x = detector_center.X(); + double tank_center_y = detector_center.Y(); + double tank_center_z = detector_center.Z(); + + for (std::pair> &&apair : *MCLAPPDHits) + { + unsigned long chankey = apair.first; + std::vector hits = apair.second; + + for (MCLAPPDHit &ahit : hits) + { + std::vector pos = ahit.GetPosition(); + double x = pos.at(0) - tank_center_x; + double y = pos.at(1) - tank_center_y; + double z = pos.at(2) - tank_center_z; + + std::vector local_pos = ahit.GetLocalPosition(); + // double local_x = local_pos.at(1); + // double local_y = local_pos.at(0); + double parallel = local_pos.at(0); + double transverse = local_pos.at(1); + + int tubeID = ahit.GetTubeId(); + double hitTime = ahit.GetTime(); + double hitCharge = ahit.GetCharge(); + + fLAPPDMCHitTubeIDs.push_back(tubeID); + fLAPPDMCHitChankeys.push_back(chankey); + fLAPPDMCHitTime.push_back(hitTime); + fLAPPDMCHitCharge.push_back(hitCharge); + fLAPPDMCHitX.push_back(x); + fLAPPDMCHitY.push_back(y); + fLAPPDMCHitZ.push_back(z); + fLAPPDMCHitParallelPos.push_back(parallel); + fLAPPDMCHitTransversePos.push_back(transverse); + } + } +} \ No newline at end of file diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h new file mode 100644 index 000000000..c6243def4 --- /dev/null +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h @@ -0,0 +1,572 @@ +#ifndef ANNIEEventTreeMaker_H +#define ANNIEEventTreeMaker_H + +#include +#include + +#include "Tool.h" +// ROOT includes +#include "TApplication.h" +#include +#include +#include "TFile.h" +#include "TTree.h" +#include "TH1D.h" +#include "TMath.h" +#include "ADCPulse.h" +#include "Waveform.h" +#include "CalibratedADCWaveform.h" +#include "Hit.h" +#include "RecoDigit.h" +#include "ANNIEalgorithms.h" +#include "TimeClass.h" +#include "BeamStatus.h" +#include "PsecData.h" +#include "LAPPDPulse.h" +#include "LAPPDHit.h" +#include "Geometry.h" + +/** + * \class ANNIEEventTreeMaker + * + * + * $Author: Yue Feng $ + * $Date: 2024/8 $ + * Contact: yuef@iastate.edu + */ +class ANNIEEventTreeMaker : public Tool +{ + +public: + ANNIEEventTreeMaker(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + + bool LoadEventInfo(); + void LoadBeamInfo(); + + void LoadRWMBRFInfo(); + + void LoadAllTankHits(); + void LoadSiPMHits(); + + void LoadLAPPDInfo(); + void FillLAPPDInfo(); + void FillLAPPDHit(); + void FillLAPPDPulse(); + + bool LoadClusterInfo(); + + void LoadMRDCluster(); + + void LoadMRDInfo(); + void LoadLAPPDRecoInfo(); + void FillLAPPDRecoInfo(); + void FillLAPPDWaveform(); + void FillLAPPDMCHitInfo(); + + bool FillMCTruthInfo(); + bool FillTankRecoInfo(); + int LoadMRDTrackReco(int SubEventNumber); + void LoadAllMRDHits(bool isData); + void FillRecoDebugInfo(); + void FillTruthRecoDiffInfo(bool got_mc, bool got_reco); + + void RecoSummary(); + void LoadTankClusterHits(std::vector cluster_hits); + void LoadTankClusterHitsMC(std::vector cluster_hits, std::vector cluster_detkeys); + bool LoadTankClusterClassifiers(double cluster_time); + + void ResetVariables(); + +private: + // General variables + bool isData = 1; + bool hasGenie; + + int ANNIEEventTreeMakerVerbosity = 0; + int v_error = 0; + int v_warning = 1; + int v_message = 2; + int v_debug = 3; + + int EventNumberIndex = 0; + + // What events will be filled - Triggers + bool fillAllTriggers; // if true, fill all events with any major trigger + // if fillAllTriggers = false: + bool fill_singleTrigger; // if true, only fill events with selected trigger, for example 14 + int fill_singleTriggerWord; + // if fillAllTriggers = false and fill_singleTrigger = false: + vector fill_TriggerWord; // fill events with any of these triggers in this vector + + // What events will be filled - status + bool fillCleanEventsOnly = 0; // Only output events not flagged by EventSelector tool + bool fillLAPPDEventsOnly = 0; // Only fill events with LAPPD data + + // What information will be filled + bool TankHitInfo_fill = 1; + bool TankCluster_fill = 1; + bool cluster_TankHitInfo_fill = 1; + bool MRDHitInfo_fill = 1; + bool LAPPDData_fill = 1; + bool RWMBRF_fill = 1; + bool LAPPD_PPS_fill = 1; + bool LAPPD_Waveform_fill = 1; + bool LAPPD_MC_fill = 0; + + // What reco information will be filled + bool MCTruth_fill = 0; // Output the MC truth information + bool TankReco_fill = 0; + bool MRDReco_fill = 1; + bool RecoDebug_fill = 0; // Outputs results of Reconstruction at each step (best fits, FOMs, etc.) + bool muonTruthRecoDiff_fill = 0; // Output difference in tmuonruth and reconstructed values + bool SiPMPulseInfo_fill = 0; + bool LAPPDReco_fill = 1; + bool BeamInfo_fill = 1; + + TFile *fOutput_tfile = nullptr; + TTree *fANNIETree = nullptr; + Geometry *geom = nullptr; + + int processedEvents = 0; + + // Variables for filling the tree + + // EventInfo + int fRunNumber; + int fSubrunNumber; + int fPartFileNumber; + int fRunType = 0; + int fEventNumber; + int fPrimaryTriggerWord; + int trigword; + uint64_t fPrimaryTriggerTime; + vector fGroupedTriggerTime; + vector fGroupedTriggerWord; + int fTriggerword; + int fExtended; + int fTankMRDCoinc; + int fNoVeto; + int fHasTank; + int fHasMRD; + int fHasLAPPD; + std::string fMRDTriggerType; + int fMRDTriggerTypeInt; + + ULong64_t fEventTimeTank; + ULong64_t fEventTimeMRD; + + // beam information + double fPot; + int fBeamok; + double beam_E_TOR860; + double beam_E_TOR875; + double beam_THCURR; + double beam_BTJT2; + double beam_HP875; + double beam_VP875; + double beam_HPTG1; + double beam_VPTG1; + double beam_HPTG2; + double beam_VPTG2; + double beam_BTH2T2; + uint64_t fBeamInfoTime; + int64_t fBeamInfoTimeToTriggerDiff; + + // RWM and BRF information + double fRWMRisingStart; // start of the rising of the waveform + double fRWMRisingEnd; // maximum of the rising of the waveform + double fRWMHalfRising; // half of the rising of the waveform, from start to maximum + double fRWMFHWM; // full width at half maximum of the waveform + double fRWMFirstPeak; // first peak of the waveform + + double fBRFFirstPeak; // first peak of the waveform + double fBRFAveragePeak; // average peak of the waveform + double fBRFFirstPeakFit; // first peak of the waveform, Gaussian fit + + // TankHitInfo_fill + int fNHits = 0; + std::vector fIsFiltered; + std::vector fHitX; + std::vector fHitY; + std::vector fHitZ; + std::vector fHitT; + std::vector fHitQ; + std::vector fHitPE; + std::vector fHitType; + std::vector fHitDetID; + std::vector fHitChankey; + std::vector fHitChankeyMC; + + // SiPMPulseInfo_fill + int fSiPM1NPulses; + int fSiPM2NPulses; + std::vector fSiPMHitQ; + std::vector fSiPMHitT; + std::vector fSiPMHitAmplitude; + std::vector fSiPMNum; + + // LAPPDData_fill + int fLAPPD_Count; + vector fLAPPD_ID; + vector fLAPPD_Beamgate_ns; + vector fLAPPD_Timestamp_ns; + vector fLAPPD_Beamgate_Raw; + vector fLAPPD_Timestamp_Raw; + vector fLAPPD_Offset; + vector fLAPPD_TSCorrection; + vector fLAPPD_BGCorrection; + vector fLAPPD_OSInMinusPS; + vector fLAPPD_BGPPSBefore; + vector fLAPPD_BGPPSAfter; + vector fLAPPD_BGPPSDiff; + vector fLAPPD_BGPPSMissing; + vector fLAPPD_TSPPSBefore; + vector fLAPPD_TSPPSAfter; + vector fLAPPD_TSPPSDiff; + vector fLAPPD_TSPPSMissing; + vector fLAPPD_BG_switchBit0; + vector fLAPPD_BG_switchBit1; + + // LAPPD Reco Fill + vector fLAPPDPulseTimeStampUL; + vector fLAPPDPulseBeamgateUL; + vector fLAPPD_IDs; + vector fChannelID; + vector fPulsePeakTime; + vector fPulseHalfHeightTime; + vector fPulseCharge; + vector fPulsePeakAmp; + vector fPulseStart; + vector fPulseEnd; + vector fPulseWidth; + vector fPulseSide; + vector fPulseStripNum; + std::map fChannelBaseline; + + vector fLAPPDHitTimeStampUL; + vector fLAPPDHitBeamgateUL; + vector fLAPPDHit_IDs; + vector fLAPPDHitChannel; + vector fLAPPDHitStrip; + vector fLAPPDHitTime; + vector fLAPPDHitAmp; + vector fLAPPDHitParallelPos; + vector fLAPPDHitTransversePos; + vector fLAPPDHitP1StartTime; + vector fLAPPDHitP2StartTime; + vector fLAPPDHitP1EndTime; + vector fLAPPDHitP2EndTime; + vector fLAPPDHitP1PeakTime; + vector fLAPPDHitP2PeakTime; + vector fLAPPDHitP1PeakAmp; + vector fLAPPDHitP2PeakAmp; + vector fLAPPDHitP1HalfHeightTime; + vector fLAPPDHitP2HalfHeightTime; + vector fLAPPDHitP1HalfEndTime; + vector fLAPPDHitP2HalfEndTime; + vector fLAPPDHitP1Charge; + vector fLAPPDHitP2Charge; + + // waveform + vector LAPPDWaveformChankey; + vector waveformMaxValue; + vector waveformRMSValue; + vector waveformMaxFoundNear; + vector waveformMaxNearingValue; + vector waveformMaxTimeBinValue; + + // LAPPD waveform Fill + string LAPPDWaveformInputLabel; + vector> fLAPPDWaveforms; + + // LAPPD MC Hit info, loaded from WCSim + vector fLAPPDMCHitTubeIDs; + vector fLAPPDMCHitChankeys; + vector fLAPPDMCHitTime; + vector fLAPPDMCHitCharge; + vector fLAPPDMCHitX; + vector fLAPPDMCHitY; + vector fLAPPDMCHitZ; + vector fLAPPDMCHitParallelPos; + vector fLAPPDMCHitTransversePos; + + // finished **************************************************** + + // tank cluster information + + int fNumberOfClusters; // how many clusters in this event + // vector fClusterIndex; // index of which cluster this data belongs to + vector fClusterHits; // how many hits in this cluster + vector fClusterChargeV; + vector fClusterTimeV; + vector fClusterPEV; + + vector> fCluster_HitX; // each vector is a cluster, each element is a hit in that cluster + vector> fCluster_HitY; + vector> fCluster_HitZ; + vector> fCluster_HitT; + vector> fCluster_HitQ; + vector> fCluster_HitPE; + vector> fCluster_HitType; + vector> fCluster_HitDetID; + vector> fCluster_HitChankey; + vector> fCluster_HitChankeyMC; + + vector fClusterMaxPEV; + vector fClusterChargePointXV; + vector fClusterChargePointYV; + vector fClusterChargePointZV; + vector fClusterChargeBalanceV; + + // MRD cluster information + ULong64_t fEventTimeMRD_Tree; + int fMRDClusterNumber; + std::vector fMRDClusterHitNumber; + std::vector fMRDClusterTime; + std::vector fMRDClusterTimeSigma; + + // MRDHitInfo_fill + int fVetoHit; + std::vector fMRDHitClusterIndex; + std::vector fMRDHitT; + std::vector fMRDHitCharge; + std::vector fMRDHitDigitPMT; + std::vector fMRDHitDetID; + std::vector fMRDHitChankey; + std::vector fMRDHitChankeyMC; + + std::vector fFMVHitT; + std::vector fFMVHitDetID; + std::vector fFMVHitChankey; + std::vector fFMVHitChankeyMC; + + // MRDReco_fill + int fNumMRDClusterTracks; + std::vector fMRDTrackAngle; + std::vector fMRDTrackAngleError; + std::vector fMRDPenetrationDepth; + std::vector fMRDTrackLength; + std::vector fMRDEntryPointRadius; + std::vector fMRDEnergyLoss; + std::vector fMRDEnergyLossError; + std::vector fMRDTrackStartX; + std::vector fMRDTrackStartY; + std::vector fMRDTrackStartZ; + std::vector fMRDTrackStopX; + std::vector fMRDTrackStopY; + std::vector fMRDTrackStopZ; + std::vector fMRDSide; + std::vector fMRDStop; + std::vector fMRDThrough; + std::vector fMRDClusterIndex; + + std::vector fNumClusterTracks; + + // fillCleanEventsOnly + int fEventStatusApplied; + int fEventStatusFlagged; + + // MCTruth_fill + // ************ MC Truth Information **************** // + uint64_t fMCEventNum; + uint16_t fMCTriggerNum; + int fiMCTriggerNum; + // True muon + double fTrueVtxX; + double fTrueVtxY; + double fTrueVtxZ; + double fTrueVtxTime; + double fTrueDirX; + double fTrueDirY; + double fTrueDirZ; + double fTrueAngle; + double fTruePhi; + double fTrueMuonEnergy; + int fTruePrimaryPdg; + double fTrueTrackLengthInWater; + double fTrueTrackLengthInMRD; + std::vector *fTruePrimaryPdgs = nullptr; + std::vector *fTrueNeutCapVtxX = nullptr; + std::vector *fTrueNeutCapVtxY = nullptr; + std::vector *fTrueNeutCapVtxZ = nullptr; + std::vector *fTrueNeutCapNucleus = nullptr; + std::vector *fTrueNeutCapTime = nullptr; + std::vector *fTrueNeutCapGammas = nullptr; + std::vector *fTrueNeutCapE = nullptr; + std::vector *fTrueNeutCapGammaE = nullptr; + int fTrueMultiRing; + + // Genie information for event + double fTrueNeutrinoEnergy; + double fTrueNeutrinoMomentum_X; + double fTrueNeutrinoMomentum_Y; + double fTrueNeutrinoMomentum_Z; + double fTrueNuIntxVtx_X; + double fTrueNuIntxVtx_Y; + double fTrueNuIntxVtx_Z; + double fTrueNuIntxVtx_T; + double fTrueFSLVtx_X; + double fTrueFSLVtx_Y; + double fTrueFSLVtx_Z; + double fTrueFSLMomentum_X; + double fTrueFSLMomentum_Y; + double fTrueFSLMomentum_Z; + double fTrueFSLTime; + double fTrueFSLMass; + int fTrueFSLPdg; + double fTrueFSLEnergy; + double fTrueQ2; + int fTrueCC; + int fTrueNC; + int fTrueQEL; + int fTrueRES; + int fTrueDIS; + int fTrueCOH; + int fTrueMEC; + int fTrueNeutrons; + int fTrueProtons; + int fTruePi0; + int fTruePiPlus; + int fTruePiPlusCher; + int fTruePiMinus; + int fTruePiMinusCher; + int fTrueKPlus; + int fTrueKPlusCher; + int fTrueKMinus; + int fTrueKMinusCher; + + // TankReco_fill + double fRecoVtxX; + double fRecoVtxY; + double fRecoVtxZ; + double fRecoVtxTime; + double fRecoVtxFOM; + double fRecoDirX; + double fRecoDirY; + double fRecoDirZ; + double fRecoAngle; + double fRecoPhi; + int fRecoStatus; + + // RecoDebug_fill + // **************** Full reco chain information ************* // + // seed vertices + std::vector fSeedVtxX; + std::vector fSeedVtxY; + std::vector fSeedVtxZ; + std::vector fSeedVtxFOM; + double fSeedVtxTime; + + // Reco vertex + // Point Position Vertex + double fPointPosX; + double fPointPosY; + double fPointPosZ; + double fPointPosTime; + double fPointPosFOM; + int fPointPosStatus; + double fPointDirX; + double fPointDirY; + double fPointDirZ; + double fPointDirTime; + double fPointDirFOM; + int fPointDirStatus; + + // Point Vertex Finder + double fPointVtxPosX; + double fPointVtxPosY; + double fPointVtxPosZ; + double fPointVtxTime; + double fPointVtxDirX; + double fPointVtxDirY; + double fPointVtxDirZ; + double fPointVtxFOM; + int fPointVtxStatus; + + // muonTruthRecoDiff_fill + // ************* Difference between MC and Truth *********** // + double fDeltaVtxX; + double fDeltaVtxY; + double fDeltaVtxZ; + double fDeltaVtxR; + double fDeltaVtxT; + double fDeltaParallel; + double fDeltaPerpendicular; + double fDeltaAzimuth; + double fDeltaZenith; + double fDeltaAngle; + + // Pion and kaon counts for event + int fPi0Count; + int fPiPlusCount; + int fPiMinusCount; + int fK0Count; + int fKPlusCount; + int fKMinusCount; + + //******************************************************************************************************************** + + // data variables for filling the tree + // Event Info + std::map fDataStreams; + std::map GroupedTrigger; + + // LAPPDData_fill + std::map LAPPDDataMap; + std::map LAPPDBeamgate_ns; + std::map LAPPDTimeStamps_ns; // data and key are the same + std::map LAPPDTimeStampsRaw; + std::map LAPPDBeamgatesRaw; + std::map LAPPDOffsets; + std::map LAPPDTSCorrection; + std::map LAPPDBGCorrection; + std::map LAPPDOSInMinusPS; + std::map LAPPDBG_PPSBefore; + std::map LAPPDBG_PPSAfter; + std::map LAPPDBG_PPSDiff; + std::map LAPPDBG_PPSMissing; + std::map LAPPDTS_PPSBefore; + std::map LAPPDTS_PPSAfter; + std::map LAPPDTS_PPSDiff; + std::map LAPPDTS_PPSMissing; + std::map> SwitchBitBG; + + std::map>> lappdPulses; + std::map> lappdHits; + + //******************************************************************************************************************** + + // detector maps, don't clear + std::map *AuxChannelNumToTypeMap; + std::map ChannelKeyToSPEMap; + + std::map pmtid_to_channelkey; + std::map channelkey_to_pmtid; + std::map channelkey_to_mrdpmtid; + std::map mrdpmtid_to_channelkey_data; + std::map channelkey_to_faccpmtid; + std::map faccpmtid_to_channelkey_data; + + //******************************************************************************************************************** + // some left not used objects + + // left for raw data + std::vector fADCWaveformChankeys; + std::vector fADCWaveformSamples; + + // ************ Muon reconstruction level information ******** // + std::string MRDTriggertype; + + // ************* LAPPD RecoInfo *********** // + // left for LAPPD waveforms if needed + std::map> waveformMax; // strip number+30*side, value + std::map> waveformRMS; + std::map> waveformMaxLast; + std::map> waveformMaxNearing; + std::map> waveformMaxTimeBin; +}; + +#endif diff --git a/UserTools/ANNIEEventTreeMaker/README.md b/UserTools/ANNIEEventTreeMaker/README.md new file mode 100644 index 000000000..cb2e852ff --- /dev/null +++ b/UserTools/ANNIEEventTreeMaker/README.md @@ -0,0 +1,20 @@ +# ANNIEEventTreeMaker + +ANNIEEventTreeMaker + +## Data + +Describe any data formats ANNIEEventTreeMaker creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for ANNIEEventTreeMaker. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/Factory/Factory.cpp b/UserTools/Factory/Factory.cpp index c986c48b7..8f3a5e124 100644 --- a/UserTools/Factory/Factory.cpp +++ b/UserTools/Factory/Factory.cpp @@ -174,5 +174,6 @@ if (tool=="BackTracker") ret=new BackTracker; if (tool=="PrintDQ") ret=new PrintDQ; if (tool=="AssignBunchTimingMC") ret=new AssignBunchTimingMC; if (tool=="FitRWMWaveform") ret=new FitRWMWaveform; +if (tool=="ANNIEEventTreeMaker") ret=new ANNIEEventTreeMaker; return ret; } diff --git a/UserTools/Unity.h b/UserTools/Unity.h index 7e64d4e9b..93fb69ce1 100644 --- a/UserTools/Unity.h +++ b/UserTools/Unity.h @@ -182,3 +182,4 @@ #include "PrintDQ.h" #include "AssignBunchTimingMC.h" #include "FitRWMWaveform.h" +#include "ANNIEEventTreeMaker.h" From bd613422cebd29cdc0b27867c25910c132d834ce Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Mon, 20 Jan 2025 01:38:39 -0600 Subject: [PATCH 121/163] Add LAPPDTreeMaker, this is a part of LAPPD tool chains but also needed by EBV2 work flow --- UserTools/Factory/Factory.cpp | 1 + UserTools/LAPPDTreeMaker/LAPPDTreeMaker.cpp | 1093 +++++++++++++++++++ UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h | 185 ++++ UserTools/LAPPDTreeMaker/README.md | 20 + UserTools/Unity.h | 1 + 5 files changed, 1300 insertions(+) create mode 100644 UserTools/LAPPDTreeMaker/LAPPDTreeMaker.cpp create mode 100644 UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h create mode 100644 UserTools/LAPPDTreeMaker/README.md diff --git a/UserTools/Factory/Factory.cpp b/UserTools/Factory/Factory.cpp index c986c48b7..71ff0b66c 100644 --- a/UserTools/Factory/Factory.cpp +++ b/UserTools/Factory/Factory.cpp @@ -174,5 +174,6 @@ if (tool=="BackTracker") ret=new BackTracker; if (tool=="PrintDQ") ret=new PrintDQ; if (tool=="AssignBunchTimingMC") ret=new AssignBunchTimingMC; if (tool=="FitRWMWaveform") ret=new FitRWMWaveform; +if (tool=="LAPPDTreeMaker") ret=new LAPPDTreeMaker; return ret; } diff --git a/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.cpp b/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.cpp new file mode 100644 index 000000000..3091f508f --- /dev/null +++ b/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.cpp @@ -0,0 +1,1093 @@ +#include "LAPPDTreeMaker.h" + +LAPPDTreeMaker::LAPPDTreeMaker() : Tool() {} + +bool LAPPDTreeMaker::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + m_variables.Get("treeMakerVerbosity", treeMakerVerbosity); + m_variables.Get("treeMakerInputPulseLabel", treeMakerInputPulseLabel); + m_variables.Get("treeMakerInputHitLabel", treeMakerInputHitLabel); + treeMakerOutputFileName = "LAPPDTree.root"; + m_variables.Get("treeMakerOutputFileName", treeMakerOutputFileName); + + LoadPulse = false; + m_variables.Get("LoadPulse", LoadPulse); + LoadHit = false; + m_variables.Get("LoadHit", LoadHit); + LoadWaveform = false; + m_variables.Get("LoadWaveform", LoadWaveform); + LoadLAPPDDataTimeStamp = false; + m_variables.Get("LoadLAPPDDataTimeStamp", LoadLAPPDDataTimeStamp); + LoadPPSTimestamp = false; + m_variables.Get("LoadPPSTimestamp", LoadPPSTimestamp); + LoadRunInfoRaw = false; + m_variables.Get("LoadRunInfoRaw", LoadRunInfoRaw); + LoadRunInfoANNIEEvent = false; + m_variables.Get("LoadRunInfoANNIEEvent", LoadRunInfoANNIEEvent); + LoadTriggerInfo = false; + m_variables.Get("LoadTriggerInfo", LoadTriggerInfo); + LoadGroupedTriggerInfo = false; + m_variables.Get("LoadGroupedTriggerInfo", LoadGroupedTriggerInfo); + if (!LoadTriggerInfo) + LoadGroupedTriggerInfo = false; // if not loading trigger, don't fill grouped trigger + LoadGroupOption = "beam"; + m_variables.Get("LoadGroupOption", LoadGroupOption); + MultiLAPPDMapTreeMaker = false; + m_variables.Get("MultiLAPPDMapTreeMaker", MultiLAPPDMapTreeMaker); + + TString filename = treeMakerOutputFileName; + file = new TFile(filename, "RECREATE"); + fPulse = new TTree("Pulse", "Pulse"); + fHit = new TTree("Hit", "Hit"); + fWaveform = new TTree("Waveform", "Waveform"); + fTimeStamp = new TTree("TimeStamp", "TimeStamp"); + fTrigger = new TTree("Trig", "Trig"); + fGroupedTrigger = new TTree("GTrig", "GTrig"); + + fPulse->Branch("RunNumber", &RunNumber, "RunNumber/I"); + fPulse->Branch("SubRunNumber", &SubRunNumber, "SubRunNumber/I"); + fPulse->Branch("PartFileNumber", &PartFileNumber, "PartFileNumber/I"); + fPulse->Branch("EventNumber", &EventNumber, "EventNumber/I"); + fPulse->Branch("LAPPD_ID", &LAPPD_ID, "LAPPD_ID/I"); + fPulse->Branch("LAPPDDataTimeStampUL", &LAPPDDataTimeStampUL, "LAPPDDataTimeStampUL/l"); + fPulse->Branch("LAPPDDataBeamgateUL", &LAPPDDataBeamgateUL, "LAPPDDataBeamgateUL/l"); + fPulse->Branch("ChannelID", &ChannelID, "ChannelID/I"); + fPulse->Branch("StripNumber", &StripNumber, "StripNumber/I"); + fPulse->Branch("PeakTime", &PeakTime, "PeakTime/D"); + fPulse->Branch("Charge", &Charge, "Charge/D"); + fPulse->Branch("PeakAmp", &PeakAmp, "PeakAmp/D"); + fPulse->Branch("PulseStart", &PulseStart, "PulseStart/D"); + fPulse->Branch("PulseEnd", &PulseEnd, "PulseEnd/D"); + fPulse->Branch("PulseSize", &PulseSize, "PulseSize/D"); + fPulse->Branch("PulseSide", &PulseSide, "PulseSide/I"); + fPulse->Branch("PulseThreshold", &PulseThreshold, "PulseThreshold/D"); + fPulse->Branch("PulseBaseline", &PulseBaseline, "PulseBaseline/D"); + if (MultiLAPPDMapTreeMaker) + { + fPulse->Branch("LTSRaw", <SRaw, "LTSRaw/l"); + fPulse->Branch("LBGRaw", &LBGRaw, "LBGRaw/l"); + fPulse->Branch("LOffset_ns", &LOffset_ns, "LOffset_ns/l"); + fPulse->Branch("LTSCorrection", <SCorrection, "LTSCorrection/I"); + fPulse->Branch("LBGCorrection", &LBGCorrection, "LBGCorrection/I"); + fPulse->Branch("LOSInMinusPS", &LOSInMinusPS, "LOSInMinusPS/I"); + fPulse->Branch("CTCPrimeTriggerTime", &CTCPrimeTriggerTime, "CTCPrimeTriggerTime/l"); + } + + fHit->Branch("RunNumber", &RunNumber, "RunNumber/I"); + fHit->Branch("SubRunNumber", &SubRunNumber, "SubRunNumber/I"); + fHit->Branch("PartFileNumber", &PartFileNumber, "PartFileNumber/I"); + fHit->Branch("EventNumber", &EventNumber, "EventNumber/I"); + fHit->Branch("LAPPD_ID", &LAPPD_ID, "LAPPD_ID/I"); + fHit->Branch("LAPPDDataTimeStampUL", &LAPPDDataTimeStampUL, "LAPPDDataTimeStampUL/l"); + fHit->Branch("LAPPDDataBeamgateUL", &LAPPDDataBeamgateUL, "LAPPDDataBeamgateUL/l"); + fHit->Branch("StripNumber", &StripNumber, "StripNumber/I"); + fHit->Branch("HitTime", &HitTime, "HitTime/D"); + fHit->Branch("HitAmp", &HitAmp, "HitAmp/D"); + fHit->Branch("XPosTank", &XPosTank, "XPosTank/D"); + fHit->Branch("YPosTank", &YPosTank, "YPosTank/D"); + fHit->Branch("ZPosTank", &ZPosTank, "ZPosTank/D"); + fHit->Branch("ParallelPos", &ParallelPos, "ParallelPos/D"); + fHit->Branch("TransversePos", &TransversePos, "TransversePos/D"); + fHit->Branch("Pulse1StartTime", &Pulse1StartTime, "Pulse1StartTime/D"); + fHit->Branch("Pulse2StartTime", &Pulse2StartTime, "Pulse2StartTime/D"); + fHit->Branch("Pulse1LastTime", &Pulse1LastTime, "Pulse1LastTime/D"); + fHit->Branch("Pulse2LastTime", &Pulse2LastTime, "Pulse2LastTime/D"); + if (MultiLAPPDMapTreeMaker) + { + fHit->Branch("LTSRaw", <SRaw, "LTSRaw/l"); + fHit->Branch("LBGRaw", &LBGRaw, "LBGRaw/l"); + fHit->Branch("LOffset_ns", &LOffset_ns, "LOffset_ns/l"); + fHit->Branch("LTSCorrection", <SCorrection, "LTSCorrection/I"); + fHit->Branch("LBGCorrection", &LBGCorrection, "LBGCorrection/I"); + fHit->Branch("LOSInMinusPS", &LOSInMinusPS, "LOSInMinusPS/I"); + fHit->Branch("CTCPrimeTriggerTime", &CTCPrimeTriggerTime, "CTCPrimeTriggerTime/l"); + } + + fWaveform->Branch("RunNumber", &RunNumber, "RunNumber/I"); + fWaveform->Branch("SubRunNumber", &SubRunNumber, "SubRunNumber/I"); + fWaveform->Branch("PartFileNumber", &PartFileNumber, "PartFileNumber/I"); + fWaveform->Branch("EventNumber", &EventNumber, "EventNumber/I"); + fWaveform->Branch("LAPPD_ID", &LAPPD_ID, "LAPPD_ID/I"); + fWaveform->Branch("LAPPDDataTimeStampUL", &LAPPDDataTimeStampUL, "LAPPDDataTimeStampUL/l"); + fWaveform->Branch("LAPPDDataBeamgateUL", &LAPPDDataBeamgateUL, "LAPPDDataBeamgateUL/l"); + fWaveform->Branch("StripNumber", &StripNumber, "StripNumber/I"); + fWaveform->Branch("PulseSide", &PulseSide, "PulseSide/I"); + fWaveform->Branch("WaveformMax", &waveformMaxValue, "WaveformMax/D"); + fWaveform->Branch("WaveformRMS", &waveformRMSValue, "WaveformRMS/D"); + fWaveform->Branch("WaveformMaxTimeBin", &waveformMaxTimeBinValue, "WaveformMaxTimeBin/I"); + fWaveform->Branch("waveformMaxFoundNear", &waveformMaxFoundNear, "waveformMaxFoundNear/O"); // O is boolean + fWaveform->Branch("WaveformMaxNearing", &waveformMaxNearingValue, "WaveformMaxNearing/D"); + if (MultiLAPPDMapTreeMaker) + { + fWaveform->Branch("LTSRaw", <SRaw, "LTSRaw/l"); + fWaveform->Branch("LBGRaw", &LBGRaw, "LBGRaw/l"); + fWaveform->Branch("LOffset_ns", &LOffset_ns, "LOffset_ns/l"); + fWaveform->Branch("LTSCorrection", <SCorrection, "LTSCorrection/I"); + fWaveform->Branch("LBGCorrection", &LBGCorrection, "LBGCorrection/I"); + fWaveform->Branch("LOSInMinusPS", &LOSInMinusPS, "LOSInMinusPS/I"); + fWaveform->Branch("CTCPrimeTriggerTime", &CTCPrimeTriggerTime, "CTCPrimeTriggerTime/l"); + } + + fTimeStamp->Branch("RunNumber", &RunNumber, "RunNumber/I"); + fTimeStamp->Branch("SubRunNumber", &SubRunNumber, "SubRunNumber/I"); + fTimeStamp->Branch("PartFileNumber", &PartFileNumber, "PartFileNumber/I"); + fTimeStamp->Branch("EventNumber", &EventNumber, "EventNumber/I"); + fTimeStamp->Branch("LAPPD_ID", &LAPPD_ID, "LAPPD_ID/I"); + fTimeStamp->Branch("LAPPDDataTimeStampUL", &LAPPDDataTimeStampUL, "LAPPDDataTimeStampUL/l"); + fTimeStamp->Branch("LAPPDDataBeamgateUL", &LAPPDDataBeamgateUL, "LAPPDDataBeamgateUL/l"); + fTimeStamp->Branch("LAPPDDataTimestamp", &LAPPDDataTimestampPart1, "LAPPDDataTimestamp/l"); + fTimeStamp->Branch("LAPPDDataBeamgate", &LAPPDDataBeamgatePart1, "LAPPDDataBeamgate/l"); + fTimeStamp->Branch("LAPPDDataTimestampFloat", &LAPPDDataTimestampPart2, "LAPPDDataTimestampFloat/D"); + fTimeStamp->Branch("LAPPDDataBeamgateFloat", &LAPPDDataBeamgatePart2, "LAPPDDataBeamgateFloat/D"); + fTimeStamp->Branch("ppsDiff", &ppsDiff, "ppsDiff/L"); + fTimeStamp->Branch("ppsCount0", &ppsCount0, "ppsCount0/l"); + fTimeStamp->Branch("ppsCount1", &ppsCount1, "ppsCount1/l"); + fTimeStamp->Branch("ppsTime0", &ppsTime0, "ppsTime0/l"); + fTimeStamp->Branch("ppsTime1", &ppsTime1, "ppsTime1/l"); + + // trigger trees have no related to LAPPD data or PPS, so don't need event number + fTrigger->Branch("RunNumber", &RunNumber, "RunNumber/I"); + fTrigger->Branch("SubRunNumber", &SubRunNumber, "SubRunNumber/I"); + fTrigger->Branch("PartFileNumber", &PartFileNumber, "PartFileNumber/I"); + fTrigger->Branch("CTCTimeStamp", &CTCTimeStamp, "CTCTimeStamp/l"); + fTrigger->Branch("CTCTriggerWord", &CTCTriggerWord); + fTrigger->Branch("trigNumInMap", &trigNumInThisMap, "trigNumInMap/I"); + fTrigger->Branch("trigIndexInMap", &trigIndexInThisMap, "trigNumInMap/I"); + + fGroupedTrigger->Branch("RunNumber", &RunNumber, "RunNumber/I"); + fGroupedTrigger->Branch("SubRunNumber", &SubRunNumber, "SubRunNumber/I"); + fGroupedTrigger->Branch("PartFileNumber", &PartFileNumber, "PartFileNumber/I"); + fGroupedTrigger->Branch("gTrigWord", &groupedTriggerWords); + fGroupedTrigger->Branch("gTrigTime", &groupedTriggerTimestamps); + fGroupedTrigger->Branch("gTrigType", &groupedTriggerType, "gTrigType/I"); + fGroupedTrigger->Branch("gTrigNum", &TriggerGroupNumInThisEvent, "gTrigNum/I"); + + TriggerWordMap = new std::map>; + m_data->Stores["ANNIEEvent"]->Header->Get("AnnieGeometry", _geom); + EventNumber = 0; + + return true; +} + +bool LAPPDTreeMaker::Execute() +{ + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::Execute()" << endl; + CleanVariables(); + + m_data->CStore.Get("LoadingPPS", LoadingPPS); + if (treeMakerVerbosity > 0) + cout << "LoadingPPS: " << LoadingPPS << endl; + + m_data->CStore.Get("LAPPDana", LAPPDana); + if (treeMakerVerbosity > 0) + cout << "LAPPDana: " << LAPPDana << endl; + + if (LoadRunInfoRaw) + LoadRunInfoFromRaw(); + + if (LoadRunInfoANNIEEvent) + LoadRunInfoFromANNIEEvent(); + + bool loadTriggerPaused = false; + m_data->CStore.Get("PauseCTCDecoding", loadTriggerPaused); + if (treeMakerVerbosity > 0) + cout << "loadTriggerPaused: " << loadTriggerPaused << endl; + if (!loadTriggerPaused) + { + if (LoadTriggerInfo) + { + bool getTrig = m_data->CStore.Get("TimeToTriggerWordMap", TriggerWordMap); + if (!getTrig) + cout << "Error in getting trigger word map" << endl; + if (getTrig) + { + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker:: TimeToTriggerWordMap size: " << TriggerWordMap->size() << endl; + FillTriggerTree(); + } + } + } + + if (LoadGroupedTriggerInfo) + FillGroupedTriggerTree(); + + if (MultiLAPPDMapTreeMaker && LAPPDana) + { + m_data->Stores["ANNIEEvent"]->Get("PrimaryTriggerTime", CTCPrimeTriggerTime); + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::Execute() MultiLAPPDMapTreeMaker" << endl; + LoadLAPPDMapInfo(); + bool getMap = m_data->Stores["ANNIEEvent"]->Get("LAPPDDataMap", LAPPDDataMap); + bool gotBeamgates_ns = m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + bool gotTimeStamps_ns = m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); + bool gotTimeStampsRaw = m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStampsRaw", LAPPDTimeStampsRaw); + bool gotBeamgatesRaw = m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgatesRaw", LAPPDBeamgatesRaw); + bool gotOffsets = m_data->Stores["ANNIEEvent"]->Get("LAPPDOffsets", LAPPDOffsets); + bool gotTSCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDTSCorrection", LAPPDTSCorrection); + bool gotDBGCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDBGCorrection", LAPPDBGCorrection); + bool gotOSInMinusPS = m_data->Stores["ANNIEEvent"]->Get("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::Execute() MultiLAPPDMapTreeMaker get map = " << getMap << endl; + if (getMap) + { + if (treeMakerVerbosity > 0) + cout << "map size: " << LAPPDDataMap.size() << endl; + for (auto &item : LAPPDDataMap) + { + PsecData thisData = item.second; + int thisLAPPD_ID = thisData.LAPPD_ID; + + uint64_t thisDataTime = item.first; + uint64_t thisTSRaw = LAPPDTimeStampsRaw.at(thisDataTime); + uint64_t thisBGRaw = LAPPDBeamgatesRaw.at(thisDataTime); + uint64_t thisOffset = LAPPDOffsets.at(thisDataTime); + int thisTSCorr = LAPPDTSCorrection.at(thisDataTime); + int thisDBGCorr = LAPPDBGCorrection.at(thisDataTime); + int thisOSInMinusPS = LAPPDOSInMinusPS.at(thisDataTime); + + if (treeMakerVerbosity > 0) + cout << "outside tree maker, Got LAPPD ID: " << thisLAPPD_ID << ", time stamp: " << thisDataTime << ", TSraw " << thisTSRaw << ", BGraw " << thisBGRaw << ", offset " << thisOffset << ", TSCorr " << thisTSCorr << ", DBGCorr " << thisDBGCorr << ", OSInMinusPS " << thisOSInMinusPS << endl; + + LAPPD_IDs.push_back(thisLAPPD_ID); + LAPPDMapTimeStampRaw.push_back(thisTSRaw); + LAPPDMapBeamgateRaw.push_back(thisBGRaw); + LAPPDMapOffsets.push_back(thisOffset); + LAPPDMapTSCorrections.push_back(thisTSCorr); + LAPPDMapBGCorrections.push_back(thisDBGCorr); + LAPPDMapOSInMinusPS.push_back(thisOSInMinusPS); + + if (treeMakerVerbosity > 0) + cout << "outside size of LAPPD_IDs: " << LAPPD_IDs.size() << endl; + } + } + else + { + cout << "outside LAPPDTreeMaker::LoadLAPPDMapInfo, no LAPPDDataMap found" << endl; + } + + if (treeMakerVerbosity > 0) + { + cout << "LAPPDMapTimeStampRaw: "; + for (auto &item : LAPPDMapTimeStampRaw) + cout << item << " "; + cout << "LAPPDTreeMaker::Execute() MultiLAPPDMapTreeMaker finished " << endl; + } + } + + if (LoadPPSTimestamp && LoadingPPS) + { + bool gotPPSTimestamp = m_data->CStore.Get("LAPPDPPSVector", pps_vector); + bool gotPPSCounter = m_data->CStore.Get("LAPPDPPScount", pps_count_vector); + if (!gotPPSTimestamp) + cout << "Error in getting PPS timestamp" << endl; + if (!gotPPSCounter) + cout << "Error in getting PPS counter" << endl; + if (gotPPSTimestamp && gotPPSCounter) + FillPPSTimestamp(); + } + + if (LoadLAPPDDataTimeStamp && !LoadingPPS) + { + bool newDataEvent; + m_data->CStore.Get("LAPPD_new_event", newDataEvent); + if (newDataEvent) + FillLAPPDDataTimeStamp(); + m_data->CStore.Set("LAPPD_new_event", true); + } + + if (LoadPulse && LAPPDana) + { + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::Execute() LoadPulse" << endl; + bool gotPulse = m_data->Stores["ANNIEEvent"]->Get(treeMakerInputPulseLabel, lappdPulses); + if (!gotPulse) + cout << "Error in getting LAPPD pulses" << endl; + if (gotPulse) + FillPulseTree(); + } + + if (LoadHit && LAPPDana) + { + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::Execute() LoadHit" << endl; + bool gotHit = m_data->Stores["ANNIEEvent"]->Get(treeMakerInputHitLabel, lappdHits); + if (!gotHit) + cout << "Error in getting LAPPD hits" << endl; + if (gotHit) + FillHitTree(); + } + + if (LoadWaveform && LAPPDana) + { + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::Execute() LoadWaveform" << endl; + bool gotWaveformMax = m_data->Stores["ANNIEEvent"]->Get("waveformMax", waveformMax); + if (!gotWaveformMax) + cout << "Error in getting waveform max" << endl; + bool gotWaveformRMS = m_data->Stores["ANNIEEvent"]->Get("waveformRMS", waveformRMS); + if (!gotWaveformRMS) + cout << "Error in getting waveform RMS" << endl; + bool gotWaveformMaxLast = m_data->Stores["ANNIEEvent"]->Get("waveformMaxLast", waveformMaxLast); + if (!gotWaveformMaxLast) + cout << "Error in getting waveform max last" << endl; + bool gotWaveformMaxNearing = m_data->Stores["ANNIEEvent"]->Get("waveformMaxNearing", waveformMaxNearing); + if (!gotWaveformMaxNearing) + cout << "Error in getting waveform max nearing" << endl; + bool gotWaveformMaxTimeBin = m_data->Stores["ANNIEEvent"]->Get("waveformMaxTimeBin", waveformMaxTimeBin); + if (!gotWaveformMaxTimeBin) + cout << "Error in getting waveform max time bin" << endl; + + if (gotWaveformMax && gotWaveformRMS && gotWaveformMaxLast && gotWaveformMaxNearing && gotWaveformMaxTimeBin) + FillWaveformTree(); + } + + if (LAPPDana) + EventNumber++; + + if (TriggerWordMap != nullptr) + TriggerWordMap->clear(); + + return true; +} + +bool LAPPDTreeMaker::Finalise() +{ + file->cd(); + fPulse->Write(); + fHit->Write(); + fWaveform->Write(); + fTimeStamp->Write(); + fTrigger->Write(); + fGroupedTrigger->Write(); + file->Close(); + return true; +} + +void LAPPDTreeMaker::CleanVariables() +{ + LAPPDana = false; + + RunNumber = -9999; + SubRunNumber = -9999; + PartFileNumber = -9999; + + lappdPulses.clear(); + lappdHits.clear(); + lappdData.clear(); + waveformMax.clear(); + waveformRMS.clear(); + waveformMaxLast.clear(); + waveformMaxNearing.clear(); + waveformMaxTimeBin.clear(); + pps_vector.clear(); + pps_count_vector.clear(); + + LAPPD_ID = -9999; + ChannelID = -9999; + PeakTime = -9999; + Charge = -9999; + PeakAmp = -9999; + PulseStart = -9999; + PulseEnd = -9999; + PulseSize = -9999; + PulseSide = -9999; + PulseThreshold = -9999; + PulseBaseline = -9999; + + HitTime = -9999; + HitAmp = -9999; + XPosTank = -9999; + YPosTank = -9999; + ZPosTank = -9999; + ParallelPos = -9999; + TransversePos = -9999; + Pulse1StartTime = -9999; + Pulse2StartTime = -9999; + Pulse1LastTime = -9999; + Pulse2LastTime = -9999; + + LAPPDDataTimeStampUL = 0; + LAPPDDataBeamgateUL = 0; + LAPPDDataTimestampPart1 = 0; + LAPPDDataBeamgatePart1 = 0; + LAPPDDataTimestampPart2 = -9999; + LAPPDDataBeamgatePart2 = -9999; + + ppsDiff = -9999; + ppsCount0 = 0; + ppsCount1 = 0; + ppsTime0 = 0; + ppsTime1 = 0; + + CTCTimeStamp = 0; + CTCTriggerWord.clear(); + trigNumInThisMap = -9999; + trigIndexInThisMap = 0; + + groupedTriggerWordsVector.clear(); + groupedTriggerTimestampsVector.clear(); + groupedTriggerWords.clear(); + groupedTriggerTimestamps.clear(); + groupedTriggerByType.clear(); + groupedTriggerType = -9999; + TriggerGroupNumInThisEvent = 0; // start from 0 + groupedTriggerType = -9999; + + LAPPD_IDs.clear(); + LAPPDMapTimeStampRaw.clear(); + LAPPDMapBeamgateRaw.clear(); + LAPPDMapOffsets.clear(); + LAPPDMapTSCorrections.clear(); + LAPPDMapBGCorrections.clear(); + LAPPDMapOSInMinusPS.clear(); + + LAPPDDataMap.clear(); + LAPPDBeamgate_ns.clear(); + LAPPDTimeStamps_ns.clear(); + LAPPDTimeStampsRaw.clear(); + LAPPDBeamgatesRaw.clear(); + LAPPDOffsets.clear(); + LAPPDTSCorrection.clear(); + LAPPDBGCorrection.clear(); + LAPPDOSInMinusPS.clear(); +} + +bool LAPPDTreeMaker::LoadRunInfoFromRaw() +{ + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::LoadRunInfoFromRaw" << endl; + m_data->CStore.Get("runNumber", RunNumber); + m_data->CStore.Get("rawFileNumber", PartFileNumber); + m_data->CStore.Get("subrunNumber", SubRunNumber); + return true; +} + +bool LAPPDTreeMaker::LoadRunInfoFromANNIEEvent() +{ + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::LoadRunInfoFromANNIEEvent" << endl; + m_data->Stores["ANNIEEvent"]->Get("RunNumber", RunNumber); + m_data->Stores["ANNIEEvent"]->Get("SubRunNumber", SubRunNumber); + m_data->Stores["ANNIEEvent"]->Get("PartNumber", PartFileNumber); + if (treeMakerVerbosity > 0) + cout << "RunNumber: " << RunNumber << ", SubRunNumber: " << SubRunNumber << ", PartFileNumber: " << PartFileNumber << endl; + return true; +} + +bool LAPPDTreeMaker::FillPulseTree() +{ + // LAPPDPulse thisPulse(LAPPD_ID, channel, peakBin*(25./256.), Q, peakAmp, pulseStart, pulseStart+pulseSize); + std::map>>::iterator it; + int foundPulseNum = 0; + if (lappdPulses.size() == 0) + { + if (treeMakerVerbosity > 0) + cout << "No pulses found" << endl; + return true; + } + for (it = lappdPulses.begin(); it != lappdPulses.end(); it++) + { + int stripno = it->first; + vector> stripPulses = it->second; + vector pulse0 = stripPulses.at(0); + vector pulse1 = stripPulses.at(1); + for (int i = 0; i < pulse0.size(); i++) + { + PulseSide = 0; + LAPPDPulse thisPulse = pulse0.at(i); + LAPPD_ID = thisPulse.GetTubeId(); + ChannelID = thisPulse.GetChannelID(); + StripNumber = stripno; + PeakTime = thisPulse.GetTime(); + Charge = thisPulse.GetCharge(); + PeakAmp = thisPulse.GetPeak(); + PulseStart = thisPulse.GetLowRange(); + PulseEnd = thisPulse.GetHiRange(); + PulseSize = PulseEnd - PulseStart; + // cout << " tree maker, this pulse0 LAPPD ID is " << LAPPD_ID << endl; + // TODO save threshold and baseline + if (MultiLAPPDMapTreeMaker) + { + // find the LAPPD_ID in LAPPD_IDs, get the index + // use that index to get the timestamp and beamgate + // if not found, set them to zero + int index = std::distance(LAPPD_IDs.begin(), std::find(LAPPD_IDs.begin(), LAPPD_IDs.end(), LAPPD_ID)); + if (index < LAPPDMapTimeStampRaw.size()) + { + LTSRaw = LAPPDMapTimeStampRaw.at(index); + LBGRaw = LAPPDMapBeamgateRaw.at(index); + LOffset_ns = LAPPDMapOffsets.at(index); + LTSCorrection = LAPPDMapTSCorrections.at(index); + LBGCorrection = LAPPDMapBGCorrections.at(index); + LOSInMinusPS = LAPPDMapOSInMinusPS.at(index); + } + else + { + LTSRaw = 0; + LBGRaw = 0; + LOffset_ns = 0; + LTSCorrection = 0; + LBGCorrection = 0; + LOSInMinusPS = 0; + } + } + + fPulse->Fill(); + foundPulseNum++; + } + for (int i = 0; i < pulse1.size(); i++) + { + PulseSide = 1; + LAPPDPulse thisPulse = pulse1.at(i); + LAPPD_ID = thisPulse.GetTubeId(); + ChannelID = thisPulse.GetChannelID(); + StripNumber = stripno; + PeakTime = thisPulse.GetTime(); + Charge = thisPulse.GetCharge(); + PeakAmp = thisPulse.GetPeak(); + PulseStart = thisPulse.GetLowRange(); + PulseEnd = thisPulse.GetHiRange(); + PulseSize = PulseEnd - PulseStart; + /*cout << " this pulse1 LAPPD ID is " << LAPPD_ID << endl; + cout << "ThresReco pulse1 got LAPPD_IDs: "; + for (int i = 0; i < LAPPD_IDs.size(); i++) + { + cout << LAPPD_IDs.at(i) << " "; + }*/ + // TODO save threshold and baseline + if (MultiLAPPDMapTreeMaker) + { + // find the index of LAPPD_ID in LAPPD_IDs, use that index to assign the timestamlUL and beam gate UL, if not found set them to zero + int index = std::distance(LAPPD_IDs.begin(), std::find(LAPPD_IDs.begin(), LAPPD_IDs.end(), LAPPD_ID)); + if (index < LAPPDMapTimeStampRaw.size()) + { + LTSRaw = LAPPDMapTimeStampRaw.at(index); + LBGRaw = LAPPDMapBeamgateRaw.at(index); + LOffset_ns = LAPPDMapOffsets.at(index); + LTSCorrection = LAPPDMapTSCorrections.at(index); + LBGCorrection = LAPPDMapBGCorrections.at(index); + LOSInMinusPS = LAPPDMapOSInMinusPS.at(index); + } + else + { + LTSRaw = 0; + LBGRaw = 0; + LOffset_ns = 0; + LTSCorrection = 0; + LBGCorrection = 0; + LOSInMinusPS = 0; + } + } + fPulse->Fill(); + foundPulseNum++; + } + } + if (treeMakerVerbosity > 0) + cout << "Found and saved " << foundPulseNum << " pulses" << endl; + return true; +} + +bool LAPPDTreeMaker::FillHitTree() +{ + // LAPPDHit hit(tubeID, averageTimeLow, averageAmp, positionInTank, positionOnLAPPD, pulse1LastTime, pulse2LastTime, pulse1StartTime, pulse2StartTime); + int foundHitNum = 0; + if (lappdHits.size() == 0) + { + if (treeMakerVerbosity > 0) + cout << "No hits found" << endl; + return true; + } + std::map>::iterator it; + for (it = lappdHits.begin(); it != lappdHits.end(); it++) + { + int stripno = it->first; + vector stripHits = it->second; + for (int i = 0; i < stripHits.size(); i++) + { + LAPPDHit thisHit = stripHits.at(i); + LAPPD_ID = thisHit.GetTubeId(); + StripNumber = stripno; + HitTime = thisHit.GetTime(); + HitAmp = thisHit.GetCharge(); + vector position = thisHit.GetPosition(); + XPosTank = position.at(0); + YPosTank = position.at(1); + ZPosTank = position.at(2); + vector localPosition = thisHit.GetLocalPosition(); + ParallelPos = localPosition.at(0); + TransversePos = localPosition.at(1); + Pulse1StartTime = thisHit.GetPulse1StartTime(); + Pulse2StartTime = thisHit.GetPulse2StartTime(); + Pulse1LastTime = thisHit.GetPulse1LastTime(); + Pulse2LastTime = thisHit.GetPulse2LastTime(); + if (treeMakerVerbosity > 0) + { + cout << " this hit LAPPD ID is " << LAPPD_ID << endl; + cout << "ThresReco hit got LAPPD_IDs: "; + for (int i = 0; i < LAPPD_IDs.size(); i++) + { + cout << LAPPD_IDs.at(i) << " "; + } + } + if (MultiLAPPDMapTreeMaker) + { + // find the LAPPD_ID in LAPPD_IDs, get the index + // use that index to get the timestamp and beamgate + // if not found, set them to zero + int index = std::distance(LAPPD_IDs.begin(), std::find(LAPPD_IDs.begin(), LAPPD_IDs.end(), LAPPD_ID)); + if (index < LAPPDMapTimeStampRaw.size()) + { + LTSRaw = LAPPDMapTimeStampRaw.at(index); + LBGRaw = LAPPDMapBeamgateRaw.at(index); + LOffset_ns = LAPPDMapOffsets.at(index); + LTSCorrection = LAPPDMapTSCorrections.at(index); + LBGCorrection = LAPPDMapBGCorrections.at(index); + LOSInMinusPS = LAPPDMapOSInMinusPS.at(index); + } + else + { + LTSRaw = 0; + LBGRaw = 0; + LOffset_ns = 0; + LTSCorrection = 0; + LBGCorrection = 0; + LOSInMinusPS = 0; + } + } + fHit->Fill(); + foundHitNum++; + } + } + if (treeMakerVerbosity > 0) + cout << "Found and saved " << foundHitNum << " hits" << endl; + return true; +} + +bool LAPPDTreeMaker::FillWaveformTree() +{ + if (waveformMax.size() == 0) + { + if (treeMakerVerbosity > 0) + cout << "No waveforms found" << endl; + return true; + } + std::map>::iterator it; + for (it = waveformMax.begin(); it != waveformMax.end(); it++) + { + int key = it->first; + LAPPD_ID = static_cast(key / 60); + int stripSide = static_cast((key - LAPPD_ID * 60) / 30); + StripNumber = key - LAPPD_ID * 60 - stripSide * 30; + // cout << " this waveform LAPPD ID is " << LAPPD_ID << endl; + + for (int side = 0; side < 2; side++) + { + PulseSide = side; + waveformMaxValue = waveformMax.at(key).at(side); + waveformRMSValue = waveformRMS.at(key).at(side); + waveformMaxFoundNear = waveformMaxLast.at(key).at(side); + waveformMaxNearingValue = waveformMaxNearing.at(key).at(side); + waveformMaxTimeBinValue = waveformMaxTimeBin.at(key).at(side); + /*cout << " LAPPDTreeMaker fill waveform tree, LAPPD ID is " << LAPPD_ID << endl; + cout << "ThresReco got LAPPD_IDs: "; + for (int i = 0; i < LAPPD_IDs.size(); i++) + { + cout << LAPPD_IDs.at(i) << " "; + }*/ + if (MultiLAPPDMapTreeMaker) + { + // find the LAPPD_ID in LAPPD_IDs, get the index + // use that index to get the timestamp and beamgate + // if not found, set them to zero + int index = std::distance(LAPPD_IDs.begin(), std::find(LAPPD_IDs.begin(), LAPPD_IDs.end(), LAPPD_ID)); + if (index < LAPPDMapTimeStampRaw.size()) + { + LTSRaw = LAPPDMapTimeStampRaw.at(index); + LBGRaw = LAPPDMapBeamgateRaw.at(index); + LOffset_ns = LAPPDMapOffsets.at(index); + LTSCorrection = LAPPDMapTSCorrections.at(index); + LBGCorrection = LAPPDMapBGCorrections.at(index); + LOSInMinusPS = LAPPDMapOSInMinusPS.at(index); + } + else + { + LTSRaw = 0; + LBGRaw = 0; + LOffset_ns = 0; + LTSCorrection = 0; + LBGCorrection = 0; + LOSInMinusPS = 0; + } + } + fWaveform->Fill(); + } + } + if (treeMakerVerbosity > 0) + cout << "Found and saved " << waveformMax.size() << " waveforms" << endl; + return true; +} + +bool LAPPDTreeMaker::FillPPSTimestamp() +{ + ppsTime0 = pps_vector.at(0); + ppsTime1 = pps_vector.at(1); + ppsCount0 = pps_count_vector.at(0); + ppsCount1 = pps_count_vector.at(1); + ppsDiff = ppsTime1 - ppsTime0; + m_data->CStore.Get("LAPPD_ID", LAPPD_ID); + if (treeMakerVerbosity > 0) + cout << "LAPPD_ID: " << LAPPD_ID << ", ppsDiff: " << ppsDiff << ", ppsTime0: " << ppsTime0 << ", ppsTime1: " << ppsTime1 << ", ppsCount0: " << ppsCount0 << ", ppsCount1: " << ppsCount1 << endl; + fTimeStamp->Fill(); + return true; +} + +bool LAPPDTreeMaker::FillLAPPDDataTimeStamp() +{ + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::FillLAPPDDataTimeStamp. Before fill: LAPPDDataTimeStampUL: " << LAPPDDataTimeStampUL << ", LAPPDDataBeamgateUL: " << LAPPDDataBeamgateUL << ", LAPPDDataTimestampPart1: " << LAPPDDataTimestampPart1 << ", LAPPDDataBeamgatePart1: " << LAPPDDataBeamgatePart1 << ", LAPPDDataTimestampPart2: " << LAPPDDataTimestampPart2 << ", LAPPDDataBeamgatePart2: " << LAPPDDataBeamgatePart2 << endl; + if (!MultiLAPPDMapTreeMaker) + { + m_data->CStore.Get("LAPPDBeamgate_Raw", LAPPDDataBeamgateUL); + m_data->CStore.Get("LAPPDTimestamp_Raw", LAPPDDataTimeStampUL); + m_data->CStore.Get("LAPPDBGIntCombined", LAPPDDataBeamgatePart1); + m_data->CStore.Get("LAPPDBGFloat", LAPPDDataBeamgatePart2); + m_data->CStore.Get("LAPPDTSIntCombined", LAPPDDataTimestampPart1); + m_data->CStore.Get("LAPPDTSFloat", LAPPDDataTimestampPart2); + m_data->CStore.Get("LAPPD_ID", LAPPD_ID); + fTimeStamp->Fill(); + } + else + { + for (int i = 0; i < LAPPD_IDs.size(); i++) + { + LAPPD_ID = LAPPD_IDs.at(i); + LAPPDDataBeamgateUL = LAPPDMapBeamgateRaw.at(i); + LAPPDDataTimeStampUL = LAPPDMapTimeStampRaw.at(i); + fTimeStamp->Fill(); + } + } + if (treeMakerVerbosity > 0) + cout << "LAPPDDataTimeStampUL: " << LAPPDDataTimeStampUL << ", LAPPDDataBeamgateUL: " << LAPPDDataBeamgateUL << ", LAPPDDataTimestampPart1: " << LAPPDDataTimestampPart1 << ", LAPPDDataBeamgatePart1: " << LAPPDDataBeamgatePart1 << ", LAPPDDataTimestampPart2: " << LAPPDDataTimestampPart2 << ", LAPPDDataBeamgatePart2: " << LAPPDDataBeamgatePart2 << endl; + return true; +} + +bool LAPPDTreeMaker::FillTriggerTree() +{ + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::FillTriggerTree" << endl; + + trigNumInThisMap = TriggerWordMap->size(); + for (const auto &item : *TriggerWordMap) + { + CTCTimeStamp = item.first; + CTCTriggerWord = item.second; + fTrigger->Fill(); + trigIndexInThisMap++; + } + if (treeMakerVerbosity > 0) + cout << "FillTriggerTree: " << trigNumInThisMap << " triggers filled" << endl; + + return true; +} + +bool LAPPDTreeMaker::FillGroupedTriggerTree() +{ + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::FillGroupedTriggerTree" << endl; + + // fill new triggers from the map to ungrouped trigger buffer + for (const auto &item : *TriggerWordMap) + { + CTCTimeStamp = item.first; + CTCTriggerWord = item.second; + + for (const auto &trigw : CTCTriggerWord) + { + unGroupedTriggerTimestamps.push_back(CTCTimeStamp); + unGroupedTriggerWords.push_back(trigw); + } + } + + if (LoadGroupOption == "beam") + GroupTriggerByBeam(); + else if (LoadGroupOption == "laser") + GroupTriggerByLaser(); + + GroupPPSTrigger(); + + for (int i = 0; i < groupedTriggerWordsVector.size(); i++) + { + groupedTriggerWords = groupedTriggerWordsVector.at(i); + groupedTriggerTimestamps = groupedTriggerTimestampsVector.at(i); + groupedTriggerType = groupedTriggerByType.at(i); + fGroupedTrigger->Fill(); + TriggerGroupNumInThisEvent += 1; + } + + CleanTriggers(); + + return true; +} + +bool LAPPDTreeMaker::GroupTriggerByBeam() +{ + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::GroupTriggerByBeam" << endl; + + vector removeIndex; + bool beamNow = false; + bool trigger2ed = false; + bool trigger14ed = false; + bool trigger1ed = false; + int beamConfirm = 0; + vector thisTGroup; + vector thisTTimestamp; + bool ppsNow = false; + + for (int i = 0; i < unGroupedTriggerWords.size(); i++) + { + uint32_t tWord = unGroupedTriggerWords.at(i); + unsigned long tTime = unGroupedTriggerTimestamps.at(i); + bool pushedToBuffer = false; + if (!beamNow) + { + // not in a beam group + if (tWord == 3) + { + beamNow = true; + beamConfirm = 0; + thisTGroup.push_back(tWord); + thisTTimestamp.push_back(tTime); + pushedToBuffer = true; + trigger2ed = false; + trigger14ed = false; + trigger1ed = false; + } + } + else + { // while in a group + if (beamConfirm <= 2 && tWord == 3) + { + // in grouping mode, meet a new start, but haven't got enough trigger 14 and 2 + // clear buffer, restart the grouping from this t 3 + thisTGroup.clear(); + thisTTimestamp.clear(); + beamNow = true; + thisTGroup.push_back(tWord); + thisTTimestamp.push_back(tTime); + pushedToBuffer = true; + trigger2ed = false; + trigger14ed = false; + trigger1ed = false; + } + + if (beamConfirm > 2 && tWord == 10) + { + // if beam confirmed and meet a trigger 10, save the grouped triggers + // 10 always come with 8, which is delayed trigger to MRD + thisTGroup.push_back(tWord); + thisTTimestamp.push_back(tTime); + pushedToBuffer = true; + // if found trigger 14 and 2, save the grouped triggers + if ((std::find(thisTGroup.begin(), thisTGroup.end(), 14) != thisTGroup.end()) && (std::find(thisTGroup.begin(), thisTGroup.end(), 2) != thisTGroup.end())) + { + groupedTriggerWordsVector.push_back(thisTGroup); + groupedTriggerTimestampsVector.push_back(thisTTimestamp); + groupedTriggerByType.push_back(14); + } + thisTGroup.clear(); + thisTTimestamp.clear(); + beamNow = false; + trigger14ed = false; + trigger2ed = false; + trigger1ed = false; + beamConfirm = 0; + } + + if (!pushedToBuffer && tWord != 32 && tWord != 34 && tWord != 36) + { + if (tWord == 2) + { + trigger2ed = true; + beamConfirm++; + } + + if (tWord != 14) + { + thisTGroup.push_back(tWord); + thisTTimestamp.push_back(tTime); + } + else if (!trigger14ed) + { + thisTGroup.push_back(tWord); + thisTTimestamp.push_back(tTime); + trigger14ed = true; + beamConfirm++; + } + pushedToBuffer = true; + } + } + + if (pushedToBuffer) + { + removeIndex.push_back(i); + } + } + + vector unRemovedTriggerWords; + vector unRemovedTriggerTimestamps; + for (int i = 0; i < unGroupedTriggerWords.size(); i++) + { + if (std::find(removeIndex.begin(), removeIndex.end(), i) == removeIndex.end()) + { + unRemovedTriggerWords.push_back(unGroupedTriggerWords.at(i)); + unRemovedTriggerTimestamps.push_back(unGroupedTriggerTimestamps.at(i)); + } + } + unGroupedTriggerTimestamps = unRemovedTriggerTimestamps; + unGroupedTriggerWords = unRemovedTriggerWords; + + return true; +} + +bool LAPPDTreeMaker::GroupPPSTrigger() +{ + if (treeMakerVerbosity > 0) + cout << "LAPPDTreeMaker::GroupPPSTrigger" << endl; + + vector removeIndex; + vector thisTGroup; + vector thisTTimestamp; + bool ppsNow = false; + for (int i = 0; i < unGroupedTriggerWords.size(); i++) + { + uint32_t tWord = unGroupedTriggerWords.at(i); + unsigned long tTime = unGroupedTriggerTimestamps.at(i); + bool pushedToBuffer = false; + if (!ppsNow) + { + if (tWord == 32) + { + ppsNow = true; + thisTGroup.push_back(tWord); + thisTTimestamp.push_back(tTime); + pushedToBuffer = true; + } + } + else + { + if (tWord == 34) + { + thisTGroup.push_back(tWord); + thisTTimestamp.push_back(tTime); + pushedToBuffer = true; + groupedTriggerWordsVector.push_back(thisTGroup); + groupedTriggerTimestampsVector.push_back(thisTTimestamp); + groupedTriggerByType.push_back(32); + thisTGroup.clear(); + thisTTimestamp.clear(); + ppsNow = false; + } + } + + if (pushedToBuffer) + { + removeIndex.push_back(i); + } + } + + vector unRemovedTriggerWords; + vector unRemovedTriggerTimestamps; + for (int i = 0; i < unGroupedTriggerWords.size(); i++) + { + if (std::find(removeIndex.begin(), removeIndex.end(), i) == removeIndex.end()) + { + unRemovedTriggerWords.push_back(unGroupedTriggerWords.at(i)); + unRemovedTriggerTimestamps.push_back(unGroupedTriggerTimestamps.at(i)); + } + } + unGroupedTriggerTimestamps = unRemovedTriggerTimestamps; + unGroupedTriggerWords = unRemovedTriggerWords; + return true; +} + +bool LAPPDTreeMaker::GroupTriggerByLaser() +{ + // waiting for implementation + return true; +} + +void LAPPDTreeMaker::CleanTriggers() +{ + // only keep the last 1000 triggers + // create new vector to store the last 1000 triggers + if (unGroupedTriggerWords.size() > 1000) + { + std::vector lastTrigWords(unGroupedTriggerWords.end() - 1000, unGroupedTriggerWords.end()); + unGroupedTriggerWords = lastTrigWords; + std::vector lastTrigTimestamps(unGroupedTriggerTimestamps.end() - 1000, unGroupedTriggerTimestamps.end()); + unGroupedTriggerTimestamps = lastTrigTimestamps; + } +} + +void LAPPDTreeMaker::LoadLAPPDMapInfo() +{ + // cout << "LAPPDTreeMaker::LoadLAPPDMapInfo" << endl; + bool getMap = m_data->Stores["ANNIEEvent"]->Get("LAPPDDataMap", LAPPDDataMap); + bool gotBeamgates_ns = m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgate_ns", LAPPDBeamgate_ns); + bool gotTimeStamps_ns = m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStamps_ns", LAPPDTimeStamps_ns); + bool gotTimeStampsRaw = m_data->Stores["ANNIEEvent"]->Get("LAPPDTimeStampsRaw", LAPPDTimeStampsRaw); + bool gotBeamgatesRaw = m_data->Stores["ANNIEEvent"]->Get("LAPPDBeamgatesRaw", LAPPDBeamgatesRaw); + bool gotOffsets = m_data->Stores["ANNIEEvent"]->Get("LAPPDOffsets", LAPPDOffsets); + bool gotTSCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDTSCorrection", LAPPDTSCorrection); + bool gotDBGCorrection = m_data->Stores["ANNIEEvent"]->Get("LAPPDBGCorrection", LAPPDBGCorrection); + bool gotOSInMinusPS = m_data->Stores["ANNIEEvent"]->Get("LAPPDOSInMinusPS", LAPPDOSInMinusPS); + // cout << "LAPPDTreeMaker::LoadLAPPDMapInfo() get map = " << getMap << endl; + + if (getMap) + { + if (treeMakerVerbosity > 0) + cout << "map size: " << LAPPDDataMap.size() << endl; + for (auto &item : LAPPDDataMap) + { + PsecData thisData = item.second; + int thisLAPPD_ID = thisData.LAPPD_ID; + + uint64_t thisDataTime = item.first; + uint64_t thisTSRaw = LAPPDTimeStampsRaw.at(thisDataTime); + uint64_t thisBGRaw = LAPPDBeamgatesRaw.at(thisDataTime); + uint64_t thisOffset = LAPPDOffsets.at(thisDataTime); + int thisTSCorr = LAPPDTSCorrection.at(thisDataTime); + int thisDBGCorr = LAPPDBGCorrection.at(thisDataTime); + int thisOSInMinusPS = LAPPDOSInMinusPS.at(thisDataTime); + + if (treeMakerVerbosity > 0) + cout << "tree maker, Got LAPPD ID: " << thisLAPPD_ID << ", time stamp: " << thisDataTime << ", TSraw " << thisTSRaw << ", BGraw " << thisBGRaw << ", offset " << thisOffset << ", TSCorr " << thisTSCorr << ", DBGCorr " << thisDBGCorr << ", OSInMinusPS " << thisOSInMinusPS << endl; + + LAPPD_IDs.push_back(thisLAPPD_ID); + LAPPDMapTimeStampRaw.push_back(thisTSRaw); + LAPPDMapBeamgateRaw.push_back(thisBGRaw); + LAPPDMapOffsets.push_back(thisOffset); + LAPPDMapTSCorrections.push_back(thisTSCorr); + LAPPDMapBGCorrections.push_back(thisDBGCorr); + LAPPDMapOSInMinusPS.push_back(thisOSInMinusPS); + + if (treeMakerVerbosity > 0) + cout << "size of LAPPD_IDs: " << LAPPD_IDs.size() << endl; + } + } + else + { + cout << "LAPPDTreeMaker::LoadLAPPDMapInfo, no LAPPDDataMap found" << endl; + } +} \ No newline at end of file diff --git a/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h b/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h new file mode 100644 index 000000000..9fc491e2b --- /dev/null +++ b/UserTools/LAPPDTreeMaker/LAPPDTreeMaker.h @@ -0,0 +1,185 @@ +#ifndef LAPPDTreeMaker_H +#define LAPPDTreeMaker_H + +#include +#include + +#include "Tool.h" +#include "TTree.h" +#include "TFile.h" +#include "TString.h" +#include "LAPPDPulse.h" +#include "LAPPDHit.h" +#include "Geometry.h" +#include "Position.h" +#include "PsecData.h" + +/** + * \class LAPPDTreeMaker + * + * This is a blank template for a Tool used by the script to generate a new custom tool. Please fill out the description and author information. + * + * $Author: Yue Feng $ + * $Date: 2024/02/03 16:10:00 $ + * Contact: yuef@iastate.edu + */ +class LAPPDTreeMaker : public Tool +{ + +public: + LAPPDTreeMaker(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + void CleanVariables(); + bool FillPulseTree(); + bool FillHitTree(); + bool FillWaveformTree(); + bool FillPPSTimestamp(); + bool FillLAPPDDataTimeStamp(); + bool LoadRunInfoFromRaw(); + bool LoadRunInfoFromANNIEEvent(); + bool GroupTriggerByBeam(); + bool GroupTriggerByLaser(); + bool GroupPPSTrigger(); + bool FillTriggerTree(); + bool FillGroupedTriggerTree(); + void CleanTriggers(); + void LoadLAPPDMapInfo(); + +private: + TFile *file; + TTree *fPulse; + TTree *fHit; + TTree *fWaveform; + TTree *fTimeStamp; + TTree *fTrigger; + TTree *fGroupedTrigger; + + int treeMakerVerbosity; + bool LAPPDana; + bool LoadingPPS; + + bool LoadPulse; + bool LoadHit; + bool LoadWaveform; + bool LoadLAPPDDataTimeStamp; + bool LoadPPSTimestamp; + bool LoadRunInfoRaw; + bool LoadRunInfoANNIEEvent; + bool LoadTriggerInfo; + bool LoadGroupedTriggerInfo; + string LoadGroupOption; // using beam, or laser, or other. + + std::map>> lappdData; + std::map> waveformMax; // strip number+30*side, value + std::map> waveformRMS; + std::map> waveformMaxLast; + std::map> waveformMaxNearing; + std::map> waveformMaxTimeBin; + + map> *TriggerWordMap; + unsigned long CTCTimeStamp; + std::vector CTCTriggerWord; + int trigNumInThisMap; + int trigIndexInThisMap; + int TriggerGroupNumInThisEvent; + int groupedTriggerType; + + vector unGroupedTriggerWords; + vector unGroupedTriggerTimestamps; + vector> groupedTriggerWordsVector; + vector> groupedTriggerTimestampsVector; + vector groupedTriggerByType; + vector groupedTriggerWords; + vector groupedTriggerTimestamps; + + double waveformMaxValue; + double waveformRMSValue; + bool waveformMaxFoundNear; + double waveformMaxNearingValue; + int waveformMaxTimeBinValue; + + std::map>> lappdPulses; + std::map> lappdHits; + Geometry *_geom; + string treeMakerInputPulseLabel; + string treeMakerInputHitLabel; + string treeMakerOutputFileName; + + int EventNumber; // this is for LAPPD relate event number, data or PPS, not trigger!! + int StripNumber; + + int LAPPD_ID; + int ChannelID; + double PeakTime; + double Charge; + double PeakAmp; + double PulseStart; + double PulseEnd; + double PulseSize; + int PulseSide; + double PulseThreshold; + double PulseBaseline; + + double HitTime; + double HitAmp; + double XPosTank; + double YPosTank; + double ZPosTank; + double ParallelPos; + double TransversePos; + double Pulse1StartTime; + double Pulse2StartTime; + double Pulse1LastTime; + double Pulse2LastTime; + + unsigned long LAPPDDataTimeStampUL; + unsigned long LAPPDDataBeamgateUL; + unsigned long LAPPDDataTimestampPart1; + unsigned long LAPPDDataBeamgatePart1; + double LAPPDDataTimestampPart2; + double LAPPDDataBeamgatePart2; + + vector pps_vector; + vector pps_count_vector; + Long64_t ppsDiff; + unsigned long ppsCount0; + unsigned long ppsCount1; + unsigned long ppsTime0; // in clock tick, without 3.125ns + unsigned long ppsTime1; // in clock tick, without 3.125ns + + int RunNumber; + int SubRunNumber; + int PartFileNumber; + + bool MultiLAPPDMapTreeMaker; + vector LAPPD_IDs; + vector LAPPDMapTimeStampRaw; + vector LAPPDMapBeamgateRaw; + vector LAPPDMapOffsets; + vector LAPPDMapTSCorrections; + vector LAPPDMapBGCorrections; + vector LAPPDMapOSInMinusPS; + + std::map LAPPDDataMap; + std::map LAPPDBeamgate_ns; + std::map LAPPDTimeStamps_ns; // data and key are the same + std::map LAPPDTimeStampsRaw; + std::map LAPPDBeamgatesRaw; + std::map LAPPDOffsets; + std::map LAPPDTSCorrection; + std::map LAPPDBGCorrection; + std::map LAPPDOSInMinusPS; + + + uint64_t LTSRaw; + uint64_t LBGRaw; + uint64_t LOffset_ns; + int LTSCorrection; + int LBGCorrection; + int LOSInMinusPS; + uint64_t CTCPrimeTriggerTime; +}; + +#endif diff --git a/UserTools/LAPPDTreeMaker/README.md b/UserTools/LAPPDTreeMaker/README.md new file mode 100644 index 000000000..23363ae82 --- /dev/null +++ b/UserTools/LAPPDTreeMaker/README.md @@ -0,0 +1,20 @@ +# LAPPDTreeMaker + +LAPPDTreeMaker + +## Data + +Describe any data formats LAPPDTreeMaker creates, destroys, changes, or analyzes. E.G. + +**RawLAPPDData** `map>>` +* Takes this data from the `ANNIEEvent` store and finds the number of peaks + + +## Configuration + +Describe any configuration variables for LAPPDTreeMaker. + +``` +param1 value1 +param2 value2 +``` diff --git a/UserTools/Unity.h b/UserTools/Unity.h index 7e64d4e9b..9769ae107 100644 --- a/UserTools/Unity.h +++ b/UserTools/Unity.h @@ -182,3 +182,4 @@ #include "PrintDQ.h" #include "AssignBunchTimingMC.h" #include "FitRWMWaveform.h" +#include "LAPPDTreeMaker.h" From fc99749e09e74f59fba48cc0120056a234a7cbd7 Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Fri, 4 Apr 2025 14:33:56 -0500 Subject: [PATCH 122/163] Add changes from Steven's latest change for Event building about hits from local code at /exp/annie/app/users/doran/EB_BC_TA Changes list at https://docs.google.com/spreadsheets/d/13OXWEUbxF2vjMa6SKUKhL2rhXHUsshZY1PF4VnS7pnA/edit?gid=88985152#gid=88985152 --- .../PhaseIIADCCalibrator.cpp | 35 ++- .../PhaseIIADCHitFinder.cpp | 217 ++++++++++++++++-- .../EventBuilderV2/PhaseIIADCHitFinderConfig | 2 +- .../PhaseIIADCHitFinderConfig | 2 +- .../PhaseIIADCHitFinderConfig | 2 +- .../PhaseIIADCHitFinderConfig | 2 +- 6 files changed, 233 insertions(+), 27 deletions(-) diff --git a/UserTools/PhaseIIADCCalibrator/PhaseIIADCCalibrator.cpp b/UserTools/PhaseIIADCCalibrator/PhaseIIADCCalibrator.cpp index a85341ac1..bcca11115 100644 --- a/UserTools/PhaseIIADCCalibrator/PhaseIIADCCalibrator.cpp +++ b/UserTools/PhaseIIADCCalibrator/PhaseIIADCCalibrator.cpp @@ -723,20 +723,27 @@ PhaseIIADCCalibrator::make_calibrated_waveforms_ze3ra_multi( // come from the same readout for the same channel) std::vector< CalibratedADCWaveform > calibrated_waveforms; for (const auto& raw_waveform : raw_waveforms) { - std::vector baselines; + std::vector baselines; + std::vector sigma_baselines; std::vector RepresentationRegion; - double first_baseline=0; - double first_sigma_baseline; + bool isFirst = true; + double first_baseline, first_sigma_baseline; double baseline, sigma_baseline; const size_t nsamples = raw_waveform.Samples().size(); for(size_t starting_sample = 0; starting_sample < nsamples; starting_sample += baseline_rep_samples){ double baseline, sigma_baseline; ze3ra_baseline(raw_waveform, baseline, sigma_baseline, num_baseline_samples,starting_sample); - if(sigma_baseline4) std::cout << "BASELINE UNCERTAINTY BEYOND SET THRESHOLD. IGNORING SAMPLE" << std::endl; } } @@ -746,6 +753,7 @@ PhaseIIADCCalibrator::make_calibrated_waveforms_ze3ra_multi( if(verbosity>4) std::cout << "NO BASLINE FOUND WITHIN TOLERANCE. USING FIRST AS BEST ESTIMATE" << std::endl; RepresentationRegion.push_back(baseline_rep_samples); baselines.push_back(first_baseline); + sigma_baselines.push_back(first_sigma_baseline); } std::vector cal_data; const std::vector& raw_data = raw_waveform.Samples(); @@ -762,10 +770,23 @@ PhaseIIADCCalibrator::make_calibrated_waveforms_ze3ra_multi( } } } - double bl_estimates_mean, bl_estimates_var; - ComputeMeanAndVariance(baselines, bl_estimates_mean, bl_estimates_var); + double bl_estimates_mean = 0; + double bl_estimates_sigma = 0; + + // When averaging multiple means you need to average the variances as well + // We don't want to use the variance of the mean of all the baselines. + // If there is only one baseline then the variance is 0 if you do that... + for (size_t idx = 0; idx < baselines.size(); ++idx) { + bl_estimates_mean += baselines[idx]; + bl_estimates_sigma += pow(sigma_baselines[idx],2); + } + bl_estimates_sigma = sqrt(bl_estimates_sigma / double(baselines.size())); + bl_estimates_mean = bl_estimates_mean / double(baselines.size()); + + // ComputeMeanAndVariance(baselines, bl_estimates_mean, bl_estimates_var, std::numeric_limits::max(), 0, 7); + calibrated_waveforms.emplace_back(raw_waveform.GetStartTime(), - cal_data, bl_estimates_mean, bl_estimates_var); + cal_data, bl_estimates_mean, bl_estimates_sigma); } return calibrated_waveforms; } diff --git a/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp b/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp index 4b0d1ab25..246bd8550 100755 --- a/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp +++ b/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp @@ -386,9 +386,6 @@ bool PhaseIIADCHitFinder::Execute() { // std::cout <<"InProgressHits size (calibrator): "<size()<size()<size()<size()<size()<CStore.Set("InProgressRecoADCHits",InProgressRecoADCHits); m_data->CStore.Set("InProgressChkey",InProgressChkey); - cout<<"InProgressChkey size: "<size()<CStore.Set("InProgressHitsAux",InProgressHitsAux); // std::cout <<"FinishedRecoADCHitsAux"< PhaseIIADCHitFinder::find_pulses_bywindow( } +// ****************************************************************** +// "PulseFindingApproach" default for EventBuilding std::vector PhaseIIADCHitFinder::find_pulses_bythreshold( const Waveform& raw_minibuffer_data, const CalibratedADCWaveform& calibrated_minibuffer_data, @@ -828,8 +826,8 @@ std::vector PhaseIIADCHitFinder::find_pulses_bythreshold( if(it != ChannelKeyToTimingOffsetMap.end()){ //Timing offset is available timing_offset = ChannelKeyToTimingOffsetMap.at(channel_key); } else { - if(verbosity>2){ - std::cout << "Didn't find Timing offset for channel " << channel_key << std::endl; + if(verbosity>v_error){ + std::cout << "PhaseIIADCHitFinder: Didn't find Timing offset for channel... setting this channel's offset to 0ns" << channel_key << std::endl; } } @@ -841,7 +839,191 @@ std::vector PhaseIIADCHitFinder::find_pulses_bythreshold( calibrated_minibuffer_data.GetSigmaBaseline(), raw_area, max_ADC, calibrated_amplitude, charge); } - + + + // ****************************************************************** + // Fixed integration window defined relative to *baseline* threshold crossings + // "PulseWindowType" default for EventBuilding (to match the 2023 gains calibration integration approach) + } else if(pulse_window_type == "Fixed_2023_Gains"){ + + // 2023 Gains integration approach (same as 'full_window_maxpeak' PulseFindingApproach, but we require pulse threshold finding) + // * pulse is defined as any instance of sample above the ADC threshold + // * pulse start defined as 5 samples to the left from where the pulse emerges from the baseline + // * pulse end defined as 5 samples to the right from where the pulse returns to the baseline + + size_t pulse_start_sample = BOGUS_INT; + size_t pulse_end_sample = BOGUS_INT; + + // loop through samples until we find a pulse, then extraction pulse parameters + for (size_t s = 0; s < num_samples; ++s) { + + // if any values are above threshold, we have found a pulse + if ( !in_pulse && raw_minibuffer_data.GetSample(s) > adc_threshold ) { + in_pulse = true; + if(verbosity>v_debug) std::cout << "PhaseIIADCHitFinder: FOUND PULSE" << std::endl; + + // for cases that are very early in the buffer, we can just assign the pulse start as 0 to avoid errors + if (static_cast(s) - 5 < 0) { + if(verbosity>v_debug) std::cout << "Pulse found is VERY EARLY in the minibuffer (< 5 samples)... assigning pulse start as 0" << std::endl; + pulse_start_sample = 0; + } + + else { + size_t pulsewinleft = s; + + // determine start of pulse by walking back from the threshold crossing point until we dip below baseline, then take 5 samples before as the pulse start + while (pulsewinleft > 0) { + double raw_sample_height = raw_minibuffer_data.GetSample(pulsewinleft); + if (raw_sample_height <= baseline_plus_one_sigma) { + + if (pulsewinleft >= 5) { // avoid underflow + pulse_start_sample = pulsewinleft - 5; // pulse start = baseline crossing - 5 samples + } + + else { + if(verbosity>v_debug) std::cout << "Baseline crossing is VERY EARLY in the minibuffer (< 5 samples)... assigning pulse start as 0" << std::endl; + pulse_start_sample = 0; + } + + break; + } + pulsewinleft--; + } + + // if pulsewinleft reaches 0 without finding a baseline crossing (maybe ringing?), hault it at 0 and assign pulse start + // TODO: figure out what is wrong with these pulses + if (pulsewinleft == 0) { + if (verbosity > v_debug) { + std::cout << "Baseline crossing was not found... assigning pulse start as 0" << std::endl; + } + pulse_start_sample = 0; + } + } + + // once we reach the baseline again (right side of the pulse), we determine the pulse stop (5 samples after baseline + sigma crossing) + // or in case we've reached the end of the minibuffer, force pulse to end + } else if ( in_pulse && ((raw_minibuffer_data.GetSample(s) < baseline_plus_one_sigma) || (s == num_samples - 1)) ) { + in_pulse = false; + + if (s == num_samples - 1) { + if(verbosity>v_debug) std::cout << "Pulse found is VERY LATE in the minibuffer (we're at the final sample)... forcing pulse to end" << std::endl; + pulse_end_sample = s; + } else { + pulse_end_sample = (s + 5 < (num_samples - 1)) ? (s + 5) : (num_samples - 1); // ensure we don't exceed the buffer + } + + // double check that pulse start and stop were found successfully + if (verbosity > v_debug) { + std::cout << "Pulse start and end determined! (" << pulse_start_sample + << ", " << pulse_end_sample << ")" << std::endl; + } + + + // Integrate the pulse to get its area. Use a Riemann sum. Also get + // the raw amplitude (maximum ADC value within the pulse) and the + // sample at which the peak occurs. + unsigned long raw_area = 0; // ADC * samples + unsigned short max_ADC = std::numeric_limits::lowest(); + size_t peak_sample = BOGUS_INT; + for (size_t p = pulse_start_sample; p <= pulse_end_sample; ++p) { + raw_area += raw_minibuffer_data.GetSample(p); + if (max_ADC < raw_minibuffer_data.GetSample(p)) { + max_ADC = raw_minibuffer_data.GetSample(p); + peak_sample = p; + } + } + // The amplitude of the pulse (V) + double calibrated_amplitude + = calibrated_minibuffer_data.GetSample(peak_sample); + + // Calculated the charge detected in this pulse (nC) + // using the calibrated waveform + double charge = 0.; + // Integrate the calibrated pulse (to get a quantity in V * samples) + for (size_t p = pulse_start_sample; p <= pulse_end_sample; ++p) { + charge += calibrated_minibuffer_data.GetSample(p); + } + + // Convert the pulse integral to nC + // FIXME: We need a static database with each PMT's impedance + charge *= NS_PER_ADC_SAMPLE / ADC_IMPEDANCE; + // TODO: consider adding code to merge pulses if they occur + // very close together (i.e. if the end of one is just a few samples away + // from the start of another) + + // PMT Timing offsets + double timing_offset=0.0; + std::map::const_iterator it = ChannelKeyToTimingOffsetMap.find(channel_key); + if(it != ChannelKeyToTimingOffsetMap.end()){ //Timing offset is available + timing_offset = ChannelKeyToTimingOffsetMap.at(channel_key); + } else { + if(verbosity>v_error){ + std::cout << "PhaseIIADCHitFinder: Didn't find Timing offset for channel... setting this channel's offset to 0ns" << channel_key << std::endl; + } + } + + // New approach to hit timing to avoid 2ns bins - 50% threshold above baseline + // Look for where the ADC value crosses 50% of the maximum, assign hit time + // TODO: consider using an approach recommended by Bob: get time at 50%, get time at 20%, draw straight line in between and find time to zero threshold + const double threshold_percentage = 0.5; + unsigned short threshold_value = ((max_ADC - adc_threshold) * threshold_percentage) + adc_threshold; + double hit_time = peak_sample; + bool hit_time_found = false; + + // Find the first sample where the ADC value is above 50% + for (size_t p = peak_sample; p > pulse_start_sample; --p) { + if (raw_minibuffer_data.GetSample(p) < threshold_value) { + hit_time = p; + hit_time_found = true; + break; + } + } + + // Perform simple linear interpolation to find exact crossing point + if (hit_time_found) { + if(verbosity>v_debug) std::cout << "Interpolating hit time..." << std::endl; + if (hit_time > pulse_start_sample && hit_time < pulse_end_sample) { + double x1 = hit_time; + double x2 = hit_time + 1.0; + unsigned short y1 = raw_minibuffer_data.GetSample(static_cast(x1)); + unsigned short y2 = raw_minibuffer_data.GetSample(static_cast(x2)); + hit_time = x1 + (threshold_value - y1) * (x2 - x1) / (y2 - y1); // linear interpolation + } + } + + if(verbosity>v_debug) { + + std::cout << "Hit time [ns] " << hit_time * NS_PER_ADC_SAMPLE << std::endl; + + if (hit_time < 0.0) { + // If for some reason the interpolation finds a negative time value (if the pulse is extremely early in the buffer), + // default to the peak time (maximum ADC value of the pulse) + std::cout << "Hit time is negative! Defaulting to peak time" << std::endl; + hit_time = peak_sample; + } + + std::cout << "Pulse properties: " << std::endl; + std::cout << " chanID: " << channel_key << std::endl; + std::cout << " charge: " << ( charge ) << std::endl; + std::cout << " start time: " << ( pulse_start_sample ) << std::endl; + std::cout << " hit time: " << ( hit_time ) << std::endl; + std::cout << " stop time: " << ( pulse_end_sample ) << std::endl; + + } + + // Store the freshly made pulse in the vector of found pulses + pulses.emplace_back(channel_key, + ( pulse_start_sample * NS_PER_ADC_SAMPLE )-timing_offset, + ( hit_time * NS_PER_ADC_SAMPLE )-timing_offset, // interpolated hit time + calibrated_minibuffer_data.GetBaseline(), + calibrated_minibuffer_data.GetSigmaBaseline(), + raw_area, max_ADC, calibrated_amplitude, charge); + } + } + + + // ****************************************************************** + // "PulseWindowType" default for EventBuilding // Peak windows are defined only by crossing and un-crossing of ADC threshold } else if(pulse_window_type == "dynamic"){ size_t pulse_start_sample = BOGUS_INT; @@ -902,8 +1084,8 @@ std::vector PhaseIIADCHitFinder::find_pulses_bythreshold( if(it != ChannelKeyToTimingOffsetMap.end()){ //Timing offset is available timing_offset = ChannelKeyToTimingOffsetMap.at(channel_key); } else { - if(verbosity>2){ - std::cout << "Didn't find Timing offset for channel " << channel_key << std::endl; + if(verbosity>v_error){ + std::cout << "PhaseIIADCHitFinder: Didn't find Timing offset for channel... setting this channel's offset to 0ns" << channel_key << std::endl; } } @@ -936,20 +1118,23 @@ std::vector PhaseIIADCHitFinder::find_pulses_bythreshold( } } - if(verbosity>4) std::cout << "Hit time [ns] " << hit_time * NS_PER_ADC_SAMPLE << std::endl; + if(verbosity>v_debug) { + + std::cout << "Hit time [ns] " << hit_time * NS_PER_ADC_SAMPLE << std::endl; - if (hit_time < 0.0) { - // If for some reason the interpolation finds a negative time value (if the pulse is extremely early in the buffer), - // default to the peak time - std::cout << "Hit time is negative! Defaulting to peak time" << std::endl; - hit_time = peak_sample; + if (hit_time < 0.0) { + // If for some reason the interpolation finds a negative time value (if the pulse is extremely early in the buffer), + // default to the peak time (maximum ADC value of the pulse) + std::cout << "Hit time is negative! Defaulting to peak time" << std::endl; + hit_time = peak_sample; + } } // Store the freshly made pulse in the vector of found pulses pulses.emplace_back(channel_key, ( pulse_start_sample * NS_PER_ADC_SAMPLE )-timing_offset, - (hit_time * NS_PER_ADC_SAMPLE)-timing_offset, + (hit_time * NS_PER_ADC_SAMPLE)-timing_offset, // interpolated hit time calibrated_minibuffer_data.GetBaseline(), calibrated_minibuffer_data.GetSigmaBaseline(), raw_area, max_ADC, calibrated_amplitude, charge); diff --git a/configfiles/EventBuilderV2/PhaseIIADCHitFinderConfig b/configfiles/EventBuilderV2/PhaseIIADCHitFinderConfig index d183b7b27..991f5d222 100644 --- a/configfiles/EventBuilderV2/PhaseIIADCHitFinderConfig +++ b/configfiles/EventBuilderV2/PhaseIIADCHitFinderConfig @@ -3,7 +3,7 @@ verbosity 0 UseLEDWaveforms 0 PulseFindingApproach threshold -PulseWindowType dynamic +PulseWindowType Fixed_2023_Gains DefaultADCThreshold 7 DefaultThresholdType relative diff --git a/configfiles/EventBuilderV2_AmBe/PhaseIIADCHitFinderConfig b/configfiles/EventBuilderV2_AmBe/PhaseIIADCHitFinderConfig index d183b7b27..991f5d222 100644 --- a/configfiles/EventBuilderV2_AmBe/PhaseIIADCHitFinderConfig +++ b/configfiles/EventBuilderV2_AmBe/PhaseIIADCHitFinderConfig @@ -3,7 +3,7 @@ verbosity 0 UseLEDWaveforms 0 PulseFindingApproach threshold -PulseWindowType dynamic +PulseWindowType Fixed_2023_Gains DefaultADCThreshold 7 DefaultThresholdType relative diff --git a/configfiles/EventBuilderV2_cosmic/PhaseIIADCHitFinderConfig b/configfiles/EventBuilderV2_cosmic/PhaseIIADCHitFinderConfig index d183b7b27..991f5d222 100644 --- a/configfiles/EventBuilderV2_cosmic/PhaseIIADCHitFinderConfig +++ b/configfiles/EventBuilderV2_cosmic/PhaseIIADCHitFinderConfig @@ -3,7 +3,7 @@ verbosity 0 UseLEDWaveforms 0 PulseFindingApproach threshold -PulseWindowType dynamic +PulseWindowType Fixed_2023_Gains DefaultADCThreshold 7 DefaultThresholdType relative diff --git a/configfiles/EventBuilderV2_laser/PhaseIIADCHitFinderConfig b/configfiles/EventBuilderV2_laser/PhaseIIADCHitFinderConfig index d183b7b27..991f5d222 100644 --- a/configfiles/EventBuilderV2_laser/PhaseIIADCHitFinderConfig +++ b/configfiles/EventBuilderV2_laser/PhaseIIADCHitFinderConfig @@ -3,7 +3,7 @@ verbosity 0 UseLEDWaveforms 0 PulseFindingApproach threshold -PulseWindowType dynamic +PulseWindowType Fixed_2023_Gains DefaultADCThreshold 7 DefaultThresholdType relative From c91001a1ddf2a1ff06a6f0428c1885aadeb146ec Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Fri, 4 Apr 2025 14:38:08 -0500 Subject: [PATCH 123/163] Increase the limit about loading files in a tool chain --- Setup.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Setup.sh b/Setup.sh index 42bbeacac..e59ef742c 100644 --- a/Setup.sh +++ b/Setup.sh @@ -4,6 +4,8 @@ ToolDAQapp=`pwd` +ulimit -n 4096 + export LIBGL_ALWAYS_INDIRECT=1 source ${ToolDAQapp}/ToolDAQ/root-6.24.06/install/bin/thisroot.sh From f372cb3a7dff762c999a87edf5c620ce20c93721 Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Fri, 4 Apr 2025 17:42:38 -0500 Subject: [PATCH 124/163] Fix a bug about NumWavesInCompleteSet in EBPMT Previously, if NumWavesInCompleteSet was set to 140 and there are only ~133 PMT waveforms exist in data, the AlmostCompleteWaveforms[PMTCounterTimeNs] won't be created. But the usage of AlmostCompleteWaveforms[PMTCounterTimeNs] in Log will create an entry there. This won't affect the later code because there are checks to require AlmostCompleteWaveforms[PMTCounterTimeNs] > 5. Now the Log was removed and the tolerance for PMT number is changed to 10 at: ChannelKey.size() >= (NumWavesInCompleteSet - 10) Also change the pedestal subtraction for LAPPD_EB tool chain to be 0. --- UserTools/EBPMT/EBPMT.cpp | 55 ++++++++++++++++++++++++------------ configfiles/LAPPD_EB/Configs | 2 +- 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/UserTools/EBPMT/EBPMT.cpp b/UserTools/EBPMT/EBPMT.cpp index 72b21cb3f..cc160819f 100644 --- a/UserTools/EBPMT/EBPMT.cpp +++ b/UserTools/EBPMT/EBPMT.cpp @@ -26,8 +26,8 @@ bool EBPMT::Initialise(std::string configfile, DataModel &data) NumWavesInCompleteSet = 140; FinishedHits = new std::map> *>(); - RWMRawWaveforms = new std::map>(); - BRFRawWaveforms = new std::map>(); + //RWMRawWaveforms = new std::map>(); + //BRFRawWaveforms = new std::map>(); saveRWMWaveforms = true; saveBRFWaveforms = true; @@ -43,10 +43,14 @@ bool EBPMT::Execute() bool gotHits = m_data->CStore.Get("InProgressHits", InProgressHits); bool gotChkey = m_data->CStore.Get("InProgressChkey", InProgressChkey); - m_data->CStore.Get("RWMRawWaveforms", RWMRawWaveforms); - m_data->CStore.Get("BRFRawWaveforms", BRFRawWaveforms); - Log("EBPMT: Got RWMRawWaveforms size: " + std::to_string(RWMRawWaveforms->size()), v_message, verbosityEBPMT); - Log("EBPMT: Got BRFRawWaveforms size: " + std::to_string(BRFRawWaveforms->size()), v_message, verbosityEBPMT); + if (!gotHits || !gotChkey) + { + Log("EBPMT: No InProgressHits or InProgressChkey found", v_message, verbosityEBPMT); + return true; + } + Log("EBPMT: got inprogress hits and chkey with size " + std::to_string(InProgressHits->size()) + " and " + std::to_string(InProgressChkey->size()), v_message, verbosityEBPMT); + + if (exeNum % 80 == 0 && exeNum != 0) { @@ -72,14 +76,19 @@ bool EBPMT::Execute() Log("EBPMT: Got PairedPMTTimeStamps size: " + std::to_string(PairedPMTTimeStamps.size()), v_message, verbosityEBPMT); Log("EBPMT: Got PairedPMTTriggerTimestamp size: " + std::to_string(PairedCTCTimeStamps.size()), v_message, verbosityEBPMT); - Log("EBPMT: gotHits = " + std::to_string(gotHits) + " gotChkey = " + std::to_string(gotChkey), v_message, verbosityEBPMT); - if (!gotHits || !gotChkey) + + + bool gotRWM = m_data->CStore.Get("RWMRawWaveforms", RWMRawWaveforms); + bool gotBRF = m_data->CStore.Get("BRFRawWaveforms", BRFRawWaveforms); + if (gotRWM && gotBRF && RWMRawWaveforms != NULL && BRFRawWaveforms != NULL) { - Log("EBPMT: No InProgressHits or InProgressChkey found", v_message, verbosityEBPMT); - return true; + Log("EBPMT: Got RWMRawWaveforms size: " + std::to_string(RWMRawWaveforms->size()), v_message, verbosityEBPMT); + Log("EBPMT: Got BRFRawWaveforms size: " + std::to_string(BRFRawWaveforms->size()), v_message, verbosityEBPMT); + } + else + { + Log("EBPMT: No RWMRawWaveforms or BRFRawWaveforms found", v_message, verbosityEBPMT); } - - Log("EBPMT: got inprogress hits and chkey with size " + std::to_string(InProgressHits->size()) + " and " + std::to_string(InProgressChkey->size()), v_message, verbosityEBPMT); vector PMTEmplacedHitTimes; vector RWMEmplacedTimes; @@ -109,7 +118,7 @@ bool EBPMT::Execute() if (MaxObservedNumWaves > NumWavesInCompleteSet) NumWavesInCompleteSet = MaxObservedNumWaves; - if (ChannelKey.size() == (NumWavesInCompleteSet - 1)) + if (ChannelKey.size() >= (NumWavesInCompleteSet - 10)) { Log("EBPMT: ChannelKey.size() == (NumWavesInCompleteSet - 1), ChannelKey.size() = " + std::to_string(ChannelKey.size()) + " == NumWavesInCompleteSet - 1 = " + std::to_string(NumWavesInCompleteSet - 1), v_debug, verbosityEBPMT); if (AlmostCompleteWaveforms.find(PMTCounterTimeNs) != AlmostCompleteWaveforms.end()) @@ -122,7 +131,7 @@ bool EBPMT::Execute() Log("EBPMT: AlmostCompleteWaveforms adding PMTCounterTimeNs = " + std::to_string(PMTCounterTimeNs) + " to " + std::to_string(AlmostCompleteWaveforms[PMTCounterTimeNs]), v_debug, verbosityEBPMT); } - Log("EBPMT: ChannelKey.size() = " + std::to_string(ChannelKey.size()) + " >= NumWavesInCompleteSet = " + std::to_string(NumWavesInCompleteSet) + " or AlmostCompleteWaveforms.at(PMTCounterTimeNs) = " + std::to_string(AlmostCompleteWaveforms[PMTCounterTimeNs] >= 5), v_debug, verbosityEBPMT); + //Log("EBPMT: ChannelKey.size() = " + std::to_string(ChannelKey.size()) + " >= NumWavesInCompleteSet = " + std::to_string(NumWavesInCompleteSet) + " or AlmostCompleteWaveforms.at(PMTCounterTimeNs) = " + std::to_string(AlmostCompleteWaveforms[PMTCounterTimeNs] >= 5), v_debug, verbosityEBPMT); // print all elements in vector ChannelKey @@ -132,9 +141,15 @@ bool EBPMT::Execute() // cout<second; + } - if (ChannelKey.size() >= NumWavesInCompleteSet || ((ChannelKey.size() == NumWavesInCompleteSet - 1) && (AlmostCompleteWaveforms[PMTCounterTimeNs] >= 5))) + if (ChannelKey.size() >= NumWavesInCompleteSet || ((ChannelKey.size() == NumWavesInCompleteSet - 1) && (AlmostCompleteWaveforms_CountHere >= 5))) { Log("EBPMT: Emplace hit map to FinishedHits, ChannelKey.size() = " + std::to_string(ChannelKey.size()) + " >= NumWavesInCompleteSet = " + std::to_string(NumWavesInCompleteSet) + " or AlmostCompleteWaveforms.at(PMTCounterTimeNs) = " + std::to_string(AlmostCompleteWaveforms.at(PMTCounterTimeNs) >= 5), v_debug, verbosityEBPMT); @@ -322,9 +337,13 @@ bool EBPMT::Matching(int targetTrigger, int matchToTrack) Log("EBPMT: looping hit " + std::to_string(loopNum) + ", minDT: " + std::to_string(minDT) + ", minDTTrigger time: " + std::to_string(minDTTrigger) + " with word " + std::to_string(matchedTrigWord) + ", in trigger track " + std::to_string(matchedTrack), v_warning, verbosityEBPMT); if (minDT < matchTolerance_ns) { - PairedCTCTimeStamps[matchedTrack].push_back(minDTTrigger); - PairedPMTTimeStamps[matchedTrack].push_back(PMTCounterTimeNs); - PairedPMT_TriggerIndex[matchedTrack].push_back(matchedIndex); + //PairedCTCTimeStamps[matchedTrack].push_back(minDTTrigger); + //PairedPMTTimeStamps[matchedTrack].push_back(PMTCounterTimeNs); + //PairedPMT_TriggerIndex[matchedTrack].push_back(matchedIndex); + + PairedCTCTimeStamps.emplace(matchedTrack, std::vector{}).first->second.push_back(minDTTrigger); + PairedPMTTimeStamps.emplace(matchedTrack, std::vector{}).first->second.push_back(PMTCounterTimeNs); + PairedPMT_TriggerIndex.emplace(matchedTrack, std::vector{}).first->second.push_back(matchedIndex); // the pmt hit map with timestmap PMTCounterTimeNs, match to trigger with timestamp minDTTrigger // the matched trigger is at matchedIndex of that trigger track diff --git a/configfiles/LAPPD_EB/Configs b/configfiles/LAPPD_EB/Configs index 57eea8279..0975b4615 100644 --- a/configfiles/LAPPD_EB/Configs +++ b/configfiles/LAPPD_EB/Configs @@ -18,7 +18,7 @@ BoardIndexLabel BoardIndex #Label of the vector of read out boards PsecReceiveMode 1 stopEntries 10000000000 -DoPedSubtraction 1 +DoPedSubtraction 0 Nboards 6 #Number of pedestal files to be read in PedinputfileTXT ../Pedestals/Laser2024Feb/P PSECinputfile /pnfs/annie/persistent/processed/LAPPD40Merged/FinalVersion_withRawTS/FilteredData_PMT_MRDtrack_noveto_15mV_7strips_3xxx_104 From 3ab1e99e177d91b3e602f9f8e16e6c48e256d710 Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Wed, 9 Apr 2025 20:34:25 -0500 Subject: [PATCH 125/163] Add device for bunch rotation information in IFBeamDBInterfaceV2 --- UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp b/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp index 6f332d446..6426ee50f 100644 --- a/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp +++ b/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp @@ -31,7 +31,10 @@ IFBeamDBInterfaceV2::IFBeamDBInterfaceV2() {"E:VPTG1", "mm"}, {"E:HPTG2", "mm"}, {"E:VPTG2", "mm"}, - {"E:BTH2T2", "DegC"}}; + {"E:BTH2T2", "DegC"}, + {"B:BRRMPL","bool"}, + {"B:BRRMPS","bool"}, + {"B:BRRMPQ","bool"}}; } IFBeamDBInterfaceV2::~IFBeamDBInterfaceV2() From fd227f7cfc0b9c1e0a28ec42e57bdda7846bc988 Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Wed, 9 Apr 2025 20:42:20 -0500 Subject: [PATCH 126/163] Add saving bunch rotation device information to EBSaver --- UserTools/EBSaver/EBSaver.cpp | 17 +++++++++++++++++ UserTools/EBSaver/EBSaver.h | 4 ++++ 2 files changed, 21 insertions(+) diff --git a/UserTools/EBSaver/EBSaver.cpp b/UserTools/EBSaver/EBSaver.cpp index b07780d2c..dc022613d 100644 --- a/UserTools/EBSaver/EBSaver.cpp +++ b/UserTools/EBSaver/EBSaver.cpp @@ -1349,6 +1349,7 @@ void EBSaver::LoadBeamInfo() uint64_t timestamp; double E_TOR860, E_TOR875, THCURR, BTJT2, HP875, VP875, HPTG1, VPTG1, HPTG2, VPTG2, BTH2T2; + double B_BRRMPL, B_BRRMPQ, B_BRRMPS; tree->SetBranchAddress("Timestamp", ×tamp); tree->SetBranchAddress("E_TOR860", &E_TOR860); @@ -1362,6 +1363,9 @@ void EBSaver::LoadBeamInfo() tree->SetBranchAddress("E_HPTG2", &HPTG2); tree->SetBranchAddress("E_VPTG2", &VPTG2); tree->SetBranchAddress("E_BTH2T2", &BTH2T2); + tree->SetBranchAddress("B_BRRMPL", &B_BRRMPL); + tree->SetBranchAddress("B_BRRMPQ", &B_BRRMPQ); + tree->SetBranchAddress("B_BRRMPS", &B_BRRMPS); Long64_t nentries = tree->GetEntries(); Log("EBSaver: Loading beam infor, total entries in beam info file: " + std::to_string(nentries), v_message, verbosityEBSaver); @@ -1382,6 +1386,9 @@ void EBSaver::LoadBeamInfo() HPTG2_map.emplace(timestamp, HPTG2); VPTG2_map.emplace(timestamp, VPTG2); BTH2T2_map.emplace(timestamp, BTH2T2); + B_BRRMPL_map.emplace(timestamp, B_BRRMPL); + B_BRRMPQ_map.emplace(timestamp, B_BRRMPQ); + B_BRRMPS_map.emplace(timestamp, B_BRRMPS); } Log("EBSaver: Loaded number of E_TOR860 entries: " + std::to_string(E_TOR860_map.size()), v_message, verbosityEBSaver); @@ -1394,6 +1401,7 @@ void EBSaver::LoadBeamInfo() bool EBSaver::SaveBeamInfo(uint64_t TriggerTime) { double E_TOR860, E_TOR875, THCURR, BTJT2, HP875, VP875, HPTG1, VPTG1, HPTG2, VPTG2, BTH2T2; + double B_BRRMPL, B_BRRMPQ, B_BRRMPS; // find the closest timestamp in vector BeamInfoTimestamps uint64_t closestTimestamp = 0; @@ -1437,6 +1445,9 @@ bool EBSaver::SaveBeamInfo(uint64_t TriggerTime) ANNIEEvent->Set("beam_HPTG2", defaultVal); ANNIEEvent->Set("beam_VPTG2", defaultVal); ANNIEEvent->Set("beam_BTH2T2", defaultVal); + ANNIEEvent->Set("beam_B_BRRMPL", defaultVal); + ANNIEEvent->Set("beam_B_BRRMPQ", defaultVal); + ANNIEEvent->Set("beam_B_BRRMPS", defaultVal); ANNIEEvent->Set("beam_good", beam_good); Log("EBSaver: Saved beam info with time " + std::to_string(0) + ", pot E_TOR860 = " + std::to_string(-9999) + ", beam_good = " + std::to_string(-9999), v_message, verbosityEBSaver); @@ -1462,6 +1473,9 @@ bool EBSaver::SaveBeamInfo(uint64_t TriggerTime) HPTG2 = HPTG2_map.at(beamInfoTime); VPTG2 = VPTG2_map.at(beamInfoTime); BTH2T2 = BTH2T2_map.at(beamInfoTime); + B_BRRMPL = B_BRRMPL_map.at(beamInfoTime); + B_BRRMPQ = B_BRRMPQ_map.at(beamInfoTime); + B_BRRMPS = B_BRRMPS_map.at(beamInfoTime); ANNIEEvent->Set("BeamInfoTime", beamInfoTime); ANNIEEvent->Set("BeamInfoTimeToTriggerDiff", timeDiff); @@ -1477,6 +1491,9 @@ bool EBSaver::SaveBeamInfo(uint64_t TriggerTime) ANNIEEvent->Set("beam_HPTG2", HPTG2); ANNIEEvent->Set("beam_VPTG2", VPTG2); ANNIEEvent->Set("beam_BTH2T2", BTH2T2); + ANNIEEvent->Set("beam_B_BRRMPL", B_BRRMPL); + ANNIEEvent->Set("beam_B_BRRMPQ", B_BRRMPQ); + ANNIEEvent->Set("beam_B_BRRMPS", B_BRRMPS); int beam_good = 0; diff --git a/UserTools/EBSaver/EBSaver.h b/UserTools/EBSaver/EBSaver.h index f2dedb5f6..9d57e332d 100644 --- a/UserTools/EBSaver/EBSaver.h +++ b/UserTools/EBSaver/EBSaver.h @@ -197,6 +197,10 @@ class EBSaver : public Tool std::map HPTG2_map; std::map VPTG2_map; std::map BTH2T2_map; + std::map B_BRRMPL_map; + std::map B_BRRMPS_map; + std::map B_BRRMPQ_map; + }; #endif From 79a02f2a3c1592b703691cb03e6fa2c734cc13f5 Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Wed, 9 Apr 2025 20:44:52 -0500 Subject: [PATCH 127/163] Add bunch rotation device information saving to ANNIEEventTreeMaker --- UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp | 9 +++++++++ UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index 7c469d014..fd2519324 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -107,6 +107,9 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) fANNIETree->Branch("beam_HPTG2", &beam_HPTG2, "beam_HPTG2/D"); fANNIETree->Branch("beam_VPTG2", &beam_VPTG2, "beam_VPTG2/D"); fANNIETree->Branch("beam_BTH2T2", &beam_BTH2T2, "beam_BTH2T2/D"); + fANNIETree->Branch("beam_B_BRRMPL", &beam_B_BRRMPL, "beam_B_BRRMPL/D"); + fANNIETree->Branch("beam_B_BRRMPQ", &beam_B_BRRMPQ, "beam_B_BRRMPQ/D"); + fANNIETree->Branch("beam_B_BRRMPS", &beam_B_BRRMPS, "beam_B_BRRMPS/D"); fANNIETree->Branch("BeamInfoTime", &fBeamInfoTime, "BeamInfoTime/l"); fANNIETree->Branch("BeamInfoTimeToTriggerDiff", &fBeamInfoTimeToTriggerDiff, "BeamInfoTimeToTriggerDiff/L"); } @@ -645,6 +648,9 @@ void ANNIEEventTreeMaker::ResetVariables() beam_HPTG2 = -9999; beam_VPTG2 = -9999; beam_BTH2T2 = -9999; + beam_B_BRRMPL = -9999; + beam_B_BRRMPQ = -9999; + beam_B_BRRMPS = -9999; fBeamInfoTime = 0; fBeamInfoTimeToTriggerDiff = -9999; @@ -1129,6 +1135,9 @@ void ANNIEEventTreeMaker::LoadBeamInfo() m_data->Stores["ANNIEEvent"]->Get("beam_HPTG2", beam_HPTG2); m_data->Stores["ANNIEEvent"]->Get("beam_VPTG2", beam_VPTG2); m_data->Stores["ANNIEEvent"]->Get("beam_BTH2T2", beam_BTH2T2); + m_data->Stores["ANNIEEvent"]->Get("beam_B_BRRMPL", beam_B_BRRMPL); + m_data->Stores["ANNIEEvent"]->Get("beam_B_BRRMPQ", beam_B_BRRMPQ); + m_data->Stores["ANNIEEvent"]->Get("beam_B_BRRMPS", beam_B_BRRMPS); m_data->Stores["ANNIEEvent"]->Get("beam_E_TOR875", fPot); m_data->Stores["ANNIEEvent"]->Get("beam_good", fBeamok); diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h index c6243def4..79068c239 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h @@ -172,6 +172,9 @@ class ANNIEEventTreeMaker : public Tool double beam_HPTG2; double beam_VPTG2; double beam_BTH2T2; + double beam_B_BRRMPL; + double beam_B_BRRMPQ; + double beam_B_BRRMPS; uint64_t fBeamInfoTime; int64_t fBeamInfoTimeToTriggerDiff; From 12c97abcfd631c237fab0d33c9381e476529a184 Mon Sep 17 00:00:00 2001 From: Steven Doran Date: Thu, 10 Apr 2025 09:44:09 -0500 Subject: [PATCH 128/163] Add ADC traces to ADCPulse, to be stored in RecoADCHits --- .vscode/settings.json | 78 +++++++++++++++++ DataModel/ADCPulse.cpp | 3 +- DataModel/ADCPulse.h | 18 +++- .../PhaseIIADCHitFinder.cpp | 85 ++++++++++++++++--- 4 files changed, 172 insertions(+), 12 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..f0d2c9ca4 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,78 @@ +{ + "files.associations": { + "__bit_reference": "cpp", + "__bits": "cpp", + "__config": "cpp", + "__debug": "cpp", + "__errc": "cpp", + "__hash_table": "cpp", + "__locale": "cpp", + "__mutex_base": "cpp", + "__node_handle": "cpp", + "__split_buffer": "cpp", + "__threading_support": "cpp", + "__tree": "cpp", + "__tuple": "cpp", + "__verbose_abort": "cpp", + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "complex": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "exception": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "ios": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "locale": "cpp", + "map": "cpp", + "memory": "cpp", + "mutex": "cpp", + "new": "cpp", + "optional": "cpp", + "ostream": "cpp", + "ratio": "cpp", + "regex": "cpp", + "set": "cpp", + "sstream": "cpp", + "stack": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "thread": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "typeinfo": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "variant": "cpp", + "vector": "cpp", + "__nullptr": "cpp", + "__string": "cpp", + "chrono": "cpp", + "compare": "cpp", + "concepts": "cpp", + "numeric": "cpp", + "algorithm": "cpp" + } +} \ No newline at end of file diff --git a/DataModel/ADCPulse.cpp b/DataModel/ADCPulse.cpp index 84a3e3247..1216559cb 100755 --- a/DataModel/ADCPulse.cpp +++ b/DataModel/ADCPulse.cpp @@ -10,6 +10,7 @@ ADCPulse::ADCPulse(int TubeId, double start_time, double peak_time, double charge) : Hit(TubeId, start_time, charge), start_time_(start_time), peak_time_(peak_time), baseline_(baseline), sigma_baseline_(sigma_baseline), raw_area_(area), - raw_amplitude_(raw_amplitude), calibrated_amplitude_(calibrated_amplitude) + raw_amplitude_(raw_amplitude), calibrated_amplitude_(calibrated_amplitude), + trace_x_(x_points), trace_y_(y_points) { } diff --git a/DataModel/ADCPulse.h b/DataModel/ADCPulse.h index 891e840d0..5522507ad 100755 --- a/DataModel/ADCPulse.h +++ b/DataModel/ADCPulse.h @@ -9,6 +9,7 @@ // ToolAnalysis includes #include "ChannelKey.h" #include "Hit.h" +#include class ADCPulse : public Hit { @@ -23,7 +24,7 @@ class ADCPulse : public Hit { ADCPulse(int TubeId, double start_time, double peak_time, double baseline, double sigma_baseline, unsigned long raw_area, unsigned short raw_amplitude, double calibrated_amplitude, - double charge); + double charge, const std::vector& trace_x_, const std::vector& trace_y_); // @brief Returns the start time (ns) of the pulse relative to the // start of its minibuffer @@ -59,6 +60,10 @@ class ADCPulse : public Hit { // (baseline-subtracted) pulse inline double amplitude() const { return calibrated_amplitude_; } + // @brief Returns the x and y points of the "found" pulse (baseline-subtracted and relative to pulse start point) + inline const std::vector& GetTraceXPoints() const { return trace_x_; } + inline const std::vector& GetTraceYPoints() const { return trace_y_; } + template void serialize(Archive& ar, const unsigned int version) { @@ -71,6 +76,10 @@ class ADCPulse : public Hit { ar & raw_area_; ar & raw_amplitude_; ar & calibrated_amplitude_; + if (version > 0) { + ar & trace_x_; + ar & trace_y_; + } } protected: @@ -83,4 +92,11 @@ class ADCPulse : public Hit { unsigned short raw_amplitude_; // ADC double calibrated_amplitude_; // V + + std::vector trace_x_; // x points of the pulse (start at 0, relative to pulse start) + std::vector trace_y_; // y points of the pulse (baseline-subtracted) }; + +// Need to increment the class version since we added time as a new variable +// the version number ensures backward compatibility when serializing +BOOST_CLASS_VERSION(ADCPulse, 1) \ No newline at end of file diff --git a/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp b/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp index 246bd8550..c637ebdfc 100755 --- a/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp +++ b/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp @@ -608,7 +608,7 @@ bool PhaseIIADCHitFinder::build_pulse_and_hit_map( else pmap.at(channel_key).push_back(apulsevec); } //Convert ADCPulses to Hits and fill into Hit map - HitsOnPMT = this->convert_adcpulses_to_hits(channel_key,pulse_vec); + HitsOnPMT = this->convert_adcpulses_to_hits(channel_key,pulse_vec,hit_trace_map); Log("PhaseIIADCHitFinder: Filling hit map.", v_debug, verbosity); for(int j=0; j < (int) HitsOnPMT.size(); j++){ @@ -717,13 +717,29 @@ std::vector PhaseIIADCHitFinder::find_pulses_bywindow( } } + // extract the x and y points of the pulse (subtract off baseline and "zero" the pulse to the pulse start) + + std::vector trace_x; + std::vector trace_y; + + double pulse_start_time = wmin * NS_PER_ADC_SAMPLE; + double pulse_baseline = calibrated_minibuffer_data.GetBaseline(); + + for (size_t p = wmin; p <= wmax; ++p) { + double ns_time = p * NS_PER_ADC_SAMPLE; + double val_adc = raw_minibuffer_data.GetSample(p); + trace_x.push_back(ns_time - pulse_start_time); + trace_y.push_back(val_adc - pulse_baseline); + } + // Store the freshly made pulse in the vector of found pulses pulses.emplace_back(channel_key, - ( wmin * NS_PER_SAMPLE )-timing_offset, - (peak_sample * NS_PER_SAMPLE)-timing_offset, + ( wmin * NS_PER_ADC_SAMPLE )-timing_offset, + (peak_sample * NS_PER_ADC_SAMPLE)-timing_offset, calibrated_minibuffer_data.GetBaseline(), calibrated_minibuffer_data.GetSigmaBaseline(), - raw_area, max_ADC, calibrated_amplitude, charge); + raw_area, max_ADC, calibrated_amplitude, charge, + trace_x, trace_y); } return pulses; } @@ -831,13 +847,30 @@ std::vector PhaseIIADCHitFinder::find_pulses_bythreshold( } } + // extract the x and y points of the pulse (subtract off baseline and "zero" the pulse to the pulse start) + + std::vector trace_x; + std::vector trace_y; + + double pulse_start_time = wmin * NS_PER_ADC_SAMPLE; + double pulse_baseline = calibrated_minibuffer_data.GetBaseline(); + + for (size_t p = wmin; p <= wmax; ++p) { + double ns_time = p * NS_PER_ADC_SAMPLE; + double val_adc = raw_minibuffer_data.GetSample(p); + trace_x.push_back(ns_time - pulse_start_time); + trace_y.push_back(val_adc - pulse_baseline); + } + + // Store the freshly made pulse in the vector of found pulses pulses.emplace_back(channel_key, - ( pulse_start_sample * NS_PER_SAMPLE )-timing_offset, - (peak_sample * NS_PER_SAMPLE)-timing_offset, + ( pulse_start_sample * NS_PER_ADC_SAMPLE )-timing_offset, + (peak_sample * NS_PER_ADC_SAMPLE)-timing_offset, calibrated_minibuffer_data.GetBaseline(), calibrated_minibuffer_data.GetSigmaBaseline(), - raw_area, max_ADC, calibrated_amplitude, charge); + raw_area, max_ADC, calibrated_amplitude, charge, + trace_x, trace_y); } @@ -991,6 +1024,21 @@ std::vector PhaseIIADCHitFinder::find_pulses_bythreshold( } } + // extract the x and y points of the pulse (subtract off baseline and "zero" the pulse to the pulse start) + + std::vector trace_x; + std::vector trace_y; + + double pulse_start_time = pulse_start_sample * NS_PER_ADC_SAMPLE; + double pulse_baseline = calibrated_minibuffer_data.GetBaseline(); + + for (size_t p = pulse_start_sample; p <= pulse_end_sample; ++p) { + double ns_time = p * NS_PER_ADC_SAMPLE; + double val_adc = raw_minibuffer_data.GetSample(p); + trace_x.push_back(ns_time - pulse_start_time); + trace_y.push_back(val_adc - pulse_baseline); + } + if(verbosity>v_debug) { std::cout << "Hit time [ns] " << hit_time * NS_PER_ADC_SAMPLE << std::endl; @@ -1017,13 +1065,14 @@ std::vector PhaseIIADCHitFinder::find_pulses_bythreshold( ( hit_time * NS_PER_ADC_SAMPLE )-timing_offset, // interpolated hit time calibrated_minibuffer_data.GetBaseline(), calibrated_minibuffer_data.GetSigmaBaseline(), - raw_area, max_ADC, calibrated_amplitude, charge); + raw_area, max_ADC, calibrated_amplitude, charge, + trace_x, trace_y); } } // ****************************************************************** - // "PulseWindowType" default for EventBuilding + // Previously used in the event building // Peak windows are defined only by crossing and un-crossing of ADC threshold } else if(pulse_window_type == "dynamic"){ size_t pulse_start_sample = BOGUS_INT; @@ -1130,6 +1179,21 @@ std::vector PhaseIIADCHitFinder::find_pulses_bythreshold( } } + // extract the x and y points of the pulse (subtract off baseline and "zero" the pulse to the pulse start) + + std::vector trace_x; + std::vector trace_y; + + double pulse_start_time = pulse_start_sample * NS_PER_ADC_SAMPLE; + double pulse_baseline = calibrated_minibuffer_data.GetBaseline(); + + for (size_t p = pulse_start_sample; p <= pulse_end_sample; ++p) { + double ns_time = p * NS_PER_ADC_SAMPLE; + double val_adc = raw_minibuffer_data.GetSample(p); + trace_x.push_back(ns_time - pulse_start_time); + trace_y.push_back(val_adc - pulse_baseline); + } + // Store the freshly made pulse in the vector of found pulses pulses.emplace_back(channel_key, @@ -1137,7 +1201,8 @@ std::vector PhaseIIADCHitFinder::find_pulses_bythreshold( (hit_time * NS_PER_ADC_SAMPLE)-timing_offset, // interpolated hit time calibrated_minibuffer_data.GetBaseline(), calibrated_minibuffer_data.GetSigmaBaseline(), - raw_area, max_ADC, calibrated_amplitude, charge); + raw_area, max_ADC, calibrated_amplitude, charge, + trace_x, trace_y); } } } else { From c039b1d66a45ef303faa5cf461acaee1209c43e9 Mon Sep 17 00:00:00 2001 From: Steven Doran Date: Thu, 10 Apr 2025 09:48:04 -0500 Subject: [PATCH 129/163] Remove whatever that settings.json was lol --- .vscode/settings.json | 78 ------------------------------------------- 1 file changed, 78 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index f0d2c9ca4..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "files.associations": { - "__bit_reference": "cpp", - "__bits": "cpp", - "__config": "cpp", - "__debug": "cpp", - "__errc": "cpp", - "__hash_table": "cpp", - "__locale": "cpp", - "__mutex_base": "cpp", - "__node_handle": "cpp", - "__split_buffer": "cpp", - "__threading_support": "cpp", - "__tree": "cpp", - "__tuple": "cpp", - "__verbose_abort": "cpp", - "array": "cpp", - "atomic": "cpp", - "bit": "cpp", - "bitset": "cpp", - "cctype": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "complex": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "deque": "cpp", - "exception": "cpp", - "fstream": "cpp", - "future": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "ios": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "locale": "cpp", - "map": "cpp", - "memory": "cpp", - "mutex": "cpp", - "new": "cpp", - "optional": "cpp", - "ostream": "cpp", - "ratio": "cpp", - "regex": "cpp", - "set": "cpp", - "sstream": "cpp", - "stack": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "string": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "thread": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "typeinfo": "cpp", - "unordered_map": "cpp", - "unordered_set": "cpp", - "variant": "cpp", - "vector": "cpp", - "__nullptr": "cpp", - "__string": "cpp", - "chrono": "cpp", - "compare": "cpp", - "concepts": "cpp", - "numeric": "cpp", - "algorithm": "cpp" - } -} \ No newline at end of file From 287b095837994a091302a91a1247b34ca5f51978 Mon Sep 17 00:00:00 2001 From: Steven Doran Date: Thu, 10 Apr 2025 10:07:11 -0500 Subject: [PATCH 130/163] Bugfix to ADCPulse --- .vscode/settings.json | 78 ++++++++++++++++++++++++++++++++++++++++++ DataModel/ADCPulse.cpp | 5 +-- 2 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..f0d2c9ca4 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,78 @@ +{ + "files.associations": { + "__bit_reference": "cpp", + "__bits": "cpp", + "__config": "cpp", + "__debug": "cpp", + "__errc": "cpp", + "__hash_table": "cpp", + "__locale": "cpp", + "__mutex_base": "cpp", + "__node_handle": "cpp", + "__split_buffer": "cpp", + "__threading_support": "cpp", + "__tree": "cpp", + "__tuple": "cpp", + "__verbose_abort": "cpp", + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "complex": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "exception": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "ios": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "locale": "cpp", + "map": "cpp", + "memory": "cpp", + "mutex": "cpp", + "new": "cpp", + "optional": "cpp", + "ostream": "cpp", + "ratio": "cpp", + "regex": "cpp", + "set": "cpp", + "sstream": "cpp", + "stack": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "thread": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "typeinfo": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "variant": "cpp", + "vector": "cpp", + "__nullptr": "cpp", + "__string": "cpp", + "chrono": "cpp", + "compare": "cpp", + "concepts": "cpp", + "numeric": "cpp", + "algorithm": "cpp" + } +} \ No newline at end of file diff --git a/DataModel/ADCPulse.cpp b/DataModel/ADCPulse.cpp index 1216559cb..d33c97b86 100755 --- a/DataModel/ADCPulse.cpp +++ b/DataModel/ADCPulse.cpp @@ -7,10 +7,11 @@ ADCPulse::ADCPulse(int TubeId, double start_time, double peak_time, double baseline, double sigma_baseline, unsigned long area, unsigned short raw_amplitude, double calibrated_amplitude, - double charge) : Hit(TubeId, start_time, charge), + double charge, std::vector trace_x_, std::vector trace_y_) : + Hit(TubeId, start_time, charge), start_time_(start_time), peak_time_(peak_time), baseline_(baseline), sigma_baseline_(sigma_baseline), raw_area_(area), raw_amplitude_(raw_amplitude), calibrated_amplitude_(calibrated_amplitude), - trace_x_(x_points), trace_y_(y_points) + trace_x_(trace_x_), trace_y_(trace_y_) { } From 3690cedfad4d91a773766b5f0bcf42b7b1ac6e36 Mon Sep 17 00:00:00 2001 From: Steven Doran Date: Thu, 10 Apr 2025 10:08:44 -0500 Subject: [PATCH 131/163] remove VSCode settings file and ignore it in future --- .gitignore | 1 + .vscode/settings.json | 78 ------------------------------------------- 2 files changed, 1 insertion(+), 78 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index 4c45d695e..959ba974a 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ DataModel/DataModel_Linkdef.hh UserTools/ImportedTools UserTools/InactiveTools +.vscode/ diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index f0d2c9ca4..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "files.associations": { - "__bit_reference": "cpp", - "__bits": "cpp", - "__config": "cpp", - "__debug": "cpp", - "__errc": "cpp", - "__hash_table": "cpp", - "__locale": "cpp", - "__mutex_base": "cpp", - "__node_handle": "cpp", - "__split_buffer": "cpp", - "__threading_support": "cpp", - "__tree": "cpp", - "__tuple": "cpp", - "__verbose_abort": "cpp", - "array": "cpp", - "atomic": "cpp", - "bit": "cpp", - "bitset": "cpp", - "cctype": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "complex": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "deque": "cpp", - "exception": "cpp", - "fstream": "cpp", - "future": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "ios": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "locale": "cpp", - "map": "cpp", - "memory": "cpp", - "mutex": "cpp", - "new": "cpp", - "optional": "cpp", - "ostream": "cpp", - "ratio": "cpp", - "regex": "cpp", - "set": "cpp", - "sstream": "cpp", - "stack": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "string": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "thread": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "typeinfo": "cpp", - "unordered_map": "cpp", - "unordered_set": "cpp", - "variant": "cpp", - "vector": "cpp", - "__nullptr": "cpp", - "__string": "cpp", - "chrono": "cpp", - "compare": "cpp", - "concepts": "cpp", - "numeric": "cpp", - "algorithm": "cpp" - } -} \ No newline at end of file From 0e5e643ec363dfd9a9b7d326395631aca54f3b2d Mon Sep 17 00:00:00 2001 From: Steven Doran Date: Thu, 10 Apr 2025 10:14:37 -0500 Subject: [PATCH 132/163] Bugfix (again) to ADCPulse --- DataModel/ADCPulse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DataModel/ADCPulse.cpp b/DataModel/ADCPulse.cpp index d33c97b86..f482f40b3 100755 --- a/DataModel/ADCPulse.cpp +++ b/DataModel/ADCPulse.cpp @@ -7,7 +7,7 @@ ADCPulse::ADCPulse(int TubeId, double start_time, double peak_time, double baseline, double sigma_baseline, unsigned long area, unsigned short raw_amplitude, double calibrated_amplitude, - double charge, std::vector trace_x_, std::vector trace_y_) : + double charge, const std::vector trace_x_, const std::vector trace_y_) : Hit(TubeId, start_time, charge), start_time_(start_time), peak_time_(peak_time), baseline_(baseline), sigma_baseline_(sigma_baseline), raw_area_(area), From cb11576d2d7e26699189c7c53b2b02f932f2aeb3 Mon Sep 17 00:00:00 2001 From: Steven Doran Date: Thu, 10 Apr 2025 10:18:56 -0500 Subject: [PATCH 133/163] Bugfix (again, again) to ADCPulse --- DataModel/ADCPulse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DataModel/ADCPulse.cpp b/DataModel/ADCPulse.cpp index f482f40b3..efb75e597 100755 --- a/DataModel/ADCPulse.cpp +++ b/DataModel/ADCPulse.cpp @@ -7,7 +7,7 @@ ADCPulse::ADCPulse(int TubeId, double start_time, double peak_time, double baseline, double sigma_baseline, unsigned long area, unsigned short raw_amplitude, double calibrated_amplitude, - double charge, const std::vector trace_x_, const std::vector trace_y_) : + double charge, const std::vector& trace_x_, const std::vector& trace_y_) : Hit(TubeId, start_time, charge), start_time_(start_time), peak_time_(peak_time), baseline_(baseline), sigma_baseline_(sigma_baseline), raw_area_(area), From 713288c1b6dee1c4645705e07ecf9d3b9de3b2c9 Mon Sep 17 00:00:00 2001 From: Steven Doran Date: Thu, 10 Apr 2025 13:03:36 -0500 Subject: [PATCH 134/163] Bugfix (again, again, AGAIN) to ADCPulse (and HitFinder) --- DataModel/ADCPulse.cpp | 4 +-- DataModel/ADCPulse.h | 11 +++---- .../PhaseIIADCHitFinder.cpp | 6 ++-- .../ANNIEEventTreeMakerConfig_cosmic | 30 ------------------- 4 files changed, 11 insertions(+), 40 deletions(-) delete mode 100644 configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig_cosmic diff --git a/DataModel/ADCPulse.cpp b/DataModel/ADCPulse.cpp index efb75e597..03d5a0d21 100755 --- a/DataModel/ADCPulse.cpp +++ b/DataModel/ADCPulse.cpp @@ -7,11 +7,11 @@ ADCPulse::ADCPulse(int TubeId, double start_time, double peak_time, double baseline, double sigma_baseline, unsigned long area, unsigned short raw_amplitude, double calibrated_amplitude, - double charge, const std::vector& trace_x_, const std::vector& trace_y_) : + double charge, const std::vector& trace_x, const std::vector& trace_y) : Hit(TubeId, start_time, charge), start_time_(start_time), peak_time_(peak_time), baseline_(baseline), sigma_baseline_(sigma_baseline), raw_area_(area), raw_amplitude_(raw_amplitude), calibrated_amplitude_(calibrated_amplitude), - trace_x_(trace_x_), trace_y_(trace_y_) + trace_x_(trace_x), trace_y_(trace_y) { } diff --git a/DataModel/ADCPulse.h b/DataModel/ADCPulse.h index 5522507ad..fd594e5bb 100755 --- a/DataModel/ADCPulse.h +++ b/DataModel/ADCPulse.h @@ -23,8 +23,9 @@ class ADCPulse : public Hit { // int TubeId member ADCPulse(int TubeId, double start_time, double peak_time, double baseline, double sigma_baseline, unsigned long raw_area, - unsigned short raw_amplitude, double calibrated_amplitude, - double charge, const std::vector& trace_x_, const std::vector& trace_y_); + unsigned short raw_amplitude, double calibrated_amplitude, double charge, + const std::vector& trace_x = std::vector(), + const std::vector& trace_y = std::vector()); // @brief Returns the start time (ns) of the pulse relative to the // start of its minibuffer @@ -60,7 +61,7 @@ class ADCPulse : public Hit { // (baseline-subtracted) pulse inline double amplitude() const { return calibrated_amplitude_; } - // @brief Returns the x and y points of the "found" pulse (baseline-subtracted and relative to pulse start point) + // @brief Returns the x [ns] and y [ADC] points of the "found" pulse (baseline-subtracted and relative to pulse start point) inline const std::vector& GetTraceXPoints() const { return trace_x_; } inline const std::vector& GetTraceYPoints() const { return trace_y_; } @@ -93,8 +94,8 @@ class ADCPulse : public Hit { unsigned short raw_amplitude_; // ADC double calibrated_amplitude_; // V - std::vector trace_x_; // x points of the pulse (start at 0, relative to pulse start) - std::vector trace_y_; // y points of the pulse (baseline-subtracted) + std::vector trace_x_; // x points of the pulse (start at 0, relative to pulse start) [ns] + std::vector trace_y_; // y points of the pulse (baseline-subtracted) [ADC] }; // Need to increment the class version since we added time as a new variable diff --git a/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp b/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp index c637ebdfc..e9f5a812b 100755 --- a/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp +++ b/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp @@ -608,7 +608,7 @@ bool PhaseIIADCHitFinder::build_pulse_and_hit_map( else pmap.at(channel_key).push_back(apulsevec); } //Convert ADCPulses to Hits and fill into Hit map - HitsOnPMT = this->convert_adcpulses_to_hits(channel_key,pulse_vec,hit_trace_map); + HitsOnPMT = this->convert_adcpulses_to_hits(channel_key,pulse_vec); Log("PhaseIIADCHitFinder: Filling hit map.", v_debug, verbosity); for(int j=0; j < (int) HitsOnPMT.size(); j++){ @@ -852,10 +852,10 @@ std::vector PhaseIIADCHitFinder::find_pulses_bythreshold( std::vector trace_x; std::vector trace_y; - double pulse_start_time = wmin * NS_PER_ADC_SAMPLE; + double pulse_start_time = pulse_start_sample * NS_PER_ADC_SAMPLE; double pulse_baseline = calibrated_minibuffer_data.GetBaseline(); - for (size_t p = wmin; p <= wmax; ++p) { + for (size_t p = pulse_start_sample; p <= pulse_end_sample; ++p) { double ns_time = p * NS_PER_ADC_SAMPLE; double val_adc = raw_minibuffer_data.GetSample(p); trace_x.push_back(ns_time - pulse_start_time); diff --git a/configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig_cosmic b/configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig_cosmic deleted file mode 100644 index cac47db04..000000000 --- a/configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig_cosmic +++ /dev/null @@ -1,30 +0,0 @@ -ANNIEEventTreeMakerVerbosity 0 - -fillAllTriggers 1 -fill_singleTrigger 0 -fillLAPPDEventsOnly 0 -TankCluster_fill 1 -cluster_TankHitInfo_fill 1 - -TankReco_fill 0 - -OutputFile ANNIETree.root -TankClusterProcessing 1 -MRDClusterProcessing 1 -TriggerProcessing 1 -TankHitInfo_fill 1 -MRDHitInfo_fill 1 -MRDReco_fill 1 -SiPMPulseInfo_fill 0 -fillCleanEventsOnly 0 -MCTruth_fill 0 -Reco_fill 1 -RecoDebug_fill 0 -muonTruthRecoDiff_fill 0 -isData 1 -HasGenie 0 - -LAPPDData_fill 1 -LAPPDReco_fill 0 -RWMBRF_fill 0 -LAPPD_PPS_fill 0 From 913de42f513b8bf4cf1f772afa3f846434a2e0c3 Mon Sep 17 00:00:00 2001 From: Steven Doran Date: Thu, 10 Apr 2025 14:37:44 -0500 Subject: [PATCH 135/163] Tried to make it as backwards compatible as possible... also modified PrintANNIEEvent to read the pulses --- DataModel/ADCPulse.h | 4 +- UserTools/PrintANNIEEvent/PrintANNIEEvent.cpp | 46 ++++++++++++++++--- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/DataModel/ADCPulse.h b/DataModel/ADCPulse.h index fd594e5bb..e78f8d5e1 100755 --- a/DataModel/ADCPulse.h +++ b/DataModel/ADCPulse.h @@ -94,8 +94,8 @@ class ADCPulse : public Hit { unsigned short raw_amplitude_; // ADC double calibrated_amplitude_; // V - std::vector trace_x_; // x points of the pulse (start at 0, relative to pulse start) [ns] - std::vector trace_y_; // y points of the pulse (baseline-subtracted) [ADC] + std::vector trace_x_ = {}; // x points of the pulse (start at 0, relative to pulse start) [ns] + std::vector trace_y_ = {}; // y points of the pulse (baseline-subtracted) [ADC] }; // Need to increment the class version since we added time as a new variable diff --git a/UserTools/PrintANNIEEvent/PrintANNIEEvent.cpp b/UserTools/PrintANNIEEvent/PrintANNIEEvent.cpp index e80661db3..16e49b726 100644 --- a/UserTools/PrintANNIEEvent/PrintANNIEEvent.cpp +++ b/UserTools/PrintANNIEEvent/PrintANNIEEvent.cpp @@ -301,13 +301,45 @@ bool PrintANNIEEvent::Execute(){ cout <<"RecoADCPulses : {"< Date: Fri, 11 Apr 2025 14:37:50 -0500 Subject: [PATCH 136/163] Add B:BRRMP also for bunch rotation, which is "Bunch Rotation 473 Curve (Volt)" --- UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp b/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp index 6426ee50f..8149ef343 100644 --- a/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp +++ b/UserTools/BeamFetcherV2/IFBeamDBInterfaceV2.cpp @@ -32,9 +32,10 @@ IFBeamDBInterfaceV2::IFBeamDBInterfaceV2() {"E:HPTG2", "mm"}, {"E:VPTG2", "mm"}, {"E:BTH2T2", "DegC"}, - {"B:BRRMPL","bool"}, - {"B:BRRMPS","bool"}, - {"B:BRRMPQ","bool"}}; + {"B:BRRMPL","unknown"}, + {"B:BRRMPS","unknown"}, + {"B:BRRMPQ","unknown"}, + {"B:BRRMP","volt"}}; } IFBeamDBInterfaceV2::~IFBeamDBInterfaceV2() From b004f4a5b53b5c996c14076ae4d8d2113f359549 Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Fri, 11 Apr 2025 14:50:29 -0500 Subject: [PATCH 137/163] Add a bunch rotation on/off flag --- .../ANNIEEventTreeMaker.cpp | 6 ++++ .../ANNIEEventTreeMaker/ANNIEEventTreeMaker.h | 2 ++ UserTools/EBSaver/EBSaver.cpp | 32 +++++++++++++------ UserTools/EBSaver/EBSaver.h | 1 + 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index fd2519324..e8b842b99 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -96,6 +96,7 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) { fANNIETree->Branch("beam_pot_875", &fPot, "beam_pot_875/D"); fANNIETree->Branch("beam_ok", &fBeamok, "beam_ok/I"); + fANNIETree->Branch("BunchRotationOn", &fBunchRotationOn, "BunchRotationOn/D"); fANNIETree->Branch("beam_E_TOR860", &beam_E_TOR860, "beam_E_TOR860/D"); fANNIETree->Branch("beam_E_TOR875", &beam_E_TOR875, "beam_E_TOR875/D"); fANNIETree->Branch("beam_THCURR", &beam_THCURR, "beam_THCURR/D"); @@ -110,6 +111,7 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) fANNIETree->Branch("beam_B_BRRMPL", &beam_B_BRRMPL, "beam_B_BRRMPL/D"); fANNIETree->Branch("beam_B_BRRMPQ", &beam_B_BRRMPQ, "beam_B_BRRMPQ/D"); fANNIETree->Branch("beam_B_BRRMPS", &beam_B_BRRMPS, "beam_B_BRRMPS/D"); + fANNIETree->Branch("beam_B_BRRMP", &beam_B_BRRMP, "beam_B_BRRMP/D"); fANNIETree->Branch("BeamInfoTime", &fBeamInfoTime, "BeamInfoTime/l"); fANNIETree->Branch("BeamInfoTimeToTriggerDiff", &fBeamInfoTimeToTriggerDiff, "BeamInfoTimeToTriggerDiff/L"); } @@ -637,6 +639,7 @@ void ANNIEEventTreeMaker::ResetVariables() // beam info fPot = -9999; fBeamok = 0; + fBunchRotationOn = 0; beam_E_TOR860 = -9999; beam_E_TOR875 = -9999; beam_THCURR = -9999; @@ -651,6 +654,7 @@ void ANNIEEventTreeMaker::ResetVariables() beam_B_BRRMPL = -9999; beam_B_BRRMPQ = -9999; beam_B_BRRMPS = -9999; + beam_B_BRRMP = -9999 fBeamInfoTime = 0; fBeamInfoTimeToTriggerDiff = -9999; @@ -1138,9 +1142,11 @@ void ANNIEEventTreeMaker::LoadBeamInfo() m_data->Stores["ANNIEEvent"]->Get("beam_B_BRRMPL", beam_B_BRRMPL); m_data->Stores["ANNIEEvent"]->Get("beam_B_BRRMPQ", beam_B_BRRMPQ); m_data->Stores["ANNIEEvent"]->Get("beam_B_BRRMPS", beam_B_BRRMPS); + m_data->Stores["ANNIEEvent"]->Get("beam_B_BRRMP", beam_B_BRRMP); m_data->Stores["ANNIEEvent"]->Get("beam_E_TOR875", fPot); m_data->Stores["ANNIEEvent"]->Get("beam_good", fBeamok); + m_data->Stores["ANNIEEvent"]->Get("bunch_rotation_on", fBunchRotationOn); m_data->Stores["ANNIEEvent"]->Get("BeamInfoTime", fBeamInfoTime); m_data->Stores["ANNIEEvent"]->Get("BeamInfoTimeToTriggerDiff", fBeamInfoTimeToTriggerDiff); diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h index 79068c239..4fa24ea4f 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h @@ -161,6 +161,7 @@ class ANNIEEventTreeMaker : public Tool // beam information double fPot; int fBeamok; + int fBunchRotationOn; double beam_E_TOR860; double beam_E_TOR875; double beam_THCURR; @@ -175,6 +176,7 @@ class ANNIEEventTreeMaker : public Tool double beam_B_BRRMPL; double beam_B_BRRMPQ; double beam_B_BRRMPS; + double beam_B_BRRMP; uint64_t fBeamInfoTime; int64_t fBeamInfoTimeToTriggerDiff; diff --git a/UserTools/EBSaver/EBSaver.cpp b/UserTools/EBSaver/EBSaver.cpp index dc022613d..3348db81e 100644 --- a/UserTools/EBSaver/EBSaver.cpp +++ b/UserTools/EBSaver/EBSaver.cpp @@ -761,9 +761,9 @@ bool EBSaver::SavePMTData(uint64_t PMTTime) ANNIEEvent->Set("RecoAuxADCData", PMTRecoADCHitsAux); ANNIEEvent->Set("RawAcqSize", PMTRawAcqSize); - if(saveRawRWMWaveform) + if (saveRawRWMWaveform) { - //find PMTTime as key in RWMRawWaveforms, if found, save it, if not, save an empty vector + // find PMTTime as key in RWMRawWaveforms, if found, save it, if not, save an empty vector if (RWMRawWaveforms->find(PMTTime) != RWMRawWaveforms->end() && RWMRawWaveforms->at(PMTTime).size() > 0) { std::vector RWMRawWaveform = RWMRawWaveforms->at(PMTTime); @@ -778,9 +778,9 @@ bool EBSaver::SavePMTData(uint64_t PMTTime) Log("EBSaver: Saved empty RWM data with PMTTime " + std::to_string(PMTTime), v_debug, verbosityEBSaver); } } - if(saveRawBRFWaveform) + if (saveRawBRFWaveform) { - //find PMTTime as key in BRFRawWaveforms, if found, save it, if not, save an empty vector + // find PMTTime as key in BRFRawWaveforms, if found, save it, if not, save an empty vector if (BRFRawWaveforms->find(PMTTime) != BRFRawWaveforms->end() && BRFRawWaveforms->at(PMTTime).size() > 0) { std::vector BRFRawWaveform = BRFRawWaveforms->at(PMTTime); @@ -947,7 +947,7 @@ bool EBSaver::SaveLAPPDData(uint64_t LAPPDTime) LAPPDTS_PPSDiff.emplace(LAPPDTime, Buffer_LAPPDTS_PPSDiff.at(index)); LAPPDTS_PPSMissing.emplace(LAPPDTime, Buffer_LAPPDTS_PPSMissing.at(index)); - if(Buffer_LAPPDTS_PPSMissing.at(index)!= Buffer_LAPPDBG_PPSMissing.at(index)) + if (Buffer_LAPPDTS_PPSMissing.at(index) != Buffer_LAPPDBG_PPSMissing.at(index)) { Log("EBSaver: LAPPDTS_PPSMissing is different from LAPPDBG_PPSMissing, LAPPDTS_PPSMissing " + std::to_string(Buffer_LAPPDTS_PPSMissing.at(index)) + " LAPPDBG_PPSMissing " + std::to_string(Buffer_LAPPDBG_PPSMissing.at(index)), v_message, verbosityEBSaver); } @@ -1119,9 +1119,9 @@ bool EBSaver::GotAllDataFromOriginalBuffer() bool gotBuffer_LAPPDTS_PPSAfter = m_data->CStore.Get("Buffer_LAPPDTS_PPSAfter", Buffer_LAPPDTS_PPSAfter); bool gotBuffer_LAPPDTS_PPSDiff = m_data->CStore.Get("Buffer_LAPPDTS_PPSDiff", Buffer_LAPPDTS_PPSDiff); bool gotBuffer_LAPPDTS_PPSMissing = m_data->CStore.Get("Buffer_LAPPDTS_PPSMissing", Buffer_LAPPDTS_PPSMissing); - if(!gotBuffer_LAPPDBG_PPSBefore || !gotBuffer_LAPPDBG_PPSAfter || !gotBuffer_LAPPDBG_PPSDiff || !gotBuffer_LAPPDBG_PPSMissing || !gotBuffer_LAPPDTS_PPSBefore || !gotBuffer_LAPPDTS_PPSAfter || !gotBuffer_LAPPDTS_PPSDiff || !gotBuffer_LAPPDTS_PPSMissing) + if (!gotBuffer_LAPPDBG_PPSBefore || !gotBuffer_LAPPDBG_PPSAfter || !gotBuffer_LAPPDBG_PPSDiff || !gotBuffer_LAPPDBG_PPSMissing || !gotBuffer_LAPPDTS_PPSBefore || !gotBuffer_LAPPDTS_PPSAfter || !gotBuffer_LAPPDTS_PPSDiff || !gotBuffer_LAPPDTS_PPSMissing) Log("EBSaver: Failed to get LAPPD PPS data from buffer", v_message, verbosityEBSaver); - + // got LAPPD match info bool gotPairedLAPPDTriggerTimestamp = m_data->CStore.Get("PairedLAPPDTriggerTimestamp", PairedLAPPDTriggerTimestamp); bool gotPairedLAPPDTimeStamps = m_data->CStore.Get("PairedLAPPDTimeStamps", PairedLAPPDTimeStamps); @@ -1349,7 +1349,7 @@ void EBSaver::LoadBeamInfo() uint64_t timestamp; double E_TOR860, E_TOR875, THCURR, BTJT2, HP875, VP875, HPTG1, VPTG1, HPTG2, VPTG2, BTH2T2; - double B_BRRMPL, B_BRRMPQ, B_BRRMPS; + double B_BRRMPL, B_BRRMPQ, B_BRRMPS, B_BRRMP; tree->SetBranchAddress("Timestamp", ×tamp); tree->SetBranchAddress("E_TOR860", &E_TOR860); @@ -1366,6 +1366,7 @@ void EBSaver::LoadBeamInfo() tree->SetBranchAddress("B_BRRMPL", &B_BRRMPL); tree->SetBranchAddress("B_BRRMPQ", &B_BRRMPQ); tree->SetBranchAddress("B_BRRMPS", &B_BRRMPS); + tree->SetBranchAddress("B_BRRMP", &B_BRRMP); Long64_t nentries = tree->GetEntries(); Log("EBSaver: Loading beam infor, total entries in beam info file: " + std::to_string(nentries), v_message, verbosityEBSaver); @@ -1389,6 +1390,7 @@ void EBSaver::LoadBeamInfo() B_BRRMPL_map.emplace(timestamp, B_BRRMPL); B_BRRMPQ_map.emplace(timestamp, B_BRRMPQ); B_BRRMPS_map.emplace(timestamp, B_BRRMPS); + B_BRRMP_map.emplace(timestamp, B_BRRMP); } Log("EBSaver: Loaded number of E_TOR860 entries: " + std::to_string(E_TOR860_map.size()), v_message, verbosityEBSaver); @@ -1401,7 +1403,7 @@ void EBSaver::LoadBeamInfo() bool EBSaver::SaveBeamInfo(uint64_t TriggerTime) { double E_TOR860, E_TOR875, THCURR, BTJT2, HP875, VP875, HPTG1, VPTG1, HPTG2, VPTG2, BTH2T2; - double B_BRRMPL, B_BRRMPQ, B_BRRMPS; + double B_BRRMPL, B_BRRMPQ, B_BRRMPS, B_BRRMP; // find the closest timestamp in vector BeamInfoTimestamps uint64_t closestTimestamp = 0; @@ -1432,6 +1434,7 @@ bool EBSaver::SaveBeamInfo(uint64_t TriggerTime) int64_t timeDiff = -9999; double defaultVal = -9999.; int beam_good = 0; + int bunch_rotation_on = 0; ANNIEEvent->Set("BeamInfoTime", beamInfoTime_long); ANNIEEvent->Set("BeamInfoTimeToTriggerDiff", timeDiff); ANNIEEvent->Set("beam_E_TOR860", defaultVal); @@ -1448,7 +1451,9 @@ bool EBSaver::SaveBeamInfo(uint64_t TriggerTime) ANNIEEvent->Set("beam_B_BRRMPL", defaultVal); ANNIEEvent->Set("beam_B_BRRMPQ", defaultVal); ANNIEEvent->Set("beam_B_BRRMPS", defaultVal); + ANNIEEvent->Set("beam_B_BRRMP", defaultVal); ANNIEEvent->Set("beam_good", beam_good); + ANNIEEvent->Set("bunch_rotation_on", bunch_rotation_on); Log("EBSaver: Saved beam info with time " + std::to_string(0) + ", pot E_TOR860 = " + std::to_string(-9999) + ", beam_good = " + std::to_string(-9999), v_message, verbosityEBSaver); } @@ -1476,6 +1481,7 @@ bool EBSaver::SaveBeamInfo(uint64_t TriggerTime) B_BRRMPL = B_BRRMPL_map.at(beamInfoTime); B_BRRMPQ = B_BRRMPQ_map.at(beamInfoTime); B_BRRMPS = B_BRRMPS_map.at(beamInfoTime); + B_BRRMP = B_BRRMP_map.at(beamInfoTime); ANNIEEvent->Set("BeamInfoTime", beamInfoTime); ANNIEEvent->Set("BeamInfoTimeToTriggerDiff", timeDiff); @@ -1494,6 +1500,7 @@ bool EBSaver::SaveBeamInfo(uint64_t TriggerTime) ANNIEEvent->Set("beam_B_BRRMPL", B_BRRMPL); ANNIEEvent->Set("beam_B_BRRMPQ", B_BRRMPQ); ANNIEEvent->Set("beam_B_BRRMPS", B_BRRMPS); + ANNIEEvent->Set("beam_B_BRRMP", B_BRRMP); int beam_good = 0; @@ -1505,6 +1512,13 @@ bool EBSaver::SaveBeamInfo(uint64_t TriggerTime) ANNIEEvent->Set("beam_good", beam_good); + int bunch_rotation_on = 0; + if (B_BRRMP > 0) + { + bunch_rotation_on = 1; + } + ANNIEEvent->Set("bunch_rotation_on", bunch_rotation_on); + Log("EBSaver: Saved beam info with time " + std::to_string(beamInfoTime) + ", pot E_TOR860 = " + std::to_string(E_TOR860) + ", beam_good = " + std::to_string(beam_good), v_message, verbosityEBSaver); } diff --git a/UserTools/EBSaver/EBSaver.h b/UserTools/EBSaver/EBSaver.h index 9d57e332d..9a78b2ac1 100644 --- a/UserTools/EBSaver/EBSaver.h +++ b/UserTools/EBSaver/EBSaver.h @@ -200,6 +200,7 @@ class EBSaver : public Tool std::map B_BRRMPL_map; std::map B_BRRMPS_map; std::map B_BRRMPQ_map; + std::map B_BRRMP_map; }; From 7e26fe14503606352137f3995a4c51c07e211a3c Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Mon, 14 Apr 2025 11:44:49 -0500 Subject: [PATCH 138/163] Update ANNIEEventTreeMaker.cpp Forgot a semicolon :) --- UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index e8b842b99..32aa65ccc 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -654,7 +654,7 @@ void ANNIEEventTreeMaker::ResetVariables() beam_B_BRRMPL = -9999; beam_B_BRRMPQ = -9999; beam_B_BRRMPS = -9999; - beam_B_BRRMP = -9999 + beam_B_BRRMP = -9999; fBeamInfoTime = 0; fBeamInfoTimeToTriggerDiff = -9999; @@ -2589,4 +2589,4 @@ void ANNIEEventTreeMaker::FillLAPPDMCHitInfo() fLAPPDMCHitTransversePos.push_back(transverse); } } -} \ No newline at end of file +} From 984d5af4fb4c11d44238c4dfe414a63a189bc0db Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 16 Apr 2025 14:40:04 -0500 Subject: [PATCH 139/163] Update EBSaverConfig - no beam in laser remove beam info for laser runs, missed bug fix --- configfiles/EventBuilderV2_laser/EBSaverConfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configfiles/EventBuilderV2_laser/EBSaverConfig b/configfiles/EventBuilderV2_laser/EBSaverConfig index 4753d1a76..7483a7a8d 100644 --- a/configfiles/EventBuilderV2_laser/EBSaverConfig +++ b/configfiles/EventBuilderV2_laser/EBSaverConfig @@ -5,6 +5,6 @@ saveMRD 0 saveCTC 1 saveLAPPD 1 saveRunInfo 1 -saveBeamInfo 1 +saveBeamInfo 0 beamInfoFileName beamfetcher_tree.root From ae552d2771eeb0486c5127e0363768e5650bec20 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Wed, 16 Apr 2025 14:41:31 -0500 Subject: [PATCH 140/163] Update EBLoadRawConfig wrong path --- configfiles/EventBuilderV2_laser/EBLoadRawConfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configfiles/EventBuilderV2_laser/EBLoadRawConfig b/configfiles/EventBuilderV2_laser/EBLoadRawConfig index 63966d0cb..7901c4de7 100644 --- a/configfiles/EventBuilderV2_laser/EBLoadRawConfig +++ b/configfiles/EventBuilderV2_laser/EBLoadRawConfig @@ -1,7 +1,7 @@ verbosityEBLoadRaw 2 ReadTriggerOverlap 1 -InputFile ./configfiles/EventBuilderV2/my_files.txt +InputFile ./configfiles/EventBuilderV2_laser/my_files.txt LoadPMT 1 LoadMRD 0 From 0e28d5fea0ec4d01e59ee308ad4ae32ae85d8a44 Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Wed, 16 Apr 2025 15:20:50 -0500 Subject: [PATCH 141/163] Fix a bug for saving the bunch rotation with /D rather than /I in tree --- UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index 32aa65ccc..a1d8d72d5 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -96,7 +96,7 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) { fANNIETree->Branch("beam_pot_875", &fPot, "beam_pot_875/D"); fANNIETree->Branch("beam_ok", &fBeamok, "beam_ok/I"); - fANNIETree->Branch("BunchRotationOn", &fBunchRotationOn, "BunchRotationOn/D"); + fANNIETree->Branch("BunchRotationOn", &fBunchRotationOn, "BunchRotationOn/I"); fANNIETree->Branch("beam_E_TOR860", &beam_E_TOR860, "beam_E_TOR860/D"); fANNIETree->Branch("beam_E_TOR875", &beam_E_TOR875, "beam_E_TOR875/D"); fANNIETree->Branch("beam_THCURR", &beam_THCURR, "beam_THCURR/D"); From 41bdbcb683fe2df60fc4a1f23bf725820dfda347 Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Wed, 16 Apr 2025 15:57:05 -0500 Subject: [PATCH 142/163] Add a comment for bunch rotation document in EBSaver. Add new bunch rotation variables for Filter --- UserTools/EBSaver/EBSaver.cpp | 4 ++++ .../ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/UserTools/EBSaver/EBSaver.cpp b/UserTools/EBSaver/EBSaver.cpp index 3348db81e..988c8ec08 100644 --- a/UserTools/EBSaver/EBSaver.cpp +++ b/UserTools/EBSaver/EBSaver.cpp @@ -1345,6 +1345,10 @@ void EBSaver::LoadBeamInfo() // * BTH2T2 - target air cooling temperature. This is the temperature of the // air going into the horn. + // For bunch rotation, the information can be found here: + // https://beamdocs.fnal.gov/AD/DocDB/0069/006904/008/20181214BunchRotation.pdf + // The B_BRRMP has unit of volt, others are not clear. + // additionally, the unit of E_TOR860 and E_TOR875 is E12 uint64_t timestamp; diff --git a/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp index 7b0d64deb..8fb4ff3e0 100644 --- a/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp +++ b/UserTools/ProcessedLAPPDFilter/ProcessedLAPPDFilter.cpp @@ -604,6 +604,8 @@ bool ProcessedLAPPDFilter::GotANNIEEventAndSave(BoostStore *BS, string savePath) double defaultVal = -9999.; int beam_good = 0; double E_TOR860, E_TOR875, THCURR, BTJT2, HP875, VP875, HPTG1, VPTG1, HPTG2, VPTG2, BTH2T2; + double B_BRRMPL, B_BRRMPQ, B_BRRMPS, B_BRRMP; + int bunch_rotation_on; m_data->Stores["ANNIEEvent"]->Get("BeamInfoTime", beamInfoTime); BS->Set("BeamInfoTime", beamInfoTime); m_data->Stores["ANNIEEvent"]->Get("BeamInfoTimeToTriggerDiff", timeDiff); @@ -630,6 +632,16 @@ bool ProcessedLAPPDFilter::GotANNIEEventAndSave(BoostStore *BS, string savePath) BS->Set("beam_VPTG2", VPTG2); m_data->Stores["ANNIEEvent"]->Get("beam_BTH2T2", BTH2T2); BS->Set("beam_BTH2T2", BTH2T2); + m_data->Stores["ANNIEEvent"]->Get("beam_B_BRRMPL", B_BRRMPL); + BS->Set("beam_B_BRRMPL", B_BRRMPL); + m_data->Stores["ANNIEEvent"]->Get("beam_B_BRRMPQ", B_BRRMPQ); + BS->Set("beam_B_BRRMPQ", B_BRRMPQ); + m_data->Stores["ANNIEEvent"]->Get("beam_B_BRRMPS", B_BRRMPS); + BS->Set("beam_B_BRRMPS", B_BRRMPS); + m_data->Stores["ANNIEEvent"]->Get("beam_B_BRRMP", B_BRRMP); + BS->Set("beam_B_BRRMP", B_BRRMP); + m_data->Stores["ANNIEEvent"]->Get("bunch_rotation_on", bunch_rotation_on); + BS->Set("bunch_rotation_on", bunch_rotation_on); m_data->Stores["ANNIEEvent"]->Get("beam_good", beam_good); BS->Set("beam_good", beam_good); From dbdf16baa3bfbf6f521c6337acb866a8360c6d60 Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Wed, 16 Apr 2025 20:30:46 -0500 Subject: [PATCH 143/163] Add PMT type load from channel class to tree maker --- DataModel/Channel.h | 9 +++++++-- .../ANNIEEventTreeMaker.cpp | 16 ++++++++++++++++ .../ANNIEEventTreeMaker/ANNIEEventTreeMaker.h | 2 ++ UserTools/LoadGeometry/LoadGeometry.cpp | 19 ++++++++++++++++++- 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/DataModel/Channel.h b/DataModel/Channel.h index 80f4b2626..3c44cb804 100644 --- a/DataModel/Channel.h +++ b/DataModel/Channel.h @@ -14,8 +14,9 @@ class Channel : public SerialisableObject{ public: Channel() : ChannelID(-1), channelrelposition(Position(-1,-1,-1)), stripside(2), stripnum(-1), signal_crate(-1), signal_card(-1), signal_channel(-1), level2_crate(-1), level2_card(-1), level2_channel(-1), hv_crate(-1), hv_card(-1), hv_channel(-1), status(channelstatus::OFF) - {serialise=true;} - Channel(unsigned long chnID, Position chanpos, int strp, int strpnm, unsigned int sig_crt, unsigned int sig_crd, unsigned int sig_chn, unsigned int lv2_crt, unsigned int lv2_crd, unsigned int lv2_ch, unsigned int hv_crt, unsigned int hv_crd, unsigned int hv_chn, channelstatus chanstat) : ChannelID(chnID), channelrelposition(chanpos), stripside(strp), stripnum(strpnm), signal_crate(sig_crt), signal_card(sig_crd), signal_channel(sig_chn), level2_crate(lv2_crt), level2_card(lv2_crd), level2_channel(lv2_ch), hv_crate(hv_crt), hv_card(hv_crd), hv_channel(hv_chn), status(chanstat) {serialise=true;} + {channelType = 0; serialise=true;} + Channel(unsigned long chnID, Position chanpos, int strp, int strpnm, unsigned int sig_crt, unsigned int sig_crd, unsigned int sig_chn, unsigned int lv2_crt, unsigned int lv2_crd, unsigned int lv2_ch, unsigned int hv_crt, unsigned int hv_crd, unsigned int hv_chn, channelstatus chanstat) : ChannelID(chnID), channelrelposition(chanpos), stripside(strp), stripnum(strpnm), signal_crate(sig_crt), signal_card(sig_crd), signal_channel(sig_chn), level2_crate(lv2_crt), level2_card(lv2_crd), level2_channel(lv2_ch), hv_crate(hv_crt), hv_card(hv_crd), hv_channel(hv_chn), status(chanstat) {channelType=0; serialise=true;} + Channel(unsigned long chnID, Position chanpos, int strp, int strpnm, unsigned int sig_crt, unsigned int sig_crd, unsigned int sig_chn, unsigned int lv2_crt, unsigned int lv2_crd, unsigned int lv2_ch, unsigned int hv_crt, unsigned int hv_crd, unsigned int hv_chn, channelstatus chanstat, int channelPMTType) : ChannelID(chnID), channelrelposition(chanpos), stripside(strp), stripnum(strpnm), signal_crate(sig_crt), signal_card(sig_crd), signal_channel(sig_chn), level2_crate(lv2_crt), level2_card(lv2_crd), level2_channel(lv2_ch), hv_crate(hv_crt), hv_card(hv_crd), hv_channel(hv_chn), status(chanstat), channelType(channelPMTType) {serialise=true;} virtual ~Channel(){} unsigned long GetChannelID(){return ChannelID;} @@ -32,6 +33,7 @@ class Channel : public SerialisableObject{ unsigned int GetHvCard(){return hv_card;} unsigned int GetHvChannel(){return hv_channel;} channelstatus GetStatus(){return status;} + int GetChannelType(){return channelType;} void SetChannelID(unsigned long channelIDin){ChannelID=channelIDin;} void SetRelPos(Position pos){ channelrelposition=pos;} @@ -47,6 +49,7 @@ class Channel : public SerialisableObject{ void SetHvCard(unsigned int cardin){hv_card=cardin;} void SetHvChannel(unsigned int chanin){hv_channel=chanin;} void SetStatus(channelstatus stat){status=stat;} + void SetChannelType(int type){channelType=type;} bool Print(){ std::cout<<"ChannelID : "< void serialize(Archive & ar, const unsigned int version){ if(serialise){ ar & ChannelID; @@ -97,6 +101,7 @@ class Channel : public SerialisableObject{ ar & hv_card; ar & hv_channel; ar & status; + ar & channelType; } } diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index a1d8d72d5..9cc2a9bcf 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -153,6 +153,7 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) fANNIETree->Branch("Cluster_HitDetID", &fCluster_HitDetID); fANNIETree->Branch("Cluster_HitChankey", &fCluster_HitChankey); fANNIETree->Branch("Cluster_HitChankeyMC", &fCluster_HitChankeyMC); + fANNIETree->Branch("Cluster_HitPMTType", &fCluster_HitPMTType); // MRD cluster information fANNIETree->Branch("eventTimeMRD", &fEventTimeMRD_Tree); @@ -176,6 +177,7 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) fANNIETree->Branch("hitDetID", &fHitDetID); fANNIETree->Branch("hitChankey", &fHitChankey); fANNIETree->Branch("hitChankeyMC", &fHitChankeyMC); + fANNIETree->Branch("hitPMTType", &fHitPMTType); } if (SiPMPulseInfo_fill) @@ -681,6 +683,7 @@ void ANNIEEventTreeMaker::ResetVariables() fHitDetID.clear(); fHitChankey.clear(); fHitChankeyMC.clear(); + fHitPMTType.clear(); // SiPMPulse Info fSiPM1NPulses = 0; @@ -792,6 +795,7 @@ void ANNIEEventTreeMaker::ResetVariables() fCluster_HitDetID.clear(); fCluster_HitChankey.clear(); fCluster_HitChankeyMC.clear(); + fCluster_HitPMTType.clear(); fClusterMaxPEV.clear(); fClusterChargePointXV.clear(); @@ -1242,6 +1246,8 @@ void ANNIEEventTreeMaker::LoadAllTankHits() fHitDetID.push_back(detkey); fHitChankey.push_back(channel_key); fHitChankeyMC.push_back(channel_key); + Channel *thisHitChannel = geom->GetChannel(channel_key); + fHitPMTType.push_back(thisHitChannel->GetChannelType()); fHitType.push_back(RecoDigit::PMT8inch); // 0 For PMTs } } @@ -1262,6 +1268,8 @@ void ANNIEEventTreeMaker::LoadAllTankHits() fHitDetID.push_back(detkey); fHitChankey.push_back(channel_key_data); fHitChankeyMC.push_back(channel_key); + Channel *thisHitChannel = geom->GetChannel(channel_key); + fHitPMTType.push_back(thisHitChannel->GetChannelType()); fHitType.push_back(RecoDigit::PMT8inch); // 0 For PMTs } } @@ -1633,6 +1641,7 @@ void ANNIEEventTreeMaker::LoadTankClusterHits(std::vector cluster_hits) vector HitDetIDV; vector HitChankeyV; vector HitCKMC; + vector HitPMTType; for (int i = 0; i < (int)cluster_hits.size(); i++) { @@ -1655,6 +1664,8 @@ void ANNIEEventTreeMaker::LoadTankClusterHits(std::vector cluster_hits) HitChankeyV.push_back(channel_key); HitCKMC.push_back(channel_key); + Channel* thisHitChannel = geom->GetChannel(channel_key); + HitPMTType.push_back(thisHitChannel->GetChannelType()); HitTypeV.push_back(RecoDigit::PMT8inch); ClusterCharge += hit_charge; ClusterPE += hit_PE; @@ -1682,6 +1693,7 @@ void ANNIEEventTreeMaker::LoadTankClusterHits(std::vector cluster_hits) fCluster_HitDetID.push_back(HitDetIDV); fCluster_HitChankey.push_back(HitChankeyV); fCluster_HitChankeyMC.push_back(HitCKMC); + fCluster_HitPMTType.push_back(HitPMTType); return; } @@ -1706,6 +1718,7 @@ void ANNIEEventTreeMaker::LoadTankClusterHitsMC(std::vector cluster_hits, vector HitDetIDV; vector HitChankeyV; vector HitCKMC; + vector HitPMTType; for (int i = 0; i < (int)cluster_hits.size(); i++) { @@ -1733,6 +1746,8 @@ void ANNIEEventTreeMaker::LoadTankClusterHitsMC(std::vector cluster_hits, HitDetIDV.push_back(detkey); HitChankeyV.push_back(channel_key_data); HitCKMC.push_back(channel_key); + Channel* thisHitChannel = geom->GetChannel(channel_key_data); + HitPMTType.push_back(thisHitChannel->GetChannelType()); HitTypeV.push_back(RecoDigit::PMT8inch); ClusterCharge += hit_charge; ClusterPE += hit_PE; @@ -1760,6 +1775,7 @@ void ANNIEEventTreeMaker::LoadTankClusterHitsMC(std::vector cluster_hits, fCluster_HitDetID.push_back(HitDetIDV); fCluster_HitChankey.push_back(HitChankeyV); fCluster_HitChankeyMC.push_back(HitCKMC); + fCluster_HitPMTType.push_back(HitPMTType); return; } diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h index 4fa24ea4f..1dcd13091 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h @@ -204,6 +204,7 @@ class ANNIEEventTreeMaker : public Tool std::vector fHitDetID; std::vector fHitChankey; std::vector fHitChankeyMC; + std::vector fHitPMTType; // SiPMPulseInfo_fill int fSiPM1NPulses; @@ -319,6 +320,7 @@ class ANNIEEventTreeMaker : public Tool vector> fCluster_HitDetID; vector> fCluster_HitChankey; vector> fCluster_HitChankeyMC; + vector> fCluster_HitPMTType; vector fClusterMaxPEV; vector fClusterChargePointXV; diff --git a/UserTools/LoadGeometry/LoadGeometry.cpp b/UserTools/LoadGeometry/LoadGeometry.cpp index de93f7e7b..e077e1f9a 100644 --- a/UserTools/LoadGeometry/LoadGeometry.cpp +++ b/UserTools/LoadGeometry/LoadGeometry.cpp @@ -630,6 +630,22 @@ bool LoadGeometry::ParseTankPMTDataEntry(std::vector SpecLine, detstatus, 0.); + if (verbosity > 5) std::cout << "Filling a channel with PMT_type == " << PMT_type << ", PMT_type == LUX:" << (PMT_type == "LUX") << ", PMT_type == Hamamatsu:" << (PMT_type == "Hamamatsu") << std::endl; + int channelType = 0; + if (PMT_type == "LUX"){ + channelType = 1; + } else if (PMT_type == "ETEL"){ + channelType = 2; + } else if (PMT_type == "Hamamatsu"){ + channelType = 3; + } else if (PMT_type == "Watchboy"){ + channelType = 4; + } else if (PMT_type == "Watchman"){ + channelType = 5; + } else { + Log("LoadGeometry Tool: Loading UNDEFINED PMT type for channel "+std::to_string(channel_num),0,verbosity); + } + Channel pmtchannel( channel_num, Position(0,0,0.), -1, // stripside @@ -643,7 +659,8 @@ bool LoadGeometry::ParseTankPMTDataEntry(std::vector SpecLine, hv_crate, hv_slot, hv_channel, - chanstatus); //channel status same as detector status here + chanstatus, + channelType); //channel status same as detector status here // Also add this channel to the Tank PMT electronics map std::vector crate_map{signal_crate,signal_slot,signal_channel}; From c4263412e675d4a0bb7af223ce270af6c2200384 Mon Sep 17 00:00:00 2001 From: Steven Doran Date: Thu, 17 Apr 2025 15:00:14 -0500 Subject: [PATCH 144/163] New PrintADCTraces tool to export pulses to root file --- UserTools/Factory/Factory.cpp | 1 + UserTools/PrintADCTraces/PrintADCTraces.cpp | 269 ++++++++++++++++++ UserTools/PrintADCTraces/PrintADCTraces.h | 69 +++++ UserTools/PrintADCTraces/README.md | 59 ++++ UserTools/Unity.h | 1 + .../PrintADCTraces/LoadANNIEEventConfig | 4 + .../PrintADCTraces/PrintADCTracesConfig | 17 ++ configfiles/PrintADCTraces/ToolChainConfig | 23 ++ configfiles/PrintADCTraces/ToolsConfig | 4 + .../PrintADCTraces/create_my_inputs.sh | 19 ++ configfiles/PrintADCTraces/my_inputs.txt | 1 + 11 files changed, 467 insertions(+) create mode 100644 UserTools/PrintADCTraces/PrintADCTraces.cpp create mode 100644 UserTools/PrintADCTraces/PrintADCTraces.h create mode 100644 UserTools/PrintADCTraces/README.md create mode 100644 configfiles/PrintADCTraces/LoadANNIEEventConfig create mode 100644 configfiles/PrintADCTraces/PrintADCTracesConfig create mode 100644 configfiles/PrintADCTraces/ToolChainConfig create mode 100644 configfiles/PrintADCTraces/ToolsConfig create mode 100644 configfiles/PrintADCTraces/create_my_inputs.sh create mode 100644 configfiles/PrintADCTraces/my_inputs.txt diff --git a/UserTools/Factory/Factory.cpp b/UserTools/Factory/Factory.cpp index 6bc13642c..137bdf08a 100644 --- a/UserTools/Factory/Factory.cpp +++ b/UserTools/Factory/Factory.cpp @@ -186,5 +186,6 @@ if (tool=="BeamQuality") ret=new BeamQuality; if (tool=="FitRWMWaveform") ret=new FitRWMWaveform; if (tool=="LAPPDLoadTXT") ret=new LAPPDLoadTXT; if (tool=="LAPPDBSCharging") ret=new LAPPDBSCharging; +if (tool=="PrintADCTraces") ret=new PrintADCTraces; return ret; } diff --git a/UserTools/PrintADCTraces/PrintADCTraces.cpp b/UserTools/PrintADCTraces/PrintADCTraces.cpp new file mode 100644 index 000000000..a93dc55b1 --- /dev/null +++ b/UserTools/PrintADCTraces/PrintADCTraces.cpp @@ -0,0 +1,269 @@ +#include + +#include "ANNIEconstants.h" +#include "PrintADCTraces.h" + +#include "TGraph.h" + +PrintADCTraces::PrintADCTraces():Tool(){} + +// Tool will loop over hits, extract ADC traces from the RecoADCData, and output those traces to a root file + +// output root file structure +// ROOT file: +// ├── chankey/ # directory for each PMT channel +// ├── 332/ +// │ ├── wf1 TGraph # for each pulse, a TGraph +// │ └── wf2 TGraph +// ├── 463/ +// │ ├── wf1 TGraph +// │ └── ... +// └── TraceSummary TTree # metadata +// ├── chan # all pulse channel ids +// ├── hitT # all pulse hit times [ns] +// └── hitPE # all pulse hit charges [pe] + + +bool PrintADCTraces::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if(configfile!="") m_variables.Initialise(configfile); // loading config file + + m_data= &data; //assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + // get config variables + + bool gotVerbosity = m_variables.Get("verbosity", verbosity); + if (!gotVerbosity) verbosity = 1; + + // range of hit charges to save + gotPEmin = m_variables.Get("hitPE_min", fhitPEmin); + if (!gotPEmin) { + logmessage = "PrintADCTraces: hitPE_min not defined. No selection will be imposed."; + Log(logmessage, v_error, verbosity); + } + gotPEmax = m_variables.Get("hitPE_max", fhitPEmax); + if (!gotPEmax) { + logmessage = "PrintADCTraces: hitPE_max not defined. No selection will be imposed."; + Log(logmessage, v_error, verbosity); + } + + // save only hit times in a certain range (useful for laser peak or beam spill) + gotTmin = m_variables.Get("hitT_min", fhitTmin); + if (!gotTmin) { + logmessage = "PrintADCTraces: hitT_min not defined. No selection will be imposed."; + Log(logmessage, v_error, verbosity); + } + gotTmax = m_variables.Get("hitT_max", fhitTmax); + if (!gotTmax) { + logmessage = "PrintADCTraces: hitT_max not defined. No selection will be imposed."; + Log(logmessage, v_error, verbosity); + } + + // maximum number of total traces saved - this could explode depending on how many events we run over + bool gotMaxTraces = m_variables.Get("MaxTraces", fMaxTraces); + if (!gotMaxTraces) { + logmessage = "PrintADCTraces: MaxTraces not defined. Using default of 10000."; + Log(logmessage, v_error, verbosity); + fMaxTraces = 10000; + } + + // per individual channel, how many traces do you want? + bool gotMaxTracesPerChan = m_variables.Get("MaxTracesPerChannel", fMaxTracesPerChan); + if (!gotMaxTracesPerChan) { + logmessage = "PrintADCTraces: MaxTracesPerChannel not defined. Setting no limit on traces per channel, will default to filling according to MaxTraces argument."; + Log(logmessage, v_error, verbosity); + fMaxTracesPerChan = 0; + } + + // name of the output root file containing trace data + bool gotOutputFilename = m_variables.Get("OutputFilename", filename); + if (!gotOutputFilename) { + logmessage = "PrintADCTraces: OutputFilename not defined. Setting output file name to: 'ADCTraces.root'"; + Log(logmessage, v_error, verbosity); + filename = "ADCTraces.root"; + } + + // set up output file + fOutFile = new TFile(filename.c_str(), "RECREATE"); + + // summary TTree containing global distribution of all saved ADC traces + fTraceSummaryTree = new TTree("TraceSummary", "Summary of saved ADC traces"); + fTraceSummaryTree->Branch("chan", &fchan); + fTraceSummaryTree->Branch("hitT", &fhitT); + fTraceSummaryTree->Branch("hitPE", &fhitPE); + + return true; +} + +//------------------------------------------------------------------------------ +bool PrintADCTraces::Execute() +{ + Log("PrintADCTraces: Execute()", v_debug, verbosity); + + // *********************************** + // load stores + + bool goodAnnieEvent = m_data->Stores.count("ANNIEEvent"); + if (!goodAnnieEvent) { + logmessage = "PrintADCTraces: no ANNIEEvent store! Aborting!"; + Log(logmessage, v_error, verbosity); + return false; + } + + // need this for the nQ -> PE conversion + bool gotSPEmap = m_data->CStore.Get("ChannelNumToTankPMTSPEChargeMap",fChannelKeyToSPEMap); + if (!gotSPEmap) { + logmessage = "PrintADCTraces: could not find ChannelNumToTankPMTSPEChargeMap! Aborting!"; + Log(logmessage, v_error, verbosity); + return false; + } + + // ADCPulse class information (contains the traces) + bool got_recoadc = m_data->Stores["ANNIEEvent"]->Get("RecoADCData",fRecoADCData); + if (!got_recoadc) { + logmessage = "PrintADCTraces: could not find RecoADCData! Aborting!"; + Log(logmessage, v_error, verbosity); + return false; + } + + // TGraph title will be ____ + int fRunNumber = 9999; + int fPartFileNumber = 9999; + uint64_t fWaveformTime = 0; + + bool gotRunNumber = m_data->Stores["ANNIEEvent"]->Get("RunNumber", fRunNumber); + bool gotPartFile = m_data->Stores["ANNIEEvent"]->Get("PartNumber", fPartFileNumber); + bool gotTimestamp = m_data->Stores["ANNIEEvent"]->Get("EventTimeTank", fWaveformTime); + + if (!gotPartFile || !gotTimestamp || !gotRunNumber) { + logmessage = "PrintADCTraces: Error retrieving "; + if (!gotRunNumber) logmessage += "RunNumber "; + if (!gotPartFile) logmessage += "PartNumber "; + if (!gotTimestamp) logmessage += "EventTimeTank "; + logmessage += "from ANNIEEvent! Setting default (nonsense) values."; + Log(logmessage, v_error, verbosity); + } + + // *********************************** + // write out ADC traces + + fOutFile->cd(); // go to root of output file + + // loop through RecoADCData and fill the graphs with the ADC traces + for (auto& chan_pair : fRecoADCData) { + unsigned long chankey = chan_pair.first; + auto& minibuffers = chan_pair.second; + + int& chanGraphCount = graphsPerChannel[chankey]; + + // make/get directory + std::string chanStr = std::to_string(chankey); + TDirectory* dir = fOutFile->GetDirectory(chanStr.c_str()); + if (!dir) dir = fOutFile->mkdir(chanStr.c_str()); + dir->cd(); + + for (size_t mb_i = 0; mb_i < minibuffers.size(); ++mb_i) { + + // if the max trace limit is reached, stop looping over the minibuffers + if ((fMaxTraces != 0 && totalGraphs >= fMaxTraces) || + (fMaxTracesPerChan != 0 && chanGraphCount >= fMaxTracesPerChan)) { + break; + } + + const auto& pulsevec = minibuffers.at(mb_i); + + for (const auto& pulse : pulsevec) { + + double hitT = pulse.peak_time(); // interpolated hit time + double hitQ = pulse.charge(); // charge in nQ + + // need to convert from nQ -> PE using SPE conversion map + auto spe_it = fChannelKeyToSPEMap.find(chankey); + double hitPE = -9999; + if (spe_it != fChannelKeyToSPEMap.end() && spe_it->second > 0) { + hitPE = hitQ / spe_it->second; + } else { + logmessage = "PrintADCTraces: Missing or invalid SPE value for channel " + std::to_string(chankey) + + ". Cannot convert to PE. Using placeholder -9999."; + Log(logmessage, v_warning, verbosity); + } + + // apply hitT and hitPE cuts (skip pulse if it doesn't pass) + bool passTime = (!gotTmin || hitT >= fhitTmin) && (!gotTmax || hitT <= fhitTmax); + bool passPE = (!gotPEmin || hitPE >= fhitPEmin) && (!gotPEmax || hitPE <= fhitPEmax); + if (!passTime || !passPE) continue; + + // construct TGraph title: ____ + std::stringstream grTitle; + grTitle << fRunNumber << "_" << fPartFileNumber << "_" << fWaveformTime + << "_" << std::fixed << std::setprecision(2) << hitT + << "_" << std::fixed << std::setprecision(2) << hitPE; + + // grab trace + const auto& xpts = pulse.GetTraceXPoints(); + const auto& ypts = pulse.GetTraceYPoints(); + + if (xpts.empty() || ypts.empty()) continue; + + // create and write to TGraph + TGraph gr(xpts.size()); + for (size_t i = 0; i < std::min(xpts.size(), ypts.size()); ++i) { + gr.SetPoint(i, xpts[i], ypts[i]); + } + gr.SetTitle(grTitle.str().c_str()); + gr.Write(); + + // write to summary TTree + fchan = chankey; + fhitT = pulse.peak_time(); + fhitPE = hitPE; + fTraceSummaryTree->Fill(); + + ++totalGraphs; + ++chanGraphCount; + } + } + } + + logmessage = "PrintADCTraces: Total graphs written this event: " + std::to_string(totalGraphs); + Log(logmessage, v_debug, verbosity); + + return true; +} + +//------------------------------------------------------------------------------ +bool PrintADCTraces::Finalise() +{ + if (fOutFile) { + + if (fTraceSummaryTree) { // write summary to root file + fOutFile->cd(); + fTraceSummaryTree->Write(); + } + + fOutFile->cd(); + fOutFile->Write(); // write all contents to file + fOutFile->Close(); // close the ROOT file + delete fOutFile; // clean up the pointer + fOutFile = nullptr; + } + + Log("PrintADCTraces: Finished and closed output ROOT file.", v_debug, verbosity); + + logmessage = "PrintADCTraces: Total graphs written across all events: " + std::to_string(totalGraphs); + Log(logmessage, v_debug, verbosity); + for (const auto& entry : graphsPerChannel) { + logmessage = " Channel " + std::to_string(entry.first) + + " → " + std::to_string(entry.second) + " graphs"; + Log(logmessage, v_debug, verbosity); + } + + return true; +} + +//------------------------------------------------------------------------------ + +// done \ No newline at end of file diff --git a/UserTools/PrintADCTraces/PrintADCTraces.h b/UserTools/PrintADCTraces/PrintADCTraces.h new file mode 100644 index 000000000..b82890c1d --- /dev/null +++ b/UserTools/PrintADCTraces/PrintADCTraces.h @@ -0,0 +1,69 @@ +#ifndef PrintADCTraces_H +#define PrintADCTraces_H + +#include "Tool.h" +#include "TFile.h" +#include "TTree.h" +#include "TGraph.h" +#include "ADCPulse.h" +#include "Hit.h" + +/** + * \class PrintADCTraces + * + * \brief Tool to extract and store ADC traces in TGraphs + * + * $Author: S. Doran $ + * $Date: Apr 2025 $ + * Contact: doran@iastate.edu + */ +class PrintADCTraces: public Tool { + + + public: + + PrintADCTraces(); ///< Simple constructor + bool Initialise(std::string configfile,DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + + private: + + TFile* fOutFile = nullptr; // output root file + TTree* fTraceSummaryTree = nullptr; // summary TTree in root file + int fchan; // branches in summary TTree + float fhitT, fhitPE; + + int totalGraphs = 0; // keep track how many TGraphs were written + std::map graphsPerChannel; + + float fhitTmin = 0; // config parameters + float fhitTmax = 0; + float fhitPEmin = 0; + float fhitPEmax = 0; + int fMaxTraces = 0; + int fMaxTracesPerChan = 0; + std::string filename; + + bool gotTmin = false; + bool gotTmax = false; + bool gotPEmin = false; + bool gotPEmax = false; + + // maps to Store objects + std::map>> fRecoADCData; + std::map fChannelKeyToSPEMap; + + int verbosity; + int v_error=0; + int v_warning=1; + int v_message=2; + int v_debug=3; + std::string logmessage; +}; + + +#endif + + + diff --git a/UserTools/PrintADCTraces/README.md b/UserTools/PrintADCTraces/README.md new file mode 100644 index 000000000..e89005b61 --- /dev/null +++ b/UserTools/PrintADCTraces/README.md @@ -0,0 +1,59 @@ +# PrintADCTraces + +`PrintADCTraces` will read the ADC traces in "RecoADCData", and output the pulses to a root file. It will also filter traces/hits within some range of charges or times provided by the user. + +## Output rootfile + +`PrintADCTraces` produces a root file containing directories for each PMT channel - within each channel will be TGraphs for each ADC trace: + +``` +// ROOT file: +// ├── chankey/ # directory for each PMT channel +// ├── 332/ +// │ ├── wf1 TGraph # for each pulse, a TGraph +// │ └── wf2 TGraph +// ├── 463/ +// │ ├── wf1 TGraph +// │ └── ... +// └── TraceSummary TTree # metadata +// ├── chan # all pulse channel ids +// ├── hitT # all pulse hit times [ns] +// └── hitPE # all pulse hit charges [pe] +``` + +where the TGraph name is given by: ```____``` + + +## Configuration +``` +# PrintADCTraces Config File + +verbosity 0 + +hitPE_min 0.5 # minimum hit charge [pe] to include in the root file +hitPE_max 1.5 # maximum hit charge [pe] to include in the root file + # omitting both of these will not impose a charge selection + +hitT_min 0 # minimum hit time [ns] to include in the root file +hitT_max 2000 # maximum hit time [ns] to include in the root file + # omitting both of these will not impose a time selection + +MaxTraces 10000 # maximum number of traces to include in the root file (default is 10,000 if not set by user) + # if set to '0', no limit will be imposed + +MaxTracesPerChannel 100 # maximum number of traces per channel to include in the root file + # if set to '0' or left undefined, it will not impose a limit + +OutputFilename ADCTraces.root # name of the output root file +``` + +## Example toolchain +``` +LoadANNIEEvent +LoadGeometry +PrintADCTraces +``` + +## Additional information +- ADC traces will be in ADC (y) vs time [ns] (x). All pulse times will be relative (and zeroed) to the start time of the pulse. All pulse amplitudes (y) are baseline-subtracted. This way its easier to compare. You can cross reference the pulse features with the title (which contains the charge and time of the pulse) to determine more information. +- This tool is similar to `PrintADCData`, but instead of printing out all raw PMT waveforms, it only prints out the found pulse traces (and provides more identifying / filtering information based on charge / time). diff --git a/UserTools/Unity.h b/UserTools/Unity.h index af90ecca3..454e3d884 100644 --- a/UserTools/Unity.h +++ b/UserTools/Unity.h @@ -194,3 +194,4 @@ #include "FitRWMWaveform.h" #include "LAPPDLoadTXT.h" #include "LAPPDBSCharging.h" +#include "PrintADCTraces.h" diff --git a/configfiles/PrintADCTraces/LoadANNIEEventConfig b/configfiles/PrintADCTraces/LoadANNIEEventConfig new file mode 100644 index 000000000..284622ea2 --- /dev/null +++ b/configfiles/PrintADCTraces/LoadANNIEEventConfig @@ -0,0 +1,4 @@ +verbose 1 +FileForListOfInputs ./configfiles/PrintADCTraces/my_inputs.txt +EventOffset 0 +GlobalEvNr 1 diff --git a/configfiles/PrintADCTraces/PrintADCTracesConfig b/configfiles/PrintADCTraces/PrintADCTracesConfig new file mode 100644 index 000000000..804a380df --- /dev/null +++ b/configfiles/PrintADCTraces/PrintADCTracesConfig @@ -0,0 +1,17 @@ +verbosity 0 + +hitPE_min 0.5 # minimum hit charge [pe] to include in the root file +hitPE_max 1.5 # maximum hit charge [pe] to include in the root file + # omitting both of these will not impose a charge selection + +hitT_min 0 # minimum hit time [ns] to include in the root file +hitT_max 2000 # maximum hit time [ns] to include in the root file + # omitting both of these will not impose a time selection + +MaxTraces 10000 # maximum number of traces to include in the root file (default is 10,000 if not set by user) + # if set to '0', no limit will be imposed + +MaxTracesPerChannel 100 # maximum number of traces per channel to include in the root file + # if set to '0' or left undefined, it will not impose a limit + +OutputFilename ADCTraces.root # name of the output root file \ No newline at end of file diff --git a/configfiles/PrintADCTraces/ToolChainConfig b/configfiles/PrintADCTraces/ToolChainConfig new file mode 100644 index 000000000..bfe534b1c --- /dev/null +++ b/configfiles/PrintADCTraces/ToolChainConfig @@ -0,0 +1,23 @@ +#ToolChain dynamic setup file + +##### Runtime Paramiters ##### +verbose 1 +error_level 0 # 0= do not exit, 1= exit on unhandeled errors only, 2= exit on unhandeled errors and handeled errors +attempt_recover 1 + +###### Logging ##### +log_mode Interactive # Interactive=cout , Remote= remote logging system "serservice_name Remote_Logging" , Local = local file log; +log_local_path ./log +log_service LogStore + +###### Service discovery ##### +service_publish_sec -1 +service_kick_sec -1 + +##### Tools To Add ##### +Tools_File ./configfiles/PrintADCTraces/ToolsConfig + +##### Run Type ##### +Inline -1 +Interactive 0 + diff --git a/configfiles/PrintADCTraces/ToolsConfig b/configfiles/PrintADCTraces/ToolsConfig new file mode 100644 index 000000000..c9fd4022c --- /dev/null +++ b/configfiles/PrintADCTraces/ToolsConfig @@ -0,0 +1,4 @@ +LoadANNIEEvent LoadANNIEEvent ./configfiles/PrintADCTraces/LoadANNIEEventConfig +LoadGeometry LoadGeometry ./configfiles/LoadGeometry/LoadGeometryConfig +#ClusterFinder ClusterFinder ./configfiles/PrintADCTraces/ClusterFinderConfig +PrintADCTraces PrintADCTraces ./configfiles/PrintADCTraces/PrintADCTracesConfig diff --git a/configfiles/PrintADCTraces/create_my_inputs.sh b/configfiles/PrintADCTraces/create_my_inputs.sh new file mode 100644 index 000000000..3e200e3c3 --- /dev/null +++ b/configfiles/PrintADCTraces/create_my_inputs.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +if [[ -z "$1" ]]; then + echo "" + echo "##############################" + echo "Error: No run number provided." + echo "Usage: $0 " + echo "" + exit 1 +fi + +run=$1 + +output_file="my_inputs.txt" +processed_dir="/pnfs/annie/persistent/processed/processingData_EBV2/processed_EBV2/R${run}/" + +find "$processed_dir" -type f -name "Processed*" | sort -t'/' -k2V > "$output_file" + +echo "done" diff --git a/configfiles/PrintADCTraces/my_inputs.txt b/configfiles/PrintADCTraces/my_inputs.txt new file mode 100644 index 000000000..c63be866a --- /dev/null +++ b/configfiles/PrintADCTraces/my_inputs.txt @@ -0,0 +1 @@ +/pnfs/annie/persistent/processed/processed_EBV2_LAPPDFiltered/AnalysisFile/FilteredLAPPD_BeamSelection_Pedestal2022 From 7de10e821d5a05da1cc69d43748234aab148b23c Mon Sep 17 00:00:00 2001 From: Steven Doran Date: Thu, 17 Apr 2025 15:04:08 -0500 Subject: [PATCH 145/163] Add README to PrintADCTraces toolchain --- configfiles/PrintADCTraces/README.md | 52 ++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 configfiles/PrintADCTraces/README.md diff --git a/configfiles/PrintADCTraces/README.md b/configfiles/PrintADCTraces/README.md new file mode 100644 index 000000000..32f1725c8 --- /dev/null +++ b/configfiles/PrintADCTraces/README.md @@ -0,0 +1,52 @@ +# PrintADCTraces + +`PrintADCTraces` toolchain will read the ADC traces in "RecoADCData", and output the pulses to a root file. It will also filter traces/hits within some range of charges or times provided by the user. + +## Output rootfile + +`PrintADCTraces` produces a root file containing directories for each PMT channel - within each channel will be TGraphs for each ADC trace: + +``` +// ROOT file: +// ├── chankey/ # directory for each PMT channel +// ├── 332/ +// │ ├── wf1 TGraph # for each pulse, a TGraph +// │ └── wf2 TGraph +// ├── 463/ +// │ ├── wf1 TGraph +// │ └── ... +// └── TraceSummary TTree # metadata +// ├── chan # all pulse channel ids +// ├── hitT # all pulse hit times [ns] +// └── hitPE # all pulse hit charges [pe] +``` + +where the TGraph name is given by: ```____``` + + +## Configuration +``` +# PrintADCTraces Config File + +verbosity 0 + +hitPE_min 0.5 # minimum hit charge [pe] to include in the root file +hitPE_max 1.5 # maximum hit charge [pe] to include in the root file + # omitting both of these will not impose a charge selection + +hitT_min 0 # minimum hit time [ns] to include in the root file +hitT_max 2000 # maximum hit time [ns] to include in the root file + # omitting both of these will not impose a time selection + +MaxTraces 10000 # maximum number of traces to include in the root file (default is 10,000 if not set by user) + # if set to '0', no limit will be imposed + +MaxTracesPerChannel 100 # maximum number of traces per channel to include in the root file + # if set to '0' or left undefined, it will not impose a limit + +OutputFilename ADCTraces.root # name of the output root file +``` + +## Additional information +- ADC traces will be in ADC (y) vs time [ns] (x). All pulse times will be relative (and zeroed) to the start time of the pulse. All pulse amplitudes (y) are baseline-subtracted. This way its easier to compare. You can cross reference the pulse features with the title (which contains the charge and time of the pulse) to determine more information. +- This tool is similar to the `PrintADCData` toolchain, but instead of printing out all raw PMT waveforms, it only prints out the found pulse traces (and provides more identifying / filtering information based on charge / time). From 9f4aa989e16171b3b841525f984027791fa8f2f1 Mon Sep 17 00:00:00 2001 From: Steven Doran Date: Thu, 17 Apr 2025 15:07:49 -0500 Subject: [PATCH 146/163] Final modifications for PrintADCTraces --- configfiles/PrintADCTraces/README.md | 1 + configfiles/PrintADCTraces/ToolsConfig | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/configfiles/PrintADCTraces/README.md b/configfiles/PrintADCTraces/README.md index 32f1725c8..e9185a0dc 100644 --- a/configfiles/PrintADCTraces/README.md +++ b/configfiles/PrintADCTraces/README.md @@ -50,3 +50,4 @@ OutputFilename ADCTraces.root # name of the output root file ## Additional information - ADC traces will be in ADC (y) vs time [ns] (x). All pulse times will be relative (and zeroed) to the start time of the pulse. All pulse amplitudes (y) are baseline-subtracted. This way its easier to compare. You can cross reference the pulse features with the title (which contains the charge and time of the pulse) to determine more information. - This tool is similar to the `PrintADCData` toolchain, but instead of printing out all raw PMT waveforms, it only prints out the found pulse traces (and provides more identifying / filtering information based on charge / time). +- `create_my_inputs.sh` will populate the my_inputs.txt file with all ProcessedData from a given run. Adjust the internal paths accordingly. Usage: `sh create_my_inputs.sh ` diff --git a/configfiles/PrintADCTraces/ToolsConfig b/configfiles/PrintADCTraces/ToolsConfig index c9fd4022c..38ac2af03 100644 --- a/configfiles/PrintADCTraces/ToolsConfig +++ b/configfiles/PrintADCTraces/ToolsConfig @@ -1,4 +1,3 @@ LoadANNIEEvent LoadANNIEEvent ./configfiles/PrintADCTraces/LoadANNIEEventConfig LoadGeometry LoadGeometry ./configfiles/LoadGeometry/LoadGeometryConfig -#ClusterFinder ClusterFinder ./configfiles/PrintADCTraces/ClusterFinderConfig PrintADCTraces PrintADCTraces ./configfiles/PrintADCTraces/PrintADCTracesConfig From 03dba624c48baa35eb5a7c650e095c6fe4caadd9 Mon Sep 17 00:00:00 2001 From: Steven Doran Date: Tue, 22 Apr 2025 13:29:33 -0500 Subject: [PATCH 147/163] EventBuilderV2_LED toolchain --- .../EventBuilderV2_LED/EBLoadRawConfig | 10 +++++++ configfiles/EventBuilderV2_LED/EBPMTConfig | 4 +++ configfiles/EventBuilderV2_LED/EBSaverConfig | 10 +++++++ .../EventBuilderV2_LED/EBTriggerGrouperConfig | 28 +++++++++++++++++++ .../EventBuilderV2_LED/PMTDataDecoderConfig | 5 ++++ .../PhaseIIADCCalibratorConfig | 15 ++++++++++ .../PhaseIIADCHitFinderConfig | 10 +++++++ .../EventBuilderV2_LED/SaveConfigInfoConfig | 3 ++ .../EventBuilderV2_LED/ToolChainConfig | 23 +++++++++++++++ configfiles/EventBuilderV2_LED/ToolsConfig | 12 ++++++++ .../TriggerDataDecoderConfig | 3 ++ configfiles/EventBuilderV2_LED/my_files.txt | 3 ++ 12 files changed, 126 insertions(+) create mode 100644 configfiles/EventBuilderV2_LED/EBLoadRawConfig create mode 100644 configfiles/EventBuilderV2_LED/EBPMTConfig create mode 100644 configfiles/EventBuilderV2_LED/EBSaverConfig create mode 100644 configfiles/EventBuilderV2_LED/EBTriggerGrouperConfig create mode 100644 configfiles/EventBuilderV2_LED/PMTDataDecoderConfig create mode 100644 configfiles/EventBuilderV2_LED/PhaseIIADCCalibratorConfig create mode 100644 configfiles/EventBuilderV2_LED/PhaseIIADCHitFinderConfig create mode 100644 configfiles/EventBuilderV2_LED/SaveConfigInfoConfig create mode 100644 configfiles/EventBuilderV2_LED/ToolChainConfig create mode 100644 configfiles/EventBuilderV2_LED/ToolsConfig create mode 100644 configfiles/EventBuilderV2_LED/TriggerDataDecoderConfig create mode 100644 configfiles/EventBuilderV2_LED/my_files.txt diff --git a/configfiles/EventBuilderV2_LED/EBLoadRawConfig b/configfiles/EventBuilderV2_LED/EBLoadRawConfig new file mode 100644 index 000000000..31ddd80ea --- /dev/null +++ b/configfiles/EventBuilderV2_LED/EBLoadRawConfig @@ -0,0 +1,10 @@ +verbosityEBLoadRaw 2 +ReadTriggerOverlap 1 + +InputFile ./configfiles/EventBuilderV2_LED/my_files.txt + +LoadPMT 1 +LoadMRD 0 +LoadCTC 1 +LoadLAPPD 0 + diff --git a/configfiles/EventBuilderV2_LED/EBPMTConfig b/configfiles/EventBuilderV2_LED/EBPMTConfig new file mode 100644 index 000000000..57bb72693 --- /dev/null +++ b/configfiles/EventBuilderV2_LED/EBPMTConfig @@ -0,0 +1,4 @@ +verbosityEBPMT 0 +matchTargetTrigger 46 +matchTolerance_ns 1000 +matchToAllTriggers 1 diff --git a/configfiles/EventBuilderV2_LED/EBSaverConfig b/configfiles/EventBuilderV2_LED/EBSaverConfig new file mode 100644 index 000000000..d3e1e75c7 --- /dev/null +++ b/configfiles/EventBuilderV2_LED/EBSaverConfig @@ -0,0 +1,10 @@ +verbosityEBSaver 1 + +savePMT 1 +saveMRD 0 +saveCTC 1 +saveLAPPD 0 +saveRunInfo 1 +saveBeamInfo 0 + +beamInfoFileName beamfetcher_tree.root diff --git a/configfiles/EventBuilderV2_LED/EBTriggerGrouperConfig b/configfiles/EventBuilderV2_LED/EBTriggerGrouperConfig new file mode 100644 index 000000000..b00af8388 --- /dev/null +++ b/configfiles/EventBuilderV2_LED/EBTriggerGrouperConfig @@ -0,0 +1,28 @@ +verbosityEBTG 0 +GroupMode beam +GroupTolerance 3000000 +GroupTrigWord 14 //undelayed beam + +groupBeam 0 +BeamTolerance 25000000 + +groupCosmic 0 +CosmicTriggerMain 36 + +groupLaser 0 +LaserTolerance 10000 + +groupLED 0 +#LEDTriggerMain 31 +#LEDTolerance 10000 + +groupAmBe 1 +AmBeTolerance 10000 # 10us for testing +AmBeTriggerMain 11 + +groupPPS 0 + +groupNuMI 0 + +maxNumAllowedInBuffer 20000 + diff --git a/configfiles/EventBuilderV2_LED/PMTDataDecoderConfig b/configfiles/EventBuilderV2_LED/PMTDataDecoderConfig new file mode 100644 index 000000000..cca7bb6b5 --- /dev/null +++ b/configfiles/EventBuilderV2_LED/PMTDataDecoderConfig @@ -0,0 +1,5 @@ +verbosity 1 +ADCCountsToBuildWaves 0 +Mode Offline +OffsetVME03 0 +OffsetVME01 0 diff --git a/configfiles/EventBuilderV2_LED/PhaseIIADCCalibratorConfig b/configfiles/EventBuilderV2_LED/PhaseIIADCCalibratorConfig new file mode 100644 index 000000000..158dc6ed1 --- /dev/null +++ b/configfiles/EventBuilderV2_LED/PhaseIIADCCalibratorConfig @@ -0,0 +1,15 @@ +# PhaseIIADCCalibrator config file + +verbosity 0 + +BaselineEstimationType ze3ra_multi +NumBaselineSamples 15 +NumSubWaveforms 10 + +SamplesPerBaselineEstimate 2000 +BaselineUncertaintyTolerance 2 +PCritical 0.01 +MakeCalLEDWaveforms 0 + +EventBuilding 1 +ExecutesPerBuild 10 diff --git a/configfiles/EventBuilderV2_LED/PhaseIIADCHitFinderConfig b/configfiles/EventBuilderV2_LED/PhaseIIADCHitFinderConfig new file mode 100644 index 000000000..991f5d222 --- /dev/null +++ b/configfiles/EventBuilderV2_LED/PhaseIIADCHitFinderConfig @@ -0,0 +1,10 @@ +verbosity 0 + +UseLEDWaveforms 0 + +PulseFindingApproach threshold +PulseWindowType Fixed_2023_Gains +DefaultADCThreshold 7 +DefaultThresholdType relative + +EventBuilding 1 diff --git a/configfiles/EventBuilderV2_LED/SaveConfigInfoConfig b/configfiles/EventBuilderV2_LED/SaveConfigInfoConfig new file mode 100644 index 000000000..569dcf758 --- /dev/null +++ b/configfiles/EventBuilderV2_LED/SaveConfigInfoConfig @@ -0,0 +1,3 @@ +verbosity 5 +OutFileName config_info.txt +FullDepth 0 diff --git a/configfiles/EventBuilderV2_LED/ToolChainConfig b/configfiles/EventBuilderV2_LED/ToolChainConfig new file mode 100644 index 000000000..b6cc94954 --- /dev/null +++ b/configfiles/EventBuilderV2_LED/ToolChainConfig @@ -0,0 +1,23 @@ +#ToolChain dynamic setup file + +##### Runtime Paramiters ##### +verbose 1 +error_level 0 # 0= do not exit, 1= exit on unhandeled errors only, 2= exit on unhandeled errors and handeled errors +attempt_recover 1 + +###### Logging ##### +log_mode Interactive # Interactive=cout , Remote= remote logging system "serservice_name Remote_Logging" , Local = local file log; +log_local_path ./log +log_service LogStore + +###### Service discovery ##### +service_publish_sec -1 +service_kick_sec -1 + +##### Tools To Add ##### +Tools_File ./configfiles/EventBuilderV2_LED/ToolsConfig + +##### Run Type ##### +Inline -1 +Interactive 0 + diff --git a/configfiles/EventBuilderV2_LED/ToolsConfig b/configfiles/EventBuilderV2_LED/ToolsConfig new file mode 100644 index 000000000..6fd615c39 --- /dev/null +++ b/configfiles/EventBuilderV2_LED/ToolsConfig @@ -0,0 +1,12 @@ +LoadGeometry LoadGeometry ./configfiles/LoadGeometry/LoadGeometryConfig +EBLoadRaw EBLoadRaw ./configfiles/EventBuilderV2_LED/EBLoadRawConfig +PMTDataDecoder PMTDataDecoder ./configfiles/EventBuilderV2_LED/PMTDataDecoderConfig +TriggerDataDecoder TriggerDataDecoder ./configfiles/EventBuilderV2_LED/TriggerDataDecoderConfig +PhaseIIADCCalibrator PhaseIIADCCalibrator ./configfiles/EventBuilderV2_LED/PhaseIIADCCalibratorConfig +PhaseIIADCHitFinder PhaseIIADCHitFinder ./configfiles/EventBuilderV2_LED/PhaseIIADCHitFinderConfig +EBTriggerGrouper EBTriggerGrouper ./configfiles/EventBuilderV2_LED/EBTriggerGrouperConfig +EBPMT EBPMT ./configfiles/EventBuilderV2_LED/EBPMTConfig +SaveConfigInfo SaveConfigInfo ./configfiles/EventBuilderV2_LED/SaveConfigInfoConfig +EBSaver EBSaver ./configfiles/EventBuilderV2_LED/EBSaverConfig + + diff --git a/configfiles/EventBuilderV2_LED/TriggerDataDecoderConfig b/configfiles/EventBuilderV2_LED/TriggerDataDecoderConfig new file mode 100644 index 000000000..a8ef6641f --- /dev/null +++ b/configfiles/EventBuilderV2_LED/TriggerDataDecoderConfig @@ -0,0 +1,3 @@ +verbosity 0 +StoreTrigOverlap 0 +ReadTrigOverlap 0 diff --git a/configfiles/EventBuilderV2_LED/my_files.txt b/configfiles/EventBuilderV2_LED/my_files.txt new file mode 100644 index 000000000..7697d0d84 --- /dev/null +++ b/configfiles/EventBuilderV2_LED/my_files.txt @@ -0,0 +1,3 @@ +/pnfs/annie/persistent/raw/raw/4499/RAWDataR4499S0p0 +/pnfs/annie/persistent/raw/raw/4499/RAWDataR4499S0p1 +/pnfs/annie/persistent/raw/raw/4499/RAWDataR4499S0p2 From 3950027d6d5b31d9c8d4ef39326427f7dc17d6f6 Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Thu, 24 Apr 2025 14:38:32 -0500 Subject: [PATCH 148/163] Edit LAPPD filter config for beam cluster jobs --- .../LAPPDProcessedFilter/ProcessedLAPPDFilterConfig | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig b/configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig index b40c3dbf6..0598cb709 100644 --- a/configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig +++ b/configfiles/LAPPDProcessedFilter/ProcessedLAPPDFilterConfig @@ -1,11 +1,12 @@ FilterVerbosity 0 -saveAllLAPPDEvents 0 +saveAllLAPPDEvents 1 savePMTClusterEvents 0 -#filterType MRDtrack +filterType MRDtrack + +#filterType BeamSelection -filterType BeamSelection RequireNoVeto 1 RequireCherenkovCover 1 From 67c208966d588a3870de357183be4ab8e08d65cc Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Mon, 28 Apr 2025 15:55:44 -0500 Subject: [PATCH 149/163] Add LAPPD follow charge variables For pulse found in LAPPDThresReco, integral a few bins after the end of the pulse as a follow charge, to show possible affect from SANDI + crosstalk --- DataModel/LAPPDPulse.h | 8 +++++ .../ANNIEEventTreeMaker.cpp | 34 +++++++++++++++++- .../ANNIEEventTreeMaker/ANNIEEventTreeMaker.h | 10 +++++- UserTools/LAPPDThresReco/LAPPDThresReco.cpp | 36 +++++++++++++++++-- UserTools/LAPPDThresReco/LAPPDThresReco.h | 4 +++ 5 files changed, 88 insertions(+), 4 deletions(-) diff --git a/DataModel/LAPPDPulse.h b/DataModel/LAPPDPulse.h index 8aff68195..497ae30cb 100755 --- a/DataModel/LAPPDPulse.h +++ b/DataModel/LAPPDPulse.h @@ -28,6 +28,10 @@ class LAPPDPulse : public Hit{ inline double GetHalfEndTime(){return halfEndTime;} inline void SetBaseline(double base){baseline=base;} inline double GetBaseline(){return baseline;} + inline void SetPulseFollowTime(double pulseFollow){pulseFollowTime=pulseFollow;} + inline double GetPulseFollowTime(){return pulseFollowTime;} + inline void SetPulseFollowCharge(double pulseFollow){pulseFollowCharge=pulseFollow;} + inline double GetPulseFollowCharge(){return pulseFollowCharge;} bool Print() { cout<<"TubeId : "<Branch("LAPPD_PulseWidth", &fPulseWidth); fANNIETree->Branch("LAPPD_PulseSide", &fPulseSide); fANNIETree->Branch("LAPPD_PulseStripNum", &fPulseStripNum); + fANNIETree->Branch("LAPPD_PulseBaseline", &fPulseBaseline); + fANNIETree->Branch("LAPPD_PulseFollowTime", &fPulseFollowTime); + fANNIETree->Branch("LAPPD_PulseFollowCharge", &fPulseFollowCharge); // fANNIETree->Branch("LAPPDHitTimeStampUL", &fLAPPDHitTimeStampUL, "LAPPDHitTimeStampUL/l"); // fANNIETree->Branch("LAPPDHitBeamgateUL", &fLAPPDHitBeamgateUL, "LAPPDHitBeamgateUL/l"); @@ -263,6 +266,12 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) fANNIETree->Branch("LAPPDHitP2HalfEndTime", &fLAPPDHitP2HalfEndTime); fANNIETree->Branch("LAPPDHitP1Charge", &fLAPPDHitP1Charge); fANNIETree->Branch("LAPPDHitP2Charge", &fLAPPDHitP2Charge); + fANNIETree->Branch("LAPPDHitP1Baseline", &fLAPPDHitP1Baseline); + fANNIETree->Branch("LAPPDHitP2Baseline", &fLAPPDHitP2Baseline); + fANNIETree->Branch("LAPPDHitP1FollowTime", &fLAPPDHitP1FollowTime); + fANNIETree->Branch("LAPPDHitP2FollowTime", &fLAPPDHitP2FollowTime); + fANNIETree->Branch("LAPPDHitP1FollowCharge", &fLAPPDHitP1FollowCharge); + fANNIETree->Branch("LAPPDHitP2FollowCharge", &fLAPPDHitP2FollowCharge); /* fANNIETree->Branch("LAPPDWaveformChankey", &LAPPDWaveformChankey, "LAPPDWaveformChankey/I"); @@ -730,7 +739,9 @@ void ANNIEEventTreeMaker::ResetVariables() fPulseWidth.clear(); fPulseSide.clear(); fPulseStripNum.clear(); - fChannelBaseline.clear(); + fPulseBaseline.clear(); + fPulseFollowTime.clear(); + fPulseFollowCharge.clear(); fLAPPDHitTimeStampUL.clear(); fLAPPDHitBeamgateUL.clear(); @@ -755,6 +766,12 @@ void ANNIEEventTreeMaker::ResetVariables() fLAPPDHitP2HalfEndTime.clear(); fLAPPDHitP1Charge.clear(); fLAPPDHitP2Charge.clear(); + fLAPPDHitP1Baseline.clear(); + fLAPPDHitP2Baseline.clear(); + fLAPPDHitP1FollowTime.clear(); + fLAPPDHitP2FollowTime.clear(); + fLAPPDHitP1FollowCharge.clear(); + fLAPPDHitP2FollowCharge.clear(); LAPPDWaveformChankey.clear(); waveformMaxValue.clear(); @@ -1436,6 +1453,9 @@ void ANNIEEventTreeMaker::FillLAPPDPulse() fPulseStart.push_back(thisPulse.GetLowRange()); fPulseEnd.push_back(thisPulse.GetHiRange()); fPulseWidth.push_back(thisPulse.GetHiRange() - thisPulse.GetLowRange()); + fPulseBaseline.push_back(thisPulse.GetBaseline()); + fPulseFollowTime.push_back(thisPulse.GetPulseFollowTime()); + fPulseFollowCharge.push_back(thisPulse.GetPulseFollowCharge()); } for (int i = 0; i < pulse1.size(); i++) { @@ -1451,6 +1471,9 @@ void ANNIEEventTreeMaker::FillLAPPDPulse() fPulseStart.push_back(thisPulse.GetLowRange()); fPulseEnd.push_back(thisPulse.GetHiRange()); fPulseWidth.push_back(thisPulse.GetHiRange() - thisPulse.GetLowRange()); + fPulseBaseline.push_back(thisPulse.GetBaseline()); + fPulseFollowTime.push_back(thisPulse.GetPulseFollowTime()); + fPulseFollowCharge.push_back(thisPulse.GetPulseFollowCharge()); } } } @@ -1507,6 +1530,15 @@ void ANNIEEventTreeMaker::FillLAPPDHit() fLAPPDHitP1Charge.push_back(p1.GetCharge()); fLAPPDHitP2Charge.push_back(p2.GetCharge()); + + fLAPPDHitP1Baseline.push_back(p1.GetBaseline()); + fLAPPDHitP2Baseline.push_back(p2.GetBaseline()); + + fLAPPDHitP1FollowTime.push_back(p1.GetPulseFollowTime()); + fLAPPDHitP2FollowTime.push_back(p2.GetPulseFollowTime()); + + fLAPPDHitP1FollowCharge.push_back(p1.GetPulseFollowCharge()); + fLAPPDHitP2FollowCharge.push_back(p2.GetPulseFollowCharge()); } } } diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h index 1dcd13091..ce8efa5ef 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.h @@ -250,7 +250,9 @@ class ANNIEEventTreeMaker : public Tool vector fPulseWidth; vector fPulseSide; vector fPulseStripNum; - std::map fChannelBaseline; + vector fPulseBaseline; + vector fPulseFollowTime; + vector fPulseFollowCharge; vector fLAPPDHitTimeStampUL; vector fLAPPDHitBeamgateUL; @@ -275,6 +277,12 @@ class ANNIEEventTreeMaker : public Tool vector fLAPPDHitP2HalfEndTime; vector fLAPPDHitP1Charge; vector fLAPPDHitP2Charge; + vector fLAPPDHitP1Baseline; + vector fLAPPDHitP2Baseline; + vector fLAPPDHitP1FollowTime; + vector fLAPPDHitP2FollowTime; + vector fLAPPDHitP1FollowCharge; + vector fLAPPDHitP2FollowCharge; // waveform vector LAPPDWaveformChankey; diff --git a/UserTools/LAPPDThresReco/LAPPDThresReco.cpp b/UserTools/LAPPDThresReco/LAPPDThresReco.cpp index c8cc454e7..7feceb1c1 100644 --- a/UserTools/LAPPDThresReco/LAPPDThresReco.cpp +++ b/UserTools/LAPPDThresReco/LAPPDThresReco.cpp @@ -36,6 +36,12 @@ bool LAPPDThresReco::Initialise(std::string configfile, DataModel &data) m_variables.Get("useRange", useRange); loadPrintMRDinfo = true; // print MRD track information m_variables.Get("loadPrintMRDinfo", loadPrintMRDinfo); + pulseFollowTimeStandard = 20; // 20 bins (2 ns) integral after each pulse + m_variables.Get("pulseFollowTimeStandard", pulseFollowTimeStandard); + baselineStart = 50; // start time for independent baseline calculation, 5ns + m_variables.Get("baselineStart", baselineStart); + baselineEnd = 100; + m_variables.Get("baselineEnd", baselineEnd); // Control variables in this tool, initialized in this tool eventNumber = 0; LoadLAPPDMapInfo = false; @@ -229,6 +235,7 @@ void LAPPDThresReco::CleanDataObjects() LAPPD_ID = -9999; LAPPDana = false; + pulseFollowTime = pulseFollowTimeStandard; } void LAPPDThresReco::FillLAPPDPulse() @@ -371,6 +378,13 @@ vector LAPPDThresReco::FindPulses(vector wave, int LAPPD_ID, vector binNumbers; vector amplitudes; + double baselineGet = 0; + for (int i = baselineStart; i < baselineEnd; i++) + { + baselineGet += wave.at(i); + } + baselineGet = baselineGet / (baselineEnd - baselineStart); + for (int i = 1; i < wave.size(); i++) { currentSig = wave.at(i); @@ -484,6 +498,20 @@ vector LAPPDThresReco::FindPulses(vector wave, int LAPPD_ID, } } + int startFollowTime = i; + int stopFollowTime = i + static_cast(pulseFollowTime); + if (stopFollowTime > 256) + { + stopFollowTime = 256; + pulseFollowTime = 256 - i; + } + + double integralFollowCharge = 0; + for (int j = startFollowTime; j < stopFollowTime; j++) + { + integralFollowCharge += wave.at(j); + } + if (LAPPDThresRecoVerbosity > 1) cout << "inserting pulse on LAPPD ID =" << LAPPD_ID << " at time: " << peakBin * (25. / 256.) << "(" << peakBinGaus << ") with peakAmp: " << peakAmp << " from " << pulseStart << " to " << pulseStart + pulseSize << endl; if (useMaxTime) @@ -491,7 +519,9 @@ vector LAPPDThresReco::FindPulses(vector wave, int LAPPD_ID, LAPPDPulse thisPulse(LAPPD_ID, channel, peakBin * (25. / 256.), Q, peakAmp, pulseStart, pulseStart + pulseSize); thisPulse.SetHalfHeightTime(halfPeakBin * (25. / 256.) + halfPeak_ps * 0.001 * 25 / 25.6); thisPulse.SetHalfEndTime(halfEndBin * (25. / 256.) + halfEnd_ps * 0.001 * 25 / 25.6); - thisPulse.SetBaseline(0); + thisPulse.SetBaseline(baselineGet); + thisPulse.SetPulseFollowTime(pulseFollowTime); + thisPulse.SetPulseFollowCharge(integralFollowCharge); pulses.push_back(thisPulse); } else @@ -499,7 +529,9 @@ vector LAPPDThresReco::FindPulses(vector wave, int LAPPD_ID, LAPPDPulse thisPulse(LAPPD_ID, channel, peakBinGaus * (25. / 256.), Q, peakAmp, pulseStart, pulseStart + pulseSize); thisPulse.SetHalfHeightTime(halfPeakBin * (25. / 256.) + halfPeak_ps * 0.001 * 25 / 25.6); thisPulse.SetHalfEndTime(halfEndBin * (25. / 256.) + halfEnd_ps * 0.001 * 25 / 25.6); - thisPulse.SetBaseline(0); + thisPulse.SetBaseline(baselineGet); + thisPulse.SetPulseFollowTime(pulseFollowTime); + thisPulse.SetPulseFollowCharge(integralFollowCharge); pulses.push_back(thisPulse); } // tube ID: LAPPD_ID diff --git a/UserTools/LAPPDThresReco/LAPPDThresReco.h b/UserTools/LAPPDThresReco/LAPPDThresReco.h index 737be8105..3959302df 100644 --- a/UserTools/LAPPDThresReco/LAPPDThresReco.h +++ b/UserTools/LAPPDThresReco/LAPPDThresReco.h @@ -59,8 +59,12 @@ class LAPPDThresReco : public Tool bool savePositionOnStrip; int useRange; //-1 averaged peak time, 0 low, 1 high bool loadPrintMRDinfo; + double pulseFollowTimeStandard; + int baselineStart; + int baselineEnd; // Variables that you need in the tool int eventNumber; + double pulseFollowTime; // LAPPD tool chain, control variables (Will be shared in multiple LAPPD tools to show the state of the tool chain in each loop) // Variables that you get from the config file From 9e1be5ce689def13615b0e3c162ede0a0389a5c8 Mon Sep 17 00:00:00 2001 From: Steven Doran <78985334+S81D@users.noreply.github.com> Date: Tue, 29 Apr 2025 10:38:25 -0500 Subject: [PATCH 150/163] Update EBTriggerGrouperConfig Bug fix for LED part 1 --- configfiles/EventBuilderV2_LED/EBTriggerGrouperConfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configfiles/EventBuilderV2_LED/EBTriggerGrouperConfig b/configfiles/EventBuilderV2_LED/EBTriggerGrouperConfig index b00af8388..46eb0bb9d 100644 --- a/configfiles/EventBuilderV2_LED/EBTriggerGrouperConfig +++ b/configfiles/EventBuilderV2_LED/EBTriggerGrouperConfig @@ -12,11 +12,11 @@ CosmicTriggerMain 36 groupLaser 0 LaserTolerance 10000 -groupLED 0 -#LEDTriggerMain 31 -#LEDTolerance 10000 +groupLED 1 +LEDTriggerMain 31 +LEDTolerance 10000 -groupAmBe 1 +groupAmBe 0 AmBeTolerance 10000 # 10us for testing AmBeTriggerMain 11 From 895fa6a1122c764a002c98d09f265820451eb61d Mon Sep 17 00:00:00 2001 From: fengyvoid Date: Tue, 29 Apr 2025 17:40:19 -0500 Subject: [PATCH 151/163] Add ring counting function for BC tool chain and BC-MC tool chain Put the model into RingCounting config folder, from /exp/annie/app/users/dschmid/RingCountingStore/models/ Modify configs for BeamClusterAnalysis and BeamClusterAnalysisMC Add branches in ANNIEEventTreeMaker Commented the verbose display in RingCounting.py Also set verbose for cout in DigitBuilder.cpp when loading data --- .../ANNIEEventTreeMaker.cpp | 20 +++ .../ANNIEEventTreeMaker/ANNIEEventTreeMaker.h | 5 + UserTools/DigitBuilder/DigitBuilder.cpp | 2 +- UserTools/RingCounting/RingCounting.py | 2 +- .../ANNIEEventTreeMakerConfig | 3 +- .../BeamClusterAnalysis/CNNImageConfig | 17 +++ .../ChannelSPEGains2023.csv | 122 ++++++++++++++++++ .../BeamClusterAnalysis/DigitBuilderConfig | 15 +++ .../BeamClusterAnalysis/RingCountingConfig | 25 ++++ configfiles/BeamClusterAnalysis/ToolsConfig | 6 + .../ANNIEEventTreeMakerConfig | 1 + .../BeamClusterAnalysisMC/CNNImageConfig | 15 +++ .../BeamClusterAnalysisMC/DigitBuilderConfig | 11 ++ .../LoadGenieEventConfig | 2 +- .../BeamClusterAnalysisMC/RingCountingConfig | 24 ++++ configfiles/BeamClusterAnalysisMC/ToolsConfig | 7 + .../BeamClusterAnalysisMC/my_inputs.txt | 40 ------ .../RC_model_v1_0_0.model/keras_metadata.pb | 38 ++++++ .../RC_model_v1_0_0.model/saved_model.pb | Bin 0 -> 482284 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12547884 bytes .../variables/variables.index | Bin 0 -> 5630 bytes 21 files changed, 311 insertions(+), 44 deletions(-) create mode 100644 configfiles/BeamClusterAnalysis/CNNImageConfig create mode 100644 configfiles/BeamClusterAnalysis/ChannelSPEGains2023.csv create mode 100644 configfiles/BeamClusterAnalysis/DigitBuilderConfig create mode 100644 configfiles/BeamClusterAnalysis/RingCountingConfig create mode 100644 configfiles/BeamClusterAnalysisMC/CNNImageConfig create mode 100644 configfiles/BeamClusterAnalysisMC/DigitBuilderConfig create mode 100644 configfiles/BeamClusterAnalysisMC/RingCountingConfig delete mode 100644 configfiles/BeamClusterAnalysisMC/my_inputs.txt create mode 100644 configfiles/RingCounting/RC_model_v1_0_0.model/keras_metadata.pb create mode 100644 configfiles/RingCounting/RC_model_v1_0_0.model/saved_model.pb create mode 100644 configfiles/RingCounting/RC_model_v1_0_0.model/variables/variables.data-00000-of-00001 create mode 100644 configfiles/RingCounting/RC_model_v1_0_0.model/variables/variables.index diff --git a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp index e6d9337e4..ef65e8603 100644 --- a/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp +++ b/UserTools/ANNIEEventTreeMaker/ANNIEEventTreeMaker.cpp @@ -45,6 +45,7 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) m_variables.Get("LAPPD_PPS_fill", LAPPD_PPS_fill); m_variables.Get("LAPPD_Waveform_fill", LAPPD_Waveform_fill); m_variables.Get("LAPPD_MC_fill", LAPPD_MC_fill); + m_variables.Get("RingCounting_fill", RingCounting_fill); std::string output_filename = "ANNIEEventTree.root"; m_variables.Get("OutputFile", output_filename); @@ -444,6 +445,13 @@ bool ANNIEEventTreeMaker::Initialise(std::string configfile, DataModel &data) fANNIETree->Branch("recoVtxFOM", &fRecoVtxFOM, "recoVtxFOM/D"); fANNIETree->Branch("recoStatus", &fRecoStatus, "recoStatus/I"); } + + // fill ring counting info + if (RingCounting_fill) + { + fANNIETree->Branch("RC_singleRingP", &fRC_singleRingP, "RC_singleRingP/D"); + fANNIETree->Branch("RC_multiRingP", &fRC_multiRingP, "RC_multiRingP/D"); + } // Reconstructed variables from each step in Muon Reco Analysis // Currently output when RecoDebug_fill = 1 in config @@ -585,6 +593,14 @@ bool ANNIEEventTreeMaker::Execute() got_reco = FillTankRecoInfo(); } + if (RingCounting_fill) + { + bool got_srFlag = m_data->Stores.at("RecoEvent")->Get("RingCountingSRPrediction", fRC_singleRingP); + bool got_mrFlag = m_data->Stores.at("RecoEvent")->Get("RingCountingMRPrediction", fRC_multiRingP); + if(ANNIEEventTreeMakerVerbosity>1) + cout<<"Printing ring counting: got_srFlag = "<size(); - std::cout <<"Clustersize of m_all_clusters: "<1) std::cout <<"Clustersize of m_all_clusters: "< check documentation +version 1_0_0 + +# Folder containing models +#model_path /exp/annie/app/users/dschmid/RingCountingStore/models/ +model_path ./configfiles/RingCounting/ + +# Masked PMTs (to 0) config -> check documentation +pmt_mask november_22 +# Output file +save_to RC_output.csv + diff --git a/configfiles/BeamClusterAnalysis/ToolsConfig b/configfiles/BeamClusterAnalysis/ToolsConfig index 9b7fee419..a4441e5bb 100644 --- a/configfiles/BeamClusterAnalysis/ToolsConfig +++ b/configfiles/BeamClusterAnalysis/ToolsConfig @@ -6,6 +6,9 @@ myClusterFinder ClusterFinder ./configfiles/BeamClusterAnalysis/ClusterFinderCon myClusterClassifiers ClusterClassifiers ./configfiles/BeamClusterAnalysis/ClusterClassifiersConfig myEventSelector EventSelector ./configfiles/BeamClusterAnalysis/EventSelectorConfig + +myDigitBuilder DigitBuilder ./configfiles/BeamClusterAnalysis/DigitBuilderConfig + LAPPDLoadStore LAPPDLoadStore configfiles/LAPPDProcessedAna/Configs LAPPDStoreReorder LAPPDStoreReorder configfiles/LAPPDProcessedAna/ConfigStoreReadIn LAPPDTimeAlignment LAPPDTimeAlignment configfiles/LAPPDProcessedAna/ConfigPreProcess @@ -15,4 +18,7 @@ LAPPDThresReco LAPPDThresReco configfiles/LAPPDProcessedAna/ConfigPlot FitRWMWaveform FitRWMWaveform ./configfiles/BeamClusterAnalysis/FitRWMWaveformConfig +myCNNImage CNNImage ./configfiles/BeamClusterAnalysis/CNNImageConfig +myRingCounting PythonScript configfiles/BeamClusterAnalysis/RingCountingConfig + ANNIEEventTreeMaker ANNIEEventTreeMaker ./configfiles/BeamClusterAnalysis/ANNIEEventTreeMakerConfig diff --git a/configfiles/BeamClusterAnalysisMC/ANNIEEventTreeMakerConfig b/configfiles/BeamClusterAnalysisMC/ANNIEEventTreeMakerConfig index 0be15bed6..3917232a3 100644 --- a/configfiles/BeamClusterAnalysisMC/ANNIEEventTreeMakerConfig +++ b/configfiles/BeamClusterAnalysisMC/ANNIEEventTreeMakerConfig @@ -10,6 +10,7 @@ TankCluster_fill 1 cluster_TankHitInfo_fill 1 TankReco_fill 0 +RingCounting_fill 1 TankClusterProcessing 1 MRDClusterProcessing 1 diff --git a/configfiles/BeamClusterAnalysisMC/CNNImageConfig b/configfiles/BeamClusterAnalysisMC/CNNImageConfig new file mode 100644 index 000000000..e6e997fa5 --- /dev/null +++ b/configfiles/BeamClusterAnalysisMC/CNNImageConfig @@ -0,0 +1,15 @@ +# CNNImage config file + +verbosity 1 +DataMode Normal #options: Normal / Charge-Weighted / TimeEvolution +SaveMode Static #options: Static / Geometric / PMT-wise +DimensionX 16 #choose something suitable (32/64/...) +DimensionY 10 #choose something suitable (32/64/...) +OutputFile cnnimage_electron_la_sE_1_94 +MCStaticMapping configfiles/CNNImage/mc_cnnimage_mapping.csv +DataStaticMapping configfiles/CNNImage/data_cnnimage_mapping.csv +DimensionLAPPD 5 #Size of the LAPPD pannal +IncludeTopBottom 1 +DetectorConf ANNIEp2v7 #specify the detector version used in simulation +useLAPPDs 0 +WriteToFile 0 diff --git a/configfiles/BeamClusterAnalysisMC/DigitBuilderConfig b/configfiles/BeamClusterAnalysisMC/DigitBuilderConfig new file mode 100644 index 000000000..ca0839c95 --- /dev/null +++ b/configfiles/BeamClusterAnalysisMC/DigitBuilderConfig @@ -0,0 +1,11 @@ +# DigitBuilder config file + +verbosity 0 +ParametricModel 1 +#Reading in MC files +IsMC 1 +# There are three configurations: "PMT_only", "LAPPD_only", "All" +PhotoDetectorConfiguration PMT_only +#File must be in /pnfs/ space when loading on Fermilab cluster +LAPPDIDFile ./configfiles/VertexReco/PhaseIIRecoTruth/LAPPDIDs.txt +DigitChargeThr 0 diff --git a/configfiles/BeamClusterAnalysisMC/LoadGenieEventConfig b/configfiles/BeamClusterAnalysisMC/LoadGenieEventConfig index 23799a691..83a66a9f3 100644 --- a/configfiles/BeamClusterAnalysisMC/LoadGenieEventConfig +++ b/configfiles/BeamClusterAnalysisMC/LoadGenieEventConfig @@ -22,4 +22,4 @@ ManualFileMatching 1 # 0 (false) - no manual matching, 1 (true) - us FileEvents 1000 # 1000 for James' WCSim files, 500 for Marcus' files # Number to offset the first loaded GENIE event (for usage without ManualFileMatching) - 0 by default -EventOffset 0 +EventOffset 8000 diff --git a/configfiles/BeamClusterAnalysisMC/RingCountingConfig b/configfiles/BeamClusterAnalysisMC/RingCountingConfig new file mode 100644 index 000000000..c7598a105 --- /dev/null +++ b/configfiles/BeamClusterAnalysisMC/RingCountingConfig @@ -0,0 +1,24 @@ +PythonScript RingCounting + +InitialiseFunction Initialise +ExecuteFunction Execute +FinaliseFunction Finalise + +verbose 1 + +# analysis specific settings +# +# Define file containing (multiple) filepath(s) to be loaded +load_from_file 0 +files_to_load configfiles/RingCounting/RC_files_to_load.txt +# Model version -> check documentation +version 1_0_0 +# Folder containing models +# model_path /exp/annie/app/users/dschmid/RingCountingStore/models/ +model_path ./configfiles/RingCounting/ + +# Masked PMTs (to 0) config -> check documentation +pmt_mask november_22 +# Output file +save_to RC_output.csv + diff --git a/configfiles/BeamClusterAnalysisMC/ToolsConfig b/configfiles/BeamClusterAnalysisMC/ToolsConfig index 6f40936a7..d6c7b96f4 100644 --- a/configfiles/BeamClusterAnalysisMC/ToolsConfig +++ b/configfiles/BeamClusterAnalysisMC/ToolsConfig @@ -4,10 +4,17 @@ myLoadWCSimLAPPD LoadWCSimLAPPD ./configfiles/BeamClusterAnalysisMC/LoadWCSimLAP myLoadGenieEvent LoadGenieEvent ./configfiles/BeamClusterAnalysisMC/LoadGenieEventConfig myMCParticleProperties MCParticleProperties ./configfiles/BeamClusterAnalysisMC/MCParticlePropertiesConfig myMCRecoEventLoader MCRecoEventLoader ./configfiles/BeamClusterAnalysisMC/MCRecoEventLoaderConfig + +myDigitBuilder DigitBuilder ./configfiles/BeamClusterAnalysisMC/DigitBuilderConfig + myTimeClustering TimeClustering configfiles/BeamClusterAnalysisMC/TimeClusteringConfig myFindMrdTracks FindMrdTracks configfiles/BeamClusterAnalysisMC/FindMrdTracksConfig myClusterFinder ClusterFinder ./configfiles/BeamClusterAnalysisMC/ClusterFinderConfig myClusterClassifiers ClusterClassifiers ./configfiles/BeamClusterAnalysisMC/ClusterClassifiersConfig myEventSelector EventSelector ./configfiles/BeamClusterAnalysisMC/EventSelectorConfig #myPhaseIITreeMaker PhaseIITreeMaker ./configfiles/BeamClusterAnalysisMC/PhaseIITreeMakerConfig + +myCNNImage CNNImage ./configfiles/BeamClusterAnalysisMC/CNNImageConfig +myRingCounting PythonScript configfiles/BeamClusterAnalysisMC/RingCountingConfig + myANNIEEventTreeMaker ANNIEEventTreeMaker ./configfiles/BeamClusterAnalysisMC/ANNIEEventTreeMakerConfig diff --git a/configfiles/BeamClusterAnalysisMC/my_inputs.txt b/configfiles/BeamClusterAnalysisMC/my_inputs.txt deleted file mode 100644 index 974bc6755..000000000 --- a/configfiles/BeamClusterAnalysisMC/my_inputs.txt +++ /dev/null @@ -1,40 +0,0 @@ -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p0 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p1 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p2 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p3 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p4 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p5 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p6 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p7 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p8 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p9 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p10 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p11 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p12 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p13 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p14 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p15 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p16 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p17 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p18 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p19 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p20 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p21 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p22 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p23 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p24 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p25 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p26 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p27 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p28 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p29 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p30 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p31 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p32 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p33 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p34 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p35 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p36 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p37 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p38 -/pnfs/annie/persistent/users/mnieslon/data/processed_hits_improved/R2630/ProcessedRawData_TankAndMRDAndCTC_R2630S0p39 diff --git a/configfiles/RingCounting/RC_model_v1_0_0.model/keras_metadata.pb b/configfiles/RingCounting/RC_model_v1_0_0.model/keras_metadata.pb new file mode 100644 index 000000000..39da4b4f8 --- /dev/null +++ b/configfiles/RingCounting/RC_model_v1_0_0.model/keras_metadata.pb @@ -0,0 +1,38 @@ + +¯Èroot"_tf_keras_network*ŒÈ{"name": "model_23", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "must_restore_from_config": false, "class_name": "Functional", "config": {"name": "model_23", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": {"class_name": "__tuple__", "items": [null, 10, 16, 1]}, "dtype": "float32", "sparse": false, "ragged": false, "name": "charge"}, "name": "charge", "inbound_nodes": []}, {"class_name": "Conv2D", "config": {"name": "conv2d_40", "trainable": true, "dtype": "float32", "filters": 64, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "same", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "conv2d_40", "inbound_nodes": [[["charge", 0, 0, {}]]]}, {"class_name": "Dropout", "config": {"name": "dropout_50", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}, "name": "dropout_50", "inbound_nodes": [[["conv2d_40", 0, 0, {}]]]}, {"class_name": "Activation", "config": {"name": "activation_40", "trainable": true, "dtype": "float32", "activation": {"class_name": "ReLU", "config": {"name": "re_lu_40", "trainable": true, "dtype": "float32", "max_value": null, "negative_slope": 0.0, "threshold": 0.0}}}, "name": "activation_40", "inbound_nodes": [[["dropout_50", 0, 0, {}]]]}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_30", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "name": "max_pooling2d_30", "inbound_nodes": [[["activation_40", 0, 0, {}]]]}, {"class_name": "Conv2D", "config": {"name": "conv2d_41", "trainable": true, "dtype": "float32", "filters": 128, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "same", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "conv2d_41", "inbound_nodes": [[["max_pooling2d_30", 0, 0, {}]]]}, {"class_name": "Dropout", "config": {"name": "dropout_51", "trainable": true, "dtype": "float32", "rate": 0.4, "noise_shape": null, "seed": null}, "name": "dropout_51", "inbound_nodes": [[["conv2d_41", 0, 0, {}]]]}, {"class_name": "BatchNormalization", "config": {"name": "batch_normalization_40", "trainable": true, "dtype": "float32", "axis": [3], "momentum": 0.99, "epsilon": 0.001, "center": true, "scale": true, "beta_initializer": {"class_name": "Zeros", "config": {}}, "gamma_initializer": {"class_name": "Ones", "config": {}}, "moving_mean_initializer": {"class_name": "Zeros", "config": {}}, "moving_variance_initializer": {"class_name": "Ones", "config": {}}, "beta_regularizer": null, "gamma_regularizer": null, "beta_constraint": null, "gamma_constraint": null}, "name": "batch_normalization_40", "inbound_nodes": [[["dropout_51", 0, 0, {}]]]}, {"class_name": "Activation", "config": {"name": "activation_41", "trainable": true, "dtype": "float32", "activation": {"class_name": "ReLU", "config": {"name": "re_lu_41", "trainable": true, "dtype": "float32", "max_value": null, "negative_slope": 0.0, "threshold": 0.0}}}, "name": "activation_41", "inbound_nodes": [[["batch_normalization_40", 0, 0, {}]]]}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_31", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "name": "max_pooling2d_31", "inbound_nodes": [[["activation_41", 0, 0, {}]]]}, {"class_name": "Conv2D", "config": {"name": "conv2d_42", "trainable": true, "dtype": "float32", "filters": 256, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "same", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "conv2d_42", "inbound_nodes": [[["max_pooling2d_31", 0, 0, {}]]]}, {"class_name": "Dropout", "config": {"name": "dropout_52", "trainable": true, "dtype": "float32", "rate": 0.4, "noise_shape": null, "seed": null}, "name": "dropout_52", "inbound_nodes": [[["conv2d_42", 0, 0, {}]]]}, {"class_name": "BatchNormalization", "config": {"name": "batch_normalization_41", "trainable": true, "dtype": "float32", "axis": [3], "momentum": 0.99, "epsilon": 0.001, "center": true, "scale": true, "beta_initializer": {"class_name": "Zeros", "config": {}}, "gamma_initializer": {"class_name": "Ones", "config": {}}, "moving_mean_initializer": {"class_name": "Zeros", "config": {}}, "moving_variance_initializer": {"class_name": "Ones", "config": {}}, "beta_regularizer": null, "gamma_regularizer": null, "beta_constraint": null, "gamma_constraint": null}, "name": "batch_normalization_41", "inbound_nodes": [[["dropout_52", 0, 0, {}]]]}, {"class_name": "Activation", "config": {"name": "activation_42", "trainable": true, "dtype": "float32", "activation": {"class_name": "ReLU", "config": {"name": "re_lu_42", "trainable": true, "dtype": "float32", "max_value": null, "negative_slope": 0.0, "threshold": 0.0}}}, "name": "activation_42", "inbound_nodes": [[["batch_normalization_41", 0, 0, {}]]]}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_32", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "name": "max_pooling2d_32", "inbound_nodes": [[["activation_42", 0, 0, {}]]]}, {"class_name": "Conv2D", "config": {"name": "conv2d_43", "trainable": true, "dtype": "float32", "filters": 256, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "same", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "conv2d_43", "inbound_nodes": [[["max_pooling2d_32", 0, 0, {}]]]}, {"class_name": "Dropout", "config": {"name": "dropout_53", "trainable": true, "dtype": "float32", "rate": 0.4, "noise_shape": null, "seed": null}, "name": "dropout_53", "inbound_nodes": [[["conv2d_43", 0, 0, {}]]]}, {"class_name": "Activation", "config": {"name": "activation_43", "trainable": true, "dtype": "float32", "activation": {"class_name": "ReLU", "config": {"name": "re_lu_43", "trainable": true, "dtype": "float32", "max_value": null, "negative_slope": 0.0, "threshold": 0.0}}}, "name": "activation_43", "inbound_nodes": [[["dropout_53", 0, 0, {}]]]}, {"class_name": "Flatten", "config": {"name": "flatten_10", "trainable": true, "dtype": "float32", "data_format": "channels_last"}, "name": "flatten_10", "inbound_nodes": [[["activation_43", 0, 0, {}]]]}, {"class_name": "Dense", "config": {"name": "dense_30", "trainable": true, "dtype": "float32", "units": 128, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "dense_30", "inbound_nodes": [[["flatten_10", 0, 0, {}]]]}, {"class_name": "BatchNormalization", "config": {"name": "batch_normalization_42", "trainable": true, "dtype": "float32", "axis": [1], "momentum": 0.99, "epsilon": 0.001, "center": true, "scale": true, "beta_initializer": {"class_name": "Zeros", "config": {}}, "gamma_initializer": {"class_name": "Ones", "config": {}}, "moving_mean_initializer": {"class_name": "Zeros", "config": {}}, "moving_variance_initializer": {"class_name": "Ones", "config": {}}, "beta_regularizer": null, "gamma_regularizer": null, "beta_constraint": null, "gamma_constraint": null}, "name": "batch_normalization_42", "inbound_nodes": [[["dense_30", 0, 0, {}]]]}, {"class_name": "Dense", "config": {"name": "dense_31", "trainable": true, "dtype": "float32", "units": 128, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "dense_31", "inbound_nodes": [[["batch_normalization_42", 0, 0, {}]]]}, {"class_name": "Dropout", "config": {"name": "dropout_54", "trainable": true, "dtype": "float32", "rate": 0.4, "noise_shape": null, "seed": null}, "name": "dropout_54", "inbound_nodes": [[["dense_31", 0, 0, {}]]]}, {"class_name": "BatchNormalization", "config": {"name": "batch_normalization_43", "trainable": true, "dtype": "float32", "axis": [1], "momentum": 0.99, "epsilon": 0.001, "center": true, "scale": true, "beta_initializer": {"class_name": "Zeros", "config": {}}, "gamma_initializer": {"class_name": "Ones", "config": {}}, "moving_mean_initializer": {"class_name": "Zeros", "config": {}}, "moving_variance_initializer": {"class_name": "Ones", "config": {}}, "beta_regularizer": null, "gamma_regularizer": null, "beta_constraint": null, "gamma_constraint": null}, "name": "batch_normalization_43", "inbound_nodes": [[["dropout_54", 0, 0, {}]]]}, {"class_name": "Dense", "config": {"name": "dense_32", "trainable": true, "dtype": "float32", "units": 2, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "dense_32", "inbound_nodes": [[["batch_normalization_43", 0, 0, {}]]]}, {"class_name": "Activation", "config": {"name": "pred", "trainable": true, "dtype": "float32", "activation": "softmax"}, "name": "pred", "inbound_nodes": [[["dense_32", 0, 0, {}]]]}], "input_layers": [["charge", 0, 0]], "output_layers": [["pred", 0, 0]]}, "shared_object_id": 60, "input_spec": [{"class_name": "InputSpec", "config": {"dtype": null, "shape": {"class_name": "__tuple__", "items": [null, 10, 16, 1]}, "ndim": 4, "max_ndim": null, "min_ndim": null, "axes": {}}}], "build_input_shape": {"class_name": "TensorShape", "items": [null, 10, 16, 1]}, "is_graph_network": true, "full_save_spec": {"class_name": "__tuple__", "items": [[{"class_name": "TypeSpec", "type_spec": "tf.TensorSpec", "serialized": [{"class_name": "TensorShape", "items": [null, 10, 16, 1]}, "float32", "charge"]}], {}]}, "save_spec": {"class_name": "TypeSpec", "type_spec": "tf.TensorSpec", "serialized": [{"class_name": "TensorShape", "items": [null, 10, 16, 1]}, "float32", "charge"]}, "keras_version": "2.7.0", "backend": "tensorflow", "model_config": {"class_name": "Functional", "config": {"name": "model_23", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": {"class_name": "__tuple__", "items": [null, 10, 16, 1]}, "dtype": "float32", "sparse": false, "ragged": false, "name": "charge"}, "name": "charge", "inbound_nodes": [], "shared_object_id": 0}, {"class_name": "Conv2D", "config": {"name": "conv2d_40", "trainable": true, "dtype": "float32", "filters": 64, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "same", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 1}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 2}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "conv2d_40", "inbound_nodes": [[["charge", 0, 0, {}]]], "shared_object_id": 3}, {"class_name": "Dropout", "config": {"name": "dropout_50", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}, "name": "dropout_50", "inbound_nodes": [[["conv2d_40", 0, 0, {}]]], "shared_object_id": 4}, {"class_name": "Activation", "config": {"name": "activation_40", "trainable": true, "dtype": "float32", "activation": {"class_name": "ReLU", "config": {"name": "re_lu_40", "trainable": true, "dtype": "float32", "max_value": null, "negative_slope": 0.0, "threshold": 0.0}, "shared_object_id": 5}}, "name": "activation_40", "inbound_nodes": [[["dropout_50", 0, 0, {}]]], "shared_object_id": 6}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_30", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "name": "max_pooling2d_30", "inbound_nodes": [[["activation_40", 0, 0, {}]]], "shared_object_id": 7}, {"class_name": "Conv2D", "config": {"name": "conv2d_41", "trainable": true, "dtype": "float32", "filters": 128, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "same", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 8}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 9}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "conv2d_41", "inbound_nodes": [[["max_pooling2d_30", 0, 0, {}]]], "shared_object_id": 10}, {"class_name": "Dropout", "config": {"name": "dropout_51", "trainable": true, "dtype": "float32", "rate": 0.4, "noise_shape": null, "seed": null}, "name": "dropout_51", "inbound_nodes": [[["conv2d_41", 0, 0, {}]]], "shared_object_id": 11}, {"class_name": "BatchNormalization", "config": {"name": "batch_normalization_40", "trainable": true, "dtype": "float32", "axis": [3], "momentum": 0.99, "epsilon": 0.001, "center": true, "scale": true, "beta_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 12}, "gamma_initializer": {"class_name": "Ones", "config": {}, "shared_object_id": 13}, "moving_mean_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 14}, "moving_variance_initializer": {"class_name": "Ones", "config": {}, "shared_object_id": 15}, "beta_regularizer": null, "gamma_regularizer": null, "beta_constraint": null, "gamma_constraint": null}, "name": "batch_normalization_40", "inbound_nodes": [[["dropout_51", 0, 0, {}]]], "shared_object_id": 16}, {"class_name": "Activation", "config": {"name": "activation_41", "trainable": true, "dtype": "float32", "activation": {"class_name": "ReLU", "config": {"name": "re_lu_41", "trainable": true, "dtype": "float32", "max_value": null, "negative_slope": 0.0, "threshold": 0.0}, "shared_object_id": 17}}, "name": "activation_41", "inbound_nodes": [[["batch_normalization_40", 0, 0, {}]]], "shared_object_id": 18}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_31", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "name": "max_pooling2d_31", "inbound_nodes": [[["activation_41", 0, 0, {}]]], "shared_object_id": 19}, {"class_name": "Conv2D", "config": {"name": "conv2d_42", "trainable": true, "dtype": "float32", "filters": 256, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "same", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 20}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 21}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "conv2d_42", "inbound_nodes": [[["max_pooling2d_31", 0, 0, {}]]], "shared_object_id": 22}, {"class_name": "Dropout", "config": {"name": "dropout_52", "trainable": true, "dtype": "float32", "rate": 0.4, "noise_shape": null, "seed": null}, "name": "dropout_52", "inbound_nodes": [[["conv2d_42", 0, 0, {}]]], "shared_object_id": 23}, {"class_name": "BatchNormalization", "config": {"name": "batch_normalization_41", "trainable": true, "dtype": "float32", "axis": [3], "momentum": 0.99, "epsilon": 0.001, "center": true, "scale": true, "beta_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 24}, "gamma_initializer": {"class_name": "Ones", "config": {}, "shared_object_id": 25}, "moving_mean_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 26}, "moving_variance_initializer": {"class_name": "Ones", "config": {}, "shared_object_id": 27}, "beta_regularizer": null, "gamma_regularizer": null, "beta_constraint": null, "gamma_constraint": null}, "name": "batch_normalization_41", "inbound_nodes": [[["dropout_52", 0, 0, {}]]], "shared_object_id": 28}, {"class_name": "Activation", "config": {"name": "activation_42", "trainable": true, "dtype": "float32", "activation": {"class_name": "ReLU", "config": {"name": "re_lu_42", "trainable": true, "dtype": "float32", "max_value": null, "negative_slope": 0.0, "threshold": 0.0}, "shared_object_id": 29}}, "name": "activation_42", "inbound_nodes": [[["batch_normalization_41", 0, 0, {}]]], "shared_object_id": 30}, {"class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_32", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "name": "max_pooling2d_32", "inbound_nodes": [[["activation_42", 0, 0, {}]]], "shared_object_id": 31}, {"class_name": "Conv2D", "config": {"name": "conv2d_43", "trainable": true, "dtype": "float32", "filters": 256, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "same", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 32}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 33}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "conv2d_43", "inbound_nodes": [[["max_pooling2d_32", 0, 0, {}]]], "shared_object_id": 34}, {"class_name": "Dropout", "config": {"name": "dropout_53", "trainable": true, "dtype": "float32", "rate": 0.4, "noise_shape": null, "seed": null}, "name": "dropout_53", "inbound_nodes": [[["conv2d_43", 0, 0, {}]]], "shared_object_id": 35}, {"class_name": "Activation", "config": {"name": "activation_43", "trainable": true, "dtype": "float32", "activation": {"class_name": "ReLU", "config": {"name": "re_lu_43", "trainable": true, "dtype": "float32", "max_value": null, "negative_slope": 0.0, "threshold": 0.0}, "shared_object_id": 36}}, "name": "activation_43", "inbound_nodes": [[["dropout_53", 0, 0, {}]]], "shared_object_id": 37}, {"class_name": "Flatten", "config": {"name": "flatten_10", "trainable": true, "dtype": "float32", "data_format": "channels_last"}, "name": "flatten_10", "inbound_nodes": [[["activation_43", 0, 0, {}]]], "shared_object_id": 38}, {"class_name": "Dense", "config": {"name": "dense_30", "trainable": true, "dtype": "float32", "units": 128, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 39}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 40}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "dense_30", "inbound_nodes": [[["flatten_10", 0, 0, {}]]], "shared_object_id": 41}, {"class_name": "BatchNormalization", "config": {"name": "batch_normalization_42", "trainable": true, "dtype": "float32", "axis": [1], "momentum": 0.99, "epsilon": 0.001, "center": true, "scale": true, "beta_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 42}, "gamma_initializer": {"class_name": "Ones", "config": {}, "shared_object_id": 43}, "moving_mean_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 44}, "moving_variance_initializer": {"class_name": "Ones", "config": {}, "shared_object_id": 45}, "beta_regularizer": null, "gamma_regularizer": null, "beta_constraint": null, "gamma_constraint": null}, "name": "batch_normalization_42", "inbound_nodes": [[["dense_30", 0, 0, {}]]], "shared_object_id": 46}, {"class_name": "Dense", "config": {"name": "dense_31", "trainable": true, "dtype": "float32", "units": 128, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 47}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 48}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "dense_31", "inbound_nodes": [[["batch_normalization_42", 0, 0, {}]]], "shared_object_id": 49}, {"class_name": "Dropout", "config": {"name": "dropout_54", "trainable": true, "dtype": "float32", "rate": 0.4, "noise_shape": null, "seed": null}, "name": "dropout_54", "inbound_nodes": [[["dense_31", 0, 0, {}]]], "shared_object_id": 50}, {"class_name": "BatchNormalization", "config": {"name": "batch_normalization_43", "trainable": true, "dtype": "float32", "axis": [1], "momentum": 0.99, "epsilon": 0.001, "center": true, "scale": true, "beta_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 51}, "gamma_initializer": {"class_name": "Ones", "config": {}, "shared_object_id": 52}, "moving_mean_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 53}, "moving_variance_initializer": {"class_name": "Ones", "config": {}, "shared_object_id": 54}, "beta_regularizer": null, "gamma_regularizer": null, "beta_constraint": null, "gamma_constraint": null}, "name": "batch_normalization_43", "inbound_nodes": [[["dropout_54", 0, 0, {}]]], "shared_object_id": 55}, {"class_name": "Dense", "config": {"name": "dense_32", "trainable": true, "dtype": "float32", "units": 2, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 56}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 57}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "name": "dense_32", "inbound_nodes": [[["batch_normalization_43", 0, 0, {}]]], "shared_object_id": 58}, {"class_name": "Activation", "config": {"name": "pred", "trainable": true, "dtype": "float32", "activation": "softmax"}, "name": "pred", "inbound_nodes": [[["dense_32", 0, 0, {}]]], "shared_object_id": 59}], "input_layers": [["charge", 0, 0]], "output_layers": [["pred", 0, 0]]}}, "training_config": {"loss": "binary_crossentropy", "metrics": [[{"class_name": "MeanMetricWrapper", "config": {"name": "accuracy", "dtype": "float32", "fn": "categorical_accuracy"}, "shared_object_id": 62}]], "weighted_metrics": null, "loss_weights": null, "optimizer_config": {"class_name": "Adam", "config": {"name": "Adam", "learning_rate": 9.999999747378752e-05, "decay": 0.0, "beta_1": 0.8999999761581421, "beta_2": 0.9990000128746033, "epsilon": 1e-07, "amsgrad": false}}}}2 +„ root.layer-0"_tf_keras_input_layer*Ô{"class_name": "InputLayer", "name": "charge", "dtype": "float32", "sparse": false, "ragged": false, "batch_input_shape": {"class_name": "__tuple__", "items": [null, 10, 16, 1]}, "config": {"batch_input_shape": {"class_name": "__tuple__", "items": [null, 10, 16, 1]}, "dtype": "float32", "sparse": false, "ragged": false, "name": "charge"}}2 +ô root.layer_with_weights-0"_tf_keras_layer*½ {"name": "conv2d_40", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Conv2D", "config": {"name": "conv2d_40", "trainable": true, "dtype": "float32", "filters": 64, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "same", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 1}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 2}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "inbound_nodes": [[["charge", 0, 0, {}]]], "shared_object_id": 3, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 4, "axes": {"-1": 1}}, "shared_object_id": 63}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 10, 16, 1]}}2 +­ root.layer-2"_tf_keras_layer*ƒ{"name": "dropout_50", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dropout", "config": {"name": "dropout_50", "trainable": true, "dtype": "float32", "rate": 0.2, "noise_shape": null, "seed": null}, "inbound_nodes": [[["conv2d_40", 0, 0, {}]]], "shared_object_id": 4}2 +È root.layer-3"_tf_keras_layer*ž{"name": "activation_40", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Activation", "config": {"name": "activation_40", "trainable": true, "dtype": "float32", "activation": {"class_name": "ReLU", "config": {"name": "re_lu_40", "trainable": true, "dtype": "float32", "max_value": null, "negative_slope": 0.0, "threshold": 0.0}, "shared_object_id": 5}}, "inbound_nodes": [[["dropout_50", 0, 0, {}]]], "shared_object_id": 6}2 +ã root.layer-4"_tf_keras_layer*¹{"name": "max_pooling2d_30", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_30", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "inbound_nodes": [[["activation_40", 0, 0, {}]]], "shared_object_id": 7, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": 4, "max_ndim": null, "min_ndim": null, "axes": {}}, "shared_object_id": 64}}2 +€ +root.layer_with_weights-1"_tf_keras_layer*É {"name": "conv2d_41", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Conv2D", "config": {"name": "conv2d_41", "trainable": true, "dtype": "float32", "filters": 128, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "same", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 8}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 9}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "inbound_nodes": [[["max_pooling2d_30", 0, 0, {}]]], "shared_object_id": 10, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 4, "axes": {"-1": 64}}, "shared_object_id": 65}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 5, 8, 64]}}2 +® root.layer-6"_tf_keras_layer*„{"name": "dropout_51", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dropout", "config": {"name": "dropout_51", "trainable": true, "dtype": "float32", "rate": 0.4, "noise_shape": null, "seed": null}, "inbound_nodes": [[["conv2d_41", 0, 0, {}]]], "shared_object_id": 11}2 +Ä root.layer_with_weights-2"_tf_keras_layer* {"name": "batch_normalization_40", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "BatchNormalization", "config": {"name": "batch_normalization_40", "trainable": true, "dtype": "float32", "axis": [3], "momentum": 0.99, "epsilon": 0.001, "center": true, "scale": true, "beta_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 12}, "gamma_initializer": {"class_name": "Ones", "config": {}, "shared_object_id": 13}, "moving_mean_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 14}, "moving_variance_initializer": {"class_name": "Ones", "config": {}, "shared_object_id": 15}, "beta_regularizer": null, "gamma_regularizer": null, "beta_constraint": null, "gamma_constraint": null}, "inbound_nodes": [[["dropout_51", 0, 0, {}]]], "shared_object_id": 16, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": 4, "max_ndim": null, "min_ndim": null, "axes": {"3": 128}}, "shared_object_id": 66}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 5, 8, 128]}}2 +Ö  root.layer-8"_tf_keras_layer*¬{"name": "activation_41", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Activation", "config": {"name": "activation_41", "trainable": true, "dtype": "float32", "activation": {"class_name": "ReLU", "config": {"name": "re_lu_41", "trainable": true, "dtype": "float32", "max_value": null, "negative_slope": 0.0, "threshold": 0.0}, "shared_object_id": 17}}, "inbound_nodes": [[["batch_normalization_40", 0, 0, {}]]], "shared_object_id": 18}2 +ä + root.layer-9"_tf_keras_layer*º{"name": "max_pooling2d_31", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_31", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "inbound_nodes": [[["activation_41", 0, 0, {}]]], "shared_object_id": 19, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": 4, "max_ndim": null, "min_ndim": null, "axes": {}}, "shared_object_id": 67}}2 +„ + root.layer_with_weights-3"_tf_keras_layer*Í {"name": "conv2d_42", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Conv2D", "config": {"name": "conv2d_42", "trainable": true, "dtype": "float32", "filters": 256, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "same", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 20}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 21}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "inbound_nodes": [[["max_pooling2d_31", 0, 0, {}]]], "shared_object_id": 22, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 4, "axes": {"-1": 128}}, "shared_object_id": 68}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 2, 4, 128]}}2 +¯  root.layer-11"_tf_keras_layer*„{"name": "dropout_52", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dropout", "config": {"name": "dropout_52", "trainable": true, "dtype": "float32", "rate": 0.4, "noise_shape": null, "seed": null}, "inbound_nodes": [[["conv2d_42", 0, 0, {}]]], "shared_object_id": 23}2 +Ä  root.layer_with_weights-4"_tf_keras_layer* {"name": "batch_normalization_41", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "BatchNormalization", "config": {"name": "batch_normalization_41", "trainable": true, "dtype": "float32", "axis": [3], "momentum": 0.99, "epsilon": 0.001, "center": true, "scale": true, "beta_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 24}, "gamma_initializer": {"class_name": "Ones", "config": {}, "shared_object_id": 25}, "moving_mean_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 26}, "moving_variance_initializer": {"class_name": "Ones", "config": {}, "shared_object_id": 27}, "beta_regularizer": null, "gamma_regularizer": null, "beta_constraint": null, "gamma_constraint": null}, "inbound_nodes": [[["dropout_52", 0, 0, {}]]], "shared_object_id": 28, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": 4, "max_ndim": null, "min_ndim": null, "axes": {"3": 256}}, "shared_object_id": 69}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 2, 4, 256]}}2 +× root.layer-13"_tf_keras_layer*¬{"name": "activation_42", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Activation", "config": {"name": "activation_42", "trainable": true, "dtype": "float32", "activation": {"class_name": "ReLU", "config": {"name": "re_lu_42", "trainable": true, "dtype": "float32", "max_value": null, "negative_slope": 0.0, "threshold": 0.0}, "shared_object_id": 29}}, "inbound_nodes": [[["batch_normalization_41", 0, 0, {}]]], "shared_object_id": 30}2 +å root.layer-14"_tf_keras_layer*º{"name": "max_pooling2d_32", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "MaxPooling2D", "config": {"name": "max_pooling2d_32", "trainable": true, "dtype": "float32", "pool_size": {"class_name": "__tuple__", "items": [2, 2]}, "padding": "valid", "strides": {"class_name": "__tuple__", "items": [2, 2]}, "data_format": "channels_last"}, "inbound_nodes": [[["activation_42", 0, 0, {}]]], "shared_object_id": 31, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": 4, "max_ndim": null, "min_ndim": null, "axes": {}}, "shared_object_id": 70}}2 +„ +root.layer_with_weights-5"_tf_keras_layer*Í {"name": "conv2d_43", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Conv2D", "config": {"name": "conv2d_43", "trainable": true, "dtype": "float32", "filters": 256, "kernel_size": {"class_name": "__tuple__", "items": [3, 3]}, "strides": {"class_name": "__tuple__", "items": [1, 1]}, "padding": "same", "data_format": "channels_last", "dilation_rate": {"class_name": "__tuple__", "items": [1, 1]}, "groups": 1, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 32}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 33}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "inbound_nodes": [[["max_pooling2d_32", 0, 0, {}]]], "shared_object_id": 34, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 4, "axes": {"-1": 256}}, "shared_object_id": 71}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 1, 2, 256]}}2 +¯ root.layer-16"_tf_keras_layer*„{"name": "dropout_53", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dropout", "config": {"name": "dropout_53", "trainable": true, "dtype": "float32", "rate": 0.4, "noise_shape": null, "seed": null}, "inbound_nodes": [[["conv2d_43", 0, 0, {}]]], "shared_object_id": 35}2 +Ë root.layer-17"_tf_keras_layer* {"name": "activation_43", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Activation", "config": {"name": "activation_43", "trainable": true, "dtype": "float32", "activation": {"class_name": "ReLU", "config": {"name": "re_lu_43", "trainable": true, "dtype": "float32", "max_value": null, "negative_slope": 0.0, "threshold": 0.0}, "shared_object_id": 36}}, "inbound_nodes": [[["dropout_53", 0, 0, {}]]], "shared_object_id": 37}2 +Ì root.layer-18"_tf_keras_layer*¡{"name": "flatten_10", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Flatten", "config": {"name": "flatten_10", "trainable": true, "dtype": "float32", "data_format": "channels_last"}, "inbound_nodes": [[["activation_43", 0, 0, {}]]], "shared_object_id": 38, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 1, "axes": {}}, "shared_object_id": 72}}2 +þroot.layer_with_weights-6"_tf_keras_layer*Ç{"name": "dense_30", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dense", "config": {"name": "dense_30", "trainable": true, "dtype": "float32", "units": 128, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 39}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 40}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "inbound_nodes": [[["flatten_10", 0, 0, {}]]], "shared_object_id": 41, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 512}}, "shared_object_id": 73}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 512]}}2 +¼ root.layer_with_weights-7"_tf_keras_layer*… {"name": "batch_normalization_42", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "BatchNormalization", "config": {"name": "batch_normalization_42", "trainable": true, "dtype": "float32", "axis": [1], "momentum": 0.99, "epsilon": 0.001, "center": true, "scale": true, "beta_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 42}, "gamma_initializer": {"class_name": "Ones", "config": {}, "shared_object_id": 43}, "moving_mean_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 44}, "moving_variance_initializer": {"class_name": "Ones", "config": {}, "shared_object_id": 45}, "beta_regularizer": null, "gamma_regularizer": null, "beta_constraint": null, "gamma_constraint": null}, "inbound_nodes": [[["dense_30", 0, 0, {}]]], "shared_object_id": 46, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": 2, "max_ndim": null, "min_ndim": null, "axes": {"1": 128}}, "shared_object_id": 74}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 128]}}2 +Šroot.layer_with_weights-8"_tf_keras_layer*Ó{"name": "dense_31", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dense", "config": {"name": "dense_31", "trainable": true, "dtype": "float32", "units": 128, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 47}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 48}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "inbound_nodes": [[["batch_normalization_42", 0, 0, {}]]], "shared_object_id": 49, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 128}}, "shared_object_id": 75}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 128]}}2 +® root.layer-22"_tf_keras_layer*ƒ{"name": "dropout_54", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dropout", "config": {"name": "dropout_54", "trainable": true, "dtype": "float32", "rate": 0.4, "noise_shape": null, "seed": null}, "inbound_nodes": [[["dense_31", 0, 0, {}]]], "shared_object_id": 50}2 +¾ root.layer_with_weights-9"_tf_keras_layer*‡ {"name": "batch_normalization_43", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "BatchNormalization", "config": {"name": "batch_normalization_43", "trainable": true, "dtype": "float32", "axis": [1], "momentum": 0.99, "epsilon": 0.001, "center": true, "scale": true, "beta_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 51}, "gamma_initializer": {"class_name": "Ones", "config": {}, "shared_object_id": 52}, "moving_mean_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 53}, "moving_variance_initializer": {"class_name": "Ones", "config": {}, "shared_object_id": 54}, "beta_regularizer": null, "gamma_regularizer": null, "beta_constraint": null, "gamma_constraint": null}, "inbound_nodes": [[["dropout_54", 0, 0, {}]]], "shared_object_id": 55, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": 2, "max_ndim": null, "min_ndim": null, "axes": {"1": 128}}, "shared_object_id": 76}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 128]}}2 +‰root.layer_with_weights-10"_tf_keras_layer*Ñ{"name": "dense_32", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Dense", "config": {"name": "dense_32", "trainable": true, "dtype": "float32", "units": 2, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 56}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 57}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "inbound_nodes": [[["batch_normalization_43", 0, 0, {}]]], "shared_object_id": 58, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 128}}, "shared_object_id": 77}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 128]}}2 + root.layer-25"_tf_keras_layer*ä{"name": "pred", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "Activation", "config": {"name": "pred", "trainable": true, "dtype": "float32", "activation": "softmax"}, "inbound_nodes": [[["dense_32", 0, 0, {}]]], "shared_object_id": 59}2 ++root.layer-3.activation"_tf_keras_layer*Û{"name": "re_lu_40", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "ReLU", "config": {"name": "re_lu_40", "trainable": true, "dtype": "float32", "max_value": null, "negative_slope": 0.0, "threshold": 0.0}, "shared_object_id": 5}2 +‘Groot.layer-8.activation"_tf_keras_layer*Ü{"name": "re_lu_41", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "ReLU", "config": {"name": "re_lu_41", "trainable": true, "dtype": "float32", "max_value": null, "negative_slope": 0.0, "threshold": 0.0}, "shared_object_id": 17}2 +’croot.layer-13.activation"_tf_keras_layer*Ü{"name": "re_lu_42", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "ReLU", "config": {"name": "re_lu_42", "trainable": true, "dtype": "float32", "max_value": null, "negative_slope": 0.0, "threshold": 0.0}, "shared_object_id": 29}2 +’vroot.layer-17.activation"_tf_keras_layer*Ü{"name": "re_lu_43", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "class_name": "ReLU", "config": {"name": "re_lu_43", "trainable": true, "dtype": "float32", "max_value": null, "negative_slope": 0.0, "threshold": 0.0}, "shared_object_id": 36}2 +ºÂroot.keras_api.metrics.0"_tf_keras_metric*‚{"class_name": "Mean", "name": "loss", "dtype": "float32", "config": {"name": "loss", "dtype": "float32"}, "shared_object_id": 78}2 +íÃroot.keras_api.metrics.1"_tf_keras_metric*µ{"class_name": "MeanMetricWrapper", "name": "accuracy", "dtype": "float32", "config": {"name": "accuracy", "dtype": "float32", "fn": "categorical_accuracy"}, "shared_object_id": 62}2 \ No newline at end of file diff --git a/configfiles/RingCounting/RC_model_v1_0_0.model/saved_model.pb b/configfiles/RingCounting/RC_model_v1_0_0.model/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..a9c2cce3b18856dd6c6840c34e77908a33ade054 GIT binary patch literal 482284 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 literal 0 HcmV?d00001 diff --git a/configfiles/RingCounting/RC_model_v1_0_0.model/variables/variables.data-00000-of-00001 b/configfiles/RingCounting/RC_model_v1_0_0.model/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..b4ad9836ca11af41df8f36ebcfc3e840e0ec0813 GIT binary patch literal 12547884 zcmWKXhhL6g7{*gHL?x9pM9F9=?f1Fwmx?l)DpJZ04P|dy(iSSxKt&oNE4|OT-xLuk z5wZ%&NHTv$Nq+qY&-t8lp6j}=?{yX!#cFo$Wm3;PR?DPL@ODIN~# zo550{0Yy1=!Q1gq*pG{YaB0kbao!3iT-Oiu)dp};=LPoWSUGfN5%DkHz2O$vIf>tuaio)! zPd;BG!836MnCMoBn|8GerY7x%Jt3yzzKGov8OKfH|kgSfu8vaE@Q0?9{w{&{JZNSJ2-D41l%sAoWq|%u}4j8aVMKbYkXl2tN(%a zkk2G%nhBeB+`w1+53tIc#@M2p!X01dgb#Mv!p?QKp!su|_^4w({Ebts+K1T{-7ffWc^_Ecm?~boE?+dSz6vBQN8Dx!-1)^t(h6N5q_|T;=5|j!bP7Z)grAb%j zyzEge*qV8FECE+M3#AwO#iu5zi>IGj&n{R-^WlT)DM8v3`Qg(+;({kVxb%?=RCC7O z^^a-nFAJ1{GR_S%IOli$@a1nBjaryqRlUAV?CE_S^I#ib0xIv;rqb&LR_ljX* zT^si<=&*RqiCH4w-6DuxGZ7}bh^{1Vw8qKf27%3CB#&|fteo+XdK!nK;^Hpu^eAJT zYz3h9Q5QR46*PU`NCAx+RPR3R>T-)(Zft@9^msQ2&MJ+pYCX6N=M1@AS$`;vWx9J; z#XTHBhx{YNHiNg|#q;O5la8ObYOe&+G45ay=bXigoy*zhiP7ZNjZm~JhO4^zQC$8| zUVL~-Co~vtz^5j+>F7pNlwI2jC)a+b;fcf1^q&%+Wu$@?*<*3)?M9j+;@M~jsT$+^ z0HjPinO5^S{Hz#HThjMX)Aoh*?65cXC2P7z+CHA@M-fCFE5yiI)A=X?$ln+Cd?TNE)0X@RAu~6Ii7j+euTinP-@g@ zhhXUdPCOwS9uIcr+svPd-=uCMzgu!RWKRhUnXXu6TkDC#j_(!szo?|_)x&Xxo|gFO zU3O&4f;$|4h$C8&Ra>^x-0SH z-*6f}MwKm&e+Vz$+=cok9s1%B06y8vsiQv$#yO3HCo(@tIK~sgdMhYjv4ym5PR7>< zZ-d1eBNUkG^M`!0z-dhjUGVCFiKVHS`O25pthc;cBp(5TjNG6-A+mD9{a5t%PAsMu zSXX|UB!h<6s>IKHRIKXQehg%PuL09fZ z49G|a-SIqAdhddF7I}&~qjaEfx)l1~ily@>H$(p^Pe`$^fib;4^yG`FIP$R`3cK9s zM&n;ze!&55y5u2RKSdh@7K*t`HQUL2#z`jcl}IBVpM#$9(d@5aBCL>zrVZ)`pmU!G zrMTXMzj&~q=@9yLexPMxatqhB#!Hw)M>cz;zy`Bs?zE~aX7Um%`S*bG~J z=fmLrf7zhh@8RGL7kYnXJG`144gX0@#FBzv-09V~$lK2Wbm$w%X>Fj@;ZvdcdMHNR zJqr14jZi#m3l^)6q=2)F=;hvK?rRLu;?z^zM#oB0_~MI4q+fE!n;mdN>?qNw)83qc z|3buh6VSR~p15a*BaUmmDZX>$CaiYaEB+fLq{B>{W}Lx2IWk2{e5zGK!*{$ESe)@?8Pn3~NY^D=lxIru z{(s4%po4x5DJHoOgR9kltYX9!lA(K8VE;@!401ZK-4siin7m=cJx8;b}*zXVMB3(b0NulY=OCz zim0~1879ejQ4WgO8J$~Iz3rr5p5(@F%>O?+$!_-n^YBC zlA<(^M_kzEG$pRKzD)bcdB;IcsYc*=n9O+N#sf)Vg_{2;X0Vuj99 zOJVRnQ&>N20WQp40h)JzQenb08g^y{y}DxuVJ6jd%=Zna|9BNyt%$XKY30I6{L$kj zyPe=Nr_QamAI=HI`$cyj%wX>`Wd-qnleydBk3~C-2VtejWWkzS$(4mOTLl_>lPVp) zrB;48P$pRJ7r~8n6pFrf%-~k~

`6{Sg@59gO!|w+JGI0is)X{s<=M-s0YNb_nEm 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 Uinsm+3g`@wD2os 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�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 z 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