ROOT logo
/*
  //
  // Function to dump recursivally in human readable format, content of the objects + example use case
  // 
  //
  .L  $mcProd/dumpObject.C+
  ExampleUse(); > AliTPCClusterParam.dump
  AliTPCRecoParam param; 
  DumpObjectRecursive(&param); >> AliTPCRecoParam.dump

  Use case examples 
  1.) compare oontent of alignent OCDB files for differnt yers
  2.) compare ClusterParam for different periods
   
=================================================================================================================
  // 1.)
  // Compare alignment example:
  // Compare TPC alignemnt 2013 and 2010
  //
  DumpOCDBFile("/cvmfs/alice.gsi.de/alice/data/2013/OCDB/TPC/Align/Data/Run0_999999999_v1_s0.root","TPCalign2013.dump",1);
  DumpOCDBFile("/cvmfs/alice.gsi.de/alice/data/2010/OCDB/TPC/Align/Data/Run0_999999999_v1_s0.root","TPCalign2010.dump",1);
  diff  TPCalign2013.dump TPCalign2010.dump > TPCalign2013_TPCalign2010.diff
  //
  //    
=================================================================================================================
//  2.) 
  // Compare CluterParam OCDB etry
  //
  DumpOCDBFile("/cvmfs/alice.gsi.de/alice/data/2010/OCDB/TPC/Calib/ClusterParam/Run131541_999999999_v2_s0.root","2010_TPC_Calib_ClusterParam_Run131541_999999999_v2_s0.dump",1);
  DumpOCDBFile("/cvmfs/alice.gsi.de/alice/data/2010/OCDB/TPC/Calib/ClusterParam/Run0_999999999_v1_s0.root","2010_TPC_Calib_ClusterParam_Run0_999999999_v1_s0.dump",1);
  DumpOCDBFile("/cvmfs/alice.gsi.de/alice/data/2013/OCDB/TPC/Calib/ClusterParam/Run0_999999999_v1_s0.root","2013_TPC_Calib_ClusterParam_Run0_999999999_v1_s0.dump",1);
  
  diff 2010_TPC_Calib_ClusterParam_Run131541_999999999_v2_s0.dump 2010_TPC_Calib_ClusterParam_Run0_999999999_v1_s0.dump


*/
#if !defined(__CINT__) || defined(__MAKECINT__)
#include "TMath.h"
#include "TFile.h"
#include "TTree.h"
#include <TVectorF.h>
#include <TLinearFitter.h>
#include <TH1F.h>
#include <TH3F.h>
#include <TProfile2D.h>
#include <TVectorD.h>
#include <TObjArray.h>
#include "THnBase.h"
#include "TRealData.h"
#include "TDataMember.h"
#include "TClass.h"
#include "AliCDBEntry.h"
#include "TObjArray.h"
#include "TNamed.h"
#include "TROOT.h"
#endif

void DumpObjectRecursive(TObject *obj);
void DumpObjectRecursive(TObject *obj, TString prefix, Int_t &counterRec);

void ExampleUse(){
  //
  //
  //
  TFile *f = TFile::Open("/cvmfs/alice.gsi.de/alice/simulation/2008/v4-15-Release/Residual/TPC/Calib/ClusterParam/Run127712_130850_v3_s0.root");
  //TFile *f = TFile::Open("./OCDB_NoClustersBelowThreshold/TPC/Calib/RecoParam/Run127712_130850_v0_s0.root");
  AliCDBEntry * entry = (AliCDBEntry*)f->Get("AliCDBEntry");
  TObject  *obj = ( TObject*)entry->GetObject();
  DumpObjectRecursive(obj);
  //
  //
}

void DumpOCDBFile(const char *finput , const char *foutput, Bool_t dumpMetaData, Bool_t xml){
  //
  //  
  //  DumpOCDBFile("$ALICE_ROOT/OCDB/ITS/Align/Data/Run0_999999999_v0_s0.root", "ITS_Align_Data_Run0_999999999_v0_s0.dump")
  //
  if (finput==0) return ;
  TFile *falignITS  = TFile::Open(finput);
  AliCDBEntry *entry  = (AliCDBEntry*)falignITS->Get("AliCDBEntry");
  if (!entry) return; 
  TObject *obj = ((AliCDBEntry*)falignITS->Get("AliCDBEntry"))->GetObject();  

  //
  if (!xml){
    if (dumpMetaData) gROOT->ProcessLine(TString::Format("((TObject*)%p)->Dump(); >%s",entry, foutput).Data());
    if (!obj) return;
    gROOT->ProcessLine(TString::Format("DumpObjectRecursive((TObject*)%p); >>%s",obj, foutput).Data());
  }
  if (xml){
    TFile * f = TFile::Open(TString::Format("%s.xml",foutput).Data(),"recreate");
    if (dumpMetaData) entry->Write("AliCDBEntry");
    else obj->Write("AliCDBEntry");
    f->Close();
  }
}



void DumpObjectRecursive(TObject *obj){
  //
  //
  //
  Int_t counterRec=0;
  printf("==> Dumping object at: %p, name=%s, class=%s)\n", obj, obj->GetName(), (obj->IsA()->GetName()));
  DumpObjectRecursive(obj, TString(obj->IsA()->GetName())+".",counterRec);
}
 
//
//
//
void DumpObjectRecursive(TObject *obj, TString prefix, Int_t &counterRec){
  //
  // Recursive dump of the TObject
  // Dump all basic types and follow pointers to the objects
  // current limitation:
  //    a.) clases and structures not derived from TObject not followed (to fix)
  //    b.) dynamic arrays not followed
  //    c.) std maps,array ....  not followed
  //    
  //
  if (!obj) return;
  //
  // Special case of Collection classes
  //
  if (obj->IsA()->InheritsFrom(TCollection::Class())) {
    TIter myiter((TCollection*)obj);
    TObject  *arObject=0;
    Int_t counter=0;
    while ((arObject = (TObject*)myiter.Next())) {
      TString prefixArr = TString::Format("%s[%d]",prefix.Data(),counter);
      DumpObjectRecursive(arObject,prefixArr,counterRec);
      counter++;
    } 
    counterRec++;
    return;
  }

  TClass * cl = obj->IsA();
  if (!(cl->GetListOfRealData())) cl->BuildRealData();
  TRealData* rd = 0;
  TIter next(cl->GetListOfRealData());  
  while ((rd = (TRealData*) next())) {
    counterRec++;
    TDataMember* dm = rd->GetDataMember();
    TDataType* dtype = dm->GetDataType();
    Int_t offset = rd->GetThisOffset();
    char* pointer = ((char*) obj) + offset;
    
    if (dm->IsaPointer()) {
      // We have a pointer to an object or a pointer to an array of basic types.
      TClass* clobj = 0;
      if (!dm->IsBasic()) {
	clobj = TClass::GetClass(dm->GetTypeName());
      }
      if (clobj) {
	// We have a pointer to an object.
	//
	if (!clobj->InheritsFrom(TObject::Class())) {
	  // It must be a TObject object.
	  continue; 
	}
	char** apointer = (char**) pointer;
	TObject* robj = (TObject*) *apointer;
	//	
	if(!robj)
	  printf("M:%s%s\n",prefix.Data(),dm->GetName()); // Missing - 0 pointer
	else{
	  printf("T:%s\t%s%s\n", clobj->GetName(),prefix.Data(), dm->GetName());
	  TString prefixNew=prefix;
	  prefixNew+=dm->GetName();
	  prefixNew+=".";
	  if (robj!=obj) DumpObjectRecursive(robj,prefixNew,counterRec);  // trivial check 
	  if (robj==obj){
	    printf("R:%s\t%s%s\n",clobj->GetName(),prefix.Data(), dm->GetName());
	  }
	}
      }
    } else if (dm->IsBasic()) {
      //
      // Basic data type
      //
      const char* index = dm->GetArrayIndex();
      if (dm->GetArrayDim()==0){
	printf("B:\t%s%s\t%s\n", prefix.Data(),rd->GetName(), dtype->AsString(pointer));
      }
      //
      // Basic array - fixed length
      //
      //      if (dm->GetArrayDim()>0 && strlen(index) != 0){
      if (dm->GetArrayDim()>0 ){
	printf("A:\t%s%s\t",prefix.Data(),rd->GetName());
	Int_t counter=0;
	for  (Int_t idim=0; idim<dm->GetArrayDim(); idim++){
	  //printf("A:%d\t%d\n", dm->GetArrayDim(),dm->GetMaxIndex(idim));
	  for (Int_t j=0; j<dm->GetMaxIndex(idim); j++){
	    printf("%s\t",dtype->AsString(pointer+dm->GetUnitSize()*counter));
	    counter++;
	    if (counter%5==0) printf("\nA:\t%s%s\t",prefix.Data(),rd->GetName());
	  }
	}
	printf("\n");
      }
      //
      // Basic array - dynamic length
      //
      if (dm->GetArrayDim()>0 && strlen(index) != 0){
	//
	// Dump first only for the moment
	//  
	printf("B:\t%s%s\t%s\n",prefix.Data(),rd->GetName(), dtype->AsString(pointer));
      }
    } else {
    }
  }
}  

//
// Small checks to test the TRealData and TDataType
//



void DumpDataSimple(){
  //
  // Dump example for elenatr data types 
  //
  TObject *obj = new TVectorD(20);
  TClass * cl = obj->IsA();
  if (!cl->GetListOfRealData()) cl->BuildRealData();
  //
  TRealData* rd = 0;
  rd = (TRealData*)(cl->GetListOfRealData()->FindObject("fNrows"));
  TDataMember* dm = rd->GetDataMember();
  TDataType* dtype = dm->GetDataType();
  //
  Int_t offset = rd->GetThisOffset();
  char* pointer = ((char*) obj) + offset;
  printf("%s\n",dtype->AsString(pointer));
  
}

void DumpDataArray(){
  //
  // print array example
  // 
  TObject *obj = new TVectorD(20);
  TClass * cl = obj->IsA();
  if (!cl->GetListOfRealData()) cl->BuildRealData();
  TRealData* rd = 0;
  rd = (TRealData*)(cl->GetListOfRealData()->FindObject("*fElements"));
  TDataMember* dm = rd->GetDataMember();
  TDataType* dtype = dm->GetDataType();
  dtype->Print();
  //
  Int_t offset = rd->GetThisOffset();
  char* pointer = ((char*) obj) + offset; 
  printf("%s\n",dtype->AsString(pointer));
}

void DumpTObjectArray(){
  //
  //
  //
  TObjArray *array = new TObjArray(10);
  for (Int_t i=0; i<10; i++) array->AddLast(new TNamed(Form("n%d",i), Form("n%d",i)));  
  DumpObjectRecursive(array);
  //
  //
  TObject *obj = array;
  TClass * cl = obj->IsA();
  if (!cl->GetListOfRealData()) cl->BuildRealData();
  TRealData* rd = 0;
  rd = (TRealData*)(cl->GetListOfRealData()->FindObject("*fCont"));
  TDataMember* dm = rd->GetDataMember();
  TDataType* dtype = dm->GetDataType();
  //
  Int_t offset = rd->GetThisOffset();
  char* pointer = ((char*) obj) + offset;
  char** apointer = (char**) pointer;
  //we have pointer to pointer here
  TObject** ppobj = (TObject**) *apointer;
  (*ppobj)->Print();
  //
  TIter myiter(array);
  TObject  *arObject; 
  dtype->Print();
  while ((arObject = (TObject*)myiter.Next())) {
    DumpObjectRecursive(arObject);
  } 


}
 dumpObject.C:1
 dumpObject.C:2
 dumpObject.C:3
 dumpObject.C:4
 dumpObject.C:5
 dumpObject.C:6
 dumpObject.C:7
 dumpObject.C:8
 dumpObject.C:9
 dumpObject.C:10
 dumpObject.C:11
 dumpObject.C:12
 dumpObject.C:13
 dumpObject.C:14
 dumpObject.C:15
 dumpObject.C:16
 dumpObject.C:17
 dumpObject.C:18
 dumpObject.C:19
 dumpObject.C:20
 dumpObject.C:21
 dumpObject.C:22
 dumpObject.C:23
 dumpObject.C:24
 dumpObject.C:25
 dumpObject.C:26
 dumpObject.C:27
 dumpObject.C:28
 dumpObject.C:29
 dumpObject.C:30
 dumpObject.C:31
 dumpObject.C:32
 dumpObject.C:33
 dumpObject.C:34
 dumpObject.C:35
 dumpObject.C:36
 dumpObject.C:37
 dumpObject.C:38
 dumpObject.C:39
 dumpObject.C:40
 dumpObject.C:41
 dumpObject.C:42
 dumpObject.C:43
 dumpObject.C:44
 dumpObject.C:45
 dumpObject.C:46
 dumpObject.C:47
 dumpObject.C:48
 dumpObject.C:49
 dumpObject.C:50
 dumpObject.C:51
 dumpObject.C:52
 dumpObject.C:53
 dumpObject.C:54
 dumpObject.C:55
 dumpObject.C:56
 dumpObject.C:57
 dumpObject.C:58
 dumpObject.C:59
 dumpObject.C:60
 dumpObject.C:61
 dumpObject.C:62
 dumpObject.C:63
 dumpObject.C:64
 dumpObject.C:65
 dumpObject.C:66
 dumpObject.C:67
 dumpObject.C:68
 dumpObject.C:69
 dumpObject.C:70
 dumpObject.C:71
 dumpObject.C:72
 dumpObject.C:73
 dumpObject.C:74
 dumpObject.C:75
 dumpObject.C:76
 dumpObject.C:77
 dumpObject.C:78
 dumpObject.C:79
 dumpObject.C:80
 dumpObject.C:81
 dumpObject.C:82
 dumpObject.C:83
 dumpObject.C:84
 dumpObject.C:85
 dumpObject.C:86
 dumpObject.C:87
 dumpObject.C:88
 dumpObject.C:89
 dumpObject.C:90
 dumpObject.C:91
 dumpObject.C:92
 dumpObject.C:93
 dumpObject.C:94
 dumpObject.C:95
 dumpObject.C:96
 dumpObject.C:97
 dumpObject.C:98
 dumpObject.C:99
 dumpObject.C:100
 dumpObject.C:101
 dumpObject.C:102
 dumpObject.C:103
 dumpObject.C:104
 dumpObject.C:105
 dumpObject.C:106
 dumpObject.C:107
 dumpObject.C:108
 dumpObject.C:109
 dumpObject.C:110
 dumpObject.C:111
 dumpObject.C:112
 dumpObject.C:113
 dumpObject.C:114
 dumpObject.C:115
 dumpObject.C:116
 dumpObject.C:117
 dumpObject.C:118
 dumpObject.C:119
 dumpObject.C:120
 dumpObject.C:121
 dumpObject.C:122
 dumpObject.C:123
 dumpObject.C:124
 dumpObject.C:125
 dumpObject.C:126
 dumpObject.C:127
 dumpObject.C:128
 dumpObject.C:129
 dumpObject.C:130
 dumpObject.C:131
 dumpObject.C:132
 dumpObject.C:133
 dumpObject.C:134
 dumpObject.C:135
 dumpObject.C:136
 dumpObject.C:137
 dumpObject.C:138
 dumpObject.C:139
 dumpObject.C:140
 dumpObject.C:141
 dumpObject.C:142
 dumpObject.C:143
 dumpObject.C:144
 dumpObject.C:145
 dumpObject.C:146
 dumpObject.C:147
 dumpObject.C:148
 dumpObject.C:149
 dumpObject.C:150
 dumpObject.C:151
 dumpObject.C:152
 dumpObject.C:153
 dumpObject.C:154
 dumpObject.C:155
 dumpObject.C:156
 dumpObject.C:157
 dumpObject.C:158
 dumpObject.C:159
 dumpObject.C:160
 dumpObject.C:161
 dumpObject.C:162
 dumpObject.C:163
 dumpObject.C:164
 dumpObject.C:165
 dumpObject.C:166
 dumpObject.C:167
 dumpObject.C:168
 dumpObject.C:169
 dumpObject.C:170
 dumpObject.C:171
 dumpObject.C:172
 dumpObject.C:173
 dumpObject.C:174
 dumpObject.C:175
 dumpObject.C:176
 dumpObject.C:177
 dumpObject.C:178
 dumpObject.C:179
 dumpObject.C:180
 dumpObject.C:181
 dumpObject.C:182
 dumpObject.C:183
 dumpObject.C:184
 dumpObject.C:185
 dumpObject.C:186
 dumpObject.C:187
 dumpObject.C:188
 dumpObject.C:189
 dumpObject.C:190
 dumpObject.C:191
 dumpObject.C:192
 dumpObject.C:193
 dumpObject.C:194
 dumpObject.C:195
 dumpObject.C:196
 dumpObject.C:197
 dumpObject.C:198
 dumpObject.C:199
 dumpObject.C:200
 dumpObject.C:201
 dumpObject.C:202
 dumpObject.C:203
 dumpObject.C:204
 dumpObject.C:205
 dumpObject.C:206
 dumpObject.C:207
 dumpObject.C:208
 dumpObject.C:209
 dumpObject.C:210
 dumpObject.C:211
 dumpObject.C:212
 dumpObject.C:213
 dumpObject.C:214
 dumpObject.C:215
 dumpObject.C:216
 dumpObject.C:217
 dumpObject.C:218
 dumpObject.C:219
 dumpObject.C:220
 dumpObject.C:221
 dumpObject.C:222
 dumpObject.C:223
 dumpObject.C:224
 dumpObject.C:225
 dumpObject.C:226
 dumpObject.C:227
 dumpObject.C:228
 dumpObject.C:229
 dumpObject.C:230
 dumpObject.C:231
 dumpObject.C:232
 dumpObject.C:233
 dumpObject.C:234
 dumpObject.C:235
 dumpObject.C:236
 dumpObject.C:237
 dumpObject.C:238
 dumpObject.C:239
 dumpObject.C:240
 dumpObject.C:241
 dumpObject.C:242
 dumpObject.C:243
 dumpObject.C:244
 dumpObject.C:245
 dumpObject.C:246
 dumpObject.C:247
 dumpObject.C:248
 dumpObject.C:249
 dumpObject.C:250
 dumpObject.C:251
 dumpObject.C:252
 dumpObject.C:253
 dumpObject.C:254
 dumpObject.C:255
 dumpObject.C:256
 dumpObject.C:257
 dumpObject.C:258
 dumpObject.C:259
 dumpObject.C:260
 dumpObject.C:261
 dumpObject.C:262
 dumpObject.C:263
 dumpObject.C:264
 dumpObject.C:265
 dumpObject.C:266
 dumpObject.C:267
 dumpObject.C:268
 dumpObject.C:269
 dumpObject.C:270
 dumpObject.C:271
 dumpObject.C:272
 dumpObject.C:273
 dumpObject.C:274
 dumpObject.C:275
 dumpObject.C:276
 dumpObject.C:277
 dumpObject.C:278
 dumpObject.C:279
 dumpObject.C:280
 dumpObject.C:281
 dumpObject.C:282
 dumpObject.C:283
 dumpObject.C:284
 dumpObject.C:285
 dumpObject.C:286
 dumpObject.C:287
 dumpObject.C:288
 dumpObject.C:289
 dumpObject.C:290
 dumpObject.C:291
 dumpObject.C:292
 dumpObject.C:293
 dumpObject.C:294
 dumpObject.C:295