Update the binary and component stars upon merging within a CEE.

        The binary's state and event are updated along with the donor and
        companion star masses and radii corresponding to a merger event.

        Parameters
        ----------
        binary: BinaryStar object
            The binary system
        donor : SingleStar object
            The donor star
        comp_star : SingleStar object
            The companion star
        m1_i : float
            Mass of the donor upon entering a CE (in Msun)
        m2_i : float
            Mass of the companion upon entering a CE (in Msun)
        donor_type : string
            Descriptor for the stellar type of the donor's core
        comp_type : string
            Descriptor for the stellar type of the companion or it's core
        Mejected_donor : float
            How much mass is ejected from the donor upon merger (in Msun)
        Mejected_comp : float
            How much mass is ejected from the companion upon merger (in Msun)
        verbose : bool
            In case we want information about the CEE.


Get a decorator to mark a method as the handler for a particular VCS.


Train all classes and columns with the specified list of regressors.

        Parameters
        ----------
        regressor_names : list
            List of strings specifying all the regressors to train.
        verbose : optional, bool
            Print useful information.

        Returns
        -------
        None


Train a regression algorithm.

        Implemented regressors:
            LinearNDInterpolator ('linear', ...)
            Radial Basis Function ('rbf', ...)
            GaussianProcessRegressor ('gp', ...)

        >>> rg = Regressor( TableData_object )
        >>> rg.train('linear', di = np.arange(0, Ndatapoints, 5), verbose=True)

        Trained regressor objects are uniquely defined by the algorithm used to
        train, the data set used to train (grouped by class), and finally the
        output column (there could be more than one). This motivates the data
        structure for storing the regressor objects as follows:
            Algorithm -> Class -> Output Column -> Object
        Here is more realistic example of what it could look like:
          {RBF: {"class_1": {"output_1": {instance of scipy.interpolate.rbf}}}}

        Parameters
        ----------
        regressor_name : string
            Name of regressor to train.
        class_keys : list
            List of class(es) to train on.
        col_keys : list or None
            For a given class, what columns to train on.
            If None, it trains on all columns in one class.
        di : optional, array
            Array indicies of data used to train (training on a subset).
            If None (default) - train on whole data set
        verbose : optional, bool
            Print statements with more information while training.

        Returns
        -------
        None

        Note: You can train mutliple classes at once as long as they have the
        same columns specified in col_keys.


Check for NaNs and user-specified `undefined_p_change_val`.

        Given a set of training data, the output is checked for nans and
        user-specified undefined_p_change_val. All instances are removed
        before training. Returns the new training input and output data:
        training_x, training_y.

        Parameters
        ----------
        training_x : ndarray
            Input data to clean.
        training_y : array
            Ouptut data to clean.
        class_key : str
            Which class is being cleaned.
        col_key : str
            Which column is being cleaned.

        Returns
        -------
        training_x : ndarray
            Cleaned input data free of undefined values.
        training_y : array
            Cleaned output data free of undefined values.


Fit linear ND interpolator.

        Implementation from: scipy.interpolate.LinearNDInterpolator
        (https://docs.scipy.org/doc/scipy/reference/interpolate.html)

        Parameters
        ----------
        class_keys : list
            List of classes to train on.
        col_keys : list
            List of columns in the class to train on.
            If multiple classes are given, it is assumed they all contain
            the supplied columns.
        data_interval : array, optional
            Array indicies of data used to train (training on a subset).
            If None (default) train on whole data set
        verbose : bool, optional
            Print statements with more information while training.

        Returns
        -------
        regressor_holder : dict
            Ordered by class specific data and then by column. Nested
            dictionary maps to a trained linearNDinterpolator object.


Fit RBF interpolator - binary classification (one against all).

        Implementation from: scipy.interpolate.Rbf
        (https://docs.scipy.org/doc/scipy/reference/interpolate.html)

        Parameters
        ----------
        class_keys :
            List of classes to train on.
        col_keys :
            If multiple classes are given, it is assumed they all contain
            the supplied columns.
        data_interval : array, optional
            Array indicies of data used to train (training on a subset).
            if None (default) train on whole data set
        verbose : bool, optional
            Print statements with more information while training.

        Returns
        -------
        regressor_holder : dict
            Ordered by class specific data and then by column. Nested
            dictionary maps to a trained RBF object.


Fit a Gaussian Process regressor.

        Implementation from: sklearn.gaussian_process
        (https://scikit-learn.org/stable/modules/gaussian_process.html)

        Parameters
        ----------
        class_keys :
            List of classes to train on.
        col_keys :
            If multiple classes are given, it is assumed they all contain
            the supplied columns.
        data_interval : array, optional
            Array indicies of data used to train (training on a subset).
            if None (default) train on whole data set
        verbose : bool, optional
            Print statements with more information while training.

        Returns
        -------
        regressor_holder : dict
            Ordered by class specific data and then by column. Nested
            dictionary maps to a trained GaussianProcessRegressor object.


Evaluate the trained regressor at test_input and return predictions.

        If using GaussianProcessRegressor, the std is optionally returned.


Show (print) the structure of the regression data.


Our method of cross validation for regression.

        Train on a subset of the data and predict values for the rest.
        Then calculate the difference between the true and predicted value.

        Parameters
        ----------
        regressor_name :
            Regressor name to use for analysis.
        class_key :
            Class key to take differences.
        col_key :
            Column key to take differences.
        alpha : float
            Fraction of data set used to find differences.
        verbose : bool, optional
            Print useful information.

        Returns
        -------
        percent_diffs : array
            Percent difference.
        diffs : array
            Absolute difference.


For multiple calls to cross_validate.

        Parameters
        ----------
        regressor_name : str
            Name of regression algorithm to use.
        class_key : str, class_dtype(int or other)
            Name of class data to use.
        col_keys : str
            Column keys to cross validate on.
        alpha : float
            Fraction of data set to cross validate on.
        cutoff : float
            Sets the cutoff percentage at which to calculate
            the fraction of the data set above or below.
        vebose : bool, optional
            Print useful diagnostic information.

        Returns
        -------
        p_diffs_holder : ndarray
            Percent differencs per column.
        attr_holder : ndarray
            Contains the number of points outside the cutoff, mean,
            and standard deviation of the percent difference calculations.


Plot all regression data from the chosen class.

        Parameters
        ----------
        class_name : str
            Specify what class data will plotted.

        Returns
        -------
        matplotlib figure
            Plots with all regression data for a given class.


Trains multiple classifiers at once.

        Parameters
        ----------
        classifier_names : list
            List of strings specifying classification algorithms to use.

        Returns
        -------
        None


Train a classifier.

        Implemented classifiers:
            LinearNDInterpolator ('linear', ...)
            Radial Basis Function ('rbf', ...)
            GaussianProcessClassifier ('gp', ...)

        >>> cl = Classifier( TableData_object )
        >>> cl.train('linear', di = np.arange(0, Ndatapoints, 5), verbose=True)

        Parameters
        ----------
        classifier_name : str
            Name of classifier to train.
        di : array_int, optional
            Array indicies of data used to train (training on a subset).
            if None - train on whole data set
        train_cross_val : bool, optional
            For storing regular trained interpolators and cross val
            interpolators. Used in the cross_validate() method.
            if False - save normal interpolators
            if True  - save cross validation interpolators
        verbose: bool, optional
            Print statements with more information while training.

        Returns
        -------
        None


Fit linear ND interpolator - binary one-against-all classification.

        Implementation from: scipy.interpolate.LinearNDInterpolator
        (https://docs.scipy.org/doc/scipy/reference/interpolate.html)

        Parameters
        ----------
        data_interval : array_int, optional
            Array indicies of data used to train (training on a subset).
            if None (default) train on whole data set
        verbose : bool, optional
            Print statements with more information while training.

        Returns
        -------
        binary_classifier_holder : dict
            Sorted by class, each key maps to a trained linearNDinterpolator
            object.


Fit RBF interpolator - binary classification (one against all).

        Implementation from: scipy.interpolate.Rbf
        (https://docs.scipy.org/doc/scipy/reference/interpolate.html)

        Parameters
        ----------
        data_interval : array_int, optional
            Array indicies of data used to train (training on a subset).
            if None (default) train on whole data set
        verbose : bool, optional
            Print statements with more information while training.

        Returns
        -------
        binary_classifier_holder : dict
            Sorted by class, each key maps to a trained RBF object.


Fit a Gaussian Process classifier.

        Implementation from: sklearn.gaussian_process
        (https://scikit-learn.org/stable/modules/gaussian_process.html)

        Parameters
        ----------
        data_interval : array_int, optional
            Array indicies of data used to train (training on a subset).
            if None (default) train on whole data set
        my_kernel : kernel
            Set the kernel for the GPC.
        n_restarts : int
            Number of restarts for the GPC.
        verbose : bool, optional
            Print statements with more information while training.

        Returns
        -------
        binary_classifier_holder : array_like
            Sorted by class, each key maps to a trained
            GaussianProcessClassifier object.


Given an array of probabilities, remove the nans.

        Return where not nan
        which is useful for finding good or bad values.


Return probability that a given input corresponds to a class.

        The probability is calculated using trained classifiers.

        Parameters
        ----------
        classifier_name : str
            Name of classifier to train.
        test_input : ndarray
            N dimensional inputs to be classified.
            The shape should be N_points x N_dimensions.
        verbose : optional, bool
            Print useful information.

        Returns
        -------
        normalized_probs : ndarray
            Array holding the normalized probability for a point to be in any
            of the possible classes. Shape is N_points x N_classes.
        where_not_nan: ndarray
            Indicies of the test inputs that did not result in nans.


Cross validate classifiers on data from TableData object.

        For each iteration, the classifiers specified are all trained
        and tested on the same random subset of data.

        Parameters
        ----------
        classifier_names : array
            Names of classifiers to train.
        alpha : float
            Fraction of data set to use for training. (0.05 = 5% of data set)
        verbose : bool, optional
            Print statements with more information while training.

        Returns
        -------
        percent_correct: ndarray
            Percent correct classification on (1-alpha)% of the data set.
            Element order matches the order of classifier_names.
        time_to_train : ndarray
            Time to train classifiers on a data set. Element order matches
            the order of classifier_names.


Script for running many instances of the method `cross_validate()`.

        Cross validation score and timing data produced are saved locally.

        ! Time to train GaussianProcessClassifier becomes large for num
        training points > 1000. !

        Files saved every 5 iterations to prevent loss of data for large
        N_iterations.
        Known expection occurs in GP classifier for low alpha due to data set
        with only one class.

        Parameters
        ----------
        interp_type : array_str
            Names of classifiers to train.
        alphas : array_floats
            Fractions of data set to use for training. (0.05 = 5% of data set)
            (ex. [0.01, 0.02, ...])
        N_iterations : int
            Number of iterations to run cross validation at a given alpha.
        folder_path : str
            Folder path where to save cross validation and timing data
            ("your_folder_path/").

        Returns
        -------
        None


Make the maximum classification probablity plot.

        Not generalized yet to slice along redundant axes.


Parse an ini file to run psy-cris method 'get_new_query_points'.

    Parameters
    ---------
    path : str
        Path to ini file.

    Returns
    -------
    all_kwargs_dict : dict
        Nested dictionary of parsed inifile kwargs.


Handle proposals where only one point in class and regression is needed.

    Handles proposals where only one point exists for a class and regression is
    requested. Otherwise the interpolators will fail. Drawn from a gaussian
    around the point with length scale given by the average distance between
    nearest neighbors (in each axis).

    Params
    ------
    data : ndarray
        Data to train the NearestNeighbors class on.
    n_neighbors : int
        Number of neighbors to use when finding average distance.
    neighbor : instance of NearestNeightbors class
        For passing your own object.

    Returns
    -------
    proposed_points : array
        Points sampled around classes with 1 value.
        Points are distributed as evenly as possible across all 1 value
        classes by default.
        Returns None in case of no small classes found.


Run cris algorithm iteratively.

    For a given number of starting and ending points, run the cris algorithm
    iteratively in step sizes of new_points_per_iter. After each iteration,
    query points are identified using the original 2D snythetic data set.

    Parameters
    ----------
    N_starting_points : int
        Number of starting points to being cris iterations on a 2D grid
        sampled from the original 2D synthetic data set.
    N_final_points : int
        Number of points to converge to after iterating with cris.
    new_points_per_iter : int, array-like
        For every iteration the number of new query points for cris to propose.
    threshold : float
        New query points are ommited from the next iteration if their euclidean
        distance to other data points is less than the threshold.
    jitter : bool
        Default False, for the starting grid jitter about the center randomly
        in the range of +/- the 1/2 the bin width in each dimesnion.
    verbose : bool
        Print useful things.
    show_plots : bool
        Show plots of proposed points and training points each iteration.
    all_kwargs : dict
        Dictionary of all_kwargs passed to get_new_query_points defining
        how every part of the cris algorithm is implemented.


Plot proposed points in 2-D space.


Plot proposed points in 3-D space.


Check euclidean distance between the original and proposed points.

    Proposed points a distance >= threshold are accepted.

    Parameters
    ----------
    original : ndarray
        Original points previously run.
    proposed : ndarray
        Proposed points for new simulations.
    threshold : float, optional
        The theshold distance between acceptance and rejection.

    Returns
    -------
    proposed_above_thresh_for_all_original : bool, array
        True if the distance between the proposed point is >= threshold.

    Notes
    -----
    The purpose of this function is to not propose points that are some
    threshold away from already accepted points.


Calculate accuracy and confusion matrix.

    Given a list of pandas DataFrames, iterate over them and
    calculate the accuracy and confusion matrix for synthetic data sets.

    Parameters
    ----------
    dfs_per_iter : list
        List of pandas DataFrames containing training data
        to train an classifier on and then compare to the
        true background distribution.
    cls_name : str, optional
        Name of classifier to train.
    resolution : int, optional
        Density per axis of the grid used to oversample the true background.
    verbose : bool, optional
        Print some helpful info.

    Returns
    -------
    acc_per_iter : array
        Array conatining overall accuracy of interpolator
        per iteration of training data.
    conf_matrix_per_iter : list
        List of confusion matricies per iteration. Calculated
        using 'get_confusion_matrix'.
    regr_acc_per_iter : list
        List of regression accuracy terms.


Calculate the the fractional change at which the cdf_cutoff is below.

    For a given distribution of absolute fractional differences: calculate the
    the fractional change at which the cdf_cutoff is below.

    For 50% of the data set, the range of frac diffs is [0,?].

    (What is not being asked: For a frac diff of 10% what fraction of the data
    has a frac diff <= that number. )


r"""2-dimensional analytic target distribution for testing MCMC/PTMCMC.

        The function:
        $\frac{16}{3\pi} \left( \exp\left[-\mu^2 - (9 + 4\mu^2 + 8\nu)^2\right]
        + \frac{1}{2} \exp\left[- 8 \mu^2 - 8 (\nu-2)^2\right] \right)$

        Parameters
        ----------
        name : str
            Name of algorithm to use. For this method None.
        args : array
            2D location to get the value of the function.
        **kwargs
            Kwargs for more complex target distributions.

        Returns
        -------
        array or float


r"""Target distribution using classification.

        $f(x) = 1 - max[P_{\rm class}(x)]$

        Parameters
        ----------
        classifier_name : str
            String to specify the trained classification algorithm to use.
        position : array
            Single location in parameter space for the target distribution to
            be evaluated at.
        **kwargs
            TD_BETA : float
                Exponent of target distribution - $f(x)^{\rm TD_BETA}$
                Used for smoothing or sharpening.
            TD_verbose : bool
                Extra print output every method call.

        Returns
        -------
        array
            If classification probability is Nan: f(x) = 1E-16


r"""Target distribution using both classification & regression.

        Classification: $1 - max[P_{\rm class}(x)]$
        Regression: $ A_0 \log( A_1* abs( max[APC_n [loc]]) + 1 )$

        Parameters
        ----------
        names : list like
            Iterable containing the two strings specifying the classification
            and regression algorithm to use.
        args : array
            Position in parameter space to evaluate the target distribution at.
        **kwargs
            TD_A1 : float, optional
                Scaling factor inside the Log regression error term.
                (Default = 0.5)
            TD_TAU : float, optional
                Relative weight of classification to regression term.
                (Default = 0.5)
            TD_BETA : float, optional
                Exponent of the entire target distribution. Used
                for smoothing or sharpening the distribution. Default is 1.
            TD_verbose : bool, optional
                Print more diagnostic information.

        Rreturns
        --------
        array


Save PTMCMC output chain_step_history inside the sampler object.


Run a Paralel Tempered MCMC with user-specified target distribution.

        Calls the method `run_MCMC`.

        Parameters
        ----------
        T_max : float
            Sets the maximum temperature MCMC in the chain.
        N_tot : int
            The total number of iterations for the PTMCMC.
        target_dist : callable
            The target distribution to sample.
            Must take arguments (method_name, location_to_eval)
            (A 2D analytic function is provided - analytic_target_dist)
        classifier_name : str, list
            A single string or list of strings specifying the interpolator to
            use for classification or classification & regression respectively.
        init_pos : array
            Initial position of walkers in each axis. Default is the median of
            the input data in TableData.
        N_draws_per_swap : int, optional
            Number of draws to perform for each MCMC before swap proposals.
        c_spacing : float, optional
            Sets the spacing of temperatures in each chain.
            T_{i+1} = T_{i}^{1/c}, range: [T_max , T=1]
        alpha : float, optional
            Sets the standard deviation of steps taken by the walkers. Default
            is 1/5 the range of training data from TableData.
        upper_limit_reject : float, optional
            Sets the upper limit of rejected points.
        verbose : bool, optional
            Useful print statements during execution.

        Returns
        -------
        chain_step_history : dict
            Hold the step history for every chain. Keys are integers that range
            from 0 (max T) to the total number of chains -1 (min T).
        T_list : array
            Array filled with the temperatures of each chain from max to min.

        Notes
        -----
        There is a zero prior on the PTMCMC outside the range of training data.


Run a Markov chain Monte Carlo given a target distribution.

        Parameters
        ----------
        N_trials : int
            Number of proposals or trial steps to take before stopping.
        alpha : float
            Related to the step size of the MCMC walker.
            Defines the standard deviation of a zero mean normal
            from which the step is randomly drawn.
        step_history : list
            Initial starting location in parameter space.
            Could contain an arbitrary number of previous steps
            but a walker will start at the last step in the list.
        targe_dist : callable
            The target distribution to sample.
            Must take arguments ( method_name, element_of_step_history )
            (A 2D analytic function is provided - TD_2d_analytic)
        classifier_name : str
            Name of interpolation technique used in the target_dist.
        T : float, optional
            Temperature of the MCMC.
        upper_limit_reject : int, optional
            Sets the maximum number of rejected steps before the MCMC
            stops walking. Avoiding a slowly converging walk with few
            accepted points.

        Returns
        -------
        step_history : array
            An array containing all accepted steps of the MCMC.
        accept : int
            Total number of accepted steps.
        reject : int
            Total number of rejected steps.

        Notes
        -----
        Assumes uniform priors and a symetric jump proposal (gaussian).


Take steps and normalize [0,1] according to min/max in each axis.

        The max and min are taken from the original data set from TableData.


Rescale step history.

        Take normed steps from [0,1] and return their value
        in the original range of the axes based off the range in TableData.


Perform multivariate normal density logic on a given step history.

        This is a simplified version of the method 'do_density_logic'.
        It assumes that every accepted point will have the same exact MVN.

        Each proposal distribution starts with the training set from TableData
        which keeps training data from being proposed again.

        Parameters
        ----------
        step_history : ndarray
            List of points from a PTMCMC or MCMC. (posterior)
        N_points : int
            Number of points desired to be drawn from the posterior but may not
            actually be the number of points accepted. Contributes to the
            length scale of the MVN distribution of accepted points
            (along with kappa).
        Kappa : float
            Scaling factor that sets the initial size of the MVN for accepted
            points. This should be proportional to the filling factor of the
            area of iterest described by the target distribution used to
            create the posterior.
        var_mult : float, ndarray, optional
            Variance multiplier for the MVN of accepted points.
        add_mvns_together : bool, optional
            Add MVNs together when creating the accepted point distribution.
        include_training_data : bool, optional
            Include the trainind data in the target distribution before
            sampling.
        verbose : bool, optional
            Print useful diagnostic information.

        Returns
        -------
        accepted_points : ndarray
            Accepted points from the posterior to be labled by the user.
            (query points)
        rejected_points : ndarray
            Rejected points from the posterior.

        Notes
        -----
        The accepted laguage here is indicative of query points for the oracle
        to label in an active learning scheme. It is not accepted vs rejected
        normally used for MCMC.


Do the density based of the normal gaussian kernel on each point.

        This method automatically takes out the first 5% of steps of the MCMC
        so that the initial starting points are not chosen automatically
        (if you start in a non-ideal region). Wait for the burn in.

        Parameters
        ----------
        step_history : ndarray
        N_points : int
        Kappa : float
        shuffle : bool, optional
        norm_steps : bool, optional
        var_mult : float, optional
        add_mvns_together : bool, optional
        verbose : bool, optional

        Returns
        -------
        accepted_points : ndarray
        rejected_points : ndarray
        accepted_sigmas : ndarray


Plot the proposed / accepted points over the step history.


Make a `step number` vs. `position of a sampler in an axis` plot.

        This function makes titles assuming you are using the data
        from the classifier.


Get the average distance to the nearest neighbors in the data set.

    (NearestNeighbors from sklearn.neighbors)

    Parameters
    ----------
    data : ndarray
        Data to train the NearestNeighbors class on.
    n_neighbors : int
        Number of neighbors to use when finding average distance.
    neighbor : instance of NearestNeightbors class
        For passing your own object.

    Returns
    -------
    avg_dist : array
        The average distance between nearest neighbors.
    g_indi : array
        Indicies that correspond to the nearest neighbors.


Calculate the average fractional change in a given data set.

    The method uses the N nearest neighbors (calculated beforehand).

    Parameters
    ----------
    data : ndarray
        Data set to calculate percent change.
    where_nearest_neighbors : dict
        Indicies in data for the n nearest neighbors in input space.
    undefined_p_change_val : optional
        For output with an undefined percent change (zero value), this kwarg
        defines what is put in its place. Defaults to nan.

    Returns
    -------
    avg_p_change_holder : ndarray
        Each element conatins the average percent change for a given number of
        neighbors. If any output values are 0, then a nan is put in place of a
        percent change.


Help clean up verbose print statements and storing info.

        By default, store the passed info_string regardless of verbose_bool.


Find the N nearest neighbors of a given set of arbitrary points.

        Given a set of arbitrary input points, find the N nearest neighbors
        to each point, not including themselves. Can also return average
        distance from a point to its N nearest neighbors.

        Parameters
        ----------
        input_data : ndarray, pandas DataFrame
            Data points where their nearest neighbors will be found
        n_neighbors : list
            List of integers with number of neighbors to calculate
        neighbor : instance of NearestNeightbors class
            For passing your own object.
        return_avg_dists : bool, optional
            If True, return the a dictionary with average distances between
            the N nearest neighbors listed in 'n_neighbors'.
        **kwargs
            class_key : str
                If a DataFrame is given, specifies class column name.

        Returns
        -------
        where_nearest_neighbors : dict
            Dictionary containing the n nearest neighbors for every point
            in the input data.
        avg_distances : dict
            Returned if return_avg_dists is True.
            The average distances between the nearest neighbors.


Return a regular or hidden class variable.


Print info for the instance of TableData object.

        For output descriptions see the method 'get_info()'.


Plot the 3D classification data in a 2D plot.

        3 input axis with classification output.

        Parameters
        ----------
        axes: list, optional
            By default it will order the axes as [x,y,z] in the original order
            the input axis were read in. To change the ordering, pass a list
            with the column names.
            Example:
            The default orderd is col_1, col_2, col_3.
            To change the horizontal axis from col_1 to col_2 you would use:
                'axes = ["col_2", "col_1", "col_3"]'
        fig_size: tuple, optional, default = (4,5)
            Size of the figure. (Matplotlib figure kwarg 'fig_size')
        mark_size: float, optional, default = 12
            Size of the scatter plot markers. (Matplotlib scatter kwarg 's')
        which_val: int, default = 0
            Integer choosing what unique value to 'slice' on in the
            3D data such that it can be plotted on 2D.
            (If you had x,y,z data you need to choose a z value)
        save_fig: bool, default = False
            Save the figure in the local directory.
        plt_str: str, default = '0'
            If you are saving multiple figures you can pass a string
            which will be added to the end of the default:
            "data_plot_{plt_str}.pdf"
        color_list: list, default = None

        Returns
        -------
        matplotlib figure


Plot classification data on a given axis and figure.

        Parameters
        ----------
        fig : Matplotlib Figure object
            Figure on which the plot will be made.
        ax : Matplotlib Axis object
            Axis on which a scatter plot will be drawn.
        axes_keys : list
            List containing two names of input data columns to use as
            horizontal and verital axes.
        my_slice_vals : optional, list, dict
            List giving values on which to slice in the axes not being plotted.
            Default (None) uses the first unique value found in each axis.
            If instead of individual values, a range is desired (e.g. 10 +/- 1)
            then a dict can be given with integer keys mapping to a tuple with
            the lower and upper range. ( e.g. {0:(9,11)} )
        my_class_colors : optional, list
            List of colors used to represent different classes. Default (None)
            uses the default class colors.
        return_legend_handles : optional, bool
            Returns a list of handles that connect classes to colors.
        verbose : optional, bool
            Print useful information during runtime.
        **kwargs : optional
            Kwargs for matplotlib.pyplot.scatter() .

        Returns
        -------
        fig : Matplotlib Figure object
            Figure object.
        ax : Matplotlib Axis object
            Updated axis after plotting.
        handles : optional, list
            List of legend handles connecting classes and their colors.
            Returned if 'return_legend_handles' is True. Default is False.


Unique classes 1,2,3,4,6,8 for a total of 6 classes. This nicely matches
    the colormap Dark2 for plotting.


Run a psy-cris sequence on synthetic data from the command line.

    Parameters
    ----------
        N/A

    Notes
    -----
        This code is used in the work of:
        Rocha et al. 2022, ApJ, 938, 64. doi:10.3847/1538-4357/ac8b05


Check if the input can be converted to a float.


Compute the effective temperature give the luminosity and radius.


Evaluate the zero age main sequence radius [1]_.

    Parameters
    ----------
    m : array_like
        The masses of the stars in Msun.
    z : float
        The metallicity of the star.

    Returns
    -------
    ndarray
        Array of same size as `m` containing the ZAMS radii of the stars (Rsun)

    References
    ----------
    .. [1] Tout C. A., Pols O. R., Eggleton P. P., Han Z., 1996, MNRAS, 281,
        257


Approximate the Roche lobe radius from [1]_.

    Parameters
    ----------
    m1 : float, ndarray of floats
        the mass of the star for which we calculate the Roche lobe
    m2 : float, ndarray of floats
        the mass of the companion star
    a_orb : float, ndarray of floats
        Orbital separation. The return value will have the same unit.

    Returns
    -------
    float, ndarray of floats
        Roche lobe radius in similar units as a_orb
    References
    ----------
    .. [1] Eggleton, P. P. 1983, ApJ, 268, 368


Check if either star in a binary is overfilling its Roche lobe.

    It uses roche_lobe_radius and the binary separation to determine if either
    star is overfilling their Roche lobe.

    Parameters
    ----------
    m1 : float
        Mass of star 1 (in Msun)
    r1 : float
        Radius of star 1 (in Rsun)
    m2 : float
        Mass of star 2 (in Msun)
    r2 : float
        Radius of star 2 (in Rsun)
    separation : float
        Orbital separation (in Rsun)
    tolerance : float
        The tolerance to count Roche-lobe filling as Roche-lobe overflow (in Rsun).

    Returns
    -------
    RLO: bool
        Whether either star in the binary is overfilling its Roche Lobe.


Apply the Third Kepler law.

    Parameters
    ----------
    period_days : float
        Orbital period in days.
    m1_solar : float
        Mass of the one of the stars, in solar units.
    m2_solar : float
        Mass of the other star, in solar units.

    Returns
    -------
    float
        The separation of the binary in solar radii.


Apply the Third Kepler law.

    Parameters
    ----------
    separation : float
        Orbital separation (semi-major axis) in Rsun.
    m1 : float
        Mass of one of the stars in solar units.
    m2 : type
        Mass of the other star in solar units.

    Returns
    -------
    float
        The orbital period in days.


Calculate the Eddington limit & radtiative efficiency of compact object.

    Parameters
    ----------
    binary : BinaryStar
        The binary object.

    Returns
    -------
    tuple
        The Eddington accretion limit and radiative efficiency in solar units.


Calculate the geometrical beaming of a super-Eddington accreting source
    [1]_, [2]_.

    Compute the super-Eddington isotropic-equivalent accretion rate and the
    beaming factor of a star. This does not change the intrinsic accretion onto
    the accretor and is an observational effect due to the inflated structure
    of the accretion disc that beams the outgoing X-ray emission. This is
    important for observing super-Eddington X-ray sources
    (e.g. ultraluminous X-ray sources). In case of a BH we are assuming that it
    has zero spin which is not a good approximation for high accretion rates.

    Parameters
    ----------
    binary : BinaryStar
        The binary object.

    Returns
    -------
    tuple
        The super-Eddington isotropic-equivalent accretion rate and beaming
        factor respcetively in solar units.

    References
    ----------
    .. [1] Shakura, N. I. & Sunyaev, R. A. 1973, A&A, 24, 337
    .. [2] King A. R., 2008, MNRAS, 385, L113


Calculate the Bondi-Hoyle accretion rate of a binary [1]_.

    Parameters
    ----------
    binary : BinaryStar
        The binary which accretion rate is required.
    accretor : SingleStar
        The accretor in the binary.
    donor : SingleStar
        The donor in the binary.
    idx : int
        default: -1
    wind_disk_criteria : bool
        default: True, see [5]_
    scheme : str
        There are different options:

        - 'Hurley+2002' : following [3]_
        - 'Kudritzki+2000' : following [7]_

    Returns
    -------
    float
        The Bondi-Hoyle accretion rate in solar units.

    Notes
    -----
    An approximation is used for the accretion rate [2]_ and the wind velocity
    of the donor is moddeled as in [3]_, [6]_. Also see [4]_.

    References
    ----------
    .. [1] Bondi, H., & Hoyle, F. 1944, MNRAS, 104, 273
    .. [2] Boffin, H. M. J., & Jorissen, A. 1988, A&A, 205, 155
    .. [3] Hurley, J. R., Tout, C. A., & Pols, O. R. 2002, MNRAS, 329, 897
    .. [4] Belczynski, K., Kalogera, V., Rasio, F. A., et al. 2008, ApJS, 174,
        223
    .. [5] Sen, K. ,Xu, X. -T., Langer, N., El Mellah, I. , Schurmann, C., &
        Quast, M., 2021, A&A
    .. [6] Sander A. A. C., Vink J. S., 2020, MNRAS, 499, 873
    .. [7] Kudritzki, R.-P., & Puls, J. 2000, ARA&A, 38, 613


Generate a sample from a 1d PDF using the acceptance-rejection method.

    Parameters
    ----------
    x : array_like
        The x-values of the PDF.
    y : array_like
        The y-values of the PDF.
    size : int
        The number of random numbers to generate.
    x_lim : array float
        The boundary where the pdf function is defined if passed as pdf.
    pdf : func
        The pdf function

    Returns
    -------
    ndarray
        An array with `size` random numbers generated from the PDF.


Sample from a PDF using the inverse-sampling method.

    Parameters
    ----------
    x : array-like
        The x-axis coordinates of the points where the PDF is defined.
    y : array-like
        The probablity density at `x` (or a scaled version of it).
    size : int
        Number of samples to generate.

    Returns
    -------
    array
        The sample drawn from the PDF.


Sample from an empirical PDF represented by a histogram.

    Parameters
    ----------
    x_edges : array-like
        The edges of the bins of the histrogram.
    y : array-like
        The counts (or a scaled version of them) of the histogram.
    size : int
        Number of random values to produce.

    Returns
    -------
    array
        The random sample.


Read a histogram from a CSV file.

    The expected format is:

    # comment line
    x[0], x[1], ..., x[n], x[n+1]
    y[0], y[1], ..., y[n]

    where # denotes a comment line (also empty lines are ignored), and `n` is
    the number of bins (notice that the first line contains n+1 elements.)

    Usage: bin_edges, bin_counts = read_histogram_from_file("a_histogram.csv").

    Parameters
    ----------
    path : str
        The path of the CSV file containing the histogram information.

    Returns
    -------
    list of arrays
        The bin edges and bin counts of the histogram.


Compute the timescale of GW inspiral using the orbital separation.

    Based on [1]_:
        https://journals.aps.org/pr/abstract/10.1103/PhysRev.136.B1224

    Parameters
    ----------
    star1_mass : float
        Mass of star 1 in Msun.
    star2_mass : float
        Mass of star 2 in Msun.
    separation : type
        Binary separation in Rsun.
    eccentricity : type
        Eccentricity of the binary orbit. Must be 0 <= ecc <1.

    Returns
    -------
    float
        The inspiral time scale of the two black holes.

    References
    ----------
    .. [1] Peters 1964 Phys. Rev. 136, B1224


Compute the timescale of GW inspiral using the orbital period.

    Based on [1]_:
        https://journals.aps.org/pr/abstract/10.1103/PhysRev.136.B1224

    Parameters
    ----------
    star1_mass : float
        Mass of star 1 in Msun.
    star2_mass : float
        Mass of star 2 in Msun.
    orbital_separation : type
        Binary separation in Rsun.
    eccentricity : type
        Eccentricity of the binary orbit. Must be 0 <= ecc <1.

    Returns
    -------
    float
        The inspiral time scale of the two black holes in Myr.

    References
    ----------
    .. [1] Peters 1964 Phys. Rev. 136, B1224


Calculate the spin of an accreting BH under stable mass transfer.

    Based on Thorne 1974 eq. 2a.


Get the state of a SingleStar.

    Arguments
    ----------
    star: SingleStar
        The star for which the state will be computed.
    i : integer
        Index of the model for which we want to calculate the state of the
        SingleStar object. Default = -1 (the final).
    star_CO: bool
        True if we want to assume a compact object (WD/NS/BH).
        False if the state will be calculated by its attributes.

    Returns
    -------
    state : str
        state at of the star object at index i of the history.


Calculate the evolutionary states with an array of history data.

    Parameters
    ----------
    star : SingleStar
        The star for which the state will be computed.
    N : int
        Number of history steps (from the end), to calculate the state.
    star_CO : bool
        If `True`, assume it's a compact object.

    Returns
    -------
    list of str
        The state(s) in a list.


Calculate the radius of a compact object based on its type and mass.

    Parameters
    ----------
    M : float
        CO mass in Msun
    COtype : str
        Tyep of compact object. Accepted values: "BH", "NS", "WD"

    Returns
    -------
    float
        Compact object radius in solar radii


Calculate the lifetime of He burning in a star.

    Parameters
    ----------
    mass : type
        Mass of star in solar masses

    Returns
    -------
    float
        He MS time duration in yr.


Calculate the Schwarzschild Radius of BH with mass M.

    Parameters
    ----------
    M : float
        BH mass in Msun

    Returns
    -------
    float
        Schwarzschild Radius in solar radii


Short summary.

    Parameters
    ----------
    binary : type
        Description of parameter `binary`.

    Returns
    -------
    type
        Description of returned object.


Infer the star state (corresponding to termination flags 2 and 3).


Infer the mass-transfer case of a given star.

    Parameters
    ----------
    rl_relative_overflow : float
        Relative Roche lobe overflowing parameter.
    lg_mtransfer_rate : float
        The mass transfer rate in log_10.
    donor_state : str
        Values of star parameters at a specific step.
    dominating_star : bool (default: True)
        Whether this star is the orgin of the mass transfer rate.
    verbose : bool (default: False)
        In case we want additional information printed to standard output.

    Returns
    -------
    int
        The mass-transfer case integer flag.


Summarize the history of MT cases in a short list of integers.

    Parameters
    ----------
    MT_cases : array-like
        A list of the integer MT flags at sequential history steps. If the
        cases are instead given in string format they are converted first.

    Returns
    -------
    list of int
        A shorter list of integer MT flags, following these rules:
        i.   If undetermined MT at any step, it is indicated in the beginning
             (as a warning) and ignored later.
        ii.  If no RLO anywhere, then this is the only element in the returned
             list (or the second if undetermined MT at any step). Intermediate
             no-RLO phases (between RLO cases) are ignored.
        iii. Consequent same cases are reported only once (e.g., A, A, A -> A.)

    The end result is a list of integers indicating whether undetermined MT
    anywhere, if no RLO everywhere, or "changes" of MT cases.


Convert a cumulative MT sequence to a string.

    Parameters
    ----------
    cumulative_integers : list of int
        Typically, the output of `cumulative_mass_transfer_numeric`.

    Returns
    -------
    str
        A summarization of the mass-tranfer cases in the form of a string, as
        opposed to the output of `cumulative_mass_transfer_numeric` (see this
        function to understand the rules of summarization). The character `?`
        in the beginning of the string indicates undetermined MT case at some
        point of the evolution. `no_RLO` indicates no RLO at any evolutionary
        step. `caseA`, `caseB`, etc., denote the corresponding MT cases. When
        multiple cases are found, they are indicated only when the begin, and
        are combined using `/`. For example:

        ?no_RLO     : undetermined MT at few steps, otherwise no RLO.
        caseA       : case A MT only (possible no_RLO at some points).
        ?caseA/B    : undetermined MT somewhere, then case A, then case B.
        caseA/B/A   : case A, then B, and A again (although unphysical).


Get the cumulative MT string from a list of integer MT casses.

    Arguments
    ----------
    MT_cases: list of integers
        A list of MT cases.
    shift_cases: bool
        Flag to shift non-physical cases like A1 after B1 will turn into B1.

    Returns
    -------
    str
        A string summarizing the mass transfer cases.


Calculate the carbon core mass and abundance very close to ignition.

    This is important for using the Patton+2020 SN prescription

    Arguments
    ----------
    star: SingleStar object holding the history of its attributes.

    Returns
    -------
    None

    It updates the following values in the star object
    co_core_mass_at_He_depletion: float
        co_core_mass at He core depletion
        (almost at the same time as carbon core ignition)
    avg_c_in_c_core_at_He_depletion : float
        avg carbon abundance inside CO_core_mass at He core depletion
        (almost at the same time as carbon core ignition)


Find the envelope mass for different core boundary abundance thresholds.

    The results are meant to be used in collabration with the respective
    `lambda_CE_*cent`, `lambda_CE_pure_He_star_10cent`.

    Arguments
    ----------
    star: SingleStar object holding the history of its attributes.

    Returns
    -------
    None

    It updates the following values in the star object
    m_core_CE_1cent: float
        core mass (using an element abundance of 1%)
    m_core_CE_10cent: float
        core mass (using an element abundance of 10%)
    m_core_CE_30cent: float
        core mass (using an element abundance of 30%)
    m_core_CE_pure_He_star_10cent: float
        core mass (using an element abundance of 10% in He)
    r_core_CE_1cent: float
        core radius (using an element abundance of 1%)
    r_core_CE_10cent: float
        core radius (using an element abundance of 10%)
    r_core_CE_30cent: float
        core radius (using an element abundance of 30%)
    r_core_CE_pure_He_star_10cent: float
        core radius (using an element abundance of 10% in He)
    lambda_CE_1cent: float
        lambda value (using an element abundance of 1%)
    lambda_CE_10cent: float
        lambda value (using an element abundance of 10%)
    lambda_CE_30cent: float
        lambda value (using an element abundance of 30%)
    lambda_CE_pure_He_star_10cent: float
        lambda value (using an element abundance of 10% in He)


Initialize an empty record array with NaNs and empty strings.


Calculate the shell where the core is - envelope boundary.

    Parameters
    ----------
    donor_mass : array
        Profile column of enclosed mass of the star.
    donor_star_state : string
        The POSYDON evolutionary state of the donor star
    profile : numpy.array
        Donor's star profile from MESA
    mc1_i : float
        core mass and total mass of the donor star.
    core_element_fraction_definition : float
        The mass fraction of the envelope abundant chemical element at
        the core-envelope boundary to derive the donor's core mass from
        the profile
    CO_core_in_Hrich_star: Bool
        This should be true if we want to calculate the boundary of CO core in
        a H-rich star (and not of the helium core).

    Returns
    -------
    ind_core : int
        The value of the cell position of the core - envelope boundary, at the
        donor's MESA  profile (for a profile that starts from the surface).
        More specifically, it returns the index of the first cell (starting
        from the surface), that the elements conditions for the core are met.
        - Returns 0 for a star that is all core
        - Returns -1 for a star that is all envelope.


Calculate analytically the period widening due to wind mass loss [1]_.

    Parameters
    ----------
    M_current : float
        Current mass of the mass losing star (Msun)
    M_init : float
        Initial mass of the mass losing star when the calculation starts (Msun)
    Mcomp : float
        (Constant) mass of the companion star (Msun)
    P_init : float
        Initial binary period when the calculation starts (days)

    Returns
    -------
     float
        Current binary period  in days
    References
    ----------
    .. [1] Tauris, T. M., & van den Heuvel, E. 2006, Compact stellar X-ray
        sources, 1, 623


Calculate analytically the separation widening due to wind mass loss [1]_.

    Parameters
    ----------
    M_current : float
        Current mass of the mass losing star (Msun)
    M_init : float
        Initial mass of the mass losing star when the calculation starts (Msun)
    Mcomp : float
        (Constant) mass of the companion star (Msun)
    A_init : float
        Initial binary separation when the calculation starts (Rsun)

    Returns
    -------
     float
        Current binary separation  in Rsun
    References
    ----------
    .. [1] Tauris, T. M., & van den Heuvel, E. 2006, Compact stellar X-ray
        sources, 1, 623.


Change the binary period after a semi-detached stable MT phase.

    Calculated in Sorensen, Fragos et al.  2017A&A...597A..12S.
    Note that MT efficiencies are assumed constant (i.e., not time-dependent)
    throughout the MT phase.

    Parameters
    ----------
    period_i : float
        Initial period
    Mdon_i: float
        Initial donor mass
    Mdon_f: float
        Final donor mass (should be in the same unit's of Mdon_i)
    Mdon_i: float
        Initial accretor's mass (should be in the same unit's of Mdon_i)
    alpha : float [0-1]
        Fraction of DM_don (= Mdon_i - Mdon_f) from the donor,
        lost from the donor's vicinity
    beta : float [0-1]
        Fraction of Mdot from the L1 point (= (1-alpha)*DM_don),
        lost from the accretor's vicinity.
        The final accreted rate is (1-beta)(1-alpha)*DM_don

    Returns
    -------
    period_f : float
        final period at the end of stable MT, in the same units as period_i


Interpolate quantities between two star profile shells.


Calculate common-enevelope lambda from the profile of a star.

     We also pass a more accurate calculation of the donor core mass for the
     purposes of common-envelope evolution.

    Parameters
    ----------
    profile : numpy.array
        Donor's star profile from MESA
    donor_star_state : string
        The POSYDON evolutionary state of the donor star
    common_envelope_option_for_lambda : str
        Available options:
        * 'default_lambda': using for lambda the constant value of
        common_envelope_lambda_default parameter
        * 'lambda_from_profile_gravitational': calculating the lambda
        parameter from the donor's profile by using the gravitational
        binding energy from the surface to the core
        (needing "mass", and "radius" as columns in the profile)
        * 'lambda_from_profile_gravitational_plus_internal': as above
         but taking into account a factor of common_envelope_alpha_thermal *
         internal energy too in the binding energy (needing also "energy" as
         column in the profile)
        * 'lambda_from_profile_gravitational_plus_internal_minus_recombination'
        as above but not taking into account the recombination energy in the
        internal energy (needing also "y_mass_fraction_He", "x_mass_fraction_H"
        "neutral_fraction_H", "neutral_fraction_He", and "avg_charge_He" as
        column in the profile)
    core_element_fraction_definition : float
        The mass fraction of the envelope abundant chemical element at
        the core-envelope boundary to derive the donor's core mass from
        the profile.
    ind_core : int
        The value of the cell position of the core - envelope boundary, at the
        donor's MESA  profile (for a profile that starts from the surface).
        More specifically, it returns the index of the first cell (starting
        from the surface), that the elements conditions for the core are met.
        It is 0 for a star that is all core and -1 for a star that is all
        envelope. If it is not given (None), it will be calculated inside the
        function.
    common_envelope_alpha_thermal : float
        Used and explained depending on the common_envelope_option_for_lambda
        option above.
    tolerance : float
        The tolerance of numerical difference in two floats when comparing
        and testing results.
    CO_core_in_Hrich_star: Bool
        This should be true if we want to calculate the boundary of CO core in
        a H-rich star (and not of the helium core).
    verbose : bool
        In case we want information about the CEE.

    Returns
    -------
    lambda_CE: float
        lambda_CE for the envelope of the donor in CEE,
        calculated from profile
    mc1_i: float
        More accurate calculation of the donor core mass for the purposes
        of CEE.
    rc1_i: float
        More accurate calculation of the donor core radius for the purposes
        of CEE.


Compute the recombination energy of H2 per shell in erg.

    Parameters
    ----------
    profile : array
        Donor's star profile from MESA
    tolerance : float
        The tolerance of numerical difference in two floats when comparing
        and testing results.

    Returns
    -------
    specific_donor_H2recomb_energy : array
        recombination energy of H2 per shell in ergs


Compute the recombination energy per shell in erg.

    Parameters
    ----------
    profile : numpy.array
        Donor's star profile from MESA
    tolerance : float
        The tolerance of numerical difference in two floats when comparing
        and testing results.

    Returns
    -------
    specific_donor_recomb_energy : array
        recombination energy per shell in ergs


Calculate the recombination energy per shell.

    Parameters
    ----------
    x_mass_fraction_H : array
        Mass fraction of H per shell
    y_mass_fraction_He : array
        Mass fraction of He per shell.
    frac_HII : array
        Fraction of single ionized H per shell.
    frac_HeII : array
        Fraction of single ionized He per shell.
    frac_HeIII : array
        Fraction of double ionized He per shell.

    Returns
    -------
    recomb_energy : 1D numpy.arrays
        recombination energy per shell in ergs
        (same dimension as x_mass_fraction_H and y_mass_fraction_He)


Calculate the total binding energy of the envelope of the star.

    Parameters
    ----------
    donor_mass : array
        Enclosed mass coordinate of the donor star from its profile.
    donor_radius : array
        Radius coordinate of the donor star from its profile.
    donor_dm : array
        Mass enclosed per shell in the donor star's profile.
    specific_internal_energy : array
        Specific internal energy of the donor star.
    ind_core : int
        The value of the shell position of the core - envelope boundary,
        at the donor's MESA profile
    factor_internal_energy : float
        The factor to multiply with internal energy to be taken into
        account when we calculate the  binding energy of the enevelope
    verbose : bool
        In case we want information about the CEE  (the default is False).

    Returns
    -------
    Ebind_i : float
        The total binding energy of the envelope of the star


Calculate the mass lost from the envelope for an energy budget of Ebind_threshold

    Parameters
    ----------
    profile : numpy.array
        Donor's star profile from MESA
    Ebind_threshold : float
        Orbital energy used from the spiral in to partial unbind the envelope. Positive
        We integrate from surface to calcualte the partial loss of mass during CE that merges.
    factor_internal_energy : float
        The factor to multiply with internal energy to be taken into
        account when we calculate the  binding energy of the enevelope
    verbose : bool
        In case we want information about the CEE  (the default is False).

    Returns
    -------
    Ebind_i : float
        The total binding energy of the envelope of the star


Check if metallicity is supported by POSYDON v2.


Generate rotation matrix to rotate a vector about an arbitrary axis by
        a given angle

    Parameters
    ----------
    axis : array of length 3
        Axis to rotate about
    angle : float
        Angle, in radians, through which to rotate about axis

    Returns
    -------
    rotation_matrix : 3x3 array
        Array such that rotation_matrix.dot(vector) rotates vector
        about the given axis by the given angle


Make a joint list of A and B without elements already in A and keeping
    the order.

    Parameters
    ----------
    A : iterable
        The baseline list to be extended.
    B : iterable
        The second list from which additional elements will be appened.

    Returns
    -------
    list
        The joint list by merging A and B.


Read specific columns from a MESA output file to an array.

    Note that this function also works with `.gz` files.

    Parameters
    ----------
    path : str
        The path to the file.
    columns : list of strings
        The list of names of the columns to be returned.

    Returns
    -------
    array or None
        The array containing the MESA data, or `None` if path was `None`.


Read an EEP file (can be `.gz`) - similar to `read_MESA_data_file()`.


Make He core mass/radius at least equal to CO core mass/radius.


Return a new array that is like `a`, but has additional fields.

    The contents of `a` are copied over to the appropriate fields in the new
    array, whereas the new fields are uninitialized. The arguments are not
    modified.

    Parameters
    ----------
    a : structured numpy array
        The base array.
    descr : str
        A numpy type description of the new fields.

    Returns
    -------
    type
        Description of returned object.

    Example
    -------
    >>> sa = numpy.array([(1, 'Foo'), (2, 'Bar')],
                         dtype=[('id', int), ('name', 'S3')])
    >>> sa.dtype.descr == numpy.dtype([('id', int), ('name', 'S3')])
    True
    >>> sb = add_field(sa, [('score', float)])
    >>> sb.dtype.descr == numpy.dtype([('id', int), ('name', 'S3'),
                                       ('score', float)])
    True
    >>> numpy.all(sa['id'] == sb['id'])
    True
    >>> numpy.all(sa['name'] == sb['name'])
    True


Merger time given initial orbital period and masses of binary.

    Parameters
    ----------
    P : float
        Orbital period (days).
    m1 : float
        Mass of first star (Msun).
    m2 : float
        Mass of second star (Msun).

    Returns
    -------
    float
        Merger time (Gyr)


Evaluate the "beta" (equation 5.9) from Peters (1964).

    Parameters
    ----------
    m1 : float
        Mass of the first star.
    m2 : type
        Mass of the second star.

    Returns
    -------
    float
        Peters' beta in cgs units.


Calculate the semimajor axis of a binary from its period and masses.

    Parameters
    ----------
    P : float
        Orbital period (days).
    m1 : float
        Mass of first star.
    m2 : type
        Mass of second star.

    Returns
    -------
    float
        Semi-major axis (Rsun) using Kepler's third law.


Merger time given initial orbital separation and masses of binary.

    Parameters
    ----------
    a : float
        Orbital separation (Rsun).
    m1 : float
        Mass of first star (Msun).
    m2 : float
        Mass of second star (Msun).

    Returns
    -------
    float
        Merger time (Gyr) following Peters (1964), eq. (5.10).


Convert output of a run, to a pandas dataframe.

    Note that this function also works with `.gz` files.

    Parameters
    ----------
    output_file : str
        Path to MESA output file.
    binary_history_file : str
        Path to binary history data.
    star1_history_file : str
        Path to history data for star1.
    star2_history_file : str
        Path to history data for star1.
    column_names : list of str
        Which columns to return.

    Returns
    -------
    pandas dataframe
        The table containing the requested columns from the run's histories.


Get dictionary of possible parameters/values from the default inlist.

    Parameters
    ----------
    inlist : str
        Path to inlist file.
    **kwargs : dict
        TODO

    Returns
    -------
    dict
        Dictionary of parameters and values from inlist.


Inferring the POSYDONWarning class.

        Parameters
        ----------
        category : str or a POSYDON warnings category class
            A string, which will be converted into a POSYDONWarning class.

        Returns
        -------
        POSYDONWarning or None
            A POSYDONWarning class or None if the input is neither a
            POSYDONWarning class nor convertable to one (all unknown strings
            are converted to the base POSYDONWarning).


Prints the statistics of the POSYDON warnings.


Filter a warning.

        Parameters
        ----------
        warning : dict (default: {message="No warning"})
            Dictionary containing all options passed to warnings.warn.
        registry : dict or None (default: None)
            Warnings registry. If None, use the global one.

        Returns
        -------
        warning or None in case it got filtered out.


Issue a warning.

        Parameters
        ----------
        warning : dict (default: {message="No warning"})
            Dictionary containing all options passed to warnings.warn.
        registry : dict or None (default: None)
            Warnings registry. If None, use the global one.


Checks whether there are records of caught warnings.

        Returns
        -------
        True if there are recorded warnings otherwise False.


Issueing a warning via warnings.warn.

        Parameters
        ----------
        message : str
            The message printed in the warning.
        category : str or a warnings category class (default: None)
            A string, which will be converted into a POSYDONWarning class.
        stacklevel : int (default: 2)
            The stack level passed to warnings.warn, defaults to 2.
        **kwargs : dict (optional)
            Dictionary containing extra options passed to warnings.warn.


Add the warnings filter for POSYDON warnings.

        Parameters
        ----------
        action : str (default: "default")
            The behaviour for those warnings. Should be one out of
            "default", "error", "ignore", "always", "module", or "once"
        category : str or a warnings category class (default: POSYDONWarning)
            A string, which will be converted into a POSYDONWarning class.
        **kwargs : dict (optional)
            Dictionary containing extra options passed to
            warnings.filterwarnings.


Switch the warnings filter to ignore for POSYDON warnings.

        Parameters
        ----------
        category : str or a warnings category class (default: POSYDONWarning)
            A string, which will be converted into a POSYDONWarning class.


Switch the warnings filter to always for POSYDON warnings.

        Parameters
        ----------
        category : str or a warnings category class (default: POSYDONWarning)
            A string, which will be converted into a POSYDONWarning class.


Parse the arguments given on the command-line

        Returns
        -------
        Namespace
            All the passed arguments from the commoand line or their defaults.


Print a list of available datasets

        Parameters
        ----------
        individual_sets : boolean (default: False)
            Show the individual sets or only the complete sets.
        verbose : boolean (default: False)
            Enables verbose output.


Download a data set from Zenodo if they do not exist.

        Parameters
        ----------
        dataset : string (default: 'DR2_1Zsun')
            Name of the data set to be in COMPLETE_SETS or ZENODO_COLLECTION.
        MD5_check : boolean (default: True)
            Use the MD5 check to make sure data is not corrupted.
        verbose : boolean (default: False)
            Enables verbose output.


Download data files from Zenodo if they do not exist.

        Parameters
        ----------
        set_name : string (default: 'DR2')
            Name of the data set to be in COMPLETE_SETS or ZENODO_COLLECTION.
        MD5_check : boolean (default: True)
            Use the MD5 check to make sure data is not corrupted.
        verbose : boolean (default: False)
            Enables verbose output.


Run the data download or list the datasets


Parse the arguments given on the command line

        Returns
        -------
        Namespace
            All the passed arguments from the command line or their defaults.


Get a human-readable file size in string.

    Parameters
    ----------
    filesize : int or float
        The size of the file, or directory, ... (in bytes)
    floatfmt : str
        The format for the float before the size descriptor (e.g., 2.34K).
    base : int
        The base of the units. Typically 1024 but 1000 can be used as well.
    threshold : int or float
        The threshold for using the next unit. For example, if base is 1024
        and threshold is 1000, then 1000 bytes will be returned as 0.98K.

    Returns
    -------
    str
        The filesize in string format using b, K, M, ...


Compresses a directory containing tracks evolved with MESA.

    Parameters (keys in `args`)
    ---------------------------
    verbose : bool
        Enable/Disable additional output.
    mesa_dir : string
        The directory where the MESA tracks are stored.


Run the compression of MESA files


Make a deep copy of the object.


Save the configuration entries into a JSON file.

        Parameters
        ----------
        path : str or None
            Where to save. If None, save to the path from the initialization.
        overwrite : bool
            If True, it will overwrite if the path exists.


Load the entries from a JSON file containing a dictionary.

        Parameters
        ----------
        path : str or None
            The path of the JSON file. If `None` it will use the path which
            which the ConfigFile instance was initialized.
        can_update : bool
            If True, if a key already exists, it will get the new value.
            If False, an Exception is thrown.


Parse an inifile and return dicts of each section.


Control how the strings from the inifile get parsed.


Different strings receive different evaluation.


Take a posydon binary history DataFrame from the
    BinaryStar.to_df method and clean the data for saving
    by setting Data Types of the columns explicitly.

    Parameters
    ---------
    binary_df : DataFrame
        A pandas Dataframe containing binary history
    extra_binary_dtypes_user : dict, optional
        A dictionary with extra column names as keys, and their
        associated data types as values.
    extra_S1_dtypes_user : dict, optional
        Same as above, but only for star 1.
    extra_S2_dtypes_user : dict, optional
        Same as above, but only for star 2.

    Returns
    -------
    binary_df : DataFrame
        A cleaned binary history ready for saving to HDF.


Take a posydon binary oneline DataFrame from the
    BinaryStar.to_oneline_df method and clean the data for saving
    by setting Data Types of the columns explicitly.

    This method is similar to clean_binary_history_df since they
    have many overalapping columns, with a few extras and different naming.

    Note: there may be edge cases not handed if new scalar_names are added.

    Parameters
    ---------
    binary_df : DataFrame
        A pandas Dataframe containing binary history
    extra_binary_dtypes_user : dict, optional
        A dictionary with extra column names as keys, and their
        associated data types as values.
    extra_S1_dtypes_user : dict, optional
        Same as above, but only for star 1.
    extra_S2_dtypes_user : dict, optional
        Same as above, but only for star 2.

    Returns
    -------
    binary_df : DataFrame
        A cleaned binary history ready for saving to HDF.


Parse an inifile for evolving binary populations.

    Parameters
    ---------
    path : str or list like
        Path to inifile. If multiple files are given,
        duplicate args are overwritten (stacked) first
        to last.
    verbose : bool
        Print helpful info.

    Returns
    -------
    parser : <class, ConfigParser>
        An instance of ConfigParser.


Convert an inifile into kwargs for the SimulationProperties class.

    Parameters
    ---------
    path : str or list like
        Path to inifile. If multiple files are given,
        duplicate args are overwritten (stacked) first
        to last.

    verbose : bool
        Print helpful info.

    Returns
    -------
    parser_dict : <class, dict>
        The inifile converted to the kwargs.


Convert an inifile into kwargs for the BinaryPopulation class.

    Parameters
    ---------
    path : str or list like
        Path to inifile. If multiple files are given,
        duplicate args are overwritten (stacked) first
        to last.

    verbose : bool
        Print helpful info.

    Returns
    -------
    parser_dict : <class, dict>
        The inifile converted to the kwargs.


Evolve the binary populations.

        This method is responsible for evolving the binary populations. It iterates over each population
        in the `binary_populations` list and calls the `evolve` method on each population. After evolving
        each population, it merges them using the `merge_parallel_runs` method.

        Note:
            The `merge_parallel_runs` method is called only if the `comm` attribute of the population is `None`.


Merge the parallel runs of the population.

        Parameters
        ----------
        pop : BinaryPopulation
            The binary population whose files have to be merged.


Return the first n rows of the key table

        Parameters
        ----------
        key: str
            The key of the table
        n : int, optional
            The number of rows to return. Default is 10.

        Returns
        -------
        pandas.DataFrame
            The first n rows of the key table.


        Get the last n rows of the key table.

        Parameters
        ----------
        key : str
            The key of the table.
        n : int, optional
            The number of rows to return. Default is 10.

        Returns
        -------
        pd.DataFrame
            The last n rows of the key table.


Select a subset of the key table based on the given conditions.

        Parameters
        ----------
        key : str
            The key of the table to select from.
        where : str, optional
            A string representing the query condition to apply to the data.
        start : int, optional
            The starting index of the data to select.
        stop : int, optional
            The ending index of the data to select.
        columns : list, optional
            A list of column names to select.

        Returns
        -------
        pandas.DataFrame
            The selected data as a DataFrame.


Return the first n rows of the history table

        Parameters
        ----------
        n : int, optional
            The number of rows to return. Default is 10.

        Returns
        -------
        pandas.DataFrame
            The first n rows of the history table.


Return the last n rows of the history table.

        Parameters:
        -----------
        n : int, optional
            Number of rows to return. Default is 10.

        Returns:
        --------
        pandas.DataFrame
            The last n rows of the history table.


Return the HTML representation of the history dataframe.

        This method reads the history data from an HDF file and returns
        the HTML representation of the data using the `_repr_html_` method of the
        pandas DataFrame.

        Returns
        -------
        str
            The HTML representation of the history dataframe.


Select a subset of the history table based on the given conditions.

        This method allows you to query and retrieve a subset of data from the history table
        stored in an HDFStore file. You can specify conditions using the `where` parameter,
        which is a string representing the query condition to apply to the data. You can also
        specify the starting and ending indices of the data to select using the `start` and
        `stop` parameters. Additionally, you can choose to select specific columns by providing
        a list of column names using the `columns` parameter.

        Parameters
        ----------
        where : str, optional
            A string representing the query condition to apply to the data.
            It is only possible to query on the index or string columns.
        start : int, optional
            The starting index of the data to select.
        stop : int, optional
            The ending index of the data to select.
        columns : list, optional
            A list of column names to select.

        Returns
        -------
        pandas.DataFrame
            The selected data as a DataFrame.


Get the first n rows of the oneline table.

        Parameters
        ----------
        n : int, optional
            The number of rows to return. Default is 10.

        Returns
        -------
        pd.DataFrame
            The first n rows of the oneline table.


        Get the last n rows of the oneline table.

        Parameters
        ----------
        n : int, optional
            The number of rows to return. Default is 10.

        Returns
        -------
        pd.DataFrame
            The last n rows of the oneline table.


        Get an HTML representation of the oneline table.

        Returns
        -------
        str
            The HTML representation of the oneline table.


Select a subset of the oneline table based on the given conditions.

        This method allows you to filter and extract a subset of rows from the oneline table stored in an HDF file.
        You can specify conditions to filter the rows, define the range of rows to select, and choose specific columns to include in the subset.

        Parameters
        ----------
        where : str, optional
            A condition to filter the rows of the oneline table. Default is None.
            It is only possible to query on the index or string columns.
        start : int, optional
            The starting index of the subset. Default is None.
        stop : int, optional
            The ending index of the subset. Default is None.
        columns : list, optional
            The column names to include in the subset. Default is None.

        Returns
        -------
        pd.DataFrame
            The selected subset of the oneline table.

        Examples
        --------
        # Select rows based on a condition
        >>> df = Oneline.select(where="event == 'ZAMS'")

        # Select rows from index 10 to 20
        >>> df = Oneline.select(start=10, stop=20)

        # Select specific columns
        >>> df = Oneline.select(columns=['S1_mass_i', 'S1_mass_f'])


Load the metadata from the file.

        Parameters
        ----------
        filename : str
            The name of the file to load the metadata from.

        Raises
        ------
        ValueError
            If the filename does not contain '.h5' extension.


Save the mass per metallicity data to the file.

        Parameters
        ----------
        filename : str
            The name of the file to save the mass per metallicity data to.


Load the mass per metallicity data from the file.

        Parameters
        ----------
        filename : str
            The name of the file to load the mass per metallicity data from.


Save the ini parameters to the file.

        Parameters
        ----------
        filename : str
            The name of the file to save the ini parameters to.


Load the ini parameters from the file.

        The values loaded from file are stored in the parameter_array.

        Parameters
        ----------
        filename : str
            The name of the file to load the ini parameters from.


Calculate the underlying mass of the population.

        Adds the underlying mass of the population to the mass_per_metallicity table.

        This method calculates the underlying mass of the population based on the simulated mass
        of the population and the boundaries of the sampled mass distribution.
        You can specify the fraction of binaries in the population using the `f_bin` parameter.

        Parameters
        ----------
        f_bin : float, optional
            The fraction of binaries in the population. Default is 0.7.
        overwrite : bool, optional
            If `True`, overwrite the underlying mass values if they already exist. Default is `False`.

        Returns
        -------
        np.ndarray
            The underlying mass of the population.


Export a selection of the population to a new file

        This method exports a selection of systems from the population to a new file.
        The selected systems are specified by their indices in the population.

        By default the selected systems will overwrite the file if it already exists.
        If overwrite is set to False, the selected systems will be appended to
        the existing file if it already exists and the indices will be shifted
        based on the current length of data in the file that is being appended to.

        Parameters
        ----------
        selection : list of int
            The indices of the systems to export.
        filename : str
            The name of the export file to create or append to.
        chunksize : int, optional
            The number of systems to export at a time. Default is 1000000.

        Raises
        ------
        ValueError
            If the filename does not contain ".h5" extension.

        Warnings
        --------
        ReplaceValueWarning
            If there is no "metallicity" column in the oneline dataframe and the population file contains multiple metallicities.

        Notes
        -----
        - The exported systems will be appended to the existing file if it already exists.
        - The indices of the exported systems will be shifted based on the current length of data in the file.
        - The "oneline" and "history" dataframes of the selected systems will be written to the file.
        - If available, the "formation_channels" dataframe and "history_lengths" dataframe of the selected systems will also be written to the file.
        - The "metallicity" column of the oneline dataframe will be added if it is not present, using the metallicity of the population file.
        - The "mass_per_metallicity" dataframe will be updated with the number of selected systems.

        Examples
        --------
        # Export systems with indices [0, 1, 2] to a new file named "selected.h5"
        >>> population.export_selection([0, 1, 2], "selected.h5")

        # Export systems with indices [3, 4, 5] to an existing file named "existing.h5"
        >>> population.export_selection([3, 4, 5], "existing.h5")

        # Export systems with indices [6, 7, 8] to a new file named "selected.h5" in chunks of 2
        >>> population.export_selection([6, 7, 8], "selected.h5", history_chunksize=2)


        Retrieves the formation channels from the population file.

        Returns:
            pandas.DataFrame or None: The formation channels if available, otherwise None.


Calculate the formation channels of the population.

        mt_history is a boolean that determines if the detailed mass-transfer history
        from the HMS-HMS grid is included in the formation channels.

        Parameters
        ----------
        mt_history : bool, optional
            If `True`, include the mass-transfer history in the formation channels. Default is False.

        Raises
        ------
        ValueError
            If the mt_history_HMS_HMS column is not present in the oneline dataframe.


Write the formation channels to the population file

        This will append the formation channels to the population file, while restricting the maximum
        length of the channel and channel_debug columns to 100 characters.

        Parameters
        ----------
        filename : str
            The name of the file to write the formation channels to.
        df : pd.DataFrame
            The dataframe containing the formation channels.


        Returns a dictionary containing the column names of the history and oneline dataframes.

        Returns
        -------
        dict
            A dictionary with keys 'history' and 'oneline', where the values are the column names of the respective dataframes.


Given a function, create a TransientPopulation

        This method creates a transient population using the provided function.
        `func` is given the history, oneline, and formation channels dataframes as arguments.
        The function should return a dataframe containing the transient population, which needs to contain the columns 'time' and 'metallicity'.

        Processing is done in chunks to avoid memory issues and a pandas DataFrame is stored at `'/transients/transient_name'` in the population file.

        The creation of the transient population can be sped up by limiting the oneline_cols and hist_cols to only the columns needed for the function.
        If you do not provide these, all columns will be used, which can be slow for large populations.

        Parameters
        ----------
        func : function
            Function to apply to the parsed population to create a transient population.
            The function needs to take 3 arguments:
                - history_chunk : pd.DataFrame
                - oneline_chunk : pd.DataFrame
                - formation_channels_chunk : pd.DataFrame
            and return a pd.DataFrame containing the transient population, which needs to contain the columns 'time' and 'metallicity'.

        oneline_cols : list of str, optional
            Columns to extract from the oneline dataframe. Default is all columns.

        hist_cols : list of str, optional
            Columns to extract from the history dataframe. Default is all columns.

        Returns
        -------
        TransientPopulation or None
            A TransientPopulation object for interfacing with the transient population or None if no systems are present in the TransientPopulation.

        Raises
        ------
        ValueError
            If the transient population requires a time column or if the transient population contains duplicate columns.

        Examples
        --------
        See the tutorials for examples of how to use this method.


Plot the binary evolution of a system

        This method is not currently implemented.


Returns the entire transient population as a pandas DataFrame.

        This method retrieves the transient population data from a file and returns it as a pandas DataFrame.
        Please note that if the transient population is too large, it may consume a significant amount of memory.

        Returns
        -------
        pd.DataFrame
            A DataFrame containing the transient population data.


Load the efficiency from the file

        Parameters:
            filename (str): The path to the file containing the efficiency data.

        Returns:
            None

        Raises:
            None


Save the efficiency to the file.

        Args:
            filename (str): The name of the file to save the efficiency to.

        Returns:
            None


Return the columns of the transient population.

        Returns:
            list: A list of column names in the transient population.


        Select a subset of the transient population.

        This method allows you to filter and extract a subset of rows from the transient table stored in an HDF file.
        You can specify conditions to filter the rows, define the range of rows to select, and choose specific columns to include in the subset.

        Parameters
        ----------
        where : str, optional
            A condition to filter the rows of the transient table. Default is None.
            It is only possible to search on the index or string columns.
        start : int, optional
            The starting index of the subset. Default is None.
        stop : int, optional
            The ending index of the subset. Default is None.
        columns : list, optional
            The column names to include in the subset. Default is None.

        Returns
        -------
        pd.DataFrame
            The selected subset of the transient table.

        Examples
        --------
        # Select rows based on a condition
        >>> df = transpop.select(where="S1_state == 'BH'")

        # Select rows from index 10 to 20
        >>> df = transpop.select(start=10, stop=20)

        # Select specific columns
        >>> df = transpop.select(columns=['time', 'metallicity'])


        Calculate the cosmic weights of the transient population.

        This method calculates the cosmic weights of the transient population based on the provided star formation history identifier and model parameters.
        It performs various calculations and stores the results in an HDF5 file at the location '/transients/{transient_name}/rates/{SFH_identifier}'.
        This allows for multiple star formation histories to be used with the same transient population.

        The default MODEL parameters are used if none are provided, which come from the IllustrisTNG model.

        Parameters
        ----------
        SFH_identifier : str
            Identifier for the star formation history.
        MODEL_in : dict, optional
            Dictionary containing the model parameters. If not provided, the default model parameters will be used.

        Returns
        -------
        Rates
            An instance of the Rates class.

        Raises
        ------
        ValueError
            If a parameter name in MODEL_in is not valid.

        Notes
        -----
        This function calculates the cosmic weights of the transient population based on the provided star formation history
        identifier and model parameters. It performs various calculations and stores the results in an HDF5 file.

        The cosmic weights are computed for each event in the population, taking into account the metallicity, redshift,
        and birth time of the events. The weights are calculated using the provided model parameters and the underlying mass
        distribution.

        The calculated weights, along with the corresponding redshifts of the events, are stored in the HDF5 file for further analysis.
        These can be accessed using the Rates class.

        Examples
        --------
        >>> transient_population = TransientPopulation('filename.h5', 'transient_name')
        >>> transient_population.calculate_cosmic_weights('IllustrisTNG', MODEL_in=DEFAULT_SFH_MODEL)


        Plot the efficiency over metallicity.

        Parameters
        ----------
        channel : bool, optional
            If True, plot the subchannels. Default is False.


        Plot the delay time distribution of the transient population.

        This method plots the delay time distribution of the transient population. If a specific metallicity is provided,
        the delay time distribution of the population at that metallicity will be plotted. Otherwise, the delay time distribution
        of the entire population will be plotted.

        Parameters
        ----------
        metallicity : float or None
            The metallicity value to select a specific population. If None, the delay time distribution of the entire population will be plotted.
        ax : matplotlib.axes.Axes or None
            The axes object to plot the distribution on. If None, a new figure and axes will be created.
        bins : int
            The number of bins to use for the histogram.
        color : str
            The color of the histogram.

        Raises
        ------
        ValueError
            If the specified metallicity is not present in the population.

        Notes
        -----
        - The delay time distribution is normalized by the total mass of the population if no metallicity is specified.
        Otherwise, it is normalized by the mass of the population at the specified metallicity.


        Plot the transients over the grid slice.

        Parameters
        ----------
        grid_type : str
            The type of grid to plot.
        met_Zsun : float
            The metallicity of the Sun.
        **kwargs
            Additional keyword arguments to pass to the plot_pop.plot_popsyn_over_grid_slice function.


        Write the MODEL data to the HDFStore file.

        Parameters
        ----------
        filename : str
            The path to the HDFStore file.
        path_in_file : str
            The path within the HDFStore file to store the MODEL data.
        MODEL : dict
            The MODEL data to be stored.


        Reads the MODEL data from the specified file.

        Parameters
        ----------
        filename : str
            The path to the file containing the MODEL data.


        Retrieves the weights from the HDFStore.

        The rows are indexed by the binary index of the events, while to columns are indexed by the redshift of the birth bins.

        Returns
        -------
        pandas.DataFrame
            The weights DataFrame.


        Retrieves the 'birth' data from the HDFStore.

        The 'birth' DataFrame contains the redshift and age of the Universe of the birth bins with columns 'z' and 't'.

        Returns
        -------
        pandas.DataFrame
            The 'birth' DataFrame, which contains the redshift and age of the Universe of the birth bins.


        Returns the 'z_events' data from the HDFStore.

        The 'z_events' data contains the redshifts at which the events occur.
        The rows of the returned DataFrame are indexed by the binary index of the events.
        The columns of the returned DataFrame are indexed by the redshift of the birth bins.

        Returns
        -------
        pandas.DataFrame
            The 'z_events' data from the HDFStore.


Selects a slice of a rates dataframe at key.

        This method allows you to select a slice in rows from the diffferent rates dataframes.
        The slice is selected based on the start and stop indices.
        The key specifies which rates dataframe to select, and must be one of ['weights', 'z_events', 'birth'].

        Parameters
        ----------
        key : str
            The key to select the slice from. Must be one of ['weights', 'z_events', 'birth'].
        start : int, optional
            The starting index of the slice. Defaults to None.
        stop : int, optional
            The ending index of the slice. Defaults to None.

        Returns
        -------
        pandas.DataFrame
            The selected slice of rates.

        Raises
        ------
        ValueError
            If the key is not one of ['weights', 'z_events', 'birth'].


        Compute the intrinsic rate density over redshift of the transient population.

        Besides returning the intrinsic rate density, this method also stores the results in the HDF5 file for further analysis.
        This can be accessed using the intrinsic_rate_density attribute of the Rates class.

        Parameters
        ----------
        channels : bool, optional
            Flag indicating whether to calculate the intrinsic rate density for each channel separately. Default is False.

        Returns
        -------
        pandas.DataFrame
            DataFrame containing the intrinsic rate density values.


        Calculate an observable population.

        The observable population is calculated based on the provided observable function.
        It should recalculate your weights based on an observability probability given certain transinet parameters.

        This function requires the following input chunks:
        1. transient_pop_chunk
        2. z_events_chunk
        3. weights_chunk
        The observable function should output a DataFrame with the same shape as the weights_chunk.

        The observable population is stored in the HDF5 file at
        the location '/transients/{transient_name}/rates/observable/{observable_name}'.

        Parameters
        ----------
        observable_func : function
            The observability function that takes the TransientPopulation as input.
        observable_name : str
            The name of the observable.

        Note
        ----
        - If the observable population already exists in the file, it will be overwritten.


Return the observable population based on the provided name.

        This method returns the observable population based on the provided name,
        which can take a while to load if the population is large.
        It loads the observable population from '/transients/{transient_name}/rates/observable/{observable_name}' in the HDF5 file.

        Parameters
        ----------
        observable_name : str
            The name of the observable population to return.

        Returns
        -------
        pandas.DataFrame
            The observable population based on the provided name.


Return the names of the observable populations in the associated file.

        Returns
        -------
        list
            The names of the observable populations.


Return the intrinsic rate density of the transient population at the specified SFH_identifier and transient_name.

        The data is read from the HDF5 file at '/transients/{transient_name}/rates/{SFH_identifier}/intrinsic_rate_density'.

        Returns
        -------
        pandas.DataFrame
            The intrinsic rate density of the transient population.


Plot a histogram of a given property available in the transient population.

        This method plots a histogram of a given property available in the transient population.
        The property can be intrinsic or observable, and the histogram can be plotted for a specific channel if provided.

        Parameters
        ----------
        prop : str
            The property to plot the histogram for.
        intrinsic : bool, optional
            If True, plot the intrinsic property. Default is True.
        observable : str, optional
            The observable population name to plot the histogram for. Default is None.
        bins : int, optional
            The number of bins to use for the histogram. Default is 50.
        channel : str, optional
            The channel to plot the histogram for. Default is None.
            A channel column must be present in the transient population.
        **kwargs
            Additional keyword arguments to pass to the plot

        Raises
        ------
        ValueError
            If the specified property is not a valid property in the transient population.
            If the specified observable is not a valid observable population.
            If the specified channel is not present in the transient population.


Return the edges of the metallicity bins.

        Returns
        -------
        array float
            Returns the edges of all metallicity bins. We assume metallicities
            were binned in log-space.


Return the centers of the metallicity bins.

        Returns
        -------
        array float
            Returns sampled metallicities of the population. This corresponds
            to the center of each metallicity bin.