ROOT logo
#include <TCanvas.h>

#if !defined(__CINT__) || defined(__MAKECINT__)
#include <TGrid.h>
#include <TStyle.h>
#include <TRandom.h>
#include <TFile.h>
#include <TF1.h>
#include <TH1F.h>
#include <TH1D.h>
#include <TH2F.h>
#include <TList.h>
#include <TMath.h>
#include <TGraphErrors.h>
#include <TString.h>
#include "TFitResult.h"
#include "THashList.h"
#include "Riostream.h"
#include "stdio.h"
using namespace std;
#endif

//-----------------------------------------------------------------------------
// Function declaration
void QAFillEventSelection();
void QAFillOccupancy();
void QAFillClusters();
void QAFillRP();
void QAFillTracks();
void QAFillNPi0();

void QAWriteEventSelection();
void QAWriteOccupancy();
void QAWriteClusters();
void QAWriteRP();
void QAWriteTracks();
void QAWriteNPi0();

TH1D *Pi0InvMass(TH2 *hMassPt, Float_t ptmin, Float_t ptmax);
TH1F *AddWriteTH1F(const char *name, const char *title, Double_t* values, Double_t* errors);
const TF1* GetPeriodRPFit(const char* histName = "phiRP");
void AddNoise(TH1D* hist, double noise);
void Fit1Pi0(TH1D *hMass,
	     const Int_t polN,
	     const Double_t mFitMin,
	     const Double_t mFitMax,
	     Double_t &nPi0, Double_t &ePi0);
Double_t pi0massP1(Double_t *x, Double_t *par);
Double_t pi0massP2(Double_t *x, Double_t *par);
Double_t pi0mass  (Double_t *x, Double_t *par);
Double_t bgP2     (Double_t *x, Double_t *par);

//-----------------------------------------------------------------------------
// Global variabes
const Int_t kNEventsBin = 4;
const Int_t kNCents = 1;
const Int_t kNPID = 8+6;
const char* kPIDNames[kNPID] = {"All", "Allwou", "Disp", "Disp2", "Dispwou", "CPV", "CPV2", "Both",
				"Allcore", "Dispcore", "CPVcore", "Bothcore", "Both2core", "Disp2core"};
const char* fullMergeFileName = "AnalysisResults.root";

Int_t runIndex;
Int_t runNum[500];
TList *listHist;
Double_t run[500], erun[500];
// Event selection:
Double_t nTotal4[500];
Double_t rVtx[500], rVtxZ10[500], rVtxZ10Cent[500];
Double_t eVtx[500], eVtxZ10[500], eVtxZ10Cent[500];
// Occupancy:
Double_t nCellsM1[500], nCellsM2[500], nCellsM3[500];
// Clusters:
Double_t nCluEvent[500], eCluEvent[500];
Double_t cluEnergy[500], ecluEnergy[500];
Double_t nPhotPID[kNCents][kNPID][500], enPhotPID[kNCents][kNPID][500];
Double_t mEnPID[kNCents][kNPID][500],   emEnPID[kNCents][kNPID][500];
const float highPt = 1.;
Double_t nPhotPIDHigh[kNCents][kNPID][500], enPhotPIDHigh[kNCents][kNPID][500];
Double_t mEnPIDHigh[kNCents][kNPID][500],   emEnPIDHigh[kNCents][kNPID][500];
// Reaction Plane
const int nRPD = 3;// Reaction Plane Detector
enum RPD { V0A=0, V0C=1, TPC=2};
const char* rpdNames[nRPD] = {"V0A", "V0C", "TPC" };
const char* rpdId[nRPD] = {"V0A", "V0C", "" };
const char* flatId[2] = {"", "flat"};
//Double_t 
Double_t rpSE[nRPD][2][2][500];// [rpd][flat][val/err][run]
Double_t rpSin[nRPD][2][4][2][500];// [rpd][flat][parameter][val/err][run]
Double_t rpChi2[nRPD][2][2][500];// [rpd][flat][chi val/err][run]
// Tracks:
Double_t nTracks0[500], eTracks0[500];
Double_t nTracks1[500], eTracks1[500];
// Pi0:
Double_t mPi0[500], emPi0[500];
Double_t wPi0[500], ewPi0[500];
Double_t nPi0Event[500], ePi0Event[500];


//-----------------------------------------------------------------------------
void ExtractQA(const TString runFile="runFile.txt",
	       const TString outputFileName = "outputQA.root"
	       )
{
  // Loop over per-run root files and run various QA functions

  //TGrid::Connect("alien://");

  ifstream in;
  in.open(runFile.Data());

  TFile *rootFile;

  runIndex = 0;
  while (1) {
    char rootFileName[256];
    Int_t runNumber=0;
    in >> runNumber >> rootFileName;
    if (!in.good()) break;

    runNum[runIndex] = runNumber;

    printf("root file is %s, run # = %d\n",rootFileName,runNumber);
    // char *runNum = strtok(rootFileName+35,".");
    rootFile = TFile::Open(rootFileName,"read");
    listHist = (TList*)rootFile->Get("PHOSPi0Flow_kMB/PHOSPi0Flow_kMBCoutput1");

    run[runIndex]            = runIndex+1;
    QAFillEventSelection();
    QAFillOccupancy();
    QAFillClusters();
    QAFillRP();
    QAFillTracks();
    QAFillNPi0();

    listHist->Clear();
    rootFile->Close();
    runIndex++;
//     if(runIndex>3)
//       break;
  }


  TFile *fileQA = TFile::Open(outputFileName.Data(), "recreate");
  QAWriteEventSelection();
  QAWriteOccupancy();
  QAWriteClusters();
  QAWriteRP();
  QAWriteTracks();
  QAWriteNPi0();
  fileQA         ->Close();

}

//-----------------------------------------------------------------------------
void QAFillEventSelection()
{
  TH1F *hSelEvents = (TH1F*)listHist->FindObject("hTotSelEvents");

  Double_t nTotal      = hSelEvents->GetBinContent(1);
  Int_t nVtx           = hSelEvents->GetBinContent(2);
  Int_t nVtxZ10        = hSelEvents->GetBinContent(3);
  Int_t nVtxZ10Cent    = hSelEvents->GetBinContent(4);

  if( ! nTotal )
    return;

  nTotal4[runIndex] = hSelEvents->GetBinContent(4);

  rVtx[runIndex]           = nVtx          /nTotal;
  rVtxZ10[runIndex]        = nVtxZ10       /nTotal;
  rVtxZ10Cent[runIndex]    = nVtxZ10Cent   /nTotal;


  //Change in logic (plus clarification through rewriting): t(1+p)/n/n -> p(1-p)/n:
  eVtx[runIndex]           = TMath::Sqrt(       rVtx[runIndex] * (1 - rVtx[runIndex])        /nTotal);
  eVtxZ10[runIndex]        = TMath::Sqrt(    rVtxZ10[runIndex] * (1 - rVtxZ10[runIndex])     /nTotal);
  eVtxZ10Cent[runIndex]    = TMath::Sqrt(rVtxZ10Cent[runIndex] * (1 - rVtxZ10Cent[runIndex]) /nTotal);

}

//-----------------------------------------------------------------------------
void QAFillOccupancy()
{
  TH2D *hCellNXZM1 = (TH2D*)listHist->FindObject("hCellNXZM1");
  TH2D *hCellNXZM2 = (TH2D*)listHist->FindObject("hCellNXZM2");
  TH2D *hCellNXZM3 = (TH2D*)listHist->FindObject("hCellNXZM3");

  // Count cells in each module

  Int_t nCells1=0, nCells2=0, nCells3=0;
  for (Int_t cellX=1; cellX<=64; cellX++) {
    for (Int_t cellZ=1; cellZ<=56; cellZ++) {
      if (hCellNXZM1->GetBinContent(cellX,cellZ) > 0) nCells1++;
      if (hCellNXZM2->GetBinContent(cellX,cellZ) > 0) nCells2++;
      if (hCellNXZM3->GetBinContent(cellX,cellZ) > 0) nCells3++;
    }
  }
  nCellsM1[runIndex] = nCells1;
  nCellsM2[runIndex] = nCells2;
  nCellsM3[runIndex] = nCells3;
}

//-----------------------------------------------------------------------------
void QAFillClusters()
{
  TH1F *hTotSelEvents = (TH1F*)listHist->FindObject("hTotSelEvents");
  Double_t nEvents4 = hTotSelEvents->GetBinContent(4);
  if( ! nEvents4 ) return;

  TH2F *hCluEvsClu = (TH2F*)listHist->FindObject("hCluEvsClu");
  TH1D *hClusterE = hCluEvsClu->ProjectionX("hClusterE",4,41);

  cluEnergy[runIndex]  = hClusterE->GetMean();
  ecluEnergy[runIndex] = hClusterE->GetMeanError();

  nCluEvent[runIndex]  = hClusterE->Integral() / nEvents4;
  eCluEvent[runIndex]  = TMath::Sqrt( hClusterE->Integral() )/nEvents4;


  for(int cent = 0; cent < kNCents; ++cent) {
    for(int ipid = 0; ipid < kNPID; ++ipid) {
      TObject* obj = listHist->FindObject( Form("hPhot%s_cen%d", kPIDNames[ipid], cent) );
      TH1* hPhot = dynamic_cast<TH1*> ( obj );

      hPhot->SetAxisRange(0., 100.);
      double nPhot = hPhot->Integral() /nEvents4;
      nPhotPID [cent][ipid][runIndex] = nPhot;
      enPhotPID[cent][ipid][runIndex] = TMath::Sqrt( nPhot /nEvents4 );
      mEnPID   [cent][ipid][runIndex] = hPhot->GetMean();
      emEnPID  [cent][ipid][runIndex] = hPhot->GetMeanError();

      hPhot->SetAxisRange(highPt, 100.);
      double nPhotHigh = hPhot->Integral() /nEvents4;
      nPhotPIDHigh [cent][ipid][runIndex] = nPhotHigh;
      enPhotPIDHigh[cent][ipid][runIndex] = TMath::Sqrt( nPhotHigh /nEvents4 );
      mEnPIDHigh   [cent][ipid][runIndex] = hPhot->GetMean();
      emEnPIDHigh  [cent][ipid][runIndex] = hPhot->GetMeanError();

    }
  }
}
//-----------------------------------------------------------------------------
void QAFillRP()
{
  //TH1F *hev         = (TH1F*)listHist->FindObject("hTotSelEvents") ;
  TH2F* phiRP       = (TH2F*)listHist->FindObject("phiRP");
  TH2F* phiRPV0A    = (TH2F*)listHist->FindObject("phiRPV0A");
  TH2F* phiRPV0C    = (TH2F*)listHist->FindObject("phiRPV0C");
  TH2F* phiRPV0Aflat= (TH2F*)listHist->FindObject("phiRPV0Aflat");
  TH2F* phiRPV0Cflat= (TH2F*)listHist->FindObject("phiRPV0Cflat");
  TH2F* phiRPflat   = (TH2F*)listHist->FindObject("phiRPflat");

  //int nEvents = hev->GetBinContent(kNEventsBin);

  TH1D* phiRP1[nRPD][2] = {{0}};
  phiRP1[V0A][0] = phiRPV0A->ProjectionX();
  phiRP1[V0C][0] = phiRPV0C->ProjectionX();
  phiRP1[TPC][0] = phiRP->ProjectionX();
  phiRP1[V0A][1] = phiRPV0Aflat->ProjectionX();
  phiRP1[V0C][1] = phiRPV0Cflat->ProjectionX();
  phiRP1[TPC][1] = phiRPflat->ProjectionX();

  for(int rpd=0; rpd<nRPD; ++rpd) {
    for(int flat=0; flat<2; ++flat) {
      TH1D* hist = phiRP1[rpd][flat];
      const int nEntries = hist->GetEntries();
      const int nBins = hist->GetNbinsX();
      if ( nEntries < 1000 ) {
	//Printf("skipping RP: %s, very low number of entries", hist->GetName());
	continue;
      }
      
      // rpSE
      const Double_t* array = & hist->GetArray()[1]; 
      Double_t mean = TMath::Mean(nBins, array);
      Double_t rms = TMath::RMS(nBins, array) / mean * TMath::Sqrt(double(nBins)/(nBins-1));
      rpSE[rpd][flat][0][runIndex] = rms; 
      rpSE[rpd][flat][1][runIndex] = 0;

      // rpSin
      const TF1* periodFunc = GetPeriodRPFit(Form("phiRP%s%s", rpdId[rpd], flatId[flat]));
      for(int param=1; param < 4; ++param) {
	TF1* func = (TF1*)periodFunc->Clone("newRPFunc");
	for(int param2 = 1; param2 < 4; ++param2)
	  if(param != param2 ) func->FixParameter(param2, periodFunc->GetParameter(param2));
	if(1 == param ) func->SetParLimits(1, 0, 1);
	if(2 == param ) func->SetParLimits(2, 0, 100);
	if(3 == param ) func->SetParLimits(3, periodFunc->GetParameter(3)-TMath::Pi(), periodFunc->GetParameter(3)+TMath::Pi());
	int error = hist->Fit(func, "0Q");
	if( error ) {
	  rpSin[rpd][flat][param][0][runIndex] = 0;
	  if(3 == param) rpSin[rpd][flat][3][0][runIndex] = -2*TMath::Pi();
	  rpSin[rpd][flat][param][1][runIndex] = 0;	  
	}
	else {
	  rpSin[rpd][flat][param][0][runIndex] = func->GetParameter(param);
	  if(3 == param) rpSin[rpd][flat][3][0][runIndex] = func->GetParameter(3) - periodFunc->GetParameter(3);
	  rpSin[rpd][flat][param][1][runIndex] = func->GetParError(param);
	}
	delete func;
      }

      // rpChi2
      if(flat)
	AddNoise(hist, 0.01); // stricter if flattened
      else
	AddNoise(hist, 0.1);
      TFitResultPtr result = hist->Fit("pol0", "NSQ");
      if( result.Get() && !int(result) ) {
	int ndf = result->Ndf();
	rpChi2[rpd][flat][0][runIndex] = result->Chi2()/ndf;
	rpChi2[rpd][flat][1][runIndex] = TMath::Sqrt(2*ndf)/ndf;
      } else {
	rpChi2[rpd][flat][0][runIndex] = 0;
	rpChi2[rpd][flat][1][runIndex] = 0;
      }
    }
  }
}
//-----------------------------------------------------------------------------
void QAFillTracks()
{
  TH2F *hCenTrack = (TH2F*)listHist->FindObject("hCenTrack");
  TH1D *hTrackMult = hCenTrack->ProjectionY("hTrackMult", 1, hCenTrack->GetNbinsY());

  nTracks0[runIndex] = hTrackMult->GetMean();
  eTracks0[runIndex] = hTrackMult->GetMeanError();

  //   hTrackMult->DrawCopy();
  //  hTrackMult->SetAxisRange(5., hTrackMult->GetXaxis()->GetXmax());
  //   new TCanvas;
  //   hTrackMult->DrawCopy();

  //   nTracks1[runIndex] = hTrackMult->GetMean();
  //   eTracks1[runIndex] = hTrackMult->GetMeanError();
}

//-----------------------------------------------------------------------------
void QAFillNPi0()
{
  TH1 *hTotSelEvents = (TH1*)listHist->FindObject("hTotSelEvents");
  Int_t nEvents4 = hTotSelEvents->GetBinContent(4);

  if( nEvents4 < 10000 ) {
    Printf(" -> skipping due to small number of selected events: %d", nEvents4);
    return;
  }


  TCanvas* canv = new TCanvas;
  canv->Divide(3,3);
  canv->cd(1);

  TH2F *hReMassPt = (TH2F*)listHist->FindObject("hPi0All_cen0");
  TH2 *hMiMassPt = (TH2*)listHist->FindObject("hMiPi0All_cen0");
  TH1* hReMass = Pi0InvMass(hReMassPt,2.,10.);
  TH1* hMiMass = Pi0InvMass(hMiMassPt,2.,10.);
  hReMass->Rebin(2);
  hMiMass->Rebin(2);
  hReMass->SetAxisRange(0.,0.3);
  hMiMass->SetAxisRange(0.,0.3);

  // Draw
  hReMassPt->DrawCopy("colz");
  canv->cd(2);
  //hReMass->SetAxisRange(0.1, 0.2);
  hReMass->DrawCopy("E");
  canv->cd(3);


  TH1* hReMiRatio = (TH1*)hReMass->Clone("hReMiRatio");
  TH1* hPi0SubBG  = (TH1*)hReMass->Clone("hPi0SubBG");
  hReMiRatio->Divide(hMiMass);
  hReMiRatio->DrawCopy("E");
  canv->cd(4);


  TF1 * fitM = new TF1("fitM",pi0massP2,0.,1.,6) ;
  fitM->SetLineColor(kRed);
  fitM->SetParName(0,"A") ;
  fitM->SetParName(1,"m_{0}") ;
  fitM->SetParName(2,"#sigma") ;
  fitM->SetParName(3,"a_{0}") ;
  fitM->SetParName(4,"a_{1}") ;
  fitM->SetParName(5,"a_{2}") ;

  TF1 * fitG = new TF1("fitG",pi0mass,0.,1.,3) ;
  fitG->SetLineColor(kRed);
  fitG->SetParName(0,"A") ;
  fitG->SetParName(1,"m_{0}") ;
  fitG->SetParName(2,"#sigma") ;

  TF1 * fitBG = new TF1("fitBG",bgP2,0.,1.,3) ;
  fitBG->SetLineColor(kBlue);
  fitBG->SetLineStyle(2);
  fitBG->SetParName(0,"a_{0}") ;
  fitBG->SetParName(1,"a_{1}") ;
  fitBG->SetParName(2,"a_{2}") ;

  fitM->SetParameters(0.003, 0.134, 0.007, 0.14, -0.02, -0.01) ;
  fitM->SetParLimits(0, 0., 1. ) ;
  fitM->SetParLimits(1, 0.1, 0.2 ) ;
  fitM->SetParLimits(2, 0., 0.05) ;

  Double_t rangeMin=0.06 ;
  Double_t rangeMax=0.25 ;
  TFitResultPtr mrp = hReMiRatio->Fit(fitM,"Q","",rangeMin,rangeMax) ;
  //mrp = hReMiRatio->Fit(fitM,"MQ","",rangeMin,rangeMax) ; // "M" always fail...
  int error = mrp;
  if( error % 1000) {
    Printf(" -> fit of fitM to hReMiRatio failed with error code %d", error % 1000);
    return;
  }
  else if( error )
    Printf("Warning: failure of 'improve result' of fit of fitM to hReMiRatio");
  fitBG->SetParameters(fitM->GetParameter(3),
		       fitM->GetParameter(4),
		       fitM->GetParameter(5));
  hReMiRatio->SetAxisRange(rangeMin, rangeMax);
  hReMiRatio->DrawCopy();
  canv->cd(5);


  hMiMass->Multiply(fitBG) ;
  hPi0SubBG ->Add(hMiMass,-1.) ;


  fitG->SetParameters(100.,fitM->GetParameter(1),fitM->GetParameter(2)) ;
  // fitG->SetParLimits(0,0.000,1.e+5) ;
  fitG->SetParLimits(1, rangeMin, rangeMax) ;
  fitG->SetParLimits(2, 0., rangeMax) ;
  mrp = hPi0SubBG->Fit(fitG,"Q","",rangeMin,rangeMax);
  if( (error=mrp) ) {
    Printf(" -> fit of fitG to hPi0SubBG failed with error code %d, skipping", error );
    return;
  }
  hPi0SubBG->SetAxisRange(rangeMin, rangeMax);
  hPi0SubBG->DrawCopy();



  Double_t pi0Peak  = fitG->GetParameter(1);
  Double_t pi0Sigma = fitG->GetParameter(2);
  Double_t epi0Peak  = fitG->GetParError(1);
  Double_t epi0Sigma = fitG->GetParError(2);
  Int_t iMin = hPi0SubBG->FindBin(pi0Peak - 3*pi0Sigma);
  Int_t iMax = hPi0SubBG->FindBin(pi0Peak + 3*pi0Sigma);

  Double_t nPi0,ePi0;


  nPi0 = hPi0SubBG->IntegralAndError(iMin, iMax, ePi0);
  //ePi0 = TMath::Sqrt(nPi0);
  // Fit1Pi0(hMass,2,0.05,0.20,nPi0,ePi0);

  mPi0     [runIndex] = pi0Peak;
  emPi0    [runIndex] = epi0Peak;
  wPi0     [runIndex] = pi0Sigma;
  ewPi0    [runIndex] = epi0Sigma;
  nPi0Event[runIndex] = nPi0/nEvents4;
  ePi0Event[runIndex] = ePi0/nEvents4;
}

//-----------------------------------------------------------------------------
void QAWriteEventSelection()
{
  TH1F *hNSelected       = new TH1F("hNSelected","N_{selected}",runIndex,0,runIndex);
  TH1F *grVtx           = new TH1F("grVtx","N_{vertex exists} / N_{total}",runIndex,0,runIndex);
  TH1F *grVtxZ10        = new TH1F("grVtxZ10","N_{vertex exists, |Z|<10 cm} / N_{total}",runIndex,0,runIndex);
  TH1F *grVtxZ10Cent    = new TH1F("grVtxZ10Cent","N_{vertex exists, |Z|<10 cm, centrality} / N_{total}",runIndex,0,runIndex);

  for (Int_t i=0; i<runIndex; i++) {
    hNSelected->SetBinContent(i+1, nTotal4[i]);

    grVtx          ->SetBinContent(i+1,rVtx[i]);
    grVtxZ10       ->SetBinContent(i+1,rVtxZ10[i]);
    grVtxZ10Cent   ->SetBinContent(i+1,rVtxZ10Cent[i]);

    grVtx          ->SetBinError(i+1,eVtx[i]);
    grVtxZ10       ->SetBinError(i+1,eVtxZ10[i]);
    grVtxZ10Cent   ->SetBinError(i+1,eVtxZ10Cent[i]);

    grVtx          ->GetXaxis()->SetBinLabel(i+1,Form("%d",runNum[i]));
    grVtxZ10       ->GetXaxis()->SetBinLabel(i+1,Form("%d",runNum[i]));
    grVtxZ10Cent   ->GetXaxis()->SetBinLabel(i+1,Form("%d",runNum[i]));
  }

  grVtx          ->LabelsOption("v");
  grVtxZ10       ->LabelsOption("v");
  grVtxZ10Cent   ->LabelsOption("v");

  grVtx          ->SetMarkerStyle(33);
  grVtxZ10       ->SetMarkerStyle(33);
  grVtxZ10Cent   ->SetMarkerStyle(33);

  hNSelected     ->Write();
  grVtx          ->Write();
  grVtxZ10       ->Write();
  grVtxZ10Cent   ->Write();
}

//-----------------------------------------------------------------------------
void QAWriteOccupancy()
{
  // Number of fired cells in each module

  TH1F *grNCellsM1      = new TH1F("grNCellsM1","N_{cells} in module 1",runIndex,0,runIndex);
  TH1F *grNCellsM2      = new TH1F("grNCellsM2","N_{cells} in module 2",runIndex,0,runIndex);
  TH1F *grNCellsM3      = new TH1F("grNCellsM3","N_{cells} in module 3",runIndex,0,runIndex);

  for (Int_t i=0; i<runIndex; i++) {
    grNCellsM1          ->SetBinContent(i+1,nCellsM1[i]);
    grNCellsM2          ->SetBinContent(i+1,nCellsM2[i]);
    grNCellsM3          ->SetBinContent(i+1,nCellsM3[i]);

    grNCellsM1          ->SetBinError(i+1,0);
    grNCellsM2          ->SetBinError(i+1,0);
    grNCellsM3          ->SetBinError(i+1,0);

    grNCellsM1          ->GetXaxis()->SetBinLabel(i+1,Form("%d",runNum[i]));
    grNCellsM2          ->GetXaxis()->SetBinLabel(i+1,Form("%d",runNum[i]));
    grNCellsM3          ->GetXaxis()->SetBinLabel(i+1,Form("%d",runNum[i]));

    grNCellsM1->GetYaxis()->SetTitle("N_{cells}");
    grNCellsM2->GetYaxis()->SetTitle("N_{cells}");
    grNCellsM3->GetYaxis()->SetTitle("N_{cells}");
  }

  grNCellsM1     ->LabelsOption("v");
  grNCellsM2     ->LabelsOption("v");
  grNCellsM3     ->LabelsOption("v");
  grNCellsM1     ->SetMarkerStyle(33);
  grNCellsM2     ->SetMarkerStyle(33);
  grNCellsM3     ->SetMarkerStyle(33);
  grNCellsM1     ->Write();
  grNCellsM2     ->Write();
  grNCellsM3     ->Write();
}

//-----------------------------------------------------------------------------
void QAWriteClusters()
{
  TH1F *grECluster = new TH1F("grECluster","#LTE_{cluster}#GT",runIndex,0,runIndex);
  for (Int_t i=0; i<runIndex; i++) {
    grECluster          ->SetBinContent(i+1,cluEnergy[i]);
    grECluster          ->SetBinError(i+1,ecluEnergy[i]);
    grECluster          ->GetXaxis()->SetBinLabel(i+1,Form("%d",runNum[i]));
  }

  grECluster ->LabelsOption("v");
  grECluster ->SetMarkerStyle(33);
  grECluster ->Write();

  TH1F *grNCluster = new TH1F("grNCluster","#LTN_{clusters}#GT",runIndex,0,runIndex);
  for (Int_t i=0; i<runIndex; i++) {
    grNCluster          ->SetBinContent(i+1,nCluEvent[i]);
    grNCluster          ->SetBinError(i+1,eCluEvent[i]);
    grNCluster          ->GetXaxis()->SetBinLabel(i+1,Form("%d",runNum[i]));
  }
  grNCluster ->LabelsOption("v");
  grNCluster ->SetMarkerStyle(33);
  grNCluster ->Write();

  TString name, title;
  for(int cent=0; cent<kNCents; ++cent) {
    for(int ipid = 0; ipid < kNPID; ++ipid) {
      TObject* obj = listHist->FindObject( Form("hPhot%s_cen%d", kPIDNames[ipid], cent) );
      TH1* hPhot = dynamic_cast<TH1*> (obj);
      name = Form("grNPhot%s_cen%d", kPIDNames[ipid], cent);
      title = Form("#LTN_{clusters}^{%s}#GT, c.bin=%d", kPIDNames[ipid], cent);
      AddWriteTH1F(name, title, nPhotPID[cent][ipid], enPhotPID[cent][ipid]);
      name = Form("grEn%s_cen%d", kPIDNames[ipid], cent);
      title = Form("#LTE_{clusters}^{%s}#GT, c.bin=%d", kPIDNames[ipid], cent);
      AddWriteTH1F(name , title, mEnPID[cent][ipid], emEnPID[cent][ipid]);
      name = Form("grNPhot%sHigh_cen%d", kPIDNames[ipid], cent);
      title = Form("#LTN_{clusters}^{%s}#GT, c.bin=%d, p_T>%f", kPIDNames[ipid], cent, highPt);
      AddWriteTH1F(name, title, nPhotPIDHigh[cent][ipid], enPhotPIDHigh[cent][ipid]);
      name = Form("grEn%sHigh_cen%d", kPIDNames[ipid], cent);
      title = Form("#LTE_{clusters}^{%s}#GT, c.bin=%d, p_T>%f", kPIDNames[ipid], cent, highPt);
      AddWriteTH1F(name, title, mEnPIDHigh[cent][ipid], emEnPIDHigh[cent][ipid]);
    }
  }
}

void QAWriteRP()
{
  for(int rpd=0; rpd<nRPD; ++rpd) {
    for(int flat=0; flat<2; ++flat) {
      TString name;
      TString title;
      
      //rpSE
      name = Form("grSERP%s%s", rpdNames[rpd], flatId[flat]);
      title = Form("RMS (SE) of RP of %s, %s", rpdNames[rpd], flatId[flat]);
      TH1F* grSE = new TH1F(name.Data(), title.Data(), runIndex, 0, runIndex);
      for (Int_t i=0; i<runIndex; i++) {
	grSE          ->SetBinContent(i+1,  rpSE[rpd][flat][0][i]);
	grSE          ->SetBinError(i+1,    rpSE[rpd][flat][1][i]);
	grSE          ->GetXaxis()->SetBinLabel(i+1,Form("%d",runNum[i]));
      }
      grSE->GetYaxis()->SetTitle("Std. Err.");
      grSE->LabelsOption("v");
      grSE->SetMarkerStyle(33);
      grSE->Write();
      
      // rpSin
      for(int param=1; param < 4; ++param) {
	if( flat ) {
	  name = Form("grSinRP%sflat%d", rpdNames[rpd], param);
	  title = Form("Parameter [%d] of fit constraining others, flat, %s ", param, rpdNames[rpd]);
	} else {
	  name = Form("grSinRP%s%d", rpdNames[rpd], param);
	  title = Form("Parameter [%d] of fit constraining others, %s ", param, rpdNames[rpd]);
	}
	TH1F* grSin = new TH1F(name, title, runIndex, 0, runIndex);
	Printf(name.Data());
	for (Int_t i=0; i<runIndex; i++) {
	  //Printf("  %d chi2/ndf: %f, \terror:%f", i, rpSin[rpd][flat][i][0],rpSin[rpd][flat][i][1]);
	  grSin          ->SetBinContent(i+1,  rpSin[rpd][flat][param][0][i]);
	  grSin          ->SetBinError(i+1,    rpSin[rpd][flat][param][1][i]);
	  grSin          ->GetXaxis()->SetBinLabel(i+1,Form("%d",runNum[i]));
	}
	grSin->GetYaxis()->SetTitle(Form("p[%d]",param));
	if( 1 == param ) grSin->GetYaxis()->SetTitle("s_{1}");
	if( 2 == param ) grSin->GetYaxis()->SetTitle("#omega");
	if( 3 == param ) grSin->GetYaxis()->SetTitle("#psi - #psi_{P}");
	grSin->LabelsOption("v");
	grSin->SetMarkerStyle(33);
	grSin->Write();
      }
      // rpChi2
      if( flat ) {
	name = Form("grChi2RP%sflat", rpdNames[rpd]);
	title = Form("#Chi^2 / ndf to fit of pol0 of flattened RP of %s", rpdNames[rpd]);
      } else {
	name = Form("grChi2RP%s", rpdNames[rpd]);
	title = Form("#Chi^2 / ndf to fit of pol0 of raw RP of %s", rpdNames[rpd]);
      }
      TH1F* grChi2 = new TH1F(name, title, runIndex, 0, runIndex);
      Printf(name.Data());
      for (Int_t i=0; i<runIndex; i++) {
	//Printf("  %d chi2/ndf: %f, \terror:%f", i, rpChi2[rpd][flat][i][0],rpChi2[rpd][flat][i][1]);
	grChi2          ->SetBinContent(i+1,  rpChi2[rpd][flat][0][i]);
	grChi2          ->SetBinError(i+1,    rpChi2[rpd][flat][1][i]);
	grChi2          ->GetXaxis()->SetBinLabel(i+1,Form("%d",runNum[i]));
      }
      grChi2->GetYaxis()->SetTitle("#Chi^2 / ndf");
      grChi2->LabelsOption("v");
      grChi2->SetMarkerStyle(33);
      grChi2->Write();
    }
  }
}

//-----------------------------------------------------------------------------
void QAWriteTracks()
{
  TH1F *grNTracks0 = new TH1F("grNTracks0","#LTN_{tracks}#GT",runIndex,0,runIndex);
  for (Int_t i=0; i<runIndex; i++) {
    grNTracks0          ->SetBinContent(i+1,nTracks0[i]);
    grNTracks0          ->SetBinError(i+1,eTracks0[i]);
    grNTracks0          ->GetXaxis()->SetBinLabel(i+1,Form("%d",runNum[i]));
  }
  grNTracks0 ->LabelsOption("v");
  grNTracks0 ->SetMarkerStyle(33);
  grNTracks0 ->Write();

  //   TH1F *grNTracks1 = new TH1F("grNTracks1","#LTN_{tracks}#GT, N #geq 5",runIndex,0,runIndex);
  //   for (Int_t i=0; i<runIndex; i++) {
  //     grNTracks1          ->SetBinContent(i+1,nTracks0[i]);
  //     grNTracks1          ->SetBinError(i+1,eTracks0[i]);
  //     grNTracks1          ->GetXaxis()->SetBinLabel(i+1,Form("%d",runNum[i]));
  //   }
  //   grNTracks1 ->LabelsOption("v");
  //   grNTracks1 ->SetMarkerStyle(33);
  //   grNTracks1 ->Write();
}

//-----------------------------------------------------------------------------
void QAWriteNPi0()
{
  TH1F *grNPi0 = new TH1F("grNPi0","N(#pi^{0}) per event",runIndex,0,runIndex);
  for (Int_t i=0; i<runIndex; i++) {
    grNPi0          ->SetBinContent(i+1,nPi0Event[i]);
    grNPi0          ->SetBinError(i+1,ePi0Event[i]);
    grNPi0          ->GetXaxis()->SetBinLabel(i+1,Form("%d",runNum[i]));
  }
  grNPi0     ->LabelsOption("v");
  grNPi0     ->SetMarkerStyle(33);
  grNPi0->GetYaxis()->SetTitle("#LTN#GT");
  grNPi0     ->Write();

  TH1F *grMPi0 = new TH1F("grMPi0","M(#pi^{0})",runIndex,0,runIndex);
  for (Int_t i=0; i<runIndex; i++) {
    grMPi0          ->SetBinContent(i+1,mPi0[i]);
    grMPi0          ->SetBinError(i+1,emPi0[i]);
    grMPi0          ->GetXaxis()->SetBinLabel(i+1,Form("%d",runNum[i]));
  }
  grMPi0     ->LabelsOption("v");
  grMPi0     ->SetMarkerStyle(33);
  grMPi0->GetYaxis()->SetTitle("#LTM#GT");
  grMPi0     ->Write();

  TH1F *grWPi0 = new TH1F("grWPi0","#sigma(#pi^{0})",runIndex,0,runIndex);
  for (Int_t i=0; i<runIndex; i++) {
    grWPi0          ->SetBinContent(i+1,wPi0[i]);
    grWPi0          ->SetBinError(i+1,ewPi0[i]);
    grWPi0          ->GetXaxis()->SetBinLabel(i+1,Form("%d",runNum[i]));
  }
  grWPi0     ->LabelsOption("v");
  grWPi0     ->SetMarkerStyle(33);
  grWPi0->GetYaxis()->SetTitle("#LT#sigma#GT");
  grWPi0     ->Write();
}

//-----------------------------------------------------------------------------
TH1D * Pi0InvMass(TH2 *hMassPt, Float_t ptmin, Float_t ptmax)
{
  Int_t bmin = hMassPt->GetYaxis()->FindBin(ptmin);
  Int_t bmax = hMassPt->GetYaxis()->FindBin(ptmax);

  TString name = hMassPt->GetName();
  name += "_M";
  TH1D* hMass = hMassPt->ProjectionX(name,bmin,bmax);
  char htitle[64];
  sprintf(htitle,"%.1f<p_{T}<%.1f GeV/c",ptmin,ptmax);
  hMass->SetTitle(htitle);

  hMass->Sumw2();

  return hMass;

}

//-----------------------------------------------------------------------------
TH1F *AddWriteTH1F(const char *name, const char *title, Double_t* values, Double_t* errors)
{
  TH1F* hist = new TH1F(name, title, runIndex, 0, runIndex);
  hist->SetContent(values);
  hist->SetError(errors);

  for(Int_t i=0; i<runIndex; i++) {
    hist->GetXaxis()->SetBinLabel( i+1, Form("%d",runNum[i]) );
  }

  hist->LabelsOption("v");
  hist->SetMarkerStyle(33);
  hist->Write();

  if( TString(name).Contains("En") )
    hist->GetYaxis()->SetTitle("#LTE#GT");
  if( TString(name).Contains("NPhot") )
    hist->GetYaxis()->SetTitle("#LTN#GT");

  return hist;
}

const TF1* GetPeriodRPFit(const char* histName)
{
  TString name = Form("f1RPFit%s", histName);
  
  // if created earlier, find in list
  static THashList* list = new THashList;
  TF1* func = (TF1*) list->FindObject(name.Data());
  if( func ) return func;

  TFile* file = TFile::Open(fullMergeFileName, "read");
  TList* hlist = (TList*) file->Get("PHOSPi0Flow_kCentral/PHOSPi0Flow_kCentralCoutput1");
  TH2F* hist2d = (TH2F*) hlist->FindObject(histName);
  TH1D* hist = hist2d->ProjectionX();
  int nBins = hist->GetNbinsX();
  const Double_t* array = & hist->GetArray()[1]; 
  
  //TCanvas* canv = new TCanvas;
  func = new TF1(name.Data(), "[0]*(1. + [1]*sin([2]*x + [3]))", 0, TMath::Pi());
  double mean = TMath::Mean(nBins, array);
  double rms = TMath::RMS(nBins, array) / mean;
  func->SetParameters(mean, rms, 0.6*TMath::Pi(), -0.2*TMath::Pi());
  func->SetParLimits(0, 0, 2*mean);
  func->SetParLimits(1, 0, 1);
  func->SetParLimits(2, 0, 100);
  func->SetParLimits(3, -TMath::Pi(), TMath::Pi());
  func->SetParNames("s_{0}", "s_{1}", "#omega", "#psi");
  hist->GetXaxis()->SetTitle("#phi");
  TCanvas* canv = new TCanvas(name.Data());
  gStyle->SetOptStat(0);
  gStyle->SetOptFit(1);
  int error = hist->Fit(func, "Q");
  if( ! name.Contains("flat") ) {
    gStyle->SetOptFit(1);
  } else {
    gStyle->SetOptFit(1);
  }
  hist->Draw("E");
  canv->SaveAs(Form("imgs/%s.pdf", name.Data()));
  if( error )
    Printf("GetPeriodRPFit::ERROR, could not fit %s, error:%d", histName, error);

  //hist->Draw();
  //func->Draw("same");
  //canv->SaveAs("rpfit.pdf");
  
  // Fit
  list->Add(func);
  return func;
}


//-----------------------------------------------------------------------------
void AddNoise(TH1D* hist, double noise)
{
  int nBins = hist->GetNbinsX();
  double mean = TMath::Mean(nBins, &((hist->GetArray())[1]) );
  //Printf("Adding noise to: %s", hist->GetName());
  for(int bin=1; bin<=nBins; ++bin) {
    hist->SetBinContent( bin, hist->GetBinContent(bin) + gRandom->Gaus(0, noise) );
    double err = hist->GetBinError(bin);
    hist->SetBinError( bin, TMath::Sqrt( err*err + noise*noise ) );
  }
}

//-----------------------------------------------------------------------------
void Fit1Pi0(TH1D *hMass,
	     const Int_t polN,
	     const Double_t mFitMin,
	     const Double_t mFitMax,
	     Double_t &nPi0, Double_t &ePi0)
{
  // This script takes a 2D histogram hMassPt with invariant mass vs
  // pt of cluster pairs:
  // - slices them along pt bins,
  // - fits 1D invariant mass specrta by Gaussian+polynomial
  // - calculates the number of pi0's as an integral of Gaussian
  // - calculates background under pi0 as an integral of polynomial
  // Author: Yuri Kharlov.

  TF1 *fitfun = 0;
  if      (polN == 1)
    fitfun = new TF1("fitfun",pi0massP1,0.1,0.7,5);
  else if (polN == 2)
    fitfun = new TF1("fitfun",pi0massP2,0.1,0.7,6);
  fitfun->SetLineColor(kRed);
  fitfun->SetLineWidth(2);

  fitfun->SetParName(0,"A");
  fitfun->SetParName(1,"m_{0}");
  fitfun->SetParName(2,"#sigma");
  fitfun->SetParName(3,"a_{0}");
  fitfun->SetParName(4,"a_{1}");
  if (polN == 2)
    fitfun->SetParName(5,"a_{2}");

  fitfun->SetParLimits(0,  1.000,1.e+5);
  fitfun->SetParLimits(1,  0.09,0.18);
  fitfun->SetParLimits(2,  0.003,0.020);

  Int_t   nM     = hMass->GetNbinsX();
  Float_t mMin   = hMass->GetXaxis()->GetXmin();
  Float_t mMax   = hMass->GetXaxis()->GetXmax();
  Float_t mStep  = (mMax-mMin)/nM;

  hMass->SetXTitle("M_{#gamma#gamma}, GeV/c");
  hMass->SetAxisRange(0.01,1.0);
  Float_t nPi0Max = hMass->Integral(hMass->FindBin(0.30),
                                    hMass->FindBin(0.40));
  for (Int_t iM=1; iM<nM; iM++)
    if (hMass->GetBinContent(iM) == 0) hMass->SetBinError(iM,1.0);
  hMass->SetMinimum(0.01);
  if      (polN == 1)
    fitfun->SetParameters(nPi0Max/4,0.135,0.010,1.,0.);
  else if (polN == 2)
    fitfun->SetParameters(nPi0Max/4,0.135,0.010,1.,0.,0.);
  hMass->Fit("fitfun","Q0","",mFitMin,mFitMax);

  nPi0 = fitfun->GetParameter(0)*fitfun->GetParameter(2)/
    mStep*TMath::Sqrt(TMath::TwoPi());
  ePi0 = TMath::Sqrt(nPi0);
}


//-----------------------------------------------------------------------------
Double_t pi0massP2(Double_t *x, Double_t *par)
{
  Double_t gaus = par[0] * TMath::Exp( -(x[0]-par[1])*(x[0]-par[1]) /
                                       (2*par[2]*par[2]) );
  Double_t back = par[3] + par[4]*x[0] + par[5]*x[0]*x[0];
  return gaus+back;
}

//-----------------------------------------------------------------------------
Double_t pi0massP1(Double_t *x, Double_t *par)
{
  Double_t gaus = par[0] * TMath::Exp( -(x[0]-par[1])*(x[0]-par[1]) /
                                       (2*par[2]*par[2]) );
  Double_t back = par[3] + par[4]*x[0];
  return gaus+back;
}

//-----------------------------------------------------------------------------
Double_t pi0mass(Double_t *x, Double_t *par)
{
  Double_t gaus = par[0] * TMath::Exp( -(x[0]-par[1])*(x[0]-par[1]) /
                                       (2*par[2]*par[2]) );
  return gaus;
}

//-----------------------------------------------------------------------------
Double_t bgP2(Double_t *x, Double_t *par)
{
  Double_t back = par[0] + par[1]*x[0] + par[2]*x[0]*x[0];
  return back;
}
 ExtractQA.C:1
 ExtractQA.C:2
 ExtractQA.C:3
 ExtractQA.C:4
 ExtractQA.C:5
 ExtractQA.C:6
 ExtractQA.C:7
 ExtractQA.C:8
 ExtractQA.C:9
 ExtractQA.C:10
 ExtractQA.C:11
 ExtractQA.C:12
 ExtractQA.C:13
 ExtractQA.C:14
 ExtractQA.C:15
 ExtractQA.C:16
 ExtractQA.C:17
 ExtractQA.C:18
 ExtractQA.C:19
 ExtractQA.C:20
 ExtractQA.C:21
 ExtractQA.C:22
 ExtractQA.C:23
 ExtractQA.C:24
 ExtractQA.C:25
 ExtractQA.C:26
 ExtractQA.C:27
 ExtractQA.C:28
 ExtractQA.C:29
 ExtractQA.C:30
 ExtractQA.C:31
 ExtractQA.C:32
 ExtractQA.C:33
 ExtractQA.C:34
 ExtractQA.C:35
 ExtractQA.C:36
 ExtractQA.C:37
 ExtractQA.C:38
 ExtractQA.C:39
 ExtractQA.C:40
 ExtractQA.C:41
 ExtractQA.C:42
 ExtractQA.C:43
 ExtractQA.C:44
 ExtractQA.C:45
 ExtractQA.C:46
 ExtractQA.C:47
 ExtractQA.C:48
 ExtractQA.C:49
 ExtractQA.C:50
 ExtractQA.C:51
 ExtractQA.C:52
 ExtractQA.C:53
 ExtractQA.C:54
 ExtractQA.C:55
 ExtractQA.C:56
 ExtractQA.C:57
 ExtractQA.C:58
 ExtractQA.C:59
 ExtractQA.C:60
 ExtractQA.C:61
 ExtractQA.C:62
 ExtractQA.C:63
 ExtractQA.C:64
 ExtractQA.C:65
 ExtractQA.C:66
 ExtractQA.C:67
 ExtractQA.C:68
 ExtractQA.C:69
 ExtractQA.C:70
 ExtractQA.C:71
 ExtractQA.C:72
 ExtractQA.C:73
 ExtractQA.C:74
 ExtractQA.C:75
 ExtractQA.C:76
 ExtractQA.C:77
 ExtractQA.C:78
 ExtractQA.C:79
 ExtractQA.C:80
 ExtractQA.C:81
 ExtractQA.C:82
 ExtractQA.C:83
 ExtractQA.C:84
 ExtractQA.C:85
 ExtractQA.C:86
 ExtractQA.C:87
 ExtractQA.C:88
 ExtractQA.C:89
 ExtractQA.C:90
 ExtractQA.C:91
 ExtractQA.C:92
 ExtractQA.C:93
 ExtractQA.C:94
 ExtractQA.C:95
 ExtractQA.C:96
 ExtractQA.C:97
 ExtractQA.C:98
 ExtractQA.C:99
 ExtractQA.C:100
 ExtractQA.C:101
 ExtractQA.C:102
 ExtractQA.C:103
 ExtractQA.C:104
 ExtractQA.C:105
 ExtractQA.C:106
 ExtractQA.C:107
 ExtractQA.C:108
 ExtractQA.C:109
 ExtractQA.C:110
 ExtractQA.C:111
 ExtractQA.C:112
 ExtractQA.C:113
 ExtractQA.C:114
 ExtractQA.C:115
 ExtractQA.C:116
 ExtractQA.C:117
 ExtractQA.C:118
 ExtractQA.C:119
 ExtractQA.C:120
 ExtractQA.C:121
 ExtractQA.C:122
 ExtractQA.C:123
 ExtractQA.C:124
 ExtractQA.C:125
 ExtractQA.C:126
 ExtractQA.C:127
 ExtractQA.C:128
 ExtractQA.C:129
 ExtractQA.C:130
 ExtractQA.C:131
 ExtractQA.C:132
 ExtractQA.C:133
 ExtractQA.C:134
 ExtractQA.C:135
 ExtractQA.C:136
 ExtractQA.C:137
 ExtractQA.C:138
 ExtractQA.C:139
 ExtractQA.C:140
 ExtractQA.C:141
 ExtractQA.C:142
 ExtractQA.C:143
 ExtractQA.C:144
 ExtractQA.C:145
 ExtractQA.C:146
 ExtractQA.C:147
 ExtractQA.C:148
 ExtractQA.C:149
 ExtractQA.C:150
 ExtractQA.C:151
 ExtractQA.C:152
 ExtractQA.C:153
 ExtractQA.C:154
 ExtractQA.C:155
 ExtractQA.C:156
 ExtractQA.C:157
 ExtractQA.C:158
 ExtractQA.C:159
 ExtractQA.C:160
 ExtractQA.C:161
 ExtractQA.C:162
 ExtractQA.C:163
 ExtractQA.C:164
 ExtractQA.C:165
 ExtractQA.C:166
 ExtractQA.C:167
 ExtractQA.C:168
 ExtractQA.C:169
 ExtractQA.C:170
 ExtractQA.C:171
 ExtractQA.C:172
 ExtractQA.C:173
 ExtractQA.C:174
 ExtractQA.C:175
 ExtractQA.C:176
 ExtractQA.C:177
 ExtractQA.C:178
 ExtractQA.C:179
 ExtractQA.C:180
 ExtractQA.C:181
 ExtractQA.C:182
 ExtractQA.C:183
 ExtractQA.C:184
 ExtractQA.C:185
 ExtractQA.C:186
 ExtractQA.C:187
 ExtractQA.C:188
 ExtractQA.C:189
 ExtractQA.C:190
 ExtractQA.C:191
 ExtractQA.C:192
 ExtractQA.C:193
 ExtractQA.C:194
 ExtractQA.C:195
 ExtractQA.C:196
 ExtractQA.C:197
 ExtractQA.C:198
 ExtractQA.C:199
 ExtractQA.C:200
 ExtractQA.C:201
 ExtractQA.C:202
 ExtractQA.C:203
 ExtractQA.C:204
 ExtractQA.C:205
 ExtractQA.C:206
 ExtractQA.C:207
 ExtractQA.C:208
 ExtractQA.C:209
 ExtractQA.C:210
 ExtractQA.C:211
 ExtractQA.C:212
 ExtractQA.C:213
 ExtractQA.C:214
 ExtractQA.C:215
 ExtractQA.C:216
 ExtractQA.C:217
 ExtractQA.C:218
 ExtractQA.C:219
 ExtractQA.C:220
 ExtractQA.C:221
 ExtractQA.C:222
 ExtractQA.C:223
 ExtractQA.C:224
 ExtractQA.C:225
 ExtractQA.C:226
 ExtractQA.C:227
 ExtractQA.C:228
 ExtractQA.C:229
 ExtractQA.C:230
 ExtractQA.C:231
 ExtractQA.C:232
 ExtractQA.C:233
 ExtractQA.C:234
 ExtractQA.C:235
 ExtractQA.C:236
 ExtractQA.C:237
 ExtractQA.C:238
 ExtractQA.C:239
 ExtractQA.C:240
 ExtractQA.C:241
 ExtractQA.C:242
 ExtractQA.C:243
 ExtractQA.C:244
 ExtractQA.C:245
 ExtractQA.C:246
 ExtractQA.C:247
 ExtractQA.C:248
 ExtractQA.C:249
 ExtractQA.C:250
 ExtractQA.C:251
 ExtractQA.C:252
 ExtractQA.C:253
 ExtractQA.C:254
 ExtractQA.C:255
 ExtractQA.C:256
 ExtractQA.C:257
 ExtractQA.C:258
 ExtractQA.C:259
 ExtractQA.C:260
 ExtractQA.C:261
 ExtractQA.C:262
 ExtractQA.C:263
 ExtractQA.C:264
 ExtractQA.C:265
 ExtractQA.C:266
 ExtractQA.C:267
 ExtractQA.C:268
 ExtractQA.C:269
 ExtractQA.C:270
 ExtractQA.C:271
 ExtractQA.C:272
 ExtractQA.C:273
 ExtractQA.C:274
 ExtractQA.C:275
 ExtractQA.C:276
 ExtractQA.C:277
 ExtractQA.C:278
 ExtractQA.C:279
 ExtractQA.C:280
 ExtractQA.C:281
 ExtractQA.C:282
 ExtractQA.C:283
 ExtractQA.C:284
 ExtractQA.C:285
 ExtractQA.C:286
 ExtractQA.C:287
 ExtractQA.C:288
 ExtractQA.C:289
 ExtractQA.C:290
 ExtractQA.C:291
 ExtractQA.C:292
 ExtractQA.C:293
 ExtractQA.C:294
 ExtractQA.C:295
 ExtractQA.C:296
 ExtractQA.C:297
 ExtractQA.C:298
 ExtractQA.C:299
 ExtractQA.C:300
 ExtractQA.C:301
 ExtractQA.C:302
 ExtractQA.C:303
 ExtractQA.C:304
 ExtractQA.C:305
 ExtractQA.C:306
 ExtractQA.C:307
 ExtractQA.C:308
 ExtractQA.C:309
 ExtractQA.C:310
 ExtractQA.C:311
 ExtractQA.C:312
 ExtractQA.C:313
 ExtractQA.C:314
 ExtractQA.C:315
 ExtractQA.C:316
 ExtractQA.C:317
 ExtractQA.C:318
 ExtractQA.C:319
 ExtractQA.C:320
 ExtractQA.C:321
 ExtractQA.C:322
 ExtractQA.C:323
 ExtractQA.C:324
 ExtractQA.C:325
 ExtractQA.C:326
 ExtractQA.C:327
 ExtractQA.C:328
 ExtractQA.C:329
 ExtractQA.C:330
 ExtractQA.C:331
 ExtractQA.C:332
 ExtractQA.C:333
 ExtractQA.C:334
 ExtractQA.C:335
 ExtractQA.C:336
 ExtractQA.C:337
 ExtractQA.C:338
 ExtractQA.C:339
 ExtractQA.C:340
 ExtractQA.C:341
 ExtractQA.C:342
 ExtractQA.C:343
 ExtractQA.C:344
 ExtractQA.C:345
 ExtractQA.C:346
 ExtractQA.C:347
 ExtractQA.C:348
 ExtractQA.C:349
 ExtractQA.C:350
 ExtractQA.C:351
 ExtractQA.C:352
 ExtractQA.C:353
 ExtractQA.C:354
 ExtractQA.C:355
 ExtractQA.C:356
 ExtractQA.C:357
 ExtractQA.C:358
 ExtractQA.C:359
 ExtractQA.C:360
 ExtractQA.C:361
 ExtractQA.C:362
 ExtractQA.C:363
 ExtractQA.C:364
 ExtractQA.C:365
 ExtractQA.C:366
 ExtractQA.C:367
 ExtractQA.C:368
 ExtractQA.C:369
 ExtractQA.C:370
 ExtractQA.C:371
 ExtractQA.C:372
 ExtractQA.C:373
 ExtractQA.C:374
 ExtractQA.C:375
 ExtractQA.C:376
 ExtractQA.C:377
 ExtractQA.C:378
 ExtractQA.C:379
 ExtractQA.C:380
 ExtractQA.C:381
 ExtractQA.C:382
 ExtractQA.C:383
 ExtractQA.C:384
 ExtractQA.C:385
 ExtractQA.C:386
 ExtractQA.C:387
 ExtractQA.C:388
 ExtractQA.C:389
 ExtractQA.C:390
 ExtractQA.C:391
 ExtractQA.C:392
 ExtractQA.C:393
 ExtractQA.C:394
 ExtractQA.C:395
 ExtractQA.C:396
 ExtractQA.C:397
 ExtractQA.C:398
 ExtractQA.C:399
 ExtractQA.C:400
 ExtractQA.C:401
 ExtractQA.C:402
 ExtractQA.C:403
 ExtractQA.C:404
 ExtractQA.C:405
 ExtractQA.C:406
 ExtractQA.C:407
 ExtractQA.C:408
 ExtractQA.C:409
 ExtractQA.C:410
 ExtractQA.C:411
 ExtractQA.C:412
 ExtractQA.C:413
 ExtractQA.C:414
 ExtractQA.C:415
 ExtractQA.C:416
 ExtractQA.C:417
 ExtractQA.C:418
 ExtractQA.C:419
 ExtractQA.C:420
 ExtractQA.C:421
 ExtractQA.C:422
 ExtractQA.C:423
 ExtractQA.C:424
 ExtractQA.C:425
 ExtractQA.C:426
 ExtractQA.C:427
 ExtractQA.C:428
 ExtractQA.C:429
 ExtractQA.C:430
 ExtractQA.C:431
 ExtractQA.C:432
 ExtractQA.C:433
 ExtractQA.C:434
 ExtractQA.C:435
 ExtractQA.C:436
 ExtractQA.C:437
 ExtractQA.C:438
 ExtractQA.C:439
 ExtractQA.C:440
 ExtractQA.C:441
 ExtractQA.C:442
 ExtractQA.C:443
 ExtractQA.C:444
 ExtractQA.C:445
 ExtractQA.C:446
 ExtractQA.C:447
 ExtractQA.C:448
 ExtractQA.C:449
 ExtractQA.C:450
 ExtractQA.C:451
 ExtractQA.C:452
 ExtractQA.C:453
 ExtractQA.C:454
 ExtractQA.C:455
 ExtractQA.C:456
 ExtractQA.C:457
 ExtractQA.C:458
 ExtractQA.C:459
 ExtractQA.C:460
 ExtractQA.C:461
 ExtractQA.C:462
 ExtractQA.C:463
 ExtractQA.C:464
 ExtractQA.C:465
 ExtractQA.C:466
 ExtractQA.C:467
 ExtractQA.C:468
 ExtractQA.C:469
 ExtractQA.C:470
 ExtractQA.C:471
 ExtractQA.C:472
 ExtractQA.C:473
 ExtractQA.C:474
 ExtractQA.C:475
 ExtractQA.C:476
 ExtractQA.C:477
 ExtractQA.C:478
 ExtractQA.C:479
 ExtractQA.C:480
 ExtractQA.C:481
 ExtractQA.C:482
 ExtractQA.C:483
 ExtractQA.C:484
 ExtractQA.C:485
 ExtractQA.C:486
 ExtractQA.C:487
 ExtractQA.C:488
 ExtractQA.C:489
 ExtractQA.C:490
 ExtractQA.C:491
 ExtractQA.C:492
 ExtractQA.C:493
 ExtractQA.C:494
 ExtractQA.C:495
 ExtractQA.C:496
 ExtractQA.C:497
 ExtractQA.C:498
 ExtractQA.C:499
 ExtractQA.C:500
 ExtractQA.C:501
 ExtractQA.C:502
 ExtractQA.C:503
 ExtractQA.C:504
 ExtractQA.C:505
 ExtractQA.C:506
 ExtractQA.C:507
 ExtractQA.C:508
 ExtractQA.C:509
 ExtractQA.C:510
 ExtractQA.C:511
 ExtractQA.C:512
 ExtractQA.C:513
 ExtractQA.C:514
 ExtractQA.C:515
 ExtractQA.C:516
 ExtractQA.C:517
 ExtractQA.C:518
 ExtractQA.C:519
 ExtractQA.C:520
 ExtractQA.C:521
 ExtractQA.C:522
 ExtractQA.C:523
 ExtractQA.C:524
 ExtractQA.C:525
 ExtractQA.C:526
 ExtractQA.C:527
 ExtractQA.C:528
 ExtractQA.C:529
 ExtractQA.C:530
 ExtractQA.C:531
 ExtractQA.C:532
 ExtractQA.C:533
 ExtractQA.C:534
 ExtractQA.C:535
 ExtractQA.C:536
 ExtractQA.C:537
 ExtractQA.C:538
 ExtractQA.C:539
 ExtractQA.C:540
 ExtractQA.C:541
 ExtractQA.C:542
 ExtractQA.C:543
 ExtractQA.C:544
 ExtractQA.C:545
 ExtractQA.C:546
 ExtractQA.C:547
 ExtractQA.C:548
 ExtractQA.C:549
 ExtractQA.C:550
 ExtractQA.C:551
 ExtractQA.C:552
 ExtractQA.C:553
 ExtractQA.C:554
 ExtractQA.C:555
 ExtractQA.C:556
 ExtractQA.C:557
 ExtractQA.C:558
 ExtractQA.C:559
 ExtractQA.C:560
 ExtractQA.C:561
 ExtractQA.C:562
 ExtractQA.C:563
 ExtractQA.C:564
 ExtractQA.C:565
 ExtractQA.C:566
 ExtractQA.C:567
 ExtractQA.C:568
 ExtractQA.C:569
 ExtractQA.C:570
 ExtractQA.C:571
 ExtractQA.C:572
 ExtractQA.C:573
 ExtractQA.C:574
 ExtractQA.C:575
 ExtractQA.C:576
 ExtractQA.C:577
 ExtractQA.C:578
 ExtractQA.C:579
 ExtractQA.C:580
 ExtractQA.C:581
 ExtractQA.C:582
 ExtractQA.C:583
 ExtractQA.C:584
 ExtractQA.C:585
 ExtractQA.C:586
 ExtractQA.C:587
 ExtractQA.C:588
 ExtractQA.C:589
 ExtractQA.C:590
 ExtractQA.C:591
 ExtractQA.C:592
 ExtractQA.C:593
 ExtractQA.C:594
 ExtractQA.C:595
 ExtractQA.C:596
 ExtractQA.C:597
 ExtractQA.C:598
 ExtractQA.C:599
 ExtractQA.C:600
 ExtractQA.C:601
 ExtractQA.C:602
 ExtractQA.C:603
 ExtractQA.C:604
 ExtractQA.C:605
 ExtractQA.C:606
 ExtractQA.C:607
 ExtractQA.C:608
 ExtractQA.C:609
 ExtractQA.C:610
 ExtractQA.C:611
 ExtractQA.C:612
 ExtractQA.C:613
 ExtractQA.C:614
 ExtractQA.C:615
 ExtractQA.C:616
 ExtractQA.C:617
 ExtractQA.C:618
 ExtractQA.C:619
 ExtractQA.C:620
 ExtractQA.C:621
 ExtractQA.C:622
 ExtractQA.C:623
 ExtractQA.C:624
 ExtractQA.C:625
 ExtractQA.C:626
 ExtractQA.C:627
 ExtractQA.C:628
 ExtractQA.C:629
 ExtractQA.C:630
 ExtractQA.C:631
 ExtractQA.C:632
 ExtractQA.C:633
 ExtractQA.C:634
 ExtractQA.C:635
 ExtractQA.C:636
 ExtractQA.C:637
 ExtractQA.C:638
 ExtractQA.C:639
 ExtractQA.C:640
 ExtractQA.C:641
 ExtractQA.C:642
 ExtractQA.C:643
 ExtractQA.C:644
 ExtractQA.C:645
 ExtractQA.C:646
 ExtractQA.C:647
 ExtractQA.C:648
 ExtractQA.C:649
 ExtractQA.C:650
 ExtractQA.C:651
 ExtractQA.C:652
 ExtractQA.C:653
 ExtractQA.C:654
 ExtractQA.C:655
 ExtractQA.C:656
 ExtractQA.C:657
 ExtractQA.C:658
 ExtractQA.C:659
 ExtractQA.C:660
 ExtractQA.C:661
 ExtractQA.C:662
 ExtractQA.C:663
 ExtractQA.C:664
 ExtractQA.C:665
 ExtractQA.C:666
 ExtractQA.C:667
 ExtractQA.C:668
 ExtractQA.C:669
 ExtractQA.C:670
 ExtractQA.C:671
 ExtractQA.C:672
 ExtractQA.C:673
 ExtractQA.C:674
 ExtractQA.C:675
 ExtractQA.C:676
 ExtractQA.C:677
 ExtractQA.C:678
 ExtractQA.C:679
 ExtractQA.C:680
 ExtractQA.C:681
 ExtractQA.C:682
 ExtractQA.C:683
 ExtractQA.C:684
 ExtractQA.C:685
 ExtractQA.C:686
 ExtractQA.C:687
 ExtractQA.C:688
 ExtractQA.C:689
 ExtractQA.C:690
 ExtractQA.C:691
 ExtractQA.C:692
 ExtractQA.C:693
 ExtractQA.C:694
 ExtractQA.C:695
 ExtractQA.C:696
 ExtractQA.C:697
 ExtractQA.C:698
 ExtractQA.C:699
 ExtractQA.C:700
 ExtractQA.C:701
 ExtractQA.C:702
 ExtractQA.C:703
 ExtractQA.C:704
 ExtractQA.C:705
 ExtractQA.C:706
 ExtractQA.C:707
 ExtractQA.C:708
 ExtractQA.C:709
 ExtractQA.C:710
 ExtractQA.C:711
 ExtractQA.C:712
 ExtractQA.C:713
 ExtractQA.C:714
 ExtractQA.C:715
 ExtractQA.C:716
 ExtractQA.C:717
 ExtractQA.C:718
 ExtractQA.C:719
 ExtractQA.C:720
 ExtractQA.C:721
 ExtractQA.C:722
 ExtractQA.C:723
 ExtractQA.C:724
 ExtractQA.C:725
 ExtractQA.C:726
 ExtractQA.C:727
 ExtractQA.C:728
 ExtractQA.C:729
 ExtractQA.C:730
 ExtractQA.C:731
 ExtractQA.C:732
 ExtractQA.C:733
 ExtractQA.C:734
 ExtractQA.C:735
 ExtractQA.C:736
 ExtractQA.C:737
 ExtractQA.C:738
 ExtractQA.C:739
 ExtractQA.C:740
 ExtractQA.C:741
 ExtractQA.C:742
 ExtractQA.C:743
 ExtractQA.C:744
 ExtractQA.C:745
 ExtractQA.C:746
 ExtractQA.C:747
 ExtractQA.C:748
 ExtractQA.C:749
 ExtractQA.C:750
 ExtractQA.C:751
 ExtractQA.C:752
 ExtractQA.C:753
 ExtractQA.C:754
 ExtractQA.C:755
 ExtractQA.C:756
 ExtractQA.C:757
 ExtractQA.C:758
 ExtractQA.C:759
 ExtractQA.C:760
 ExtractQA.C:761
 ExtractQA.C:762
 ExtractQA.C:763
 ExtractQA.C:764
 ExtractQA.C:765
 ExtractQA.C:766
 ExtractQA.C:767
 ExtractQA.C:768
 ExtractQA.C:769
 ExtractQA.C:770
 ExtractQA.C:771
 ExtractQA.C:772
 ExtractQA.C:773
 ExtractQA.C:774
 ExtractQA.C:775
 ExtractQA.C:776
 ExtractQA.C:777
 ExtractQA.C:778
 ExtractQA.C:779
 ExtractQA.C:780
 ExtractQA.C:781
 ExtractQA.C:782
 ExtractQA.C:783
 ExtractQA.C:784
 ExtractQA.C:785
 ExtractQA.C:786
 ExtractQA.C:787
 ExtractQA.C:788
 ExtractQA.C:789
 ExtractQA.C:790
 ExtractQA.C:791
 ExtractQA.C:792
 ExtractQA.C:793
 ExtractQA.C:794
 ExtractQA.C:795
 ExtractQA.C:796
 ExtractQA.C:797
 ExtractQA.C:798
 ExtractQA.C:799
 ExtractQA.C:800
 ExtractQA.C:801
 ExtractQA.C:802
 ExtractQA.C:803
 ExtractQA.C:804
 ExtractQA.C:805
 ExtractQA.C:806
 ExtractQA.C:807
 ExtractQA.C:808
 ExtractQA.C:809
 ExtractQA.C:810
 ExtractQA.C:811
 ExtractQA.C:812
 ExtractQA.C:813
 ExtractQA.C:814
 ExtractQA.C:815
 ExtractQA.C:816
 ExtractQA.C:817
 ExtractQA.C:818
 ExtractQA.C:819
 ExtractQA.C:820
 ExtractQA.C:821
 ExtractQA.C:822
 ExtractQA.C:823
 ExtractQA.C:824
 ExtractQA.C:825
 ExtractQA.C:826
 ExtractQA.C:827
 ExtractQA.C:828
 ExtractQA.C:829
 ExtractQA.C:830
 ExtractQA.C:831
 ExtractQA.C:832
 ExtractQA.C:833
 ExtractQA.C:834
 ExtractQA.C:835
 ExtractQA.C:836
 ExtractQA.C:837
 ExtractQA.C:838
 ExtractQA.C:839
 ExtractQA.C:840
 ExtractQA.C:841
 ExtractQA.C:842
 ExtractQA.C:843
 ExtractQA.C:844
 ExtractQA.C:845
 ExtractQA.C:846
 ExtractQA.C:847
 ExtractQA.C:848
 ExtractQA.C:849
 ExtractQA.C:850
 ExtractQA.C:851
 ExtractQA.C:852
 ExtractQA.C:853
 ExtractQA.C:854
 ExtractQA.C:855
 ExtractQA.C:856
 ExtractQA.C:857
 ExtractQA.C:858
 ExtractQA.C:859
 ExtractQA.C:860
 ExtractQA.C:861
 ExtractQA.C:862
 ExtractQA.C:863
 ExtractQA.C:864
 ExtractQA.C:865
 ExtractQA.C:866
 ExtractQA.C:867
 ExtractQA.C:868
 ExtractQA.C:869
 ExtractQA.C:870
 ExtractQA.C:871
 ExtractQA.C:872
 ExtractQA.C:873
 ExtractQA.C:874
 ExtractQA.C:875
 ExtractQA.C:876
 ExtractQA.C:877
 ExtractQA.C:878
 ExtractQA.C:879
 ExtractQA.C:880
 ExtractQA.C:881
 ExtractQA.C:882
 ExtractQA.C:883
 ExtractQA.C:884
 ExtractQA.C:885
 ExtractQA.C:886
 ExtractQA.C:887
 ExtractQA.C:888
 ExtractQA.C:889
 ExtractQA.C:890
 ExtractQA.C:891
 ExtractQA.C:892
 ExtractQA.C:893
 ExtractQA.C:894
 ExtractQA.C:895
 ExtractQA.C:896
 ExtractQA.C:897
 ExtractQA.C:898
 ExtractQA.C:899
 ExtractQA.C:900
 ExtractQA.C:901
 ExtractQA.C:902
 ExtractQA.C:903
 ExtractQA.C:904
 ExtractQA.C:905
 ExtractQA.C:906
 ExtractQA.C:907
 ExtractQA.C:908
 ExtractQA.C:909
 ExtractQA.C:910
 ExtractQA.C:911
 ExtractQA.C:912
 ExtractQA.C:913