Example #1
0
void OccupancyAscii2OCDB(Int_t runNumber,
                         const char* filename,
                         const char* ocdbpath,
                         const char* comment)
{
    TObjArray a;
    a.SetOwner(kTRUE);
    a.Add(new TObjString(filename));
    OccupancyAscii2OCDB(runNumber,a,ocdbpath,comment);
}
Example #2
0
bool FindDataSample(const TMap &lookup, TObjArray &sampleinfis){
        //
        // Find Data sample in the list of samples
        //
        TObjArray *entry = dynamic_cast<TObjArray *>(lookup.GetValue(g_sample.Data()));
        if(!entry){
                printf("Sample %s not found in the list of samples", g_sample.Data());
                return false;
        }
        // Copy to output container
        sampleinfis.SetOwner(kFALSE);
        for(int ival = 0; ival < 4; ival++) sampleinfis.AddAt(entry->At(ival), ival);
        return true;
}
Example #3
0
TMap* CreateDCSAliasMap()
{
  // Creates a DCS structure
  // The structure is the following:
  //   TMap (key --> value)
  //     <DCSAlias> --> <valueList>
  //     <DCSAlias> is a string
  //     <valueList> is a TObjArray of AliDCSValue
  //     An AliDCSValue consists of timestamp and a value in form of a AliSimpleValue

  // In this example 6 aliases exists: DCSAlias1 ... DCSAlias6
  // Each contains 1000 values randomly generated by TRandom::Gaus + 5*nAlias

  TMap* aliasMap = new TMap;
  aliasMap->SetOwner(1);
  TRandom random;

	FILE *fp = fopen("./DCSValues.txt","r");

	char name[50];
	Float_t val;
	while(!(EOF == fscanf(fp,"%s %f",name,&val))){
		TObjArray* valueSet = new TObjArray;
		valueSet->SetOwner(1);

		TString aliasName=name;
		
		//printf("alias: %s\t\t",aliasName.Data());

		int timeStamp=10;
		
		
		if(aliasName.Contains("HV")) {
			for(int i=0;i<200;i++){
				dcsVal = new AliDCSValue((Float_t) (val+random.Gaus(0,val*0.1)), timeStamp+10*i);
				valueSet->Add(dcsVal);
			}
		} else {
			for(int i=0;i<2;i++){
				AliDCSValue* dcsVal = new AliDCSValue((UInt_t) (val), timeStamp+10*i);
				valueSet->Add(dcsVal);
			}
		}
		
		aliasMap->Add(new TObjString(aliasName), valueSet);

	}
	fclose(fp);
  return aliasMap;
}
Example #4
0
	float PhiLab( const PseudoJet& jet, Double_t PzInLepton, Double_t PzInHadron, TLorentzVector electron )
	{
		TLorentzVector p;
		p . SetPxPyPzE( jet.px(), jet.py(), jet.pz(), jet.e() );
		TObjArray InputCand;
		InputCand.Add( &p );
		
		TObjArray OutputCand;
		Dijets::BreitBoost( InputCand,  OutputCand, PzInLepton, PzInHadron, electron, 2 );
		OutputCand.SetOwner();
		float phi = (static_cast<TLorentzVector*>(OutputCand.At(0))) -> Phi();
		OutputCand.Clear();
		return phi;
	}
Example #5
0
TObjArray* KVRangeYanez::GetListOfMaterials()
{
   // Create and fill a list of all materials for which range tables exist.
   // Each entry is a TNamed with the name and type (title) of the material.
   // User's responsibility to delete list after use (it owns its objects).

   TObjArray* list = new TObjArray(fMaterials->GetEntries());
   list->SetOwner(kTRUE);
   TIter next(fMaterials);
   KVIonRangeTableMaterial* mat;
   while ((mat = (KVIonRangeTableMaterial*)next())) {
      list->Add(new TNamed(mat->GetName(), mat->GetType()));
   }
   return list;
}
Example #6
0
void OccupancyHLTtest()
{
//  tail -c +205 EOR_mch-occupancy_0x02_HLT\:FXS_CAL  | more > toto
// mv toto EOR_mch-occupancy_0x02_HLT\:FXS_CAL

    TObjArray hlt;
    hlt.SetOwner(kTRUE);

    hlt.Add(new TObjString("EOR_mch-occupancy_0x02_HLT:FXS_CAL"));
    hlt.Add(new TObjString("EOR_mch-occupancy_0x03_HLT:FXS_CAL"));

    OccupancyAscii2OCDB(196474,hlt,"alien://folder=/alice/cern.ch/user/l/laphecet/HCDB","HLT");
    OccupancyAscii2OCDB(196474,"occupancy.000196474082.15","alien://folder=/alice/cern.ch/user/l/laphecet/OCDB",
                        "occupancy.000196474082.15");
}
//_______________________________________
TObjArray* GetTerminateOptions ( TString taskOpt, Bool_t isMC )
{
  TObjArray* terminateList = 0x0;
  if ( ! taskOpt.IsNull() ) {
    TObjArray* optList = taskOpt.Tokenize(";");
    for ( Int_t iopt=0; iopt<optList->GetEntries(); iopt++ ) {
      TString currOpt = (static_cast<TObjString*>(optList->At(iopt)))->GetString();
      if ( ! currOpt.Contains("@") ) continue;
      TObjArray* tmpList = currOpt.Tokenize("@");
      if ( tmpList->GetEntries() == 4 ) {
        terminateList = tmpList;
        break;
      }
      delete tmpList;
    }
    delete optList;
  }
  else {
    terminateList = new TObjArray(4);
    terminateList->SetOwner();
    TString physSel = "", trigClasses = "", centr = "", furtherOpt = "";
    if ( isMC ) {
      physSel = "PhysSelPass,PhysSelReject";
      trigClasses = "ANY";
      centr = "-5_105";
      furtherOpt = "MC verbose";
    }
    //TString GetPeriod(opt);
    terminateList->AddAt(new TObjString(physSel),0);
    terminateList->AddAt(new TObjString(trigClasses),1);
    terminateList->AddAt(new TObjString(centr),2);
    terminateList->AddAt(new TObjString(furtherOpt),3);
  }
  
//  if ( terminateList ) {
//    printf("Printing terminate list\n"); // REMEMBER TO CUT
//    PrintNames("Terminate options", terminateList);
//    printf(" ***************:\n");
//  }
  
  return terminateList;
}
Example #8
0
void AddFit(TH2* h2d)
{
  //
  // Fit in slices and draw mean and sigma
  //
  TF1 *f1 = new TF1("f1", "gaus");
  f1->SetRange(-1.5,1.5);
  TObjArray aSlices;
  h2d->FitSlicesY(f1, 0,-1, 0, "QNR",&aSlices);
  aSlices.SetOwner(1);
  TH1* hMean=(TH1*)aSlices.At(1);
  TH1* hSigma=(TH1*)aSlices.At(2);
  TH1* hChi2=(TH1*)aSlices.At(3);
  hChi2->Scale(1./10.);
  aSlices.AddAt(0x0,1);
  aSlices.AddAt(0x0,2);
  aSlices.AddAt(0x0,3);
  hMean->SetMarkerStyle(20);
  hMean->SetMarkerSize(0.3);
  hMean->SetOption("same");
  h2d->GetListOfFunctions()->Add(hMean);
  hSigma->SetMarkerStyle(20);
  hSigma->SetMarkerSize(0.3);
  hSigma->SetOption("same");
  hSigma->SetMarkerColor(kMagenta);
  h2d->GetListOfFunctions()->Add(hSigma);
  hChi2->SetOption("same");
  hChi2->SetMarkerColor(kMagenta + 2);
  hChi2->SetLineColor(kMagenta + 2);
  h2d->GetListOfFunctions()->Add(hChi2);

  TLine *l=0x0;
  l=new TLine(h2d->GetXaxis()->GetXmin(),0,h2d->GetXaxis()->GetXmax(),0);
  l->SetLineStyle(2);
  h2d->GetListOfFunctions()->Add(l);
  l=new TLine(h2d->GetXaxis()->GetXmin(),1,h2d->GetXaxis()->GetXmax(),1);
  l->SetLineStyle(2);
  h2d->GetListOfFunctions()->Add(l);
}
Example #9
0
void buildFakeAngTree(const Char_t* outtag,
                      const Float_t timereso,     // ns
                      const UInt_t  simevts=1,
                      const Float_t thetaOpt=400, // deg
                      const Float_t phiOpt=400,   // deg
                      const Float_t coneOpt=400,  // deg
                      const UInt_t  rseed=23192,
                      const Float_t norm=100.0,   // mV
                      const Float_t noise=20.0,   // mV
                      const Char_t* outdir="/data/users/cjreed/work/simEvts",
                      const Char_t* infn="/w2/arianna/jtatar/nt.sigtemps.root",
                      const Char_t* geofn="/data/users/cjreed/work/"
                                          "BounceStudy/Stn10/"
                                          "CampSiteGeometry.root") {
   // if any of the angles (thetaOpt, phiOpt, coneOpt) > 360, a random
   // value will be used instead
   //
   // expect angles in the Templates tree to be in degrees
   //
   // expect the waveforms in the Templates tree to have amplitude 1
   
   TRandom3 rnd(rseed);
   
   
   geof = TFile::Open(geofn);
   gg = dynamic_cast<TGeoManager*>(geof->Get("CampSite2013"));
   site = dynamic_cast<const TSnGeoStnSite*>(gg->GetTopVolume());
   
   
   TVector3 pos[NSnConstants::kNchans], nvec[NSnConstants::kNchans];
   for (UChar_t ch=0; ch<NSnConstants::kNchans; ++ch) {
      site->SetLPDAPosition(ch, pos[ch]);
      site->SetLPDANormalVec(ch, nvec[ch]);
      Printf("pos ch%d:",ch);
      pos[ch].Print();
      Printf("normal ch%d:",ch);
      nvec[ch].Print();
   }
   
   TArrayD zeros(6);
   
   
   inf = TFile::Open(infn);
   nnt = dynamic_cast<TTree*>(inf->Get("Templates"));
   
   TString infns(infn);
   TString indir;
   Int_t fl(0);
   if (infns.Contains('/')) {
      fl = infns.Last('/') + 1;
      indir = infns(0, fl-1);
   }
   TString plaininfn = infns(fl, infns.Length()-fl);
   TString outfn = Form("%s/FakeEvts.%s.%s", outdir, outtag,
                        plaininfn.Data());
   outf = TFile::Open(outfn.Data(),"recreate");
   outf->cd();
   TParameter<Float_t> trp("TimeResolution", timereso);
   trp.Write();
   TParameter<Float_t> nmp("Normalization", norm);
   nmp.Write();
   TParameter<Float_t> nop("NoiseRMS", noise);
   nop.Write();
   TParameter<UInt_t> rsp("RandomSeed", rseed);
   rsp.Write();
   
   
   TSnCalWvData* wave = new TSnCalWvData;
   Float_t eang(0), hang(0), hpf(0), limiter(0), coneang(0);
   Bool_t bice(kFALSE);
   nnt->SetBranchAddress("wave.",&wave);
   nnt->SetBranchAddress("EAng",&eang);
   nnt->SetBranchAddress("HAng",&hang);
   nnt->SetBranchAddress("hpf",&hpf);
   nnt->SetBranchAddress("limiter",&limiter);
   nnt->SetBranchAddress("coneAng",&coneang);
   nnt->SetBranchAddress("bIce",&bice);
   // to look up waveform for EAng, HAng
   nnt->BuildIndex("EAng + (1000*HAng)","coneAng");
   // find the max angles
   Printf("finding allowed angles...");
   std::set<Float_t> Eangs, Hangs, Cangs;
   const Long64_t nnents = nnt->GetEntries();
   for (Long64_t i=0; i<nnents; ++i) {
      nnt->GetEntry(i);
      Eangs.insert(eang);
      Hangs.insert(hang);
      Cangs.insert(coneang);
   }
#ifdef DEBUG
   std::set<Float_t>::const_iterator ang, end = Eangs.end();
   Printf("EAngs:");
   for (ang=Eangs.begin(); ang!=end; ++ang) {
      Printf("%g",*ang);
   }
   Printf("HAngs:");
   for (ang=Hangs.begin(), end=Hangs.end(); ang!=end; ++ang) {
      Printf("%g",*ang);
   }
   Printf("ConeAngs:");
   for (ang=Cangs.begin(), end=Cangs.end(); ang!=end; ++ang) {
      Printf("%g",*ang);
   }
#endif
   
   Float_t theta(0), phi(0), cone(0);
   Float_t EAng[NSnConstants::kNchans], 
           HAng[NSnConstants::kNchans];
   Float_t CAng(0);
   TSnCalWvData* evdat = new TSnCalWvData;
   TSnEventMetadata* meta = new TSnEventMetadata;
   TSnEventHeader* hdr = new TSnEventHeader;
   //ot = nnt->CloneTree(0);
   //ot->SetName("SimTemplEvts");
   ot = new TTree("SimTemplEvts","simulated events from templates",1);
   ot->SetDirectory(outf);
   ot->Branch("EventMetadata.",&meta);
   ot->Branch("EventHeader.",&hdr);
   ot->Branch("EAng",&(EAng[0]),Form("EAng[%hhu]/F",NSnConstants::kNchans));
   ot->Branch("HAng",&(HAng[0]),Form("HAng[%hhu]/F",NSnConstants::kNchans));
   ot->Branch("CAng",&CAng,"CAng/F");
   ot->Branch("theta",&theta,"theta/F");
   ot->Branch("phi",&phi,"phi/F");
   ot->Branch("NuData.",&evdat);
   // some useful aliases
   TString an;
   for (UChar_t ch=0; ch<NSnConstants::kNchans; ++ch) {
      // to use as a cut for a particular channel:
      an = Form("Ch%d",ch);
      ot->SetAlias(an.Data(),
                   Form("(Iteration$>=(%hhu*%hhu)) && (Iteration$<(%hhu*%hhu))",
                        NSnConstants::kNsamps, ch,
                        NSnConstants::kNsamps,
                        static_cast<UChar_t>(ch+1)));
      // to use as a variable showing the sample number [0,127] for any chan
      an = Form("SmpCh%d",ch);
      ot->SetAlias(an.Data(),
                   Form("Iteration$-%u", static_cast<UInt_t>(ch)
                        *static_cast<UInt_t>(NSnConstants::kNsamps)));
      // e.g. Draw("RawData.fData:SmpCh2","EventHeader.fNum==21 && Ch2","l")
   }

   Printf("generating events...");
   TStopwatch timer;
   timer.Start();
   
   for (UInt_t i=0; i<simevts; ++i) {
      
      if ( (i%1000)==0 ) {
         fprintf(stderr,"Processing %u/%u ...            \r",i,simevts);
      }
      
      // choose angles
      theta = (thetaOpt>360.) ? TMath::ACos( rnd.Uniform(-1.0, 0.0) ) 
                              : thetaOpt * TMath::DegToRad();
      phi   = (phiOpt>360.) ? rnd.Uniform(0.0, TMath::TwoPi())
                            : phiOpt * TMath::DegToRad();
      cone  = (coneOpt>360.) 
         ? rnd.Uniform(*(Cangs.begin()), *(Cangs.rbegin()))
         : coneOpt; // leave this one in degrees (as in the tree)
      CAng = findNearestAllowedAngle(Cangs, cone);
      
#ifdef DEBUG
      Printf("--- theta=%g, phi=%g, cone=%g",
             theta*TMath::RadToDeg(), phi*TMath::RadToDeg(), cone);
#endif
      
      // calculate channel shifts
      TArrayD pwdt = NSnChanCorl::GetPlaneWaveOffsets(theta,
                                                      phi,
                                                      zeros,
                                                      pos,
                                                      kNgTopFirn);
      TVector3 dir;
      dir.SetMagThetaPhi(1.0, theta, phi);
      
#ifdef DEBUG
      TObjArray graphs;
      graphs.SetOwner(kTRUE);
      TCanvas* c1 = new TCanvas("c1","c1",800,700);
      c1->Divide(2,2);
#endif
      
      for (UChar_t ch=0; ch<NSnConstants::kNchans; ++ch) {
         
         // look up the EAng, fhang for this antenna
         Float_t feang(0), fhang(0);
         findEangHang(nvec[ch], dir, feang, fhang);
         feang  = TMath::Abs(TVector2::Phi_mpi_pi(feang));
         fhang  = TMath::Abs(TVector2::Phi_mpi_pi(fhang));
         feang *= TMath::RadToDeg();
         fhang *= TMath::RadToDeg();
         // find closest allowed angle
         EAng[ch] = findNearestAllowedAngle(Eangs, feang);
         HAng[ch] = findNearestAllowedAngle(Hangs, fhang);
         const Long64_t ni = 
            nnt->GetEntryNumberWithIndex(EAng[ch] + (1000*HAng[ch]), CAng);
#ifdef DEBUG
         Printf("EAng=%g (%g), HAng=%g (%g), CAng=%g, ni=%lld",
                EAng[ch],feang,HAng[ch],fhang,CAng,ni);
#endif
         if (ni>-1) {
            nnt->GetEntry(ni);
#ifdef DEBUG
            c1->cd(ch+1);
            TGraph* och = wave->NewGraphForChan(0, kTRUE);
            const Int_t ochnp = och->GetN();
            Double_t* ochy = och->GetY();
            for (Int_t k=0; k<ochnp; ++k, ++ochy) {
               *ochy *= norm;
            }
            graphs.Add(och);
            och->SetLineColor(kBlack);
            och->SetMarkerColor(kBlack);
            och->SetMarkerStyle(7);
            och->Draw("apl");
#endif
            
            // first calculate the shift between chans due to the angle
            // ch0 is always unshifted; other chans shifted w.r.t. ch0
            // jitter the shift by the specified timing resolution
            const Double_t shift = 
               rnd.Gaus( (ch==0) ? 0.0
                            : -pwdt.At( TSnRecoChanOffsets::IndexFor(ch, 0) ),
                         timereso);
            // get a graph of the waveform
            // data only in channel 0 of the template
            TGraph* gch = wave->NewGraphForChan(0, kTRUE);
            // "fit" the graph with an spline interpolation
            TSpline3* gsp = new TSpline3("stmp", gch);
            // evaluate the spline at the new sample positions
            // (shifted, but NOT wrapped)
            // and save that into the event data waveform
            Float_t* d = evdat->GetData(ch);
            const Float_t tstep = 1.0 / NSnConstants::kSampRate;
            const Float_t tlast = static_cast<Float_t>(NSnConstants::kNsamps-1)
               / NSnConstants::kSampRate;
            Float_t xloc = shift;
            for (UChar_t s=0; s<NSnConstants::kNsamps; ++s, ++d, xloc+=tstep) {
               if ( (xloc<0.0) || (xloc>=tlast) ) {
                  *d = 0.0;
               } else {
                  *d = gsp->Eval( xloc );
               }
            }
#ifdef DEBUG
            Printf("ch%hhu: shift=%g, dt=%g", ch, shift,
                   (ch==0) ? 0.0
                   : pwdt.At( TSnRecoChanOffsets::IndexFor(ch, 0) ));
            
            TGraph* fch = evdat->NewGraphForChan(ch, kTRUE);
            Double_t* y = gch->GetY();
            Double_t* fy = fch->GetY();
            for (UChar_t s=0; s<NSnConstants::kNsamps; ++s, ++y, ++fy) {
               *y *= norm;
               *fy *= norm;
            }
            
            gch->SetLineColor(kRed+1);
            gch->SetMarkerColor(kRed+1);
            gch->SetMarkerStyle(7);
            gch->Draw("pl");
            
            delete gsp;
            gsp = new TSpline3("stmp",gch);
            gsp->SetLineColor(kAzure-6);
            gsp->SetMarkerColor(kAzure-6);
            gsp->SetMarkerStyle(7);
            gsp->Draw("pl same");
            
            graphs.Add(fch);
            fch->SetLineColor(kOrange+7);
            fch->SetMarkerColor(kOrange+7);
            fch->SetMarkerStyle(7);
            fch->Draw("pl");
#endif


            d = evdat->GetData(ch);
            // finally add noise to the waveform
            for (UChar_t s=0; s<NSnConstants::kNsamps; ++s, ++d) {
               *d = rnd.Gaus( (*d) * norm, noise );
            }
            
#ifdef DEBUG
            TGraph* nch = evdat->NewGraphForChan(ch, kTRUE);
            graphs.Add(nch);
            nch->SetLineColor(kGreen+2);
            nch->SetMarkerColor(kGreen+2);
            nch->SetMarkerStyle(7);
            nch->Draw("pl");
#endif
            
            // cleanup
#ifdef DEBUG
            graphs.Add(gch);
            graphs.Add(gsp);
#else
            delete gch;
            delete gsp;
#endif
         }

      } // end channel loop

#ifdef DEBUG
      TObject* o(0);
      while ( (o=c1->WaitPrimitive())!=0 ) {
         gSystem->ProcessEvents();
      }
      delete c1;
#endif
         
         // save this event
         ot->Fill();
         
   } // end event loop

   fprintf(stderr,"\n");

   timer.Stop();
   Printf("Finished generating events in:");
   timer.Print();
   
   outf->Write();
   
   Printf("Wrote [%s]",outf->GetName());
   
   delete outf; outf=0; // close file
}
Example #10
0
void fitter(
            const string workDirName="Test", // Working directory
            // Select the type of datasets to fit
            bool fitData     = true,         // Fits Data if true, otherwise fits MC
            bool fitPbPb     = true,         // Fits PbPb datasets
            bool fitPP       = true,         // Fits PP datasets
            // Select the type of object to fit
            bool incJpsi     = true,         // Includes Jpsi model
            bool incPsi2S    = true,         // Includes Psi(2S) model
            bool incBkg      = true,         // Includes Background model
            // Select the fitting options
            bool cutCtau     = false,        // Apply prompt ctau cuts
            bool doSimulFit  = false,        // Do simultaneous fit
            bool wantPureSMC = false,        // Flag to indicate if we want to fit pure signal MC
            int  numCores    = 2,            // Number of cores used for fitting
            // Select the drawing options
            bool setLogScale = true,         // Draw plot with log scale
            bool incSS       = false,        // Include Same Sign data
            bool zoomPsi     = false,        // Zoom Psi(2S) peak on extra pad
            int  nBins       = 54            // Number of bins used for plotting
            ) 
{
  // -------------------------------------------------------------------------------
  // STEP 0: INITIALIZE THE FITTER WORK ENVIROMENT
  // The work enviroment is divided as follows:
  /*
    main |-> Macros: Contain all the macros
         |-> Input   |-> <WorkDir> : Contain Input File, Bin and Parameter List for a given work directory (e.g. 20160201)
	 |-> Output  |-> <WorkDir> : Contain Output Plots and Results for a given work directory (e.g. 20160201)
	 |-> DataSet : Contain all the datasets (MC and Data)
  */

  if (!checkSettings(fitData, fitPbPb, fitPP, incJpsi, incPsi2S, incBkg, cutCtau, doSimulFit, wantPureSMC, setLogScale, zoomPsi, incSS, numCores, nBins)) { return; }

  map<string,string> DIR;
  if(!iniWorkEnv(DIR, workDirName)){ return; }
 
  // -------------------------------------------------------------------------------
  // STEP 1: CREATE/LOAD THE ROODATASETS
  /*
    Input : List of TTrees with format:  TAG <tab> FILE_NAME
    Output: Collection of RooDataSets splitted by tag name, including OS and SS dimuons.
  */
  
  const string InputTrees = DIR["input"] + "InputTrees.txt";
  map<string, vector<string> > InputFileCollection;
  if(!getInputFileNames(InputTrees, InputFileCollection)){ return; }
  
  TObjArray* aDSTAG = new TObjArray(); // Array to store the different tags in the list of trees
  aDSTAG->SetOwner(true);
  map<string, RooWorkspace> Workspace;

  for(map<string, vector<string> >::iterator FileCollection=InputFileCollection.begin(); FileCollection!=InputFileCollection.end(); ++FileCollection) {
    // Get the file tag which has the following format: DSTAG_COLL , i.e. DATA_PP 
    string FILETAG = FileCollection->first;  
    string DSTAG   = FILETAG;
    if (FILETAG.size()) {
      DSTAG.erase(DSTAG.find("_"));
    } else {
      cout << "[ERROR] FILETAG is empty!" << endl;
    }
    // Extract the filenames
    vector<string> InputFileNames = FileCollection->second; 
    string         OutputFileName;
    // If we have data, check if the user wants to fit data
    if ( (FILETAG.find("DATA")!=std::string::npos) && fitData==true ) {
      if ( (FILETAG.find("PP")!=std::string::npos)   && !fitPP   ) continue; // If we find PP, check if the user wants PP
      if ( (FILETAG.find("PbPb")!=std::string::npos) && !fitPbPb ) continue; // If we find PbPb, check if the user wants PbPb
      OutputFileName = DIR["dataset"] + "DATASET_" + FILETAG + ".root";
      if(!tree2DataSet(Workspace[DSTAG], InputFileNames, FILETAG, OutputFileName)){ return; }
      if (!aDSTAG->FindObject(DSTAG.c_str())) aDSTAG->Add(new TObjString(DSTAG.c_str()));
    }
    // If we find MC, check if the user wants to fit MC
    if ( (FILETAG.find("MC")!=std::string::npos) && fitData==false ) {
      if ( (FILETAG.find("PP")!=std::string::npos)    && !fitPP    ) continue; // If we find PP, check if the user wants PP
      if ( (FILETAG.find("PbPb")!=std::string::npos)  && !fitPbPb  ) continue; // If we find PbPb, check if the user wants PbPb
      if ( (FILETAG.find("JPSI")!=std::string::npos)  && !incJpsi  ) continue; // If we find Jpsi MC, check if the user wants to include Jpsi
      if ( (FILETAG.find("PSI2S")!=std::string::npos) && !incPsi2S ) continue; // If we find Psi2S MC, check if the user wants to include Psi2S
      OutputFileName = DIR["dataset"] + "DATASET_" + FILETAG + ".root";
      if(!tree2DataSet(Workspace[DSTAG], InputFileNames, FILETAG, OutputFileName)){ return; }
      if (!aDSTAG->FindObject(DSTAG.c_str())) aDSTAG->Add(new TObjString(DSTAG.c_str()));
      if (wantPureSMC)
      {
        OutputFileName = DIR["dataset"] + "DATASET_" + FILETAG + "_PureS" + ".root";
        if(!tree2DataSet(Workspace[Form("%s_PureS",DSTAG.c_str())], InputFileNames, FILETAG, OutputFileName)){ return; }
      }
    } 
  }
  if (Workspace.size()==0) {
    cout << "[ERROR] No onia tree files were found matching the user's input settings!" << endl; return;
  }

  // -------------------------------------------------------------------------------
  // STEP 2: LOAD THE INITIAL PARAMETERS
  /*
    Input : List of initial parameters with format PT <tab> RAP <tab> CEN <tab> iniPar ... 
    Output: two vectors with one entry per kinematic bin filled with the cuts and initial parameters
  */
  
  string InputFile;
  vector< struct KinCuts >       cutVector;
  vector< map<string, string> >  parIniVector;
 
  if (fitPbPb && incBkg) {
    // Add initial parameters for PbPb background models
    InputFile = (DIR["input"] + "InitialParam_MASS_BKG_PbPb.csv");
    if (!addParameters(InputFile, cutVector, parIniVector, true)) { return; }
  } 
  if (fitPbPb && incJpsi) {
    // Add initial parameters for PbPb jpsi models
    InputFile = (DIR["input"] + "InitialParam_MASS_JPSI_PbPb.csv");
    if (!addParameters(InputFile, cutVector, parIniVector, true)) { return; }
  } 
  if (fitPbPb && incPsi2S) {
    // Add initial parameters for PbPb psi(2S) models
    InputFile = (DIR["input"] + "InitialParam_MASS_PSI2S_PbPb.csv");
    if (!addParameters(InputFile, cutVector, parIniVector, true)) { return; }
  } 
  if (fitPP && incBkg) {
    // Add initial parameters for PP background models
    InputFile = (DIR["input"] + "InitialParam_MASS_BKG_PP.csv");
    if (!addParameters(InputFile, cutVector, parIniVector, false)) { return; }
  } 
  if (fitPP && incJpsi) {
    // Add initial parameters for PP jpsi models
    InputFile = (DIR["input"] + "InitialParam_MASS_JPSI_PP.csv");
    if (!addParameters(InputFile, cutVector, parIniVector, false)) { return; }
  } 
  if (fitPP && incPsi2S) {
    // Add initial parameters for PP psi(2S) models
    InputFile = (DIR["input"] + "InitialParam_MASS_PSI2S_PP.csv");
    if (!addParameters(InputFile, cutVector, parIniVector, false)) { return; }
  }

  // -------------------------------------------------------------------------------  
  // STEP 3: FIT THE DATASETS
  /*
    Input : 
              -> The cuts and initial parameters per kinematic bin
	      -> The workspace with the full datasets included.
    Output: 
              -> Plots (png, pdf and root format) of each fit.
	      -> The local workspace used for each fit.
  */
  
  TIter nextDSTAG(aDSTAG);
  string outputDir = DIR["output"];
  for (unsigned int i=0; i<cutVector.size(); i++) {

    nextDSTAG.Reset();
    TObjString* soDSTAG(0x0);
    while ( (soDSTAG = static_cast<TObjString*>(nextDSTAG.Next())) )
    {
      TString DSTAG   = static_cast<TString>(soDSTAG->GetString());
      
      if (Workspace.count(DSTAG.Data())>0) {
        // DATA/MC datasets were loaded
        if (doSimulFit) {
          // If do simultaneous fits, then just fits once
          if (!fitCharmonia( Workspace[DSTAG.Data()], cutVector.at(i), parIniVector.at(i), outputDir,
                             // Select the type of datasets to fit
                             DSTAG.Data(),
                             false,           // dummy flag when fitting simultaneously since both PP and PbPb are used
                             // Select the type of object to fit
                             incJpsi,         // Includes Jpsi model
                             incPsi2S,        // Includes Psi(2S) model
                             incBkg,          // Includes Background model
                             // Select the fitting options
                             cutCtau,         // Apply prompt ctau cuts
                             true,            // Do simultaneous fit
                             wantPureSMC,     // Flag to indicate if we want to fit pure signal MC
                             numCores,        // Number of cores used for fitting
                             // Select the drawing options
                             setLogScale,     // Draw plot with log scale
                             incSS,           // Include Same Sign data
                             zoomPsi,         // Zoom Psi(2S) peak on extra pad
                             nBins,           // Number of bins used for plotting
                             false            // Compute the mean PT (NEED TO FIX)
                             )
              ) { return; }
        } else {
          // If don't want simultaneous fits, then fit PbPb or PP separately
          if ( DSTAG.Contains("MCJPSI")  ) { incJpsi = true;  incPsi2S = false; }
          if ( DSTAG.Contains("MCPSI2S") ) { incJpsi = false; incPsi2S = true;  }
            
          if (fitPbPb) {
            if (!fitCharmonia( Workspace[DSTAG.Data()], cutVector.at(i), parIniVector.at(i), outputDir,
                               // Select the type of datasets to fit
                               DSTAG.Data(),
                               true,            // In this case we are fitting PbPb
                               // Select the type of object to fit
                               incJpsi,         // Includes Jpsi model
                               incPsi2S,        // Includes Psi(2S) model
                               incBkg,          // Includes Background model
                               // Select the fitting options
                               cutCtau,         // Apply prompt ctau cuts
                               false,           // Do simultaneous fit
                               false,     // Flag to indicate if we want to fit pure signal MC
                               numCores,        // Number of cores used for fitting
                               // Select the drawing options
                               setLogScale,     // Draw plot with log scale
                               incSS,           // Include Same Sign data
                               zoomPsi,         // Zoom Psi(2S) peak on extra pad
                               nBins,           // Number of bins used for plotting
                               false            // Compute the mean PT (NEED TO FIX)
                               )
                ) { return; }
            if (DSTAG.Contains("MC") && wantPureSMC)
            {
              if (!fitCharmonia( Workspace[Form("%s_PureS",DSTAG.Data())], cutVector.at(i), parIniVector.at(i), outputDir,
                                // Select the type of datasets to fit
                                DSTAG.Data(),
                                true,            // In this case we are fitting PbPb
                                // Select the type of object to fit
                                incJpsi,         // Includes Jpsi model
                                incPsi2S,        // Includes Psi(2S) model
                                incBkg,          // Includes Background model
                                // Select the fitting options
                                cutCtau,         // Apply prompt ctau cuts
                                false,           // Do simultaneous fit
                                true,            // Flag to indicate if we want to fit pure signal MC
                                numCores,        // Number of cores used for fitting
                                // Select the drawing options
                                setLogScale,     // Draw plot with log scale
                                incSS,           // Include Same Sign data
                                zoomPsi,         // Zoom Psi(2S) peak on extra pad
                                nBins,           // Number of bins used for plotting
                                false            // Compute the mean PT (NEED TO FIX)
                                )
                  ) { return; }
            }
          }
          if (fitPP) {
            if (!fitCharmonia( Workspace[DSTAG.Data()], cutVector.at(i), parIniVector.at(i), outputDir,
                               // Select the type of datasets to fit
                               DSTAG.Data(),
                               false,           // In this case we are fitting PP
                               // Select the type of object to fit
                               incJpsi,         // Includes Jpsi model
                               incPsi2S,        // Includes Psi(2S) model
                               incBkg,          // Includes Background model
                               // Select the fitting options
                               cutCtau,         // Apply prompt ctau cuts
                               false,           // Do simultaneous fit
                               false,           // Flag to indicate if we want to fit pure signal MC
                               numCores,        // Number of cores used for fitting
                               // Select the drawing options
                               setLogScale,     // Draw plot with log scale
                               incSS,           // Include Same Sign data
                               zoomPsi,         // Zoom Psi(2S) peak on extra pad
                               nBins,           // Number of bins used for plotting
                               false            // Compute the mean PT (NEED TO FIX)
                               )
                ) { return; }
            if (DSTAG.Contains("MC") && wantPureSMC)
            {
              if (!fitCharmonia( Workspace[Form("%s_PureS",DSTAG.Data())], cutVector.at(i), parIniVector.at(i), outputDir,
                                // Select the type of datasets to fit
                                DSTAG.Data(),
                                false,           // In this case we are fitting PP
                                // Select the type of object to fit
                                incJpsi,         // Includes Jpsi model
                                incPsi2S,        // Includes Psi(2S) model
                                incBkg,          // Includes Background model
                                // Select the fitting options
                                cutCtau,         // Apply prompt ctau cuts
                                false,           // Do simultaneous fit
                                true,            // Flag to indicate if we want to fit pure signal MC
                                numCores,        // Number of cores used for fitting
                                // Select the drawing options
                                setLogScale,     // Draw plot with log scale
                                incSS,           // Include Same Sign data
                                zoomPsi,         // Zoom Psi(2S) peak on extra pad
                                nBins,           // Number of bins used for plotting
                                false            // Compute the mean PT (NEED TO FIX)
                                )
                  ) { return; }
            }
          }
        }
      } else {
        cout << "[ERROR] The workspace for " << DSTAG.Data() << " was not found!" << endl; return;
      }  
    }
  }
  
  delete aDSTAG;
};
void TriggerInputsForMuonEventCuts ( TString runListFilename, TString selectedInputs="", TString defaultStorage = "raw://" )
{
  AliCDBManager::Instance()->SetDefaultStorage(defaultStorage.Data());
  TObjArray inputsList;
  inputsList.SetOwner();
  
  TObjArray* selectedInputsList = selectedInputs.Tokenize(",");

  // Read input run list
  ifstream inFile(runListFilename.Data());
  TString srun = "";
  if ( inFile.is_open() ) {
    while ( ! inFile.eof() ) {
      srun.ReadLine(inFile,kFALSE);
      if ( ! srun.IsDigit() ) continue;
      
      // For each run, read trigger inputs from OCDB
      Int_t runNumber = srun.Atoi();
      AliCDBManager::Instance()->SetRun(runNumber);
      
      // Get trigger class configuration
      AliCDBEntry* entry = AliCDBManager::Instance()->Get("GRP/CTP/Config");
      if ( ! entry ) continue;
      
      THashList* runInputs = new THashList();
      runInputs->SetOwner();
      runInputs->SetUniqueID((UInt_t)runNumber);
      AliTriggerConfiguration* trigConf = (AliTriggerConfiguration*)entry->GetObject();
      const TObjArray& trigInputsArray = trigConf->GetInputs();
      AliTriggerInput* trigInput = 0x0;
      TIter next(&trigInputsArray);
      while ( ( trigInput = static_cast<AliTriggerInput*>(next()) ) ) {
        if ( selectedInputsList->GetEntriesFast() > 0 && ! selectedInputsList->FindObject(trigInput->GetName()) ) continue;
        Int_t inputId = (Int_t)TMath::Log2(trigInput->GetMask());
        TObjString* currInput = new TObjString(trigInput->GetName());
        currInput->SetUniqueID(inputId);
        runInputs->Add(currInput);
      }
      inputsList.Add(runInputs);
    }
    inFile.close();
  }
  delete selectedInputsList;
  
  // Loop on the trigger inputs
  // and group runs with an equal list of inputs
  Int_t nentries = inputsList.GetEntries();
  TArrayI checkMask(nentries);
  checkMask.Reset(1);
  for ( Int_t irun=0; irun<nentries; irun++ ) {
    if ( checkMask[irun] == 0 ) continue;
    THashList* currList = static_cast<THashList*>(inputsList.At(irun));
    TString runRange = Form("Run range: %u", currList->GetUniqueID());
    for ( Int_t jrun=irun+1; jrun<nentries; jrun++ ) {
      if ( checkMask[jrun] == 0 ) continue;
      THashList* checkList = static_cast<THashList*>(inputsList.At(jrun));
      Bool_t isDifferent = kFALSE;
      for ( Int_t itrig=0; itrig<currList->GetEntries(); itrig++ ) {
        TObjString* currInput = static_cast<TObjString*>(currList->At(itrig));
        TObject* checkInput = checkList->FindObject(currInput->GetName());
        if ( ! checkInput || checkInput->GetUniqueID() != currInput->GetUniqueID() ) {
          isDifferent = kTRUE;
          break;
        }
      } // loop on trigger inputs
      if ( isDifferent ) continue;
      checkMask[jrun] = 0;
      runRange += Form(",%u", checkList->GetUniqueID());
    } // loop on runs
    
    TString outString = "\nSetTrigInputsMap(\"";
    for ( Int_t itrig=0; itrig<currList->GetEntries(); itrig++ ) {
      TObjString* currInput = static_cast<TObjString*>(currList->At(itrig));
      outString += Form("%s:%u,",currInput->GetString().Data(), currInput->GetUniqueID());
    }
    outString.Append("\");\n");
    outString.ReplaceAll(",\"","\"");
    outString += runRange;
    printf("%s\n", outString.Data());
  } // loop on runs
}