Пример #1
0
    def add_point_by_masses(self, mass1, mass2, spin1z, spin2z,
                            vary_fupper=False):
        """
        Add a point to the template bank. This differs from add point to bank
        as it assumes that the chi coordinates and the products needed to use
        vary_fupper have not already been calculated. This function calculates
        these products and then calls add_point_by_chi_coords.
        This function also
        carries out a number of sanity checks (eg. is the point within the
        ranges given by mass_range_params) that add_point_by_chi_coords does
        not do for speed concerns.

        Parameters
        -----------
        mass1 : float
            Mass of the heavier body
        mass2 : float
            Mass of the lighter body
        spin1z : float
            Spin of the heavier body
        spin2z : float
            Spin of the lighter body
        """
        # Test that masses are the expected way around (ie. mass1 > mass2)
        if mass2 > mass1:
            if not self.spin_warning_given:
                warn_msg = "Am adding a template where mass2 > mass1. The "
                warn_msg += "convention is that mass1 > mass2. Swapping mass1 "
                warn_msg += "and mass2 and adding point to bank. This message "
                warn_msg += "will not be repeated."
                logging.warn(warn_msg)
                self.spin_warning_given = True

        # These that masses obey the restrictions of mass_range_params
        if self.mass_range_params.is_outside_range(mass1, mass2, spin1z,
                                                                       spin2z):
            err_msg = "Point with masses given by "
            err_msg += "%f %f %f %f " %(mass1, mass2, spin1z, spin2z)
            err_msg += "(mass1, mass2, spin1z, spin2z) is not consistent "
            err_msg += "with the provided command-line restrictions on masses "
            err_msg += "and spins."
            raise ValueError(err_msg)

        # Get chi coordinates
        chi_coords = coord_utils.get_cov_params(mass1, mass2, spin1z, spin2z,
                                                self.metric_params,
                                                self.ref_freq)

        # Get mus and best fupper for this point, if needed
        if vary_fupper:
            mass_dict = {}
            mass_dict['m1'] = numpy.array([mass1])
            mass_dict['m2'] = numpy.array([mass2])
            mass_dict['s1z'] = numpy.array([spin1z])
            mass_dict['s2z'] = numpy.array([spin2z])
            freqs = numpy.array([self.frequency_map.keys()], dtype=float)
            freq_cutoff = coord_utils.return_nearest_cutoff(\
                                     self.upper_freq_formula, mass_dict, freqs)
            freq_cutoff = freq_cutoff[0]
            lambdas = coord_utils.get_chirp_params\
                (mass1, mass2, spin1z, spin2z, self.metric_params.f0,
                 self.metric_params.pnOrder)
            mus = []
            for freq in self.frequency_map:
                mus.append(coord_utils.get_mu_params(lambdas,
                                                    self.metric_params, freq) )
            mus = numpy.array(mus)
        else:
            freq_cutoff=None
            mus=None

        self.add_point_by_chi_coords(chi_coords, mass1, mass2, spin1z, spin2z,
                               point_fupper=freq_cutoff, mus=mus)
Пример #2
0
    def add_point_by_masses(self, mass1, mass2, spin1z, spin2z,
                            vary_fupper=False):
        """
        Add a point to the template bank. This differs from add point to bank
        as it assumes that the chi coordinates and the products needed to use
        vary_fupper have not already been calculated. This function calculates
        these products and then calls add_point_by_chi_coords.
        This function also
        carries out a number of sanity checks (eg. is the point within the
        ranges given by mass_range_params) that add_point_by_chi_coords does
        not do for speed concerns.

        Parameters
        -----------
        mass1 : float
            Mass of the heavier body
        mass2 : float
            Mass of the lighter body
        spin1z : float
            Spin of the heavier body
        spin2z : float
            Spin of the lighter body
        """
        # Test that masses are the expected way around (ie. mass1 > mass2)
        if mass2 > mass1:
            if not self.spin_warning_given:
                warn_msg = "Am adding a template where mass2 > mass1. The "
                warn_msg += "convention is that mass1 > mass2. Swapping mass1 "
                warn_msg += "and mass2 and adding point to bank. This message "
                warn_msg += "will not be repeated."
                logging.warn(warn_msg)
                self.spin_warning_given = True

        # These that masses obey the restrictions of mass_range_params
        if self.mass_range_params.is_outside_range(mass1, mass2, spin1z,
                                                                       spin2z):
            err_msg = "Point with masses given by "
            err_msg += "%f %f %f %f " %(mass1, mass2, spin1z, spin2z)
            err_msg += "(mass1, mass2, spin1z, spin2z) is not consistent "
            err_msg += "with the provided command-line restrictions on masses "
            err_msg += "and spins."
            raise ValueError(err_msg)

        # Get chi coordinates
        chi_coords = coord_utils.get_cov_params(mass1, mass2, spin1z, spin2z,
                                                self.metric_params,
                                                self.ref_freq)

        # Get mus and best fupper for this point, if needed
        if vary_fupper:
            mass_dict = {}
            mass_dict['m1'] = numpy.array([mass1])
            mass_dict['m2'] = numpy.array([mass2])
            mass_dict['s1z'] = numpy.array([spin1z])
            mass_dict['s2z'] = numpy.array([spin2z])
            freqs = numpy.array([self.frequency_map.keys()], dtype=float)
            freq_cutoff = coord_utils.return_nearest_cutoff(\
                                     self.upper_freq_formula, mass_dict, freqs)
            freq_cutoff = freq_cutoff[0]
            lambdas = coord_utils.get_chirp_params\
                (mass1, mass2, spin1z, spin2z, self.metric_params.f0,
                 self.metric_params.pnOrder)
            mus = []
            for freq in self.frequency_map:
                mus.append(coord_utils.get_mu_params(lambdas,
                                                    self.metric_params, freq) )
            mus = numpy.array(mus)
        else:
            freq_cutoff=None
            mus=None

        self.add_point_by_chi_coords(chi_coords, mass1, mass2, spin1z, spin2z,
                               point_fupper=freq_cutoff, mus=mus)
def get_mass_distribution(bestMasses,
                          scaleFactor,
                          massRangeParams,
                          metricParams,
                          fUpper,
                          numJumpPoints=100,
                          chirpMassJumpFac=0.0001,
                          etaJumpFac=0.01,
                          spin1zJumpFac=0.01,
                          spin2zJumpFac=0.01):
    """
    Given a set of masses, this function will create a set of points nearby
    in the mass space and map these to the xi space.

    Parameters
    -----------
    bestMasses : list
        Contains [ChirpMass, eta, spin1z, spin2z]. Points will be placed around
        tjos
    scaleFactor : float
        This parameter describes the radius away from bestMasses that points
        will be placed in.
    massRangeParams : massRangeParameters instance
        Instance holding all the details of mass ranges and spin ranges.
    metricParams : metricParameters instance
        Structure holding all the options for construction of the metric
        and the eigenvalues, eigenvectors and covariance matrix
        needed to manipulate the space.
    fUpper : float
        The value of fUpper that was used when obtaining the xi_i
        coordinates. This lets us know how to rotate potential physical points
        into the correct xi_i space. This must be a key in metricParams.evals,
        metricParams.evecs and metricParams.evecsCV
        (ie. we must know how to do the transformation for
        the given value of fUpper)
    numJumpPoints : int, optional (default = 100)
        The number of points that will be generated every iteration
    chirpMassJumpFac : float, optional (default=0.0001)
        The jump points will be chosen with fractional variation in chirpMass
        up to this multiplied by scaleFactor.
    etaJumpFac : float, optional (default=0.01)
        The jump points will be chosen with fractional variation in eta
        up to this multiplied by scaleFactor.
    spin1zJumpFac : float, optional (default=0.01)
        The jump points will be chosen with absolute variation in spin1z up to
        this multiplied by scaleFactor.
    spin2zJumpFac : float, optional (default=0.01)
        The jump points will be chosen with absolute variation in spin2z up to
        this multiplied by scaleFactor.

    Returns 
    --------
    Totmass : numpy.array
        Total mass of the resulting points
    Eta : numpy.array
        Symmetric mass ratio of the resulting points
    Spin1z : numpy.array
        Spin of the heavier body of the resulting points
    Spin2z : numpy.array
        Spin of the smaller body of the resulting points
    Diff : numpy.array
        Mass1 - Mass2 of the resulting points
    Mass1 : numpy.array
        Mass1 (mass of heavier body) of the resulting points
    Mass2 : numpy.array
        Mass2 (mass of smaller body) of the resulting points
    new_xis : list of numpy.array
        Position of points in the xi coordinates
    """
    # FIXME: It would be better if rejected values could be drawn from the
    # full possible mass/spin distribution. However speed in this function is
    # a major factor and must be considered.
    bestChirpmass = bestMasses[0]
    bestEta = bestMasses[1]
    bestSpin1z = bestMasses[2]
    bestSpin2z = bestMasses[3]

    # Firstly choose a set of values for masses and spins
    chirpmass = bestChirpmass * (1 - (numpy.random.random(numJumpPoints)-0.5) \
                                       * chirpMassJumpFac * scaleFactor )
    etaRange = massRangeParams.maxEta - massRangeParams.minEta
    currJumpFac = etaJumpFac * scaleFactor
    if currJumpFac > etaRange:
        currJumpFac = etaRange
    eta = bestEta * ( 1 - (numpy.random.random(numJumpPoints) - 0.5) \
                           * currJumpFac)

    maxSpinMag = max(massRangeParams.maxNSSpinMag,
                     massRangeParams.maxBHSpinMag)
    minSpinMag = min(massRangeParams.maxNSSpinMag,
                     massRangeParams.maxBHSpinMag)
    # Note that these two are cranged by spinxzFac, *not* spinxzFac/spinxz
    currJumpFac = spin1zJumpFac * scaleFactor
    if currJumpFac > maxSpinMag:
        currJumpFac = maxSpinMag

    # Actually set the new spin trial points
    if massRangeParams.nsbhFlag or (maxSpinMag == minSpinMag):
        curr_spin_1z_jump_fac = currJumpFac
        curr_spin_2z_jump_fac = currJumpFac
        # Check spins aren't going to be unphysical
        if currJumpFac > massRangeParams.maxBHSpinMag:
            curr_spin_1z_jump_fac = massRangeParams.maxBHSpinMag
        if currJumpFac > massRangeParams.maxNSSpinMag:
            curr_spin_2z_jump_fac = massRangeParams.maxNSSpinMag
        spin1z = bestSpin1z + ( (numpy.random.random(numJumpPoints) - 0.5) \
                            * curr_spin_1z_jump_fac)
        spin2z = bestSpin2z + ( (numpy.random.random(numJumpPoints) - 0.5) \
                            * curr_spin_2z_jump_fac)
    else:
        # If maxNSSpinMag is very low (0) and maxBHSpinMag is high we can
        # find it hard to place any points. So mix these when
        # masses are swapping between the NS and BH.
        curr_spin_bh_jump_fac = currJumpFac
        curr_spin_ns_jump_fac = currJumpFac
        # Check spins aren't going to be unphysical
        if currJumpFac > massRangeParams.maxBHSpinMag:
            curr_spin_bh_jump_fac = massRangeParams.maxBHSpinMag
        if currJumpFac > massRangeParams.maxNSSpinMag:
            curr_spin_ns_jump_fac = massRangeParams.maxNSSpinMag
        spin1z = numpy.zeros(numJumpPoints, dtype=float)
        spin2z = numpy.zeros(numJumpPoints, dtype=float)
        split_point = int(numJumpPoints / 2)
        # So set the first half to be at least within the BH range and the
        # second half to be at least within the NS range
        spin1z[:split_point] = bestSpin1z + \
                            ( (numpy.random.random(split_point) - 0.5)\
                              * curr_spin_bh_jump_fac)
        spin1z[split_point:] = bestSpin1z + \
                      ( (numpy.random.random(numJumpPoints-split_point) - 0.5)\
                        * curr_spin_ns_jump_fac)
        spin2z[:split_point] = bestSpin2z + \
                            ( (numpy.random.random(split_point) - 0.5)\
                              * curr_spin_bh_jump_fac)
        spin2z[split_point:] = bestSpin2z + \
                      ( (numpy.random.random(numJumpPoints-split_point) - 0.5)\
                        * curr_spin_ns_jump_fac)

    # Point[0] is always set to the original point
    chirpmass[0] = bestChirpmass
    eta[0] = bestEta
    spin1z[0] = bestSpin1z
    spin2z[0] = bestSpin2z

    # Remove points where eta becomes unphysical
    eta[eta > massRangeParams.maxEta] = massRangeParams.maxEta
    if massRangeParams.minEta:
        eta[eta < massRangeParams.minEta] = massRangeParams.minEta
    else:
        eta[eta < 0.0001] = 0.0001

    # Total mass, masses and mass diff
    totmass = chirpmass / (eta**(3. / 5.))
    diff = (totmass * totmass * (1 - 4 * eta))**0.5
    mass1 = (totmass + diff) / 2.
    mass2 = (totmass - diff) / 2.

    # Check the validity of the spin values
    # Do the first spin

    if maxSpinMag == 0:
        # Shortcut if non-spinning
        pass
    elif massRangeParams.nsbhFlag or (maxSpinMag == minSpinMag):
        # Simple case where I don't have to worry about correlation with mass
        numploga = abs(spin1z) > massRangeParams.maxBHSpinMag
        spin1z[numploga] = 0
    else:
        # Do have to consider masses
        boundary_mass = massRangeParams.ns_bh_boundary_mass
        numploga1 = numpy.logical_and(
            mass1 >= boundary_mass,
            abs(spin1z) <= massRangeParams.maxBHSpinMag)
        numploga2 = numpy.logical_and(
            mass1 < boundary_mass,
            abs(spin1z) <= massRangeParams.maxNSSpinMag)
        numploga = numpy.logical_or(numploga1, numploga2)
        numploga = numpy.logical_not(numploga)
        spin1z[numploga] = 0

    # Same for the second spin

    if maxSpinMag == 0:
        # Shortcut if non-spinning
        pass
    elif massRangeParams.nsbhFlag or (maxSpinMag == minSpinMag):
        numplogb = abs(spin2z) > massRangeParams.maxNSSpinMag
        spin2z[numplogb] = 0
    else:
        # Do have to consider masses
        boundary_mass = massRangeParams.ns_bh_boundary_mass
        numplogb1 = numpy.logical_and(
            mass2 >= boundary_mass,
            abs(spin2z) <= massRangeParams.maxBHSpinMag)
        numplogb2 = numpy.logical_and(
            mass2 < boundary_mass,
            abs(spin2z) <= massRangeParams.maxNSSpinMag)
        numplogb = numpy.logical_or(numplogb1, numplogb2)
        numplogb = numpy.logical_not(numplogb)
        spin2z[numplogb] = 0

    if (maxSpinMag) and (numploga[0] or numplogb[0]):
        raise ValueError("Cannot remove the guide point!")

    # And remove points where the individual masses are outside of the physical
    # range. Or the total masses are.
    # These "removed" points will have metric distances that will be much, much
    # larger than any thresholds used in the functions in brute_force_utils.py
    # and will always be rejected. An unphysical value cannot be used as it
    # would result in unphysical metric distances and cause failures.
    totmass[mass1 < massRangeParams.minMass1] = 0.0001
    totmass[mass1 > massRangeParams.maxMass1] = 0.0001
    totmass[mass2 < massRangeParams.minMass2] = 0.0001
    totmass[mass2 > massRangeParams.maxMass2] = 0.0001
    # There is some numerical error which can push this a bit higher. We do
    # *not* want to reject the initial guide point. This error comes from
    # Masses -> totmass, eta -> masses conversion, we will have points pushing
    # onto the boudaries of the space.
    totmass[totmass > massRangeParams.maxTotMass * 1.0001] = 0.0001
    totmass[totmass < massRangeParams.minTotMass * 0.9999] = 0.0001
    if massRangeParams.max_chirp_mass:
        totmass[chirpmass > massRangeParams.max_chirp_mass * 1.0001] = 0.0001
    if massRangeParams.min_chirp_mass:
        totmass[chirpmass < massRangeParams.min_chirp_mass * 0.9999] = 0.0001

    if totmass[0] < 0.00011:
        raise ValueError("Cannot remove the guide point!")

    mass1[totmass < 0.00011] = 0.0001
    mass2[totmass < 0.00011] = 0.0001

    # Then map to xis
    new_xis = get_cov_params(mass1, mass2, spin1z, spin2z, metricParams,
                             fUpper)
    return totmass, eta, spin1z, spin2z, mass1, mass2, new_xis
Пример #4
0
def get_mass_distribution(bestMasses, scaleFactor, massRangeParams,
                          metricParams, fUpper,
                          numJumpPoints=100, chirpMassJumpFac=0.0001,
                          etaJumpFac=0.01, spin1zJumpFac=0.01,
                          spin2zJumpFac=0.01):
    """
    Given a set of masses, this function will create a set of points nearby
    in the mass space and map these to the xi space.

    Parameters
    -----------
    bestMasses : list
        Contains [ChirpMass, eta, spin1z, spin2z]. Points will be placed around
        tjos
    scaleFactor : float
        This parameter describes the radius away from bestMasses that points
        will be placed in.
    massRangeParams : massRangeParameters instance
        Instance holding all the details of mass ranges and spin ranges.
    metricParams : metricParameters instance
        Structure holding all the options for construction of the metric
        and the eigenvalues, eigenvectors and covariance matrix
        needed to manipulate the space.
    fUpper : float
        The value of fUpper that was used when obtaining the xi_i
        coordinates. This lets us know how to rotate potential physical points
        into the correct xi_i space. This must be a key in metricParams.evals,
        metricParams.evecs and metricParams.evecsCV
        (ie. we must know how to do the transformation for
        the given value of fUpper)
    numJumpPoints : int, optional (default = 100)
        The number of points that will be generated every iteration
    chirpMassJumpFac : float, optional (default=0.0001)
        The jump points will be chosen with fractional variation in chirpMass
        up to this multiplied by scaleFactor.
    etaJumpFac : float, optional (default=0.01)
        The jump points will be chosen with fractional variation in eta
        up to this multiplied by scaleFactor.
    spin1zJumpFac : float, optional (default=0.01)
        The jump points will be chosen with absolute variation in spin1z up to
        this multiplied by scaleFactor.
    spin2zJumpFac : float, optional (default=0.01)
        The jump points will be chosen with absolute variation in spin2z up to
        this multiplied by scaleFactor.

    Returns 
    --------
    Chirpmass : numpy.array
        chirp mass of the resulting points
    Totmass : numpy.array
        Total mass of the resulting points
    Eta : numpy.array
        Symmetric mass ratio of the resulting points
    Spin1z : numpy.array
        Spin of the heavier body of the resulting points
    Spin2z : numpy.array
        Spin of the smaller body of the resulting points
    Diff : numpy.array
        Mass1 - Mass2 of the resulting points
    Mass1 : numpy.array
        Mass1 (mass of heavier body) of the resulting points
    Mass2 : numpy.array
        Mass2 (mass of smaller body) of the resulting points
    Beta : numpy.array
        1.5PN spin phasing coefficient of the resulting points
    Sigma : numpy.array
        2PN spin phasing coefficient of the resulting points
    Gamma : numpy.array
        2.5PN spin phasing coefficient of the resulting points
    Chis : numpy.array
        0.5 * (spin1z + spin2z) for the resulting points
    new_xis : list of numpy.array
        Position of points in the xi coordinates
    """
    # FIXME: It would be better if rejected values could be drawn from the 
    # full possible mass/spin distribution. However speed in this function is
    # a major factor and must be considered.
    bestChirpmass = bestMasses[0]
    bestEta = bestMasses[1]
    bestSpin1z = bestMasses[2]
    bestSpin2z = bestMasses[3]

    # Firstly choose a set of values for masses and spins
    chirpmass = bestChirpmass * (1 - (numpy.random.random(numJumpPoints)-0.5) \
                                       * chirpMassJumpFac * scaleFactor )
    etaRange = massRangeParams.maxEta - massRangeParams.minEta
    currJumpFac = etaJumpFac * scaleFactor
    if currJumpFac > etaRange:
        currJumpFac = etaRange
    eta = bestEta * ( 1 - (numpy.random.random(numJumpPoints) - 0.5) \
                           * currJumpFac)

    maxSpinMag = max(massRangeParams.maxNSSpinMag, massRangeParams.maxBHSpinMag)
    minSpinMag = min(massRangeParams.maxNSSpinMag, massRangeParams.maxBHSpinMag)
    # Note that these two are cranged by spinxzFac, *not* spinxzFac/spinxz
    currJumpFac = spin1zJumpFac * scaleFactor
    if currJumpFac > maxSpinMag:
        currJumpFac = maxSpinMag

    # Actually set the new spin trial points
    if massRangeParams.nsbhFlag or (maxSpinMag == minSpinMag):
        curr_spin_1z_jump_fac = currJumpFac
        curr_spin_2z_jump_fac = currJumpFac
        # Check spins aren't going to be unphysical
        if currJumpFac > massRangeParams.maxBHSpinMag:
            curr_spin_1z_jump_fac = massRangeParams.maxBHSpinMag
        if currJumpFac > massRangeParams.maxNSSpinMag:
            curr_spin_2z_jump_fac = massRangeParams.maxNSSpinMag
        spin1z = bestSpin1z + ( (numpy.random.random(numJumpPoints) - 0.5) \
                            * curr_spin_1z_jump_fac)
        spin2z = bestSpin2z + ( (numpy.random.random(numJumpPoints) - 0.5) \
                            * curr_spin_2z_jump_fac)
    else:
        # If maxNSSpinMag is very low (0) and maxBHSpinMag is high we can
        # find it hard to place any points. So mix these when
        # masses are swapping between the NS and BH.
        curr_spin_bh_jump_fac = currJumpFac
        curr_spin_ns_jump_fac = currJumpFac
        # Check spins aren't going to be unphysical
        if currJumpFac > massRangeParams.maxBHSpinMag:
            curr_spin_bh_jump_fac = massRangeParams.maxBHSpinMag
        if currJumpFac > massRangeParams.maxNSSpinMag:
            curr_spin_ns_jump_fac = massRangeParams.maxNSSpinMag
        spin1z = numpy.zeros(numJumpPoints, dtype=float)
        spin2z = numpy.zeros(numJumpPoints, dtype=float)
        split_point = int(numJumpPoints/2)
        # So set the first half to be at least within the BH range and the
        # second half to be at least within the NS range
        spin1z[:split_point] = bestSpin1z + \
                            ( (numpy.random.random(split_point) - 0.5)\
                              * curr_spin_bh_jump_fac)
        spin1z[split_point:] = bestSpin1z + \
                      ( (numpy.random.random(numJumpPoints-split_point) - 0.5)\
                        * curr_spin_ns_jump_fac)
        spin2z[:split_point] = bestSpin2z + \
                            ( (numpy.random.random(split_point) - 0.5)\
                              * curr_spin_bh_jump_fac)
        spin2z[split_point:] = bestSpin2z + \
                      ( (numpy.random.random(numJumpPoints-split_point) - 0.5)\
                        * curr_spin_ns_jump_fac)

    # Point[0] is always set to the original point
    chirpmass[0] = bestChirpmass
    eta[0] = bestEta
    spin1z[0] = bestSpin1z
    spin2z[0] = bestSpin2z

    # Remove points where eta becomes unphysical
    eta[eta > massRangeParams.maxEta] = massRangeParams.maxEta
    if massRangeParams.minEta:
        eta[eta < massRangeParams.minEta] = massRangeParams.minEta
    else:
        eta[eta < 0.0001] = 0.0001

    # Total mass, masses and mass diff
    totmass = chirpmass / (eta**(3./5.))
    diff = (totmass*totmass * (1-4*eta))**0.5
    mass1 = (totmass + diff)/2.
    mass2 = (totmass - diff)/2.

    # Check the validity of the spin values
    # Do the first spin

    if maxSpinMag == 0:
        # Shortcut if non-spinning
        pass
    elif massRangeParams.nsbhFlag or (maxSpinMag == minSpinMag):
        # Simple case where I don't have to worry about correlation with mass
        numploga = abs(spin1z) > massRangeParams.maxBHSpinMag
        spin1z[numploga] = 0
    else:
        # Do have to consider masses
        boundary_mass = massRangeParams.ns_bh_boundary_mass
        numploga1 = numpy.logical_and(mass1 >= boundary_mass,
                                   abs(spin1z) <= massRangeParams.maxBHSpinMag)
        numploga2 = numpy.logical_and(mass1 < boundary_mass,
                                   abs(spin1z) <= massRangeParams.maxNSSpinMag)
        numploga = numpy.logical_or(numploga1, numploga2)
        numploga = numpy.logical_not(numploga)
        spin1z[numploga] = 0

    # Same for the second spin

    if maxSpinMag == 0:
        # Shortcut if non-spinning
        pass
    elif massRangeParams.nsbhFlag or (maxSpinMag == minSpinMag):
        numplogb = abs(spin2z) > massRangeParams.maxNSSpinMag
        spin2z[numplogb] = 0
    else:
        # Do have to consider masses
        boundary_mass = massRangeParams.ns_bh_boundary_mass
        numplogb1 = numpy.logical_and(mass2 >= boundary_mass,
                                   abs(spin2z) <= massRangeParams.maxBHSpinMag)
        numplogb2 = numpy.logical_and(mass2 < boundary_mass,
                                   abs(spin2z) <= massRangeParams.maxNSSpinMag)
        numplogb = numpy.logical_or(numplogb1, numplogb2)
        numplogb = numpy.logical_not(numplogb)
        spin2z[numplogb] = 0

    # Get the various spin-derived quantities
    beta, sigma, gamma, chis = get_beta_sigma_from_aligned_spins(eta, spin1z,
                                                                 spin2z)

    if (maxSpinMag) and (numploga[0] or numplogb[0]):
        raise ValueError("Cannot remove the guide point!")

    # And remove points where the individual masses are outside of the physical
    # range. Or the total masses are.
    # These "removed" points will have metric distances that will be much, much
    # larger than any thresholds used in the functions in brute_force_utils.py
    # and will always be rejected. An unphysical value cannot be used as it
    # would result in unphysical metric distances and cause failures.
    totmass[mass1 < massRangeParams.minMass1] = 0.0001
    totmass[mass1 > massRangeParams.maxMass1] = 0.0001
    totmass[mass2 < massRangeParams.minMass2] = 0.0001
    totmass[mass2 > massRangeParams.maxMass2] = 0.0001
    # There is some numerical error which can push this a bit higher. We do
    # *not* want to reject the initial guide point. This error comes from
    # Masses -> totmass, eta -> masses conversion, we will have points pushing
    # onto the boudaries of the space.
    totmass[totmass > massRangeParams.maxTotMass*1.0001] = 0.0001
    totmass[totmass < massRangeParams.minTotMass*0.9999] = 0.0001
    if massRangeParams.max_chirp_mass:
        totmass[chirpmass > massRangeParams.max_chirp_mass*1.0001] = 0.0001
    if massRangeParams.min_chirp_mass:
        totmass[chirpmass < massRangeParams.min_chirp_mass*0.9999] = 0.0001

    if totmass[0] < 0.00011:
        raise ValueError("Cannot remove the guide point!")

    # Then map to xis
    new_xis = get_cov_params(totmass, eta, beta, sigma, gamma, chis,
                             metricParams, fUpper)
    return chirpmass, totmass, eta, spin1z, spin2z, diff, mass1, mass2, beta, \
           sigma, gamma, chis, new_xis