ROOT logo
/** 
 * Get a collection from a file directory
 * 
 * @param dir   Parent directory 
 * @param name  Name of collection
 * 
 * @return collection or null
 */
TCollection* GetCollection(TDirectory* dir, const TString& name)
{
  if (!dir) { 
    Error("GetCollection", "No parent directory for %s", name.Data());
    return 0;
  }
  TCollection* ret = 0;
  dir->GetObject(name, ret);
  if (!ret) { 
    Error("GetCollection", "Couldn't find %s in %s", 
	  name.Data(), dir->GetName());
    return 0;
  }
  return ret;
}
/** 
 * Get an object from a collection.  Optionally, we check that the
 * type of the possibly found object matches the request.
 * 
 * @param parent Parent collection
 * @param name   Name of object 
 * @param cls If specified, check that the found object (if any) is of
 * this class.
 * 
 * @return Found object (possibly type-checked) or null
 */
TObject* GetObject(const TCollection* parent, const TString& name, 
		   const TClass* cls=0)
{
  if (!parent) { 
    Error("GetObject", "No parent collection for %s", name.Data());
    return 0;
  }
  TObject* ret = parent->FindObject(name);
  if (!ret) {
    Error("GetObject", "Couldn't find %s in %s", 
	  name.Data(), parent->GetName());
    return 0;
  }
  if (cls && !ret->IsA()->InheritsFrom(cls)) { 
    Error("GetObject", "%s in %s is a %s, not a %s", name.Data(),
	  parent->GetName(), ret->ClassName(), cls->GetName());
    return 0;
  }
  return ret;
}
/** 
 * Get a collection contained in another collection
 * 
 * @param parent Parent collection
 * @param name   Name of collection to find 
 * 
 * @return Found collection or null
 */
TCollection* GetCollection(const TCollection* parent, const TString& name)
{
  TObject* o = GetObject(parent, name, TCollection::Class());
  if (!o) return 0;
  return static_cast<TCollection*>(o);
}
/** 
 * Re-run the energy loss fitter on a merged output file 
 * 
 * @param input  File name of merged output file
 * @param output If specified, the file the new results are written
 * to.  If this is not specified, it defaults to the name of the input
 * file with "_rerun" attached to the base name
 *
 * @param forceSet  Forcibly set things 
 * @param input     Input file 
 * @param output    Output file 
 */
void RerunELossFits(Bool_t forceSet=false, 
		    const TString& input="forward_eloss.root", 
		    Bool_t shift=true,
		    const TString& output="")
{
  const char* fwd = "$ALICE_ROOT/PWGLF/FORWARD/analysis2";
  gROOT->Macro(Form("%s/scripts/LoadLibs.C", fwd));

  TFile*  inFile  = 0;
  TFile*  outFile = 0;
  TString outName(output);
  if (outName.IsNull()) {
    outName = input;
    outName.ReplaceAll(".root", "_rerun.root");
  }
  Bool_t  allOk = false;
  try {
    // --- Open input file ---------------------------------------------
    inFile = TFile::Open(input, "READ");
    if (!inFile)
      throw TString::Format("Failed to open %s", input.Data());

    // --- InFiled input collections --------------------------------------
    TCollection* inFwdSum = GetCollection(inFile, "ForwardELossSums");
    if (!inFwdSum) throw new TString("Cannot proceed without sums");

    TCollection* inFwdRes = GetCollection(inFile, "ForwardELossResults");
    if (!inFwdRes) {
      inFwdRes = 
	static_cast<TCollection*>(inFwdSum->Clone("ForwardELossResults"));
      // throw new TString("Cannot proceed with merged list");
    }

    TCollection* inEFSum = GetCollection(inFwdRes, "fmdEnergyFitter");
    if (!inEFSum) throw new TString("Cannot proceed without accumulated data");
    
    TCollection* inEFRes = GetCollection(inFwdRes, "fmdEnergyFitter");
    if (!inEFRes) throw new TString("Cannot proceed without previous results");

    // --- Open output file --------------------------------------------
    outFile = TFile::Open(outName, "RECREATE");
    if (!outFile)
      throw TString::Format("Failed to open %s", outName.Data());

    // --- Write copy of sum collection to output --------------------
    TCollection* outFwdSum = static_cast<TCollection*>(inFwdSum->Clone());
    outFile->cd();
    outFwdSum->Write(inFwdSum->GetName(), TObject::kSingleKey);
    
    // --- Make our fitter object ------------------------------------
    AliFMDEnergyFitter* fitter = new AliFMDEnergyFitter("energy");
    fitter->SetDoFits(true);
    fitter->SetEnableDeltaShift(shift);
    fitter->Init();
    if (forceSet || !fitter->ReadParameters(inEFSum)) {
      Printf("Forced settings");

      const TAxis* etaAxis = static_cast<TAxis*>(GetObject(inEFSum,"etaAxis"));
      if (!etaAxis) throw new TString("Cannot proceed without eta axis");
      fitter->SetEtaAxis(*etaAxis);
      
      // Set maximum energy loss to consider 
      fitter->SetMaxE(15); 
      // Set number of energy loss bins 
      fitter->SetNEbins(500);
      // Set whether to use increasing bin sizes 
      // fitter->SetUseIncreasingBins(true);
      // Set whether to do fit the energy distributions 
      fitter->SetDoFits(kTRUE);
      // Set whether to make the correction object 
      fitter->SetDoMakeObject(kTRUE);
      // Set the low cut used for energy
      fitter->SetLowCut(0.4);
      // Set the number of bins to subtract from maximum of distributions
      // to get the lower bound of the fit range
      fitter->SetFitRangeBinWidth(4);
      // Set the maximum number of landaus to try to fit (max 5)
      fitter->SetNParticles(5);
      // Set the minimum number of entries in the distribution before
      // trying to fit to the data - 10k seems the least we can do
      fitter->SetMinEntries(10000);
      // fitter->SetMaxChi2PerNDF(10);
      // Enable debug 
    }
    fitter->SetDebug(3);
    fitter->SetStoreResiduals(AliFMDEnergyFitter::kResidualSquareDifference);
    fitter->SetRegularizationCut(1e8); // Lower by factor 3
    // Set the number of bins to subtract from maximum of distributions
    // to get the lower bound of the fit range
    // fitter->SetFitRangeBinWidth(2);
    // Skip all of FMD2 and 3 
    // fitter->SetSkips(AliFMDEnergyFitter::kFMD2|AliFMDEnergyFitter::kFMD3);

    // --- Now do the fits -------------------------------------------
    fitter->Print();
    outFwdSum->ls("R");
    fitter->Fit(static_cast<TList*>(outFwdSum));
    
    // --- Copy full result folder -----------------------------------
    TCollection* outFwdRes = static_cast<TCollection*>(inFwdRes->Clone());
    // Remove old fits 
    TCollection* outEFRes = GetCollection(outFwdRes, "fmdEnergyFitter");
    outFwdRes->Remove(outEFRes);
    // Make our new fit results folder, and add it to results folder
    TCollection* tmp = GetCollection(outFwdSum, "fmdEnergyFitter");
    outEFRes = static_cast<TCollection*>(tmp->Clone());
    outEFRes->Add(new TNamed("refitted", "Refit of the data"));
    outFwdRes->Add(outEFRes);

    // --- Write out new results folder ------------------------------
    outFile->cd();
    outFwdRes->Write(inFwdRes->GetName(), TObject::kSingleKey);
    Printf("Wrote results to \"%s\" (%s)", outName.Data(), outFile->GetName());
    allOk = true;
  }
  catch (const TString* e) {
    Error("RerunELossFits", e->Data());
  }
  catch (const TString& e) {
    Error("RerunELossFits", e.Data());
  }
  if (inFile)  inFile->Close();
  if (outFile) {
    Printf("Wrote new output to \"%s\"", outName.Data());
    outFile->Close();
  }
    
  if (allOk)
    gROOT->Macro(Form("%s/corrs/DrawCorrELoss.C(false,false,\"%s\")", 
		      fwd, outName.Data()));
}


 RerunELossFits.C:1
 RerunELossFits.C:2
 RerunELossFits.C:3
 RerunELossFits.C:4
 RerunELossFits.C:5
 RerunELossFits.C:6
 RerunELossFits.C:7
 RerunELossFits.C:8
 RerunELossFits.C:9
 RerunELossFits.C:10
 RerunELossFits.C:11
 RerunELossFits.C:12
 RerunELossFits.C:13
 RerunELossFits.C:14
 RerunELossFits.C:15
 RerunELossFits.C:16
 RerunELossFits.C:17
 RerunELossFits.C:18
 RerunELossFits.C:19
 RerunELossFits.C:20
 RerunELossFits.C:21
 RerunELossFits.C:22
 RerunELossFits.C:23
 RerunELossFits.C:24
 RerunELossFits.C:25
 RerunELossFits.C:26
 RerunELossFits.C:27
 RerunELossFits.C:28
 RerunELossFits.C:29
 RerunELossFits.C:30
 RerunELossFits.C:31
 RerunELossFits.C:32
 RerunELossFits.C:33
 RerunELossFits.C:34
 RerunELossFits.C:35
 RerunELossFits.C:36
 RerunELossFits.C:37
 RerunELossFits.C:38
 RerunELossFits.C:39
 RerunELossFits.C:40
 RerunELossFits.C:41
 RerunELossFits.C:42
 RerunELossFits.C:43
 RerunELossFits.C:44
 RerunELossFits.C:45
 RerunELossFits.C:46
 RerunELossFits.C:47
 RerunELossFits.C:48
 RerunELossFits.C:49
 RerunELossFits.C:50
 RerunELossFits.C:51
 RerunELossFits.C:52
 RerunELossFits.C:53
 RerunELossFits.C:54
 RerunELossFits.C:55
 RerunELossFits.C:56
 RerunELossFits.C:57
 RerunELossFits.C:58
 RerunELossFits.C:59
 RerunELossFits.C:60
 RerunELossFits.C:61
 RerunELossFits.C:62
 RerunELossFits.C:63
 RerunELossFits.C:64
 RerunELossFits.C:65
 RerunELossFits.C:66
 RerunELossFits.C:67
 RerunELossFits.C:68
 RerunELossFits.C:69
 RerunELossFits.C:70
 RerunELossFits.C:71
 RerunELossFits.C:72
 RerunELossFits.C:73
 RerunELossFits.C:74
 RerunELossFits.C:75
 RerunELossFits.C:76
 RerunELossFits.C:77
 RerunELossFits.C:78
 RerunELossFits.C:79
 RerunELossFits.C:80
 RerunELossFits.C:81
 RerunELossFits.C:82
 RerunELossFits.C:83
 RerunELossFits.C:84
 RerunELossFits.C:85
 RerunELossFits.C:86
 RerunELossFits.C:87
 RerunELossFits.C:88
 RerunELossFits.C:89
 RerunELossFits.C:90
 RerunELossFits.C:91
 RerunELossFits.C:92
 RerunELossFits.C:93
 RerunELossFits.C:94
 RerunELossFits.C:95
 RerunELossFits.C:96
 RerunELossFits.C:97
 RerunELossFits.C:98
 RerunELossFits.C:99
 RerunELossFits.C:100
 RerunELossFits.C:101
 RerunELossFits.C:102
 RerunELossFits.C:103
 RerunELossFits.C:104
 RerunELossFits.C:105
 RerunELossFits.C:106
 RerunELossFits.C:107
 RerunELossFits.C:108
 RerunELossFits.C:109
 RerunELossFits.C:110
 RerunELossFits.C:111
 RerunELossFits.C:112
 RerunELossFits.C:113
 RerunELossFits.C:114
 RerunELossFits.C:115
 RerunELossFits.C:116
 RerunELossFits.C:117
 RerunELossFits.C:118
 RerunELossFits.C:119
 RerunELossFits.C:120
 RerunELossFits.C:121
 RerunELossFits.C:122
 RerunELossFits.C:123
 RerunELossFits.C:124
 RerunELossFits.C:125
 RerunELossFits.C:126
 RerunELossFits.C:127
 RerunELossFits.C:128
 RerunELossFits.C:129
 RerunELossFits.C:130
 RerunELossFits.C:131
 RerunELossFits.C:132
 RerunELossFits.C:133
 RerunELossFits.C:134
 RerunELossFits.C:135
 RerunELossFits.C:136
 RerunELossFits.C:137
 RerunELossFits.C:138
 RerunELossFits.C:139
 RerunELossFits.C:140
 RerunELossFits.C:141
 RerunELossFits.C:142
 RerunELossFits.C:143
 RerunELossFits.C:144
 RerunELossFits.C:145
 RerunELossFits.C:146
 RerunELossFits.C:147
 RerunELossFits.C:148
 RerunELossFits.C:149
 RerunELossFits.C:150
 RerunELossFits.C:151
 RerunELossFits.C:152
 RerunELossFits.C:153
 RerunELossFits.C:154
 RerunELossFits.C:155
 RerunELossFits.C:156
 RerunELossFits.C:157
 RerunELossFits.C:158
 RerunELossFits.C:159
 RerunELossFits.C:160
 RerunELossFits.C:161
 RerunELossFits.C:162
 RerunELossFits.C:163
 RerunELossFits.C:164
 RerunELossFits.C:165
 RerunELossFits.C:166
 RerunELossFits.C:167
 RerunELossFits.C:168
 RerunELossFits.C:169
 RerunELossFits.C:170
 RerunELossFits.C:171
 RerunELossFits.C:172
 RerunELossFits.C:173
 RerunELossFits.C:174
 RerunELossFits.C:175
 RerunELossFits.C:176
 RerunELossFits.C:177
 RerunELossFits.C:178
 RerunELossFits.C:179
 RerunELossFits.C:180
 RerunELossFits.C:181
 RerunELossFits.C:182
 RerunELossFits.C:183
 RerunELossFits.C:184
 RerunELossFits.C:185
 RerunELossFits.C:186
 RerunELossFits.C:187
 RerunELossFits.C:188
 RerunELossFits.C:189
 RerunELossFits.C:190
 RerunELossFits.C:191
 RerunELossFits.C:192
 RerunELossFits.C:193
 RerunELossFits.C:194
 RerunELossFits.C:195
 RerunELossFits.C:196
 RerunELossFits.C:197
 RerunELossFits.C:198
 RerunELossFits.C:199
 RerunELossFits.C:200
 RerunELossFits.C:201
 RerunELossFits.C:202
 RerunELossFits.C:203
 RerunELossFits.C:204
 RerunELossFits.C:205
 RerunELossFits.C:206
 RerunELossFits.C:207
 RerunELossFits.C:208
 RerunELossFits.C:209
 RerunELossFits.C:210
 RerunELossFits.C:211
 RerunELossFits.C:212
 RerunELossFits.C:213
 RerunELossFits.C:214