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

#include "QSigExPDFs.h"

//#define DEBUG
//#define DEBUG2

#include "debugger.h"

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// QSigExPDFs                                                           //
//                                                                      //
// This abstract base class uses a card file to create a set of         //
// marginal PDFs.  Binned/unbinned functions are loaded via derived     //
// class GetFunction member function (GetFunction is a pure virtual     //
// member function of QSigExPDFs) and returned to QSigExPDFs class.     //
// Then, cuts defined in the TDirectory structure are applied (or not,  //
// depending on the derived class) and the functions are normalized.    //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

ClassImp(QSigExPDFs)

void QSigExPDFs::FormatDir()
{
  //This protected member function gives to the fMyDir TDirectory the structure
  //that is needed to store the information produced by this class. It creates
  //directory PDFs into fMyDir.

  PRINTF2(this,"\tvoid QSigExPDFs::FormatDir()\n")
  try{
    //If 'PDFs' is neither in memory nor on Disk, create it in memory
    if(!(fPDFsDir=(TDirectory*)fMyDir->Get("PDFs"))){
      fPDFsDir=fMyDir->mkdir("PDFs","PDFs");
    }

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

void QSigExPDFs::CleanDir()
{
  //This public member function reinitializes the part of the fMyDir directory
  //structure that belongs to QSigExPDFs. It removes the PDFs directories owned
  //by the class and calls FormatDir.

  PRINTF2(this,"\tvoid QSigExPDFs::CleanDir()\n")
  try{
    if((fPDFsDir=dynamic_cast<TDirectory*>(fMyDir->Get("PDFs")))){
      //Format fMyDir properly
      FormatDir();
      TList gdlist,sdlist,pdlist; //flux group, systematic groups and PDFs
      //directories lists 
      TDirectory *gdir,*sdir,*pdir;
      Int_t i,j,k; //iterators

      //Fill gdlist with the list of flux group directories in "PDFs" TDirectory
      GetDirs(&gdlist,fPDFsDir);
      //Loop over the flux group directories
      for(i=0;i<gdlist.GetSize();i++){
	//Get a flux group TDirectory pointer
	gdir=dynamic_cast<TDirectory*>(gdlist.At(i));
	//Fill sdlist with the list of systematic group directories in gdir
	GetDirs(&sdlist,gdir);
	//Loop over the systematic group directories
	for(j=0;j<sdlist.GetSize();j++){
	  //Get a systematic group TDirectory pointer
	  sdir=dynamic_cast<TDirectory*>(sdlist.At(j));
	  //Fill pdlist with the list of PDFs directories in sdir
	  GetDirs(&pdlist,sdir);
	  //Loop over the PDFs directories
	  for(k=0;k<pdlist.GetSize();k++){
	    //Get a PDF TDirectory pointer
	    pdir=dynamic_cast<TDirectory*>(pdlist.At(k));
	    //If there's an object/key in the PDF TDirectory which name is the name of this
	    if(FindObjKey(ClassName(),pdir)){
	      //Delete the PDF TDirectory (and syst. group if last PDF) (and flux
	      //group if last syst. group)
	      DelPDF(gdir->GetName(),sdir->GetName(),pdir->GetName());
	    }
	  }
	  //Clear the list of PDF TDirectory without deleting the objects
	  pdlist.Clear("nodelete");
	}
	//Clear the list of systematics TDirectory without deleting the objects
	sdlist.Clear("nodelete");
      }
      //Clear the list of flux groups TDirectory without deleting the objects
      gdlist.Clear("nodelete");
      GetDirs(&gdlist,fPDFsDir);
      if(!gdlist.GetSize()) DelObjsKeys("PDFs",fMyDir);
      gdlist.Clear("nodelete");
    }
    fPDFsDir=NULL;
  }catch(int e){
    cout << "Exception handled by QSigExPDFs::CleanDir\n";
    throw e;
  }
}

void QSigExPDFs::ClearCardBuf()
{
  //This member function clears the internal variables used to store the
  //configuration information of this class in card file format 

  fPDFCard.Clear();
}

void QSigExPDFs::LoadCardFile(const Char_t* cardfilename)
{
  //This public member function reads the card file with filename cardfilename
  //and saves the information in QSigExPDFs internal member variables.
  //
  //For the sake of flexibility, the card file entry format is not entirely
  //defined by QSigExPDFs. Only the firt 5 fields, including the keyword, have a
  //fixed meaning. For documentation about the other fields, refer to the
  //GetFunction member function of the appropriate derived class.
  //
  //Syntax of card file entries: 
  //pdf  [flags]  [typeid]  [fgroup]  [sgroup]  [...]
  //where [typeid] is the identifier used by derived classes validate
  //the PDF type, where [fgroup] is the flux group of the PDF and [sgroup] its
  //systematic group.
  //
  //[flags] specifies different options related to PDF activation and normalization.
  //Flags can be combined using a bitwise "OR" operator. The following values are
  //implemented in QSigExPDFs:
  //
  //1: The PDF entry is active
  //2: The PDF should not be normalized
  //More significant bits are passed to the function QSigExDis::Normalize. Please
  //refer to the documentation of the QSigExDis derived classes.
  //
  //About the PDFs inputs:
  //Depending on the type of PDF, a pdf entry contains one ore more fields that
  //specify the inputs to the PDF. These fields can be of 2 types:
  //-They can be branch names of the data TTree
  //-They can be equivalence names
  //In both cases, for all QSigExPDFs derived classes that let QSigExPDFs
  //normalize the PDFs, it's IMPORTANT that all the cut expressions that contain
  //the PDFs input names don't contain ANY OTHER VARIABLE.

  PRINTF4(this,"\tvoid QSigExPDFs::LoadCardFile(const Char_t* cardfilename<",cardfilename,">)\n")
  try{

    //if cardfilename is not NULL
    if(cardfilename){
      //Set the QDatReader filename to cardfilename
      fReader.SetFilename(cardfilename);
      //Set the QDatReader keywork to "pdf"
      fReader.SetKeyword("pdf");
      //Read all the pdf lines
      fPDFCard=fReader.GetMany(0);
    }
  }catch(int e){
    cout << "Exception handled by QSigExPDFs::LoadCardFile\n";
    throw e;
  }
}

Int_t QSigExPDFs::Get()
{
  //This function uses the PDF entries stored in the internal member variables
  //of this class to load, apply cuts, normalize and store a set of marginal
  //PDFs in a subfolder of "PDFs" TDirectory in the TDirectory structure. The
  //resulting PDFs are instances of a class derived from QSigExDis. 
  //
  //Each PDF is located in a TDirectory having the same name than the PDF. This
  //TDirectory is stored in another TDirectory named according to the PDF
  //systematic group.  Finally, this systematic TDirectory is placed in another
  //TDirectory named according to the flux group of the PDF. 
  //
  //The function returns the number of PDFs that have been loaded 

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

  //Set up the indices for the fields in this part of the card file:
  const Int_t minfields = 5;         //minimum expected number of fields

  const Int_t flagindex = 1;         //Active flag index
  const Int_t pdfgroupindex = 3;     //Flux group name
  const Int_t systnameindex = 4;     //Systematics group name

  try{
    FormatDir();

    //Check if the Cuts TDirectory exists
    CheckCuts();

    TDirectory* cutsdir=dynamic_cast<TDirectory*>(fMyDir->Get("Cuts"));

    //Loads the equivalence TDirectory in memory
    cutsdir->cd("Equivalences");
    TDirectory* eqdir=dynamic_cast<TDirectory*>(cutsdir->Get("Equivalences"));
    TList equiv;           //List of equivalences TNamed objects

    //Get the list of equivalences TNamed objects from the equivalence
    //TDirectory
    GetObjs(&equiv,eqdir);

    QList<TString> eqnames; //List of equivalences names
    QList<TString> eqformulas; //List of equivalences formulae
    TString strbuf; //TString buffers

    Int_t i,j; //Iterators

    //Loop over the equivalences
    for(j=0;j<equiv.GetSize();j++){

      //Add the equivalence name
      eqnames+=dynamic_cast<TNamed*>(equiv.At(j))->GetName();

      //Add the equivalence expression
      eqformulas+=dynamic_cast<TNamed*>(equiv.At(j))->GetTitle();
    }
    //Clear the list of equivalences TNamed objects and delete these
    //objects from memory
    equiv.Clear();

    TList ccuts;         //TCut objects that will contain combined cuts
    TCut  allcuts;       //All the cuts

    //Change directory to "Cuts Expressions"
    cutsdir->cd("Cuts Expressions");

    TList cuts; //List of simple cuts

    //Get the list of cuts TNamed objects from the equivalence TDirectory
    GetObjs(&cuts,gDirectory);

    TCut* buf; //TCut buffer

    //Loop over the cuts
    for(i=0;i<cuts.GetSize();i++){
      //Read the cut expression
      buf=new TCut(dynamic_cast<TNamed*>(cuts.At(i))->GetTitle());
      //Add it to allcuts
      allcuts+=(*buf);
      //Add the cut to the list of combined cuts
      ccuts.Add(buf);
    }
    //Clear the list of cuts TNamed objects and delete these objects from
    //memory
    cuts.Clear();

    TIter iter(&ccuts); //Combined cuts iterator

    Int_t actbuf;        //Buffer for the act flag
    TDirectory* fluxdir; //Flux TDirectory pointer
    TDirectory* systdir; //Systematics TDirectory Pointer
    TDirectory* pdfdir;  //PDF TDirectory pointer
    TDirectory* inputspdir; //Inputs TDirectory pointer
    QList<TString> inputs;
    Int_t ninputs;       //Number of inputs
    QSigExDis* pdfbuf;        //QSigExDis buffer
    Bool_t pdfneedscuts;

    TNamed* nbuf;      //TNamed buffer

    Double_t buf1,buf2,buf3;   //Float_t buffers

    TString cutsexpr;    //A cuts TString buffer

    TCut pdfcuts;        //Cuts for a specific pdf
    const Char_t* labels[3]={"x","y","z"}; //variable names for QSigExDis* objs
    QList<Int_t> eqfound; //Buffer for matching equivalences

    //Loop over the pdf lines in the card file
    for(i=0;i<fPDFCard.Count();i++){

      CheckCardNFields(fPDFCard[i].Count(),minfields);

      //Store the act flag in actbuf
      sscanf(fPDFCard[i][flagindex].Data(),"%i",&actbuf);

      //If the PDF is activated
      if(actbuf & kDisAct){
	//initialize fluxdir and systdir pointers
	fluxdir=NULL;
	systdir=NULL;
	
	//If the TDirectory of the current flux group doesn't exist, create
	//it
	if(!(fluxdir=(TDirectory*)fPDFsDir->Get(fPDFCard[i][pdfgroupindex]))){
	  fluxdir=fPDFsDir->mkdir(fPDFCard[i][pdfgroupindex],
				 fPDFCard[i][pdfgroupindex]);
	}

	//If the TDirectory of the current systematic group doesn't exist,
	//create it
	if(!(systdir=(TDirectory*)fluxdir->Get(fPDFCard[i][systnameindex]))){
	  systdir=fluxdir->mkdir(fPDFCard[i][systnameindex],
				 fPDFCard[i][systnameindex]);
	}
	
	inputs.Clear();
	//Load the function and its inputs. If the function needs cuts,
	//pdfneedscuts is set to kTRUE
	pdfbuf=GetFunction(fPDFCard[i],fluxdir,allcuts,&inputs,&pdfneedscuts);

	if(pdfbuf){
	  //Create a TDirectory for the pdf
	  pdfdir=systdir->mkdir(pdfbuf->GetName());

	  //Add class identifier in pdf directory;
	  nbuf=new TNamed(ClassName(),"Class Owner Identifier");
	  pdfdir->Add(nbuf);
	
	  //Create an "Inputs" directory for the pdf
	  inputspdir=pdfdir->mkdir("Inputs");
	
	  ninputs=inputs.Count();
	
	  //Loop over the coordinates in card file
	  for(j=0;j<ninputs;j++){
	    //Create a new TNamed object to contain the Input
	    nbuf=new TNamed(((TString)"Input ")+(long int)(j),inputs[j]);
	    //Add the Input object to the Input TDirectory
	    inputspdir->Add(nbuf);
	    //Increment the number of inputs
	  }
	
	  //Initialize the PDFs cuts to TRUE
	  pdfcuts="1";
	
	  if(pdfneedscuts){
	    //Reset the iterator
	    iter.Reset();
	
	    //Loop over the single cuts
	    while((buf=(TCut*)iter())){
	      //Copy the current cut into strbuf
	      strbuf=buf->GetTitle();
	
	      //Loop over the number of inputs in the PDF
	      for(j=0;j<ninputs;j++){
		//If the current cut contains the input name, add it to the
		//list of cuts for this PDF
		if(QFormulaUtils::IndexVar(strbuf,((TNamed*)inputspdir->GetList()->
			At(j))->GetTitle())!=-1) pdfcuts+=(*buf);
	      }
	    }
	  }

	  //Copy the cuts into cutsexpr
	  cutsexpr=pdfcuts;
	
	  //Loop over the inputs
	  for(j=0;j<ninputs;j++){
	    //Replace the input variables names by x,y,z
	    QFormulaUtils::ReplaceVar(&cutsexpr,((TNamed*)inputspdir->GetList()->At(j))->GetTitle(),labels[j]);
	    //For the inputs, replace the equivalences names  by their
	    //expression
	    if((eqfound=eqnames.Find(((TNamed*)inputspdir->GetList()->At(j))
				     ->GetTitle())).Count())
	      ((TNamed*)inputspdir->GetList()->At(j))->
		SetTitle(eqformulas[eqfound[0]]);
	  }
	
	  //Normalize the PDF using the cuts and according to what indicated by the act flag
	  if(!(actbuf & kDisSkipNorm)){
	    cout << "\nNormalize pdf " << pdfbuf->GetName() << "\n";
	    pdfbuf->Normalize(cutsexpr,actbuf>>2,&buf1,&buf2,&buf3);
	    cout << "Full integral: " << buf1 << "\n";
	    if(buf3==0){
	      cout << "Normalization integral: " << buf2 << "\n";
	    }else{
	      cout << "Normalization integral: " << buf2 << " (error: -" << buf3/buf2*100 << " %)\n";
	    }
	  }else{
	    cout << "\nThe pdf " << pdfbuf->GetName() << " WILL NOT be normalized\n";
	  }
	
	  //Add the PDF to pdfdir
	  pdfdir->Add(pdfbuf);
	}
      }
    }

    //Delete the combined cuts 
    ccuts.Delete();

    //Return the number of loaded PDFs
    return fPDFCard.Count();

  }catch(Int_t e){
    cout << "Exception handled by QSigExPDFs::Get\n";
    throw e;
    }
}

void QSigExPDFs::DelPDF(const Char_t* fgroup, const Char_t* sgroup, const Char_t* pdfname)
{
  //This function removes a PDF from the TDirectory structure and from the card file entries in the
  //internal member variables, given its flux group, its systematics groups and its name

  TDirectory *fgdir,*sgdir;
  TList listbuf; //TList buffer

  Int_t i;
  const Int_t pdfgroupindex = 3;     //Flux group name
  const Int_t systnameindex = 4;     //Systematics group name

  for(i=0;i<fPDFCard.Count();i++){

    if(!fPDFCard[i][pdfgroupindex].CompareTo(fgroup) && !fPDFCard[i][systnameindex].CompareTo(fgroup) && GetPDFName(i)){
      fPDFCard.Del(i);
    }
  }

  //If there's no fPDFsDir TDirectory, return
  if(!(fPDFsDir=dynamic_cast<TDirectory*>(fMyDir->Get("PDFs")))) return;

  //If there's no flux group or systematics group TDirectory corresponding
  //to the arguments given, return
  if(!(fgdir=dynamic_cast<TDirectory*>(fPDFsDir->Get(fgroup)))) return;
  if(!(sgdir=dynamic_cast<TDirectory*>(fgdir->Get(sgroup)))) return;

  //Delete all the objects corresponding to pdfname in the systematics
  //group
  DelObjsKeys(pdfname,sgdir);
  //Load the list of remaining TDirectory objects in the systematics group
  //TDirectory
  GetDirs(&listbuf,sgdir);
  //If the list is empty, delete the systematics group
  if(!listbuf.GetSize()) DelObjsKeys(sgroup,fgdir);
  //Clear the list without deleting objects
  listbuf.Clear("nodelete");
  //Load the list of remaining TDirectory objects in the flux group
  //TDirectory
  GetDirs(&listbuf,fgdir);
  //If the list is empty, delete the flux group
  if(!listbuf.GetSize()) DelObjsKeys(fgroup,fPDFsDir);
  //Clear the list without deleting objects
  listbuf.Clear("nodelete");
}

void QSigExPDFs::AddPDF(Int_t flags, const Char_t* type, const Char_t* fgroup, const Char_t* sgroup, const Char_t* param1, const Char_t* param2, const Char_t* param3, const Char_t* param4, const Char_t* param5, const Char_t* param6, const Char_t* param7, const Char_t* param8)
{
  //This function adds a PDF entry in the internal member variables. The format of the arguments is descibed in QSigExFit::LoadCardFile.

  TString flagsstr=flags;

  QList<TString> entry;
  entry+="pdf";
  entry+=flagsstr;
  entry+=type;
  entry+=fgroup;
  entry+=sgroup;
  if(param1) entry+=(TString)param1;
  if(param2) entry+=(TString)param2;
  if(param3) entry+=(TString)param3;
  if(param4) entry+=(TString)param4;
  if(param5) entry+=(TString)param5;
  if(param6) entry+=(TString)param6;
  if(param7) entry+=(TString)param7;
  if(param8) entry+=(TString)param8;
  fPDFCard+=entry;
  entry.Clear();
}

void QSigExPDFs::CheckCuts() const
{
  //Check if the TDirectories "Cuts Expressions" and "Equivalences" exist

  TDirectory* cutsdir=dynamic_cast<TDirectory*>(fMyDir->Get("Cuts"));

  if(!cutsdir || !(cutsdir->FindObject("Cuts Expressions") ||
		   cutsdir->FindKey("Cuts Expressions")) ||
     !(cutsdir->FindObject("Equivalences") ||
       cutsdir->FindKey("Equivalences"))) {
    cout <<"Problem with cuts:  cuts not input correctly in card file\n"
         <<"or ReadCuts() was not called before it was needed\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.