osiris-utils 1.0.9__py3-none-any.whl → 1.1.1__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.
- osiris_utils/__init__.py +3 -3
- osiris_utils/data.py +150 -209
- osiris_utils/simulation_data.py +229 -0
- osiris_utils/utils.py +0 -1
- {osiris_utils-1.0.9.dist-info → osiris_utils-1.1.1.dist-info}/METADATA +30 -2
- osiris_utils-1.1.1.dist-info/RECORD +11 -0
- osiris_utils/data_readers.py +0 -119
- osiris_utils-1.0.9.dist-info/RECORD +0 -11
- {osiris_utils-1.0.9.dist-info → osiris_utils-1.1.1.dist-info}/LICENSE.txt +0 -0
- {osiris_utils-1.0.9.dist-info → osiris_utils-1.1.1.dist-info}/WHEEL +0 -0
- {osiris_utils-1.0.9.dist-info → osiris_utils-1.1.1.dist-info}/top_level.txt +0 -0
osiris_utils/__init__.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from .utils import (time_estimation, filesize_estimation, transverse_average, integrate, animate_2D,
|
|
2
2
|
save_data, read_data, courant2D)
|
|
3
|
-
from .data_readers import open1D, open2D, open3D, read_osiris_file
|
|
4
3
|
from .gui import LAVA_Qt, LAVA
|
|
5
|
-
from .data import OsirisGridFile, OsirisRawFile, OsirisData
|
|
6
|
-
from .mean_field_theory import MeanFieldTheory
|
|
4
|
+
from .data import OsirisGridFile, OsirisRawFile, OsirisData, OsirisHIST
|
|
5
|
+
from .mean_field_theory import MeanFieldTheory
|
|
6
|
+
from .simulation_data import OsirisSimulation
|
osiris_utils/data.py
CHANGED
|
@@ -1,43 +1,53 @@
|
|
|
1
1
|
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
2
3
|
import h5py
|
|
3
4
|
|
|
4
5
|
class OsirisData():
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
"""
|
|
7
|
+
Base class for handling OSIRIS simulation data files (HDF5 and HIST formats).
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
This class provides common functionality for reading and managing basic attributes
|
|
10
|
+
from OSIRIS output files. It serves as the parent class for specialized data handlers.
|
|
11
|
+
|
|
12
|
+
Parameters
|
|
12
13
|
----------
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
14
|
+
filename : str
|
|
15
|
+
Path to the data file. Supported formats:
|
|
16
|
+
- HDF5 files (.h5 extension)
|
|
17
|
+
- HIST files (ending with _ene)
|
|
18
|
+
|
|
19
|
+
Attributes
|
|
20
|
+
----------
|
|
21
|
+
dt : float
|
|
22
|
+
Time step of the simulation [simulation units]
|
|
23
|
+
dim : int
|
|
24
|
+
Number of dimensions in the simulation (1, 2, or 3)
|
|
25
|
+
time : list[float, str]
|
|
26
|
+
Current simulation time and units as [value, unit_string]
|
|
27
|
+
iter : int
|
|
28
|
+
Current iteration number
|
|
29
|
+
name : str
|
|
30
|
+
Name identifier of the data field
|
|
31
|
+
type : str
|
|
32
|
+
Type of data (e.g., 'grid', 'particles')
|
|
33
|
+
verbose : bool
|
|
34
|
+
Verbosity flag controlling diagnostic messages (default: False)
|
|
35
|
+
"""
|
|
36
|
+
|
|
33
37
|
def __init__(self, filename):
|
|
34
38
|
self._filename = filename
|
|
35
|
-
self._file = None
|
|
39
|
+
# self._file = None
|
|
36
40
|
|
|
37
41
|
self._verbose = False
|
|
38
42
|
|
|
39
|
-
self.
|
|
40
|
-
|
|
43
|
+
if self._filename.endswith('.h5'):
|
|
44
|
+
self._open_file_hdf5(self._filename)
|
|
45
|
+
self._load_basic_attributes(self._file)
|
|
46
|
+
elif self._filename.endswith('_ene'):
|
|
47
|
+
self._open_hist_file(self._filename)
|
|
48
|
+
else:
|
|
49
|
+
raise ValueError('The file should be an HDF5 file with the extension .h5, or a HIST file ending with _ene.')
|
|
50
|
+
|
|
41
51
|
|
|
42
52
|
def _load_basic_attributes(self, f: h5py.File) -> None:
|
|
43
53
|
'''Load common attributes from HDF5 file'''
|
|
@@ -59,9 +69,9 @@ class OsirisData():
|
|
|
59
69
|
'''
|
|
60
70
|
self._verbose = verbose
|
|
61
71
|
|
|
62
|
-
def
|
|
72
|
+
def _open_file_hdf5(self, filename):
|
|
63
73
|
'''
|
|
64
|
-
Open the HDF5 file.
|
|
74
|
+
Open the OSIRIS output file. Usually an HDF5 file or txt.
|
|
65
75
|
|
|
66
76
|
Parameters
|
|
67
77
|
----------
|
|
@@ -69,7 +79,14 @@ class OsirisData():
|
|
|
69
79
|
The path to the HDF5 file.
|
|
70
80
|
'''
|
|
71
81
|
if self._verbose: print(f'Opening file > {filename}')
|
|
72
|
-
|
|
82
|
+
|
|
83
|
+
if filename.endswith('.h5'):
|
|
84
|
+
self._file = h5py.File(filename, 'r')
|
|
85
|
+
else:
|
|
86
|
+
raise ValueError('The file should be an HDF5 file with the extension .h5')
|
|
87
|
+
|
|
88
|
+
def _open_hist_file(self, filename):
|
|
89
|
+
self._df = pd.read_csv(filename, sep=r'\s+', comment='!', header=0, engine='python')
|
|
73
90
|
|
|
74
91
|
def _close_file(self):
|
|
75
92
|
'''
|
|
@@ -81,103 +98,59 @@ class OsirisData():
|
|
|
81
98
|
|
|
82
99
|
@property
|
|
83
100
|
def dt(self):
|
|
84
|
-
'''
|
|
85
|
-
Returns
|
|
86
|
-
-------
|
|
87
|
-
float
|
|
88
|
-
The time step
|
|
89
|
-
'''
|
|
90
101
|
return self._dt
|
|
91
102
|
@property
|
|
92
103
|
def dim(self):
|
|
93
|
-
'''
|
|
94
|
-
Returns
|
|
95
|
-
-------
|
|
96
|
-
int
|
|
97
|
-
The number of dimensions
|
|
98
|
-
'''
|
|
99
104
|
return self._dim
|
|
100
105
|
@property
|
|
101
106
|
def time(self):
|
|
102
|
-
'''
|
|
103
|
-
Returns
|
|
104
|
-
-------
|
|
105
|
-
list
|
|
106
|
-
The time and its units
|
|
107
|
-
'''
|
|
108
107
|
return self._time
|
|
109
108
|
@property
|
|
110
109
|
def iter(self):
|
|
111
|
-
'''
|
|
112
|
-
Returns
|
|
113
|
-
-------
|
|
114
|
-
int
|
|
115
|
-
The iteration number
|
|
116
|
-
'''
|
|
117
110
|
return self._iter
|
|
118
111
|
@property
|
|
119
112
|
def name(self):
|
|
120
|
-
'''
|
|
121
|
-
Returns
|
|
122
|
-
-------
|
|
123
|
-
str
|
|
124
|
-
The name of the data
|
|
125
|
-
'''
|
|
126
113
|
return self._name
|
|
127
114
|
@property
|
|
128
115
|
def type(self):
|
|
129
|
-
'''
|
|
130
|
-
Returns
|
|
131
|
-
-------
|
|
132
|
-
str
|
|
133
|
-
The type of data
|
|
134
|
-
'''
|
|
135
116
|
return self._type
|
|
136
117
|
|
|
137
118
|
class OsirisGridFile(OsirisData):
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
-----
|
|
143
|
-
- filename: the path to the HDF5 file
|
|
144
|
-
|
|
145
|
-
Attributes:
|
|
119
|
+
"""
|
|
120
|
+
Handles structured grid data from OSIRIS HDF5 simulations, including electromagnetic fields.
|
|
121
|
+
|
|
122
|
+
Parameters
|
|
146
123
|
----------
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
- name
|
|
163
|
-
|
|
164
|
-
-
|
|
165
|
-
|
|
166
|
-
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
- data
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
str
|
|
178
|
-
- label - the label of the data (LaTeX formatted)
|
|
179
|
-
|
|
180
|
-
'''
|
|
124
|
+
filename : str
|
|
125
|
+
Path to OSIRIS HDF5 grid file (.h5 extension)
|
|
126
|
+
|
|
127
|
+
Attributes
|
|
128
|
+
----------
|
|
129
|
+
grid : np.ndarray
|
|
130
|
+
Grid boundaries as ((x1_min, x1_max), (x2_min, x2_max), ...)
|
|
131
|
+
nx : tuple
|
|
132
|
+
Number of grid points per dimension (nx1, nx2, nx3)
|
|
133
|
+
dx : np.ndarray
|
|
134
|
+
Grid spacing per dimension (dx1, dx2, dx3)
|
|
135
|
+
x : list[np.ndarray]
|
|
136
|
+
Spatial coordinates arrays for each dimension
|
|
137
|
+
axis : list[dict]
|
|
138
|
+
Axis metadata with keys:
|
|
139
|
+
- 'name': Axis identifier (e.g., 'x1')
|
|
140
|
+
- 'units': Physical units (LaTeX formatted)
|
|
141
|
+
- 'long_name': Descriptive name (LaTeX formatted)
|
|
142
|
+
- 'type': Axis type (e.g., 'SPATIAL')
|
|
143
|
+
- 'plot_label': Combined label for plotting
|
|
144
|
+
data : np.ndarray
|
|
145
|
+
Raw field data array (shape depends on simulation dimensions)
|
|
146
|
+
units : str
|
|
147
|
+
Field units (LaTeX formatted)
|
|
148
|
+
label : str
|
|
149
|
+
Field label/name (LaTeX formatted, e.g., r'$E_x$')
|
|
150
|
+
FFTdata : np.ndarray
|
|
151
|
+
Fourier-transformed data (available after calling FFT())
|
|
152
|
+
"""
|
|
153
|
+
|
|
181
154
|
def __init__(self, filename):
|
|
182
155
|
super().__init__(filename)
|
|
183
156
|
|
|
@@ -230,105 +203,6 @@ class OsirisGridFile(OsirisData):
|
|
|
230
203
|
def _get_variable_key(self, f: h5py.File) -> str:
|
|
231
204
|
return next(k for k in f.keys() if k not in {'AXIS', 'SIMULATION'})
|
|
232
205
|
|
|
233
|
-
# Getters
|
|
234
|
-
@property
|
|
235
|
-
def grid(self):
|
|
236
|
-
'''
|
|
237
|
-
Returns
|
|
238
|
-
-------
|
|
239
|
-
numpy.ndarray
|
|
240
|
-
The grid data ((x1.min, x1.max), (x2.min, x2.max), (x3.min, x3.max
|
|
241
|
-
'''
|
|
242
|
-
return self._grid
|
|
243
|
-
@property
|
|
244
|
-
def nx(self):
|
|
245
|
-
'''
|
|
246
|
-
Returns
|
|
247
|
-
-------
|
|
248
|
-
numpy.ndarray
|
|
249
|
-
The number of grid points (nx1, nx2, nx3)
|
|
250
|
-
'''
|
|
251
|
-
return self._nx
|
|
252
|
-
@property
|
|
253
|
-
def dx(self):
|
|
254
|
-
'''
|
|
255
|
-
Returns
|
|
256
|
-
-------
|
|
257
|
-
numpy.ndarray
|
|
258
|
-
The grid spacing (dx1, dx2, dx3)
|
|
259
|
-
'''
|
|
260
|
-
return self._dx
|
|
261
|
-
@property
|
|
262
|
-
def x(self):
|
|
263
|
-
'''
|
|
264
|
-
Returns
|
|
265
|
-
-------
|
|
266
|
-
numpy.ndarray
|
|
267
|
-
The grid points in each axis
|
|
268
|
-
'''
|
|
269
|
-
return self._x
|
|
270
|
-
@property
|
|
271
|
-
def axis(self):
|
|
272
|
-
'''
|
|
273
|
-
Returns
|
|
274
|
-
-------
|
|
275
|
-
list of dictionaries
|
|
276
|
-
The axis data [(name_x1, units_x1, long_name_x1, type_x1), ...]
|
|
277
|
-
'''
|
|
278
|
-
return self._axis
|
|
279
|
-
@property
|
|
280
|
-
def data(self):
|
|
281
|
-
'''
|
|
282
|
-
Returns
|
|
283
|
-
-------
|
|
284
|
-
numpy.ndarray
|
|
285
|
-
The data (numpy array) with shape (nx1, nx2, nx3) (Transpose to use `plt.imshow`)
|
|
286
|
-
'''
|
|
287
|
-
return self._data
|
|
288
|
-
@property
|
|
289
|
-
def units(self):
|
|
290
|
-
'''
|
|
291
|
-
Returns
|
|
292
|
-
-------
|
|
293
|
-
str
|
|
294
|
-
The units of the data (LaTeX formatted)
|
|
295
|
-
'''
|
|
296
|
-
return self._units
|
|
297
|
-
@property
|
|
298
|
-
def label(self):
|
|
299
|
-
'''
|
|
300
|
-
Returns
|
|
301
|
-
-------
|
|
302
|
-
str
|
|
303
|
-
The label of the data (LaTeX formatted)
|
|
304
|
-
'''
|
|
305
|
-
return self._label
|
|
306
|
-
@property
|
|
307
|
-
def FFTdata(self):
|
|
308
|
-
'''
|
|
309
|
-
Returns
|
|
310
|
-
-------
|
|
311
|
-
numpy.ndarray
|
|
312
|
-
The FFT of the data
|
|
313
|
-
'''
|
|
314
|
-
if self._FFTdata is None:
|
|
315
|
-
raise ValueError('The FFT of the data has not been computed yet. Compute it using the FFT method.')
|
|
316
|
-
return self._FFTdata
|
|
317
|
-
# Setters
|
|
318
|
-
@data.setter
|
|
319
|
-
def data(self, data):
|
|
320
|
-
'''
|
|
321
|
-
Set the data attribute
|
|
322
|
-
'''
|
|
323
|
-
self._data = data
|
|
324
|
-
|
|
325
|
-
def __str__(self):
|
|
326
|
-
# write me a template to print with the name, label, units, time, iter, grid, nx, dx, axis, dt, dim in a logical way
|
|
327
|
-
return rf'{self.name}' + f'\n' + rf'Time: [{self.time[0]} {self.time[1]}], dt = {self.dt}' + f'\n' + f'Iteration: {self.iter}' + f'\n' + f'Grid: {self.grid}' + f'\n' + f'dx: {self.dx}' + f'\n' + f'Dimensions: {self.dim}D'
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
def __array__(self):
|
|
331
|
-
return np.asarray(self.data)
|
|
332
206
|
|
|
333
207
|
|
|
334
208
|
def _yeeToCellCorner1d(self, boundary):
|
|
@@ -421,6 +295,48 @@ class OsirisGridFile(OsirisData):
|
|
|
421
295
|
datafft = np.fft.fftn(self.data, axes=axis)
|
|
422
296
|
self._FFTdata = np.fft.fftshift(datafft, axes=axis)
|
|
423
297
|
|
|
298
|
+
# Getters
|
|
299
|
+
@property
|
|
300
|
+
def grid(self):
|
|
301
|
+
return self._grid
|
|
302
|
+
@property
|
|
303
|
+
def nx(self):
|
|
304
|
+
return self._nx
|
|
305
|
+
@property
|
|
306
|
+
def dx(self):
|
|
307
|
+
return self._dx
|
|
308
|
+
@property
|
|
309
|
+
def x(self):
|
|
310
|
+
return self._x
|
|
311
|
+
@property
|
|
312
|
+
def axis(self):
|
|
313
|
+
return self._axis
|
|
314
|
+
@property
|
|
315
|
+
def data(self):
|
|
316
|
+
return self._data
|
|
317
|
+
@property
|
|
318
|
+
def units(self):
|
|
319
|
+
return self._units
|
|
320
|
+
@property
|
|
321
|
+
def label(self):
|
|
322
|
+
return self._label
|
|
323
|
+
@property
|
|
324
|
+
def FFTdata(self):
|
|
325
|
+
if self._FFTdata is None:
|
|
326
|
+
raise ValueError('The FFT of the data has not been computed yet. Compute it using the FFT method.')
|
|
327
|
+
return self._FFTdata
|
|
328
|
+
# Setters
|
|
329
|
+
@data.setter
|
|
330
|
+
def data(self, data):
|
|
331
|
+
self._data = data
|
|
332
|
+
|
|
333
|
+
def __str__(self):
|
|
334
|
+
# write me a template to print with the name, label, units, time, iter, grid, nx, dx, axis, dt, dim in a logical way
|
|
335
|
+
return rf'{self.name}' + f'\n' + rf'Time: [{self.time[0]} {self.time[1]}], dt = {self.dt}' + f'\n' + f'Iteration: {self.iter}' + f'\n' + f'Grid: {self.grid}' + f'\n' + f'dx: {self.dx}' + f'\n' + f'Dimensions: {self.dim}D'
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def __array__(self):
|
|
339
|
+
return np.asarray(self.data)
|
|
424
340
|
|
|
425
341
|
|
|
426
342
|
class OsirisRawFile(OsirisData):
|
|
@@ -475,3 +391,28 @@ class OsirisRawFile(OsirisData):
|
|
|
475
391
|
'long_name': self._file.attrs['LABELS'][idx][0].decode('utf-8'),
|
|
476
392
|
}
|
|
477
393
|
self.axis[key] = axis_data
|
|
394
|
+
|
|
395
|
+
class OsirisHIST(OsirisData):
|
|
396
|
+
''''
|
|
397
|
+
Class to read the data from an OSIRIS HIST file.'
|
|
398
|
+
|
|
399
|
+
Input:
|
|
400
|
+
- filename: the path to the HIST file
|
|
401
|
+
|
|
402
|
+
Attributes:
|
|
403
|
+
- filename - the path to the file
|
|
404
|
+
str
|
|
405
|
+
- verbose - if True, the class will print messages
|
|
406
|
+
bool
|
|
407
|
+
- df - the data in a pandas DataFrame
|
|
408
|
+
pandas.DataFrame
|
|
409
|
+
'''
|
|
410
|
+
def __init__(self, filename):
|
|
411
|
+
super().__init__(filename)
|
|
412
|
+
|
|
413
|
+
@property
|
|
414
|
+
def df(self):
|
|
415
|
+
"""
|
|
416
|
+
Returns the data in a pandas DataFrame
|
|
417
|
+
"""
|
|
418
|
+
return self._df
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The utilities on data.py are cool but not useful when you want to work with whole data of a simulation instead
|
|
3
|
+
of just a single file. This is what this file is for - deal with ''folders'' of data.
|
|
4
|
+
|
|
5
|
+
Took some inspiration from Diogo and Madox's work.
|
|
6
|
+
|
|
7
|
+
This would be awsome to compute time derivatives.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
import os
|
|
12
|
+
from .data import OsirisGridFile, OsirisRawFile, OsirisHIST
|
|
13
|
+
import tqdm
|
|
14
|
+
import itertools
|
|
15
|
+
import multiprocessing as mp
|
|
16
|
+
|
|
17
|
+
class OsirisSimulation:
|
|
18
|
+
def __init__(self, simulation_folder):
|
|
19
|
+
self._simulation_folder = simulation_folder
|
|
20
|
+
if not os.path.isdir(simulation_folder):
|
|
21
|
+
raise FileNotFoundError(f"Simulation folder {simulation_folder} not found.")
|
|
22
|
+
|
|
23
|
+
def get_moment(self, species, moment):
|
|
24
|
+
self._path = f"{self._simulation_folder}/MS/UDIST/{species}/{moment}/"
|
|
25
|
+
self._file_template = os.listdir(self._path)[0][:-9]
|
|
26
|
+
self._load_attributes(self._file_template)
|
|
27
|
+
|
|
28
|
+
def get_field(self, field, centered=False):
|
|
29
|
+
if centered:
|
|
30
|
+
self._path = f"{self._simulation_folder}/MS/FLD/{field}/"
|
|
31
|
+
self._path = f"{self._simulation_folder}/MS/FLD/{field}/"
|
|
32
|
+
self._file_template = os.listdir(self._path)[0][:-9]
|
|
33
|
+
self._load_attributes(self._file_template)
|
|
34
|
+
|
|
35
|
+
def get_density(self, species, quantity):
|
|
36
|
+
self._path = f"{self._simulation_folder}/MS/DENSITY/{species}/{quantity}/"
|
|
37
|
+
self._file_template = os.listdir(self._path)[0][:-9]
|
|
38
|
+
self._load_attributes(self._file_template)
|
|
39
|
+
|
|
40
|
+
def _load_attributes(self, file_template):
|
|
41
|
+
path_file1 = os.path.join(self._path, file_template + "000001.h5")
|
|
42
|
+
dump1 = OsirisGridFile(path_file1)
|
|
43
|
+
self._dx = dump1.dx
|
|
44
|
+
self._nx = dump1.nx
|
|
45
|
+
self._x = dump1.x
|
|
46
|
+
self._dt = dump1.dt
|
|
47
|
+
self._grid = dump1.grid
|
|
48
|
+
self._axis = dump1.axis
|
|
49
|
+
self._units = dump1.units
|
|
50
|
+
self._name = dump1.name
|
|
51
|
+
self._dim = dump1.dim
|
|
52
|
+
self._ndump = dump1.iter
|
|
53
|
+
|
|
54
|
+
def _data_generator(self, index):
|
|
55
|
+
file = os.path.join(self._path, self._file_template + f"{index:06d}.h5")
|
|
56
|
+
data_object = OsirisGridFile(file)
|
|
57
|
+
if self._current_centered:
|
|
58
|
+
data_object.yeeToCellCorner(boundary="periodic")
|
|
59
|
+
yield data_object.data_centered if self._current_centered else data_object.data
|
|
60
|
+
|
|
61
|
+
def load_all(self, centered=False):
|
|
62
|
+
self._current_centered = centered
|
|
63
|
+
size = len(sorted(os.listdir(self._path)))
|
|
64
|
+
self._data = np.stack([self[i] for i in tqdm.tqdm(range(size), desc="Loading data")])
|
|
65
|
+
|
|
66
|
+
def load_all_parallel(self, centered=False, processes=None):
|
|
67
|
+
self._current_centered = centered
|
|
68
|
+
files = sorted(os.listdir(self._path))
|
|
69
|
+
size = len(files)
|
|
70
|
+
|
|
71
|
+
if processes is None:
|
|
72
|
+
processes = mp.cpu_count()
|
|
73
|
+
print(f"Using {processes} CPUs for parallel loading")
|
|
74
|
+
|
|
75
|
+
with mp.Pool(processes=processes) as pool:
|
|
76
|
+
data = list(tqdm.tqdm(pool.imap(self.__getitem__, range(size)), total=size, desc="Loading data"))
|
|
77
|
+
|
|
78
|
+
self._data = np.stack(data)
|
|
79
|
+
|
|
80
|
+
def load(self, index, centered=False):
|
|
81
|
+
self._current_centered = centered
|
|
82
|
+
self._data = next(self._data_generator(index))
|
|
83
|
+
|
|
84
|
+
def __getitem__(self, index):
|
|
85
|
+
return next(self._data_generator(index))
|
|
86
|
+
|
|
87
|
+
def __iter__(self):
|
|
88
|
+
for i in itertools.count():
|
|
89
|
+
yield next(self._data_generator(i))
|
|
90
|
+
|
|
91
|
+
def derivative(self, point, type, axis=None):
|
|
92
|
+
if point == "all":
|
|
93
|
+
if type == "t":
|
|
94
|
+
self._deriv_t = np.gradient(self.data, self.dt, axis=0, edge_order=2)
|
|
95
|
+
elif type == "x1":
|
|
96
|
+
if self._dim == 1:
|
|
97
|
+
self._deriv_x1 = np.gradient(self.data, self.dx, axis=1, edge_order=2)
|
|
98
|
+
else:
|
|
99
|
+
self._deriv_x1 = np.gradient(self.data, self.dx[0], axis=1, edge_order=2)
|
|
100
|
+
elif type == "x2":
|
|
101
|
+
self._deriv_x1 = np.gradient(self.data, self.dx[0], axis=2, edge_order=2)
|
|
102
|
+
elif type == "x3":
|
|
103
|
+
self._deriv_x2 = np.gradient(self.data, self.dx[0], axis=3, edge_order=2)
|
|
104
|
+
elif type == "xx":
|
|
105
|
+
if len(axis) != 2:
|
|
106
|
+
raise ValueError("Axis must be a tuple with two elements.")
|
|
107
|
+
self._deriv_xx = np.gradient(np.gradient(self.data, self.dx[axis[0]], axis=axis[0], edge_order=2), self.dx[axis[1]], axis=axis[1], edge_order=2)
|
|
108
|
+
elif type == "xt":
|
|
109
|
+
if not isinstance(axis, int):
|
|
110
|
+
raise ValueError("Axis must be an integer.")
|
|
111
|
+
self._deriv_xt = np.gradient(np.gradient(self.data, self.dt, axis=0, edge_order=2), self.dx[axis], axis=axis, edge_order=2)
|
|
112
|
+
elif type == "tx":
|
|
113
|
+
if not isinstance(axis, int):
|
|
114
|
+
raise ValueError("Axis must be an integer.")
|
|
115
|
+
self._deriv_tx = np.gradient(np.gradient(self.data, self.dx[axis], axis=axis, edge_order=2), self.dt, axis=axis, edge_order=2)
|
|
116
|
+
else:
|
|
117
|
+
raise ValueError("Invalid type.")
|
|
118
|
+
else:
|
|
119
|
+
try:
|
|
120
|
+
if type == "x1":
|
|
121
|
+
if self._dim == 1:
|
|
122
|
+
return np.gradient(self[point], self._dx, axis=0)
|
|
123
|
+
else:
|
|
124
|
+
return np.gradient(self[point], self._dx[0], axis=0)
|
|
125
|
+
|
|
126
|
+
elif type == "x2":
|
|
127
|
+
return np.gradient(self[point], self._dx[1], axis=1)
|
|
128
|
+
|
|
129
|
+
elif type == "x3":
|
|
130
|
+
return np.gradient(self[point], self._dx[2], axis=2)
|
|
131
|
+
|
|
132
|
+
elif type == "t":
|
|
133
|
+
if point == 0:
|
|
134
|
+
return (-3 * self[point] + 4 * self[point + 1] - self[point + 2]) / (2 * self._dt)
|
|
135
|
+
# derivate at last point not implemented yet
|
|
136
|
+
# elif self[point + 1] is None:
|
|
137
|
+
# return (3 * self[point] - 4 * self[point - 1] + self[point - 2]) / (2 * self._dt)
|
|
138
|
+
else:
|
|
139
|
+
return (self[point + 1] - self[point - 1]) / (2 * self._dt)
|
|
140
|
+
else:
|
|
141
|
+
raise ValueError("Invalid derivative type. Use 'x1', 'x2' or 't'.")
|
|
142
|
+
|
|
143
|
+
except Exception as e:
|
|
144
|
+
raise ValueError(f"Error computing derivative at point {point}: {str(e)}")
|
|
145
|
+
|
|
146
|
+
# Getters
|
|
147
|
+
@property
|
|
148
|
+
def data(self):
|
|
149
|
+
if self._data is None:
|
|
150
|
+
raise ValueError("Data not loaded into memory. Use get_* method with load_all=True or access via generator/index.")
|
|
151
|
+
return self._data
|
|
152
|
+
|
|
153
|
+
@property
|
|
154
|
+
def time(self):
|
|
155
|
+
return self._time
|
|
156
|
+
|
|
157
|
+
@property
|
|
158
|
+
def dx(self):
|
|
159
|
+
return self._dx
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
def nx(self):
|
|
163
|
+
return self._nx
|
|
164
|
+
|
|
165
|
+
@property
|
|
166
|
+
def x(self):
|
|
167
|
+
return self._x
|
|
168
|
+
|
|
169
|
+
@property
|
|
170
|
+
def dt(self):
|
|
171
|
+
return self._dt
|
|
172
|
+
|
|
173
|
+
@property
|
|
174
|
+
def grid(self):
|
|
175
|
+
return self._grid
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def axis(self):
|
|
179
|
+
return self._axis
|
|
180
|
+
|
|
181
|
+
@property
|
|
182
|
+
def units(self):
|
|
183
|
+
return self._units
|
|
184
|
+
|
|
185
|
+
@property
|
|
186
|
+
def name(self):
|
|
187
|
+
return self._name
|
|
188
|
+
|
|
189
|
+
@property
|
|
190
|
+
def dim(self):
|
|
191
|
+
return self._dim
|
|
192
|
+
|
|
193
|
+
@property
|
|
194
|
+
def path(self):
|
|
195
|
+
return self
|
|
196
|
+
|
|
197
|
+
@property
|
|
198
|
+
def simulation_folder(self):
|
|
199
|
+
return self._simulation_folder
|
|
200
|
+
|
|
201
|
+
@property
|
|
202
|
+
def ndump(self):
|
|
203
|
+
return self._ndump
|
|
204
|
+
|
|
205
|
+
@property
|
|
206
|
+
def deriv_t(self):
|
|
207
|
+
return self._deriv_t
|
|
208
|
+
|
|
209
|
+
@property
|
|
210
|
+
def deriv_x1(self):
|
|
211
|
+
return self._deriv_x1
|
|
212
|
+
|
|
213
|
+
@property
|
|
214
|
+
def deriv_x2(self):
|
|
215
|
+
return self._deriv_x2
|
|
216
|
+
|
|
217
|
+
@property
|
|
218
|
+
def deriv_xx(self):
|
|
219
|
+
return self._deriv_xx
|
|
220
|
+
|
|
221
|
+
@property
|
|
222
|
+
def deriv_xt(self):
|
|
223
|
+
return self._deriv_xt
|
|
224
|
+
|
|
225
|
+
@property
|
|
226
|
+
def deriv_tx(self):
|
|
227
|
+
return self._deriv_tx
|
|
228
|
+
|
|
229
|
+
|
osiris_utils/utils.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: osiris_utils
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.1
|
|
4
4
|
Summary: Utilities to manipulate and visualize OSIRIS framework output data
|
|
5
5
|
Author: ['João Pedro Ferreira Biu', 'João Cândido']
|
|
6
6
|
Author-email: ['joaopedrofbiu@tecnico.ulisboa.pt']
|
|
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
21
|
Classifier: Topic :: Scientific/Engineering
|
|
22
22
|
Requires-Python: >=3.11
|
|
23
|
-
Description-Content-Type: text/
|
|
23
|
+
Description-Content-Type: text/x-rst
|
|
24
24
|
License-File: LICENSE.txt
|
|
25
25
|
Requires-Dist: numpy
|
|
26
26
|
Requires-Dist: matplotlib
|
|
@@ -33,6 +33,7 @@ Requires-Dist: tqdm
|
|
|
33
33
|
Dynamic: author
|
|
34
34
|
Dynamic: author-email
|
|
35
35
|
Dynamic: classifier
|
|
36
|
+
Dynamic: description
|
|
36
37
|
Dynamic: description-content-type
|
|
37
38
|
Dynamic: keywords
|
|
38
39
|
Dynamic: license
|
|
@@ -40,3 +41,30 @@ Dynamic: project-url
|
|
|
40
41
|
Dynamic: requires-dist
|
|
41
42
|
Dynamic: requires-python
|
|
42
43
|
Dynamic: summary
|
|
44
|
+
|
|
45
|
+
OSIRIS_UTILS
|
|
46
|
+
============
|
|
47
|
+
|Pypi|
|
|
48
|
+
|
|
49
|
+
This package contains a set of utilities to open and analyze OSIRIS output files, using Python. All the methods implemented are fully integrated with `NumPy`, and use `np.ndarray` as the main data structure.
|
|
50
|
+
|
|
51
|
+
How to install it?
|
|
52
|
+
------------------
|
|
53
|
+
|
|
54
|
+
To install this package, you can use `pip`::
|
|
55
|
+
|
|
56
|
+
pip install osiris_utils
|
|
57
|
+
|
|
58
|
+
To install it from source, you can clone this repository and run (in the folder containing ``setup.py``)::
|
|
59
|
+
|
|
60
|
+
pip install -e .
|
|
61
|
+
|
|
62
|
+
Documentation
|
|
63
|
+
-------------
|
|
64
|
+
|
|
65
|
+
The documentation is available at https://osiris-utils.readthedocs.io or via this link: `osiris-utils.readthedocs.io <https://osiris-utils.readthedocs.io>`_.
|
|
66
|
+
|
|
67
|
+
.. |Pypi| image:: https://img.shields.io/pypi/v/osiris-utils
|
|
68
|
+
:target: https://pypi.org/project/osiris-utils/
|
|
69
|
+
:alt: Pypi
|
|
70
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
osiris_utils/__init__.py,sha256=mxnns9jfhmfy7QoezULfXxetK14Lol1ykZAWYcAdD54,349
|
|
2
|
+
osiris_utils/data.py,sha256=eoUrnxwQvN1kYwuUlIUZqrCr-8gTriOy1YtxBim5bI0,15933
|
|
3
|
+
osiris_utils/gui.py,sha256=YyG4MBmUFDJ141-NeorVRnRU3fcym4cfDMSGsJUFbYA,10531
|
|
4
|
+
osiris_utils/mean_field_theory.py,sha256=sJGvoJ5fTgW6fQZjNNsPswzXkh7dhMgO96qB8R5tl0M,1517
|
|
5
|
+
osiris_utils/simulation_data.py,sha256=Zxx8d68jps5eP7Uc4v48Jr8qnRx7UbqjzPTIsJI5BxU,7980
|
|
6
|
+
osiris_utils/utils.py,sha256=pj2hrmZla-6T_95eRZB_c4TSXJqBvNRvMTzuw1lPZyA,4708
|
|
7
|
+
osiris_utils-1.1.1.dist-info/LICENSE.txt,sha256=Cawy2v7wKc7n8yL8guFu-cH9sQw9r1gll1pEFPFAB-Q,1084
|
|
8
|
+
osiris_utils-1.1.1.dist-info/METADATA,sha256=KzxRqhEbdff8SRZUh22fOAnwpMVu3oZ3ATVLOsearN4,2287
|
|
9
|
+
osiris_utils-1.1.1.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
|
10
|
+
osiris_utils-1.1.1.dist-info/top_level.txt,sha256=mM-_dX5fjzIKB7te655PhZOrPACVY-bJmiASCqW1eOA,13
|
|
11
|
+
osiris_utils-1.1.1.dist-info/RECORD,,
|
osiris_utils/data_readers.py
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
This file contains methods to create datasets to train the neural network.
|
|
3
|
-
'''
|
|
4
|
-
|
|
5
|
-
import numpy as np
|
|
6
|
-
from .utils import *
|
|
7
|
-
import os
|
|
8
|
-
import h5py
|
|
9
|
-
|
|
10
|
-
def read_osiris_file(filename, pressure = False):
|
|
11
|
-
f = h5py.File(filename, 'r+')
|
|
12
|
-
atr = f.attrs
|
|
13
|
-
k = [key for key in f.keys()]
|
|
14
|
-
if 'SIMULATION' in k:
|
|
15
|
-
attrs1 = atr
|
|
16
|
-
attrs2 = f['SIMULATION'].attrs
|
|
17
|
-
attrs = {}
|
|
18
|
-
for i in range(len(attrs1)):
|
|
19
|
-
attrs[[key for key in attrs1][i]] = [value for value in attrs1.values()][i]
|
|
20
|
-
for i in range(len(attrs2)):
|
|
21
|
-
attrs[[key for key in attrs2][i]] = [value for value in attrs2.values()][i]
|
|
22
|
-
ax = f.get([key for key in f.keys()][0])
|
|
23
|
-
leanx = len(ax)
|
|
24
|
-
axis = []
|
|
25
|
-
for i in range(leanx):
|
|
26
|
-
axis.append(ax.get([key for key in ax.keys()][i]))
|
|
27
|
-
if 'SIMULATION' in k and pressure == False:
|
|
28
|
-
data = f.get([key for key in f.keys()][2])
|
|
29
|
-
data.attrs['UNITS'] = attrs1['UNITS']
|
|
30
|
-
data.attrs['LONG_NAME'] = attrs1['LABEL']
|
|
31
|
-
elif 'SIMULATION' in k and pressure == True:
|
|
32
|
-
data = f.get([key for key in f.keys()][1])
|
|
33
|
-
data.attrs['UNITS'] = attrs1['UNITS']
|
|
34
|
-
data.attrs['LONG_NAME'] = attrs1['LABEL']
|
|
35
|
-
else:
|
|
36
|
-
data = f.get([key for key in f.keys()][1])
|
|
37
|
-
|
|
38
|
-
return attrs, axis, data
|
|
39
|
-
|
|
40
|
-
def open1D(filename, pressure = False):
|
|
41
|
-
'''
|
|
42
|
-
Open a 1D OSIRIS file and return the x axis and the data array.
|
|
43
|
-
|
|
44
|
-
Parameters
|
|
45
|
-
----------
|
|
46
|
-
filename : str
|
|
47
|
-
The path to the file.
|
|
48
|
-
|
|
49
|
-
Returns
|
|
50
|
-
-------
|
|
51
|
-
x : numpy.ndarray
|
|
52
|
-
The x axis.
|
|
53
|
-
data_array : numpy.ndarray
|
|
54
|
-
The data array.
|
|
55
|
-
'''
|
|
56
|
-
attrs, axes, data = read_osiris_file(filename, pressure)
|
|
57
|
-
datash = data.shape
|
|
58
|
-
ax1 = axes[0]
|
|
59
|
-
x = np.linspace(ax1[0], ax1[1], datash[0])
|
|
60
|
-
data_array = data[:]
|
|
61
|
-
return x, data_array, [attrs, axes, data]
|
|
62
|
-
|
|
63
|
-
def open2D(filename, pressure = False):
|
|
64
|
-
'''
|
|
65
|
-
Open a 2D OSIRIS file and return the x and y axes and the data array.
|
|
66
|
-
|
|
67
|
-
Parameters
|
|
68
|
-
----------
|
|
69
|
-
filename : str
|
|
70
|
-
The path to the file.
|
|
71
|
-
|
|
72
|
-
Returns
|
|
73
|
-
-------
|
|
74
|
-
x : numpy.ndarray
|
|
75
|
-
The x axis.
|
|
76
|
-
y : numpy.ndarray
|
|
77
|
-
The y axis.
|
|
78
|
-
data_array : numpy.ndarray
|
|
79
|
-
The data array.
|
|
80
|
-
'''
|
|
81
|
-
attrs, axes, data = read_osiris_file(filename, pressure)
|
|
82
|
-
datash = data.shape
|
|
83
|
-
ax1 = axes[0]
|
|
84
|
-
ax2 = axes[1]
|
|
85
|
-
x = np.linspace(ax1[0], ax1[1], datash[-1])
|
|
86
|
-
y = np.linspace(ax2[0], ax2[1], datash[-2])
|
|
87
|
-
data_array = data[:]
|
|
88
|
-
return x, y, data_array, [attrs, axes, data]
|
|
89
|
-
|
|
90
|
-
def open3D(filename):
|
|
91
|
-
'''
|
|
92
|
-
Open a 3D OSIRIS file and return the x, y and z axes and the data array.
|
|
93
|
-
|
|
94
|
-
Parameters
|
|
95
|
-
----------
|
|
96
|
-
filename : str
|
|
97
|
-
The path to the file.
|
|
98
|
-
|
|
99
|
-
Returns
|
|
100
|
-
-------
|
|
101
|
-
x : numpy.ndarray
|
|
102
|
-
The x axis.
|
|
103
|
-
y : numpy.ndarray
|
|
104
|
-
The y axis.
|
|
105
|
-
z : numpy.ndarray
|
|
106
|
-
The z axis.
|
|
107
|
-
data_array : numpy.ndarray
|
|
108
|
-
The data array.
|
|
109
|
-
'''
|
|
110
|
-
attrs, axes, data = read_osiris_file(filename)
|
|
111
|
-
datash = data.shape
|
|
112
|
-
ax1 = axes[0]
|
|
113
|
-
ax2 = axes[1]
|
|
114
|
-
ax3 = axes[2]
|
|
115
|
-
x = np.linspace(ax1[0], ax1[1], datash[-1])
|
|
116
|
-
y = np.linspace(ax2[0], ax2[1], datash[-2])
|
|
117
|
-
z = np.linspace(ax3[0], ax3[1], datash[-3])
|
|
118
|
-
data_array = data[:]
|
|
119
|
-
return x, y, z, data_array, [attrs, axes, data]
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
osiris_utils/__init__.py,sha256=5qsicKjKzheUmdI89cIw7Egvjv6OZcGAQ5eEAiGZIcY,358
|
|
2
|
-
osiris_utils/data.py,sha256=vj5WV7SubCqR3Ia3ylFuwR5hyotk31d1xZLfYyjC5ow,16491
|
|
3
|
-
osiris_utils/data_readers.py,sha256=ZbzYQ-MK5NSv4Hfgtdc1YqXHs9yL_ZEKFFCiRn7GN5o,3264
|
|
4
|
-
osiris_utils/gui.py,sha256=YyG4MBmUFDJ141-NeorVRnRU3fcym4cfDMSGsJUFbYA,10531
|
|
5
|
-
osiris_utils/mean_field_theory.py,sha256=sJGvoJ5fTgW6fQZjNNsPswzXkh7dhMgO96qB8R5tl0M,1517
|
|
6
|
-
osiris_utils/utils.py,sha256=dlW2BvYpVSsW48kA_A6NNQ77VvKfyvs8hVwnOfJu2qk,4736
|
|
7
|
-
osiris_utils-1.0.9.dist-info/LICENSE.txt,sha256=Cawy2v7wKc7n8yL8guFu-cH9sQw9r1gll1pEFPFAB-Q,1084
|
|
8
|
-
osiris_utils-1.0.9.dist-info/METADATA,sha256=YqRPvxzvsA5TlTHP0p961tkaDrUbP7n9hqh-jJJ7_5E,1463
|
|
9
|
-
osiris_utils-1.0.9.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
|
10
|
-
osiris_utils-1.0.9.dist-info/top_level.txt,sha256=mM-_dX5fjzIKB7te655PhZOrPACVY-bJmiASCqW1eOA,13
|
|
11
|
-
osiris_utils-1.0.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|