osiris-utils 1.0.5__tar.gz → 1.0.9__tar.gz

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.
@@ -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
@@ -1,5 +1,6 @@
1
1
  OSIRIS_UTILS
2
2
  ============
3
+ |Pypi|
3
4
 
4
5
  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.
5
6
 
@@ -17,4 +18,9 @@ To install it from source, you can clone this repository and run (in the folder
17
18
  Documentation
18
19
  -------------
19
20
 
20
- The documentation is available at https://osiris-utils.readthedocs.io or via this link: `osiris-utils.readthedocs.io <https://osiris-utils.readthedocs.io>`_.
21
+ The documentation is available at https://osiris-utils.readthedocs.io or via this link: `osiris-utils.readthedocs.io <https://osiris-utils.readthedocs.io>`_.
22
+
23
+ .. |Pypi| image:: https://img.shields.io/pypi/v/osiris-utils
24
+ :target: https://pypi.org/project/osiris-utils/
25
+ :alt: Pypi
26
+
@@ -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
@@ -0,0 +1,477 @@
1
+ import numpy as np
2
+ import h5py
3
+
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):
138
+ '''
139
+ Class to read the grid data from an OSIRIS HDF5 file.
140
+
141
+ Input:
142
+ -----
143
+ - filename: the path to the HDF5 file
144
+
145
+ Attributes:
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
154
+ float
155
+ - dim - the number of dimensions
156
+ int
157
+ - time - the time and its units
158
+ list [time, units]
159
+ list [float, str]
160
+ - iter - the iteration number
161
+ int
162
+ - name - the name of the data
163
+ str
164
+ - type - the type of data
165
+ str
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
177
+ str
178
+ - label - the label of the data (LaTeX formatted)
179
+
180
+ '''
181
+ def __init__(self, filename):
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')
229
+
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):
427
+ '''
428
+ Class to read the raw data from an OSIRIS HDF5 file.
429
+
430
+ Input:
431
+ - filename: the path to the HDF5 file
432
+
433
+ Attributes:
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').
438
+ dictionary of dictionaries
439
+ - data - a dictionary where each key is a dataset name, and each value is the data
440
+ dictionary of np.arrays
441
+ - dim - the number of dimensions
442
+ int
443
+ - dt - the time step
444
+ float
445
+ - grid - maximum and minimum coordinates of the box, for each axis
446
+ numpy.ndarray(dim,2)
447
+ - iter - the iteration number
448
+ int
449
+ - name - the name of the species
450
+ str
451
+ - time - the time and its units
452
+ list [time, units]
453
+ list [float, str]
454
+ - type - type of data (particles in the case of raw files)
455
+ str
456
+
457
+ '''
458
+
459
+ def __init__(self, filename):
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]