        Interpolate beam to given frequency, az & za locations or Healpix pixel centers.

        Uses the function specified in `interpolation_function`, which defaults to
        "az_za_simple" for objects with the "az_za" pixel_coordinate_system and
        "healpix_simple" for objects with the "healpix" pixel_coordinate_system.
        Currently supported interpolation functions include:

        - "az_za_simple": Uses scipy RectBivariate spline interpolation, can only be
          used on objects with an "az_za" pixel_coordinate_system.
        - "az_za_map_coordinates": Uses scipy map_coordinates interpolation, can only
          be used on objects with an "az_za" pixel_coordinate_system.
        - "healpix_simple": Uses HEALPix nearest-neighbor bilinear interpolation, can
          only be used on objects with a "healpix" pixel_coordinate_system.

        Parameters
        ----------
        az_array : array_like of floats, optional
            Azimuth values to interpolate to in radians, either specifying the
            azimuth positions for every interpolation point or specifying the
            azimuth vector for a meshgrid if az_za_grid is True.
        za_array : array_like of floats, optional
            Zenith values to interpolate to in radians, either specifying the
            zenith positions for every interpolation point or specifying the
            zenith vector for a meshgrid if az_za_grid is True.
        interpolation_function : str, optional
            Specify the interpolation function to use. Defaults to: "az_za_simple" for
            objects with the "az_za" pixel_coordinate_system and "healpix_simple" for
            objects with the "healpix" pixel_coordinate_system. "az_za_map_coordinates"
            is also available for objects with the "az_za" pixel_coordinate_system.
        freq_interp_kind : str
            Interpolation method to use frequency. See scipy.interpolate.interp1d
            for details. Defaults to "cubic" (Note that this is a change. It used to
            default to "linear" when it was assigned to the object. However, multiple
            groups have found that a linear interpolation leads to nasty artifacts in
            visibility simulations for EoR applications.)
        az_za_grid : bool
            Option to treat the `az_array` and `za_array` as the input vectors
            for points on a mesh grid.
        healpix_nside : int, optional
            HEALPix nside parameter if interpolating to HEALPix pixels.
        healpix_inds : array_like of int, optional
            HEALPix indices to interpolate to. Defaults to all indices in the
            map if `healpix_nside` is set and `az_array` and `za_array` are None.
        freq_array : array_like of floats, optional
            Frequency values to interpolate to.
        freq_interp_tol : float
            Frequency distance tolerance [Hz] of nearest neighbors.
            If *all* elements in freq_array have nearest neighbor distances within
            the specified tolerance then return the beam at each nearest neighbor,
            otherwise interpolate the beam.
        polarizations : list of str
            polarizations to interpolate if beam_type is 'power'.
            Default is all polarizations in self.polarization_array.
        return_bandpass : bool
            Option to return the bandpass. Only applies if `new_object` is False.
        return_coupling : bool
            Option to return the interpolated coupling matrix, only applies if
            `antenna_type` is "phased_array" and `new_object` is False.
        new_object : bool
            Option to return a new UVBeam object with the interpolated data,
            if possible. Note that this is only possible for Healpix pixels or
            if az_za_grid is True and `az_array` and `za_array` are evenly spaced
            or for frequency only interpolation.
        reuse_spline : bool
            Save the interpolation functions for reuse. Only applies for
            `az_za_simple` and `az_za_map_coordinates` interpolation.
        spline_opts : dict, optional
            Provide options to numpy.RectBivariateSpline. This includes spline
            order parameters `kx` and `ky`, and smoothing parameter `s`.
            Applies for `az_za_simple` and `az_za_map_coordinates` interpolation.
            Note that this parameter is ignored if this function has been called
            previously on this object instance and reuse_spline is True.
        run_check : bool
            Only used if new_object is True. Option to check for the existence
            and proper shapes of required parameters on the new object.
        check_extra : bool
            Only used if new_object is True. Option to check optional parameters
            as well as required ones on the new object.
        run_check_acceptability : bool
            Only used if new_object is True. Option to check acceptable range
            of the values of required parameters on the new object.
        check_azza_domain : bool
            Whether to check the domain of az/za to ensure that they are covered by the
            intrinsic data array. Checking them can be quite computationally expensive.
            Conversely, if the passed az/za are outside of the domain, they will be
            silently extrapolated and the behavior is not well-defined. Only
            applies for `az_za_simple` and `az_za_map_coordinates` interpolation.
        return_basis_vector : bool
            Whether to return the interpolated basis vectors. Prior to v3.1.1 these
            were always returned. In v3.3+ they will _not_ be returned by default
            (and not computed by default, unless new_object=True).

        Returns
        -------
        array_like of float or complex or a UVBeam object
            Either an array of interpolated values or a UVBeam object if
            `new_object` is True. The shape of the interpolated data will be:
            (Naxes_vec, Nfeeds or Npols, Nfreqs or freq_array.size if
            freq_array is passed, Npixels/(Naxis1, Naxis2) or az_array.size if
            az/za_arrays are passed) or (Naxes_vec, Nfeeds or Npols,
            Nfreqs or freq_array.size if freq_array is passed, Npixels/(Naxis1, Naxis2)
        interp_basis_vector : array_like of float, optional
            The array of interpolated basis vectors (or self.basis_vector_array
            if az/za_arrays are not passed). Only returned if `new_object` is False.
            shape: (Naxes_vec, Ncomponents_vec, Npixels/(Naxis1, Naxis2) or
            az_array.size if az/za_arrays are passed)
        interp_bandpass : array_like of float, optional
            The interpolated bandpass, only returned if `return_bandpass` is True and
            `new_object` is False. Shape: (freq_array.size,)
        interp_coupling_matrix : array_like of complex, optional
            The interpolated coupling matrix. Only returned if return_coupling is True
            and `new_object` is False.
            Shape: (Nelements, Nelements, Nfeeds, Nfeeds, freq_array.size)


        Convert beam to the healpix coordinate system using interpolation.

        Note that this interpolation isn't perfect. Interpolating an Efield beam
        and then converting to power gives a different result than converting
        to power and then interpolating at about a 5% level.

        Uses the function specified in `interpolation_function`, defaults to the
        "az_za_simple" for objects with the "az_za" pixel_coordinate_system.
        Currently supported interpolation functions for beams that are not already in
        a healpix coordinate system include:

        - "az_za_simple": Uses scipy RectBivariate spline interpolation, can only be
          used on objects with an "az_za" pixel_coordinate_system.
        - "az_za_map_coordinates": Uses scipy map_coordinates interpolation, can only
          be used on objects with an "az_za" pixel_coordinate

        Parameters
        ----------
        nside : int
            The nside to use for the Healpix map. If not specified, use
            the nside that gives the closest resolution that is higher than the
            input resolution.
        interpolation_function : str, optional
            Specify the interpolation function to use. Defaults to to:
            "az_za_simple" for objects with the "az_za" pixel_coordinate_system.
            "az_za_map_coordinates" is also available for objects with the "az_za"
            pixel_coordinate_system.
        run_check : bool
            Option to check for the existence and proper shapes of required
            parameters after converting to healpix.
        check_extra : bool
            Option to check optional parameters as well as required ones.
        run_check_acceptability : bool
            Option to check acceptable range of the values of required parameters
            after combining objects
        inplace : bool
            Option to perform the interpolation directly on self or return a new
            UVBeam object.


        Get the healpix power beam map corresponding to the specified polarization.

        pseudo-stokes I: 'pI', Q: 'pQ', U: 'pU' and V: 'pV' or linear dipole
        polarization: 'XX', 'YY', etc.

        Parameters
        ----------
        pol : str or int
            polarization string or integer, Ex. a pseudo-stokes pol 'pI', or
            a linear pol 'XX'.

        Returns
        -------
        np.ndarray of float
            Healpix map of beam powers for a single pol, shape: (Nfreqs, Npixels)


        Downselect data to keep on the object along various axes.

        Axes that can be selected along include image axis indices or pixels
        (if healpix), frequencies and feeds or polarizations (if power).

        The history attribute on the object will be updated to identify the
        operations performed.

        Parameters
        ----------
        axis1_indss : array_like of int, optional
            The indices along the first image axis to keep in the object.
            Cannot be set if pixel_coordinate_system is "healpix".
        axis2_inds : array_like of int, optional
            The indices along the second image axis to keep in the object.
            Cannot be set if pixel_coordinate_system is "healpix".
        pixels : array_like of int, optional
            The healpix pixels to keep in the object.
            Cannot be set if pixel_coordinate_system is not "healpix".
        frequencies : array_like of float, optional
            The frequencies to keep in the object.
        freq_chans : array_like of int, optional
            The frequency channel numbers to keep in the object.
        feeds : array_like of str, optional
            The feeds to keep in the object. If the `x_orientation` attribute is set,
            the physical dipole strings (e.g. "n", "e") are also supported.
            Cannot be set if the beam_type is "power".
        polarizations : array_like of int or str, optional
            The polarizations to keep in the object.
            Cannot be set if the beam_type is "efield". If passing strings, the
            canonical polarization strings (e.g. "xx", "rr") are supported and if the
            `x_orientation` attribute is set, the physical dipole strings
            (e.g. "nn", "ee") are also supported.
        invert : bool
            Normally records matching given criteria are what are included in the
            subsequent object. However, if set to True, these records are excluded
            instead. Default is False.
        strict : bool or None
            Normally, select will warn when no records match a one element of a
            parameter, as long as *at least one* element matches with what is in the
            object. However, if set to True, an error is thrown if any element
            does not match. If set to None, then neither errors nor warnings are raised.
            Default is False.
        inplace : bool
            Option to perform the select directly on self or return
            a new UVBeam object, which is a subselection of self.
        run_check : bool
            Option to check for the existence and proper shapes of
            required parameters after downselecting data on this object.
        check_extra : bool
            Option to check optional parameters as well as required ones.
        run_check_acceptability : bool
            Option to check acceptable range of the values of
            required parameters after  downselecting data on this object.
        warn_spacing : bool
            Option to raise warnings about spacing that would prevent writing to
            beamfits file-format. Default is True.


        Read in data from a beamfits file.

        Parameters
        ----------
        filename : str or list of str
            The beamfits file or list of files to read from.
        run_check : bool
            Option to check for the existence and proper shapes of
            required parameters after reading in the file.
        check_extra : bool
            Option to check optional parameters as well as required ones.
        run_check_acceptabilit : bool
            Option to check acceptable range of the values of
            required parameters after reading in the file.
        check_auto_power : bool
            For power beams, check whether the auto polarization beams have non-zero
            imaginary values in the data_array (which should not mathematically exist).
        fix_auto_power : bool
            For power beams, if auto polarization beams with imaginary values are found,
            fix those values so that they are real-only in data_array.
        freq_range : tuple of float in Hz
            If given, the lower and upper limit of the frequencies to read in. Default
            is to read in all frequencies. Restricting the frequencies reduces peak
            memory usage.
        mount_type : str
            Antenna mount type to use, which describes the optics of the antenna in
            question, if the keyword is not found in the BeamFITS file being loaded.
            Supported options include: "alt-az" (primary rotates in azimuth and
            elevation), "equatorial" (primary rotates in hour angle and declination)
            "orbiting" (antenna is in motion, and its orientation depends on orbital
            parameters), "x-y" (primary rotates first in the plane connecting east,
            west, and zenith, and then perpendicular to that plane),
            "alt-az+nasmyth-r" ("alt-az" mount with a right-handed 90-degree tertiary
            mirror), "alt-az+nasmyth-l" ("alt-az" mount with a left-handed 90-degree
            tertiary mirror), "phased" (antenna is "electronically steered" by
            summing the voltages of multiple elements, e.g. MWA), "fixed" (antenna
            beam pattern is fixed in azimuth and elevation, e.g., HERA), and "other"
            (also referred to in some formats as "bizarre"). See the "Conventions"
            page of the documentation for further details.
        az_range : tuple of float in deg
            The azimuth range to read in, if the beam is specified in az/za coordinates.
            Default is to read in all azimuths. Restricting the azimuth reduces peak
            memory usage.
        za_range : tuple of float in deg
            The zenith angle range to read in, if the beam is specified in za/za
            coordinates. Default is to read in all za. Restricting the za reduces peak
            memory.


        Parse a CST beam yaml file.

        Paramters
        ---------
        filename : str
            Filename to parse.

        Returns
        -------
        dict
            Containing all the info from the yaml file.


        Read in data from a cst file.

        Parameters
        ----------
        filename : str
            Either a settings yaml file or a cst text file or
            list of cst text files to read from. If a list is passed,
            the files are combined along the appropriate axes.

            Settings yaml files must include the following keywords:

                |  - telescope_name (str)
                |  - feed_name (str)
                |  - feed_version (str)
                |  - model_name (str)
                |  - model_version (str)
                |  - history (str)
                |  - frequencies (list(float))
                |  - cst text filenames (list(str)) -- path relative to yaml file
                |  - feed_pol (str) or (list(str))

            and they may include the following optional keywords:

                |  - x_orientation (str): Optional but strongly encouraged!
                |  - ref_imp (float): beam model reference impedance
                |  - sim_beam_type (str): e.g. 'E-farfield'
                |  - all other fields will go into the extra_keywords attribute

            More details and an example are available in the docs
            (cst_settings_yaml.rst).
            Specifying any of the associated keywords to this function will
            override the values in the settings file.
        beam_type : str
            What beam_type to read in ('power' or 'efield').
        feed_pol : str
            The feed or polarization or list of feeds or polarizations the
            files correspond to.
            Defaults to 'x' (meaning x for efield or xx for power beams).
        feed_array : str or array-like of str
            Feeds to define this beam for, e.g. x & y or r & l. Only used for power
            beams (feeds are set by feed_pol for efield beams).
        feed_angle : str or array-like of float
            Position angle of a given feed, units of radians. A feed angle of 0 is
            typically oriented toward zenith for steerable antennas, otherwise toward
            north for fixed antennas (e.g., HERA, LWA). More details on this can be
            found on the "Conventions" page of the docs. Must match shape of feed_pol
            for efield beams, or feed_angle for power beams.
        rotate_pol : bool
            If True, assume the structure in the simulation is symmetric under
            90 degree rotations about the z-axis (so that the y polarization can be
            constructed by rotating the x polarization or vice versa).
            Default: True if feed_pol is a single value or a list with all
            the same values in it, False if it is a list with varying values.
        mount_type : str
            Antenna mount type, which describes the optics of the antenna in question.
            Supported options include: "alt-az" (primary rotates in azimuth and
            elevation), "equatorial" (primary rotates in hour angle and declination)
            "orbiting" (antenna is in motion, and its orientation depends on orbital
            parameters), "x-y" (primary rotates first in the plane connecting east,
            west, and zenith, and then perpendicular to that plane),
            "alt-az+nasmyth-r" ("alt-az" mount with a right-handed 90-degree tertiary
            mirror), "alt-az+nasmyth-l" ("alt-az" mount with a left-handed 90-degree
            tertiary mirror), "phased" (antenna is "electronically steered" by
            summing the voltages of multiple elements, e.g. MWA), "fixed" (antenna
            beam pattern is fixed in azimuth and elevation, e.g., HERA), and "other"
            (also referred to in some formats as "bizarre"). See the "Conventions"
            page of the documentation for further details.
        frequency : float or list of float, optional
            The frequency or list of frequencies corresponding to the filename(s).
            This is assumed to be in the same order as the files.
            If not passed, the code attempts to parse it from the filenames.
        telescope_name : str, optional
            The name of the telescope corresponding to the filename(s).
        feed_name : str, optional
            The name of the feed corresponding to the filename(s).
        feed_version : str, optional
            The version of the feed corresponding to the filename(s).
        model_name : str, optional
            The name of the model corresponding to the filename(s).
        model_version : str, optional
            The version of the model corresponding to the filename(s).
        history : str, optional
            A string detailing the history of the filename(s).
        x_orientation : str, optional
            Orientation of the physical dipole corresponding to what is
            labelled as the x polarization. Options are "east" (indicating
            east/west orientation) and "north" (indicating north/south orientation)
        reference_impedance : float, optional
            The reference impedance of the model(s).
        extra_keywords : dict, optional
            A dictionary containing any extra_keywords.
        frequency_select : list of float, optional
            Only used if the file is a yaml file. Indicates which frequencies
            to include (only read in files for those frequencies)
        run_check : bool
            Option to check for the existence and proper shapes of
            required parameters after reading in the file.
        check_extra : bool
            Option to check optional parameters as well as
            required ones.
        run_check_acceptability : bool
            Option to check acceptable range of the values of
            required parameters after reading in the file.
        check_auto_power : bool
            For power beams, check whether the auto polarization beams have non-zero
            imaginary values in the data_array (which should not mathematically exist).
        fix_auto_power : bool
            For power beams, if auto polarization beams with imaginary values are found,
            fix those values so that they are real-only in data_array.


        Read in data from a FEKO file.

        Parameters
        ----------
        filename : str
            A FEKO text file.
        beam_type : str
            What beam_type to read in ('power' or 'efield').
        feed_pol : str
            The feed polarization that the files corresponds to, e.g. x, y, r or l.
            Defaults to 'x'.
        feed_angle : float
            Position angle of the feed, units of radians. A feed angle of 0 is
            typically oriented toward zenith for steerable antennas, otherwise toward
            north for fixed antennas (e.g., HERA, LWA). More details on this can be
            found on the "Conventions" page of the docs.
        mount_type : str
            Antenna mount type, which describes the optics of the antenna in question.
            Supported options include: "alt-az" (primary rotates in azimuth and
            elevation), "equatorial" (primary rotates in hour angle and declination)
            "orbiting" (antenna is in motion, and its orientation depends on orbital
            parameters), "x-y" (primary rotates first in the plane connecting east,
            west, and zenith, and then perpendicular to that plane),
            "alt-az+nasmyth-r" ("alt-az" mount with a right-handed 90-degree tertiary
            mirror), "alt-az+nasmyth-l" ("alt-az" mount with a left-handed 90-degree
            tertiary mirror), "phased" (antenna is "electronically steered" by
            summing the voltages of multiple elements, e.g. MWA), "fixed" (antenna
            beam pattern is fixed in azimuth and elevation, e.g., HERA), and "other"
            (also referred to in some formats as "bizarre"). See the "Conventions"
            page of the documentation for further details.
        telescope_name : str, optional
            The name of the telescope corresponding to the filename(s).
        feed_name : str, optional
            The name of the feed corresponding to the filename(s).
        feed_version : str, optional
            The version of the feed corresponding to the filename(s).
        model_name : str, optional
            The name of the model corresponding to the filename(s).
        model_version : str, optional
            The version of the model corresponding to the filename(s).
        history : str, optional
            A string detailing the history of the filename(s).
        reference_impedance : float, optional
            The reference impedance of the model(s).
        extra_keywords : dict, optional
            A dictionary containing any extra_keywords.
        frequency_select : list of float, optional
            Only used if the file is a yaml file. Indicates which frequencies
            to include (only read in files for those frequencies)
        run_check : bool
            Option to check for the existence and proper shapes of
            required parameters after reading in the file.
        check_extra : bool
            Option to check optional parameters as well as
            required ones.
        run_check_acceptability : bool
            Option to check acceptable range of the values of
            required parameters after reading in the file.
        check_auto_power : bool
            For power beams, check whether the auto polarization beams have non-zero
            imaginary values in the data_array (which should not mathematically exist).
        fix_auto_power : bool
            For power beams, if auto polarization beams with imaginary values are found,
            fix those values so that they are real-only in data_array.


        Read in the full embedded element MWA beam.

        Note that the azimuth convention in for the UVBeam object is different than the
        azimuth convention in the mwa_pb repo. In that repo, the azimuth convention is
        changed from the native FEKO convention (the FEKO convention is the same as the
        UVBeam convention). The convention in the mwa_pb repo has a different zero point
        and a different direction (so it is in a left handed coordinate system).

        Parameters
        ----------
        h5filepath : str
            path to input h5 file containing the MWA full embedded element spherical
            harmonic modes. Download via
            `wget http://ws.mwatelescope.org/static/mwa_full_embedded_element_pattern.h5`
            (This reader is based on https://github.com/MWATelescope/mwa_pb).
        delays : array of ints
            Array of MWA beamformer delay steps. Should be shape (n_pols, n_dipoles).
        amplitudes : array of floats
            Array of dipole amplitudes, these are absolute values
            (i.e. relatable to physical units).
            Should be shape (n_pols, n_dipoles).
        pixels_per_deg : float
            Number of theta/phi pixels per degree. Sets the resolution of the beam.
        freq_range : array_like of float
            Range of frequencies to include in Hz, defaults to all available
            frequencies. Must be length 2.
        run_check : bool
            Option to check for the existence and proper shapes of
            required parameters after reading in the file.
        check_extra : bool
            Option to check optional parameters as well as required ones.
        run_check_acceptability : bool
            Option to check acceptable range of the values of
            required parameters after reading in the file.
        check_auto_power : bool
            For power beams, check whether the auto polarization beams have non-zero
            imaginary values in the data_array (which should not mathematically exist).
        fix_auto_power : bool
            For power beams, if auto polarization beams with imaginary values are found,
            fix those values so that they are real-only in data_array.


Initialize a new UVBeam object by reading the input file(s).


        Write the data to a beamfits file.

        Parameters
        ----------
        filename : str
            The beamfits file to write to.
        run_check : bool
            Option to check for the existence and proper shapes of
            required parameters before writing the file.
        check_extra : bool
            Option to check optional parameters as well as
            required ones.
        run_check_acceptability : bool
            Option to check acceptable range of the values of
            required parameters before writing the file.
        check_auto_power : bool
            For power beams, check whether the auto polarization beams have non-zero
            imaginary values in the data_array (which should not mathematically exist).
        fix_auto_power : bool
            For power beams, if auto polarization beams with imaginary values are found,
            fix those values so that they are real-only in data_array.
        clobber : bool
            Option to overwrite the filename if the file already exists.


    Define a yaml representer for UVbeams.

    Note: since all the possible selects cannot be extracted from the object,
    the object generated from this yaml may not be an exact match for the object
    in memory. Also note that the filename parameter must not be None and must
    point to an existing file. It's likely that the user will need to update
    the filename parameter to include the full path.

    Parameters
    ----------
    dumper: yaml.Dumper
        An instance of a yaml Loader object.
    beam: UVBeam
        A UVbeam object, which must have a filename defined on it.

    Returns
    -------
    str
        The yaml representation of the UVbeam.


r"""Create a new UVBeam object with default parameters.

    Parameters
    ----------
    telescope_name : str
        Telescope name.
    data_normalization : str
        Normalization standard of data_array, options are: "physical", "peak" or
        "solid_angle". Physical normalization means that the frequency dependence
        of the antenna sensitivity is included in the data_array while the
        frequency dependence of the receiving chain is included in the
        bandpass_array. Peak normalized means that for each frequency the
        data_array is separately normalized such that the peak is 1 (so the beam
        is dimensionless) and all direction-independent frequency dependence is
        moved to the bandpass_array (if the beam_type is "efield", then peak
        normalized means that the absolute value of the peak is 1). Solid angle
        normalized means the peak normalize beam is divided by the integral of
        the beam over the sphere, so the beam has dimensions of 1/steradian.
    freq_array : ndarray of float
        Array of frequencies in Hz.
    feed_name : str
        Name of the physical feed.
    feed_version : str
        Version of the physical feed.
    model_name : str
        Name of the beam model.
    model_version: str
        Version of the beam model.
    feed_array : ndarray of str
        Array of feed orientations. Options are: n/e or x/y or r/l.
    feed_angle : ndarray of float
        Orientation of the feed with respect to zenith (or with respect to north if
        pointed at zenith). Units is in rads, x-polarization is nominally pi / 2,
        and y-polarization (as well as l- and r-polarizations) are nominally 0.
    mount_type : str
        Antenna mount type, which describes the optics of the antenna in question.
        Supported options include: "alt-az" (primary rotates in azimuth and
        elevation), "equatorial" (primary rotates in hour angle and declination)
        "orbiting" (antenna is in motion, and its orientation depends on orbital
        parameters), "x-y" (primary rotates first in the plane connecting east,
        west, and zenith, and then perpendicular to that plane),
        "alt-az+nasmyth-r" ("alt-az" mount with a right-handed 90-degree tertiary
        mirror), "alt-az+nasmyth-l" ("alt-az" mount with a left-handed 90-degree
        tertiary mirror), "phased" (antenna is "electronically steered" by
        summing the voltages of multiple elements, e.g. MWA), "fixed" (antenna
        beam pattern is fixed in azimuth and elevation, e.g., HERA), and "other"
        (also referred to in some formats as "bizarre"). See the "Conventions"
        page of the documentation for further details.  Default is "fixed".
    polarization_array : ndarray of str or int
        Array of polarization integers or strings (eg. 'xx' or 'ee'). Must be
        provided for a power beam, otherwise an efield beam is assumed.
    x_orientation : str, optional
        Orientation of the x-axis. Options are 'east', 'north', 'e', 'n', 'ew', 'ns'.
        Ignored in feed_angle is set.
    pixel_coordinate_system : str
        Pixel coordinate system, options are "az_za", "orthoslant_zenith" and "healpix".
        Forced to be "healpix" if ``nside`` is given and by *default* set to
        "az_za" if not.
    axis1_array : ndarray of float
        Coordinates along first pixel axis (e.g. azimuth for an azimuth/zenith
        angle coordinate system). Must be regularly spaced. Should not provided
        for healpix coordinates.
    axis2_array : ndarray of float
        Coordinates along second pixel axis (e.g. zenith angle for an azimuth/zenith
        angle coordinate system). Must be regularly spaced. Should not provided
        for healpix coordinates.
    nside : int
        Healpix nside parameter, should only be provided for healpix coordinates.
    healpix_pixel_array : ndarray of int
        Healpix pixels to include. If nside is provided, defaults to all the pixels
        in the Healpix map.
    ordering : str
        Healpix ordering parameter, defaults to "ring" if nside is provided.
    basis_vector_array : ndarray of float
        Beam basis vector components, essentially the mapping between the
        directions that the electrical field values are recorded in to the
        directions aligned with the pixel coordinate system (or azimuth/zenith
        angle for HEALPix beams). Defaults to unit vectors aligned with the
        pixel coordinate systems for E-field beams.
    bandpass_array : ndarray of float
        Frequency dependence of the beam. Depending on the ``data_normalization``
        this may contain only the frequency dependence of the receiving chain
        ("physical" normalization) or all the frequency dependence ("peak"
        normalization). Must be the same length as the ``freq_array``. Defaults
        to an array of all ones the length of the ``freq_array``.
    element_location_array : ndarray of float
        Array of phased array element locations in the element_coordinate_system.
        Must be a 2 dimensional array where the first dimension indexes the
        coordinate system (so should be length 2) and the second dimension indexes
        the phased array elements. Only used for phase array antennas.
    element_coordinate_system : str
        Coordinate system for describing the layout of a phased array feed.
        Options are: n-e or x-y. Defaults to "x-y" if ``element_location_array``
        is provided. Only used for phase array antennas.
    delay_array : ndarray of float
        Array of element delays in seconds. Defaults to an array of all zeros if
        ``element_location_array`` is provided. Only used for phase array antennas.
    gain_array : ndarray of float
        Array of element gains in dB. Defaults to an array of all ones if
        ``element_location_array`` is provided. Only used for phase array antennas.
    coupling_matrix : ndarray of float
        Matrix of complex element couplings in dB. Must be an ndarray of shape
        (Nelements, Nelements, Nfeeds, Nfeeds, Nfreqs). Defaults to an array
        with couplings of one for the same element and zero for other elements if
        ``element_location_array`` is provided. Only used for phase array antennas.
    data_array : ndarray of float, optional
        Either complex E-field values (if `feed_array` is given) or power values
        (if `polarization_array` is given) for the beam model. Units are
        normalized to either peak or solid angle as given by data_normalization.
        If None (the default), the data_array is initialized to an array of the
        appropriate shape and type containing all zeros.
    history : str, optional
        History string to be added to the object. Default is a simple string
        containing the date and time and pyuvdata version.
    \*\*kwargs
        All other keyword arguments are added to the object as attributes.

    Returns
    -------
    UVCal
        A new UVCal object with default parameters.


Read the data from a beamfits file.


Write the data to a beamfits file.


        Pop the first recorded warning, raise exception if not exists.

        Parameters
        ----------
        cls : Warning
            Warning class to check for.


    Assert that code raises a particular set of warnings, used as a context manager.

    Similar to ``pytest.warns``, but allows for specifying multiple warnings.
    It also better matches warning strings when the warning uses f-strings or
    formating. Can be used as a drop-in replacement for ``pytest.warns`` if
    only one warning is issued (if more are issued they will need to be added
    to the input lists for this to pass).

    Note that unlike the older checkWarnings function, the warnings can be passed
    in any order, they do not have to match the order the warnings are raised
    in the code.

    To assert that there are no warnings raised by some code, set `expected_warning`
    to None (i.e. `with check_warnings(None):`)

    Parameters
    ----------
    expected_warning : list of Warnings or Warning
        List of expected warnings. If a single warning type or a length 1 list,
        will be used for the type of all warnings.
    match : str or regex or list of str or regex
        List of strings or regexes to match warnings to. If a str or a length 1
        list, will be used for all warnings.
    nwarnings : int, optional
        Option to specify that multiple of a single type of warning is expected.
        Only used if category and match both only have one element.


Parse numbers from a range string.


Test memory usage of read_uvfits.


Do a.

        Some long description.

        Parameters
        ----------
        x : int
            The x parameter.
        y : int
            The y parameter.

        Returns
        -------
        int
            The sum of x and y.


Do c.

        Parameters
        ----------
        z : int
            The z parameter.


Make initial uvcalibrate inputs.


Make function level initial uvcalibrate inputs.


Make uvcalibrate inputs.


Make function level uvcalibrate inputs.


Sort a tuple that starts with a pair of antennas, and may have stuff after.


Make modified version of 1-freq efield beam.


Make modified version of 2-freq efield beam.


Setup and teardown for basic parameter, property and iterator tests.


Make the default CST testing beam.


Downselect a beam to a small sky area to speed tests up.


Make a single freq version with expected history.


Make session level 2-freq efield beam.


Make function level 2-freq efield beam.


Make session level cut down 2-freq efield beam.


Make function level cut down 2-freq efield beam.


Make session level cut down HEALPix 2-freq efield beam.


Make function level cut down HEALPix 2-freq efield beam.


Make session level single freq efield beam.


Make function level single freq efield beam.


Make session level cut down single freq efield beam.


Make function level cut down single freq efield beam.


Make session level HEALPix cut down single freq efield beam.


Make function level HEALPix cut down single freq efield beam.


Make session level 2-freq power beam.


Make session level cut down 2-freq power beam.


Make function level cut down 2-freq power beam.


Make session level HEALPix cut down 2-freq power beam.


Make function level HEALPix cut down 2-freq power beam.


Make session level single freq power beam.


Make function level single freq power beam.


Make session level cut down single freq power beam.


Make function level cut down single freq power beam.


Make session level HEALPix cut down single freq power beam.


Make function level HEALPix cut down single freq power beam.


Basic phased_array beam for testing.


Set up some uvcal iter tests.


Read in gain calfits file.


Make function level gain uvcal object.


Read in delay calfits file.


Make function level delay uvcal object.


Read in raw FHD cal.


Make function raw FHD cal object.


Read in fit FHD cal.


Make function fit FHD cal object.


Some setup info for ENU/ECEF calculations.


Write miriad file, capturing warnings for pytest

    Parameters:
    -----------
    uv: UVData
        uvdata object to call write_miriad on
    filename: str
        Name of file to write to
    warn: str or None
        warnings to catch. Defaults to catch 'writing default values ...'


Read in CASA tutorial uvfits file.


Make function level CASA tutorial uvfits object.


Make function level NRAO ms object.


    Make a uvh5 file with all zero values for data-sized arrays.

    This function is a helper function used for tests of partial writing.


    Make a uvh5 file with all zeros for data-sized arrays.

    This function is a helper function used for tests of partial writing with
    integer data types.


Modify the file to have the old shapes


Sample an COMPAS h5 file.

    Parameters
    ----------
    compas_h5_filepath : str
        Path to the COMPAS h5 file.
    output_filepath : Optional[str], optional
        Path to the output COMPAS h5 file, by default None.
        If None, the output filepath will be the input filepath with "_sampled" appended.
    n : Optional[int], optional
        Number of binaries to sample, by default None.
    frac : Optional[float], optional
        Fraction of binaries to sample, by default None.
    replace : Optional[bool], optional
        Sample with or without replacement, by default False.
    seed_group : Optional[str], optional
        Group to get binary seed list to sample from, by default "BSE_System_Parameters".
    seed_key : Optional[str], optional
        Key to get binary seed list to sample from, by default "SEED".

    Raises
    ------
    ValueError
        Must specify either n or frac.
        n must be greater than 0.
        Cannot sample without replacement more than the number of binaries. Set replace=True.

    Returns
    -------
    None
        A new COMPAS h5 file will be created at the output filepath.


Use regex to parse latex maths into tokens of subscript, superscript or neither

    Parameters
    ----------
    latex_expr : str
        The input latex maths expression

    Returns
    -------
    list
        List of tuples, where the first item of the tuple is one of 'superscript', 'subscript' or 'text',
        and the second item of the tuple is the corresponding part of the expression


Takes a string, which may have latex maths expressions inside (i.e. surrounded by $),
    and returns a list of tokens determining whether the text should be sub-/superscript,
    and replacing some latex commands such as \\odot

    Parameters
    ----------
    input_string : str
        String to be parsed

    Returns
    -------
    list
        List of tuples, where the first item of the tuple is one of 'superscript', 'subscript' or 'text',
        and the second item of the tuple is the corresponding part of the string


    This function takes a sorted array of floats (in this case, event times)
    and spaces them out from each other to have a minimum separation min_separation.

    The purpose of this is so that the event letters don't overlap on the plot.

    Idea of this function: for each pair which is too close, subtract off
    some amount (nudge) from the lower, add the same amount to the upper,
    and do this over the whole range. For big clumps, the middle ones won't move
    (+/- will cancel out), but as the outer ones move away, the inner ones will
    have room to stretch out.


This function prints a synopsis of the evolutionary history to the command line; it can eventually include cartoons as well.


        This function generates a dictionary mapping COMPAS options to their specified
        values (or empty strings for boolean options). These are then combined into a string
        that can be run directly as a terminal command, or passed to the stroopwafel interface
        where some of them may be overwritten. Options not to be included in the command
        line should be set to pythons None (except booleans, which should be set to False)


    #
    # Step 1
    #
    # Vector of primary masses M1 (Msun), logarithmic orbital period P (days),
    # mass ratios q = Mcomp/M1, and eccentricities e
    #


    This Function that will create all the dimensions for stroopwafel, a dimension is basically one of the variables you want to sample
    Invoke the Dimension class to create objects for each variable. Look at the Dimension class definition in classes.py for more.
    It takes the name of the dimension, its max and min value.
    The Sampler class will tell how to sample this dimension. Similarly, prior tells it how it calculates the prior. You can find more of these in their respective modules
    OUT:
        As Output, this should return a list containing all the instances of Dimension class.


    This function is not mandatory, it is required only if you have some dependent variable.
    For example, if you want to sample Mass_1 and q, then Mass_2 is a dependent variable which is product of the two.
    Similarly, you can assume that Metallicity_2 will always be equal to Metallicity_1
    IN:
        locations (list(Location)) : A list containing objects of Location class in classes.py.
        You can play with them and update whatever fields you like or add more in the property (which is a dictionary)
    OUT: Not Required


    This function tells stroopwafel what program to run, along with its arguments.
    IN:
        batch(dict): This is a dictionary which stores some information about one of the runs. It has an number key which stores the unique id of the run
            It also has a subprocess which will run under the key process. Rest, it depends on the user. User is free to store any information they might need later
            for each batch run in this dictionary. For example, here I have stored the 'output_container' and 'grid_filename' so that I can read them during discovery of interesting systems below
    OUT:
        compas_args (list(String)) : This defines what will run. It should point to the executable file along with the arguments.
        Additionally one must also store the grid_filename in the batch so that the grid file is created


    This is a mandatory function, it tells stroopwafel what an interesting system is. User is free to define whatever looks interesting to them.
    IN:
        batch (dict): As input you will be given the current batch which just finished its execution. You can take in all the keys you defined in the configure_code_run method above
    OUT:
        Number of interesting systems
        In the below example, I define all the NSs as interesting, so I read the files, get the SEED from the system_params file and define the key is_hit in the end for all interesting systems


    This is not a mandatory function, it was written to support selection effects
    Fills in selection effects for each of the distributions
    IN:
        sw (Stroopwafel) : Stroopwafel object


    This method takes a list of locations and marks the systems which can be
    rejected by the prior distribution
    IN:
        locations (List(Location)): list of location to inspect and mark rejected
    OUT:
        num_rejected (int): number of systems which can be rejected


        Given limits on the redshift, create an array of redshifts, times, distances and volumes

        Args:
            max_redshift           --> [float]          Maximum redshift to use for calculations
            max_redshift_detection --> [float]          Maximum redshift to calculate detection rates (must be <= max_redshift)
            redshift_step          --> [float]          size of step to take in redshift
            z_first_SF             --> [float]          redshift of first star formation

        Returns:
            redshifts              --> [list of floats] List of redshifts between limits supplied
            n_redshifts_detection  --> [int]            Number of redshifts in list that should be used to calculate detection rates
            times                  --> [list of floats] Equivalent of redshifts but converted to age of Universe
            distances              --> [list of floats] Equivalent of redshifts but converted to luminosity distances
            shell_volumes          --> [list of floats] Equivalent of redshifts but converted to shell volumes


        Calculate the star forming mass per unit volume per year following
        Neijssel+19 Eq. 6, using functional form of Madau & Dickinson 2014

        Args:
            redshifts --> [list of floats] List of redshifts at which to evaluate the sfr

        Returns:
            sfr       --> [list of floats] Star forming mass per unit volume per year for each redshift


    Calculate the distribution of metallicities at different redshifts using a log skew normal distribution
    the log-normal distribution is a special case of this log skew normal distribution distribution, and is retrieved by setting
    the skewness to zero (alpha = 0).
    Based on the method in Neijssel+19. Default values of mu0=0.035, muz=-0.23, sigma_0=0.39, sigma_z=0.0, alpha =0.0,
    retrieve the dP/dZ distribution used in Neijssel+19.  See van Son+2022 for skewed log normal distribution.

    NOTE: This assumes that metallicities in COMPAS are drawn from a flat in log distribution!

    Args:
        max_redshift       --> [float]          max redshift for calculation
        redshift_step      --> [float]          step used in redshift calculation
        min_logZ_COMPAS    --> [float]          Minimum logZ value that COMPAS samples
        max_logZ_COMPAS    --> [float]          Maximum logZ value that COMPAS samples

        mu0    =  0.035    --> [float]          location (mean in normal) at redshift 0
        muz    = -0.23    --> [float]           redshift scaling/evolution of the location (alpha in Neijssel+19)
        sigma_0 = 0.39     --> [float]          Scale (variance in normal) at redshift 0 (sigma in Neijssel+19)
        sigma_z = 0.00     --> [float]          redshift scaling of the scale (variance in normal, 0 in Neijssel+19)
        alpha   = 0.00    --> [float]           shape (skewness, alpha = 0 retrieves normal dist as in Neijssel+19)

        min_logZ           --> [float]          Minimum logZ at which to calculate dPdlogZ (influences normalization)
        max_logZ           --> [float]          Maximum logZ at which to calculate dPdlogZ (influences normalization)
        step_logZ          --> [float]          Size of logZ steps to take in finding a Z range

    Returns:
        dPdlogZ            --> [2D float array] Probability of getting a particular logZ at a certain redshift
        metallicities      --> [list of floats] Metallicities at which dPdlogZ is evaluated
        p_draw_metallicity --> float            Probability of drawing a certain metallicity in COMPAS (float because assuming uniform)


        Find both the formation and merger rates for each binary at each redshift

        Args:
            n_binaries          --> [int]            Number of DCO binaries in the arrays
            redshifts           --> [list of floats] Redshifts at which to evaluate the rates
            times               --> [list of floats] Equivalent of the redshifts in terms of age of the Universe
            n_formed            --> [float]          Binary formation rate (number of binaries formed per year per cubic Gpc) represented by each simulated COMPAS binary
            dPdlogZ             --> [2D float array] Probability of getting a particular logZ at a certain redshift
            metallicities       --> [list of floats] Metallicities at which dPdlogZ is evaluated; if this is None, assume that metallicity weighting is 1 (corresponds to all SFR happening at one fixed metallicity)
            p_draw_metallicity  --> [float]          Probability of drawing a certain metallicity in COMPAS (float because assuming uniform)
            COMPAS_metallicites --> [list of floats] Metallicity of each binary in COMPAS data
            COMPAS_delay_times  --> [list of floats] Delay time of each binary in COMPAS data
            COMPAS_weights      --> [list of floats] Adaptive sampling weights for each binary in COMPAS data (defaults to all 1s for unweighted samples)

        Returns:
            formation_rate      --> [2D float array] Formation rate for each binary at each redshift
            merger_rate         --> [2D float array] Merger rate for each binary at each redshift


        Compute a grid of SNRs and detection probabilities for a range of masses and SNRs

        These grids are computed to allow for interpolating the values of the snr and detection probability. This function
        combined with find_detection_probability() could be replaced by something like
            for i in range(n_binaries):
                detection_probability = selection_effects.detection_probability(COMPAS.mass1[i],COMPAS.mass2[i],
                                            redshifts, distances, GWdetector_snr_threshold, GWdetector_sensitivity)
        if runtime was not important.

        Args:
            sensitivity                    --> [string]         Which detector sensitivity to use: one of ["design", "O1", "O3"]
            snr_threshold                  --> [float]          What SNR threshold required for a detection
            Mc_max                         --> [float]          Maximum chirp mass in grid
            Mc_step                        --> [float]          Step in chirp mass to use in grid
            eta_max                        --> [float]          Maximum symmetric mass ratio in grid
            eta_step                       --> [float]          Step in symmetric mass ratio to use in grid
            snr_max                        --> [float]          Maximum snr in grid
            snr_step                       --> [float]          Step in snr to use in grid

        Returns:
            snr_grid_at_1Mpc               --> [2D float array] The snr of a binary with masses (Mc, eta) at a distance of 1 Mpc
            detection_probability_from_snr --> [list of floats] A list of detection probabilities for different SNRs


        Compute the detection probability given a grid of SNRs and detection probabilities with masses

        Args:
            Mc                             --> [list of floats] Chirp mass of binaries in COMPAS
            eta                            --> [list of floats] Symmetric mass ratios of binaries in COMPAS
            redshifts                      --> [list of floats] List of redshifts
            distances                      --> [list of floats] List of distances corresponding to redshifts
            n_redshifts_detection          --> [int]            Index (in redshifts) to which we evaluate detection probability
            n_binaries                     --> [int]            Number of merging binaries in the COMPAS file
            snr_grid_at_1Mpc               --> [2D float array] The snr of a binary with masses (Mc, eta) at a distance of 1 Mpc
            detection_probability_from_snr --> [list of floats] A list of detection probabilities for different SNRs
            Mc_step                        --> [float]          Step in chirp mass to use in grid
            eta_step                       --> [float]          Step in symmetric mass ratio to use in grid
            snr_step                       --> [float]          Step in snr to use in grid


        The main function of this file. Finds the detection rate, formation rate and merger rate for each
        binary in a COMPAS file at a series of redshifts defined by input. Also returns relevant COMPAS
        data.

        NOTE: This code assumes that assumes that metallicities in COMPAS are drawn from a flat in log distribution

        Args:
            ===================================================
            == Arguments for finding and masking COMPAS file ==
            ===================================================
            path                   --> [string] Path to the COMPAS data file that contains the output
            dco_type               --> [string] Which DCO type to calculate rates for: one of ["all", "BBH", "BHNS", "BNS"]
            merger_output_filename --> [string] Optional name of output file to store merging DCOs (do not create the extra output if None)
            weight_column          --> [string] Name of column in "DoubleCompactObjects" file that contains adaptive sampling weights
                                                    (Leave this as None if you have unweighted samples)
            merges_in_hubble_time  --> [bool]   whether to mask binaries that don't merge in a Hubble time
            no_RLOF_after_CEE      --> [bool]   whether to mask binaries that have immediate RLOF after a CCE
            pessimistic_CEE        --> [bool]   whether to mask binaries that go through Optimistic CE scenario

            ===========================================
            == Arguments for creating redshift array ==
            ===========================================
            max_redshift           --> [float]  Maximum redshift to use in array
            max_redshift_detection --> [float]  Maximum redshift to calculate detection rates (must be <= max_redshift)
            redshift_step          --> [float]  Size of step to take in redshift

            ====================================================================
            == Arguments for determining star forming mass per sampled binary ==
            ====================================================================
            use_sampled_mass_ranges--> [bool]   whether to use the min and max m1 and m2 samples in lieu of hard cutoffs as below
            m1_min                 --> [float]  Minimum primary mass sampled by COMPAS
            m1_max                 --> [float]  Maximum primary mass sampled by COMPAS
            m2_min                 --> [float]  Minimum secondary mass sampled by COMPAS
            fbin                   --> [float]  Binary fraction used by COMPAS

            =======================================================================
            == Arguments for creating metallicity distribution and probabilities ==
            =======================================================================
            mu0                    --> [float]  metallicity dist: expected value at redshift 0
            muz                    --> [float]  metallicity dist: redshift evolution of expected value
            sigma0                 --> [float]  metallicity dist: width at redshhift 0
            sigmaz                 --> [float]  metallicity dist: redshift evolution of width
            alpha                  --> [float]  metallicity dist: skewness (0 = lognormal)
            min_logZ               --> [float]  Minimum logZ at which to calculate dPdlogZ
            max_logZ               --> [float]  Maximum logZ at which to calculate dPdlogZ
            step_logZ              --> [float]  Size of logZ steps to take in finding a Z range

            =======================================================
            == Arguments for determining detection probabilities ==
            =======================================================
            sensitivity            --> [string] Which detector sensitivity to use: one of ["design", "O1", "O3"]
            snr_threshold          --> [float]  What SNR threshold required for a detection
            Mc_max                 --> [float]  Maximum chirp mass in grid
            Mc_step                --> [float]  Step in chirp mass to use in grid
            eta_max                --> [float]  Maximum symmetric mass ratio in grid
            eta_step               --> [float]  Step in symmetric mass ratio to use in grid
            snr_max                --> [float]  Maximum snr in grid
            snr_step               --> [float]  Step in snr to use in grid

        Returns:
            detection_rate         --> [2D float array] Detection rate for each binary at each redshift in 1/yr
            formation_rate         --> [2D float array] Formation rate for each binary at each redshift in 1/yr/Gpc^3
            merger_rate            --> [2D float array] Merger rate for each binary at each redshift in 1/yr/Gpc^3
            redshifts              --> [list of floats] List of redshifts
            COMPAS                 --> [Object]         Relevant COMPAS data in COMPASData Class


        Append the formation rate, merger rate, detection rate and redshifts as a new group to your COMPAS output with weights hdf5 file

        Args:
            path                   --> [string] Path to the COMPAS file that contains the output
            detection_rate         --> [2D float array] Detection rate for each binary at each redshift in 1/yr
            formation_rate         --> [2D float array] Formation rate for each binary at each redshift in 1/yr/Gpc^3
            merger_rate            --> [2D float array] Merger rate for each binary at each redshift in 1/yr/Gpc^3
            redshifts              --> [list of floats] List of redshifts
            COMPAS                 --> [Object]         Relevant COMPAS data in COMPASData Class
            n_redshifts_detection  --> [int]            Number of redshifts in list that should be used to calculate detection rates

            maxz                   --> [float] Maximum redshhift up to where we would like to store the data
            sensitivity            --> [string] Which detector sensitivity you used to calculate rates
            dco_type               --> [string] Which DCO type you used to calculate rates
            mu0                    --> [float]  metallicity dist: expected value at redshift 0
            muz                    --> [float]  metallicity dist: redshift evolution of expected value
            sigma0                 --> [float]  metallicity dist: width at redshift 0
            sigmaz                 --> [float]  metallicity dist: redshift evolution of width
            alpha                  --> [float]  metallicity dist: skewness (0 = lognormal)

            append_binned_by_z     --> [Bool] to save space, bin rates by redshiftbin and append binned rates
            redshift_binsize       --> [float] if append_binned_by_z, how big should your redshift bin be

        Returns:
            h_new                  --> [hdf5 file] Compas output file with a new group "rates" with the same shape as DoubleCompactObjects x redshifts


        Delete the group containing all the rate information from your COMPAS output with weights hdf5 file

        Args:
            path                   --> [string] Path to the COMPAS file that contains the output

            mu0                    --> [float]  metallicity dist: expected value at redshift 0
            muz                    --> [float]  metallicity dist: redshift evolution of expected value
            sigma0                 --> [float]  metallicity dist: width at redshhift 0
            sigmaz                 --> [float]  metallicity dist: redshift evolution of width
            alpha                  --> [float]  metallicity dist: skewness (0 = lognormal)
            append_binned_by_z     --> [Bool] to save space, bin rates by redshiftbin and append binned rates


        Show a summary plot of the results, it also returns the summaries that it computes

        Args:
            save_dir                  --> [string] path where you would like to save your plot
            formation_rate            --> [2D float array] Formation rate for each binary at each redshift in 1/yr/Gpc^3
            merger_rate               --> [2D float array] Merger rate for each binary at each redshift in 1/yr/Gpc^3
            detection_rate            --> [2D float array] Detection rate for each binary at each redshift in 1/yr
            redshifts                 --> [list of floats] List of redshifts
            chirp_masses              --> [list of floats] Chrirp masses of merging DCO's

            show_plot                 --> [bool] Bool whether to show plot or not
            mu0                       --> [float]  metallicity dist: expected value at redshift 0
            muz                       --> [float]  metallicity dist: redshift evolution of expected value
            sigma0                    --> [float]  metallicity dist: width at redshhift 0
            sigmaz                    --> [float]  metallicity dist: redshift evolution of width
            alpha                     --> [float]  metallicity dist: skewness (0 = lognormal)

        Returns:
            matplotlib figure


    Returns the detection probability of a CBC event with given
    masses and distance.

    This function is a convenience function to generate the
    interpolator with 'SNR_Grid_IMRPhenomPv2_FD_all_noise.hdf5'
    and 'SimNoisePSDaLIGODesignSensitivityP1200087', redshift the
    masses, rescale the SNR using the distance, and then call
    'detection_probability_from_snr' to return the probability.

    Parameters
    ----------
    m1, m2 : float > 0
        Primary and secondary mass in source frame.
    redshift : float >= 0
        Redshift of the waveform through cosmology.
    distance : float > 0
        Luminosity Distance in Mpc to the source.
    snr_threshold : float > 0
        Threshold above which an event is considered to be detected.
    sensitivity : str
        Which detector sensitivity PSD to use. Options are 'design' and 'O1'

    Returns
    -------
    out : float
        Estimate of the detection probability.

    Notes
    -----
    The interpolator is only initialized once and then stored in a
    module level global variable to be reused.


    Returns an Interpolator class instance for a given sensitivity

    This function is a convenience function to generate the
    interpolator with 'SNR_Grid_IMRPhenomPv2_FD_all_noise.hdf5'
    and 'SimNoisePSDaLIGODesignSensitivityP1200087'.

    Parameters
    ----------
    sensitivity : str
    Which detector sensitivity PSD to use. Options are 'design' and 'O1'

    Returns
    -------
    out : Interpolator
    Interpolator class instance

    Notes
    -----
    The interpolator is only initialized once and then stored in a
    module level global variable to be reused.


        Custom function to approximate the value of any given point
        within the limits of the grid. The value is calculated as the
        average value of the 4 corners of the grid, weighed by the
        inverse distance to (m1, m2). Points for which the SNR is
        NaN are ignored.

        Parameters
        ----------
        m1, m2 : float
            Positive values for which the interpolated SNR is calculated.

        Returns
        -------
        out : float
            Estimate for the SNR at (m1, m2).


    Compute the probability of detecting an CBC with given SNR and
    threshold, averaging over all orientations and sky positions.

    Based of Finn & Chernoff 1993 (https://arxiv.org/abs/gr-qc/9301003).

    Parameters
    ----------
    snr_value : float or array of floats
        SNR value of the event under ideal conditions. Must be positive.
    snr_threshold : float
        SNR threshold for detection. Must be positive.
    n_thetas : unsigned int
        Number of random realizations of inclination and sky position
        used to calculate the average probability of detecting the
        event. Default: 1e6.

    Returns
    -------
    out : float or array of floats (same as 'snr_value')
        Probability of the received signal to be above the threshold.


Calculate the fraction of stellar mass between m and m + dm for a three part broken power law.

    Default values follow Kroupa (2001)
    https://arxiv.org/abs/astro-ph/0009005
    Equation 1-2

            zeta(m) ~ m^(-a_ij)
    Parameters
    ----------
    m : `float` or `np.ndarray`
        Mass at which to evaluate
    mi : float, optional
        masses at which to transition the slope
    aij : float, optional
        slope of the IMF between mi and mj
    Returns
    -------
    imf_vals
        IMF evaluated at the given masses


Calculate the total mass evolved per metallicity as a function of redshift in a COMPAS simulation.


Calculate the total mass of stars formed per binary star formed within the COMPAS simulation.


Draw samples from the Kroupa IMF


    Analytical computation of the mass of stars formed per binary star formed within the
    [m1 min, m1 max] and [m2 min, ..] rage,
    using the Kroupa IMF:

        p(M) \propto M^-0.3 for M between m1 and m2
        p(M) \propto M^-1.3 for M between m2 and m3;
        p(M) = alpha * M^-2.3 for M between m3 and m4;

    @Ilya Mandel's derivation


Calculates the bins used in the Riemann sum over metallicities


        This function translates between

        logOH12  = number density of oxygen to hyrdogen
        logZZsun = metallicity mass fraction in solar units

        asssumptions: logOH12sun
        The solar number density from oxygen to hydrogen.
        This assumption is non-trivial and can affect results


        Returns the fraction of the SFR.
        It combines a
        -  MZ -relation     : galaxy stellar mass - metallicity relatiion
                              This translates a metallicity to a
                              a galaxy stellar mass which has the same
                              average metallicity.
        -  GSMF function    : Galaxy stellar mass function
                              A density function of the distribution of galaxy stellar masses.

        The entire GSMF is the mass in all stars in all galaxies.
        Hence the fraction of the GSMF is the fraction of the stellar
        mass in all galaxies at that time. We assume that the
        average cosmic SFR spreads evenly among all the galaxy stellar mass.
        Meaning a galaxy with a stellar mass twice that of another galaxy, has twice
        the SFR. Hence this method does not include local star burts (SMC/LMC for example)

        The overall idea. Given a metallicity bin with upper and lower bound.
        Translate this to a galaxy stellar mass bin with upper and lower bound using
        a MZ-relation. Then find the fraction of the GSMF density function that is taken by
        this glaxy stellar mass bin. We assumed that the fraction of the stellar mass is
        proportional to the fraction of the SFR. Hence we multiply this fraction by the SFR.
        Note that because we take "cosmological averages" this method does not take into
        account galaxy specific metallicity distributions.


fingerspitzengefuhl Cosmic integration paper


Custom SFR same functional form as Madau et al


        Instead of combining a GSMF and MZ relation
        you can also directly construct a redshift dependent metallicity distribution

        In this case we focus on a log-normal distribution

        log10(Z) is normally distributed with:

        meanM  = log(Zmean)
                 This is redshift dependent and Zmean scales as
                 Zmean = Z0 * 10^(alpha * redshift)
                 Z0 is the mean metallicity at redshift zero
                 alpha is the scaling of the redshift

        sigma  = the standard deviation of log(Z) distribution
                 we assume for now that this is redshift independent


        This is the main function called in the cosmic integration routine.

        For a given binNr in the metallicity bins it calculates the MSSFR


Allows users to bin data in post-processing


Computes bootstrapped rate matrices


    Compute the detection rate matrix for a given BBH population and cosmological model.

    If the GPU is available, this function moves the np.ndarray objects to the GPU and perform the computation there.
    If the GPU is not available, this function will perform the computation on the CPU.


    Compute the detection rate matrix for a given BBH population and cosmological model.
    :return:
        np.ndarray of shape (len(chirp_mass_bins), len(redshift_bins))


Plot the detection rate matrix as a 2D heatmap with marginal histograms.


Bin data2d and data1d along the given axis using the given 1d bins


    Make a temporary ini file for testing
    uncomment all default options to ensure they can be parsed


Check that all expected_kwgs are in stdout


Get the path to the COMPAS output file generated by the test suite.

    (This is a fixture so it can passed as a parameter to other tests)


Convert a python file to a notebook


    :param notebook_filename: path of notebook to process
    :return: bool if notebook-preprocessing successful/unsuccessful


    Function to print all files with their column names/length/unit
    Returns nothing, just prints to cell/terminal
    Most of the function is for nice spacing


    Returns the left-hand riemann sum of a function in an interval (approximate definite integral), given a step size

        Parameters:
            array (1D array): An array with the values of your function at a certain interval (units: anything)
            stepSize (number): The step size used to integrate your function (units: anything really)

        Returns:
            sum (number): The left-hand riemann sum of the function in the specified interval (units: anything)


Function to print the full Compas output for given seeds, optionally with an additional mask


    Function to produce a string representing the event history of a single binary for quick readability.
    IN:
        events (list of tuples): events output from getEventHistory()
    OUT:
        eventString (string): string representing the event history of the binary

    MT strings look like:
        P>S, P<S, or P=S where P is primary type, S is secondary type,
        and >, < is RLOF (1->2 or 1<-2) or = for CEE

    SN strings look like:
        P*SR for star1 the SN progenitor,or
        R*SP for star2 the SN progenitor,
        where P is progenitor type, R is remnant type,
        S is state (I for intact, U for unbound)

    Event strings for the same seed are separated by the undesrcore character ('_')


Get the main sequence lifetime of a star with mass m and metallicity Z using Hurley+2000


        This function generates a dictionary mapping COMPAS options to their specified
        values (or empty strings for boolean options). These can be combined into a string
        and run directly as a terminal command, or passed to the stroopwafel interface
        where some of them may be overwritten. Options not to be included in the command
        line should be set to pythons None (except booleans, which should be set to False)

        Parameters
        -----------
        self : pythonProgramOptions
            Contains program options

        Returns
        --------
        commands : str or list of strs


    Write out the compas input parameters into a shell string.
    Ensure the Compas executable is first, and not repeated.
    Options are non-ordered.


clean up string parameters to avoid confusing Boost


Get the range of masses, corresponding maximum radii as well as R_ZAMS


 plot the maximum radius of each stellar type

    Parameters
    ----------
    masses : `float/array`
        Mass of each star

    R_ZAMS : `float/array`
        Radius at ZAMS (corresponding to each mass)

    max_R : `float/array`
        Maximum radius for stellar types 1-9 (corresponding to each mass)

    Z : `float`
        Metallicity of the stars

    mass_label_list : `tuple/array`
        A list of mass labels in the form (mass, label)

    mass_label_loc : `float`
        Y value of each mass label

    zloc : `tuple`
        Where to put the metallicity annotation

    stellar_type_list : `boolean`
        Whether to include the list of stellar types

    fig : `figure`, optional
        Matplotlib figure to, by default None

    ax : `axis`, optional
        Matplotlib axis to use, by default None

    show : `bool`, optional
        Whether to immediately show the plot or just return it, by default True


        This function generates a dictionary mapping COMPAS options to their specified
        values (or empty strings for boolean options). These are then combined into a string
        that can be run directly as a terminal command, or passed to the stroopwafel interface
        where some of them may be overwritten. Options not to be included in the command
        line should be set to pythons None (except booleans, which should be set to False)


Plot a Hertzsprung-Russel diagram from COMPAS Output

    Parameters
    ----------
    folder_name : `string`
        The name of the folder containing the COMPAS output

    file_numbers : `array of ints`
        Which individual detailed output files to plot

    fig : `figure`, optional
        Matplotlib figure to, by default None

    ax : `axis`, optional
        Matplotlib axis to use, by default None

    show : `bool`, optional
        Whether to immediately show the plot or just return it, by default True

    lines : `bool`, optional
        Whether to use lines or scatter points, by default True

    label_loc : `'start' or 'end'`, optional
        Location of mass labels ("), by default "start"

    max_ev_time : `float`, optional
        The maximum evolution time of the star to plot, by default 13700.0

    stellar_type_range : `array of ints`, optional
        Which stellar types to plot, by default range(1, 13)

    stellar_type_list : `bool`, optional
        Whether to include an annotation of the list of stellar types, by default True

    LBV_regime : `bool`, optional
        Whether to shade the LBV regime, by default True

    LBV_loc : `tuple`, optional
        Location of LBV regime annotation (ignored if ``LBV_regime`` is False), by default (0.77, 0.93)

    plot_R_lines : `bool`, optional
        Whether to plot lines of constant radii, by default True


        Given limits on the redshift, create an array of redshifts, times, distances and volumes
        Args:
            max_redshift           --> [float]          Maximum redshift to use for calculations
            max_redshift_detection --> [float]          Maximum redshift to calculate detection rates (must be <= max_redshift)
            redshift_step          --> [float]          size of step to take in redshift
            z_first_SF             --> [float]          redshift of first star formation
        Returns:
            redshifts              --> [list of floats] List of redshifts between limits supplied
            n_redshifts_detection  --> [int]            Number of redshifts in list that should be used to calculate detection rates
            times                  --> [list of floats] Equivalent of redshifts but converted to age of Universe
            distances              --> [list of floats] Equivalent of redshifts but converted to luminosity distances
            shell_volumes          --> [list of floats] Equivalent of redshifts but converted to shell volumes


        Calculate the star forming mass per unit volume per year following
        Neijssel+19 Eq. 6, using functional form of Madau & Dickinson 2014
        Args:
            redshifts --> [list of floats] List of redshifts at which to evaluate the sfr
        Returns:
            sfr       --> [list of floats] Star forming mass per unit volume per year for each redshift


    Calculate the distribution of metallicities at different redshifts using a log skew normal distribution
    the log-normal distribution is a special case of this log skew normal distribution distribution, and is retrieved by setting
    the skewness to zero (alpha = 0).
    Based on the method in Neijssel+19. Default values of mu0=0.035, muz=-0.23, sigma_0=0.39, sigma_z=0.0, alpha =0.0,
    retrieve the dP/dZ distribution used in Neijssel+19
    NOTE: This assumes that metallicities in COMPAS are drawn from a flat in log distribution!
    Args:
        max_redshift       --> [float]          max redshift for calculation
        redshift_step      --> [float]          step used in redshift calculation
        min_logZ_COMPAS    --> [float]          Minimum logZ value that COMPAS samples
        max_logZ_COMPAS    --> [float]          Maximum logZ value that COMPAS samples

        mu0    =  0.035    --> [float]           location (mean in normal) at redshift 0
        muz    = -0.25    --> [float]           redshift scaling/evolution of the location
        sigma_0 = 0.39     --> [float]          Scale (variance in normal) at redshift 0
        sigma_z = 0.00     --> [float]          redshift scaling of the scale (variance in normal)
        alpha   = 0.00    --> [float]          shape (skewness, alpha = 0 retrieves normal dist)
        min_logZ           --> [float]          Minimum logZ at which to calculate dPdlogZ (influences normalization)
        max_logZ           --> [float]          Maximum logZ at which to calculate dPdlogZ (influences normalization)
        step_logZ          --> [float]          Size of logZ steps to take in finding a Z range
    Returns:
        dPdlogZ            --> [2D float array] Probability of getting a particular logZ at a certain redshift
        metallicities      --> [list of floats] Metallicities at which dPdlogZ is evaluated
        p_draw_metallicity --> float            Probability of drawing a certain metallicity in COMPAS (float because assuming uniform)


        Find both the formation and merger rates for each binary at each redshift
        Args:
            n_binaries          --> [int]            Number of DCO binaries in the arrays
            redshifts           --> [list of floats] Redshifts at which to evaluate the rates
            times               --> [list of floats] Equivalent of the redshifts in terms of age of the Universe
            n_formed            --> [float]          Binary formation rate (number of binaries formed per year per cubic Gpc) represented by each simulated COMPAS binary
            dPdlogZ             --> [2D float array] Probability of getting a particular logZ at a certain redshift
            metallicities       --> [list of floats] Metallicities at which dPdlogZ is evaluated
            p_draw_metallicity  --> [float]          Probability of drawing a certain metallicity in COMPAS (float because assuming uniform)
            COMPAS_metallicites --> [list of floats] Metallicity of each binary in COMPAS data
            COMPAS_delay_times  --> [list of floats] Delay time of each binary in COMPAS data
            COMPAS_weights      --> [list of floats] Adaptive sampling weights for each binary in COMPAS data (defaults to all 1s for unweighted samples)
        Returns:
            formation_rate      --> [2D float array] Formation rate for each binary at each redshift
            merger_rate         --> [2D float array] Merger rate for each binary at each redshift


        Compute a grid of SNRs and detection probabilities for a range of masses and SNRs
        These grids are computed to allow for interpolating the values of the snr and detection probability. This function
        combined with find_detection_probability() could be replaced by something like
            for i in range(n_binaries):
                detection_probability = selection_effects.detection_probability(COMPAS.mass1[i],COMPAS.mass2[i],
                                            redshifts, distances, GWdetector_snr_threshold, GWdetector_sensitivity)
        if runtime was not important.
        Args:
            sensitivity                    --> [string]         Which detector sensitivity to use: one of ["design", "O1", "O3"]
            snr_threshold                  --> [float]          What SNR threshold required for a detection
            Mc_max                         --> [float]          Maximum chirp mass in grid
            Mc_step                        --> [float]          Step in chirp mass to use in grid
            eta_max                        --> [float]          Maximum symmetric mass ratio in grid
            eta_step                       --> [float]          Step in symmetric mass ratio to use in grid
            snr_max                        --> [float]          Maximum snr in grid
            snr_step                       --> [float]          Step in snr to use in grid
        Returns:
            snr_grid_at_1Mpc               --> [2D float array] The snr of a binary with masses (Mc, eta) at a distance of 1 Mpc
            detection_probability_from_snr --> [list of floats] A list of detection probabilities for different SNRs


        Compute the detection probability given a grid of SNRs and detection probabilities with masses
        Args:
            Mc                             --> [list of floats] Chirp mass of binaries in COMPAS
            eta                            --> [list of floats] Symmetric mass ratios of binaries in COMPAS
            redshifts                      --> [list of floats] List of redshifts
            distances                      --> [list of floats] List of distances corresponding to redshifts
            n_redshifts_detection          --> [int]            Index (in redshifts) to which we evaluate detection probability
            n_binaries                     --> [int]            Number of merging binaries in the COMPAS file
            snr_grid_at_1Mpc               --> [2D float array] The snr of a binary with masses (Mc, eta) at a distance of 1 Mpc
            detection_probability_from_snr --> [list of floats] A list of detection probabilities for different SNRs
            Mc_step                        --> [float]          Step in chirp mass to use in grid
            eta_step                       --> [float]          Step in symmetric mass ratio to use in grid
            snr_step                       --> [float]          Step in snr to use in grid


        The main function of this file. Finds the detection rate, formation rate and merger rate for each
        binary in a COMPAS file at a series of redshifts defined by input. Also returns relevant COMPAS
        data.
        NOTE: This code assumes that assumes that metallicities in COMPAS are drawn from a flat in log distribution
        Args:
            ===================================================
            == Arguments for finding and masking COMPAS file ==
            ===================================================
            path                   --> [string] Path to the COMPAS data file that contains the output
            dco_type               --> [string] Which DCO type to calculate rates for: one of ["all", "BBH", "BHNS", "BNS", "BBHandCHE"]
            weight_column          --> [string] Name of column in "DoubleCompactObjects" file that contains adaptive sampling weights
                                                    (Leave this as None if you have unweighted samples)
            merges_in_hubble_time  --> [bool]   whether to mask binaries that don't merge in a Hubble time
            no_RLOF_after_CEE      --> [bool]   whether to mask binaries that have immediate RLOF after a CCE
            pessimistic_CEE        --> [bool]   whether to mask binaries that go through Optimistic CE scenario
            ===========================================
            == Arguments for creating redshift array ==
            ===========================================
            max_redshift           --> [float]  Maximum redshift to use in array
            max_redshift_detection --> [float]  Maximum redshift to calculate detection rates (must be <= max_redshift)
            redshift_step          --> [float]  Size of step to take in redshift
            ====================================================================
            == Arguments for determining star forming mass per sampled binary ==
            ====================================================================
            m1_min                 --> [float]  Minimum primary mass sampled by COMPAS
            m1_max                 --> [float]  Maximum primary mass sampled by COMPAS
            m2_min                 --> [float]  Minimum secondary mass sampled by COMPAS
            fbin                   --> [float]  Binary fraction used by COMPAS
            =======================================================================
            == Arguments for creating metallicity distribution and probabilities ==
            =======================================================================
            mu0                    --> [float]  metallicity dist: expected value at redshift 0
            muz                    --> [float]  metallicity dist: redshift evolution of expected value
            sigma0                 --> [float]  metallicity dist: width at redshhift 0
            sigmaz                 --> [float]  metallicity dist: redshift evolution of width
            alpha                  --> [float]  metallicity dist: skewness (0 = lognormal)
            min_logZ               --> [float]  Minimum logZ at which to calculate dPdlogZ
            max_logZ               --> [float]  Maximum logZ at which to calculate dPdlogZ
            step_logZ              --> [float]  Size of logZ steps to take in finding a Z range
            =======================================================
            == Arguments for determining detection probabilities ==
            =======================================================
            sensitivity            --> [string] Which detector sensitivity to use: one of ["design", "O1", "O3"]
            snr_threshold          --> [float]  What SNR threshold required for a detection
            Mc_max                 --> [float]  Maximum chirp mass in grid
            Mc_step                --> [float]  Step in chirp mass to use in grid
            eta_max                --> [float]  Maximum symmetric mass ratio in grid
            eta_step               --> [float]  Step in symmetric mass ratio to use in grid
            snr_max                --> [float]  Maximum snr in grid
            snr_step               --> [float]  Step in snr to use in grid
        Returns:
            detection_rate         --> [2D float array] Detection rate for each binary at each redshift in 1/yr
            formation_rate         --> [2D float array] Formation rate for each binary at each redshift in 1/yr/Gpc^3
            merger_rate            --> [2D float array] Merger rate for each binary at each redshift in 1/yr/Gpc^3
            redshifts              --> [list of floats] List of redshifts
            COMPAS                 --> [Object]         Relevant COMPAS data in COMPASData Class


        Append the formation rate, merger rate, detection rate and redshifts as a new group to your COMPAS output with weights hdf5 file
        Args:
            path                   --> [string] Path to the COMPAS file that contains the output
            detection_rate         --> [2D float array] Detection rate for each binary at each redshift in 1/yr
            formation_rate         --> [2D float array] Formation rate for each binary at each redshift in 1/yr/Gpc^3
            merger_rate            --> [2D float array] Merger rate for each binary at each redshift in 1/yr/Gpc^3
            redshifts              --> [list of floats] List of redshifts
            COMPAS                 --> [Object]         Relevant COMPAS data in COMPASData Class
            n_redshifts_detection  --> [int]            Number of redshifts in list that should be used to calculate detection rates
            maxz                   --> [float] Maximum redshhift up to where we would like to store the data
            sensitivity            --> [string] Which detector sensitivity you used to calculate rates
            dco_type               --> [string] Which DCO type you used to calculate rates
            mu0                    --> [float]  metallicity dist: expected value at redshift 0
            muz                    --> [float]  metallicity dist: redshift evolution of expected value
            sigma0                 --> [float]  metallicity dist: width at redshhift 0
            sigmaz                 --> [float]  metallicity dist: redshift evolution of width
            alpha                  --> [float]  metallicity dist: skewness (0 = lognormal)
            append_binned_by_z     --> [Bool] to save space, bin rates by redshiftbin and append binned rates
            redshift_binsize       --> [float] if append_binned_by_z, how big should your redshift bin be
        Returns:
            h_new                  --> [hdf5 file] Compas output file with a new group "rates" with the same shape as DoubleCompactObjects x redshifts


        Delete the group containing all the rate information from your COMPAS output with weights hdf5 file
        Args:
            path                   --> [string] Path to the COMPAS file that contains the output
            mu0                    --> [float]  metallicity dist: expected value at redshift 0
            muz                    --> [float]  metallicity dist: redshift evolution of expected value
            sigma0                 --> [float]  metallicity dist: width at redshhift 0
            sigmaz                 --> [float]  metallicity dist: redshift evolution of width
            alpha                  --> [float]  metallicity dist: skewness (0 = lognormal)
            append_binned_by_z     --> [Bool] to save space, bin rates by redshiftbin and append binned rates


        Show a summary plot of the results, it also returns the summaries that it computes
        Args:
            save_dir                  --> [string] path where you would like to save your plot
            formation_rate            --> [2D float array] Formation rate for each binary at each redshift in 1/yr/Gpc^3
            merger_rate               --> [2D float array] Merger rate for each binary at each redshift in 1/yr/Gpc^3
            detection_rate            --> [2D float array] Detection rate for each binary at each redshift in 1/yr
            redshifts                 --> [list of floats] List of redshifts
            chirp_masses              --> [list of floats] Chrirp masses of merging DCO's
            show_plot                 --> [bool] Bool whether to show plot or not
            mu0                       --> [float]  metallicity dist: expected value at redshift 0
            muz                       --> [float]  metallicity dist: redshift evolution of expected value
            sigma0                    --> [float]  metallicity dist: width at redshhift 0
            sigmaz                    --> [float]  metallicity dist: redshift evolution of width
            alpha                     --> [float]  metallicity dist: skewness (0 = lognormal)
        Returns:
            matplotlib figure


            Calculate the star forming mass evolved for each binary in the file.
            This function does this by sampling from the IMF and mass ratio distributions
            Args:
                mi                       --> [float]    masses at which to transition the slope of the IMF (ignored if primary_mass_inverse_CDF is not None)
                aij                      --> [float]    slope of the IMF between mi and mj (ignored if primary_mass_inverse_CDF is not None)
                primary_mass_inverse_CDF --> [function] a function that computes the inverse CDF functoin for the primary mass distribution
                                                        this defaults to the Kroupa IMF (which can be varied using mi, aij)
                mass_ratio_inverse_CDF   --> [function] a function that computes the inverse CDF function for the mass ratio distribution
                                                        this defaults to assuming a uniform mass ratio on [0, 1]
                SAMPLES                  --> [int]      number of samples to draw when creating a mock universe


        Calculate the fraction of stellar mass between m and m + dm for a three part broken power law.
        Default values follow Kroupa (2001)
            zeta(m) ~ m^(-a_ij)

        Args:
            m       --> [float, list of floats] mass or masses at which to evaluate
            mi      --> [float]                 masses at which to transition the slope
            aij     --> [float]                 slope of the IMF between mi and mj

        Returns:
            zeta(m) --> [float, list of floats] value or values of the IMF at m


    Returns the detection probability of a CBC event with given
    masses and distance.
    This function is a convenience function to generate the
    interpolator with 'SNR_Grid_IMRPhenomPv2_FD_all_noise.hdf5'
    and 'SimNoisePSDaLIGODesignSensitivityP1200087', redshift the
    masses, rescale the SNR using the distance, and then call
    'detection_probability_from_snr' to return the probability.
    Parameters
    ----------
    m1, m2 : float > 0
        Primary and secondary mass in source frame.
    redshift : float >= 0
        Redshift of the waveform through cosmology.
    distance : float > 0
        Luminosity Distance in Mpc to the source.
    snr_threshold : float > 0
        Threshold above which an event is considered to be detected.
    sensitivity : str
        Which detector sensitivity PSD to use. Options are 'design' and 'O1'
    Returns
    -------
    out : float
        Estimate of the detection probability.
    Notes
    -----
    The interpolator is only initialized once and then stored in a
    module level global variable to be reused.


        Custom function to approximate the value of any given point
        within the limits of the grid. The value is calculated as the
        average value of the 4 corners of the grid, weighed by the
        inverse distance to (m1, m2). Points for which the SNR is
        NaN are ignored.
        Parameters
        ----------
        m1, m2 : float
            Positive values for which the interpolated SNR is calculated.
        Returns
        -------
        out : float
            Estimate for the SNR at (m1, m2).