QA plots for the TPC detector
# imports to write dynamic markdown contents
import os
from IPython.display import display, Markdown, Latex
from IPython.display import HTML
# turn off/on code for the result HTML page
display(Markdown('*For the result HTML page:* '))
HTML('''<script>
code_show=true;
function code_toggle() {
if (code_show){
$('div.input').hide();
$('div.jp-CodeMirrorEditor').hide(); // for newer versions of nbviewer.org
} else {
$('div.input').show();
$('div.jp-CodeMirrorEditor').show(); // for newer versions of nbviewer.org
}
code_show = !code_show
}
$( document ).ready(code_toggle);
</script>
<form action="javascript:code_toggle()"><input type="submit" value="Click here to toggle on/off the raw code."></form>''')
For the result HTML page:
import os.path
# readme file of the macros, available if run under JenkinsCI
# https://github.com/sPHENIX-Collaboration/utilities/blob/master/jenkins/built-test/test-tracking-qa.sh
macro_markdown = 'Fun4All-macros-README.md'
if os.path.isfile(macro_markdown) :
with open(macro_markdown, 'r') as file:
display(Markdown(file.read()))
PYTHIA high $p_T$ tracking QA consists full tracker + reconstruction of events with the default Pythia configuration file. This cfg file has a single hard QCD ccbar event with minimum partonic $p_T$ of 10 GeV and truth jet triggering of $p_T>20$ GeV.
Last a D0->piK filter is applied so the same sample canbe used in D0 reco validation. Please note the calorimeters are disabled to improve execution speed, which also removed some of the correlated albedo background for the tracker.
In addition to the Pythia event, an Upsilon is embedded to probe an agregated tracking resolution.
The source code of the macro can be found at https://github.com/sPHENIX-Collaboration/macros/tree/QA-tracking-pythiajet or comparing it to the master branch.
pyROOT
env check¶import ROOT
OFFLINE_MAIN = os.getenv("OFFLINE_MAIN")
if OFFLINE_MAIN is not None:
display(Markdown(f"via sPHENIX software distribution at `{OFFLINE_MAIN}`"))
via sPHENIX software distribution at /var/lib/jenkins/workspace/sPHENIX/Build-Master-gcc14/build/new/install.1
import subprocess
try:
git_url = \
subprocess.run(['git','remote','get-url','origin'], stdout=subprocess.PIPE)\
.stdout.decode('utf-8').strip()\
.replace('git@github.com:','https://github.com/')
display(Markdown(f"View the source code repository at {git_url}"))
except: # catch *all* exceptions
# well do nothing
pass
View the source code repository at https://github.com/sPHENIX-Collaboration/QA-gallery.git
display(Markdown('Some further details about the QA run, if executed under the Jenkins CI:'))
checkrun_repo_commit = os.getenv("checkrun_repo_commit")
if checkrun_repo_commit is not None:
display(Markdown(f"* The commit being checked is {checkrun_repo_commit}"))
ghprbPullLink = os.getenv("ghprbPullLink")
if ghprbPullLink is not None:
display(Markdown(f"* Link to the pull request: {ghprbPullLink}"))
BUILD_URL = os.getenv("BUILD_URL")
if BUILD_URL is not None:
display(Markdown(f"* Link to the build: {BUILD_URL}"))
git_url_macros = os.getenv("git_url_macros")
sha_macros = os.getenv("sha_macros")
if git_url_macros is not None:
display(Markdown(f"* Git repo for macros: {git_url_macros} , which merges `{sha_macros}` and the QA tracking branch"))
RUN_ARTIFACTS_DISPLAY_URL = os.getenv("RUN_ARTIFACTS_DISPLAY_URL")
if RUN_ARTIFACTS_DISPLAY_URL is not None:
display(Markdown(f"* Download the QA ROOT files: {RUN_ARTIFACTS_DISPLAY_URL}"))
JENKINS_URL = os.getenv("JENKINS_URL")
if JENKINS_URL is not None:
display(Markdown(f"Automatically generated by [sPHENIX Jenkins continuous integration]({JENKINS_URL}) [](https://www.sphenix.bnl.gov/web/) [](https://jenkins.io/)"))
Some further details about the QA run, if executed under the Jenkins CI:
master
and the QA tracking branchAutomatically generated by sPHENIX Jenkins continuous integration
%%cpp -d
#include "QA_Draw_Utility.C"
#include <sPhenixStyle.C>
#include <TFile.h>
#include <TLine.h>
#include <TString.h>
#include <TTree.h>
#include <cassert>
#include <cmath>
%%cpp
SetsPhenixStyle();
TVirtualFitter::SetDefaultFitter("Minuit2");
// test sPHENIX lib load
// gSystem->Load("libg4eval.so");
// test libs
// gSystem->ListLibraries();
sPhenixStyle: Applying nominal settings. sPhenixStyle: ROOT6 mode
%jsroot on
qa_file_name_new = os.getenv("qa_file_name_new")
if qa_file_name_new is None:
qa_file_name_new = "G4sPHENIX_test-tracking-low-occupancy-qa_Event100_Sum10_qa.root"
display(Markdown(f"`qa_file_name_new` env not set. use the default `qa_file_name_new={qa_file_name_new}`"))
qa_file_name_ref = os.getenv("qa_file_name_ref")
if qa_file_name_ref is None:
qa_file_name_ref = "reference/G4sPHENIX_test-tracking-low-occupancy-qa_Event100_Sum10_qa.root"
display(Markdown(f"`qa_file_name_ref` env not set. use the default `qa_file_name_ref={qa_file_name_ref}`"))
elif qa_file_name_ref == 'None':
qa_file_name_ref = None
display(Markdown(f"`qa_file_name_ref` = None and we are set to not to use the reference histograms"))
# qa_file_new = ROOT.TFile.Open(qa_file_name_new);
# assert qa_file_new.IsOpen()
# qa_file_new.ls()
display(Markdown(f"Openning QA file at `{qa_file_name_new}`"))
ROOT.gInterpreter.ProcessLine(f"TFile *qa_file_new = new TFile(\"{qa_file_name_new}\");")
ROOT.gInterpreter.ProcessLine(f"const char * qa_file_name_new = \"{qa_file_name_new}\";")
if qa_file_name_ref is not None:
# qa_file_ref = ROOT.TFile.Open(qa_file_name_ref);
# assert qa_file_ref.IsOpen()
display(Markdown(f"Openning QA reference file at `{qa_file_name_ref}`"))
ROOT.gInterpreter.ProcessLine(f"TFile *qa_file_ref = new TFile(\"{qa_file_name_ref}\");")
ROOT.gInterpreter.ProcessLine(f"const char * qa_file_name_ref = \"{qa_file_name_ref}\";")
else:
ROOT.gInterpreter.ProcessLine(f"TFile *qa_file_ref = nullptr;")
ROOT.gInterpreter.ProcessLine(f"const char * qa_file_name_ref = nullptr;")
Openning QA file at G4sPHENIX_test-tracking_Event550_Sum10_qa.root
Openning QA reference file at reference/G4sPHENIX_test-tracking_Event550_Sum10_qa.root
%%cpp
if (qa_file_new == nullptr)
{
cout <<"Error, can not open QA root file"<<qa_file_name_new<<endl;
exit(1);
}
// list inputs histograms if needed
// qa_file_new ->ls();
//TFile *qa_file_ref = NULL;
//if (qa_file_name_ref)
//{
// qa_file_ref = new TFile(qa_file_name_ref);
//
// if (qa_file_ref == nullptr)
// {
// cout <<"Error, can not open QA root file"<<qa_file_name_ref<<endl;
// exit(1);
// }
//}
%%cpp
//constants
const char *hist_name_prefix = "QAG4SimulationTpc";
static constexpr int nregions_tpc = 3;
%%cpp -d
// utility functions for batch plotting
TCanvas* Draw( TFile* qa_file_new, TFile* qa_file_ref, const TString& hist_name_prefix, const TString& tag )
{
const TString prefix = TString("h_") + hist_name_prefix + TString("_");
auto cv = new TCanvas(
TString("QA_Draw_Tpc_") + tag + TString("_") + hist_name_prefix,
TString("QA_Draw_Tpc_") + tag + TString("_") + hist_name_prefix,
950, 600);
cv->Divide( nregions_tpc, 1 );
for( int region = 0; region < nregions_tpc; ++region )
{
// get histograms
auto hnew = static_cast<TH1*>( qa_file_new->GetObjectChecked( Form( "%s%s_%i", prefix.Data(), tag.Data(), region ), "TH1" ) );
hnew->Scale( 1./hnew->GetEntries() );
hnew->SetMinimum(0);
// reference
auto href = qa_file_ref ? static_cast<TH1*>( qa_file_ref->GetObjectChecked( Form( "%s%s_%i", prefix.Data(), tag.Data(), region ), "TH1" ) ) : nullptr;
if( href )
{
href->Scale( 1./href->GetEntries() );
href->SetMinimum(0);
}
// draw
cv->cd( region+1 );
DrawReference(hnew, href);
auto line = VerticalLine( gPad, 0 );
line->Draw();
}
return cv;
}
TCanvas* Draw_eff( TFile* qa_file_new, TFile* qa_file_ref, const TString& hist_name_prefix, const TString& tag )
{
const TString prefix = TString("h_") + hist_name_prefix + TString("_");
auto cv = new TCanvas(
TString("QA_Draw_Tpc_") + tag + TString("_") + hist_name_prefix,
TString("QA_Draw_Tpc_") + tag + TString("_") + hist_name_prefix,
950, 600);
// get histograms
auto hnew0 = static_cast<TH1*>( qa_file_new->GetObjectChecked( Form( "%s%s_0", prefix.Data(), tag.Data()), "TH1" ) );
auto hnew1 = static_cast<TH1*>( qa_file_new->GetObjectChecked( Form( "%s%s_1", prefix.Data(), tag.Data()), "TH1" ) );
hnew1->Divide(hnew1, hnew0, 1, 1, "B");
hnew1->SetMinimum(0);
// reference
auto href0 = qa_file_ref ? static_cast<TH1*>( qa_file_ref->GetObjectChecked( Form( "%s%s_0", prefix.Data(), tag.Data()), "TH1" ) ) : nullptr;
auto href1 = qa_file_ref ? static_cast<TH1*>( qa_file_ref->GetObjectChecked( Form( "%s%s_1", prefix.Data(), tag.Data()), "TH1" ) ) : nullptr;
if( href0 )
{
href1->Divide(href1, href0, 1, 1, "B");
href1->SetMinimum(0);
}
// draw
DrawReference(hnew1, href1);
auto line = HorizontalLine( gPad, 1 );
line->Draw();
return cv;
}
%%cpp
Draw_eff( qa_file_new, qa_file_ref, hist_name_prefix, "efficiency" ) -> Draw();
KSTestSummary::PushKSTest - Warning - received pValue = 0. Reset to an arbitary small non-zero value (e^(-15))
%%cpp
Draw( qa_file_new, qa_file_ref, hist_name_prefix, "drphi" )-> Draw();
%%cpp
Draw( qa_file_new, qa_file_ref, hist_name_prefix, "rphi_error" )-> Draw();
%%cpp
Draw( qa_file_new, qa_file_ref, hist_name_prefix, "phi_pulls" )-> Draw();
%%cpp
Draw( qa_file_new, qa_file_ref, hist_name_prefix, "dz" )-> Draw();
%%cpp
Draw( qa_file_new, qa_file_ref, hist_name_prefix, "z_error" )-> Draw();
KSTestSummary::PushKSTest - Warning - received pValue = 0. Reset to an arbitary small non-zero value (e^(-15))
%%cpp
Draw( qa_file_new, qa_file_ref, hist_name_prefix, "z_pulls" )-> Draw();
%%cpp
Draw( qa_file_new, qa_file_ref, hist_name_prefix, "clus_size" )-> Draw();
KSTestSummary::PushKSTest - Warning - received pValue = 0. Reset to an arbitary small non-zero value (e^(-15))
%%cpp
Draw( qa_file_new, qa_file_ref, hist_name_prefix, "clus_size_phi" )-> Draw();
%%cpp
Draw( qa_file_new, qa_file_ref, hist_name_prefix, "clus_size_z" )-> Draw();
%%cpp
KSTestSummary::getInstance()->make_summary_txt("QA-Tpc.txt");
This notebook contains 28 KSTets: combined Chi2/nDoF = 809.482 / 56, and combined __p-Value = 4.07261e-134__
%%cpp
KSTestSummary::getInstance()->make_summary_TCanvas() -> Draw();