// Author: Pierre-Luc Drouin <http://www.pldrouin.net>
// Copyright Carleton University

#include "QSigExGaussCor.h"

//#define DEBUG
//#define DEBUG2

#include "debugger.h"

////////////////////////////////////////////////////////////////////////
//                                                                    //
// QSigExGaussCor                                                     //
//                                                                    //
// This class, used with class QSigExGCJointProbs, allows to          //
// compute joint probability densities of flux groups considering the //
// correlations between their variables. To achieve this, it creates  //
// for each variable x a mapping function y(x) that has a gaussian    //
// distribution, such that the distribution of y(x) variables for     //
// each flux group is multi-gaussian. The covariance matrix of y(x)   //
// variables being computed for each flux group, it is possible to    //
// compute the joint probabilities using the multi-gaussian equation. //
//                                                                    //
// The class QSigExGaussCor loops over the flux groups in "PDFs"      //
// TDirectory and finds the ones that have a clean TTree named        //
// "Event Info". For each flux group, it finds QSigExDisTH PDFs and   //
// produces a y(x) mapping function with gaussian distribution (TF1   //
// object). Then, it uses the set of y(x) functions and the clean     //
// TTree belonging to the flux group to compute the covariance matrix //
// (TMatrixDSym object).  Matrix indexes are identified using TNamed  //
// objects in the PDFs directories.                                   //
//                                                                    //
////////////////////////////////////////////////////////////////////////

ClassImp(QSigExGaussCor)

void QSigExGaussCor::FormatDir()
{
  //This protected member function gives to the fMyDir TDirectory the structure
  //that is needed to store the information produced by this class. It doesn't
  //create any objects actually. 

}

void QSigExGaussCor::CleanDir()
{
  //This public member function reinitializes the part of the fMyDir directory
  //structure that belongs to QSigExGaussCor. It removes the y(x) mapping
  //functions and matrix indexes from PDFs directories and it removes covariance
  //matrices in flux group directories.

  PRINTF2(this,"\tvoid QSigExGaussCor::CleanDir()\n")
  try{
    //Check if the "PDFs" TDirectory exists
    CheckPDFs();
    TDirectory *pdfsdir,*fdir,*sdir; //"PDFs", flux group and systematic group
				     //TDirectory pointers
    //Get a pointer to "PDFs" TDirectory
    pdfsdir=dynamic_cast<TDirectory*>(fMyDir->Get("PDFs"));
    TList flist,slist,plist; //flux group, syst. group and PDFs TDirectory lists
    Int_t i,j,k; //iterators
    //Fill flist with the list of flux group directories in "PDFs" 
    GetDirs(&flist,pdfsdir);

    //Loops over the flux group directories in "PDFs"
    for(i=0;i<flist.GetSize();i++){
      //Get a pointer to the current flux group TDirectory
      fdir=dynamic_cast<TDirectory*>(flist.At(i));
      //Delete covariance matrix object/keys in the flux group TDirectory
      DelObjsKeys("TMatrixDSym",fdir);
      //Fill slist with the list of systematic groups directories in fdir
      GetDirs(&slist,fdir);

      //Loops over the syst. group directories in fdir
      for(j=0;j<slist.GetSize();j++){
	//Get a pointer to the current syst. group TDirectory
	sdir=dynamic_cast<TDirectory*>(slist.At(j));
	//Fill plist with the list of PDF directories in sdir
	GetDirs(&plist,sdir);

	//Loops over the PDF directories in sdir
	for(k=0;k<plist.GetSize();k++){
	  //Delete y(x) function object/keys in the PDF TDirectory
	  DelObjsKeys("GaussMapping",dynamic_cast<TDirectory*>(plist.At(k)));
	  //Dekete matrix index object/keys in the PDf TDirectory
	  DelObjsKeys("TMatrixIndex",dynamic_cast<TDirectory*>(plist.At(k)));
	}
	//Clear the PDF directories list without deleting the objects
	plist.Clear("nodelete");
      }
      //Clear the syst. group directories list without deleting the objects
      slist.Clear("nodelete");
    }
    //Clear the flux group directories list without deleting the objects
    flist.Clear("nodelete");

  }catch(int e){
    cout << "Exception handled by QSigExGaussCor::CleanDir\n";
    throw e;
  }
}

void QSigExGaussCor::LoadCardFile(const Char_t* cardfilename)
{
  //This is an empty function in this class actually
  PRINTF4(this,"\tvoid QSigExGaussCor::LoadCardFile(const Char_t* cardfilename<",
      cardfilename,">)\n")
  cardfilename=NULL;
}

Int_t QSigExGaussCor::Get()
{
  //This function uses the "Event Info" TTree objects in flux group directories
  //and QSigExDisTH* PDFs in pdf directories to create TMatrixDSym covariance matrices
  //in flux group directories after to have produced "GaussMapping" TF1 objects
  //(y(x) mapping functions) and "TMatrixIndex" TNamed objects (matrix indexes)
  //in PDF directories

  PRINTF2(this,"\tInt_t QSigExGaussCor::Get()\n")

  //Call FormatDir()
  FormatDir();

  QSigExDisTH *qthbuf; //PDF buffer
  TH1 *thbuf; //TH1 buffer
  TF1 *tfbuf; //TF1 buffer
  TNamed* nbuf; //TNamed buffer
  TTree* eitree; //Pointer to "Event Info" TTree in flux group directories
  QList<TString> vars; //List of correlated variable names
  //"PDFs", flux group, syst. group, pdf and "Inputs" TDirectory pointers
  TDirectory *pdfsdir,*fdir,*sdir,*pdir,*idir;
  Bool_t tloaded; //Was the "Event Info" TTree already loaded in memory?
  QSigExStaticList* staticlist; //Used to pass information to y(x) functions

  //flux group, syst. group, pdf and "Inputs" directories list
  TList flist,slist,plist,ilist;
  TList mflist; //y(x) functions list
  Int_t i,j,k,l,m; //iterators

  TString strbuf; //TString buffer
  Double_t dbuf1,dbuf2; //Double_t buffers
  Float_t *farray; //"Event Info" TTree branches addresses
  Double_t *m1array; //Array of first moments*n
  Double_t *m2array; //Array of sum(xi*xj)
  Double_t *bufarray; //Buffer for y(x) function values
  Int_t ibuf1,ibuf2; //2 Int_t buffers
  Int_t nentries,nignored; //Number of entries in "Event Info" TTree
  TMatrixDSym* matrix; //pointer to a covariance matrix
  Bool_t ignore; //flag that indicate if an event must be ignored

  //Get a pointer to the "PDFs" TDirectory
  pdfsdir=dynamic_cast<TDirectory*>(fMyDir->Get("PDFs"));
  //Fill flist with the list of flux groups directories in the "PDFs" TDirectory
  GetDirs(&flist,pdfsdir);

  //Loop over the flux group directories in "PDFs"
  for(i=0;i<flist.GetSize();i++){
    //Clear the list of correlated variable names
    vars.Clear();
    //Get a pointer to the current flux group TDirectory
    fdir=dynamic_cast<TDirectory*>(flist.At(i));

    //Is the "Event Info" TTree in fdir already loaded in memory?
    tloaded=fdir->FindKey("Event Info") && !fdir->FindObject("Event Info");
    //If there's an "Event Info" TTree in the flux group TDirectory

    if((eitree=dynamic_cast<TTree*>(fdir->Get("Event Info")))){
      //Fill slist with the list of systematic groups directories in fdir
      GetDirs(&slist,fdir);

      //Loop over the systematic groups in fdir
      for(j=0;j<slist.GetSize();j++){
	//Get a pointer to the current syst. group TDirectory 
	sdir=dynamic_cast<TDirectory*>(slist.At(j));
	//Fill plist with the list of PDFs directories in sdir
	GetDirs(&plist,sdir);
	
	//Loop over the PDFs directories in sdir
	for(k=0;k<plist.GetSize();k++){
	  //Get a pointer to the current PDF TDirectory in sdir
	  pdir=dynamic_cast<TDirectory*>(plist.At(k));
	  //Fill strbuf with the name of y(x) function
	  strbuf="GaussMapping_";
	  strbuf+=pdir->GetName();

	  //If there's an "Inputs" TDirectory in pdir and if there's a QSigExDisTH
	  //object with the same name than pdir in pdir (save pointers)
	  if((idir=dynamic_cast<TDirectory*>(pdir->Get("Inputs"))) &&
	      (qthbuf=dynamic_cast<QSigExDisTH*>(pdir->Get(pdir->GetName()))) &&
	      qthbuf->GetDimension()==1){
	    //Fill ilist with the list of objects in ilist TDirectory
	    GetObjs(&ilist,idir);

	    //If the list is not empty and if the first object in the list is a
	    //TNamed object
	    if(ilist.GetSize() && (nbuf=dynamic_cast<TNamed*>(ilist.At(0)))){
	      //Resize the list of correlated variable names
	      vars.RedimList(vars.Count()+1);
	      //Add the title of the TNamed object to the list of correlated variables
	      vars[vars.Count()-1]=nbuf->GetTitle();

	    //Else if there's no TNamed object in "Inputs" TDirectory, throw an exception  
	    }else{
	      cout << "Error in QSigExGaussCor::Get: There's no Inputs directory for pdf " << qthbuf->GetName() << "\n";
	      throw 1;
	    }
	    //Clear the list of inputs and delete its owned objects from memory
	    ilist.Clear();
	    //Create an instamce of QSigExStaticList
	    staticlist=new QSigExStaticList;
	    //Get the TH1F object from the current PDF
	    thbuf=dynamic_cast<TH1F*>(qthbuf->GetObject());
	    //Add the TH1F object to the static list
	    staticlist->Add(thbuf);
	    cout << "Building TF1... \n";
	    //Get the low edge of the first PDF bin
	    dbuf1=thbuf->GetBinLowEdge(1);
	    //Get the high edge if the last PDF bin
	    dbuf2=thbuf->GetBinLowEdge(thbuf->GetNbinsX())+thbuf->GetBinWidth(thbuf->GetNbinsX());
	    //	      dbuf1=eitree->GetMinimum(vars[vars.Count()-1]);
	    //	      dbuf2=eitree->GetMaximum(vars[vars.Count()-1]);
	    //Create a new TF1 object (y(x) function) with same range than the
	    //PDF. A pointer to QSigExGaussMapping function is passed.
	    tfbuf=new TF1(strbuf,QSigExGaussMapping,dbuf1,dbuf2,0);
	    //Set the number of points to 10 times the number of bins in the PDF
	    tfbuf->SetNpx(10*thbuf->GetNbinsX());
	    //Store the array of (x,y) points in the internal member variables
	    //of the TF1 object
	    tfbuf->Save(dbuf1,dbuf2,0,0,0,0);
	    //Deallocate the function pointer
	    tfbuf->SetFunction(NULL);
	    cout << "Min/Max: " << dbuf1 << "/" << dbuf2 << "\n";

	    //Add the new y(x) function to the list of functions
	    mflist.AddLast(tfbuf);
	    cout << "done\n";
	    //Add the TF1 object to the PDF TDirectory
	    pdir->Add(tfbuf);
	    //Clear the static list without deleting its objects
	    staticlist->Clear("nodelete");
	    //Delete the static list instance
	    delete staticlist;
	    strbuf="";
	    //Assign the new correlated variable index to strbuf (string)
	    strbuf+=vars.Count()-1;
	    //Create a new TNamed object with name "TMatrixIndex" and with the
	    //correlated variable index string as title
	    nbuf=new TNamed("TMatrixIndex",strbuf.Data());
	    //Add it to the PDF TDirectory
	    pdir->Add(nbuf);
	  }
	}
	  //Clear the list of PDF directories without deleting its objects
	  plist.Clear("nodelete");
      }
        //Clear the list of syst. directories without deleting its objects
	slist.Clear("nodelete");

	//Assign the number of correlated variables to ibuf1
	ibuf1=vars.Count();
	//Create an array of ibuf1 cells to hold "Event Info" TTree branch
	//addresses
	farray=new Float_t[ibuf1];
	//Create an array of ibuf1 cells to hold a set of y(x) values 
	bufarray=new Double_t[ibuf1];
	//Create an array of ibuf1 cells to hold the first moments x n
	m1array=new Double_t[ibuf1];
	//Initialize this array to 0
	memset(m1array,0,ibuf1*sizeof(Double_t));

	//Number of cells in the packed notation of a triangular matrix ibuf1 x inbuf1 
	ibuf2=ibuf1*(ibuf1+1)/2;
	//Create an array to hold sum(xi*xj) values
	m2array=new Double_t[ibuf2];
	//Initialize the array to 0
	memset(m2array,0,ibuf2*sizeof(Double_t));
	//Clear the branches of th "Event Info" TTree
	QTTreeUtils::ClearBranchesAddresses(eitree);

	//Loop over the number of correlated variables
	for(j=0;j<ibuf1;j++){
	  //Give to the appropriate branch of "Event Info" TTree a buffer address
	  eitree->SetBranchAddress(vars[j],farray+j);
	}
	
	//Set nentries to the number of events in "Event Info" TTree
	nentries=(Int_t)(eitree->GetEntries());
	//Initialize the number of ignored events
	nignored=0;

	cout << "Now compute covariance matrix for flux group " << fdir->GetName() << endl;
	QProgress progress(nentries,1000);
	//Loop over the entries in "Event Info" TTree
	for(j=0;j<nentries;j++){
          progress(j);

	  //Load the entry in the branch buffers
	  eitree->GetEntry(j);
	  //Set ignore to false
	  ignore=kFALSE;

	  //Loop over the correlated variables (first index)
	  for(k=0;k<ibuf1;k++){
	    //Evaluate y(x) for this variable
	    bufarray[k]=((TF1*)mflist.At(k))->Eval(farray[k]);
	    //Get the domain range of this y(x) function
	    ((TF1*)mflist.At(k))->GetRange(dbuf1,dbuf2);

	    //If the x value for the current event is outside this range, set
	    //ignore to true and stop looping on variables
	    if(farray[k]<dbuf1 || farray[k]>dbuf2){
	      //	      cout << "pdf " << k << "\t" << farray[k] << "\t" << dbuf1 << "\t" << dbuf2 << endl;
	      ignore=kTRUE;
	      break;
	    }
	  }

	  //If ignore is true, increment nignored and go to next entry
	  if(ignore){
	    nignored++;
	    continue;
	  }

	  //Set the packed notation index to 0
	  m=0;

	  //Loop over the correlated variables (first index) for this event
	  for(k=0;k<ibuf1;k++){
	    //Add the y(x) value to the moment x n value of this variable
	    m1array[k]+=bufarray[k];

	    //Loop over the correlated variables (second index), from the
	    //variable k to the end
	    for(l=k;l<ibuf1;l++){
	      //Add xk*xl value to the sum(xk*xl) array 
	      m2array[m]+=bufarray[k]*bufarray[l];
	      //Increment the packed notaiton index
	      m++;
	    }
	  }
	}
	progress(j,kTRUE);
	cout << "\tdone\n";

	cout << nignored << " events outside of range for flux group " << fdir->GetName() << "\n";

	//Clear the "Event Info" TTree branch addresses
	QTTreeUtils::ClearBranchesAddresses(eitree);

	//If "Event Info" TTree has been loaded by this function, delete it
	if(tloaded) eitree->Delete();

	//Delete the branch buffers
	delete[] farray;
	//Delete the y(x) values buffer
	delete[] bufarray;
	
	cout << "The covariance matrix of flux group " << fdir->GetName() << " has been computed for " << nentries-nignored << "/" << nentries << " events\n";

	//Create an new square TMatrixDSym matrix
	matrix=new TMatrixDSym(ibuf1);

	//Initiazlie the packed notation index
	m=0;

	//Loop over the correlated variables (first index)
	for(k=0;k<ibuf1;k++){

	  //Loop over the correlated variables (second index), from the
	  //variable k to the end
	  for(l=k;l<ibuf1;l++){
	    //Assign the covariance value to symmetric cells in the covariance matrix
	    (*matrix)(k,l)=(*matrix)(l,k)=(m2array[m]-m1array[k]*m1array[l]/(nentries-nignored))/(nentries-nignored);
	    //Increment the packed notation index
	    m++;
	  }
	}

	//Print the covariance matrix (covariance in y domain)
	matrix->Print();
	//Add the matrix to the flux group TDirectory
	fdir->Add(matrix);

	//Delete m1array and m2arra arrays
	delete[] m1array;
	delete[] m2array;
	//Clear the list of y(x) functions without deleting its objects
	mflist.Clear("nodelete");
    }
  }
  //Clear the list of flux group directories without deleting its objects
  flist.Clear("nodelete");
  //Return 0;
  return 0;
}

void QSigExGaussCor::CheckPDFs() const
{
  //This protected function check if "PDFs" TDirectory exists
  if(!FindObjKey("PDFs",fMyDir)){
    cout << "Error: There's no PDF in fMyDir\n";
    throw 1;
  }
}

#include "debugger.h"







ROOT page - Class index - Class Hierarchy - 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.