:py:mod:`pylbo` =============== .. py:module:: pylbo Subpackages ----------- .. toctree:: :titlesonly: :maxdepth: 3 automation/index.rst utilities/index.rst visualisation/index.rst Submodules ---------- .. toctree:: :titlesonly: :maxdepth: 1 _version/index.rst data_containers/index.rst exceptions/index.rst testing/index.rst Package Contents ---------------- Functions ~~~~~~~~~ .. autoapisummary:: pylbo.generate_parfiles pylbo.run_legolas pylbo.load pylbo.load_logfile pylbo.load_series pylbo.get_equilibrium_balance pylbo.disable_logging pylbo.set_loglevel pylbo.plot_continua pylbo.plot_equilibrium pylbo.plot_equilibrium_balance pylbo.plot_matrices pylbo.plot_merged_spectrum pylbo.plot_spectrum pylbo.plot_spectrum_comparison pylbo.plot_spectrum_multi pylbo.plot_1d_temporal_evolution pylbo.plot_2d_slice pylbo.plot_3d_slice pylbo.prepare_vtk_export .. py:function:: generate_parfiles(parfile_dict: dict, basename: str = None, output_dir: Union[str, os.PathLike] = None, subdir: bool = True, prefix_numbers: bool = True, nb_prefix_digits: int = 4) -> list[str] Generates parfiles based on a given configuration dictionary. The separate namelists do not have to be taken into account, and a normal dictionary should be supplied where the keys correspond to the namelist items that are required. Typechecking is done automatically during parfile generation. :param parfile_dict: Dictionary containing the keys to be placed in the parfile. :type parfile_dict: dict :param basename: The basename for the parfile, the `.par` suffix is added automatically and is not needed. If multiple parfiles are generated, these will be prepended by a 4-digit number (e.g. 0003myparfile.par). If not provided, the basename will default to `parfile`. :type basename: str :param output_dir: Output directory where the parfiles are saved, defaults to the current working directory if not specified. A subdirectory called `parfiles` will be created in which the parfiles will be saved. :type output_dir: str, ~os.PathLike :param subdir: If `True` (default), creates a subdirectory `parfiles` in the output folder. :type subdir: boolean :param prefix_numbers: If `True` prepends the `basename` by a n-digit number (e.g. xxxxmyparfile.par). The number of digits is specified by `nb_prefix_digits`. :type prefix_numbers: boolean :param nb_prefix_digits: Number of digits to prepend to the `basename` if `prefix_numbers` is `True`. Defaults to 4. :type nb_prefix_digits: int .. rubric:: Notes This routine is quite flexible and specifically designed for parametric studies. You can specify both single values and list-like items as dictionary items. This routine will automatically generate multiple parfiles if lists/numpy arrays are present. :returns: **parfiles** -- A list with the paths to the parfiles that were generated. This list can be passed immediately to :func:`pylbo.run_legolas`. :rtype: list .. rubric:: Examples This will generate a single parfile in a subdirectory `parfile` of the current working directory. >>> import pylbo >>> config = { >>> "geometry": "Cartesian", >>> "x_start": 0, >>> "x_end": 1, >>> "equilibrium_type": "resistive_homo", >>> "gridpoints": 100, >>> "write_eigenfunctions": True, >>> "basename_datfile": "my_run", >>> "output_folder": "output", >>> } >>> parfile = pylbo.generate_parfiles(config) This will generate 10 parfiles in the directory `my_parfiles` relative to the current working directory. The first parfile will have `x_end = 1.0` and 100 gridpoints, the second one will have `x_end = 2.0` and 150 gridpoints, etc. >>> import pylbo >>> import numpy as np >>> config = { >>> "geometry": "Cartesian", >>> "x_start": 0, >>> "x_end": np.arange(1, 11) >>> "number_of_runs": 10 >>> "equilibrium_type": "resistive_homo", >>> "gridpoints": np.arange(100, 600, 50), >>> "write_eigenfunctions": True, >>> "basename_datfile": "my_run", >>> "output_folder": "output", >>> } >>> parfile_list = pylbo.generate_parfiles(config, output_dir="my_parfiles") .. !! processed by numpydoc !! .. py:function:: run_legolas(parfiles: Union[str, list, os.PathLike], remove_parfiles: bool = False, nb_cpus: int = 1, executable: Union[str, os.PathLike] = None) -> None Runs the legolas executable for a given list of parfiles. If more than one parfile is passed, the runs can be performed in parallel using the multiprocessing module. Parallelisation can be enabled by setting the `nb_cpus` kwarg to a number greater than one, and is disabled by default. Every CPU will have a single legolas executable subprocess associated with it. :param parfiles: A string, list or array containing the paths to the parfile(s). Accepts the output of :func:`pylbo.generate_parfiles`. :type parfiles: str, list, numpy.ndarray :param remove_parfiles: If `True`, removes the parfiles after running Legolas. This will also remove the containing folder if it turns out to be empty after the parfiles are removed. If there are other files still in the folder it remains untouched. :type remove_parfiles: bool :param nb_cpus: The number of CPUs to use when running Legolas. If equal to 1 then parallelisation is disabled. Defaults to the maximum number of CPUs available if a number larger than the available number is specified. :type nb_cpus: int :param executable: The path to the legolas executable. If not specified, defaults to the standard one in the legolas home directory. :type executable: str, ~os.PathLike .. rubric:: Notes If multiprocessing is enabled, it is usually a good idea to have the number of runs requested divisible by the number of CPUs that are available. For example, if 24 runs are requested it is good practice to use either 2, 4, 6 or 8 CPUs, and avoid numbers like 3, 5 and 7. .. rubric:: Examples The example below will run a list of parfiles using using a local legolas executable from the current directory, on 4 CPU's. >>> import pylbo >>> from pathlib import Path >>> files = sorted(Path("parfiles").glob("*.dat")) >>> pylbo.run_legolas(files, nb_cpus=4, executable="legolas") .. !! processed by numpydoc !! .. py:function:: load(datfile) Loads a single Legolas datfile. :param datfile: Path to the datfile. :type datfile: str, ~os.PathLike :raises ValueError: If `datfile` is not a single file. :returns: **ds** -- A dataset instance for the given datfile. :rtype: ~pylbo.data_containers.LegolasDataSet .. !! processed by numpydoc !! .. py:function:: load_logfile(logfile, sort=False) Reads a Legolas log file. :param logfile: The path to the logfile. :type logfile: str, ~os.PathLike :param sort: If `True`, sorts the eigenvalues in the logfile. Sorting is done first on the real part, then on the imaginary part. :type sort: bool :returns: **eigenvalues** -- Array containing the eigenvalues from the logfile. :rtype: numpy.ndarray .. !! processed by numpydoc !! .. py:function:: load_series(datfiles) Loads multiple Legolas datfiles. :param datfiles: Paths to the datfiles that should be loaded, in list/array form. Every element should be a string or a ~os.PathLike object. :type datfiles: list, numpy.ndarray :raises ValueError: If an empty list or array is supplied. :returns: **series** -- A dataseries instance for the given datfiles. :rtype: ~pylbo.data_containers.LegolasDataSeries .. !! processed by numpydoc !! .. py:function:: get_equilibrium_balance(ds: pylbo.data_containers.LegolasDataSet) -> dict .. py:function:: disable_logging() Completely disables logging. .. !! processed by numpydoc !! .. py:function:: set_loglevel(level) Sets the logging level. :param level: The level for logging. See :class:`~logging.Logger`, or the `allowed levels `_. Both the string and integer values can be set, case-insensitive. :type level: int, str .. !! processed by numpydoc !! .. py:function:: plot_continua(data, figsize=None, interactive=True, **kwargs) Plots the continua profiles. :param data: The dataset or series that should be used. :type data: ~pylbo.data_containers.LegolasDataSet :param figsize: Optional figure size like the usual matplotlib (x, x) size. :type figsize: tuple :param interactive: If `True` (default), enables an interactive legend. :type interactive: bool :returns: **p** -- The profile instance containing the continua plots. :rtype: ~pylbo.visualisation.profiles.ContinuumProfile .. !! processed by numpydoc !! .. py:function:: plot_equilibrium(data, figsize=None, interactive=True, **kwargs) Plots the equilibrium profiles. :param data: The dataset or series that should be used. :type data: ~pylbo.data_containers.LegolasDataSet :param figsize: Optional figure size like the usual matplotlib (x, x) size. :type figsize: tuple :param interactive: If `True` (default), enables an interactive legend. :type interactive: bool :returns: **p** -- The profile instance containing the equilibrium plots. :rtype: ~pylbo.visualisation.profiles.EquilibriumProfile .. !! processed by numpydoc !! .. py:function:: plot_equilibrium_balance(data, figsize=None, interactive=True, **kwargs) Creates a plot of the balance equations. These should be as close to zero as possible over the entire grid. :param data: The dataset that should be used :type data: ~pylbo.data_containers.LegolasDataSet :param figsize: Optional figure size like the usual matplotlib (x, x) size. :type figsize: tuple :param interactive: If `True` (default), enables an interactive legend. :type interactive: bool :returns: **p** -- The profile instance containing the equilibrium balance plots. :rtype: ~pylbo.visualisation.profiles.EquilibriumBalance .. !! processed by numpydoc !! .. py:function:: plot_matrices(data, figsize=None, **kwargs) Plots the continua profiles. :param data: The dataset that should be used. :type data: ~pylbo.data_containers.LegolasDataSet :param figsize: Optional figure size like the usual matplotlib (x, x) size. :type figsize: tuple :returns: **p** -- The instance containing the matrix plots. :rtype: ~pylbo.visualisation.matrices.MatrixFigure .. !! processed by numpydoc !! .. py:function:: plot_merged_spectrum(data, figsize=None, custom_figure=None, interactive=True, legend=True, **kwargs) Creates a merged spectrum from various datasets, useful in plotting multiple results from the shift-invert solver, for example. This draws every dataset in a different color by default, and creates a corresponding legend. Supply the optional argument `color` to draw all points in the same color. :param data: :type data: ~pylbo.data_containers.LegolasDataSeries :param figsize: Optional figure size like the usual matplotlib (x, x) size. :type figsize: tuple :param custom_figure: Optional, in the form (fig, ax). If supplied no new figure will be created but this one will be used instead. `fig` refers to the matplotlib figure and `ax` to a (single) axes instance, meaning that you can pass a subplot as well. :type custom_figure: tuple :param interactive: If `True` (default), enables an interactive legend. :type interactive: bool :param legend: If `True` (default), draws a legend. :type legend: bool :returns: **p** -- The spectrumfigure instance, containing the plot. :rtype: ~pylbo.visualisation.spectra.MultiSpectrumPlot .. !! processed by numpydoc !! .. py:function:: plot_spectrum(data, figsize=None, custom_figure=None, use_residuals=False, **kwargs) Plots the spectrum of a single dataset. :param data: The dataset that should be used. :type data: ~pylbo.data_containers.LegolasDataSet :param figsize: Optional figure size like the usual matplotlib (x, x) size. :type figsize: tuple :param custom_figure: Optional, in the form (fig, ax). If supplied no new figure will be created but this one will be used instead. `fig` refers to the matplotlib figure and `ax` to a (single) axes instance, meaning that you can pass a subplot as well. :type custom_figure: tuple :param use_residuals: If `True`, colors the spectrum based on the residual in the datfile. :type use_residuals: bool :returns: **p** -- The spectrum instance which can be used further to add continua, eigenfunctions, etc. :rtype: ~pylbo.visualisation.spectra.SingleSpectrumPlot .. !! processed by numpydoc !! .. py:function:: plot_spectrum_comparison(ds1, ds2, figsize=None, custom_figure=None, lock_zoom=False, use_residuals=False, **kwargs) Compares two spectra. :param ds1: The first dataset, this one is put on the left panel. :type ds1: ~pylbo.data_containers.LegolasDataSet :param ds2: The second dataset, this one is put on the right panel. :type ds2: ~pylbo.data_containers.LegolasDataSet :param figsize: Optional figure size like the usual matplotlib (x, x) size. :type figsize: tuple :param custom_figure: The custom figure to use in the form (fig, axes). :type custom_figure: tuple :param lock_zoom: If `True` (`False` by default), locks the zoom of both axis. When locked, zoomin in on one of the axis automatically scales the zoom on the other one as well. :type lock_zoom: bool :param use_residuals: If `True`, colors the spectrum based on the residual in the datfile. :type use_residuals: bool :returns: **p** -- The figure instance containing the compared spectrum plot. :rtype: ~pylbo.visualisation.spectra.SpectrumComparisonPlot .. !! processed by numpydoc !! .. py:function:: plot_spectrum_multi(data, xdata, use_squared_omega=False, use_real_parts=True, figsize=None, custom_figure=None, **kwargs) Plots the spectrum of a dataset series. :param data: The dataseries that should be used. :type data: ~pylbo.data_containers.LegolasDataSeries :param xdata: Data to use for the horizontal axis. This can either be a key from the parameters dictionary, or a list/numpy array containing actual data. :type xdata: str, list, numpy.ndarray :param use_squared_omega: If `True`, this will square the eigenvalues when they are plotted on the vertical axis. If `False` (default), either the real or imaginary part of the eigenvalues will be plotted depending on the value of `use_real_parts`. :type use_squared_omega: bool :param figsize: Optional figure size like the usual matplotlib (x, x) size. :type figsize: tuple :param custom_figure: Optional, in the form (fig, ax). If supplied no new figure will be created but this one will be used instead. `fig` refers to the matplotlib figure and `ax` to a (single) axes instance, meaning that you can pass a subplot as well. :type custom_figure: tuple :returns: **p** -- The spectrum instance which can be used further to add continua, eigenfunctions, etc. :rtype: ~pylbo.visualisation.spectra.MultiSpectrumPlot .. !! processed by numpydoc !! .. py:function:: plot_1d_temporal_evolution(ds: pylbo.data_containers.LegolasDataSet, omega: Union[complex, list[complex], numpy.ndarray], ef_name: str, u2: float, u3: float, time: Union[list, numpy.ndarray], figsize: tuple[int, int] = None, add_background: bool = False, use_real_part: bool = True, complex_factor: complex = None, show_ef_panel: bool = True, **kwargs) -> pylbo.visualisation.modes.temporal_1d.TemporalEvolutionPlot1D Plot the temporal evolution of a 1D eigenmode solution, i.e. :math:`f(u_1, u_2, u_3, t) = f_1(u_1) \exp\left(ik_2u_2 + ik_3u_3 - i\omega t\right)`, for a particular set of coordinates :math:`(u_2, u_3)` over a time interval. :param ds: The data set containing the eigenfunction. :type ds: LegolasDataSet :param omega: The (approximate) eigenvalue of the mode(s) to visualise. :type omega: complex, list[complex], np.ndarray :param ef_name: The name of the eigenfunction to visualise. :type ef_name: str :param u2: The y or :math:`\theta` coordinate of the eigenmode solution. :type u2: float :param u3: The z coordinate of the eigenmode solution. :type u3: float :param time: The time interval to visualise. :type time: list or np.ndarray :param figsize: The size of the figure. :type figsize: tuple[int, int] :param add_background: Whether to add the equilibrium background to the plot. :type add_background: bool :param use_real_part: Whether to use the real part of the eigenmode solution. :type use_real_part: bool :param complex_factor: A complex factor to multiply the eigenmode solution with. :type complex_factor: complex :param show_ef_panel: Whether to show the eigenfunction panel. :type show_ef_panel: bool :param kwargs: Additional keyword arguments to pass to :meth:`~matplotlib.pyplot.imshow`. :type kwargs: dict :returns: The plot object. :rtype: TemporalEvolutionPlot1D .. !! processed by numpydoc !! .. py:function:: plot_2d_slice(ds: pylbo.data_containers.LegolasDataSet, omega: Union[complex, list[complex], numpy.ndarray], ef_name: str, u2: Union[float, numpy.ndarray], u3: Union[float, numpy.ndarray], time: float, slicing_axis: str, figsize: tuple[int, int] = None, add_background: bool = False, use_real_part: bool = True, complex_factor: complex = None, show_ef_panel: bool = True, polar: bool = False, **kwargs) -> pylbo.visualisation.modes.cartesian_2d.CartesianSlicePlot2D Plot a 2D spatial view of the eigenmode solution, i.e. :math:`f(u_1, u_2, u_3, t) = f_1(u_1) \exp\left(ik_2u_2 + ik_3u_3 - i\omega t\right)`, for a particular set of coordinates. If `slicing_axis = 'z'` then a 2D view is created for a given slicing point along the 'z'-axis (hence a 'xy'-view), for `slicing_axis = 'y'` a 'xz'-view will be created. The given spatial coordinates `u2` and `u3` must be consistent with the slicing axis. For cylindrical geometries slices in both Cartesian and polar coordinates can be created. :param ds: The data set containing the eigenfunction. :type ds: LegolasDataSet :param omega: The (approximate) eigenvalue of the mode(s) to visualise. :type omega: complex, list[complex], np.ndarray :param ef_name: The name of the eigenfunction to visualise. :type ef_name: str :param u2: The y or :math:`\theta` coordinate of the eigenmode solution. :type u2: float, np.ndarray :param u3: The z coordinate of the eigenmode solution. :type u3: float, np.ndarray :param time: The time at which to visualise the eigenmode solution. :type time: float :param slicing_axis: The axis to slice the 2D view along, either 'z', 'y' or 'theta' :type slicing_axis: str :param figsize: The size of the figure. :type figsize: tuple[int, int] :param add_background: Whether to add the equilibrium background to the plot. :type add_background: bool :param use_real_part: Whether to use the real part of the eigenmode solution. :type use_real_part: bool :param complex_factor: A complex factor to multiply the eigenmode solution with. :type complex_factor: complex :param show_ef_panel: Whether to show the eigenfunction panel. :type show_ef_panel: bool :param polar: Whether to use polar coordinates for the 2D view. Only used if the dataset geometry is cylindrical. Default is False. :type polar: bool :param kwargs: Additional keyword arguments to pass to the plotting function. :type kwargs: dict :returns: **p** -- The plot object. :rtype: CartesianSlicePlot2D or CylindricalSlicePlot2D .. !! processed by numpydoc !! .. py:function:: plot_3d_slice(ds: pylbo.data_containers.LegolasDataSet, omega: Union[complex, list[complex], numpy.ndarray], ef_name: str, u2: Union[float, numpy.ndarray], u3: Union[float, numpy.ndarray], time: float, slicing_axis: str, figsize: tuple[int, int] = None, add_background: bool = False, use_real_part: bool = True, complex_factor: complex = None, **kwargs) -> pylbo.visualisation.modes.cartesian_3d.CartesianSlicePlot3D Plot a 3D spatial view of the eigenmode solution, i.e. :math:`f(u_1, u_2, u_3, t) = f_1(u_1) \exp\left(ik_2u_2 + ik_3u_3 - i\omega t\right)`, for a particular set of coordinates. Several 2D slices are superimposed on each other for every value of :math:`u_3`. :param ds: The data set containing the eigenfunction. :type ds: LegolasDataSet :param omega: The (approximate) eigenvalue of the mode(s) to visualise. :type omega: complex, list[complex], np.ndarray :param ef_name: The name of the eigenfunction to visualise. :type ef_name: str :param u2: The y or :math:`\theta` coordinate of the eigenmode solution. :type u2: float, np.ndarray :param u3: The z coordinate of the eigenmode solution. :type u3: float, np.ndarray :param time: The time at which to visualise the eigenmode solution. :type time: float :param slicing_axis: The axis to slice the 2D view along, either 'z', 'y' or 'theta' :type slicing_axis: str :param figsize: The size of the figure. :type figsize: tuple[int, int] :param add_background: Whether to add the equilibrium background to the plot. :type add_background: bool :param use_real_part: Whether to use the real part of the eigenmode solution. :type use_real_part: bool :param complex_factor: A complex factor to multiply the eigenmode solution with. :type complex_factor: complex :param kwargs: Additional keyword arguments to pass to the plotting function. :type kwargs: dict :returns: **p** -- The plot object. :rtype: CartesianSlicePlot3D or CylindricalSlicePlot3D .. !! processed by numpydoc !! .. py:function:: prepare_vtk_export(ds: pylbo.data_containers.LegolasDataSet, omega: Union[complex, list[complex], numpy.ndarray], u2: numpy.ndarray, u3: numpy.ndarray, use_real_part: bool = True, complex_factor: complex = None) -> Union[pylbo.visualisation.modes.vtk_export.VTKCartesianData, pylbo.visualisation.modes.vtk_export.VTKCylindricalData] Prepares for a VTK file export of the eigenmode solution in three dimensions. Returns a :class:`VTKDataCube3D` object which can be used to generate VTK files. :param ds: The data set containing the eigenfunction. :type ds: LegolasDataSet :param omega: The (approximate) eigenvalue of the mode(s) to visualise. :type omega: complex, list[complex], np.ndarray :param u2: The y or :math:`\theta` coordinates of the eigenmode solution. :type u2: np.ndarray :param u3: The z coordinates of the eigenmode solution. :type u3: np.ndarray :param use_real_part: Whether to use the real part of the eigenmode solution. :type use_real_part: bool :returns: Object that can be used to generate VTK files. :rtype: VTKCartesianData or VTKCylindricalData .. !! processed by numpydoc !!