TFile::Delete a TObject from a directory

Hi experts,

I can’t delete a specific cycle from a specific directory in a TFile.
Here’s a dummy code (and attached is the running script) with other
issues described below:

 {
        TFile f("test.root", "RECREATE");
        TH1F h("h","",10,0,10);
        h.Fill(3);
        f.mkdir("testDirA");
        f.cd("testDirA");
        h.Write();
        h.Write();
        f.mkdir("testDirB");
        f.cd("testDirB");
        h.Write();
        h.Write();
        f.Close();
}
{
        TFile f("test.root", "UPDATE");
        f.cd("testDirA");
        f.ls();// shows h;1 and h;2 in the testDirA directory
        f.Delete("h;1");
        f.ls();// Q1:  ls() still (?) shows h;1 in the testDirA directory
        f.Close();
        f.Open("test.root", "READ");
        f.ls();// Q2: ls() no directories shown (?)
        f.Close();
}
{
        TFile f("test.root", "READ");
        f.cd("testDirA");
        f.ls();// Q3: shows h;1 and h;2 in the testDirA directory
        f.Close();
}

Questions
Q1. Immediately after deleting an ls() of the file still shows the
histogram supposedly deleted. TFile::Delete is mediated by a buffer?
Q2. After closing and reopening the file the ls() changes and no
directory is shown. This is rather awkward since TBrowsing the file at
this stage (in a separate or the same session) shows that all
directories are still in the file.
Q3. The histogram testDirA/h;1 was actually never deleted from the
file. How can this Histogram be deleted?

Thanks in advance,
Hernan.
testDelete.C (1.24 KB)

[quote]Q2. After closing and reopening the file the ls() changes and no
directory is shown.[/quote] humm … f.Open("test.root", "READ");Does NOT affect the object ‘j’ because TFile::Open is a static function that allocates and return a new object. i.e. TFile *f2 TFile::Open("test.root", "READ"); f2->ls(); f2->Close();will work better.

Cheers,
Philippe.

[quote]Q1. Immediately after deleting an ls() of the file still shows the
histogram supposedly deleted. TFile::Delete is mediated by a buffer?[/quote]This means that the object has not been removed from the file (and hence explain Q3). This is because the TFile is also the top level directory and the call;f.Delete("h;1");request “h1;1” to be removed from the top level directory … which of course can not happen since it is not there. Instead use:gDirectory->Delete("h1;1"); where gDirectory point to the directory reached by f.cd(…);

Cheers,
Philippe.

Thanks for the reply Philippe.

Some things still confuse me.

TFile f("test.root", "UPDATE");
f.cd("testDirA");
f.pwd();

shows the top level, but pwd calls TDirectory::GetPath which should show full path. This (odd?) behavior may be related to the next doubt:

[quote]

request “h1;1” to be removed from the top level directory … which of course can not happen since it is not there.[/quote]

So doing

should remove the desired object, which doesn’t. I tried simple variations like

TFile f("test.root", "UPDATE");
f.Delete("testDirA/h;1");
f.Delete("/testDirA/h;1");

and

TFile f("test.root", "UPDATE");
f.cd("testDirA"); 
f.Delete("testDirA/h;1");
f.Delete("/testDirA/h;1");

Seems like TFile::Delete() applies always on top directory. Shouldn’t it be possible to delete a nested directory by TFile::Delete using the Delete() argument? Mean delete from gDirectory by default or from (the expected behavior of) TFile::pwd()?

Thanks again.

[quote]but pwd calls TDirectory::GetPath which should show full path.[/quote]It is intended to show the full path of the object it is called upon. The ‘only’ trace/marker of the current directory is the value of gDirectory. If you want/need an operation to be done on the current directory call it on gDirectory (gDirectory->pwd(), gDirectory->Delete(…)).

[quote]f.Delete(“testDirA/h;1”);
should remove the desired object[/quote]Humm … no. Which part of the documentation claimed it should?
Delete intentional only look for a cycle name in the object/directory it is called on. So calling it on f (f being a TFile*) can only delete objects in the top level directory.

[quote]Seems like TFile::Delete() applies always on top directory.[/quote]By definition, yes (since a TFile object is always the top level directory).

[quote]Shouldn’t it be possible to delete a nested directory by TFile::Delete using the Delete() argument?
[/quote]It is not supported, you need to first get to the correct subdirectory.

[quote]Mean delete from gDirectory by default instead from (the expected behavior of) TFile::pwd()?[/quote]This is not desirable as it conflicts with the idea/concept of object orientation.

To achieve what you want use either:TFile f("test.root", "UPDATE"); f.cd("testDirA"); gDirectory->Delete("h;1");orTFile f("test.root", "UPDATE"); TDirectory *testDir = f.GetDirectory("testDirA"); testDir->Delete("h;1");

Cheers,
Philippe.

Thanks again Philippe. Your answers cleared me up.

Bests,
Hernan.