def get_area(trig_mc, lim_h1, lim_h2, lim_v1, lim_v2): """Returns the area of the chirp mass contour in each region of the m1m2 plane taking horizontal and vertical limits of the region as arguments. """ mcb = trig_mc[0] + trig_mc[1] mcs = trig_mc[0] - trig_mc[1] # The points where the equal mass line and a chirp mass # curve intersect is m1 = m2 = 2**0.2 * mchirp mib = (2.**0.2) * mcb mis = (2.**0.2) * mcs if lim_h1 == 'diagonal': Pb_h1 = mib Ps_h1 = mis fun_sup = lambda x: x else: Pb_h1 = m2mcm1(mcb, lim_h1) Ps_h1 = m2mcm1(mcs, lim_h1) fun_sup = lambda x: lim_h1 Pb_h2 = m2mcm1(mcb, lim_h2) Ps_h2 = m2mcm1(mcs, lim_h2) fun_inf = lambda x: lim_h2 limb1 = np.clip(Pb_h1, lim_v1, lim_v2) limb2 = np.clip(Pb_h2, lim_v1, lim_v2) lims1 = np.clip(Ps_h1, lim_v1, lim_v2) lims2 = np.clip(Ps_h2, lim_v1, lim_v2) intb = intmc(mcb, limb1, limb2) ints = intmc(mcs, lims1, lims2) intline_sup = quad(fun_sup, lims1, limb1)[0] intline_inf = quad(fun_inf, lims2, limb2)[0] area = intb + intline_sup - ints - intline_inf return area
def get_area(trig_mc, lim_h1, lim_h2, lim_v1, lim_v2): """ Returns the area under the chirp mass contour in a region of the m1m2 plane (m1 > m2) Parameters ---------- trig_mc : sequence of two values first represents central estimate of mchirp in source frame, second its uncertainty lim_h1, lim_h2 : floats or the string 'diagonal' upper and lower horizontal limits of the region (limits on m2) lim_v1, lim_v2 : floats right and left vertical limits of the region (limits on m1) Returns ------- area : float """ mc_max = trig_mc[0] + trig_mc[1] mc_min = trig_mc[0] - trig_mc[1] # The points where the equal mass line and a chirp mass # curve intersect is m1 = m2 = 2**0.2 * mchirp mi_max = (2.**0.2) * mc_max mi_min = (2.**0.2) * mc_min if lim_h1 == 'diagonal': max_h1 = mi_max min_h1 = mi_min fun_sup = lambda x: x else: max_h1 = m2mcm1(mc_max, lim_h1) min_h1 = m2mcm1(mc_min, lim_h1) fun_sup = lambda x: lim_h1 max_h2 = m2mcm1(mc_max, lim_h2) min_h2 = m2mcm1(mc_min, lim_h2) fun_inf = lambda x: lim_h2 lim_max1 = np.clip(max_h1, lim_v1, lim_v2) lim_max2 = np.clip(max_h2, lim_v1, lim_v2) lim_min1 = np.clip(min_h1, lim_v1, lim_v2) lim_min2 = np.clip(min_h2, lim_v1, lim_v2) int_max = intmc(mc_max, lim_max1, lim_max2) int_min = intmc(mc_min, lim_min1, lim_min2) intline_sup = quad(fun_sup, lim_min1, lim_max1)[0] intline_inf = quad(fun_inf, lim_min2, lim_max2)[0] area = int_max + intline_sup - int_min - intline_inf return area
def intmc(mc, x_min, x_max): """Returns the integral of a component mass as a function of the mass of the other component, taking mchirp as an argument. """ integral = quad(lambda x, mc: m2mcm1(mc, x), x_min, x_max, args=mc) return integral[0]
def calc_areas(trig_mc_det, mass_limits, mass_bdary, z, mass_gap): """Computes the area inside the lines of the second component mass as a function of the first component mass for the two extreme values of mchirp: mchirp +/- mchirp_uncertainty, for each region of the source classifying diagram. """ trig_mc = src_mass_from_z_det_mass(z["central"], z["delta"], trig_mc_det["central"], trig_mc_det["delta"]) mcb = trig_mc[0] + trig_mc[1] mcs = trig_mc[0] - trig_mc[1] m2_min = mass_limits["min_m2"] m1_max = mass_limits["max_m1"] ns_max = mass_bdary["ns_max"] gap_max = mass_bdary["gap_max"] # The points where the equal mass line and a chirp mass # curve intersect is m1 = m2 = 2**0.2 * mchirp mib = (2.**0.2) * mcb mis = (2.**0.2) * mcs # AREA FOR BBH if mib < gap_max: abbh = 0.0 else: limb_bbh = min(m1_max, m2mcm1(mcb, gap_max)) intb_bbh = intmc(mcb, mib, limb_bbh) if mis < gap_max: lims1_bbh = gap_max lims2_bbh = lims1_bbh else: lims1_bbh = mis lims2_bbh = min(m1_max, m2mcm1(mcs, gap_max)) ints_bbh = intmc(mcs, lims1_bbh, lims2_bbh) limdiag_bbh = max(m2mcm1(mcs, lims1_bbh), gap_max) intline_sup_bbh = 0.5 * (limdiag_bbh + mib) * (mib - lims1_bbh) intline_inf_bbh = (limb_bbh - lims2_bbh) * gap_max int_sup_bbh = intb_bbh + intline_sup_bbh int_inf_bbh = ints_bbh + intline_inf_bbh abbh = int_sup_bbh - int_inf_bbh # AREA FOR BHG if m2mcm1(mcb, gap_max) < ns_max or m2mcm1(mcs, m1_max) > gap_max: abhg = 0.0 else: if m2mcm1(mcb, m1_max) > gap_max: limb2_bhg = m1_max limb1_bhg = limb2_bhg else: limb2_bhg = min(m1_max, m2mcm1(mcb, ns_max)) limb1_bhg = max(gap_max, m2mcm1(mcb, gap_max)) intb_bhg = intmc(mcb, limb1_bhg, limb2_bhg) if m2mcm1(mcs, gap_max) < ns_max: lims2_bhg = gap_max lims1_bhg = lims2_bhg else: lims1_bhg = max(gap_max, m2mcm1(mcs, gap_max)) lims2_bhg = min(m1_max, m2mcm1(mcs, ns_max)) intline_inf_bhg = (limb2_bhg - lims2_bhg) * ns_max intline_sup_bhg = (limb1_bhg - lims1_bhg) * gap_max ints_bhg = intmc(mcs, lims1_bhg, lims2_bhg) int_sup_bhg = intb_bhg + intline_sup_bhg int_inf_bhg = ints_bhg + intline_inf_bhg abhg = int_sup_bhg - int_inf_bhg # AREA FOR GG if m2mcm1(mcs, gap_max) > gap_max or m2mcm1(mcb, ns_max) < ns_max: agg = 0.0 else: if m2mcm1(mcb, gap_max) > gap_max: limb2_gg = gap_max limb1_gg = limb2_gg else: limb1_gg = mib limb2_gg = min(gap_max, m2mcm1(mcb, ns_max)) intb_gg = intmc(mcb, limb1_gg, limb2_gg) if m2mcm1(mcs, ns_max) < ns_max: lims2_gg = ns_max lims1_gg = lims2_gg else: lims1_gg = mis lims2_gg = min(gap_max, m2mcm1(mcs, ns_max)) ints_gg = intmc(mcs, lims1_gg, lims2_gg) limdiag1_gg = max(m2mcm1(mcs, lims1_gg), ns_max) limdiag2_gg = min(m2mcm1(mcb, limb1_gg), gap_max) intline_sup_gg = (0.5 * (limb1_gg - lims1_gg) * (limdiag1_gg + limdiag2_gg)) intline_inf_gg = (limb2_gg - lims2_gg) * ns_max int_sup_gg = intb_gg + intline_sup_gg int_inf_gg = ints_gg + intline_inf_gg agg = int_sup_gg - int_inf_gg # AREA FOR BNS if m2mcm1(mcs, ns_max) > ns_max: abns = 0.0 else: if m2mcm1(mcb, ns_max) > ns_max: limb2_bns = ns_max limb1_bns = limb2_bns else: limb2_bns = min(ns_max, m2mcm1(mcb, m2_min)) limb1_bns = mib intb_bns = intmc(mcb, limb1_bns, limb2_bns) if mis < m2_min: lims2_bns = m2_min lims1_bns = lims2_bns else: lims2_bns = min(ns_max, m2mcm1(mcs, m2_min)) lims1_bns = mis ints_bns = intmc(mcs, lims1_bns, lims2_bns) intline_inf_bns = (limb2_bns - lims2_bns) * m2_min limdiag1_bns = max(m2mcm1(mcs, lims1_bns), m2_min) limdiag2_bns = min(m2mcm1(mcb, limb1_bns), ns_max) intline_sup_bns = (0.5 * (limdiag1_bns + limdiag2_bns) * (limb1_bns - lims1_bns)) int_sup_bns = intb_bns + intline_sup_bns int_inf_bns = ints_bns + intline_inf_bns abns = int_sup_bns - int_inf_bns # AREA FOR GNS if m2mcm1(mcs, gap_max) > ns_max or m2mcm1(mcb, ns_max) < m2_min: agns = 0.0 else: if m2mcm1(mcb, gap_max) > ns_max: limb2_gns = gap_max limb1_gns = limb2_gns else: limb2_gns = min(gap_max, m2mcm1(mcb, m2_min)) limb1_gns = max(ns_max, m2mcm1(mcb, ns_max)) intb_gns = intmc(mcb, limb1_gns, limb2_gns) if m2mcm1(mcs, ns_max) < m2_min: lims2_gns = ns_max lims1_gns = lims2_gns else: lims1_gns = max(ns_max, m2mcm1(mcs, ns_max)) lims2_gns = min(gap_max, m2mcm1(mcs, m2_min)) intline_inf_gns = (limb2_gns - lims2_gns) * m2_min intline_sup_gns = (limb1_gns - lims1_gns) * ns_max ints_gns = intmc(mcs, lims1_gns, lims2_gns) int_sup_gns = intb_gns + intline_sup_gns int_inf_gns = ints_gns + intline_inf_gns agns = int_sup_gns - int_inf_gns # AREA FOR NSBH if m2mcm1(mcs, m1_max) > ns_max or m2mcm1(mcb, gap_max) < m2_min: ansbh = 0.0 else: if m2mcm1(mcb, m1_max) > ns_max: limb2_nsbh = m1_max limb1_nsbh = limb2_nsbh else: limb1_nsbh = max(gap_max, m2mcm1(mcb, ns_max)) limb2_nsbh = min(m1_max, m2mcm1(mcb, m2_min)) intb_nsbh = intmc(mcb, limb1_nsbh, limb2_nsbh) if m2mcm1(mcs, gap_max) < m2_min: lims1_nsbh = gap_max lims2_nsbh = lims1_nsbh else: lims1_nsbh = max(gap_max, m2mcm1(mcs, ns_max)) lims2_nsbh = min(m1_max, m2mcm1(mcs, m2_min)) intline_inf_nsbh = (limb2_nsbh - lims2_nsbh) * m2_min intline_sup_nsbh = (limb1_nsbh - lims1_nsbh) * ns_max ints_nsbh = intmc(mcs, lims1_nsbh, lims2_nsbh) int_sup_nsbh = intb_nsbh + intline_sup_nsbh int_inf_nsbh = ints_nsbh + intline_inf_nsbh ansbh = int_sup_nsbh - int_inf_nsbh if mass_gap: return { "BNS": abns, "GNS": agns, "NSBH": ansbh, "GG": agg, "BHG": abhg, "BBH": abbh } return { "BNS": abns, "NSBH": ansbh, "BBH": abbh, "Mass Gap": agns + agg + abhg }
def mchange(x, mc): """Returns a component mass as a function of mchirp and the other component mass. """ return m2mcm1(mc, x)
def intmc(mc, x_min, x_max): """Returns the integral of m2 over m1 between x_min and x_max, assuming that mchirp is fixed. """ integral = quad(lambda x, mc: m2mcm1(mc, x), x_min, x_max, args=mc) return integral[0]
def contour_mass_plot(trig_mc_det, mass_limits, mass_bdary, z, plot_args): trig_mc = mchirp_area.src_mass_from_z_det_mass(z["central"], z["delta"], trig_mc_det["central"], trig_mc_det["delta"]) mcb = trig_mc[0] + trig_mc[1] mcs = trig_mc[0] - trig_mc[1] m2_min = mass_limits["min_m2"] m1_max = mass_limits["max_m1"] ns_max = mass_bdary["ns_max"] gap_max = mass_bdary["gap_max"] mib = (2.**0.2) * mcb mis = (2.**0.2) * mcs lim_m1b = min(m1_max, m2mcm1(mcb, m2_min)) m1b = np.linspace(mib, lim_m1b, num=100) m2b = m2mcm1(mcb, m1b) lim_m1s = min(m1_max, m2mcm1(mcs, m2_min)) m1s = np.linspace(mis, lim_m1s, num=100) m2s = m2mcm1(mcs, m1s) fig = plt.figure() #plot contour if mib > m1_max: plt.plot((m1_max, m1_max), (m2mcm1(mcs, lim_m1s), m1_max), "b") else: plt.plot(m1b, m2b, "b") plt.plot((m1_max, m1_max), (m2mcm1(mcs, lim_m1s), m2mcm1(mcb, lim_m1b)), "b") if mis >= m2_min: plt.plot(m1s, m2s, "b") plt.plot((lim_m1s, lim_m1b), (m2_min, m2_min), "b") else: plt.plot((m2_min, lim_m1b), (m2_min, m2_min), "b") #plot limits plt.plot((m2_min, m1_max), (m2_min, m1_max), "k--") plt.plot((ns_max, ns_max), (m2_min, ns_max), "k:") plt.plot((gap_max, gap_max), (m2_min, gap_max), "k:") plt.plot((ns_max, m1_max), (ns_max, ns_max), "k:") plt.plot((gap_max, m1_max), (gap_max, gap_max), "k:") #colour plot plt.fill_between(np.arange(0.0, ns_max - 0.01, 0.01), gap_max, m1_max, color=source_color('NSBH'), alpha=0.5) plt.fill_between(np.arange(gap_max, m1_max, 0.01), 0.0, ns_max, color=source_color('NSBH')) plt.fill_between(np.arange(ns_max, gap_max, 0.01), np.arange(ns_max, gap_max, 0.01), m1_max, color=source_color('Mass Gap'), alpha=0.5) plt.fill_between(np.arange(0.0, ns_max, 0.01), ns_max, gap_max, color=source_color('Mass Gap'), alpha=0.5) plt.fill_between(np.arange(gap_max, m1_max, 0.01), np.arange(gap_max, m1_max, 0.01), m1_max, color=source_color('BBH'), alpha=0.5) plt.fill_between(np.arange(gap_max, m1_max, 0.01), np.arange(gap_max, m1_max, 0.01), gap_max, color=source_color('BBH')) plt.fill_between(np.arange(0.0, ns_max, 0.01), 0.0, np.arange(0.0, ns_max, 0.01), color=source_color('BNS')) plt.fill_between(np.arange(0.0, ns_max, 0.01), ns_max, np.arange(0.0, ns_max, 0.01), color=source_color('BNS'), alpha=0.5) plt.fill_between(np.arange(ns_max, gap_max, 0.01), np.arange(ns_max, gap_max, 0.01), color=source_color('Mass Gap')) plt.fill_between(np.arange(gap_max, m1_max, 0.01), ns_max, gap_max, color=source_color('Mass Gap')) #colour contour x1 = np.arange(mis, mib + 0.01, 0.01) plt.fill_between(x1, x1, m2mcm1(mcs, x1), facecolor=(1, 1, 1, 0.5), edgecolor=(0, 0, 0, 0)) x2 = np.arange(mib, lim_m1b, 0.01) plt.fill_between(x2, m2mcm1(mcb, x2), m2mcm1(mcs, x2), facecolor=(1, 1, 1, 0.5), edgecolor=(0, 0, 0, 0)) #plot_details plt.xlim(left=plot_args['x_limits'][0], right=plot_args['x_limits'][1]) plt.ylim(bottom=plot_args['y_limits'][0], top=plot_args['y_limits'][1]) plt.xlabel("M1") plt.ylabel("M2") return fig