osiris-utils 1.0.5__py3-none-any.whl → 1.0.9__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 CHANGED
@@ -1,5 +1,6 @@
1
1
  from .utils import (time_estimation, filesize_estimation, transverse_average, integrate, animate_2D,
2
- save_data, read_data, mft_decomposition, courant2D)
2
+ save_data, read_data, courant2D)
3
3
  from .data_readers import open1D, open2D, open3D, read_osiris_file
4
4
  from .gui import LAVA_Qt, LAVA
5
- from .data import OsirisGridFile, OsirisRawFile
5
+ from .data import OsirisGridFile, OsirisRawFile, OsirisData
6
+ from .mean_field_theory import MeanFieldTheory
osiris_utils/data.py CHANGED
@@ -1,158 +1,477 @@
1
1
  import numpy as np
2
2
  import h5py
3
3
 
4
- class OsirisGridFile():
4
+ class OsirisData():
5
+ '''
6
+ Parent class for Osiris data files.
7
+
8
+ Input:
9
+ ------
10
+ - filename: the path to the HDF5 file
11
+ Attributes:
12
+ ----------
13
+ - filename - the path to the HDF5 file
14
+ str
15
+ - file - the HDF5 file
16
+ h5py.File
17
+ - verbose - if True, the class will print messages
18
+ bool
19
+ - dt - the time step
20
+ float
21
+ - dim - the number of dimensions
22
+ int
23
+ - time - the time and its units
24
+ list [time, units]
25
+ list [float, str]
26
+ - iter - the iteration number
27
+ int
28
+ - name - the name of the data
29
+ str
30
+ - type - the type of data
31
+ str
32
+ '''
33
+ def __init__(self, filename):
34
+ self._filename = filename
35
+ self._file = None
36
+
37
+ self._verbose = False
38
+
39
+ self._open_file(self._filename)
40
+ self._load_basic_attributes(self._file)
41
+
42
+ def _load_basic_attributes(self, f: h5py.File) -> None:
43
+ '''Load common attributes from HDF5 file'''
44
+ self._dt = float(f['SIMULATION'].attrs['DT'][0])
45
+ self._dim = int(f['SIMULATION'].attrs['NDIMS'][0])
46
+ self._time = [float(f.attrs['TIME'][0]), f.attrs['TIME UNITS'][0].decode('utf-8')]
47
+ self._iter = int(f.attrs['ITER'][0])
48
+ self._name = f.attrs['NAME'][0].decode('utf-8')
49
+ self._type = f.attrs['TYPE'][0].decode('utf-8')
50
+
51
+ def verbose(self, verbose: bool = True):
52
+ '''
53
+ Set the verbosity of the class
54
+
55
+ Parameters
56
+ ----------
57
+ verbose : bool, optional
58
+ If True, the class will print messages, by default True when calling (False when not calling)
59
+ '''
60
+ self._verbose = verbose
61
+
62
+ def _open_file(self, filename):
63
+ '''
64
+ Open the HDF5 file.
65
+
66
+ Parameters
67
+ ----------
68
+ filename : str
69
+ The path to the HDF5 file.
70
+ '''
71
+ if self._verbose: print(f'Opening file > {filename}')
72
+ self._file = h5py.File(self._filename, 'r')
73
+
74
+ def _close_file(self):
75
+ '''
76
+ Close the HDF5 file.
77
+ '''
78
+ if self._verbose: print('Closing file')
79
+ if self._file:
80
+ self._file.close()
81
+
82
+ @property
83
+ def dt(self):
84
+ '''
85
+ Returns
86
+ -------
87
+ float
88
+ The time step
89
+ '''
90
+ return self._dt
91
+ @property
92
+ def dim(self):
93
+ '''
94
+ Returns
95
+ -------
96
+ int
97
+ The number of dimensions
98
+ '''
99
+ return self._dim
100
+ @property
101
+ def time(self):
102
+ '''
103
+ Returns
104
+ -------
105
+ list
106
+ The time and its units
107
+ '''
108
+ return self._time
109
+ @property
110
+ def iter(self):
111
+ '''
112
+ Returns
113
+ -------
114
+ int
115
+ The iteration number
116
+ '''
117
+ return self._iter
118
+ @property
119
+ def name(self):
120
+ '''
121
+ Returns
122
+ -------
123
+ str
124
+ The name of the data
125
+ '''
126
+ return self._name
127
+ @property
128
+ def type(self):
129
+ '''
130
+ Returns
131
+ -------
132
+ str
133
+ The type of data
134
+ '''
135
+ return self._type
136
+
137
+ class OsirisGridFile(OsirisData):
5
138
  '''
6
139
  Class to read the grid data from an OSIRIS HDF5 file.
7
140
 
8
141
  Input:
142
+ -----
9
143
  - filename: the path to the HDF5 file
10
144
 
11
145
  Attributes:
12
- - grid: the grid data ((x1.min, x1.max), (x2.min, x2.max), (x3.min, x3.max))
13
- numpy.ndarray
14
- - nx: the number of grid points (nx1, nx2, nx3)
15
- numpy.ndarray
16
- - dx: the grid spacing (dx1, dx2, dx3)
17
- numpy.ndarray
18
- - axis: the axis data [(name_x1, units_x1, long_name_x1, type_x1), ...]
19
- list of dictionaries
20
- - data: the data (numpy array) with shape (nx1, nx2, nx3) (Transpose to use `plt.imshow`)
21
- numpy.ndarray
22
- - dt: the time step
146
+ ----------
147
+ - filename - the path to the HDF5 file
148
+ str
149
+ - file - the HDF5 file
150
+ h5py.File
151
+ - verbose - if True, the class will print messages
152
+ bool
153
+ - dt - the time step
23
154
  float
24
- - dim: the number of dimensions
155
+ - dim - the number of dimensions
25
156
  int
26
- - time: the time and its units
157
+ - time - the time and its units
27
158
  list [time, units]
28
159
  list [float, str]
29
- - iter: the iteration number
160
+ - iter - the iteration number
30
161
  int
31
- - name: the name of the data
162
+ - name - the name of the data
163
+ str
164
+ - type - the type of data
32
165
  str
33
- - units: the units of the data
166
+ - grid - the grid data ((x1.min, x1.max), (x2.min, x2.max), (x3.min, x3.max))
167
+ numpy.ndarray
168
+ - nx - the number of grid points (nx1, nx2, nx3)
169
+ numpy.ndarray
170
+ - dx - the grid spacing (dx1, dx2, dx3)
171
+ numpy.ndarray
172
+ - axis - the axis data [(name_x1, units_x1, long_name_x1, type_x1), ...]
173
+ list of dictionaries
174
+ - data: the data (numpy array) with shape (nx1, nx2, nx3) (Transpose to use `plt.imshow`)
175
+ numpy.ndarray
176
+ - units - the units of the data
34
177
  str
35
- - label: the label of the data (LaTeX formatted)
178
+ - label - the label of the data (LaTeX formatted)
36
179
 
37
- Example:
38
- example = utils.OsirisGridFile("grid/file/osiris/output-000000.h5")
39
- plt.imshow(example.data.T, aspect='auto', origin='lower', extent=[example.grid[0][0], example.grid[0][-1], example.grid[1][0], example.grid[1][-1]])
40
- plt.xlabel(rf"${example.axis[0]["long_name"]}$ [${example.axis[0]["units"]}$]")
41
- plt.ylabel(rf"${example.axis[1]["long_name"]}$ [${example.axis[1]["units"]}$]")
42
- plt.title(rf"${example.label}$, t={example.time[0]} ${example.time[1]}$")
43
180
  '''
44
181
  def __init__(self, filename):
45
- with h5py.File(filename, 'r+') as f:
46
- # Get the data
47
- known_keys = {"AXIS", "SIMULATION"}
48
- all_keys = set(f.keys())
49
- variable_key = (all_keys - known_keys).pop()
182
+ super().__init__(filename)
183
+
184
+ variable_key = self._get_variable_key(self._file)
185
+
186
+ self._units = self._file.attrs['UNITS'][0].decode('utf-8')
187
+ self._label = self._file.attrs['LABEL'][0].decode('utf-8')
188
+ self._FFTdata = None
189
+
190
+ data = np.array(self._file[variable_key][:])
191
+
192
+ axis = list(self._file['AXIS'].keys())
193
+ if len(axis) == 1:
194
+ self._grid = self._file['AXIS/' + axis[0]][()]
195
+ self._nx = len(data)
196
+ self._dx = (self.grid[1] - self.grid[0] ) / self.nx
197
+ self._x = np.arange(self.grid[0], self.grid[1], self.dx)
198
+ else:
199
+ grid = []
200
+ for ax in axis: grid.append(self._file['AXIS/' + ax][()])
201
+ self._grid = np.array(grid)
202
+ self._nx = self._file[variable_key][()].transpose().shape
203
+ self._dx = (self.grid[:, 1] - self.grid[:, 0])/self.nx
204
+ self._x = [np.arange(self.grid[i, 0], self.grid[i, 1], self.dx[i]) for i in range(self.dim)]
205
+
206
+ self._axis = []
207
+ for ax in axis:
208
+ axis_data = {
209
+ 'name': self._file['AXIS/'+ax].attrs['NAME'][0].decode('utf-8'),
210
+ 'units': self._file['AXIS/'+ax].attrs['UNITS'][0].decode('utf-8'),
211
+ 'long_name': self._file['AXIS/'+ax].attrs['LONG_NAME'][0].decode('utf-8'),
212
+ 'type': self._file['AXIS/'+ax].attrs['TYPE'][0].decode('utf-8'),
213
+ 'plot_label': rf'${self._file["AXIS/"+ax].attrs["LONG_NAME"][0].decode("utf-8")}$ $[{self._file["AXIS/"+ax].attrs["UNITS"][0].decode("utf-8")}]$',
214
+ }
215
+ self._axis.append(axis_data)
216
+
217
+ self._data = np.ascontiguousarray(data.T)
218
+
219
+ self._close_file()
220
+
221
+ def _load_basic_attributes(self, f: h5py.File) -> None:
222
+ '''Load common attributes from HDF5 file'''
223
+ self._dt = float(f['SIMULATION'].attrs['DT'][0])
224
+ self._dim = int(f['SIMULATION'].attrs['NDIMS'][0])
225
+ self._time = [float(f.attrs['TIME'][0]), f.attrs['TIME UNITS'][0].decode('utf-8')]
226
+ self._iter = int(f.attrs['ITER'][0])
227
+ self._name = f.attrs['NAME'][0].decode('utf-8')
228
+ self._type = f.attrs['TYPE'][0].decode('utf-8')
50
229
 
51
- # The data
52
- self.data = np.array(f[variable_key][:])
53
-
54
- keys = list(f.keys())
55
- # Now get the infos
56
- axis = list(f["AXIS"].keys())
57
- if len(axis) == 1:
58
- self.grid = f["AXIS/"+axis[0]][()]
59
- self.nx = len(self.data)
60
- self.dx = (self.grid[1] - self.grid[0] ) / self.nx
61
- else:
62
- grid = []
63
- for ax in axis: grid.append(f["AXIS/"+ax][()])
64
- self.grid = np.array(grid)
65
-
66
- self.nx = f[variable_key][()].transpose().shape
67
- self.dx = (self.grid[:, 1] - self.grid[:, 0])/self.nx
68
- self.axis = []
69
- for ax in axis:
70
- axis_data = {
71
- "name": f["AXIS/"+ax].attrs["NAME"][0].decode('utf-8'),
72
- "units": f["AXIS/"+ax].attrs["UNITS"][0].decode('utf-8'),
73
- "long_name": f["AXIS/"+ax].attrs["LONG_NAME"][0].decode('utf-8'),
74
- "type": f["AXIS/"+ax].attrs["TYPE"][0].decode('utf-8'),
75
- }
76
- self.axis.append(axis_data)
77
-
78
- # NOW WORK ON THE SIMULATION DATA
79
- self.dt = float(f["SIMULATION"].attrs["DT"][0])
80
- self.dims_simulation = int(f["SIMULATION"].attrs["NDIMS"][0])
81
- self.time = [float(f.attrs["TIME"][0]), f.attrs["TIME UNITS"][0].decode('utf-8')]
82
- self.iter = int(f.attrs["ITER"][0])
83
- self.name = f.attrs["NAME"][0].decode('utf-8')
84
- self.units = f.attrs["UNITS"][0].decode('utf-8')
85
- self.label = f.attrs["LABEL"][0].decode('utf-8')
86
- self.type = f.attrs["TYPE"][0].decode('utf-8')
87
- self.data = self.data.T
88
-
89
-
90
- class OsirisRawFile():
230
+ def _get_variable_key(self, f: h5py.File) -> str:
231
+ return next(k for k in f.keys() if k not in {'AXIS', 'SIMULATION'})
232
+
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
+
333
+
334
+ def _yeeToCellCorner1d(self, boundary):
335
+ '''
336
+ Converts 1d EM fields from a staggered Yee mesh to a grid with field values centered on the corner of the cell (the corner of the cell [1] has coordinates [1])
337
+ '''
338
+
339
+ if self.name.lower() in ['b2', 'b3', 'e1']:
340
+ if boundary == 'periodic': return 0.5 * (np.roll(self.data, shift=1) + self.data)
341
+ else: return 0.5 * (self.data[1:] + self.data[:-1])
342
+ elif self.name.lower() in ['b1', 'e2', 'e3']:
343
+ if boundary == 'periodic': return self.data
344
+ else: return self.data[1:]
345
+ else:
346
+ raise TypeError(f'This method expects magnetic or electric field grid data but received \'{self.name}\' instead')
347
+
348
+
349
+ def _yeeToCellCorner2d(self, boundary):
350
+ '''
351
+ Converts 2d EM fields from a staggered Yee mesh to a grid with field values centered on the corner of the cell (the corner of the cell [1,1] has coordinates [1,1])
352
+ '''
353
+
354
+ if self.name.lower() in ['e1', 'b2']:
355
+ if boundary == 'periodic': return 0.5 * (np.roll(self.data, shift=1, axis=0) + self.data)
356
+ else: return 0.5 * (self.data[1:, 1:] + self.data[:-1, 1:])
357
+ elif self.name.lower() in ['e2', 'b1']:
358
+ if boundary == 'periodic': return 0.5 * (np.roll(self.data, shift=1, axis=1) + self.data)
359
+ else: return 0.5 * (self.data[1:, 1:] + self.data[1:, :-1])
360
+ elif self.name.lower() in ['b3']:
361
+ if boundary == 'periodic':
362
+ return 0.5 * (np.roll((0.5 * (np.roll(self.data, shift=1, axis=0) + self.data)), shift=1, axis=1) + (0.5 * (np.roll(self.data, shift=1, axis=0) + self.data)))
363
+ else:
364
+ return 0.25 * (self.data[1:, 1:] + self.data[:-1, 1:] + self.data[1:, :-1] + self.data[:-1, :-1])
365
+ elif self.name.lower() in ['e3']:
366
+ if boundary == 'periodic': return self.data
367
+ else: return self.data[1:, 1:]
368
+ else:
369
+ raise TypeError(f'This method expects magnetic or electric field grid data but received \'{self.name}\' instead')
370
+
371
+
372
+ def _yeeToCellCorner3d(self, boundary):
373
+ '''
374
+ Converts 3d EM fields from a staggered Yee mesh to a grid with field values centered on the corner of the cell (the corner of the cell [1,1,1] has coordinates [1,1,1])
375
+ '''
376
+ if boundary == 'periodic':
377
+ raise ValueError('Centering field from 3D simulations considering periodic boundary conditions is not implemented yet')
378
+ if self.name.lower() == 'b1':
379
+ return 0.25 * (self.data[1:, 1:, 1:] + self.data[1:, :-1, 1:] + self.data[1:, 1:, :-1] + self.data[1:, :-1, :-1])
380
+ elif self.name.lower() == 'b2':
381
+ return 0.25 * (self.data[1:, 1:, 1:] + self.data[:-1, 1:, 1:] + self.data[1:, 1:, :-1] + self.data[:-1, 1:, :-1])
382
+ elif self.name.lower() == 'b3':
383
+ return 0.25 * (self.data[1:, 1:, 1:] + self.data[:-1, 1:, 1:] + self.data[1:, :-1, 1:] + self.data[:-1, :-1, 1:])
384
+ elif self.name.lower() == 'e1':
385
+ return 0.5 * (self.data[1:, 1:, 1:] + self.data[:-1, 1:, 1:])
386
+ elif self.name.lower() == 'e2':
387
+ return 0.5 * (self.data[1:, 1:, 1:] + self.data[1:, :-1, 1:])
388
+ elif self.name.lower() == 'e3':
389
+ return 0.5 * (self.data[1:, 1:, 1:] + self.data[1:, 1:, :-1])
390
+ else:
391
+ raise TypeError(f'This method expects magnetic or electric field grid data but received \'{self.name}\' instead')
392
+
393
+ def yeeToCellCorner(self, boundary=None):
394
+ ''''
395
+ Converts EM fields from a staggered Yee mesh to a grid with field values centered on the corner of the cell.'
396
+ Can be used for 1D, 2D and 3D simulations.'
397
+ Creates a new attribute `data_centered` with the centered data.'
398
+ '''
399
+
400
+ cases = {'b1', 'b2', 'b3', 'e1', 'e2', 'e3'}
401
+ if self.name not in cases:
402
+ raise TypeError(f'This method expects magnetic or electric field grid data but received \'{self.name}\' instead')
403
+
404
+ if self.dim == 1:
405
+ self.data_centered = self._yeeToCellCorner1d(boundary)
406
+ return self.data_centered
407
+ elif self.dim == 2:
408
+ self.data_centered = self._yeeToCellCorner2d(boundary)
409
+ return self.data_centered
410
+ elif self.dim == 3:
411
+ self.data_centered = self._yeeToCellCorner3d(boundary)
412
+ return self.data_centered
413
+ else:
414
+ raise ValueError(f'Dimension {self.dim} is not supported')
415
+
416
+ def FFT(self, axis=(0, )):
417
+ '''
418
+ Computes the Fast Fourier Transform of the data along the specified axis and shifts the zero frequency to the center.
419
+ Transforms the data to the frequency domain. A(x, y, z) -> A(kx, ky, kz)
420
+ '''
421
+ datafft = np.fft.fftn(self.data, axes=axis)
422
+ self._FFTdata = np.fft.fftshift(datafft, axes=axis)
423
+
424
+
425
+
426
+ class OsirisRawFile(OsirisData):
91
427
  '''
92
428
  Class to read the raw data from an OSIRIS HDF5 file.
93
429
 
94
430
  Input:
95
431
  - filename: the path to the HDF5 file
96
-
432
+
97
433
  Attributes:
98
-
99
- - axis: a dictionary where each key is a dataset name, and each value is another dictionary containing:
100
- name (str): The name of the quantity (e.g., 'x1', 'ene').
101
- units (str): The units associated with that dataset in LaTeX (e.g., 'c/\\omega_p', 'm_e c^2').
102
- long_name (str): The name of the quantity in LaTeX (e.g., 'x_1', 'En2').
434
+ - axis - a dictionary where each key is a dataset name, and each value is another dictionary containing
435
+ name (str): The name of the quantity (e.g., r'x1', r'ene').
436
+ units (str): The units associated with that dataset in LaTeX (e.g., r'c/\\omega_p', r'm_e c^2').
437
+ long_name (str): The name of the quantity in LaTeX (e.g., r'x_1', r'En2').
103
438
  dictionary of dictionaries
104
- - data: a dictionary where each key is a dataset name, and each value is the data
439
+ - data - a dictionary where each key is a dataset name, and each value is the data
105
440
  dictionary of np.arrays
106
- - dim: the number of dimensions
441
+ - dim - the number of dimensions
107
442
  int
108
- - dt: the time step
443
+ - dt - the time step
109
444
  float
110
- - grid: maximum and minimum coordinates of the box, for each axis
445
+ - grid - maximum and minimum coordinates of the box, for each axis
111
446
  numpy.ndarray(dim,2)
112
- - iter: the iteration number
447
+ - iter - the iteration number
113
448
  int
114
- - name: the name of the species
449
+ - name - the name of the species
115
450
  str
116
- - time: the time and its units
451
+ - time - the time and its units
117
452
  list [time, units]
118
453
  list [float, str]
119
- -type: type of data (particles in the case of raw files)
454
+ - type - type of data (particles in the case of raw files)
120
455
  str
121
456
 
122
- Example:
123
-
124
- electrons = utils.OsirisRawFile("MS/RAW/electrons/RAW-electrons-000002.h5")
125
- plt.hist2d(electrons.data["x1"], electrons.data["x2"], bins=100, cmap='plasma', norm=mpl.colors.LogNorm())
126
- plt.xlabel(r"${}$".format(electrons.axis["x1"]["long_name"]) + r"$\quad[{}]$".format(electrons.axis["x1"]["units"]))
127
- plt.ylabel(r"${}$".format(electrons.axis["x2"]["long_name"]) + r"$\quad[{}]$".format(electrons.axis["x2"]["units"]))
128
- plt.title(r"$t={}$".format(electrons.time[0]) + r"$\quad[{}]$".format(electrons.time[1]))
129
- plt.show()
130
457
  '''
131
458
 
132
459
  def __init__(self, filename):
133
- self.filename = filename
134
-
135
- with h5py.File(self.filename, "r") as f:
136
-
137
- self.dt = float(f["SIMULATION"].attrs["DT"][0])
138
- self.dim = int(f["SIMULATION"].attrs["NDIMS"][0])
139
- self.time = [float(f.attrs["TIME"][0]), f.attrs["TIME UNITS"][0].decode('utf-8')]
140
- self.iter = int(f.attrs["ITER"][0])
141
- self.name = f.attrs["NAME"][0].decode('utf-8')
142
- self.type = f.attrs["TYPE"][0].decode('utf-8')
143
- self.grid = np.array([f["SIMULATION"].attrs["XMIN"], f["SIMULATION"].attrs["XMAX"]]).T
144
-
145
- self.data = {}
146
- self.axis = {}
147
- for key in f.keys():
148
- if key == "SIMULATION": continue
149
-
150
- self.data[key] = np.array(f[key][()])
151
-
152
- idx = np.where(f.attrs["QUANTS"] == str(key).encode('utf-8'))
153
- axis_data = {
154
- "name": f.attrs["QUANTS"][idx][0].decode('utf-8'),
155
- "units": f.attrs["UNITS"][idx][0].decode('utf-8'),
156
- "long_name": f.attrs["LABELS"][idx][0].decode('utf-8'),
157
- }
158
- self.axis[key] = axis_data
460
+ super().__init__(filename)
461
+
462
+ self.grid = np.array([self._file['SIMULATION'].attrs['XMIN'], self._file['SIMULATION'].attrs['XMAX']]).T
463
+
464
+ self.data = {}
465
+ self.axis = {}
466
+ for key in self._file.keys():
467
+ if key == 'SIMULATION': continue
468
+
469
+ self.data[key] = np.array(self._file[key][()])
470
+
471
+ idx = np.where(self._file.attrs['QUANTS'] == str(key).encode('utf-8'))
472
+ axis_data = {
473
+ 'name': self._file.attrs['QUANTS'][idx][0].decode('utf-8'),
474
+ 'units': self._file.attrs['UNITS'][idx][0].decode('utf-8'),
475
+ 'long_name': self._file.attrs['LABELS'][idx][0].decode('utf-8'),
476
+ }
477
+ self.axis[key] = axis_data
@@ -11,9 +11,9 @@ def read_osiris_file(filename, pressure = False):
11
11
  f = h5py.File(filename, 'r+')
12
12
  atr = f.attrs
13
13
  k = [key for key in f.keys()]
14
- if "SIMULATION" in k:
14
+ if 'SIMULATION' in k:
15
15
  attrs1 = atr
16
- attrs2 = f["SIMULATION"].attrs
16
+ attrs2 = f['SIMULATION'].attrs
17
17
  attrs = {}
18
18
  for i in range(len(attrs1)):
19
19
  attrs[[key for key in attrs1][i]] = [value for value in attrs1.values()][i]
@@ -24,21 +24,21 @@ def read_osiris_file(filename, pressure = False):
24
24
  axis = []
25
25
  for i in range(leanx):
26
26
  axis.append(ax.get([key for key in ax.keys()][i]))
27
- if "SIMULATION" in k and pressure == False:
27
+ if 'SIMULATION' in k and pressure == False:
28
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:
29
+ data.attrs['UNITS'] = attrs1['UNITS']
30
+ data.attrs['LONG_NAME'] = attrs1['LABEL']
31
+ elif 'SIMULATION' in k and pressure == True:
32
32
  data = f.get([key for key in f.keys()][1])
33
- data.attrs["UNITS"] = attrs1["UNITS"]
34
- data.attrs["LONG_NAME"] = attrs1["LABEL"]
33
+ data.attrs['UNITS'] = attrs1['UNITS']
34
+ data.attrs['LONG_NAME'] = attrs1['LABEL']
35
35
  else:
36
36
  data = f.get([key for key in f.keys()][1])
37
37
 
38
38
  return attrs, axis, data
39
39
 
40
40
  def open1D(filename, pressure = False):
41
- """
41
+ '''
42
42
  Open a 1D OSIRIS file and return the x axis and the data array.
43
43
 
44
44
  Parameters
@@ -52,7 +52,7 @@ def open1D(filename, pressure = False):
52
52
  The x axis.
53
53
  data_array : numpy.ndarray
54
54
  The data array.
55
- """
55
+ '''
56
56
  attrs, axes, data = read_osiris_file(filename, pressure)
57
57
  datash = data.shape
58
58
  ax1 = axes[0]
@@ -61,7 +61,7 @@ def open1D(filename, pressure = False):
61
61
  return x, data_array, [attrs, axes, data]
62
62
 
63
63
  def open2D(filename, pressure = False):
64
- """
64
+ '''
65
65
  Open a 2D OSIRIS file and return the x and y axes and the data array.
66
66
 
67
67
  Parameters
@@ -77,7 +77,7 @@ def open2D(filename, pressure = False):
77
77
  The y axis.
78
78
  data_array : numpy.ndarray
79
79
  The data array.
80
- """
80
+ '''
81
81
  attrs, axes, data = read_osiris_file(filename, pressure)
82
82
  datash = data.shape
83
83
  ax1 = axes[0]
@@ -88,7 +88,7 @@ def open2D(filename, pressure = False):
88
88
  return x, y, data_array, [attrs, axes, data]
89
89
 
90
90
  def open3D(filename):
91
- """
91
+ '''
92
92
  Open a 3D OSIRIS file and return the x, y and z axes and the data array.
93
93
 
94
94
  Parameters
@@ -106,7 +106,7 @@ def open3D(filename):
106
106
  The z axis.
107
107
  data_array : numpy.ndarray
108
108
  The data array.
109
- """
109
+ '''
110
110
  attrs, axes, data = read_osiris_file(filename)
111
111
  datash = data.shape
112
112
  ax1 = axes[0]
osiris_utils/gui.py CHANGED
@@ -14,7 +14,7 @@ from .utils import integrate, transverse_average # Update import as needed
14
14
  class LAVA_Qt(QMainWindow):
15
15
  def __init__(self):
16
16
  super().__init__()
17
- self.setWindowTitle("LAVA (LabAstro Visualization Assistant) - OSIRIS Data Grid Viewer")
17
+ self.setWindowTitle('LAVA (LabAstro Visualization Assistant) - OSIRIS Data Grid Viewer')
18
18
  self.setGeometry(100, 100, 1000, 600)
19
19
 
20
20
  # Initialize data
@@ -39,28 +39,28 @@ class LAVA_Qt(QMainWindow):
39
39
  control_layout = QHBoxLayout(control_frame)
40
40
 
41
41
  # Buttons
42
- self.browse_btn = QPushButton("Browse Folder")
42
+ self.browse_btn = QPushButton('Browse Folder')
43
43
  self.browse_btn.clicked.connect(self.load_folder)
44
- self.save_btn = QPushButton("Save Plot")
44
+ self.save_btn = QPushButton('Save Plot')
45
45
  self.save_btn.clicked.connect(self.save_plot)
46
46
 
47
47
  # File selector
48
48
  self.file_selector = QComboBox()
49
- self.file_selector.setPlaceholderText("Select file...")
49
+ self.file_selector.setPlaceholderText('Select file...')
50
50
  self.file_selector.currentIndexChanged.connect(self.file_selection_changed)
51
51
  self.file_selector.view().setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
52
52
  self.file_selector.setSizeAdjustPolicy(QComboBox.AdjustToContents)
53
53
 
54
54
  # Plot type combo box
55
55
  self.plot_combo = QComboBox()
56
- self.plot_combo.addItem("Select Plot Type")
56
+ self.plot_combo.addItem('Select Plot Type')
57
57
  self.plot_combo.currentTextChanged.connect(self.plot_data)
58
58
 
59
59
  control_layout.addWidget(self.browse_btn)
60
60
  control_layout.addWidget(self.save_btn)
61
- control_layout.addWidget(QLabel("Files:"))
61
+ control_layout.addWidget(QLabel('Files:'))
62
62
  control_layout.addWidget(self.file_selector)
63
- control_layout.addWidget(QLabel("Plot Type:"))
63
+ control_layout.addWidget(QLabel('Plot Type:'))
64
64
  control_layout.addWidget(self.plot_combo)
65
65
  self.main_layout.addWidget(control_frame)
66
66
 
@@ -80,11 +80,11 @@ class LAVA_Qt(QMainWindow):
80
80
  self.ylabel_edit.textChanged.connect(self.update_plot_labels)
81
81
 
82
82
 
83
- labels_layout.addWidget(QLabel("Title:"))
83
+ labels_layout.addWidget(QLabel('Title:'))
84
84
  labels_layout.addWidget(self.title_edit)
85
- labels_layout.addWidget(QLabel("X Label:"))
85
+ labels_layout.addWidget(QLabel('X Label:'))
86
86
  labels_layout.addWidget(self.xlabel_edit)
87
- labels_layout.addWidget(QLabel("Y Label:"))
87
+ labels_layout.addWidget(QLabel('Y Label:'))
88
88
  labels_layout.addWidget(self.ylabel_edit)
89
89
 
90
90
  # define the size of the labels frame
@@ -94,7 +94,7 @@ class LAVA_Qt(QMainWindow):
94
94
  def load_folder(self):
95
95
  folder_dialog = QFileDialog()
96
96
  folderpath = folder_dialog.getExistingDirectory(
97
- self, "Select Folder with HDF5 Files"
97
+ self, 'Select Folder with HDF5 Files'
98
98
  )
99
99
 
100
100
  if not folderpath:
@@ -119,16 +119,16 @@ class LAVA_Qt(QMainWindow):
119
119
  h5_files.sort(key=sort_key)
120
120
 
121
121
  if not h5_files:
122
- raise ValueError("No HDF5 files found in selected folder")
122
+ raise ValueError('No HDF5 files found in selected folder')
123
123
 
124
124
  self.file_selector.addItems(h5_files)
125
125
  self.file_selector.setCurrentIndex(0)
126
126
 
127
127
  except Exception as e:
128
- QMessageBox.critical(self, "Error", str(e))
128
+ QMessageBox.critical(self, 'Error', str(e))
129
129
 
130
130
  def file_selection_changed(self, index):
131
- """Handle file selection change in the combo box"""
131
+ '''Handle file selection change in the combo box'''
132
132
  if index >= 0 and self.current_folder:
133
133
  filename = self.file_selector.itemText(index)
134
134
  self.process_file(filename)
@@ -140,32 +140,32 @@ class LAVA_Qt(QMainWindow):
140
140
  self.dims = len(gridfile.axis)
141
141
  self.type = gridfile.type
142
142
 
143
- if self.type == "grid":
143
+ if self.type == 'grid':
144
144
  if self.dims == 1:
145
- x = np.linspace(gridfile.grid[0], gridfile.grid[1], gridfile.nx)
146
- self.xlabel_edit.setText(r"$%s$ [$%s$]" % (gridfile.axis[0]["long_name"], gridfile.axis[0]["units"]))
147
- self.ylabel_edit.setText(r"$%s$ [$%s$]" % (gridfile.label, gridfile.units))
145
+ x = np.arange(gridfile.grid[0], gridfile.grid[1], gridfile.dx)
146
+ self.xlabel_edit.setText(r'$%s$ [$%s$]' % (gridfile.axis[0]['long_name'], gridfile.axis[0]['units']))
147
+ self.ylabel_edit.setText(r'$%s$ [$%s$]' % (gridfile.label, gridfile.units))
148
148
  self.data_info = (x, gridfile.data)
149
149
  elif self.dims == 2:
150
- x = np.linspace(gridfile.grid[0][0], gridfile.grid[0][1], gridfile.nx[0])
151
- y = np.linspace(gridfile.grid[1][0], gridfile.grid[1][1], gridfile.nx[1])
152
- self.xlabel_edit.setText(r"$%s$ [$%s$]" % (gridfile.axis[0]["long_name"], gridfile.axis[0]["units"]))
153
- self.ylabel_edit.setText(r"$%s$ [$%s$]" % (gridfile.axis[1]["long_name"], gridfile.axis[1]["units"]))
150
+ x = np.arange(gridfile.grid[0][0], gridfile.grid[0][1], gridfile.dx[0])
151
+ y = np.arange(gridfile.grid[1][0], gridfile.grid[1][1], gridfile.dx[1])
152
+ self.xlabel_edit.setText(r'$%s$ [$%s$]' % (gridfile.axis[0]['long_name'], gridfile.axis[0]['units']))
153
+ self.ylabel_edit.setText(r'$%s$ [$%s$]' % (gridfile.axis[1]['long_name'], gridfile.axis[1]['units']))
154
154
  self.data_info = (x, y, gridfile.data)
155
155
  elif self.dims == 3:
156
- raise ValueError("3D not supported yet")
156
+ raise ValueError('3D not supported yet')
157
157
  else:
158
- raise ValueError("Unsupported dimensionality")
158
+ raise ValueError('Unsupported dimensionality')
159
159
 
160
- self.title_edit.setText(r"$%s$ [$%s$]" %( gridfile.label, gridfile.units))
160
+ self.title_edit.setText(r'$%s$ [$%s$]' %( gridfile.label, gridfile.units))
161
161
  self.update_plot_menu()
162
162
  self.plot_data()
163
163
 
164
164
  else:
165
- QMessageBox.information(self, "Info", f"{self.type} data not supported yet")
165
+ QMessageBox.information(self, 'Info', f'{self.type} data not supported yet')
166
166
 
167
167
  except Exception as e:
168
- QMessageBox.critical(self, "Error", str(e))
168
+ QMessageBox.critical(self, 'Error', str(e))
169
169
 
170
170
  def create_plot_area(self):
171
171
  # Matplotlib figure and canvas
@@ -194,9 +194,9 @@ class LAVA_Qt(QMainWindow):
194
194
  self.current_ax = self.figure.add_subplot(111)
195
195
  plot_type = self.plot_combo.currentText()
196
196
 
197
- if "Line" in plot_type:
197
+ if 'Line' in plot_type:
198
198
  self.current_ax.plot(x, data)
199
- elif "Scatter" in plot_type:
199
+ elif 'Scatter' in plot_type:
200
200
  self.current_ax.scatter(x, data)
201
201
 
202
202
  self.current_ax.set_xlabel(self.xlabel_edit.text())
@@ -208,17 +208,17 @@ class LAVA_Qt(QMainWindow):
208
208
  self.current_ax = self.figure.add_subplot(111)
209
209
  plot_type = self.plot_combo.currentText()
210
210
 
211
- if "Quantity" in plot_type:
212
- img = self.current_ax.imshow(data, extent=(x[0], x[-1], y[0], y[-1]), origin='lower', aspect='auto')
211
+ if 'Quantity' in plot_type:
212
+ img = self.current_ax.imshow(data.T, extent=(x[0], x[-1], y[0], y[-1]), origin='lower', aspect='auto')
213
213
  self.figure.colorbar(img)
214
- elif "Integral" in plot_type:
214
+ elif 'Integral' in plot_type:
215
215
  avg = integrate(transverse_average(data), x[-1]/len(x))
216
216
  self.current_ax.plot(x, avg)
217
- elif "Transverse" in plot_type:
217
+ elif 'Transverse' in plot_type:
218
218
  avg = transverse_average(data)
219
219
  self.current_ax.plot(x, avg)
220
- elif "Phase" in plot_type:
221
- img = self.current_ax.imshow(np.abs(-data), extent=(x[0], x[-1], y[0], y[-1]), origin='lower', aspect='auto', norm=LogNorm())
220
+ elif 'Phase' in plot_type:
221
+ img = self.current_ax.imshow(np.abs(-data.T), extent=(x[0], x[-1], y[0], y[-1]), origin='lower', aspect='auto', norm=LogNorm())
222
222
  self.figure.colorbar(img)
223
223
 
224
224
  self.current_ax.set_xlabel(self.xlabel_edit.text())
@@ -233,9 +233,9 @@ class LAVA_Qt(QMainWindow):
233
233
 
234
234
  # Determine items based on dimensions
235
235
  if self.dims == 1:
236
- items = ["Line Plot", "Scatter Plot"]
236
+ items = ['Line Plot', 'Scatter Plot']
237
237
  elif self.dims == 2:
238
- items = ["Quantity Plot", "T. Average Integral", "Transverse Average", "Phase Space"]
238
+ items = ['Quantity Plot', 'T. Average Integral', 'Transverse Average', 'Phase Space']
239
239
  else:
240
240
  items = []
241
241
 
@@ -250,11 +250,11 @@ class LAVA_Qt(QMainWindow):
250
250
  def save_plot(self):
251
251
  file_dialog = QFileDialog()
252
252
  filepath, _ = file_dialog.getSaveFileName(
253
- self, "Save Plot", "", "PNG Files (*.png);;PDF Files (*.pdf)"
253
+ self, 'Save Plot', '', 'PNG Files (*.png);;PDF Files (*.pdf)'
254
254
  )
255
255
 
256
256
  if filepath:
257
- self.figure.savefig(filepath, dpi=800, bbox_inches="tight")
257
+ self.figure.savefig(filepath, dpi=800, bbox_inches='tight')
258
258
 
259
259
  def LAVA():
260
260
  app = QApplication(sys.argv)
@@ -262,5 +262,5 @@ def LAVA():
262
262
  window.show()
263
263
  sys.exit(app.exec())
264
264
 
265
- if __name__ == "__main__":
265
+ if __name__ == '__main__':
266
266
  LAVA()
@@ -0,0 +1,52 @@
1
+ import numpy as np
2
+ from .data import OsirisGridFile
3
+
4
+
5
+ class MeanFieldTheory(OsirisGridFile):
6
+ '''
7
+ Class to handle the mean field theory on data. Inherits from OsirisGridFile.
8
+
9
+ Parameters
10
+ ----------
11
+ source : str or OsirisGridFile
12
+ The filename or an OsirisGridFile object.
13
+ axis : int
14
+ The axis to average over.
15
+ '''
16
+ def __init__(self, source, axis=1):
17
+ if isinstance(source, OsirisGridFile):
18
+ self.__dict__.update(source.__dict__)
19
+ else:
20
+ super().__init__(source)
21
+ self._compute_mean_field(axis=axis)
22
+
23
+ def _compute_mean_field(self, axis=1):
24
+ self._average = np.expand_dims(np.mean(self.data, axis=axis), axis=axis)
25
+ self._fluctuations = self.data - self._average
26
+
27
+ def __array__(self):
28
+ return self.data
29
+
30
+ @property
31
+ def average(self):
32
+ return self._average
33
+
34
+ @property
35
+ def delta(self):
36
+ return self._fluctuations
37
+
38
+ def __str__(self):
39
+ return super().__str__() + f'\nAverage: {self.average.shape}\nDelta: {self.delta.shape}'
40
+
41
+ def derivative(self, field, axis=0):
42
+ '''
43
+ Compute the derivative of the average or the fluctuations.
44
+
45
+ Parameters
46
+ ----------
47
+ field : MeanFieldTheory.average or MeanFieldTheory.delta
48
+ The field to compute the derivative.
49
+ axis : int
50
+ The axis to compute the derivative.
51
+ '''
52
+ return np.gradient(field, self.dx[axis], axis=0)
osiris_utils/utils.py CHANGED
@@ -7,7 +7,7 @@ import scipy
7
7
  import pandas as pd
8
8
 
9
9
  def courant2D(dx, dy):
10
- """
10
+ '''
11
11
  Compute the Courant number for a 2D simulation.
12
12
 
13
13
  Parameters
@@ -21,12 +21,12 @@ def courant2D(dx, dy):
21
21
  -------
22
22
  float
23
23
  The limit for dt.
24
- """
24
+ '''
25
25
  dt = 1 / (np.sqrt(1/dx**2 + 1/dy**2))
26
26
  return dt
27
27
 
28
28
  def time_estimation(n_cells, ppc, push_time, t_steps, n_cpu, hours = False):
29
- """
29
+ '''
30
30
  Estimate the simulation time.
31
31
 
32
32
  Parameters
@@ -48,7 +48,7 @@ def time_estimation(n_cells, ppc, push_time, t_steps, n_cpu, hours = False):
48
48
  -------
49
49
  float
50
50
  The estimated time in seconds or hours.
51
- """
51
+ '''
52
52
  time = (n_cells*ppc*push_time*t_steps)/n_cpu
53
53
  if hours:
54
54
  return time/3600
@@ -59,7 +59,7 @@ def filesize_estimation(n_gridpoints):
59
59
  return n_gridpoints*4/(1024**2)
60
60
 
61
61
  def transverse_average(data):
62
- """
62
+ '''
63
63
  Computes the transverse average of a 2D array.
64
64
 
65
65
  Parameters
@@ -74,14 +74,14 @@ def transverse_average(data):
74
74
  Dim: 1D.
75
75
  The transverse average.
76
76
 
77
- """
77
+ '''
78
78
 
79
79
  if len(data.shape) != 2:
80
- raise ValueError("The input data must be a 2D array.")
80
+ raise ValueError('The input data must be a 2D array.')
81
81
  return np.mean(data, axis = 1)
82
82
 
83
83
  def integrate(array, dx):
84
- """
84
+ '''
85
85
  Integrate a 1D from the left to the right. This may be changed in the future to allow
86
86
  for integration in both directions or for other more general cases.
87
87
 
@@ -98,24 +98,24 @@ def integrate(array, dx):
98
98
  numpy.ndarray
99
99
  Dim: 1D.
100
100
  The integrated array.
101
- """
101
+ '''
102
102
 
103
103
  if len(array.shape) != 1:
104
- raise ValueError(f"Array must be 1D\n Array shape: {array.shape}")
104
+ raise ValueError(f'Array must be 1D\n Array shape: {array.shape}')
105
105
  flip_array = np.flip(array)
106
106
  # int = -scipy.integrate.cumulative_trapezoid(flip_array, dx = dx, initial = flip_array[0])
107
107
  int = -scipy.integrate.cumulative_simpson(flip_array, dx = dx, initial = 0)
108
108
  return np.flip(int)
109
109
 
110
110
  def animate_2D(datafiles, frames, interval, fps, savename, **kwargs):
111
- """
111
+ '''
112
112
  Animate 2D OSIRIS files.
113
113
 
114
114
  Parameters
115
115
  ----------
116
116
  datafiles : str
117
117
  The path to the files.
118
- Must be of the type "path/to/file_%06d.h5".
118
+ Must be of the type 'path/to/file_%06d.h5'.
119
119
  kwargs : dict
120
120
  Additional keyword arguments for plotting.
121
121
 
@@ -123,7 +123,7 @@ def animate_2D(datafiles, frames, interval, fps, savename, **kwargs):
123
123
  -------
124
124
  matplotlib.animation.FuncAnimation
125
125
  The animation.
126
- """
126
+ '''
127
127
  fig, ax = plt.subplots(figsize=(12, 6), tight_layout=True)
128
128
  im = 0
129
129
 
@@ -133,8 +133,8 @@ def animate_2D(datafiles, frames, interval, fps, savename, **kwargs):
133
133
  ax.clear()
134
134
  # Display image data, make sure data shape is valid for imshow
135
135
  im = ax.imshow(-data, extent=[x.min(), x.max(), y.min(), y.max()], aspect='auto', origin='lower', **kwargs)
136
- plt.xlabel(r"x [c/$\omega_p$]")
137
- plt.ylabel(r"y [c/$\omega_p$]")
136
+ plt.xlabel(r'x [c/$\omega_p$]')
137
+ plt.ylabel(r'y [c/$\omega_p$]')
138
138
 
139
139
 
140
140
  # Creating the animation, and frames should be updated accordingly
@@ -146,7 +146,7 @@ def animate_2D(datafiles, frames, interval, fps, savename, **kwargs):
146
146
  # Display the animation
147
147
  return ani
148
148
 
149
- def save_data(data, savename, option="numpy"):
149
+ def save_data(data, savename, option='numpy'):
150
150
  """
151
151
  Save the data to a .txt (with Numpy) or .csv (with Pandas) file.
152
152
 
@@ -157,17 +157,17 @@ def save_data(data, savename, option="numpy"):
157
157
  savename : str
158
158
  The path to the file.
159
159
  option : str, optional
160
- The option for saving the data. The default is "numpy". Can be "numpy" or "pandas".
160
+ The option for saving the data. The default is 'numpy'. Can be 'numpy' or 'pandas'.
161
161
  """
162
- if option == "numpy":
162
+ if option == 'numpy':
163
163
  np.savetxt(savename, data)
164
- elif option == "pandas":
164
+ elif option == 'pandas':
165
165
  pd.DataFrame(data).to_csv(savename, index=False)
166
166
  else:
167
167
  raise ValueError("Option must be 'numpy' or 'pandas'.")
168
168
 
169
- def read_data(filename, option="numpy"):
170
- """
169
+ def read_data(filename, option='numpy'):
170
+ '''
171
171
  Read the data from a .txt file.
172
172
 
173
173
  Parameters
@@ -180,54 +180,5 @@ def read_data(filename, option="numpy"):
180
180
  numpy.ndarray
181
181
  Dim: 2D.
182
182
  The data.
183
- """
184
- return np.loadtxt(filename) if option == "numpy" else pd.read_csv(filename).values
185
-
186
- def mft_decomposition(filename, pressure = False, xy = False, data = False):
187
- """
188
- Mean Field Theory decomposition of the data.
189
- Considering that A = ⟨A⟩ + δA with ⟨δA⟩ = 0
190
- This function returns ⟨A⟩ and δA from A.
191
-
192
- Parameters
193
- ----------
194
- filename : str
195
- The path to the file.
196
- The data is 2D.
197
- pressure : bool, optional
198
- If True, the file is a pressure file. The default is False.
199
- xy : bool, optional
200
- If True, the function returns x and y axes. The default is False.
201
- data : bool, optional
202
- If True, the function returns the data (2D with no transformation). The default is False.
203
-
204
- Returns
205
- -------
206
- mean : numpy.ndarray
207
- Dim: 1D.
208
- The mean field ⟨A⟩.
209
- fluctuation : numpy.ndarray
210
- Dim: 2D.
211
- The fluctuation δA.
212
- x : numpy.ndarray
213
- Dim: 1D.
214
- The x axis.
215
- y : numpy.ndarray
216
- Dim: 1D.
217
- The y axis.
218
- data : numpy.ndarray
219
- Dim: 2D.
220
- The data.
221
- """
222
- x, y, d, _ = open2D(filename, pressure)
223
- mean = transverse_average(d)
224
- fluctuation = d - mean
225
-
226
- if xy and data:
227
- return mean, fluctuation, x, y, d
228
- elif xy:
229
- return mean, fluctuation, x, y
230
- elif data:
231
- return mean, fluctuation, d
232
- else:
233
- return mean, fluctuation
183
+ '''
184
+ return np.loadtxt(filename) if option == 'numpy' else pd.read_csv(filename).values
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: osiris_utils
3
- Version: 1.0.5
3
+ Version: 1.0.9
4
4
  Summary: Utilities to manipulate and visualize OSIRIS framework output data
5
- Author: ['João Pedro Ferreira Biu', 'João Cândido', 'Rafael Russo de Almeida']
5
+ Author: ['João Pedro Ferreira Biu', 'João Cândido']
6
6
  Author-email: ['joaopedrofbiu@tecnico.ulisboa.pt']
7
7
  License: MIT
8
8
  Project-URL: Issues Tracker, https://github.com/joaopedrobiu6/osiris_utils/issues
@@ -17,8 +17,9 @@ Classifier: Programming Language :: Python :: 3.8
17
17
  Classifier: Programming Language :: Python :: 3.9
18
18
  Classifier: Programming Language :: Python :: 3.10
19
19
  Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
20
21
  Classifier: Topic :: Scientific/Engineering
21
- Requires-Python: >=3.12
22
+ Requires-Python: >=3.11
22
23
  Description-Content-Type: text/markdown
23
24
  License-File: LICENSE.txt
24
25
  Requires-Dist: numpy
@@ -27,6 +28,8 @@ Requires-Dist: pandas
27
28
  Requires-Dist: scipy
28
29
  Requires-Dist: h5py
29
30
  Requires-Dist: pyside6
31
+ Requires-Dist: pyarrow
32
+ Requires-Dist: tqdm
30
33
  Dynamic: author
31
34
  Dynamic: author-email
32
35
  Dynamic: classifier
@@ -0,0 +1,11 @@
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.0)
2
+ Generator: setuptools (76.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,10 +0,0 @@
1
- osiris_utils/__init__.py,sha256=mXRRxiNNJ6pxmRGO23OCNR3Yn3MvrBZFiNI9Rui_un8,318
2
- osiris_utils/data.py,sha256=awf6v_zWsOTPjdbLQ_8E0SsaGGvp_UQZGUBh2UuCIyk,6678
3
- osiris_utils/data_readers.py,sha256=ZeqbYHsFmdKRxqUNkkauurjz-1VABW4GZ-WaPQREdfc,3264
4
- osiris_utils/gui.py,sha256=DPRqqFIYfgNZEMnt4rEo5TiHe5fogkWySrOllQvj0ak,10533
5
- osiris_utils/utils.py,sha256=SrHsMaOq1zw9Qx9YJV7jJvS1u6hr5RLV7IvikygM4pg,6097
6
- osiris_utils-1.0.5.dist-info/LICENSE.txt,sha256=Cawy2v7wKc7n8yL8guFu-cH9sQw9r1gll1pEFPFAB-Q,1084
7
- osiris_utils-1.0.5.dist-info/METADATA,sha256=6kPFf27IPybWbwPEyf36VxPgRyD6-Du81tfVj04DeSM,1396
8
- osiris_utils-1.0.5.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
9
- osiris_utils-1.0.5.dist-info/top_level.txt,sha256=mM-_dX5fjzIKB7te655PhZOrPACVY-bJmiASCqW1eOA,13
10
- osiris_utils-1.0.5.dist-info/RECORD,,