/***************************************************************************** * Project: CMS TOB Silicon Testing * Package: * File: arcs_macro.cc * Authors: * Stephen Levy (SL), levys@slac.stanford.edu * History: * 10-Sep-2003 CM Removed Gain Plots, added PeakTime cuts * 31-Mar-2003 SL Created initial version * 24-Apr-2003 SL Update (major rework) * 31-Apr-2003 SL * Make summary ascii for PeakOn,DecOn * Read in separate cuts for PeakOn,DecOn from single config file * Include pulseheight stats in ascii file * 07-May-2003 SL * Add plots taken in all modes for a given test to one canvas * Reading a recordNum of -1 from configFile means the latest Record * will be used * Change chip numbering convention in summary ascii file (1,512) * * Description: * Macro to make gain, noise, pedestal, pulseheight, pinhole, etc., * plots from a root file created with Aachen ARCS software 6.0 beta * which is used to test CMS TOB silicon modules/hybrids. The ARCS * software may be downloaded from: * http://www.physik.rwth-aachen.de/group/IIIphys/CMS/tracker/en/index.html * * PLEASE NOTE: This macro will _not_ work with ARCS software * versions prior to release 6.0 beta. * * Takes name of configuration ascii file as only required argument. * Format of configuration ascii file is as follows: * * RootFileInfo * * * * * # * PedestalCuts * * PeakOn * * * DecOn * * * # * NoiseCuts * * PeakOn * * * * * DecOn * * * * * # * GainCuts * * PeakOn * * * * * DecOn * * * * * # * PinholeCuts * * PeakOn * * * DecOn * * * # * PulseHeightCuts * * PeakOn * * * DecOn * * * * The macro will search the configuration file for the string * 'RootFileInfo' and then it will proceed to read in 4 lines whose * meaning are specified above. For each set of cuts, the macro looks * for the tag line (eg, 'GainCuts'). Then it reads whether the cuts * will be Absolute or Percentage cuts. It needs to find 'PeakOn' and * the expected cuts and then 'DecOn' and the expected cuts (there are * different numbers of cuts defined for each test). The comment * lines (designated #) are aesthetic only and not required. * * When the same module is tested more than once, the Aachen software * stores the results in separate TDirectories of the same root file * called RecordX, where X is an integer. This integer is supplied in * the fourth line below RootFileInfo in the config file. Using a * value of -1 in this field will retrieve RecordX_{max} where X_{max} * is the largest integer (less than 1000) for which a Record exists. * * Conventions: * The macro looks for noise, gain, pedestal, noise, and pulseheight * plots taken in the PeakInvOn, DecInvOn, PeakInvOff, DecInvOff * mode. It searches for the pinhole test plots taken in the * PeakInvOff mode since this seems to be the only way to take the * test with the arcs 6.0 beta version. Failure to find these hists * should not result in a crash -- just no output plot. * * Specifying a recordNum of -1 causes latest record to be used (see * above). * * Percentage cuts should be specified as a decimal. * * Running: * One can run the macro from a unix command line (assuming root is * installed) as follows: * * unix> root -b -l -q 'arcs_macro_6_1.cc("configTestA.dat","CTA",0)' * * where the example configuration file is named configTestA.dat. * Note that the second argument "CTA" is optional -- it is a string * that will be appended to the ascii output file and hist names for * convenience. The third integer argument is also optional and will * output useful debug information to the screen if it is non-zero. * * Output: * Example of output files when using command line shown above and * reading in root file "module_XXXX.root" which has hists in Record2 * h_pedestal_module_XXXX_Rec2_CTA_pctCut.eps * h_pulseheight_module_XXXX_Rec2_CTA_eps * h_noise_module_XXXX_Rec2_CTA_pctCut.eps * h_gainSlope_module_XXXX_Rec2_CTA_pctCut.eps * h_gainChiSq_module_XXXX_Rec2_CTA_pctCut.eps * h_gainOffset_module_XXXX_Rec2_CTA_pctCut.eps * h_pinhole_module_XXXX_Rec2_CTA_pctCut.eps * Summary_module_XXXX_Rec2_PeakOn_CTA.dat * Summary_module_XXXX_Rec2_DecOn_CTA.dat * * The histogram names may have "pctCut" replaced by "absCut" if * absolute cuts are specified in the configuration file instead of * percentage cuts. * ******************************************************************************/ #include // ------------------ // Global definitions // ------------------ const Int_t nChip(4), nChanPerChip(128); enum modeType{ PeakOn=1, PeakOff=2, DecOn=3, DecOff=4 }; modeType mode; // header vars const char *defChar = "Unknown"; const char *date=defChar; const char *modName=defChar; const char *oper=defChar; const char *testCenter=defChar; const char *swVer=defChar; Int_t recordNum; Double_t yTitleOffset(1.2); // cut vars peak on Double_t minPedCutPk(-999.), maxPedCutPk(-999.); Double_t minNoiseCutPk(-999.), maxNoiseCutPk(-999.); Double_t minPeakTimeCutPk(-999.), maxPeakTimeCutPk(-999.); Double_t minPulseCutPk(-999.), maxPulseCutPk(-999.); Double_t minOneSensNoiseCutPk(-999.), minTwoSensNoiseCutPk(-999.); Double_t minOneSensPeakTimeCutPk(-999.), minTwoSensPeakTimeCutPk(-999.); // cut vars dec on Double_t minPedCutDc(-999.), maxPedCutDc(-999.); Double_t minPulseCutDc(-999.), maxPulseCutDc(-999.); Double_t minOneSensNoiseCutDc(-999.), minTwoSensNoiseCutDc(-999.); Double_t minNoiseCutDc(-999.), maxNoiseCutDc(-999.); Double_t minOneSensPeakTimeCutDc(-999.), minTwoSensPeakTimeCutDc(-999.); Double_t minPeakTimeCutDc(-999.), maxPeakTimeCutDc(-999.); // hist borders Double_t pedHistMin(100.0), pedHistMax(300.); Double_t noiseHistMin(0.0), noiseHistMax(5.0); Double_t peaktimeHistMin(-100.), peaktimeHistMax(20.0); Double_t xMinLab(0.6),yMinLab(0.9),xMaxLab(0.9),yMaxLab(1.0); // arrays to store cut results Int_t pedStatPkOn[nChanPerChip*nChip], pedStatDcOn[nChanPerChip*nChip]; Int_t pedStatPkOff[nChanPerChip*nChip], pedStatDcOff[nChanPerChip*nChip]; Int_t noiStatPkOn[nChanPerChip*nChip], noiStatDcOn[nChanPerChip*nChip]; Int_t noiStatPkOff[nChanPerChip*nChip], noiStatDcOff[nChanPerChip*nChip]; Int_t peaktimeStatPkOn[nChanPerChip*nChip], peaktimeStatDcOn[nChanPerChip*nChip]; Int_t peaktimeStatPkOff[nChanPerChip*nChip], peaktimeStatDcOff[nChanPerChip*nChip]; Int_t pulseStatPkOn[nChanPerChip*nChip], pulseStatDcOn[nChanPerChip*nChip]; Int_t pulseStatPkOff[nChanPerChip*nChip], pulseStatDcOff[nChanPerChip*nChip]; // bad channel type storage Int_t badchan[nChanPerChip*nChip]; Int_t badchanpkoff[nChanPerChip*nChip]; Int_t badchanpkon[nChanPerChip*nChip]; Int_t badchandcoff[nChanPerChip*nChip]; Int_t badchandcon[nChanPerChip*nChip]; // cut strings TString noiseCutType, pedCutType, pulseCutType,peaktimeCutType; // status histograms TH1F h_stat_pkon("h_stat_pkon", "Status peakOn", nChanPerChip*nChip,1.,nChanPerChip*nChip+1.0); TH1F h_stat_pkoff("h_stat_pkoff","Status peakOff",nChanPerChip*nChip,1.,nChanPerChip*nChip+1.0); TH1F h_stat_dcon("h_stat_dcon", "Status decOn", nChanPerChip*nChip,1.,nChanPerChip*nChip+1.0); TH1F h_stat_dcoff("h_stat_dcoff","Status decOff", nChanPerChip*nChip,1.,nChanPerChip*nChip+1.0); // ------------------ // Begin macro // ------------------ lt_macro(const char *configFile="TOB.dat", const char* label="null", Int_t verbose=0) { TStopwatch watch; watch.Start(); initArrays(); // --- open configFile ifstream datafile; datafile.open(configFile); if ( !datafile.good() ) { cout << endl << "arcs_macro: ERROR: configFile " << configFile << " unreadable; ABORT" << endl << endl; return; } char *tagname = "RootFileInfo"; Int_t len=100; Int_t j; char line[100]; Bool_t tag = kFALSE; while(!tag){ if ( datafile.eof() || !datafile.good() ) break ; datafile.getline(line,len); TString fline(line); tag = ( fline.Contains(tagname) ); } TString rootFile, inDir, outDir; TString modeName; // --- read initialization if (tag) { datafile >> inDir ; datafile >> rootFile; datafile >> outDir; datafile >> recordNum; cout << endl; cout << "--- Found tagname '" << tagname << "' in configFile " << configFile << endl; cout << Form("%25s","inDir = ") << inDir << endl; cout << Form("%25s","rootFile = ") << rootFile << endl; cout << Form("%25s","outDir = ") << outDir << endl; cout << Form("%25s","recordNum = ") << recordNum << endl << endl; } else { cout << "arcs_macro: ERROR : Could not find tag " << tagname << " in confileFile " << configFile << ": ABORT" << endl; return; } // --- read PedestalCuts tagname = "PedestalCuts"; tag = kFALSE; while (!tag) { if ( datafile.eof() || !datafile.good() ) break ; datafile.getline(line,len); TString fline(line); tag = ( fline.Contains(tagname) ); } if ( tag ) { datafile >> pedCutType; if ( !isValCutType(pedCutType) ) return; datafile >> modeName; if ( !isValMode(modeName,modeType::PeakOn) ) return; datafile >> minPedCutPk; datafile >> maxPedCutPk; datafile >> modeName; if ( !isValMode(modeName,modeType::DecOn) ) return; datafile >> minPedCutDc; datafile >> maxPedCutDc; if ( verbose==1 ) { cout << "--- Found tagname '" << tagname << "' in configFile " << configFile << endl; cout << Form("%25s","pedCutType = ") << pedCutType.Data() << endl; cout << Form("%25s","minPedCutPk = ") << minPedCutPk << endl; cout << Form("%25s","maxPedCutPk = ") << maxPedCutPk << endl; cout << Form("%25s","minPedCutDc = ") << minPedCutDc << endl; cout << Form("%25s","maxPedCutDc = ") << maxPedCutDc << endl << endl; } } else { cout << "arcs_macro: ERROR : Could not find tag '" << tagname << "' in configFile " << configFile << ": ABORT" << endl; return; } // --- read NoiseCuts tagname = "NoiseCuts"; tag = kFALSE; while (!tag) { if ( datafile.eof() || !datafile.good() ) break ; datafile.getline(line,len); TString fline(line); tag = ( fline.Contains(tagname) ); } if ( tag ) { datafile >> noiseCutType; if ( !isValCutType(noiseCutType) ) return; datafile >> modeName; if ( !isValMode(modeName,modeType::PeakOn) ) return; datafile >> minTwoSensNoiseCutPk; datafile >> minOneSensNoiseCutPk; datafile >> minNoiseCutPk; datafile >> maxNoiseCutPk; datafile >> modeName; if ( !isValMode(modeName,modeType::DecOn) ) return; datafile >> minTwoSensNoiseCutDc; datafile >> minOneSensNoiseCutDc; datafile >> minNoiseCutDc; datafile >> maxNoiseCutDc; if ( verbose==1 ) { cout << "--- Found tagname '" << tagname << "' in configFile " << configFile << endl; cout << Form("%25s","noiseCutType = ") << noiseCutType.Data() << endl; cout << Form("%25s","minTwoSensNoiseCutPk = ") << minTwoSensNoiseCutPk << endl; cout << Form("%25s","minOneSensNoiseCutPk = ") << minOneSensNoiseCutPk << endl; cout << Form("%25s","minNoiseCutPk = ") << minNoiseCutPk << endl; cout << Form("%25s","maxNoiseCutPk = ") << maxNoiseCutPk << endl; cout << Form("%25s","minTwoSensNoiseCutDc = ") << minTwoSensNoiseCutDc << endl; cout << Form("%25s","minOneSensNoiseCutDc = ") << minOneSensNoiseCutDc << endl; cout << Form("%25s","minNoiseCutDc = ") << minNoiseCutDc << endl; cout << Form("%25s","maxNoiseCutDc = ") << maxNoiseCutDc << endl << endl; } } else { cout << "arcs_macro: ERROR : Could not find tag '" << tagname << "' in configFile " << configFile << ": ABORT" << endl; return; } // --- read PeakTimeCuts tagname = "PeakTimeCuts"; tag = kFALSE; while (!tag) { if ( datafile.eof() || !datafile.good() ) break ; datafile.getline(line,len); TString fline(line); tag = ( fline.Contains(tagname) ); } if ( tag ) { datafile >> peaktimeCutType; if ( !isValCutType(peaktimeCutType) ) return; datafile >> modeName; if ( !isValMode(modeName,modeType::PeakOn) ) return; datafile >> minTwoSensPeakTimeCutPk; datafile >> minOneSensPeakTimeCutPk; datafile >> minPeakTimeCutPk; datafile >> maxPeakTimeCutPk; datafile >> modeName; if ( !isValMode(modeName,modeType::DecOn) ) return; datafile >> minTwoSensPeakTimeCutDc; datafile >> minOneSensPeakTimeCutDc; datafile >> minPeakTimeCutDc; datafile >> maxPeakTimeCutDc; if ( verbose==1 ) { cout << "--- Found tagname '" << tagname << "' in configFile " << configFile << endl; cout << Form("%25s","peaktimeCutType = ") << peaktimeCutType.Data() << endl; cout << Form("%25s","minTwoSensPeakTimeCutPk = ") << minTwoSensPeakTimeCutPk << endl; cout << Form("%25s","minOneSensPeakTimeCutPk = ") << minOneSensPeakTimeCutPk << endl; cout << Form("%25s","minPeakTimeCutPk = ") << minPeakTimeCutPk << endl; cout << Form("%25s","maxPeakTimeCutPk = ") << maxPeakTimeCutPk << endl; cout << Form("%25s","minTwoSensPeakTimeCutDc = ") << minTwoSensPeakTimeCutDc << endl; cout << Form("%25s","minOneSensPeakTimeCutDc = ") << minOneSensPeakTimeCutDc << endl; cout << Form("%25s","minPeakTimeCutDc = ") << minPeakTimeCutDc << endl; cout << Form("%25s","maxPeakTimeCutDc = ") << maxPeakTimeCutDc << endl << endl; } } else { cout << "arcs_macro: ERROR : Could not find tag '" << tagname << "' in configFile " << configFile << ": ABORT" << endl; return; } // --- read PulseHeightCuts tagname = "PulseHeightCuts"; tag = kFALSE; while (!tag) { if ( datafile.eof() || !datafile.good() ) break ; datafile.getline(line,len); TString fline(line); tag = ( fline.Contains(tagname) ); } if ( tag ) { datafile >> pulseCutType; if ( !isValCutType(pulseCutType) ) return; datafile >> modeName; if ( !isValMode(modeName,modeType::PeakOn) ) return; datafile >> minPulseCutPk; datafile >> maxPulseCutPk; datafile >> modeName; if ( !isValMode(modeName,modeType::DecOn) ) return; datafile >> minPulseCutDc; datafile >> maxPulseCutDc; if ( verbose==1 ) { cout << "--- Found tagname '" << tagname << "' in configFile " << configFile << endl; cout << Form("%25s","pulseCutType = ") << pulseCutType.Data() << endl; cout << Form("%25s","minPulseCutPk = ") << minPulseCutPk << endl; cout << Form("%25s","maxPulseCutPk = ") << maxPulseCutPk << endl; cout << Form("%25s","minPulseCutDc = ") << minPulseCutDc << endl; cout << Form("%25s","maxPulseCutDc = ") << maxPulseCutDc << endl << endl; } } else { cout << "arcs_macro: ERROR : Could not find tag '" << tagname << "' in configFile " << configFile << ": ABORT" << endl; return; } // -- open root file const char *filename = Form("%s/%s",inDir.Data(),rootFile.Data()); if ( rootFile.Contains(".root") ) rootFile.ReplaceAll(".root",""); TFile inf(filename); if ( gDirectory->GetListOfKeys()->GetSize() == 0 ) { cout << "arcs_macro: ERROR : No TKeys found in root file " << filename << endl; return; } // --- Record, PeakInvOn, DecInvOn dir if ( recordNum == -1 ) recordNum = getMaxRecord(); TDirectory *rec_dir = (TDirectory*) inf.Get(Form("Record%d",recordNum)); cout << "Searching " << Form("Record%d",recordNum) << " for histograms." << endl << endl; if ( !rec_dir ) { cout << "arcs_macro: ERROR : Unable to find Record" << recordNum << " in root file " << filename << endl << " Must be a config error." << endl << " ABORTING." << endl << endl; return; } TDirectory *pkInvOn_dir = (TDirectory*) rec_dir->Get("PeakInvOn"); TDirectory *dcInvOn_dir = (TDirectory*) rec_dir->Get("DecInvOn"); TDirectory *pkInvOff_dir = (TDirectory*) rec_dir->Get("PeakInvOff"); TDirectory *dcInvOff_dir = (TDirectory*) rec_dir->Get("DecInvOff"); TDirectory *header_dir = (TDirectory*) rec_dir->Get("Header"); TDirectory *summary_dir = (TDirectory*) rec_dir->Get("Summary"); // -- Read header configuration if ( !header_dir ) { cout << "arcs_macro: ERROR : Unable to find Header sub-directory." << endl << " Documentation will be incomplete." << endl << endl; } else { if (header_dir->Get("Date_C")) { date = (header_dir->Get("Date_C"))->GetName();} if (header_dir->Get("Object_C")){ modName = (header_dir->Get("Object_C"))->GetName();} if (header_dir->Get("Operator_C")){ oper = (header_dir->Get("Operator_C"))->GetName();} if (header_dir->Get("Version_C")) { swVer = (header_dir->Get("Version_C"))->GetName();} if (header_dir->Get("TestCenter_C")){ testCenter = (header_dir->Get("TestCenter_C"))->GetName();} } if ( !summary_dir ) { cout << "arcs_macro: ERROR : Unable to find Header sub-directory." << endl << " Documentation will be incomplete." << endl << endl; } else { if (summary_dir->Get("TNmodid")) { modName = (summary_dir->Get("TNmodid"))->GetName();} } // --- PeakInvOn Subdirectories TDirectory *ped_pkon_dir, *noi_pkon_dir,*pulse_pkon_dir; if ( !pkInvOn_dir ) { cout << "arcs_macro: WARNING : Unable to find PeakInvOn sub-directory." << endl << " Skip it. Some output will be missing." << endl << endl; } else { ped_pkon_dir = (TDirectory*) pkInvOn_dir->Get("Pedestal"); noi_pkon_dir = (TDirectory*) pkInvOn_dir->Get("Noise"); pulse_pkon_dir = (TDirectory*) pkInvOn_dir->Get("PulseShape"); } // --- PeakInvOff Subdirectories TDirectory *ped_pkoff_dir, *noi_pkoff_dir,*pulse_pkoff_dir; if ( !pkInvOff_dir ) { cout << "arcs_macro: WARNING : Unable to find PeakInvOff sub-directory." << endl << " Skip it. Some output will be missing." << endl << endl; } else { ped_pkoff_dir = (TDirectory*) pkInvOff_dir->Get("Pedestal"); noi_pkoff_dir = (TDirectory*) pkInvOff_dir->Get("Noise"); pulse_pkoff_dir = (TDirectory*) pkInvOff_dir->Get("PulseShape"); } // --- DecInvOn Subdirectories TDirectory *ped_dcon_dir, *noi_dcon_dir, *pulse_dcon_dir; if ( !dcInvOn_dir ) { cout << "arcs_macro: WARNING : Unable to find DecInvOn sub-directory." << endl << " Skip it. Some output will be missing." << endl << endl; } else { ped_dcon_dir = (TDirectory*) dcInvOn_dir->Get("Pedestal"); noi_dcon_dir = (TDirectory*) dcInvOn_dir->Get("Noise"); pulse_dcon_dir = (TDirectory*) dcInvOn_dir->Get("PulseShape"); } // --- DecInvOff Subdirectories TDirectory *ped_dcoff_dir, *noi_dcoff_dir, *pulse_dcoff_dir; if ( !dcInvOff_dir ) { cout << "arcs_macro: WARNING : Unable to find DecInvOff sub-directory." << endl << " Skip it. Some output will be missing." << endl << endl; } else { ped_dcoff_dir = (TDirectory*) dcInvOff_dir->Get("Pedestal"); noi_dcoff_dir = (TDirectory*) dcInvOff_dir->Get("Noise"); pulse_dcoff_dir = (TDirectory*) dcInvOff_dir->Get("PulseShape"); } // -- Canvas for all plots TCanvas can("can","can",1200,1200); can.Range(0,0,25,25); TPaveLabel canHeader(5,23.5,20,24.5,Form("%s; Record%d; %s",modName,recordNum,date),"br"); canHeader.SetFillColor(18); TPad pad1("pad1","pad1",0.02,0.49,0.48,0.92); TPad pad2("pad2","pad2",0.52,0.49,0.98,0.92); TPad pad3("pad3","pad3",0.02,0.02,0.48,0.45); TPad pad4("pad4","pad4",0.52,0.02,0.98,0.45); pad1.Draw(); pad2.Draw(); pad3.Draw(); pad4.Draw(); TPaveText pkOnLabel(xMinLab,yMinLab,xMaxLab,yMaxLab,"ndc"); pkOnLabel->AddText("Peak InvOn"); pkOnLabel->SetTextColor(2); TPaveText pkOffLabel(xMinLab,yMinLab,xMaxLab,yMaxLab,"ndc"); pkOffLabel->AddText("Peak InvOff"); pkOffLabel->SetTextColor(2); TPaveText dcOnLabel(xMinLab,yMinLab,xMaxLab,yMaxLab,"ndc"); dcOnLabel->AddText("Dec InvOn"); dcOnLabel->SetTextColor(2); TPaveText dcOffLabel(xMinLab,yMinLab,xMaxLab,yMaxLab,"ndc"); dcOffLabel->AddText("Dec InvOff"); dcOffLabel->SetTextColor(2); char *histType; TString outputName; char *cutType = "absCut"; canHeader.Draw(); // --- plot peaktime histType = "peaktime"; cutType="pctCut"; outputName = Form("%s/h_%s_%s_Rec%d_%s_%s.eps",outDir.Data(),histType,rootFile.Data(),recordNum,cutType,label); pad1.cd(); if ( pulse_pkon_dir ) plotPeakTime(pulse_pkon_dir,"PeakOn", &h_stat_pkon); pkOnLabel->Draw(); pad2.cd(); if ( pulse_pkoff_dir ) plotPeakTime(pulse_pkoff_dir,"PeakOff", &h_stat_pkoff); pkOffLabel->Draw(); pad3.cd(); if ( pulse_dcon_dir ) plotPeakTime(pulse_dcon_dir,"DecOn", &h_stat_dcon); dcOnLabel->Draw(); pad4.cd(); if ( pulse_dcoff_dir ) plotPeakTime(pulse_dcoff_dir,"DecOff", &h_stat_dcoff); dcOffLabel->Draw(); can.Update(); can.SaveAs(outputName); clearPads(pad1,pad2,pad3,pad4); resetStatHists(); // --- plot pedestal histType = "pedestal"; if ( !pedCutType.CompareTo("Percentage") ) cutType="pctCut"; outputName = Form("%s/h_%s_%s_Rec%d_%s_%s.eps",outDir.Data(),histType,rootFile.Data(),recordNum,cutType,label); pad1.cd(); if ( ped_pkon_dir ) plotPedestal(ped_pkon_dir,"PeakOn", &h_stat_pkon); pkOnLabel->Draw(); pad2.cd(); if ( ped_pkoff_dir ) plotPedestal(ped_pkoff_dir,"PeakOff", &h_stat_pkoff); pkOffLabel->Draw(); pad3.cd(); if ( ped_dcon_dir ) plotPedestal(ped_dcon_dir,"DecOn", &h_stat_dcon); dcOnLabel->Draw(); pad4.cd(); if ( ped_dcoff_dir ) plotPedestal(ped_dcoff_dir,"DecOff", &h_stat_dcoff); dcOffLabel->Draw(); can.Update(); can.SaveAs(outputName); clearPads(pad1,pad2,pad3,pad4); resetStatHists(); // --- plot pulseshape histType = "pulseheight"; if ( !pulseCutType.CompareTo("Percentage") ) cutType="pctCut"; outputName = Form("%s/h_%s_%s_Rec%d_%s_%s.eps",outDir.Data(),histType,rootFile.Data(),recordNum,cutType,label); pad1.cd(); if ( pulse_pkon_dir ) plotPulseHeight(pulse_pkon_dir,"PeakOn", &h_stat_pkon); pkOnLabel->Draw(); pad2.cd(); if ( pulse_pkoff_dir ) plotPulseHeight(pulse_pkoff_dir,"PeakOff", &h_stat_pkoff); pkOffLabel->Draw(); pad3.cd(); if ( pulse_dcon_dir ) plotPulseHeight(pulse_dcon_dir,"DecOn",&h_stat_dcon); dcOnLabel->Draw(); pad4.cd(); if ( pulse_dcoff_dir ) plotPulseHeight(pulse_dcoff_dir,"DecOff", &h_stat_dcoff); dcOffLabel->Draw(); can.Update(); can.SaveAs(outputName); clearPads(pad1,pad2,pad3,pad4); resetStatHists(); // --- plot noise histType = "noise"; outputName = Form("%s/h_%s_%s_Rec%d_%s_%s.eps",outDir.Data(),histType,rootFile.Data(),recordNum,cutType,label); if ( !noiseCutType.CompareTo("Percentage") ) cutType="pctCut"; pad1->cd(); if ( noi_pkon_dir ) plotNoise(noi_pkon_dir, "PeakOn", &h_stat_pkon); pkOnLabel->Draw(); pad2->cd(); if ( noi_pkoff_dir ) plotNoise(noi_pkoff_dir, "PeakOff", &h_stat_pkoff); pkOffLabel->Draw(); pad3->cd(); if ( noi_dcon_dir ) plotNoise(noi_dcon_dir, "DecOn", &h_stat_dcon); dcOnLabel->Draw(); pad4->cd(); if ( noi_dcoff_dir ) plotNoise(noi_dcoff_dir, "DecOff", &h_stat_dcoff); dcOffLabel->Draw(); can.Update(); can.SaveAs(outputName); clearPads(pad1,pad2,pad3,pad4); resetStatHists(); // --- create output summary file char *ofileNamePkOn = Form("%s/Summary_%s_Rec%d_PeakOn_%s.dat",outDir.Data(),rootFile.Data(),recordNum,label); char *ofileNameDcOn = Form("%s/Summary_%s_Rec%d_DecOn_%s.dat",outDir.Data(),rootFile.Data(),recordNum,label); char *ofileNamePkOff = Form("%s/Summary_%s_Rec%d_PeakOff_%s.dat",outDir.Data(),rootFile.Data(),recordNum,label); char *ofileNameDcOff = Form("%s/Summary_%s_Rec%d_DecOff_%s.dat",outDir.Data(),rootFile.Data(),recordNum,label); ofstream outFilePkOn(ofileNamePkOn, ios::out); ofstream outFileDcOn(ofileNameDcOn, ios::out); ofstream outFilePkOff(ofileNamePkOff, ios::out); ofstream outFileDcOff(ofileNameDcOff, ios::out); if ( outFilePkOn.bad() ) { cout << "arcs_macro : ERROR : Unable to open output file " << ofileNamePkOn << endl << " ABORT." << endl; return; } if ( outFileDcOn.bad() ) { cout << "arcs_macro : ERROR : Unable to open output file " << ofileNameDcOn << endl << " ABORT." << endl; return; } if ( outFilePkOff.bad() ) { cout << "arcs_macro : ERROR : Unable to open output file " << ofileNamePkOn << endl << " ABORT." << endl; return; } if ( outFileDcOff.bad() ) { cout << "arcs_macro : ERROR : Unable to open output file " << ofileNameDcOn << endl << " ABORT." << endl; return; } printHeader(modeType::PeakOn, configFile, outFilePkOn); outFilePkOn << endl << endl << endl; printSummary(modeType::PeakOn, outFilePkOn); outFilePkOn.close(); for (j=0;j= 10 ) { counter = 0; ++deca; if ( deca >= 10 ) { deca = 0; ++hecto; } } } os << digiStream << endl; return; } void printStat(ofstream& os, TString label, Int_t chipNum, modeType mode, Bool_t isFirstHalf=kTRUE) { Int_t ind,j; Int_t offset = chipNum*nChanPerChip; Int_t lowBound = offset; Int_t highBound = nChanPerChip/2 + offset; if ( !isFirstHalf ) { lowBound=nChanPerChip/2 + offset; highBound=nChanPerChip + offset; } Int_t *noiPtr, *pedPtr, *pulsPtr,*peaktimePtr; switch (mode) { case PeakOn: noiPtr = noiStatPkOn; pedPtr = pedStatPkOn; pulsPtr = pulseStatPkOn; peaktimePtr = peaktimeStatPkOn; break; case PeakOff: noiPtr = noiStatPkOff; pedPtr = pedStatPkOff; pulsPtr = pulseStatPkOff; peaktimePtr = peaktimeStatPkOff; break; case DecOn: noiPtr = noiStatDcOn; pedPtr = pedStatDcOn; pulsPtr = pulseStatDcOn; peaktimePtr = peaktimeStatDcOn; break; case DecOff: noiPtr = noiStatDcOff; pedPtr = pedStatDcOff; pulsPtr = pulseStatDcOff; peaktimePtr = peaktimeStatDcOff; break; default: cout << "arcs_macro : PrintStat : modeType " << mode << " is not used for ascii file output" << endl << " Unable to generate proper output." << endl; break; } noiPtr+=lowBound; pedPtr+=lowBound; pulsPtr+=lowBound;peaktimePtr+=lowBound; for (ind=lowBound;indGet("Pedestal"); if ( !h_ped ) { cout << "arcs_macro::plotPedestal: WARNING : dir " << dir->GetName() << " is missing plot(s) Pedestal" << endl; return; } h_ped->SetMinimum(pedHistMin); h_ped->SetMaximum(pedHistMax); // --- channel status determination calcChipAvg(h_ped,pedChipAvg); for (j=0;jGetYaxis()->SetTitleOffset(yTitleOffset); h_ped->Draw(); h_stat->SetLineColor(kRed); h_stat->SetFillColor(kRed); h_stat->Draw("same"); drawCutLines(nChanPerChip,maxCut,minCut); drawChipLines(nChanPerChip,pedHistMin,pedHistMax); return; } void plotPulseHeight( TDirectory *dir, TString outName, TH1F* h_stat ) { if ( !dir ) { cout << "arcs_macro::plotPulseHeight: WARNING : directory not found" << endl; return; } Int_t j; Double_t minCut[nChip], maxCut[nChip]; Double_t pulseChipAvg[nChip]; TH1* h_pulse = (TH1*) dir->Get("PulseHeight"); if ( !h_pulse ) { cout << "arcs_macro::plotPulseHeight: WARNING : dir " << dir->GetName() << " is missing plot(s) PulseHeight" << endl; return; } Double_t sign = h_pulse->GetMinimum(); // --- channel status determination calcChipAvg(h_pulse,pulseChipAvg); for (j=0;jGetYaxis()->SetTitleOffset(yTitleOffset); h_pulse->Draw(); h_stat->SetLineColor(kRed); h_stat->SetFillColor(kRed); if ( sign < 0 ) h_stat->Draw("esame"); else h_stat->Draw("same"); drawCutLines(nChanPerChip,maxCut,minCut); drawChipLines(nChanPerChip,h_pulse->GetMinimum(),h_pulse->GetMaximum()); return; } void plotNoise( TDirectory *dir, TString outName, TH1F *h_stat ) { Int_t i,j; Double_t noiChipAvg[nChip]; // --- sanity checks if ( !dir ) { cout << "arcs_macro::plotNoise: WARNING : directory not found" << endl; return; } TH1* h_noi_raw = (TH1*) dir->Get("RawNoise"); TH1* h_noi_cms = (TH1*) dir->Get("CMSubtractedNoise"); if ( !h_noi_raw || !h_noi_cms ) { cout << "arcs_macro::plotNoise: WARNING : dir " << dir->GetName() << " is missing plot(s) RawNoise, CMSubtractedNoise" << endl; return; } h_noi_raw->SetMinimum(noiseHistMin); h_noi_raw->SetMaximum(noiseHistMax); // --- calculate avg noise calcChipAvg(h_noi_cms,noiChipAvg); // --- get cut values Double_t maxCut[nChip], minCut[nChip], minOSCut[nChip], minTSCut[nChip]; for (j=0;jSetLineColor(kRed); h_noi_raw->GetYaxis()->SetTitleOffset(yTitleOffset); h_noi_raw->Draw(); h_noi_cms->SetLineColor(kBlue); h_noi_cms->Draw("same"); h_stat->SetLineColor(kRed); h_stat->SetFillColor(kRed); h_stat->Draw("same"); drawCutLines(nChanPerChip,maxCut,minCut,minOSCut,minTSCut ); drawChipLines(nChanPerChip,noiseHistMin,noiseHistMax); TLegend *text = new TLegend(0.2,0.75,0.5,0.85); text->SetFillColor(0); text->AddEntry(h_noi_raw,"Raw Noise","l"); text->AddEntry(h_noi_cms,"CMS Noise","l"); text->SetTextSize(0.05); text->SetTextAlign(11); text->Draw("same"); return; } void plotPeakTime( TDirectory *dir, TString outName, TH1F *h_stat ) { const Int_t nChip(4), nChanPerChip(128); Int_t i,j; Double_t peaktimeChipAvg[nChip]; TH1F* h_peaktimeave; h_peaktimeave = new TH1F("h_peaktimeave","Averaged Rise Time",nChanPerChip*nChip,0.5,nChanPerChip*nChip+0.5); TH1F* h_peaktimeavesub; h_peaktimeavesub = new TH1F("h_peaktimeavesub","Ave Sub Peak Time",nChanPerChip*nChip,0.5,nChanPerChip*nChip+0.5); // --- sanity checks if ( !dir ) { cout << "arcs_macro::plotNoise: WARNING : directory not found" << endl; return; } TH1* h_peaktime = (TH1*) dir->Get("RiseTime"); if ( !h_peaktime ) { cout << "arcs_macro::plotPeakTime: WARNING : dir " << dir->GetName() << " is missing plot(s) PeakTime" << endl; return; } // --- calculate avg peaktime calcChipAvg(h_peaktime,peaktimeChipAvg); for (j=1;jFill(j+i*nChanPerChip,-1.*peaktimeChipAvg[i]); }} h_peaktimeavesub->Add(h_peaktime,h_peaktimeave,1.,1.); h_peaktimeavesub->SetMinimum(peaktimeHistMin); h_peaktimeavesub->SetMaximum(peaktimeHistMax); // --- get cut values Double_t maxCut[nChip], minCut[nChip], minOSCut[nChip], minTSCut[nChip]; for (j=0;jSetLineColor(kBlack); h_peaktimeavesub->GetYaxis()->SetTitleOffset(yTitleOffset); h_peaktimeavesub->Draw(); h_stat->SetLineColor(kRed); h_stat->SetFillColor(kRed); h_stat->Draw("same"); drawCutLines(nChanPerChip,maxCut,minCut,minOSCut,minTSCut ); drawChipLines(nChanPerChip,peaktimeHistMin,peaktimeHistMax); return; } void calcChipAvg( const TH1* hist, Double_t chipAvg[], Int_t verbose=0) { Int_t i,j; for (j=0;jGetBinContent(channel+1); sum += hval; sumSq += sum*sum; } chipAvg[j]=sum/nChanPerChip; if ( verbose ) cout << "avg for chip " << j << " = " << chipAvg[j] << endl; } return; } void calcNGStatus( const TH1* hist, TH1F *h_stat, Int_t status[], Double_t maxCut[], Double_t minCut[], Double_t minOSCut[]=0, Double_t minTSCut[]=0, Int_t verbose=0 ) { Double_t peaktimeChipAvg[nChip]; Double_t histMin = hist->GetMinimum(); Double_t histMax = hist->GetMaximum(); if ( verbose ) { cout << "histMin = " << histMin << endl; cout << "histMax = " << histMax << endl; } Bool_t isNoise=kFALSE; Bool_t isPeakTime=kFALSE; TString hName(hist->GetName()) ; if ( hName.Contains("noise") ) isNoise=kTRUE; if ( hName.Contains("calPTrise") ) isPeakTime=kTRUE; Int_t i,j; for (j=0;jSetBinContent(channel+1,0.); Double_t val = hist->GetBinContent(channel+1); TString hName(hist->GetName()) ; if ( isNoise ) { histMin=0.; histMax=3.; if ( val > maxCut[j] ) status[channel]=4; // high noise else if ( val < minCut[j] && val > minOSCut[j] ) status[channel]=1; // one sensor unbonded noise else if ( val < minOSCut[j] && val > minTSCut[j] ) status[channel]=2; // two sensor unbonded noise else if ( val < minTSCut[j] ) status[channel]=3; // low noise (ph?) } elseif ( isPeakTime ) { calcChipAvg(hist,peaktimeChipAvg); histMin=-100.; histMax=200. ; if ( val-peaktimeChipAvg[j] > maxCut[j] ) status[channel]=4; // high peaktime else if ( val-peaktimeChipAvg[j] < minCut[j] && val-peaktimeChipAvg[j] > minOSCut[j] ) status[channel]=1; // one sensor unbonded peaktime else if ( val-peaktimeChipAvg[j] < minOSCut[j] && val-peaktimeChipAvg[j] > minTSCut[j] ) status[channel]=2; // two sensor unbonded peaktime else if ( val-peaktimeChipAvg[j] < minTSCut[j] ) status[channel]=3; // low peaktime (ph?) } else { cout << "calcNGStatus : ERROR : histogram name " << hist->GetName() << " not expected!" << endl << " ABORT calculation" << endl; return; } if ( status[channel]!=0 ) { Double_t statFillVal = histMin+0.07*fabs(histMax-histMin); Double_t statFillErr = 0.07*fabs(histMax-histMin); h_stat->SetBinContent(channel+1,statFillVal); h_stat->SetBinError(channel+1,statFillErr); if ( verbose ) cout << "arcs_macro::calcNGStatus : set bin content " << channel+1 << " = " << statFillVal << " +- " << statFillErr << endl; } } // channel loop } // chip loop } void calcStatus( const TH1* hist, Double_t chipAvg[], Int_t chanStatus[], Double_t minCut[], Double_t maxCut[], TH1F *h_stat, Int_t verbose=0) { Int_t i,j; Double_t histMin = hist->GetMinimum(); Double_t histMax = hist->GetMaximum(); if ( verbose ) { cout << "histMin = " << histMin << endl; cout << "histMax = " << histMax << endl; } for (j=0;jSetBinContent(channel+1,1000); chanStatus[channel]=0; // pass status = 0 Double_t val = hist->GetBinContent(channel+1); if ( val < minCut[j] ) chanStatus[channel]=1; // below min cut failure = 1 if ( val > maxCut[j] ) chanStatus[channel]=2; // above max cut failure = 2 if ( chanStatus[channel]!=0 ) { Double_t statFillVal = histMin+0.07*fabs(histMax-histMin); Double_t statFillErr = 0.07*fabs(histMax-histMin); h_stat->SetBinError(channel+1,statFillErr); h_stat->SetBinContent(channel+1,statFillVal); if ( verbose ) cout << "arcs_macro::calcStatus : set bin content " << channel+1 << " = " << statFillVal << endl; } } } return; } void drawCutLines( const int nChanPerChip, Double_t hCut[], Double_t lCut[], Double_t aCut[]=0, Double_t bCut[]=0, const int lineStyle=2, const char* option="same") { TLine *hCutLine0, *lCutLine0, *hCutLine1, *lCutLine1, *hCutLine2, *lCutLine2, *hCutLine3, *lCutLine3; hCutLine0 = new TLine(0*nChanPerChip+1.0,hCut[0],1*nChanPerChip+1.0,hCut[0]); lCutLine0 = new TLine(0*nChanPerChip+1.0,lCut[0],1*nChanPerChip+1.0,lCut[0]); hCutLine1 = new TLine(1*nChanPerChip+1.0,hCut[1],2*nChanPerChip+1.0,hCut[1]); lCutLine1 = new TLine(1*nChanPerChip+1.0,lCut[1],2*nChanPerChip+1.0,lCut[1]); hCutLine2 = new TLine(2*nChanPerChip+1.0,hCut[2],3*nChanPerChip+1.0,hCut[2]); lCutLine2 = new TLine(2*nChanPerChip+1.0,lCut[2],3*nChanPerChip+1.0,lCut[2]); hCutLine3 = new TLine(3*nChanPerChip+1.0,hCut[3],4*nChanPerChip+1.0,hCut[3]); lCutLine3 = new TLine(3*nChanPerChip+1.0,lCut[3],4*nChanPerChip+1.0,lCut[3]); TLine *aCutLine0, *aCutLine1, *aCutLine2, *aCutLine3; if ( aCut[0] ) { aCutLine0 = new TLine(0*nChanPerChip+1.0,aCut[0],1*nChanPerChip+1.0,aCut[0]); aCutLine1 = new TLine(1*nChanPerChip+1.0,aCut[1],2*nChanPerChip+1.0,aCut[1]); aCutLine2 = new TLine(2*nChanPerChip+1.0,aCut[2],3*nChanPerChip+1.0,aCut[2]); aCutLine3 = new TLine(3*nChanPerChip+1.0,aCut[3],4*nChanPerChip+1.0,aCut[3]); aCutLine0->SetLineStyle(lineStyle); aCutLine0->Draw(option); aCutLine1->SetLineStyle(lineStyle); aCutLine1->Draw(option); aCutLine2->SetLineStyle(lineStyle); aCutLine2->Draw(option); aCutLine3->SetLineStyle(lineStyle); aCutLine3->Draw(option); } TLine *bCutLine0, *bCutLine1, *bCutLine2, *bCutLine3; if ( bCut[0] ) { bCutLine0 = new TLine(0*nChanPerChip+1.0,bCut[0],1*nChanPerChip+1.0,bCut[0]); bCutLine1 = new TLine(1*nChanPerChip+1.0,bCut[1],2*nChanPerChip+1.0,bCut[1]); bCutLine2 = new TLine(2*nChanPerChip+1.0,bCut[2],3*nChanPerChip+1.0,bCut[2]); bCutLine3 = new TLine(3*nChanPerChip+1.0,bCut[3],4*nChanPerChip+1.0,bCut[3]); bCutLine0->SetLineStyle(lineStyle); bCutLine0->Draw(option); bCutLine1->SetLineStyle(lineStyle); bCutLine1->Draw(option); bCutLine2->SetLineStyle(lineStyle); bCutLine2->Draw(option); bCutLine3->SetLineStyle(lineStyle); bCutLine3->Draw(option); } hCutLine0->SetLineStyle(lineStyle); lCutLine0->SetLineStyle(lineStyle); hCutLine1->SetLineStyle(lineStyle); lCutLine1->SetLineStyle(lineStyle); hCutLine2->SetLineStyle(lineStyle); lCutLine2->SetLineStyle(lineStyle); hCutLine3->SetLineStyle(lineStyle); lCutLine3->SetLineStyle(lineStyle); hCutLine0->Draw(option); lCutLine0->Draw(option); hCutLine1->Draw(option); lCutLine1->Draw(option); hCutLine2->Draw(option); lCutLine2->Draw(option); hCutLine3->Draw(option); lCutLine3->Draw(option); return; } void drawChipLines(const int nChanPerChip, Double_t histMin, Double_t histMax, const int lineStyle=3, const char* option="same") { TLine *chip1b, *chip2b, *chip3b; chip1b = new TLine(1*nChanPerChip+1.5,histMin,1*nChanPerChip+1.5,histMax); chip2b = new TLine(2*nChanPerChip+1.5,histMin,2*nChanPerChip+1.5,histMax); chip3b = new TLine(3*nChanPerChip+1.5,histMin,3*nChanPerChip+1.5,histMax); chip1b->SetLineStyle(lineStyle); chip2b->SetLineStyle(lineStyle); chip3b->SetLineStyle(lineStyle); chip1b->Draw(option); chip2b->Draw(option); chip3b->Draw(option); return; } Bool_t isValCutType( TString cutType ) { if ( cutType.CompareTo("Percentage") && cutType.CompareTo("Absolute") ) { cout << "arcs_macro: isValCutType : ERROR : cutType " << cutType.Data() << " not valid" << endl << " Please fix configuration file -- ABORTING." << endl << endl; return kFALSE; } return kTRUE; } Bool_t isValMode( TString modeName, modeType goodMode ) { modeType thisMode = getModeType(modeName); if ( thisMode == goodMode ) return kTRUE; else { cout << "arcs_macro : isValMode : ERROR : modeType " << thisMode << " does not match" << endl << " expected type " << goodMode << " -- ABORT." << endl; return kFALSE; } } void initArrays() { Int_t i; for (i=0;i0;i--) { TObject *rec_obj = gDirectory->Get(Form("Record%d",i)); if ( rec_obj ) { if ( i==nMaxRec ) { cout << "arcs_macro : getMaxRecord : WARNING, latest record found is at maximum : " << nMaxRec << endl << " Perhaps the hardwired limit should be increased." << endl; } return i; } } cout << "arcs_macro : getMaxRecord : Unable to find any records in range [1," << nMaxRec << "]" << endl << " Must be a configuration error. Please fix." << endl; return -1; } void clearPads(TPad &pad1, TPad &pad2, TPad &pad3, TPad &pad4) { pad1.Clear(); pad2.Clear(); pad3.Clear(); pad4.Clear(); return; } void resetStatHists() { h_stat_pkon->Reset("ICE"); h_stat_pkoff->Reset("ICE"); h_stat_dcon->Reset("ICE"); h_stat_dcoff->Reset("ICE"); }