/////////////////////////////////////////////////////////////////////////////
//
// EEezClusterQA
//
// Author: Jason C. Webb <jwebb@iucf.indiana.edu>
//
// EEezClusterQA provides a set of QA histograms which may be filled
// using a single call to EEezClusterQA::Fill(). The arguement of fill
// may either be a pointer to a cluster or a vector of cluster pointers.
//
// The code assumes that the user has set a pointer to the EEsmdProfile
// object, via setSmdProfiler(). An instance of EEezAnalysis should
// also be set, via setAnalysis(), but is not required.
//
/////////////////////////////////////////////////////////////////////////////
#include "EEezClusterQA.h"
#include <TH1F.h>
#include <TH2F.h>
#include <TProfile.h>
#include <TVector3.h>
#include "StEEmcUtil/EEmcGeom/EEmcGeomDefs.h"
#include "StEEmcUtil/StEEmcSmd/EEmcSmdGeom.h"
#ifndef __ROOT__
#include "EEezSectorStats.h"
#endif
#include "EEezTower.h"
#include "EEezStrip.h"
#include "EEezCluster.h"
#include <iostream>
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
ClassImp(EEezClusterQA);
EEezClusterQA::EEezClusterQA( const Char_t *name, const Char_t *title )
: TDirectory( name, title )
{
// Class constructor
m_EEezAnaly = 0;
m_EEsmdProf = 0;
m_EEsmdGeom = EEmcSmdGeom::instance();
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
void EEezClusterQA::Init()
{
// Initialize the class
bookHistograms();
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
void EEezClusterQA::bookHistograms()
{
// Book all QA histograms
cd();
m_XY = new TH2F("m_XY", "Y vs X of clusters",100,-175.,175.,100,-175.,175.);
m_XY_smd = new TH2F("m_XY_smd", "Y vs X of clusters, from SMD response",100,-175.,175.,100,-175.,175.);
m_Energy = new TH1F("m_Energy", "Energy of clusters",100,0.,20.);
m_EcVsEtot = new TH2F("m_EcVsEtot", "Cluster energy vs sector energy sum", 100, 0., 20., 100, 0., 20. );
m_HitStrips[0] = new TH1F("m_HitStripsU", "Frequency plot of hit U strips vs strip index (id-1)",288,0.,288.);
m_HitStrips[1] = new TH1F("m_HitStripsV", "Frequency plot of hit V strips vs strip index (id-1)",288,0.,288.);
m_MipStrips[0] = new TH1F("m_MipStripsU", "Frequency plot of mip U strips vs strip index (id-1)",288,0.,288.);
m_MipStrips[1] = new TH1F("m_MipStripsV", "Frequency plot of mip V strips vs strip index (id-1)",288,0.,288.);
m_Sum9VsEc[0] = new TH2F("m_Sum9VsEcU", "Sum of 9 strips near SMD-U centroid vs E_{cluster}",50,0.,10.,100,0.,100.);
m_Sum9VsEc[1] = new TH2F("m_Sum9VsEcV", "Sum of 9 strips near SMD-V centroid vs E_{cluster}",50,0.,10.,100,0.,100.);
m_Sum5VsEc[0] = new TH2F("m_Sum5VsEcU", "Sum of 9 strips near SMD-U centroid vs E_{cluster}",50,0.,10.,100,0.,100.);
m_Sum5VsEc[1] = new TH2F("m_Sum5VsEcV", "Sum of 9 strips near SMD-V centroid vs E_{cluster}",50,0.,10.,100,0.,100.);
m_SumVsEc[0] = new TH2F("m_SumVsEcU", "Sum of SMD-U strips under seed tower vs E_{cluster}",50,0.,10.,100,0.,100.);
m_SumVsEc[1] = new TH2F("m_SumVsEcV", "Sum of SMD-V strips under seed tower vs E_{cluster}",50,0.,10.,100,0.,100.);
m_SumVsEc_pfx[0] = new TProfile("m_SumVsEcU_pfx", "Mean sum of SMD-U strips under seed tower vs E_{cluster}",50,0.,10.,0.,20000.);
m_SumVsEc_pfx[1] = new TProfile("m_SumVsEcV_pfx", "Mean sum of SMD-V strips under seed tower vs E_{cluster}",50,0.,10.,0.,20000.);
m_Towers = new TH1F("m_Towers", "Tower energy response vs index", 720, 0., 720.);
m_Sum5 = new TH2F("m_Sum5","Sum of 5 strips U vs V",25,0.,100.,25,0.,100.);
m_Sum9 = new TH2F("m_Sum9","Sum of 9 strips U vs V",25,0.,100.,25,0.,100.);
m_Frac5to9[0] = new TH1F("m_Frac5to9U","Ratio of sum of 5 strips to sum of 9 strips",100,0.,1.);
m_Frac5to9[1] = new TH1F("m_Frac5to9V","Ratio of sum of 5 strips to sum of 9 strips",100,0.,1.);
m_Yield = new TH2F("m_Yield","Fit yield U vs V",50,0.,200.,50,0.,200.);
m_Sigma = new TH2F("m_Sigma","Fit sigma U vs V",100,0.,5.,100,0.,5.);
m_RedChi2 = new TH2F("m_RedChi2","#chi^{2}/#nu U vs V",50,0.,20.,50,0.,20.);
m_YieldVsEc[0] = new TH2F("m_YieldVsEcU","Fit yield vs E_{cluster}",100,0.,10.,100,0.,200.);
m_YieldVsEc[1] = new TH2F("m_YieldVsEcV","Fit yield vs E_{cluster}",100,0.,10.,100,0.,200.);
m_YieldToSum[0] = new TH1F("m_YieldToSumU","Ratio of fit yield to sum over seed tower, U",300,0.,3.);
m_YieldToSum[1] = new TH1F("m_YieldToSumV","Ratio of fit yield to sum over seed tower, V",300,0.,3.);
m_FreqBigChi2[0] = new TH1F("m_FreqBigChi2U","Frequency plot of strip with highest #chi^{2}",288,0.,288.);
m_FreqBigChi2[1] = new TH1F("m_FreqBigChi2V","Frequency plot of strip with highest #chi^{2}",288,0.,288.);
m_FreqEmpty[0] = new TH1F("m_FreqEmptyU", "Frequency with which strips show no response near fit, and yield>50 mips",288,0.,288.);
m_FreqEmpty[1] = new TH1F("m_FreqEmptyV", "Frequency with which strips show no response near fit, and yield>50 mips",288,0.,288.);
m_SeedAdc[0] = new TH1F("m_SeedTowerAdc", "Seed-tower ADC spectrum", 1024, 0., 1024. );
m_SeedAdc[1] = new TH1F("m_SeedPre1Adc", "Seed-preshower-1 ADC spectrum",1024,0.,1024. );
m_SeedAdc[2] = new TH1F("m_SeedPre2Adc", "Seed-preshower-2 ADC spectrum",1024,0.,1024. );
m_SeedAdc[3] = new TH1F("m_SeedPostAdc", "Seed-postshower ADC spectrum",1024,0.,1024. );
m_NeighborAdc[0] = new TH1F("m_NeighborTowerAdc", "Neighbor-tower ADC spectrum", 1024, 0., 2048. );
m_NeighborAdc[1] = new TH1F("m_NeighborPre1Adc", "Neighbor-preshower-1 ADC spectrum",1024,0.,2048. );
m_NeighborAdc[2] = new TH1F("m_NeighborPre2Adc", "Neighbor-preshower-2 ADC spectrum",1024,0.,2048. );
m_NeighborAdc[3] = new TH1F("m_NeighborPostAdc", "Neighbor-postshower ADC spectrum",1024,0.,2048. );
m_SumSmd = new TH2F("m_SumSmd","Sum of mips beneath seed tower, U vs V",100,0.,400.,100,0.,400.);
//-- Fit parameters to SMD distributions
const Float_t hmin[] = { 0.,0.,0.,0.,0. };
const Float_t hmax[] = { 500., 288., 5., 1., 5.0 };
for ( Int_t abc = 0; abc < 5; abc++ ) {
TString hname = "m_Parameters["; hname += abc; hname += "]";
TString htitle = "Fit parameter "; htitle += abc;
m_Parameters[abc] = new TH1F(hname,htitle,100,hmin[abc],hmax[abc]);
}
cd(); m_UFail = new TDirectory("UFail","SMD-U profiles which failed a user cut");
cd(); m_VFail = new TDirectory("VFail","SMD-V profiles which passed a user cut");
cd(); m_UPass = new TDirectory("UPass","SMD-U profiles which passed a user cut");
cd(); m_VPass = new TDirectory("VPass","SMD-V profiles which passed a user cut");
cd(); m_UFlag = new TDirectory("UFlag","SMD-U profiles flagged for study");
cd(); m_VFlag = new TDirectory("VFlag","SMD-V profiles flagged for study");
cd("..");
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
void EEezClusterQA::Fill ( EEezCluster *cluster )
{
// Given a pointer to a cluster, fill the QA histograms
assert(cluster);
//-- Get the seed tower for the cluster
EEezTower *seed = cluster -> getSeedTower();
m_SumSmd -> Fill ( seed -> getSumMipV(), seed -> getSumMipU() );
//-- Unit vector pointing towards cluster centroid
TVector3 unit = ( cluster -> getMomentum() ).Unit();
m_XY -> Fill ( kEEmcZSMD * unit.X(), kEEmcZSMD * unit.Y() );
Float_t umean = seed -> getMeanU();
Float_t vmean = seed -> getMeanV();
if ( umean > 0. && vmean > 0. ) {
TVector3 post = m_EEsmdGeom -> getIntersection( seed -> getSector(), (Int_t)umean, (Int_t)vmean );
m_XY_smd -> Fill ( kEEmcZSMD * post.Unit().X(),
kEEmcZSMD * post.Unit().Y() );
}
//-- Energy of the cluster
Float_t eCluster = cluster -> getEnergy();
m_Energy -> Fill ( eCluster );
//-- Sector-based sums (only fill if m_EEezAnaly is not NULL)
//Int_t sector = seed -> getSector();
//----- Hit strips vs index -----
for ( Int_t i = 0; i < seed -> getNUStrips(); i++ ) {
EEezStrip *strip = seed -> getUStrip(i);
if ( strip -> getEnergy() > 0. ) {
m_HitStrips[0] -> Fill( strip -> getIndex() + 0.5 );
m_MipStrips[0] -> Fill( strip -> getIndex() + 0.5,
strip -> getNumMips() );
}
}
for ( Int_t i = 0; i < seed -> getNVStrips(); i++ ) {
EEezStrip *strip = seed -> getVStrip(i);
if ( strip -> getEnergy() > 0. ) {
m_HitStrips[1] -> Fill( strip -> getIndex() + 0.5 );
m_MipStrips[1] -> Fill( strip -> getIndex() + 0.5,
strip -> getNumMips() );
}
}
//-----<<<<< Kludge >>>>>-----
assert(m_EEsmdProf);
//-- Sums over 5 and 9 strips vs cluster energy
TH1F *hsum5U = m_EEsmdProf -> getProfileSum5U(cluster);
TH1F *hsum5V = m_EEsmdProf -> getProfileSum5V(cluster);
TH1F *hsum9U = m_EEsmdProf -> getProfileSum9U(cluster);
TH1F *hsum9V = m_EEsmdProf -> getProfileSum9V(cluster);
//-- Sum over 5 strips (but trap NULL)
Float_t sum5U = (hsum5U!=NULL) ? hsum5U -> GetMaximum() : -1.;
Float_t sum5V = (hsum5V!=NULL) ? hsum5V -> GetMaximum() : -1.;
Float_t sum9U = (hsum9U!=NULL) ? hsum9U -> GetMaximum() : -1.;
Float_t sum9V = (hsum9V!=NULL) ? hsum9V -> GetMaximum() : -1.;
m_Sum5VsEc[0] -> Fill( eCluster, sum5U );
m_Sum5VsEc[1] -> Fill( eCluster, sum5V );
m_Sum9VsEc[0] -> Fill( eCluster, sum9U );
m_Sum9VsEc[1] -> Fill( eCluster, sum9V );
m_Sum5 -> Fill ( sum5V, sum5U );
m_Sum9 -> Fill ( sum9V, sum9U );
m_SumVsEc[0] -> Fill ( eCluster, seed -> getSumMipU() );
m_SumVsEc[1] -> Fill ( eCluster, seed -> getSumMipV() );
m_SumVsEc_pfx[0] -> Fill ( eCluster, seed -> getSumMipU() );
m_SumVsEc_pfx[1] -> Fill ( eCluster, seed -> getSumMipV() );
if ( sum9U > 0. ) {
m_Frac5to9[0] -> Fill ( sum5U/sum9U );
}
if ( sum9V > 0. ) {
m_Frac5to9[1] -> Fill ( sum5V/sum9V );
}
//-- Fit parameters
TF1 *fitU = m_EEsmdProf -> getFitU(cluster);
TF1 *fitV = m_EEsmdProf -> getFitV(cluster);
if ( (fitU != NULL) && (fitV != NULL) ) {
m_Yield -> Fill ( fitV -> GetParameter(0), fitU -> GetParameter(0) );
m_Sigma -> Fill ( fitV -> GetParameter(2), fitU -> GetParameter(2) );
Float_t chi2u = fitU -> GetChisquare();
Float_t chi2v = fitV -> GetChisquare();
Float_t ndfu = fitU -> GetNDF();
Float_t ndfv = fitV -> GetNDF();
if ( ndfu > 0. && ndfv > 0. ) {
m_RedChi2 -> Fill ( chi2v/ndfv, chi2u/ndfu );
}
m_YieldVsEc[0] -> Fill ( eCluster, fitU -> GetParameter(0) );
m_YieldVsEc[1] -> Fill ( eCluster, fitV -> GetParameter(0) );
for ( Int_t abc = 0; abc < 5; abc++ ) {
m_Parameters[abc] -> Fill ( fitU -> GetParameter(abc) );
m_Parameters[abc] -> Fill ( fitV -> GetParameter(abc) );
}
}
//-- Frequency plots for U and V strip having largest chi2
for ( Int_t i = 0; i < 2; i++ ) {
TH1F *chi2strip = (i==0)?
m_EEsmdProf -> getProfileChi2U(cluster):
m_EEsmdProf -> getProfileChi2V(cluster);
TH1F *prof = (i==0)?
m_EEsmdProf -> getProfileU(cluster):
m_EEsmdProf -> getProfileV(cluster);
Float_t yy = prof -> Integral();
if ( !chi2strip ) continue; //------<<<<<< CHECK WITH ASSERT! >>>>>>------
Float_t x = chi2strip -> GetBinCenter( chi2strip -> GetMaximumBin() );
m_FreqBigChi2[i] -> Fill(x);
for ( Int_t j = 1; j <= chi2strip->GetNbinsX(); j++ ) {
Float_t xx = chi2strip->GetBinCenter(j);
if ( chi2strip->GetBinContent(j)==0 &&yy>50.0)
m_FreqEmpty[i] -> Fill(xx);
}
}
// ------- tower, preshower, postshower ADC response -------
for ( Int_t i = 0; i < 4; i++ ) m_SeedAdc[i] -> Fill ( seed -> getAdc(i) );
EEezTowerPtrVec_t neighbors = seed -> getNeighbors();
EEezTowerPtrVecIter_t iter = neighbors.begin();
while ( iter != neighbors.end() ) {
for ( Int_t i = 0; i < 4; i++ )
m_NeighborAdc[i] -> Fill ( (*iter)->getAdc(i) );
iter++;
}
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
void EEezClusterQA::Fill ( EEezClusterPtrVec_t *clusters )
{
// Loop over all clusters in the vector, filling histograms
// from the clusters contained therein.
EEezClusterPtrVecIter_t iter = clusters -> begin();
while ( iter != clusters -> end() ) {
//-- Get a pointer to the cluster, for simplicity
EEezCluster *c = (*iter);
Fill(c);
iter++;
}
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
void EEezClusterQA::pass( EEezCluster *cluster, const Char_t *tag )
{
// Save the SMD profile and associated histograms in a directory
// as an example of a cluster which passed a cut. One should not
// call this on every event, just a subset of the data.
static Int_t npass = 0;
if ( npass++ >= 100 ) return;
m_UPass -> cd();
save( cluster, 0, tag );
m_UPass -> cd("..");
m_VPass -> cd();
save( cluster, 1, tag );
m_VPass -> cd("..");
}
void EEezClusterQA::fail( EEezCluster *cluster, const Char_t *tag )
{
// Save the SMD profile and associated histograms in a directory
// as an example of a cluster which failed a cut. One should not
// call this on every event, just a subset of the data.
static Int_t npass = 0;
if ( npass++ >= 100 ) return;
m_UFail -> cd();
save( cluster, 0, tag );
m_UFail -> cd("..");
m_VFail -> cd();
save( cluster, 1, tag );
m_VFail -> cd("..");
}
void EEezClusterQA::flag( EEezCluster *cluster, const Char_t *tag )
{
// Save the specified cluster in the "flag" directory, just as
// with pass and fail. Here we do not limit ourselves to the
// first 50 clusters. Use with care.
m_UFlag -> cd();
save ( cluster, 0, tag );
m_UFlag -> cd("..");
m_VFlag -> cd();
save ( cluster, 1, tag );
m_VFlag -> cd("..");
}
void EEezClusterQA::save( EEezCluster *cluster, Int_t iuv, const Char_t *tag )
{
// Saves the specified cluster's SMD profile (and other assoicated
// histograms) in the current directory.
//-- Get the specified profile histograms
TH1F *profile = (iuv)?m_EEsmdProf->getProfileV(cluster):m_EEsmdProf->getProfileU(cluster);
TH1F *profsum = (iuv)?m_EEsmdProf->getProfileSum5V(cluster):m_EEsmdProf->getProfileSum5U(cluster);
TH1F *fitinit = (iuv)?m_EEsmdProf->getProfileInitV(cluster):m_EEsmdProf->getProfileInitU(cluster);
//-- Clone them (create new ones in current directory)
TString profile_name;
if ( profile != NULL ) {
profile_name = profile -> GetName();
profile_name.ReplaceAll("hu","smd_u_prof_");
profile_name.ReplaceAll("hv","smd_v_prof_");
if ( tag != "" ) {
profile_name += tag;
profile_name += tag;
}
profile -> Clone( profile_name );
if ( profsum != NULL ) {
profile_name.ReplaceAll("prof","sum5");
profsum -> Clone( profile_name );
}
if ( fitinit != NULL ) {
profile_name.ReplaceAll("sum5","init");
profile_name.ReplaceAll("prof","init");
fitinit -> Clone( profile_name );
}
}
}
void EEezClusterQA::save( TH1F *histo, Int_t iuv, const Char_t *tag )
{
// Saves the specified histogram
cd();
histo -> Clone();
cd("..");
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
void EEezClusterQA::bookCut ( const Char_t *name, const Char_t *title, Int_t nbin, Float_t min, Float_t max )
{
// Book a histogram for quantities which are cut on. Histograms are
// stored in a TList, which is searched whenever we fill. This is
// slow, and should be changed to a hash table.
if ( !m_ListOfCuts )
m_ListOfCuts = new TList();
cd();
m_ListOfCuts -> Add ( new TH1F(name,title,nbin,min,max) );
cd("..");
}
void EEezClusterQA::fillCut( const Char_t *name, Float_t value )
{
// Fills the specified cut
TH1F *h = ((TH1F*)m_ListOfCuts -> FindObject( name )) ;
if ( h != NULL )
h -> Fill ( value );
else
Warning("fillCut","%s not found",name);
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
void EEezClusterQA::bookCut ( const Char_t *name, const Char_t *title, Int_t nbin, Float_t min, Float_t max, Int_t nbiny, Float_t miny, Float_t maxy )
{
// Book a histogram for quantities which are cut on. Histograms are
// stored in a TList, which is searched whenever we fill. This is
// slow, and should be changed to a hash table.
if ( !m_ListOf2DCuts )
m_ListOf2DCuts = new TList();
cd();
m_ListOf2DCuts -> Add ( new TH2F(name,title,nbin,min,max,nbiny,miny,maxy) );
cd("..");
}
void EEezClusterQA::fillCut( const Char_t *name, Float_t value, Float_t valuey )
{
// Fills the specified cut
// ((TH1F*)m_ListOf2DCuts -> FindObject( name )) -> Fill(value,valuey);
TH2F *h = ((TH2F*)m_ListOf2DCuts -> FindObject( name )) ;
if ( h != NULL )
h -> Fill ( value, valuey );
else
Warning("fillCut","%s not found",name);
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
ROOT page - Class index - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.