forked from root-project/root
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path_tfile.py
More file actions
137 lines (112 loc) · 5 KB
/
_tfile.py
File metadata and controls
137 lines (112 loc) · 5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# Author: Danilo Piparo, Massimiliano Galli CERN 08/2018
# Author: Vincenzo Eduardo Padulano CERN/UPV 03/2022
################################################################################
# Copyright (C) 1995-2022, Rene Brun and Fons Rademakers. #
# All rights reserved. #
# #
# For the licensing terms see $ROOTSYS/LICENSE. #
# For the list of contributors see $ROOTSYS/README/CREDITS. #
################################################################################
r'''
\pythondoc TFile
In the same way as for TDirectory, it is possible to get the content of a
TFile object with the familiar item-getting syntax.
For more information, please refer to the TDirectory documentation.
In addition, TFile instances can be inspected via the `Get` method, a feature
that is inherited from TDirectoryFile (please see the documentation of
TDirectoryFile for examples on how to use it).
In order to write objects into a TFile, the `WriteObject` Python method can
be used (more information in the documentation of TDirectoryFile).
PyROOT modifies the TFile constructor and the TFile::Open method to make them
behave in a more pythonic way. In particular, they both throw an `OSError` if
there was a problem accessing the file (e.g. non-existent or corrupted file).
This class can also be used as a context manager, with the goal of opening a
file and doing some quick manipulations of the objects inside it. The
TFile::Close method will be automatically called at the end of the context. For
example:
\code{.py}
from ROOT import TFile
with TFile("file1.root", "recreate") as outfile:
hout = ROOT.TH1F(...)
outfile.WriteObject(hout, "myhisto")
\endcode
Since the file is closed at the end of the context, all objects created or read
from the file inside the context are not accessible anymore in the application
(but they will be stored in the file if they were written to it). ROOT objects
like histograms can be detached from a file with the SetDirectory method. This
will leave the object untouched so that it can be accessed after the end of the
context:
\code{.py}
import ROOT
from ROOT import TFile
with TFile("file1.root", "read") as infile:
hin = infile.Get("myhisto")
hin.SetDirectory(ROOT.nullptr)
# Use the histogram afterwards
print(hin.GetName())
\endcode
\note The TFile::Close method automatically sets the current directory in
the program to the gROOT object. If you want to restore the status of the
current directory to some other file that was opened prior to the `with`
statement, you can use the context manager functionality offered by TContext.
\endpythondoc
'''
from . import pythonization
def _TFileConstructor(self, *args):
# Redefinition of ROOT.TFile(str, ...):
# check if the instance of TFile has IsZombie() = True
# and raise OSError if so.
# Parameters:
# self: instance of TFile class
# *args: arguments passed to the constructor
self._OriginalConstructor(*args)
if len(args) >= 1:
if self.IsZombie():
raise OSError('Failed to open file {}'.format(args[0]))
def _TFileOpen(klass, *args):
import ROOT
# Redefinition of ROOT.TFile.Open(str, ...):
# check if the instance of TFile is a C++ nullptr and raise a
# OSError if this is the case.
# Parameters:
# klass: TFile class
# *args: arguments passed to the constructor
f = klass._OriginalOpen(*args)
if not f:
# args[0] can be either a string or a TFileOpenHandle
raise OSError('Failed to open file {}'.format(str(args[0])))
return f
def _TFileExit(obj, exc_type, exc_val, exc_tb):
"""
Close the TFile object.
Signature and return value are imposed by Python, see
https://docs.python.org/3/library/stdtypes.html#typecontextmanager.
"""
# A TFile might be storing references to objects retrieved by the user in
# a cache. Make sure the cache is cleaned at exit time rather than having
# to wait for the garbage collector.
try:
delattr(obj, "_cached_items")
except AttributeError:
pass
obj.Close()
return False
@pythonization('TFile')
def pythonize_tfile(klass):
"""
TFile inherits from
- TDirectory the pythonized attr syntax (__getattr__) and WriteObject method.
- TDirectoryFile the pythonized Get method (pythonized only in Python)
and defines the __enter__ and __exit__ methods to work as a context manager.
"""
# Pythonizations for TFile::Open
klass.Open.__creates__ = True
klass._OriginalOpen = klass.Open
klass.Open = classmethod(_TFileOpen)
# Pythonization for TFile constructor
klass._OriginalConstructor = klass.__init__
klass.__init__ = _TFileConstructor
# Pythonization for __enter__ and __exit__ methods
# These make TFile usable in a `with` statement as a context manager
klass.__enter__ = lambda tfile: tfile
klass.__exit__ = _TFileExit