//Contact Person: Mark Stringer ms711@sussex.ac.uk #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using std::vector; using std::string; namespace RAT { DQLaserballProc::DQLaserballProc() : DataQualityProc("dqlaserballProc") { //Initializing all the variables fDQChecks = NULL; fMinTime=0; fMaxTime=0; fMinQhsLow=0; fMaxQhsLow=0; fMinQhsPeak=0; fMaxQhsPeak=0; fMinQhsHigh=0; fMaxQhsHigh=0; fFitPositionThreshOnCentralAxis=0; fFitPositionThreshOffCentralAxis=0; fMinNHit=0; fMaxNHit=0; fMaxNZero=0; fMaxFullOccupancyMean=0; fMaxFullOccupancySpread=0; fMaxPromptOccupancyMean=0; fMaxPromptOccupancySpread=0; fMaxNBadPMTs=0; fMaxPMTTimeError=0; } DQLaserballProc::~DQLaserballProc() { } void DQLaserballProc::BeginOfRun( DS::Run& run ) { //DQ begin of run DataQualityProc::BeginOfRun( run ); //Getting DB RAT::DU::Utility::Get()->BeginOfRun(); //loading lightpath fLP = RAT::DU::Utility::Get()->GetLightPathCalculator(); //Loading GroupVelocity fGV = RAT::DU::Utility::Get()->GetGroupVelocity(); //Putting PMT position database into arrays fPMTInfo = RAT::DU::Utility::Get()->GetPMTInfo(); //Loading DB checks file fDQChecks = DB::Get()->GetLink( "DQCHECKS", "laserball" ); //Loading limits into variables fMinTime = fDQChecks->GetD("min_time"); fMaxTime = fDQChecks->GetD("max_time"); fMinQhsLow = fDQChecks->GetD("min_qhs_low"); fMaxQhsLow = fDQChecks->GetD("max_qhs_low"); fMinQhsPeak = fDQChecks->GetD("min_qhs_peak"); fMaxQhsPeak = fDQChecks->GetD("max_qhs_peak"); fMinQhsHigh = fDQChecks->GetD("min_qhs_high"); fMaxQhsHigh = fDQChecks->GetD("max_qhs_high"); fMinNHit = fDQChecks->GetI("min_nhit"); fMaxNHit = fDQChecks->GetI("max_nhit"); fMaxNZero = fDQChecks->GetI("max_nzero"); fMaxFullOccupancyMean = fDQChecks->GetD("max_full_occupancy_mean"); fMaxFullOccupancySpread = fDQChecks->GetD("max_full_occupancy_spread"); fMaxPromptOccupancyMean = fDQChecks->GetD("max_prompt_occupancy_mean"); fMaxPromptOccupancySpread = fDQChecks->GetD("max_prompt_occupancy_spread"); fFitPositionThreshOnCentralAxis = fDQChecks->GetD("fit_position_thresh_on_central_axis"); fFitPositionThreshOffCentralAxis = fDQChecks->GetD("fit_position_thresh_off_central_axis"); fMaxNBadPMTs = fDQChecks->GetI("n_bad_pmts"); fMaxPMTTimeError = fDQChecks->GetD("max_time_error"); fCentralAxesX = fDQChecks->GetDArray("urm_ports_x"); fCentralAxesY = fDQChecks->GetDArray("urm_ports_y"); fManipInfo = DB::Get()->GetLink("CALIB_COMMON_RUN_LEVEL" ,"MANIP"); std::vector laserballPositionArray = fManipInfo->GetDArray("position"); fSourceType = fManipInfo->GetS("source_type"); fPositionValid = fManipInfo->GetZ("position_valid"); fLaserballPosition = TVector3(laserballPositionArray[0],laserballPositionArray[1],laserballPositionArray[2]); fLaserballWavelength = fManipInfo->GetD("wavelength"); } //Method to perform all checks and provide user info on whether checks failed or pass as well as setting check flags void DQLaserballProc::SOCAnalysis( DS::SOC& soc ) { info << "DQLaserballProc::SOCAnalysis: avaliable fit names:" << newline; vector fitNames = soc.GetFitNames(); for( vector::iterator iFitName = fitNames.begin(); iFitName != fitNames.end(); iFitName++ ) info << *iFitName << newline; info << "Now Performing Checks"<fMaxNHit){ info << "NHitCheck Failed too many hits NHits: "<fMaxNZero){ info << "NZero Check Failed: Too many unhit PMTs Unhit PMTs: "< qhsInfo = GetQHSInfo(soc); AddToRATDB("peak_qhs_value",qhsInfo[0]); if(qhsInfo[0]>fMaxQhsPeak){ info << "QHS Test Failed: Peak value too high Peak Value: "<fMaxQhsLow){ info << "QHS Test Failed: QHS Low too high Low Value: " <fMaxQhsHigh){ info << "QHS Test Failed: QHS high too high High Value: " < timeCheck = TimeChecks(soc); AddToRATDB("mean_time_residual",timeCheck[0]); if(timeCheck[0]<-10000){ info << "Fit Time Test Failed: Fit Failed"<fMaxTime){ info << "Fit Time Test Failed: Time More than maximum Value fit Time Value: "<fMaxNBadPMTs){ info << "Too many PMTs failing peak time Check NBadPMTs: "<fMaxNBadPMTs){ info << "Too many PMTs failing time Error Check NBadPMTs: "< occ = GetFullOccupancyMeanSpread(soc); Update("lbFullOccupancyMeanCheck",true); Update("lbFullOccupancySpreadCheck",true); AddToRATDB("mean_occupancy",occ[0]); if(occ[0]>fMaxFullOccupancyMean){ info << "Occupancy Test Failed: Mean Full Occupancy too high Mean Occupancy: "<fMaxFullOccupancySpread){ info << "Occupancy Test Failed: Occupancy Full Spread too high Occupancy: "<fMaxPromptOccupancyMean){ info << "Occupancy Test Failed: Mean Prompt Occupancy too high Mean Occupancy: "<fMaxPromptOccupancySpread){ info << "Occupancy Test Failed: Occupancy Prompt Spread too high Occupancy: "< SOCSourceIDs = run.GetSOCSourceIDs(); for( vector::iterator iSOCSourceID = SOCSourceIDs.begin(); iSOCSourceID != SOCSourceIDs.end(); iSOCSourceID++ ) { DS::SOC& soc = run.GetSOCData( *iSOCSourceID ); //Performing laserball check SOCAnalysis( soc ); //DQ end of run for flags DataQualityProc::EndOfRun(run); } } //Number of PMT hits per pulse double DQLaserballProc::GetNHit( DS::SOC& soc){ double nhits = 0; std::vector ids = soc.GetSOCPMTIDs(); //Iterating over all pmts summing up number of hits for(unsigned int i=0; i(nhits)/soc.GetNPulsesTriggered(); } //Number of PMTS with zero hits after entire run int DQLaserballProc::GetNZero(DS::SOC& soc){ int nzero = 0; //Iterating through all PMTs to get number of unhit pmts for(unsigned int i=0; i DQLaserballProc::GetFullOccupancyMeanSpread(DS::SOC& soc ){ //Mean and spread std::vectoroutput(2,0); //Setting up occupancy histo TH1D occupancy("LBDQ_Full_Occupancy_of_the_PMTs","LBDQ_Full_Occupancy_of_the_PMTS",50,0,0.3); //Filling histogram with occupancy for(unsigned int i=0; i DQLaserballProc::GetPromptOccupancyMeanSpread(DS::SOC& soc ){ //Mean and spread std::vectoroutput(2,0); //Setting up occupancy histo TH1D occupancy ("LBDQ_Prompt_Occupancy_of_the_PMTs","LBDQ_Prompt_Occupancy_of_the_PMTS",50,0,0.3); //Filling histogram with occupancy for(unsigned int i=0; i fitNames = soc.GetFitNames(); TVector3 fitpos; for( vector::iterator iFitName = fitNames.begin(); iFitName != fitNames.end(); iFitName++ ){ DS::FitResult fit = soc.GetFitResult(*iFitName); info << "Fit Position threshold is: "<1){ info << "Should only be one vertex"<threshold){ info << " Fit vertex "<< *iFitName << " not close enough to laserball position : FAIL." << newline; info << "Fit Position is: ("< manipPos; manipPos.push_back(fLaserballPosition.X()); manipPos.push_back(fLaserballPosition.Y()); manipPos.push_back(fLaserballPosition.Z()); std::vector fitPosition; fitPosition.push_back(fitpos.X()); fitPosition.push_back(fitpos.Y()); fitPosition.push_back(fitpos.Z()); AddToRATDB("manip_laserball_position",manipPos); AddToRATDB("fit_laserball_position",fitPosition); return true; } //Method to measure time difference between hit time (Shifted for all electronics and TOF) and firing time //returns //>Mean Time offset over all pmts //>Number of PMTS which fail as their peak time falls outside limits //>Number of PMTS which fail as their peak error is too large std::vector DQLaserballProc::TimeChecks(DS::SOC& soc){ double meanTimeFails = 0; double errorTimeFails = 0; //Creating histogram to store peak prompt values TH1D timeHisto ("LBDQ_TimeHisto","LBDQ_TimeHisto",125,-20,20); TH1D pmtTime ("LBDQ_PMT_Mean_Time_Check","LBDQ_PMT_Mean_Time_Check",10000,0,10000); TH1D pmtTimeError ("LBDQ_PMT_Error_Time_Check","LBDQ_PMT_Error_Time_Check",10000,0,10000); //Getting time offset due to electronics double globalTimeOffset = soc.GetGlobalTimeOffset(); //getting wavelength of lb and converting wavelength into mm double wavelength = fLaserballWavelength*1.0e-6; //Getting energy of photons double energy = RAT::util::WavelengthToEnergy(wavelength); //Iterating through PMTs for(unsigned int i=0; ifMaxTime || meanTimefMaxPMTTimeError){ pmtTimeError.SetBinContent(lcn,1.0); errorTimeFails++; } vector tacs = pmt.GetTimes(); for(unsigned int k=0; k-1000){ pmtHisto.Fill(TACtime); timeHisto.Fill(TACtime); } } } } } //Drawing output plot and fitting to gaussian TCanvas c2 ("LBDQ_TimeHistogram"); timeHisto.Fit("gaus"); timeHisto.Draw(); WriteToRoot(&c2); TCanvas c3 ("LBDQ_pmtTimeCrateMap"); TH2D pmtTimeCrateMap = CrateMapFromChannelHisto(pmtTime); pmtTimeCrateMap.Draw("colz"); WriteToRoot(&c3); TH2D pmtTimeErrorCrateMap = CrateMapFromChannelHisto(pmtTimeError); TCanvas c4 ("LBDQ_pmtTimeErrorCrateMap"); pmtTimeErrorCrateMap.Draw("colz"); WriteToRoot(&c4); TF1 * func = timeHisto.GetFunction("gaus"); //Returing mean value of fitted gaussian std::vector output (3,0); output[0] = -10000; if(func!=NULL){ output[0] = func->GetParameter(1); } output[1] = meanTimeFails; output[2] = errorTimeFails; delete func; return output; } //Method to obtain //>The peak value of QHS histogram (QHS Peak) //>The half maximum value on the left side of the peak (QHS Low) //>The half maximum value on the right side of the peak (QHS High) std::vector DQLaserballProc::GetQHSInfo(DS::SOC& soc){ //Loading the QHS Histogram TH1D qhsHisto ("LBDQ_QHS_Histogram","LBDQ_QHS_Histogram",500,0,500); //Filling QHS Histogram for(unsigned int i=0; i qhsVals = pmt.GetQHSs(); for(unsigned int j=0; jSetLineColor(1); peakFunc->Draw("same"); //Getting height of peak (norm) and peak value (mean) double mean = peakFunc->GetParameter(1); double norm = peakFunc->GetParameter(0); int peakBin = qhsHisto.GetXaxis()->FindFixBin(mean); int lowBin = -1; int upBin = 999999; //Getting 25% and 75% bins on left side of peak for(int i=1; i(0.75*norm) && upBin > peakBin) upBin = i-1; if(lowBin < 0 && qhsHisto.GetBinContent(i)>(0.25*norm)) lowBin = i; } //Setting up linear function between the 25% and 75% bins to interpolate and get the 50% value TF1 lowerFunc ("lowerFunc","([1]*x)+[0]",qhsHisto.GetBinCenter(lowBin),qhsHisto.GetBinCenter(upBin)); lowerFunc.SetLineColor(2); //Fitting function qhsHisto.Fit("lowerFunc","+","",qhsHisto.GetBinCenter(lowBin),qhsHisto.GetBinCenter(upBin)); lowerFunc.Draw("same"); //Getting gradient and intercept of function double lowIntercept = lowerFunc.GetParameter(0); double lowGrad = lowerFunc.GetParameter(1); //Rearranging equation to solve for 50% value double qhsLow = (0.5*norm-lowIntercept)/lowGrad; //Now doing the same for the right side of the peak lowBin=-1; upBin = -1; for(int i=peakBin; iGetNbins(); i++){ if(qhsHisto.GetBinContent(i)<(0.75*norm) && lowBin==-1) lowBin = i-1; if(upBin==-1 && qhsHisto.GetBinContent(i)<(0.25*norm)) upBin = i-1; } TF1 upperFunc ("upperFunc","([1]*x)+[0]",qhsHisto.GetBinCenter(lowBin),qhsHisto.GetBinCenter(upBin)); qhsHisto.Fit("upperFunc","+","",qhsHisto.GetBinCenter(lowBin),qhsHisto.GetBinCenter(upBin)); upperFunc.SetLineColor(2); upperFunc.Draw("same"); double upperIntercept = upperFunc.GetParameter(0); double upperGrad = upperFunc.GetParameter(1); double qhsHigh = (0.5*norm-upperIntercept)/upperGrad; std::vectoroutput(3,0); //Outputting peak then low then high output[0] = mean; output[1] = qhsLow; output[2] = qhsHigh; WriteToRoot(&c1); delete peakFunc; return output; } //If channel fails input histobin is set to 1 -> Red In output crate map //If channel passed input histobin -> Blue in output crate map TH2D DQLaserballProc::CrateMapFromChannelHisto(TH1D channelFails){ char histoName [100]; sprintf(histoName,"LBDQ_%s_Crate_Map",channelFails.GetName()); TH2D outputHisto(histoName,histoName,280,0,1,100,0,1); int crateGap = 10; int xOffset = 10; int yOffset = 10; for(unsigned int i=0; i= 9){ ybin += 50; xbin = cardNum+((crateNum-9)*(16+crateGap))+xOffset; } //16 cards per crate int bin = outputHisto.GetBin(xbin,ybin); outputHisto.SetBinContent(bin,channelFails.GetBinContent(i)*10000+1); } outputHisto.SetStats(false); return outputHisto; } int DQLaserballProc::crateNumber(int lcn){ return lcn/512; } int DQLaserballProc::cardNumber(int lcn){ return ((lcn-(512*crateNumber(lcn)))/32); } int DQLaserballProc::channelNumber(int lcn){ return lcn-(32*cardNumber(lcn))-(512*crateNumber(lcn)); } } //namespace RAT