#include #include #include #include #include #include "TTree.h" #include "TChain.h" #include "TGraphErrors.h" #include "TGraph.h" #include "TCanvas.h" #include "TFile.h" #include "TF1.h" #include "TH1.h" #include "TH2.h" #include "TH1F.h" #include "TLegend.h" #include #include "TROOT.h" #include "TBrowser.h" #include "MTime.h" //#include "MSignalCam.h" #include "MRawEvtHeader.h" //#include "MSoftwareTrigger.h" #include "MRawBoardsFACT.h" using namespace std; /* C : a character string terminated by the 0 character B : an 8 bit signed integer (Char_t) b : an 8 bit unsigned integer (UChar_t) S : a 16 bit signed integer (Short_t) s : a 16 bit unsigned integer (UShort_t) I : a 32 bit signed integer (Int_t) i : a 32 bit unsigned integer (UInt_t) F : a 32 bit floating point (Float_t) D : a 64 bit floating point (Double_t) L : a 64 bit signed integer (Long64_t) l : a 64 bit unsigned integer (ULong64_t) O : [the letter o, not a zero] a boolean (Bool_t) */ vector calibration(TString HEye_path) { /* INPUT: HEye_path: Path to HAWC's Eye data (calibrated or cleaned) OUTPUT: calibrated time in Unix_s */ // Vectors to store the Unix time after calibration vector unix_s = {}; TFile *tHEye = new TFile(HEye_path); cout << "------------------------------------------------------------------------" << endl; cout << "Do time calibration with file: " << HEye_path << endl; TTree *tEvents = (TTree*) tHEye->Get("Events"); MTime *mtime_utc = 0; // PC's timestamp in UNIX MRawBoardsFACT *mtime_board = 0; // board's counter tEvents->SetBranchAddress("MTime.", &mtime_utc); tEvents->SetBranchAddress("MRawBoardsFACT.", &mtime_board); Long64_t nEvents = tEvents->GetEntries(); //cout << "Number of Events: " << nEvents << endl; Double_t Mjd; // time in Mjd int Mjd_unix = 40587; // Mjd at 01/01/1970 Double_t unix_timestamp; // For fitting and plotting Double_t Unix_fit[nEvents], Board_fit[nEvents], UnixErr_fit[nEvents]; for (Long64_t i = 0; i < nEvents; i++) { tEvents->GetEntry(i); //mtime_utc->Print(); Mjd = mtime_utc->GetMjd(); UInt_t board_timestamp = mtime_board->GetFadTime(0); // calculate the PC's unix timestamp based on the PC UTC's time Double_t unix_timestamp = (Mjd - Mjd_unix)*24*60*60; Unix_fit[i] = unix_timestamp; Board_fit[i] = board_timestamp; UnixErr_fit[i] = 0.001; // jitter of 1ms } // Use a linear fit to determine the offset and the conversion factor as the fit's slope auto *board_unix = new TGraphErrors(nEvents, Board_fit, Unix_fit, 0, UnixErr_fit); TF1 *fit_timestamp = new TF1("fit_timestamp", "[0] + [1]*x", Board_fit[0], Board_fit[nEvents-1]); board_unix->Fit("fit_timestamp", "S"); Double_t offset = fit_timestamp->GetParameter(0); Double_t conv_timestamp = fit_timestamp->GetParameter(1); // Calculate the Unix timestamp based on board's counter and the calibration data vector unix_time_s = {}; for (Long64_t i = 0; i < nEvents; i++) { tEvents->GetEntry(i); UInt_t board_timestamp = mtime_board->GetFadTime(0); Double_t unix_time = board_timestamp * conv_timestamp + offset; unix_time_s.push_back(unix_time); } // Calculate the mean time difference between calibrated unix_timestamp and PC's timestamp Double_t time_diff = 0.0; for (Long64_t i = 0; i < nEvents; i++) { time_diff += TMath::Abs(Unix_fit[i] - unix_time_s[i]); } Double_t mean_time_diff = time_diff/nEvents; printf("Mean time difference between PC's timestamps and calibrated counter's timestamp: %f s\n", mean_time_diff); /* TCanvas *c = new TCanvas("time_calibration", "Board's time and PC's UTC time",1200,800); c->SetGridx(); c->SetGridy(); board_unix->SetTitle("FAD's timestamp vs. PC's UTC timestamp"); board_unix->GetXaxis()->SetTitle("Board's counter"); board_unix->GetYaxis()->SetTitle("Unix timestamp [s]"); board_unix->SetMarkerStyle(8); board_unix->SetMarkerColor(1); gStyle->SetOptFit(0111); board_unix->Draw("AP"); */ return unix_time_s; } // structure of HAWC reconstructed data struct rec_struct { Int_t status ; Int_t version ; Int_t eventID ; Int_t runID ; Int_t timeSliceID ; Int_t trigger_flags; Int_t event_flags ; Int_t gtc_flags ; Int_t gpsSec ; Int_t gpsNanosec ; Int_t nChTot ; Int_t nChAvail ; Int_t nHitTot ; Int_t nHit ; Int_t nHitSP10 ; Int_t nHitSP20 ; Int_t nTankTot ; Int_t nTankAvail ; Int_t nTankHitTot ; Int_t nTankHit ; Int_t windowHits ; Int_t angleFitStatus; Int_t planeNDOF ; Int_t coreFitStatus; Int_t CxPE40PMT ; Int_t CxPE40XnCh ; Double_t mPFnHits; Double_t mPFnPlanes; Double_t mPFp0nAssign; Double_t mPFp1nAssign; Double_t nHitMPF ; Int_t coreFiduScale; Double_t coreFiduScaleOR ; Double_t coreLoc ; Double_t zenithAngle ; Double_t azimuthAngle ; Double_t dec ; Double_t ra ; Double_t planeChi2 ; Double_t coreX ; Double_t coreY ; Double_t logCoreAmplitude ; Double_t coreFitUnc ; Double_t logNNEnergy ; Double_t fAnnulusCharge0; Double_t fAnnulusCharge1; Double_t fAnnulusCharge2; Double_t fAnnulusCharge3; Double_t fAnnulusCharge4; Double_t fAnnulusCharge5; Double_t fAnnulusCharge6; Double_t fAnnulusCharge7; Double_t fAnnulusCharge8; Double_t protonlheEnergy; Double_t protonlheLLH ; Double_t gammalheEnergy ; Double_t gammalheLLH ; Int_t chargeFiduScale50 ; Int_t chargeFiduScale70 ; Int_t chargeFiduScale90 ; Double_t logMaxPE; Double_t logNPE ; Int_t CxPE40 ; Double_t CxPE40SPTime; Double_t LDFAge ; Double_t LDFAmp ; Double_t LDFChi2 ; Double_t logGP ; Double_t mPFp0Weight; Double_t mPFp0toangleFit; Double_t mPFp1Weight ; Double_t mPFp1toangleFit; Double_t PINC ; Double_t disMax ; Double_t TankLHR ; Double_t LHLatDistFitXmax ; Double_t LHLatDistFitEnergy; Double_t LHLatDistFitGoF ; Double_t probaGBT ; }; struct tel_struct { MTime *mTime = 0; MRawEvtHeader *mRawEvtHeader = 0; //MSignalCam *mSignalCam = 0; //MRawEvtHeader *mRawEvtHeader = 0; //MSoftwareTrigger *mSoftwareTrigger = 0; //MRawBoardsFACT *mRawBoardsFACT = 0; Double_t cal_unix; // calibrated unix timestamp based on board's counter UInt_t DAQ_id; // event's DAQ ID (fDAQEvtNumber) }; struct sync_struct { Double_t ts; UInt_t id; }; //Earlier timestamps first in vector: bool sort_time (sync_struct str_1, sync_struct str_2) { return (str_1.ts unix_s = calibration(HEye_path); //-------------------------------------------------------------------------------------------- // Read in the ID list and timestamps and sort them vector vts_HEye; vector vts_Hawc; sync_struct tsync; printf("Reading telescope data....\n"); Long64_t nHE_events = tHEye.GetEntries(); cout << "Number of HawcEye's Events: " << nHE_events << endl; for(Int_t i = 0; i < nHE_events; i++) { tHEye.GetEntry(i); tsync.id = i; tsync.ts = unix_s[i]; vts_HEye.push_back(tsync); } printf("Sorting telescope data....\n"); sort(vts_HEye.begin(), vts_HEye.end(),sort_time); printf("Reading HAWC data....\n"); Long64_t nHawc_events = tHawc.GetEntries(); cout << "Number of Hawc's Events: " << nHawc_events << endl; for(Int_t i=0;i < nHawc_events; i++) { tHawc.GetEntry(i); tsync.id = i; tsync.ts = HAWC_toffset + rec.gpsSec + ((Double_t)rec.gpsNanosec)/1000000000.0; vts_Hawc.push_back(tsync); } printf("Sorting HAWC data....\n"); sort(vts_Hawc.begin(), vts_Hawc.end(),sort_time); // Find the best sync offset printf("HAWC Data:\nFirst event: %f s Last event: %f s (Trigger: %ld, Rate: %f)\n\n", vts_Hawc[0].ts, vts_Hawc[vts_Hawc.size()-1].ts, vts_Hawc.size(), vts_Hawc.size() / (vts_Hawc[vts_Hawc.size()-1].ts - vts_Hawc[0].ts)); printf("HEye Data:\nFirst event: %f s Last event: %f s (Trigger: %ld, Rate: %f)\n\n", vts_HEye[0].ts, vts_HEye[vts_HEye.size()-1].ts, vts_HEye.size(), vts_HEye.size()/(vts_HEye[vts_HEye.size()-1].ts-vts_HEye[0].ts)); if (vts_Hawc[0].ts>vts_HEye[nHE_events-1].ts) { printf("NO OVERLAP: HAWC data later, choose later HEye file!\n"); return 1; } if (vts_Hawc[nHawc_events-1].ts first HE's time - Start_Shift Int_t last_shift = 0; // index of last Hawc's event with time < last HE's time - Stop_Shift Int_t first = 0; // index of first Hawc's event with trigger time > first HE's time Int_t last = 0 ; // index of last Hawc's event with trigger time < last HE's time for (Long64_t i = 0; i < nHawc_events; i++) { if (vts_Hawc[i].ts > vts_HEye[0].ts) { first = i; } if (vts_Hawc[i].ts > vts_HEye[0].ts - Start_Shift) { first_shift = i; break; } } for(Long64_t i = nHawc_events-1; i > 0; i--) { if (vts_Hawc[i].ts < vts_HEye[nHE_events-1].ts) { last = i; } if (vts_Hawc[i].ts < vts_HEye[nHE_events-1].ts - Stop_Shift) { last_shift = i; break; } } printf("HAWC Data (reduced):\nFirst event: %f s Last event: %f s\n\n", vts_Hawc[first_shift].ts, vts_Hawc[last_shift].ts); printf("HEye Data:\nFirst event: %f s Last event: %f s\n\n", vts_HEye[0].ts, vts_HEye[vts_HEye.size()-1].ts); //---------------------- Define the Output TTree ---------------------- TFile fOut(Outpath, "RECREATE"); TTree tOut1("Hawc_Data", "Hawc_Data"); // Hawc's data TTree tOut2("HE_Data", "HE_Data"); // Telescope's data TTree tOut3("timediff_tot", "timediff_tot"); // Synchronisation's info TTree tOut4("timediff_pass", "timediff_pass"); TTree tOut5("SyncInfo", "SyncInfo"); // Hawc Data tOut1.Branch("rec.status" , &rec.status) ; tOut1.Branch("rec.version", &rec.version) ; tOut1.Branch("rec.eventID", &rec.eventID) ; tOut1.Branch("rec.runID", &rec.runID) ; tOut1.Branch("rec.timeSliceID", &rec.timeSliceID); tOut1.Branch("rec.trigger_flags", &rec.trigger_flags); tOut1.Branch("rec.event_flags",&rec.event_flags) ; tOut1.Branch("rec.gtc_flags",&rec.gtc_flags) ; tOut1.Branch("rec.gpsSec",&rec.gpsSec) ; tOut1.Branch("rec.gpsNanosec",&rec.gpsNanosec) ; tOut1.Branch("rec.nChTot",&rec.nChTot) ; tOut1.Branch("rec.nChAvail",&rec.nChAvail) ; tOut1.Branch("rec.nHitTot",&rec.nHitTot) ; tOut1.Branch("rec.nHit",&rec.nHit) ; tOut1.Branch("rec.nHitSP10",&rec.nHitSP10) ; tOut1.Branch("rec.nHitSP20",&rec.nHitSP20) ; tOut1.Branch("rec.nTankTot",&rec.nTankTot) ; tOut1.Branch("rec.nTankAvail",&rec.nTankAvail) ; tOut1.Branch("rec.nTankHitTot",&rec.nTankHitTot) ; tOut1.Branch("rec.nTankHit",&rec.nTankHit) ; tOut1.Branch("rec.windowHits",&rec.windowHits) ; tOut1.Branch("rec.angleFitStatus",&rec.angleFitStatus); tOut1.Branch("rec.planeNDOF",&rec.planeNDOF) ; tOut1.Branch("rec.coreFitStatus",&rec.coreFitStatus); tOut1.Branch("rec.CxPE40PMT",&rec.CxPE40PMT) ; tOut1.Branch("rec.CxPE40XnCh",&rec.CxPE40XnCh); tOut1.Branch("rec.mPFnHits",&rec.mPFnHits); tOut1.Branch("rec.mPFnPlanes",&rec.mPFnPlanes); tOut1.Branch("rec.mPFp0nAssign",&rec.mPFp0nAssign); tOut1.Branch("rec.mPFp1nAssign",&rec.mPFp1nAssign); tOut1.Branch("rec.nHitMPF",&rec.nHitMPF) ; tOut1.Branch("rec.coreFiduScale",&rec.coreFiduScale); tOut1.Branch("rec.coreFiduScaleOR",&rec.coreFiduScaleOR) ; tOut1.Branch("rec.coreLoc",&rec.coreLoc) ; tOut1.Branch("rec.zenithAngle",&rec.zenithAngle) ; tOut1.Branch("rec.azimuthAngle",&rec.azimuthAngle) ; tOut1.Branch("rec.dec",&rec.dec) ; tOut1.Branch("rec.ra",&rec.ra) ; tOut1.Branch("rec.planeChi2",&rec.planeChi2) ; tOut1.Branch("rec.coreX",&rec.coreX) ; tOut1.Branch("rec.coreY",&rec.coreY) ; tOut1.Branch("rec.logCoreAmplitude",&rec.logCoreAmplitude) ; tOut1.Branch("rec.coreFitUnc",&rec.coreFitUnc) ; tOut1.Branch("rec.logNNEnergy",&rec.logNNEnergy) ; tOut1.Branch("rec.fAnnulusCharge0",&rec.fAnnulusCharge0); tOut1.Branch("rec.fAnnulusCharge1",&rec.fAnnulusCharge1); tOut1.Branch("rec.fAnnulusCharge2",&rec.fAnnulusCharge2); tOut1.Branch("rec.fAnnulusCharge3",&rec.fAnnulusCharge3); tOut1.Branch("rec.fAnnulusCharge4",&rec.fAnnulusCharge4); tOut1.Branch("rec.fAnnulusCharge5",&rec.fAnnulusCharge5); tOut1.Branch("rec.fAnnulusCharge6",&rec.fAnnulusCharge6); tOut1.Branch("rec.fAnnulusCharge7",&rec.fAnnulusCharge7); tOut1.Branch("rec.fAnnulusCharge8",&rec.fAnnulusCharge8); tOut1.Branch("rec.protonlheEnergy",&rec.protonlheEnergy); tOut1.Branch("rec.protonlheLLH",&rec.protonlheLLH) ; tOut1.Branch("rec.gammalheEnergy",&rec.gammalheEnergy) ; tOut1.Branch("rec.gammalheLLH",&rec.gammalheLLH) ; tOut1.Branch("rec.chargeFiduScale50",&rec.chargeFiduScale50) ; tOut1.Branch("rec.chargeFiduScale70",&rec.chargeFiduScale70) ; tOut1.Branch("rec.chargeFiduScale90",&rec.chargeFiduScale90) ; tOut1.Branch("rec.logMaxPE",&rec.logMaxPE); tOut1.Branch("rec.logNPE",&rec.logNPE) ; tOut1.Branch("rec.CxPE40",&rec.CxPE40) ; tOut1.Branch("rec.CxPE40SPTime",&rec.CxPE40SPTime); tOut1.Branch("rec.LDFAge",&rec.LDFAge) ; tOut1.Branch("rec.LDFAmp",&rec.LDFAmp) ; tOut1.Branch("rec.LDFChi2",&rec.LDFChi2) ; tOut1.Branch("rec.logGP",&rec.logGP) ; tOut1.Branch("rec.mPFp0Weight",&rec.mPFp0Weight); tOut1.Branch("rec.mPFp0toangleFit",&rec.mPFp0toangleFit); tOut1.Branch("rec.mPFp1Weight",&rec.mPFp1Weight) ; tOut1.Branch("rec.mPFp1toangleFit",&rec.mPFp1toangleFit); tOut1.Branch("rec.PINC",&rec.PINC) ; tOut1.Branch("rec.disMax",&rec.disMax) ; tOut1.Branch("rec.TankLHR",&rec.TankLHR) ; tOut1.Branch("rec.LHLatDistFitXmax",&rec.LHLatDistFitXmax) ; tOut1.Branch("rec.LHLatDistFitEnergy",&rec.LHLatDistFitEnergy); tOut1.Branch("rec.LHLatDistFitGoF",&rec.LHLatDistFitGoF) ; tOut1.Branch("rec.probaGBT",&rec.probaGBT) ; // Telescope's Data tOut2.Branch("cal_unix", &tel.cal_unix); tOut2.Branch("DAQ_id", &tel.DAQ_id); // Synchronisation Info Double_t min_miss = 100; // [s] Double_t best_shift = 0.0; // best time shift Double_t timediff_tot; // time difference after best shift - for all events Double_t timediff_passed; // time difference after best shift - for events within TimeDiff_Cut tOut3.Branch("timediff_tot", &timediff_tot); // time diff between neighbor events after shift for all events tOut4.Branch("timediff_passed", &timediff_passed); // time diff between neighbors after shift for sync events tOut5.Branch("min_miss", &min_miss); // mean time diff with best shift tOut5.Branch("best_shift", &best_shift); // best time shift //---------------------------------------------------------------------------- Double_t total_miss = 0.0; // total time difference sum( |t_Hawc(i) - t_HE(i)|) [s] Double_t mean_miss = 0.0; // total_miss/n_Hawc Double_t diff_p = 0.0; Double_t diff_n = 0.0; Double_t diff_min = 0.0; Int_t temp_ind = 0; Int_t last_index = 0; // For the plot Mean Time Difference vs. Time Shift vector gr_tShift, gr_tDiff; Int_t gr_n = (Stop_Shift-Start_Shift)/shift_step; printf("Doing shift match....\n"); // Search for best shift with min. mean timem difference for (Double_t shift = Start_Shift; shift < Stop_Shift; shift += shift_step) { for (Int_t i = first_shift; i < last_shift; i++) { //1. Find the nearest neighbor in vts_HEye to vts_Hawc[i]+shift: while (1) { if(vts_Hawc[i].ts + shift > vts_HEye[last_index + 1].ts) last_index++; else break; } //2. calculate the difference diff_n = vts_Hawc[i].ts+shift - vts_HEye[last_index].ts; diff_p = vts_HEye[last_index+1].ts - vts_Hawc[i].ts-shift; diff_min = diff_n > diff_p ? diff_p : diff_n; //3. Add to total_miss total_miss += diff_min; } mean_miss = total_miss/(last_shift-first_shift); gr_tShift.push_back(shift); gr_tDiff.push_back(mean_miss); if (min_miss > mean_miss) { min_miss = mean_miss; best_shift = shift; } total_miss = 0.0; last_index = 0; } tOut5.Fill(); printf("->Minimum sync miss: %f @ a shift of %fs\n", min_miss, best_shift); TH1F timediff_neighbor("timediff_neighbor","timediff_neighbor",1000,-0.01,0.01); // Shift all events by the found best shift for(Int_t i = first; i < last; i++) { //1. Find the nearest neighbor in vts_HEye to vts_Hawc[i]+best_shift: while(1) { if(vts_Hawc[i].ts + best_shift > vts_HEye[last_index+1].ts) last_index++; else break; } //2. calculate the difference diff_n = vts_Hawc[i].ts + best_shift - vts_HEye[last_index].ts; diff_p = vts_HEye[last_index+1].ts - vts_Hawc[i].ts-best_shift; if (diff_p > diff_n) { diff_min = diff_n; temp_ind = last_index; } else { diff_min = diff_p; temp_ind = last_index+1; } timediff_tot = diff_min; if (diff_min < TimeDiff_Cut) { tHEye.GetEntry(vts_HEye[temp_ind].id); tHawc.GetEntry(vts_Hawc[i].id); tel.cal_unix = vts_HEye[temp_ind].ts; tel.DAQ_id = tel.mRawEvtHeader->GetDAQEvtNumber(); timediff_passed = diff_min; tOut1.Fill(); tOut2.Fill(); tOut4.Fill(); } timediff_neighbor.Fill(diff_min); //Fill historgramm with diff tOut3.Fill(); } //---------------------------Plots and Output files--------------------------- tOut1.Write(); tOut2.Write(); tOut3.Write(); tOut4.Write(); tOut5.Write(); fOut.Close(); TCanvas *c1 = new TCanvas("timediff_shift", "Synchronisation", 1200,800); c1->SetGridx(); c1->SetGridy(); TGraph *gr_shift = new TGraph(gr_n, &gr_tShift[0], &gr_tDiff[0]); gr_shift->SetTitle("Synchronisation"); gr_shift->GetXaxis()->SetTitle("Time Shift [s]"); gr_shift->GetYaxis()->SetTitle("Mean time difference [s]"); gr_shift->Draw(); TCanvas *c2 = new TCanvas("timediff_neighbor", "timediff_neighbor", 1200, 800); c2->SetGridx(); c2->SetGridy(); timediff_neighbor.GetXaxis()->SetTitle("Time Difference [s]"); timediff_neighbor.GetYaxis()->SetTitle("Counts"); timediff_neighbor.DrawClone(); // Write out files TFile fOutPlots(Outpath+"_syncplots.root","RECREATE"); c1->Write(); c2->Write(); fOutPlots.Close(); return 0; }