Re: [ROOT] TObjectSet/TDataSet vs. TFolder (Was: TFolder: examples? and a bug.)

From: Valeri Fine (fine@bnl.gov)
Date: Tue Jun 26 2001 - 19:03:42 MEST


> I don't find this test. Valeri, can you point it out? 

   There was the attachment (I have attached it again and appended the  
   source directly).
 
> In the mean time, I have looked over the TObjectSet/TDataSet classes
> and the document you gave and also the TFolder class and Rene's
> example (thanks!).  These two indeed seem to do much of the same
> things.  

  They are slightly different.     
 
> Can someone give a comparison between the two from an end-user
> (programmer) point of view.

 Some  major points are:

-------------
  1. TDataSet is a named collection of TDataSet's
      This is its FULL definition. 
     The member of TDataSet is TDataSet always.

  2. TFolder is a collection of TObject's
       The "regular" TObject can be a member of TFolder.

   This  means the behavior of TDataSet "collection" is defined by TDataSet implementation
   The behavior of TFolder relies on the behavior of the end-user-class  TObject::FindObject method
    implementations as well.
-------------

  1. TDataSet itself doesn't define the way to iterate/navigate it. It is defined by TDataSetIter class.
      This class  is good to iterate / navigate any TDataSet structure with the object of the classes derived
       from TDataSet. On another hand the user can provide its own iterator and the way to navigate the structure.
       I'd like to highlight the current TDataSetIter class provide all 3 major ways to iterate such kind of collections
       (See for exampleTVolumeViewIter. This is a special iterator over GEANT-like geometry structure)

 2. The navigation of TFolder structure is defined by TFolder methods and methods of all classes involved.
     This is to say nobody knows its exact behavior in case it is used widely by word-wide collaboration.

-------------

   1. TDataSet "browser" view is defined by TDataSet::Browse method
       In the case of TObjectSet the user has a choice  between TObjectSet::Browse()  and TObject::Browse()

   2. TFolder view is defined by TObject::Browse method (when non-TFolder TObject is a memeber of TFolder)

-------------

      TFolder class can be done by deriving it from TDataSet. TDataSet can not be done  this way.
      This is to prove TFolder does provide some extra functionality.

      (2.5 years ago I did send to ROOT team the working version of ROOT with TDirectoiry class
      derived from TDataSet.)
-------------

  1. TDatSet - one add TDataSet only in. There is no way to add something else. To add any extra thing
       into TDataSet one has to pack it into an envelope (like TObjectSet)

  2. TFolder - Any TObject can be added with no extra effort. To facilitate this the interface of TObject was changed recently
      and new "abstract" /"default" methods were introduced.  TDataSet was designed 4 years ago ax the Custom class. 
      We could TObject interface available that time .

> The particular context in which I am interested is a system where
> various reconstruction modules and chains of modules can register
> themselves, their various entry points, and their configuration
> parameters in such a way that they can be accessed from a GUI
> (menus/browser) or at the prompt.

  This is the way the STAR offline reconstruction chain  has been working succefully for three years.
  (see our Chep1999 / Chep2000 talks )
  As I have pointed above no bug in the end-user-class TObject implementation may damage 
  the property of the collection built with TDataSet's. 

Since all our STAR "Module" classes as well as STAR "Data" classes both are derived form TDataSet 
and both does belong the single "BigFullChain" class (the last one is  the top TDataSet), our user can 
use one and the same methods to navigate the algorithms structure and data structures.
(Again see our publications)

 I can not say in advance which class does fit your needs. I am willing provide any working example and further 
 explanation regarding TDataSet family the future development plans as well.

    With my best regards,
                                                    Valeri


> 
> Thanks,
> -Brett.
> 

file://*CMZ :          12/07/98  18.27.27  by  Valery Fine(fine@bnl.gov)
file://*-- Author :    Valery Fine(fine@bnl.gov)   07/04/99
// $Id: testdataset.c,v 1.14 2001/02/05 19:08:44 fine Exp $
// $Log: testdataset.c,v $
// Revision 1.14  2001/02/05 19:08:44  fine
// An extra check to test TDataSetIter::FindObject method
//
// Revision 1.13  2000/09/30 17:51:54  perev
// Evolution On/Off SetEvol.C added
//
// Revision 1.11  1999/12/28 23:32:02  fine
// TDataSetIter  operator++ removed to avoid a future problem
//
// Revision 1.10  1999/12/28 22:25:03  fine
// new test for operators ++ and * implemented
//
// Revision 1.9  1999/04/15 19:45:26  fine
// testdataset.c has been improved
//
// Revision 1.8  1999/04/07 15:41:22  fine
// Extra test for TDataSetIter::Du() was introduced
//
{
  gROOT->Reset();
  // Determinate the brand of the OS
  gSystem.Load("libStar");

  TDataSetIter d;
  d.Mkdir("v1/v1_1/v1_1_1");
  cout << "Short list:" << endl;
  d.Pwd();  
  cout << "Wide list:" << endl;
  d.Pwd("*");
                                  cout << endl;
  d.Mkdir("/v1/v1_2/v1_2_1");
  d.Pwd("*");
                                  cout << endl;
  d.Mkdir("v1/v1_3/v1_2_2");

  TDataSet *last = d.Mkdir("v1/v1/v1_v1_2_2");
  TDataSet *just = d("v1/v1/v1_v1_2_2");

  if (last != just) 
        cout << "Error: Mkdir return a wrong addrees";
   else    
        cout << "Ok! return value of TDataSetIter::Mkdir method has been tested";
        
   cout << endl << endl;     

  d.Pwd("*");
                                  cout << endl;
  d.Mkdir("v1/v21/v3211");
  d.Pwd("*");
  cout  << endl << "------------ 1 ------------ " << endl;
                                  cout << endl;
  d.Mkdir("v1/v21/v3212/v4");
  cout << "the current path: " << d("v1/v21/v3212/v4")->Path() << endl;
  d.Pwd("/");
  d("/")->ls();
  d.ls("/");
  cout << "list \"v3212\" the relative path " << endl;
  d.Pwd("v1/v21/v3212");
  d("v1/v21/v3212")->ls();
  d.ls("v1/v21/v3212");
   
                                 cout << endl;
  cout << "--------------------" << " Testing TDataSetIter::Du() method: " <<
          "--------------------" << endl;  
  Int_t total = d.Du();                               
  cout << "---------------------" << endl;  
  cout << "Total: " << total << " datasets were listed" << endl;
  cout << "-----------------" << " End of Testing TDataSetIter::Du() method: " <<
          "----------------" << endl;  
                                  cout << endl;
  cout << "We'll try some \"wrong\" path now" << endl;
  d.Ls("unknown");
//  d.Pwd()->ls("unknown");
//  cout  << endl << "------------ 2 ------------ " << endl;
  cout  << endl << "-------- 2 test \"FindObject\" ------------ " << endl;

  const Char_t *v3212 = "v3212";
  TDataSet *found = d.FindObject(v3212);
  if (found) {
      const Char_t *t = found->Path();
      cout << "Object: " << v3212 << " found. It\'s path is " << t << endl;
  }
  else {
      cout <<  "Object: " << v3212 << " has not been found." << endl;
      cout << "Try FindByName" << endl;
      TDataSet *lost = d.FindByName(v3212);
      if (lost) {
 cout << "The wrong implementation of TDataSetIter::FindObject method has been discovered" << endl;
            lost->ls();
      }
      return;
  }

  cout  << endl << "-------- 2.2 test \"FindByName\" ------------ " << endl;
  cout  << endl << "-------- 2.2 test \"FindByName\" ------------ " << endl;
 
  const Char_t *vS3213 = "/v32/13";
  cout << " ===   Error message expected " << endl;
  found = d.FindByName(vS3213);
  if (found) return;

  cout  << endl << "-------- 2.3 test \"FindByName\" ------------ " << endl;
  cout  << endl << "-------- 2.3 test \"FindByName\" ------------ " << endl;

  const Char_t *V3212 = "V3212";
  found = d.FindByName(V3212,0,"-I");
  if (found) {
       const Char_t *t2 = found->Path();
       cout << "Object: " << V3212 << " found. It\'s path is " << t2 << endl;
  }
  else {
       cout <<  "Object: " << V3212 << " has not been found." << endl;
       return;
  }

  cout  << endl << "-------- 2.4 test \"FindByName\" ------------ " << endl;
  cout  << endl << "-------- 2.4 test \"FindByName\" ------------ " << endl;

  cout << " ===   Error message expected " << endl;
  found = d.FindByName(V3212,"v1/v21/v3212/v4","-I");
  if (found) return;
  cout << " Object not found" << endl;

  cout << "recreating directories" << endl;

  d.Rmdir("v1/v1_1/v1_1_1");
  d.Pwd()->ls("*");
  cout  << endl << "------------ 3 ------------ " << endl;
  d.Mkdir("v1/v1_1/v1_1_1");
  d.Pwd()->ls("*");
  cout  << endl << "------------ 4 ------------ " << endl;
  d.Rmdir("v1/v1_1/v1_1_1");
  d.Pwd()->ls("*");
  cout  << endl << "------------ 5 ------------ " << endl;
  d.Mkdir("v1/v1_1/v1_1_1");
  d.ls("/v1",3);
  cout  << endl << "------------ 6 ------------ " << endl;
  cout << "Let's check the operator []" << endl;
  if  (d["v1/v1_1/v1_1_1"])
     cout << " ** Error **: the path to d[\"" << d("v1/v1_1/v1_1_1")->Path() << "\"]=" << d["v1/v1_1/v1_1_1"] << endl; 
   else
     cout << " Ok! the path to d[\"" <<  d("v1/v1_1/v1_1_1")->Path() << "\"]=" << d["v1/v1_1/v1_1_1"] << ";" << endl; 
  cout  << endl << "------------ 7 ------------ " << endl;
  cout  << "  Check loop with \"TDataSet *operator *() const\"" << endl;
  TDataSet *ds = 0;
  do { 
    ds = *d; 
    if (ds) {
        cout << "\tCurrent ds <" << ds->GetName() << ">;";
        if (d()) { 
          cout << "\tnext ds will be <" << (*d)->GetName();
          cout << ">" << endl; 
        } else 
          cout << "\tthere will be no new ds" << endl; 

    }
  } while (ds);
  cout << "   end of loop " << endl << endl ;

  cout  << endl << "------------ 8 ------------ " << endl;
  d.Pwd();
  d.Rmdir("v1/v21");
  cout  << endl << "------------ 9 ------------ " << endl;
  d.ls("","*");
  d.Rmdir("v1");
  d.Rmdir("v1");
  if (d.Cwd()) { 
     d.ls("","*");
     cout << "Error the directory should be undefined nowadays " << endl;
  }
  else cout << "Ok! The last dataset has NO active directory anymore" << endl;
  d.Pwd();

  cout  << endl << "------------ 9 ------------ " << endl;
  
}





This archive was generated by hypermail 2b29 : Tue Jan 01 2002 - 17:50:50 MET