zpic 0.1.0__cp310-cp310-manylinux_2_35_x86_64.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.
- zpic/__init__.py +0 -0
- zpic/em1d.cpython-310-x86_64-linux-gnu.so +0 -0
- zpic/em1ds.cpython-310-x86_64-linux-gnu.so +0 -0
- zpic/em2d.cpython-310-x86_64-linux-gnu.so +0 -0
- zpic/em2ds.cpython-310-x86_64-linux-gnu.so +0 -0
- zpic/es1d.cpython-310-x86_64-linux-gnu.so +0 -0
- zpic/zdf.py +779 -0
- zpic-0.1.0.dist-info/LICENCE +661 -0
- zpic-0.1.0.dist-info/METADATA +43 -0
- zpic-0.1.0.dist-info/RECORD +11 -0
- zpic-0.1.0.dist-info/WHEEL +4 -0
zpic/zdf.py
ADDED
@@ -0,0 +1,779 @@
|
|
1
|
+
"""
|
2
|
+
Python module for reading ZDF data files
|
3
|
+
|
4
|
+
Copyright (C) 2017 Instituto Superior Tecnico
|
5
|
+
|
6
|
+
This file is part of the ZPIC Educational code suite
|
7
|
+
|
8
|
+
The ZPIC Educational code suite is free software: you can redistribute it and/or modify
|
9
|
+
it under the terms of the GNU Affero General Public License as
|
10
|
+
published by the Free Software Foundation, either version 3 of the
|
11
|
+
License, or (at your option) any later version.
|
12
|
+
|
13
|
+
The ZPIC Educational code suite is distributed in the hope that it will be useful,
|
14
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
GNU Affero General Public License for more details.
|
17
|
+
|
18
|
+
You should have received a copy of the GNU Affero General Public License
|
19
|
+
along with the ZPIC Educational code suite. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
"""
|
21
|
+
|
22
|
+
import sys
|
23
|
+
import numpy as np
|
24
|
+
|
25
|
+
class ZDF_Record:
|
26
|
+
"""ZDF_Record()
|
27
|
+
|
28
|
+
ZDF Datafile record information
|
29
|
+
|
30
|
+
Attributes
|
31
|
+
----------
|
32
|
+
pos : int64
|
33
|
+
Position in ZDF file
|
34
|
+
id : int
|
35
|
+
Type id
|
36
|
+
name : str
|
37
|
+
Record name
|
38
|
+
len : uint64
|
39
|
+
Additional record length in bytes
|
40
|
+
"""
|
41
|
+
def __init__( self ):
|
42
|
+
self.pos = -1
|
43
|
+
self.id = -1
|
44
|
+
self.name = ''
|
45
|
+
self.len = -1
|
46
|
+
|
47
|
+
def version( self ):
|
48
|
+
"""version()
|
49
|
+
|
50
|
+
Gets record version number
|
51
|
+
|
52
|
+
Returns
|
53
|
+
-------
|
54
|
+
version : int
|
55
|
+
Record version number
|
56
|
+
"""
|
57
|
+
return self.id & 0x0000FFFF
|
58
|
+
|
59
|
+
def type( self ):
|
60
|
+
"""type( typeTag )
|
61
|
+
|
62
|
+
Gets record type from tag
|
63
|
+
|
64
|
+
Returns
|
65
|
+
-------
|
66
|
+
type : {'int', 'double', 'string', 'dataset', 'iteration', 'grid_info', 'part_info','unknown'}
|
67
|
+
Type of record
|
68
|
+
"""
|
69
|
+
|
70
|
+
typeID = self.id & 0xFFFF0000
|
71
|
+
|
72
|
+
types = {0x00010000: "int",
|
73
|
+
0x00020000: "double",
|
74
|
+
0x00030000: "string",
|
75
|
+
0x00100000: "dataset",
|
76
|
+
0x00200000: "iteration",
|
77
|
+
0x00210000: "grid_info",
|
78
|
+
0x00220000: "part_info", }
|
79
|
+
|
80
|
+
if (typeID in types):
|
81
|
+
return types[typeID]
|
82
|
+
else:
|
83
|
+
return "unknown"
|
84
|
+
|
85
|
+
|
86
|
+
class ZDF_Iteration:
|
87
|
+
"""ZDF_Iteration()
|
88
|
+
|
89
|
+
Class describing iteration information.
|
90
|
+
|
91
|
+
Attributes
|
92
|
+
----------
|
93
|
+
name : str
|
94
|
+
Name for iteration metadata (usually set to 'ITERATION')
|
95
|
+
n : int
|
96
|
+
Iteration value
|
97
|
+
t : float
|
98
|
+
Time value
|
99
|
+
tunits : str
|
100
|
+
Units used for time value
|
101
|
+
"""
|
102
|
+
def __init__( self ):
|
103
|
+
self.name = ""
|
104
|
+
self.n = 0
|
105
|
+
self.t = 0.0
|
106
|
+
self.tunits = ""
|
107
|
+
|
108
|
+
class ZDF_Grid_Axis:
|
109
|
+
"""ZDF_Grid_Axis()
|
110
|
+
|
111
|
+
Class describing grid axis
|
112
|
+
|
113
|
+
Attributes
|
114
|
+
----------
|
115
|
+
name : str
|
116
|
+
Axis name
|
117
|
+
type : {0,1,2}
|
118
|
+
Axis type, must be one of 0 (linear), 1 (log10) or 2 (log2)
|
119
|
+
min : float
|
120
|
+
Minimum axis value
|
121
|
+
max : float
|
122
|
+
Maximum axis value
|
123
|
+
label : str
|
124
|
+
Axis label
|
125
|
+
units : str
|
126
|
+
Axis values data units
|
127
|
+
"""
|
128
|
+
def __init__( self ):
|
129
|
+
self.name = ''
|
130
|
+
self.type = 0
|
131
|
+
self.min = 0.
|
132
|
+
self.max = 0.
|
133
|
+
self.label = ''
|
134
|
+
self.units = ''
|
135
|
+
|
136
|
+
class ZDF_Grid_Info:
|
137
|
+
"""ZDF_Grid_Info()
|
138
|
+
|
139
|
+
Grid dataset information
|
140
|
+
|
141
|
+
Attributes
|
142
|
+
----------
|
143
|
+
ndims : int
|
144
|
+
Dimensionality of dataset
|
145
|
+
nx : list of int (ndims)
|
146
|
+
Number of grid points in each direction
|
147
|
+
label : str
|
148
|
+
Dataset label
|
149
|
+
units : str
|
150
|
+
Dataset units
|
151
|
+
has_axis : bool
|
152
|
+
True if the dataset includes axis information
|
153
|
+
axis : list of ZDF_Grid_Axis (ndims)
|
154
|
+
Information on each axis, when available
|
155
|
+
"""
|
156
|
+
def __init__( self ):
|
157
|
+
self.name = ''
|
158
|
+
self.ndims = 0
|
159
|
+
self.nx = []
|
160
|
+
self.label = ''
|
161
|
+
self.units = ''
|
162
|
+
self.has_axis = 0
|
163
|
+
self.axis = []
|
164
|
+
|
165
|
+
class ZDF_Part_Info:
|
166
|
+
"""ZDF_Part_Info()
|
167
|
+
|
168
|
+
Particle dataset information
|
169
|
+
|
170
|
+
Attributes
|
171
|
+
----------
|
172
|
+
name : str
|
173
|
+
Particle dataset name
|
174
|
+
label : str
|
175
|
+
Particle dataset label
|
176
|
+
nquants : int
|
177
|
+
Number of quantities per particle
|
178
|
+
quants : list of str (nquants)
|
179
|
+
Name of individual quantities
|
180
|
+
qlabels : dictionary
|
181
|
+
Labels for each quantity
|
182
|
+
qunits : dictionary
|
183
|
+
Units for each quantity
|
184
|
+
nparts: int
|
185
|
+
Number of particles in dataset
|
186
|
+
"""
|
187
|
+
def __init__( self ):
|
188
|
+
self.name = ''
|
189
|
+
self.label = ''
|
190
|
+
self.nquants = 0
|
191
|
+
self.quants = []
|
192
|
+
self.qlabels = dict()
|
193
|
+
self.qunits = dict()
|
194
|
+
self.nparts = 0
|
195
|
+
|
196
|
+
class ZDFfile:
|
197
|
+
"""ZDFfile( file_name )
|
198
|
+
|
199
|
+
ZDF data file class
|
200
|
+
|
201
|
+
Parameters
|
202
|
+
----------
|
203
|
+
file_name : str
|
204
|
+
File name of ZDF data file, should include path
|
205
|
+
"""
|
206
|
+
def __init__(self, file_name):
|
207
|
+
self.__file = open(file_name, "rb")
|
208
|
+
|
209
|
+
# Check magic number
|
210
|
+
magic = self.__file.read(4)
|
211
|
+
if (magic != b'ZDF1'):
|
212
|
+
print('File is not a proper ZDF file, aborting', file=sys.stderr)
|
213
|
+
self.__file.close
|
214
|
+
|
215
|
+
def close(self):
|
216
|
+
"""close()
|
217
|
+
|
218
|
+
Closes ZDF file
|
219
|
+
"""
|
220
|
+
self.__file.close
|
221
|
+
|
222
|
+
def __read_uint32(self):
|
223
|
+
data = np.fromfile(self.__file,dtype='<u4',count=1)
|
224
|
+
if ( data.size == 0 ):
|
225
|
+
return False
|
226
|
+
else:
|
227
|
+
return data[0]
|
228
|
+
|
229
|
+
def __read_int32(self):
|
230
|
+
return np.fromfile(self.__file,dtype='<i4',count=1)[0]
|
231
|
+
|
232
|
+
def __read_uint64(self):
|
233
|
+
return np.fromfile(self.__file,dtype='<u8',count=1)[0]
|
234
|
+
|
235
|
+
def __read_int64(self):
|
236
|
+
return np.fromfile(self.__file,dtype='<i8',count=1)[0]
|
237
|
+
|
238
|
+
def __read_float32(self):
|
239
|
+
return np.fromfile(self.__file,dtype='<f4',count=1)[0]
|
240
|
+
|
241
|
+
def __read_float64(self):
|
242
|
+
return np.fromfile(self.__file,dtype='<f8',count=1)[0]
|
243
|
+
|
244
|
+
def __read_string(self):
|
245
|
+
|
246
|
+
length = self.__read_uint32()
|
247
|
+
|
248
|
+
if (length > 0):
|
249
|
+
data = self.__file.read(length)
|
250
|
+
fstring = data.decode()
|
251
|
+
|
252
|
+
# Data is always written in blocks of 4 byt
|
253
|
+
pad = ((length - 1) // 4 + 1) * 4 - length
|
254
|
+
if ( pad > 0 ):
|
255
|
+
self.__file.seek(pad,1)
|
256
|
+
else:
|
257
|
+
fstring = ""
|
258
|
+
|
259
|
+
return fstring
|
260
|
+
|
261
|
+
def record_type(self, typeTag):
|
262
|
+
version = typeTag & 0x0000FFFF
|
263
|
+
typeID = typeTag & 0xFFFF0000
|
264
|
+
|
265
|
+
types = {0x00010000: "int",
|
266
|
+
0x00020000: "double",
|
267
|
+
0x00030000: "string",
|
268
|
+
0x00100000: "dataset",
|
269
|
+
0x00110000: "cdset_start",
|
270
|
+
0x00120000: "cdset_chunk",
|
271
|
+
0x00130000: "cdset_end",
|
272
|
+
0x00200000: "iteration",
|
273
|
+
0x00210000: "grid_info",
|
274
|
+
0x00220000: "part_info",
|
275
|
+
0x00230000: "track_info", }
|
276
|
+
|
277
|
+
if (typeID in types):
|
278
|
+
return types[typeID]
|
279
|
+
else:
|
280
|
+
return "unknown"
|
281
|
+
|
282
|
+
# -----------------------------------------------------------------------------
|
283
|
+
# Array datatypes
|
284
|
+
# -----------------------------------------------------------------------------
|
285
|
+
|
286
|
+
def __read_int32_arr(self, nx):
|
287
|
+
size = np.prod(nx)
|
288
|
+
data = np.fromfile(self.__file,dtype='<i4',count=size)
|
289
|
+
data.shape = np.flip(nx)
|
290
|
+
return data
|
291
|
+
|
292
|
+
def __read_uint32_arr(self, nx):
|
293
|
+
size = np.prod(nx)
|
294
|
+
data = np.fromfile(self.__file,dtype='<u4',count=size)
|
295
|
+
data.shape = np.flip(nx)
|
296
|
+
return data
|
297
|
+
|
298
|
+
def __read_int64_arr(self, nx):
|
299
|
+
size = np.prod(nx)
|
300
|
+
data = np.fromfile(self.__file,dtype='<i8',count=size)
|
301
|
+
data.shape = np.flip(nx)
|
302
|
+
return data
|
303
|
+
|
304
|
+
def __read_uint64_arr(self, nx):
|
305
|
+
size = np.prod(nx)
|
306
|
+
data = np.fromfile(self.__file,dtype='<u8',count=size)
|
307
|
+
data.shape = np.flip(nx)
|
308
|
+
return data
|
309
|
+
|
310
|
+
def __read_float32_arr(self, nx):
|
311
|
+
size = np.prod(nx)
|
312
|
+
data = np.fromfile(self.__file,dtype='<f4',count=size)
|
313
|
+
data.shape = np.flip(nx)
|
314
|
+
return data
|
315
|
+
|
316
|
+
def __read_float64_arr(self, nx):
|
317
|
+
size = np.prod(nx)
|
318
|
+
data = np.fromfile(self.__file,dtype='<f8',count=size)
|
319
|
+
data.shape = np.flip(nx)
|
320
|
+
return data
|
321
|
+
|
322
|
+
def __read_arr( self, dtype, nx ):
|
323
|
+
|
324
|
+
if ( dtype == 5 ):
|
325
|
+
data = self.__read_int32_arr(nx)
|
326
|
+
elif ( dtype == 3 ):
|
327
|
+
data = self.__read_uint32_arr(nx)
|
328
|
+
elif ( dtype == 7 ):
|
329
|
+
data = self.__read_int64_arr(nx)
|
330
|
+
elif ( dtype == 8 ):
|
331
|
+
data = self.__read_uint64_arr(nx)
|
332
|
+
elif ( dtype == 9 ):
|
333
|
+
data = self.__read_float32_arr(nx)
|
334
|
+
elif ( dtype == 10 ):
|
335
|
+
data = self.__read_float64_arr(nx)
|
336
|
+
else:
|
337
|
+
print( '(*error*) ZDF: Data type not yet supported.' , file=sys.stderr)
|
338
|
+
data = False
|
339
|
+
|
340
|
+
return data
|
341
|
+
|
342
|
+
# -----------------------------------------------------------------------------
|
343
|
+
# Low level interfaces
|
344
|
+
# -----------------------------------------------------------------------------
|
345
|
+
|
346
|
+
# -----------------------------------------------------------------------------
|
347
|
+
# Read record header
|
348
|
+
# -----------------------------------------------------------------------------
|
349
|
+
|
350
|
+
def read_record(self, skip=False):
|
351
|
+
"""read_record(skip=False)
|
352
|
+
|
353
|
+
Reads current record information from file
|
354
|
+
|
355
|
+
Parameters
|
356
|
+
----------
|
357
|
+
skip : bool, optional
|
358
|
+
If set to True, skip to next record after reading record
|
359
|
+
header data
|
360
|
+
"""
|
361
|
+
|
362
|
+
rec = ZDF_Record()
|
363
|
+
rec.pos = self.__file.tell()
|
364
|
+
|
365
|
+
# Read record id and check for EOF
|
366
|
+
rec.id = self.__read_uint32()
|
367
|
+
|
368
|
+
if (rec.id is False):
|
369
|
+
# If end of file return false
|
370
|
+
return False
|
371
|
+
|
372
|
+
# Read name and length
|
373
|
+
rec.name = self.__read_string()
|
374
|
+
rec.len = self.__read_uint64()
|
375
|
+
|
376
|
+
# If requested, skip over to next record
|
377
|
+
if (skip):
|
378
|
+
self.__file.seek(rec.len, 1)
|
379
|
+
|
380
|
+
return rec
|
381
|
+
|
382
|
+
def __record_skip( self, rec ):
|
383
|
+
self.__file.seek(rec.len, 1)
|
384
|
+
|
385
|
+
# -----------------------------------------------------------------------------
|
386
|
+
# Read string
|
387
|
+
# -----------------------------------------------------------------------------
|
388
|
+
|
389
|
+
def read_string(self, rec = False):
|
390
|
+
"""read_string(rec = False)
|
391
|
+
|
392
|
+
Reads string record from data file
|
393
|
+
|
394
|
+
Parameters
|
395
|
+
----------
|
396
|
+
rec : ZDF_Record, optional
|
397
|
+
If not set the routine will read the record before reading the data
|
398
|
+
|
399
|
+
Returns
|
400
|
+
-------
|
401
|
+
string : str
|
402
|
+
String data
|
403
|
+
"""
|
404
|
+
if ( rec is False ):
|
405
|
+
rec = self.read_record()
|
406
|
+
|
407
|
+
fstring = self.__read_string()
|
408
|
+
return fstring
|
409
|
+
|
410
|
+
# -----------------------------------------------------------------------------
|
411
|
+
# Read iteration
|
412
|
+
# -----------------------------------------------------------------------------
|
413
|
+
|
414
|
+
def read_iteration(self, rec = False):
|
415
|
+
"""read_iteration( rec = False )
|
416
|
+
|
417
|
+
Read iteration record from data file
|
418
|
+
|
419
|
+
Parameters
|
420
|
+
----------
|
421
|
+
rec : ZDF_Record, optional
|
422
|
+
If not set the routine will read the record before reading the data
|
423
|
+
|
424
|
+
Returns
|
425
|
+
-------
|
426
|
+
iteration : ZDF_Iteration()
|
427
|
+
Iteration data
|
428
|
+
"""
|
429
|
+
if ( rec is False ):
|
430
|
+
rec = self.read_record()
|
431
|
+
iteration = ZDF_Iteration()
|
432
|
+
iteration.name = rec.name
|
433
|
+
iteration.n = self.__read_int32()
|
434
|
+
iteration.t = self.__read_float64()
|
435
|
+
iteration.tunits = self.__read_string()
|
436
|
+
return iteration
|
437
|
+
|
438
|
+
# -----------------------------------------------------------------------------
|
439
|
+
# Read grid info
|
440
|
+
# -----------------------------------------------------------------------------
|
441
|
+
|
442
|
+
def read_grid_info(self, rec = False):
|
443
|
+
"""read_grid_info( rec = False )
|
444
|
+
|
445
|
+
Read grid information record from data file
|
446
|
+
|
447
|
+
Parameters
|
448
|
+
----------
|
449
|
+
rec : ZDF_Record, optional
|
450
|
+
If not set the routine will read the record before reading the data
|
451
|
+
|
452
|
+
Returns
|
453
|
+
-------
|
454
|
+
info : ZDF_Grid_Info()
|
455
|
+
Grid information data
|
456
|
+
"""
|
457
|
+
if ( rec is False ):
|
458
|
+
rec = self.read_record()
|
459
|
+
|
460
|
+
# Maximum supported version
|
461
|
+
max_version = 0x00000001
|
462
|
+
|
463
|
+
# Get version
|
464
|
+
version = rec.version()
|
465
|
+
if ( version > max_version ):
|
466
|
+
print( '(*error*) ZDF: Grid info version is higher than supported.' , file=sys.stderr)
|
467
|
+
print( '(*error*) ZDF: Please update the code to a newer version.' , file=sys.stderr)
|
468
|
+
return False
|
469
|
+
|
470
|
+
info = ZDF_Grid_Info()
|
471
|
+
|
472
|
+
info.name = rec.name
|
473
|
+
info.ndims = self.__read_uint32()
|
474
|
+
info.nx = self.__read_uint64_arr( info.ndims )
|
475
|
+
|
476
|
+
info.label = self.__read_string()
|
477
|
+
info.units = self.__read_string()
|
478
|
+
info.has_axis = self.__read_int32()
|
479
|
+
|
480
|
+
if ( info.has_axis ):
|
481
|
+
for i in range(info.ndims):
|
482
|
+
ax = ZDF_Grid_Axis()
|
483
|
+
if (version > 0):
|
484
|
+
ax.name = self.__read_string()
|
485
|
+
else:
|
486
|
+
ax.name = 'axis_{}'.format(i)
|
487
|
+
ax.type = self.__read_int32()
|
488
|
+
ax.min = self.__read_float64()
|
489
|
+
ax.max = self.__read_float64()
|
490
|
+
ax.label = self.__read_string()
|
491
|
+
ax.units = self.__read_string()
|
492
|
+
info.axis.append(ax)
|
493
|
+
|
494
|
+
return info
|
495
|
+
|
496
|
+
# -----------------------------------------------------------------------------
|
497
|
+
# Read particle info
|
498
|
+
# -----------------------------------------------------------------------------
|
499
|
+
|
500
|
+
def read_part_info(self, rec = False):
|
501
|
+
"""read_part_info( rec = False )
|
502
|
+
|
503
|
+
Read particle information record from data file
|
504
|
+
|
505
|
+
Parameters
|
506
|
+
----------
|
507
|
+
rec : ZDF_Record, optional
|
508
|
+
If not set the routine will read the record before reading the data
|
509
|
+
|
510
|
+
Returns
|
511
|
+
-------
|
512
|
+
iteration : ZDF_Part_Info()
|
513
|
+
Iteration data
|
514
|
+
"""
|
515
|
+
if ( rec is False ):
|
516
|
+
rec = self.read_record()
|
517
|
+
|
518
|
+
# Maximum supported version
|
519
|
+
max_version = 0x00000002
|
520
|
+
|
521
|
+
# Get version
|
522
|
+
version = rec.version()
|
523
|
+
if ( version > max_version ):
|
524
|
+
print( '(*error*) ZDF: Particles info version is higher than supported.' , file=sys.stderr)
|
525
|
+
print( '(*error*) ZDF: Please update the code to a newer version.' , file=sys.stderr)
|
526
|
+
return False
|
527
|
+
|
528
|
+
info = ZDF_Part_Info()
|
529
|
+
info.name = rec.name
|
530
|
+
info.label = self.__read_string()
|
531
|
+
|
532
|
+
if ( version >= 1 ):
|
533
|
+
# version 1
|
534
|
+
info.nparts = self.__read_uint64()
|
535
|
+
info.nquants = self.__read_uint32()
|
536
|
+
|
537
|
+
for i in range(info.nquants):
|
538
|
+
info.quants.append( self.__read_string() )
|
539
|
+
for q in info.quants:
|
540
|
+
info.qlabels[q] = self.__read_string()
|
541
|
+
for q in info.quants:
|
542
|
+
info.qunits[q] = self.__read_string()
|
543
|
+
|
544
|
+
else:
|
545
|
+
# version 0
|
546
|
+
info.nquants = self.__read_uint32()
|
547
|
+
|
548
|
+
for i in range(info.nquants):
|
549
|
+
info.quants.append( self.__read_string() )
|
550
|
+
|
551
|
+
# version 0 does not have label information
|
552
|
+
for q in info.quants:
|
553
|
+
info.qlabels[q] = q
|
554
|
+
|
555
|
+
for q in info.quants:
|
556
|
+
info.qunits[q] = self.__read_string()
|
557
|
+
|
558
|
+
info.nparts = self.__read_uint64()
|
559
|
+
|
560
|
+
return info
|
561
|
+
|
562
|
+
# -----------------------------------------------------------------------------
|
563
|
+
# Read dataset
|
564
|
+
# -----------------------------------------------------------------------------
|
565
|
+
|
566
|
+
def read_dataset(self, rec = False):
|
567
|
+
"""read_dataset()
|
568
|
+
|
569
|
+
Read dataset from data file
|
570
|
+
|
571
|
+
Parameters
|
572
|
+
----------
|
573
|
+
rec : ZDF_Record, optional
|
574
|
+
If not set the routine will read the record before reading the data
|
575
|
+
|
576
|
+
Returns
|
577
|
+
-------
|
578
|
+
data : numpy.ndarray
|
579
|
+
Numpy ndarray with data
|
580
|
+
"""
|
581
|
+
if ( rec is False ):
|
582
|
+
rec = self.read_record()
|
583
|
+
|
584
|
+
if ( self.record_type(rec.id) != 'dataset' ):
|
585
|
+
print( '(*error*) ZDF: Expected dataset record but found {} instead.'.format(self.record_type(rec.id)),
|
586
|
+
file=sys.stderr)
|
587
|
+
return False
|
588
|
+
|
589
|
+
|
590
|
+
# Maximum supported version
|
591
|
+
max_version = 0x00000002
|
592
|
+
|
593
|
+
# Get version
|
594
|
+
version = rec.version()
|
595
|
+
if ( version > max_version ):
|
596
|
+
print( '(*error*) ZDF: Dataset version is higher than supported.' , file=sys.stderr)
|
597
|
+
print( '(*error*) ZDF: Please update the code to a newer version.' , file=sys.stderr)
|
598
|
+
return False
|
599
|
+
|
600
|
+
# Version 0x0001 includes id tag
|
601
|
+
if ( version >= 1 ):
|
602
|
+
id = self.__read_uint32()
|
603
|
+
else:
|
604
|
+
id = 0
|
605
|
+
|
606
|
+
data_type = self.__read_int32()
|
607
|
+
ndims = self.__read_uint32()
|
608
|
+
nx = self.__read_uint64_arr(ndims)
|
609
|
+
data = self.__read_arr( data_type, nx )
|
610
|
+
|
611
|
+
return data
|
612
|
+
|
613
|
+
# -----------------------------------------------------------------------------
|
614
|
+
# Retrieve list of file contents / print file contents
|
615
|
+
# -----------------------------------------------------------------------------
|
616
|
+
|
617
|
+
def list(self, printRec=False):
|
618
|
+
"""list( printRec=False )
|
619
|
+
|
620
|
+
Gets a list of file contents and optionally prints it to screen
|
621
|
+
|
622
|
+
Parameters
|
623
|
+
----------
|
624
|
+
printRec : bool, optional
|
625
|
+
If set to True will print all records found in the file,
|
626
|
+
defaults to False.
|
627
|
+
"""
|
628
|
+
# Position file after magic number
|
629
|
+
self.__file.seek(4)
|
630
|
+
|
631
|
+
rec_list = []
|
632
|
+
while True:
|
633
|
+
rec = self.read_record(skip=True)
|
634
|
+
if (rec is False):
|
635
|
+
break
|
636
|
+
else:
|
637
|
+
rec_list.append(rec)
|
638
|
+
|
639
|
+
if (printRec and (len(rec_list) > 0)):
|
640
|
+
print('Position Size(bytes) Type Name')
|
641
|
+
print('-----------------------------------------------------')
|
642
|
+
for rec in rec_list:
|
643
|
+
print('{:#010x} {:#010x} {:11} {}'.format(
|
644
|
+
rec.pos, rec.len,
|
645
|
+
self.record_type(rec.id), rec.name)
|
646
|
+
)
|
647
|
+
|
648
|
+
return rec_list
|
649
|
+
|
650
|
+
# -----------------------------------------------------------------------------
|
651
|
+
# High level interfaces
|
652
|
+
# -----------------------------------------------------------------------------
|
653
|
+
|
654
|
+
class ZDF_Info:
|
655
|
+
"""ZDF_Info()
|
656
|
+
ZDF File information
|
657
|
+
|
658
|
+
Attributes
|
659
|
+
----------
|
660
|
+
type : {'grid','particles'}
|
661
|
+
Type of ZDF file
|
662
|
+
grid : ZDF_Grid_Info
|
663
|
+
Grid information for grid files
|
664
|
+
particles : ZDF_Part_Info
|
665
|
+
Particle information for particle files
|
666
|
+
iteration : ZDF_Iteration
|
667
|
+
Iteration information
|
668
|
+
|
669
|
+
"""
|
670
|
+
def __init__(self):
|
671
|
+
self.type = ""
|
672
|
+
self.grid = None
|
673
|
+
self.particles = None
|
674
|
+
self.iteration = None
|
675
|
+
|
676
|
+
|
677
|
+
def info( file_name ):
|
678
|
+
"""info( file_name )
|
679
|
+
|
680
|
+
Gets metadata for a ZDF file
|
681
|
+
|
682
|
+
Parameters
|
683
|
+
----------
|
684
|
+
file_name : str
|
685
|
+
File name of ZDF data file, should include path
|
686
|
+
|
687
|
+
Returns
|
688
|
+
-------
|
689
|
+
info : ZDF_Info
|
690
|
+
File information. If file is invalid False is returned.
|
691
|
+
"""
|
692
|
+
# Open file
|
693
|
+
zdf = ZDFfile( file_name )
|
694
|
+
|
695
|
+
# Check file type and read metadata
|
696
|
+
info = ZDF_Info()
|
697
|
+
info.type = zdf.read_string()
|
698
|
+
if ( info.type == "grid" ):
|
699
|
+
info.grid = zdf.read_grid_info()
|
700
|
+
elif ( info.type == "particles" ):
|
701
|
+
info.particles = zdf.read_part_info()
|
702
|
+
else:
|
703
|
+
print("File is not a valid ZDF grid or particles file", file=sys.stderr)
|
704
|
+
zdf.close()
|
705
|
+
return False
|
706
|
+
|
707
|
+
# Read iteration info
|
708
|
+
info.iteration = zdf.read_iteration()
|
709
|
+
|
710
|
+
# Close file
|
711
|
+
zdf.close()
|
712
|
+
|
713
|
+
return info
|
714
|
+
|
715
|
+
def read( file_name ):
|
716
|
+
"""read( file_name )
|
717
|
+
|
718
|
+
Reads all data in a ZDF file
|
719
|
+
|
720
|
+
Parameters
|
721
|
+
----------
|
722
|
+
file_name : str
|
723
|
+
File name of ZDF data file, should include path
|
724
|
+
|
725
|
+
Returns
|
726
|
+
-------
|
727
|
+
(data, info) : ( numpy.ndarray | dictionary, ZDF_Info )
|
728
|
+
Tuple containing file data and metadata. Data will be a
|
729
|
+
numpy.ndarray for grid data, and a dictionary of numpy.array for
|
730
|
+
particle data (one entry per quantity). Metadata is returned as a
|
731
|
+
ZDF_Info object. If file is invalid False is returned.
|
732
|
+
"""
|
733
|
+
# Open file
|
734
|
+
zdf = ZDFfile( file_name )
|
735
|
+
|
736
|
+
# Check file type and read metadata
|
737
|
+
info = ZDF_Info()
|
738
|
+
|
739
|
+
info.type = zdf.read_string()
|
740
|
+
if ( info.type == "grid" ):
|
741
|
+
info.grid = zdf.read_grid_info()
|
742
|
+
info.iteration = zdf.read_iteration()
|
743
|
+
data = zdf.read_dataset()
|
744
|
+
elif ( info.type == "particles" ):
|
745
|
+
info.particles = zdf.read_part_info()
|
746
|
+
info.iteration = zdf.read_iteration()
|
747
|
+
|
748
|
+
# Read all quantities
|
749
|
+
data = dict()
|
750
|
+
for q in info.particles.quants:
|
751
|
+
data[q] = zdf.read_dataset()
|
752
|
+
else:
|
753
|
+
print("File is not a valid ZDF grid or particles file", file=sys.stderr)
|
754
|
+
zdf.close()
|
755
|
+
return False
|
756
|
+
|
757
|
+
#Close file
|
758
|
+
zdf.close()
|
759
|
+
|
760
|
+
return (data,info)
|
761
|
+
|
762
|
+
def list(file_name, printRec=False):
|
763
|
+
"""list( printRec=False )
|
764
|
+
|
765
|
+
Gets a list of file contents and optionally print it to screen
|
766
|
+
|
767
|
+
Parameters
|
768
|
+
----------
|
769
|
+
file_name : str
|
770
|
+
File name of ZDF data file, should include path
|
771
|
+
|
772
|
+
printRec : bool, optional
|
773
|
+
If set to True will print all records found in the file,
|
774
|
+
defaults to False.
|
775
|
+
"""
|
776
|
+
zdf = ZDFfile(file_name)
|
777
|
+
zdf.list(printRec)
|
778
|
+
zdf.close()
|
779
|
+
|