evefile 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- evefile/__init__.py +8 -0
- evefile/__pycache__/__init__.cpython-311.pyc +0 -0
- evefile/boundaries/__init__.py +1 -0
- evefile/boundaries/__pycache__/__init__.cpython-311.pyc +0 -0
- evefile/boundaries/__pycache__/evefile.cpython-311.pyc +0 -0
- evefile/boundaries/__pycache__/eveh5.cpython-311.pyc +0 -0
- evefile/boundaries/evefile.py +721 -0
- evefile/boundaries/eveh5.py +932 -0
- evefile/controllers/__init__.py +4 -0
- evefile/controllers/__pycache__/__init__.cpython-311.pyc +0 -0
- evefile/controllers/__pycache__/joining.cpython-311.pyc +0 -0
- evefile/controllers/__pycache__/timestamp_mapping.cpython-311.pyc +0 -0
- evefile/controllers/__pycache__/version_mapping.cpython-311.pyc +0 -0
- evefile/controllers/joining.py +1091 -0
- evefile/controllers/timestamp_mapping.py +187 -0
- evefile/controllers/version_mapping.py +1152 -0
- evefile/entities/__init__.py +5 -0
- evefile/entities/__pycache__/__init__.cpython-311.pyc +0 -0
- evefile/entities/__pycache__/data.cpython-311.pyc +0 -0
- evefile/entities/__pycache__/file.cpython-311.pyc +0 -0
- evefile/entities/__pycache__/metadata.cpython-311.pyc +0 -0
- evefile/entities/data.py +1961 -0
- evefile/entities/file.py +320 -0
- evefile/entities/metadata.py +592 -0
- evefile-0.1.0.dist-info/METADATA +132 -0
- evefile-0.1.0.dist-info/RECORD +30 -0
- evefile-0.1.0.dist-info/WHEEL +5 -0
- evefile-0.1.0.dist-info/licenses/COPYING +674 -0
- evefile-0.1.0.dist-info/licenses/LICENSE +15 -0
- evefile-0.1.0.dist-info/top_level.txt +1 -0
evefile/entities/file.py
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
"""
|
|
2
|
+
|
|
3
|
+
*Entities representing an eveH5 file on the entire file level.*
|
|
4
|
+
|
|
5
|
+
While the entities in this module represent the contents of an eveH5 file,
|
|
6
|
+
they clearly abstract from the internal structure of these files.
|
|
7
|
+
Furthermore, there are different versions of the underlying schema
|
|
8
|
+
(*i.e.*, organisation) of these files, and the entities abstract away from
|
|
9
|
+
these differences as well. The key concept is to provide users of the
|
|
10
|
+
``evefile`` interface with useful abstractions allowing to conveniently
|
|
11
|
+
access all the data present in an eveH5 file.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
Overview
|
|
15
|
+
========
|
|
16
|
+
|
|
17
|
+
A first overview of the classes implemented in this module and their
|
|
18
|
+
hierarchy is given in the UML diagram below.
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
.. figure:: /uml/evefile.entities.file.*
|
|
22
|
+
:align: center
|
|
23
|
+
|
|
24
|
+
Class hierarchy of the :mod:`evefile.entities.file` module. The
|
|
25
|
+
:class:`File` class is sort of the central interface to the entire
|
|
26
|
+
subpackage, as this class provides a faithful representation of all
|
|
27
|
+
information available from a given eveH5 file. To this end,
|
|
28
|
+
it incorporates instances of classes of the other modules of the
|
|
29
|
+
subpackage. Furthermore, "Scan" inherits from the identically named
|
|
30
|
+
facade of the scan functional layer and contains the full information
|
|
31
|
+
of the SCML file (if the SCML file is present in the eveH5 file).
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
Module documentation
|
|
35
|
+
====================
|
|
36
|
+
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
import datetime
|
|
40
|
+
import logging
|
|
41
|
+
|
|
42
|
+
logger = logging.getLogger(__name__)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class File:
|
|
46
|
+
"""
|
|
47
|
+
Representation of all information available from a given eveH5 file.
|
|
48
|
+
|
|
49
|
+
Individual measurements are saved in HDF5 files using a particular
|
|
50
|
+
schema (eveH5). Besides file-level metadata, there are log messages
|
|
51
|
+
and the actual data.
|
|
52
|
+
|
|
53
|
+
The data are organised in three functionally different sections: data,
|
|
54
|
+
snapshots, and monitors.
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
Attributes
|
|
58
|
+
----------
|
|
59
|
+
metadata : :class:`Metadata`
|
|
60
|
+
File metadata
|
|
61
|
+
|
|
62
|
+
log_messages : :class:`list`
|
|
63
|
+
Log messages from an individual measurement
|
|
64
|
+
|
|
65
|
+
Each item in the list is an instance of :class:`LogMessage`.
|
|
66
|
+
|
|
67
|
+
data : :class:`dict`
|
|
68
|
+
Data recorded from the devices involved in the scan.
|
|
69
|
+
|
|
70
|
+
Each item is an instance of
|
|
71
|
+
:class:`evefile.entities.data.Data`.
|
|
72
|
+
|
|
73
|
+
snapshots : :class:`dict`
|
|
74
|
+
Device data recorded as snapshot during a measurement.
|
|
75
|
+
|
|
76
|
+
Each item is an instance of
|
|
77
|
+
:class:`evefile.entities.data.Data`.
|
|
78
|
+
|
|
79
|
+
monitors : :class:`dict`
|
|
80
|
+
Device data monitored during a measurement.
|
|
81
|
+
|
|
82
|
+
Each item is an instance of
|
|
83
|
+
:class:`evefile.entities.data.Data`.
|
|
84
|
+
|
|
85
|
+
position_timestamps : :class:`evefile.entities.data.TimestampData`
|
|
86
|
+
Timestamps for each individual position.
|
|
87
|
+
|
|
88
|
+
Monitors have timestamps (milliseconds since start of the scan)
|
|
89
|
+
rather than positions as primary quantisation axis. This object
|
|
90
|
+
provides a mapping between timestamps and positions and can be used
|
|
91
|
+
to map monitor data to positions.
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
Examples
|
|
95
|
+
--------
|
|
96
|
+
The :class:`File` class is not meant to be used directly, as any
|
|
97
|
+
entities, but rather indirectly by means of the respective facades in
|
|
98
|
+
the boundaries technical layer of the ``evefile`` package.
|
|
99
|
+
Hence, for the time being, there are no dedicated examples how to use
|
|
100
|
+
this class. Of course, you can instantiate an object as usual.
|
|
101
|
+
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
def __init__(self):
|
|
105
|
+
self.metadata = Metadata()
|
|
106
|
+
self.log_messages = []
|
|
107
|
+
self.data = {}
|
|
108
|
+
self.snapshots = {}
|
|
109
|
+
self.monitors = {}
|
|
110
|
+
self.position_timestamps = None
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class Metadata:
|
|
114
|
+
"""
|
|
115
|
+
Metadata of a given eveH5 file.
|
|
116
|
+
|
|
117
|
+
As measurements result in individual files, there is a series of
|
|
118
|
+
crucial metadata of such a measurement on this global level.
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
Attributes
|
|
122
|
+
----------
|
|
123
|
+
filename : :class:`str`
|
|
124
|
+
Name (full path) of the eveH5 file.
|
|
125
|
+
|
|
126
|
+
eveh5_version : :class:`str`
|
|
127
|
+
Version of the eveH5 schema.
|
|
128
|
+
|
|
129
|
+
eve_version : :class:`str`
|
|
130
|
+
Version of the eve engine used to record the data.
|
|
131
|
+
|
|
132
|
+
xml_version : :class:`str`
|
|
133
|
+
Version of the schema used for the scan description (SCML/XML)
|
|
134
|
+
|
|
135
|
+
measurement_station : :class:`str`
|
|
136
|
+
Name of the measurement station used to record the data.
|
|
137
|
+
|
|
138
|
+
start : :class:`datetime.datetime`
|
|
139
|
+
Timestamp of the start of the measurement
|
|
140
|
+
|
|
141
|
+
end : :class:`datetime.datetime`
|
|
142
|
+
Timestamp of the end of the measurement
|
|
143
|
+
|
|
144
|
+
description : :class:`str`
|
|
145
|
+
User-entered description of the entire scan.
|
|
146
|
+
|
|
147
|
+
simulation : :class:`bool`
|
|
148
|
+
Flag signalling whether the measurement was a simulation.
|
|
149
|
+
|
|
150
|
+
Default: ``False``
|
|
151
|
+
|
|
152
|
+
preferred_axis : :class:`string`
|
|
153
|
+
Name of the axis marked as preferred in the scan description.
|
|
154
|
+
|
|
155
|
+
Default: ""
|
|
156
|
+
|
|
157
|
+
preferred_channel : :class:`string`
|
|
158
|
+
Name of the channel marked as preferred in the scan description.
|
|
159
|
+
|
|
160
|
+
Default: ""
|
|
161
|
+
|
|
162
|
+
preferred_normalisation_channel : :class:`string`
|
|
163
|
+
Name of the channel marked as preferred for normalising.
|
|
164
|
+
|
|
165
|
+
Default: ""
|
|
166
|
+
|
|
167
|
+
Examples
|
|
168
|
+
--------
|
|
169
|
+
The :class:`Metadata` class is not meant to be used directly, as any
|
|
170
|
+
entities, but rather indirectly by means of the respective facades in
|
|
171
|
+
the boundaries technical layer of the ``evefile`` package.
|
|
172
|
+
Hence, for the time being, there are no dedicated examples how to use
|
|
173
|
+
this class. Of course, you can instantiate an object as usual.
|
|
174
|
+
|
|
175
|
+
Nevertheless, as you may use the class indirectly, one important feature
|
|
176
|
+
should be highlighted here: the string representation used if you just
|
|
177
|
+
apply :func:`print` to an object of the class:
|
|
178
|
+
|
|
179
|
+
.. code-block::
|
|
180
|
+
|
|
181
|
+
print(Metadata())
|
|
182
|
+
|
|
183
|
+
The output of an (empty) object would look as follows:
|
|
184
|
+
|
|
185
|
+
.. code-block:: bash
|
|
186
|
+
|
|
187
|
+
filename:
|
|
188
|
+
eveh5_version:
|
|
189
|
+
eve_version:
|
|
190
|
+
xml_version:
|
|
191
|
+
measurement_station:
|
|
192
|
+
start: 2025-08-07 10:57:16.849298
|
|
193
|
+
end: 2025-08-07 10:57:16.849307
|
|
194
|
+
description:
|
|
195
|
+
simulation: False
|
|
196
|
+
preferred_axis:
|
|
197
|
+
preferred_channel:
|
|
198
|
+
preferred_normalisation_channel:
|
|
199
|
+
|
|
200
|
+
This can be used to get a convenient overview of the metadata contained
|
|
201
|
+
in a loaded eveH5 file.
|
|
202
|
+
|
|
203
|
+
"""
|
|
204
|
+
|
|
205
|
+
def __init__(self):
|
|
206
|
+
self.filename = ""
|
|
207
|
+
self.eveh5_version = ""
|
|
208
|
+
self.eve_version = ""
|
|
209
|
+
self.xml_version = ""
|
|
210
|
+
self.measurement_station = ""
|
|
211
|
+
self.start = datetime.datetime.now()
|
|
212
|
+
self.end = datetime.datetime.now()
|
|
213
|
+
self.description = ""
|
|
214
|
+
self.simulation = False
|
|
215
|
+
self.preferred_axis = ""
|
|
216
|
+
self.preferred_channel = ""
|
|
217
|
+
self.preferred_normalisation_channel = ""
|
|
218
|
+
|
|
219
|
+
def __str__(self):
|
|
220
|
+
"""
|
|
221
|
+
Human-readable representation of the metadata.
|
|
222
|
+
|
|
223
|
+
Returns
|
|
224
|
+
-------
|
|
225
|
+
output : :class:`str`
|
|
226
|
+
Multiline string with one attribute per line
|
|
227
|
+
|
|
228
|
+
"""
|
|
229
|
+
output = []
|
|
230
|
+
# Note: Attributes are listed manually here for explicit ordering
|
|
231
|
+
attributes = [
|
|
232
|
+
"filename",
|
|
233
|
+
"eveh5_version",
|
|
234
|
+
"eve_version",
|
|
235
|
+
"xml_version",
|
|
236
|
+
"measurement_station",
|
|
237
|
+
"start",
|
|
238
|
+
"end",
|
|
239
|
+
"description",
|
|
240
|
+
"simulation",
|
|
241
|
+
"preferred_axis",
|
|
242
|
+
"preferred_channel",
|
|
243
|
+
"preferred_normalisation_channel",
|
|
244
|
+
]
|
|
245
|
+
attribute_name_length = max(
|
|
246
|
+
len(attribute) for attribute in attributes
|
|
247
|
+
)
|
|
248
|
+
for attribute in attributes:
|
|
249
|
+
output.append(
|
|
250
|
+
f"{attribute:>{attribute_name_length}}:"
|
|
251
|
+
f" {getattr(self, attribute)}"
|
|
252
|
+
)
|
|
253
|
+
return "\n".join(output)
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
class LogMessage:
|
|
257
|
+
"""
|
|
258
|
+
Log message from an individual measurement.
|
|
259
|
+
|
|
260
|
+
Operators can enter log messages during a measurement using the
|
|
261
|
+
eve-gui. In such case, the respective message appears in the eveH5
|
|
262
|
+
file together with a timestamp.
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
Attributes
|
|
266
|
+
----------
|
|
267
|
+
timestamp : :class:`datetime.datetime`
|
|
268
|
+
Timestamp of the log message
|
|
269
|
+
|
|
270
|
+
message : :class:`str`
|
|
271
|
+
Actual content of the log message.
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
Examples
|
|
275
|
+
--------
|
|
276
|
+
The :class:`Scan` class is not meant to be used directly, as any
|
|
277
|
+
entities, but rather indirectly by means of the respective facades in
|
|
278
|
+
the boundaries technical layer of the ``evefile`` package.
|
|
279
|
+
Hence, for the time being, there are no dedicated examples how to use
|
|
280
|
+
this class. Of course, you can instantiate an object as usual.
|
|
281
|
+
|
|
282
|
+
"""
|
|
283
|
+
|
|
284
|
+
def __init__(self):
|
|
285
|
+
self.timestamp = datetime.datetime.now()
|
|
286
|
+
self.message = ""
|
|
287
|
+
|
|
288
|
+
def from_string(self, string=""):
|
|
289
|
+
"""
|
|
290
|
+
Set attributes from string.
|
|
291
|
+
|
|
292
|
+
In eveH5 files up to v7, the log messages are single strings with
|
|
293
|
+
the ISO timestamp at the beginning, followed by the actual message.
|
|
294
|
+
Timestamp and message are separated by ": ".
|
|
295
|
+
|
|
296
|
+
This method separates both parts and converts the timestamp into an
|
|
297
|
+
actual :obj:`datetime.datetime` object, consistent with the
|
|
298
|
+
:attr:`timestamp` attribute.
|
|
299
|
+
|
|
300
|
+
Parameters
|
|
301
|
+
----------
|
|
302
|
+
string : :class:`str`
|
|
303
|
+
Log message consisting of timestamp and actual message.
|
|
304
|
+
|
|
305
|
+
"""
|
|
306
|
+
timestamp, message = string.split(": ", maxsplit=1)
|
|
307
|
+
self.timestamp = datetime.datetime.fromisoformat(timestamp)
|
|
308
|
+
self.message = message
|
|
309
|
+
|
|
310
|
+
def __str__(self):
|
|
311
|
+
"""
|
|
312
|
+
Human-readable representation of the log message.
|
|
313
|
+
|
|
314
|
+
Returns
|
|
315
|
+
-------
|
|
316
|
+
output : :class:`str`
|
|
317
|
+
String containing timestamp and log message
|
|
318
|
+
|
|
319
|
+
"""
|
|
320
|
+
return f"{self.timestamp.isoformat()}: {self.message}"
|