aboutsummaryrefslogtreecommitdiffstats
path: root/utils/plot.py
diff options
context:
space:
mode:
Diffstat (limited to 'utils/plot.py')
-rw-r--r--utils/plot.py1014
1 files changed, 288 insertions, 726 deletions
diff --git a/utils/plot.py b/utils/plot.py
index c7c94a5..2a9daf7 100644
--- a/utils/plot.py
+++ b/utils/plot.py
@@ -48,6 +48,25 @@ BAYES_K = 1. # Substantial degree of belief.
# BAYES_K = 5/2. # Decisive degree of belief
+LV_ATMO_90PC_LIMITS = {
+ 3: (2E-24, 1E-1),
+ 4: (2.7E-28, 3.16E-25),
+ 5: (1.5E-32, 1.12E-27),
+ 6: (9.1E-37, 2.82E-30),
+ 7: (3.6E-41, 1.77E-32),
+ 8: (1.4E-45, 1.00E-34)
+}
+
+
+PS = 8.203E-20 # GeV^{-1}
+PLANCK_SCALE = {
+ 5: PS,
+ 6: PS**2,
+ 7: PS**3,
+ 8: PS**4
+}
+
+
if os.path.isfile('./plot_llh/paper.mplstyle'):
plt.style.use('./plot_llh/paper.mplstyle')
elif os.environ.get('GOLEMSOURCEPATH') is not None:
@@ -79,6 +98,173 @@ def texture_label(x):
raise AssertionError
+def cmap_discretize(cmap, N):
+ colors_i = np.concatenate((np.linspace(0, 1., N), (0.,0.,0.,0.)))
+ colors_rgba = cmap(colors_i)
+ indices = np.linspace(0, 1., N+1)
+ cdict = {}
+ for ki,key in enumerate(('red','green','blue')):
+ cdict[key] = [ (indices[i], colors_rgba[i-1,ki], colors_rgba[i,ki]) for i in xrange(N+1) ]
+ # Return colormap object.
+ return mpl.colors.LinearSegmentedColormap(cmap.name + "_%d"%N, cdict, 1024)
+
+
+def get_limit(scales, statistic, mask_initial=False):
+ max_st = np.max(statistic)
+ if args.stat_method is StatCateg.BAYESIAN:
+ if (statistic[0] - max_st) > np.log(10**(BAYES_K)):
+ raise AssertionError('Discovered LV!')
+
+ try:
+ tck, u = splprep([scales, statistic], s=0)
+ except:
+ continue
+ sc, st = splev(np.linspace(0, 1, 10000), tck)
+
+ if mask_initial:
+ scales_rm = sc[sc >= scales[1]]
+ statistic_rm = st[sc >= scales[1]]
+ else:
+ scales_rm = sc
+ statistic_rm = st
+
+ min_idx = np.argmin(scales)
+ null = statistic[min_idx]
+ if args.stat_method is StatCateg.BAYESIAN:
+ reduced_ev = -(statistic_rm - null)
+ print 'reduced_ev', reduced_ev
+ al = scales_rm[reduced_ev > np.log(10**(BAYES_K))]
+ else:
+ assert 0
+ if len(al) == 0:
+ print 'No points for DIM {0} X {1}!'.format(dim, x)
+ continue
+ if reduced_ev[-1] < np.log(10**(BAYES_K)) - 0.1:
+ print 'Peaked contour does not exclude large scales! For ' \
+ 'DIM {0} X {1}!'.format(dim, x)
+ continue
+ lim = al[0]
+ print 'limit = {0}'.format(lim)
+ return lim
+
+
+def heatmap(data, scale, vmin=None, vmax=None, style='triangular'):
+ for k, v in data.items():
+ data[k] = np.array(v)
+ style = style.lower()[0]
+ if style not in ["t", "h", 'd']:
+ raise ValueError("Heatmap style must be 'triangular', 'dual-triangular', or 'hexagonal'")
+
+ vertices_values = polygon_generator(data, scale, style)
+
+ vertices = []
+ for v, value in vertices_values:
+ vertices.append(v)
+ return vertices
+
+
+def get_tax(ax, scale, ax_labels):
+ ax.set_aspect('equal')
+
+ # Boundary and Gridlines
+ fig, tax = ternary.figure(ax=ax, scale=scale)
+
+ # Draw Boundary and Gridlines
+ tax.boundary(linewidth=2.0)
+ tax.gridlines(color='grey', multiple=scale/5., linewidth=1.0, alpha=0.4, ls='--')
+ tax.gridlines(color='grey', multiple=scale/10., linewidth=0.5, alpha=0.4, ls=':')
+
+ # Set Axis labels and Title
+ fontsize = 23
+ tax.bottom_axis_label(ax_labels[0], fontsize=fontsize+8, position=(0.55, -0.20/2, 0.5), rotation=0)
+ tax.right_axis_label(ax_labels[1], fontsize=fontsize+8, offset=0.2, rotation=0)
+ tax.left_axis_label(ax_labels[2], fontsize=fontsize+8, offset=0.2, rotation=0)
+
+ # Remove default Matplotlib axis
+ tax.get_axes().axis('off')
+ tax.clear_matplotlib_ticks()
+
+ # Set ticks
+ ticks = np.linspace(0, 1, 6)
+ tax.ticks(ticks=ticks, locations=ticks*scale, axis='blr', linewidth=1,
+ offset=0.03, fontsize=fontsize, tick_formats='%.1f')
+ tax.ticks()
+
+ tax._redraw_labels()
+
+ return tax
+
+
+def flavour_contour(frs, ax, nbins, coverage, **kwargs):
+ """Plot the flavour contour for a specified coverage."""
+ # Histogram in flavour space
+ H, b = np.histogramdd(
+ (frs[:,0], frs[:,1], frs[:,2]),
+ bins=(nbins+1, nbins+1, nbins+1), range=((0, 1), (0, 1), (0, 1))
+ )
+ H = H / np.sum(H)
+
+ # 3D smoothing
+ smoothing = 0.05
+ H_s = gaussian_filter(H, sigma=smoothing)
+
+ # Finding coverage
+ H_r = np.ravel(H_s)
+ H_rs = np.argsort(H_r)[::-1]
+ H_crs = np.cumsum(H_r[H_rs])
+ thres = np.searchsorted(H_crs, coverage/100.)
+ mask_r = np.zeros(H_r.shape)
+ mask_r[H_rs[:thres]] = 1
+ mask = mask_r.reshape(H_s.shape)
+
+ # Get vertices inside covered region
+ binx = np.linspace(0, 1, nbins+1)
+ interp_dict = {}
+ for i in xrange(len(binx)):
+ for j in xrange(len(binx)):
+ for k in xrange(len(binx)):
+ if mask[i][j][k] == 1:
+ interp_dict[(i, j, k)] = H_s[i, j, k]
+ vertices = np.array(heatmap(interp_dict, nbins))
+ points = vertices.reshape((len(vertices)*3, 2))
+
+ # Convex full to find points forming exterior bound
+ pc = geometry.MultiPoint(points)
+ polygon = pc.convex_hull
+ ex_cor = np.array(list(polygon.exterior.coords))
+
+ # Join points with a spline
+ tck, u = splprep([ex_cor.T[0], ex_cor.T[1]], s=0., per=1, k=1)
+ xi, yi = map(np.array, splev(np.linspace(0, 1, 300), tck))
+
+ # Spline again to smooth
+ tck, u = splprep([xi, yi], s=0.4, per=1, k=3)
+ xi, yi = map(np.array, splev(np.linspace(0, 1, 300), tck))
+ ev_polygon = np.dstack((xi, yi))[0]
+
+ def project_toflavour(p):
+ """Convert from cartesian to flavour space."""
+ x, y = p
+ b = y / (np.sqrt(3)/2.)
+ a = x - b/2.
+ return [a, b, nbins-a-b]
+
+ # Remove points interpolated outside flavour triangle
+ f_ev_polygon = np.array(map(project_toflavour, ev_polygon))
+ xf, yf, zf = f_ev_polygon.T
+ mask = np.array((xf < 0) | (yf < 0) | (zf < 0) | (xf > nbins) |
+ (yf > nbins) | (zf > nbins))
+ ev_polygon = np.dstack((xi[~mask], yi[~mask]))[0]
+
+ # Plot
+ ax.plot(
+ ev_polygon.T[0], ev_polygon.T[1], label=r'{0}\%'.format(int(coverage)),
+ **kwargs
+ )
+ ax.scatter(points.T[0], points.T[1], marker='o', s=2, alpha=1, zorder=3,
+ **kwargs)
+
+
def plot_Tchain(Tchain, axes_labels, ranges):
"""Plot the Tchain using getdist."""
Tsample = mcsamples.MCSamples(
@@ -283,81 +469,6 @@ def plot_statistic(data, outfile, outformat, args, scale_param, label=None):
fig.savefig(outfile+'.'+of, bbox_inches='tight', dpi=150)
-def plot_sens_full(data, outfile, outformat, args):
- print 'Making FULL sensitivity plot'
-
- colour = {0:'red', 1:'blue', 2:'green', 3:'purple', 4:'orange', 5:'black'}
- xticks = ['{0}'.format(x) for x in range(np.min(args.dimensions),
- np.max(args.dimensions)+1)]
- yranges = [np.inf, -np.inf]
- legend_handles = []
-
- fig = plt.figure(figsize=(7, 5))
- ax = fig.add_subplot(111)
-
- ax.set_xlim(args.dimensions[0]-1, args.dimensions[-1]+1)
- ax.set_xticklabels([''] + xticks + [''])
- ax.set_xlabel(r'BSM operator dimension ' + r'$d$')
- ax.set_ylabel(r'${\rm log}_{10} \left (\Lambda^{-1} / GeV^{-d+4} \right )$')
-
- argsc = deepcopy(args)
- for idim in xrange(len(data)):
- dim = args.dimensions[idim]
- print 'dim', dim
- argsc.dimension = dim
- for isrc in xrange(len(data[idim])):
- src = args.source_ratios[isrc]
- argsc.source_ratio = src
-
- # fig_text = gen_figtext(argsc)
- scales, statistic = data[idim][isrc].T
- min_idx = np.argmin(scales)
- null = statistic[min_idx]
- if args.stat_method is StatCateg.BAYESIAN:
- reduced_ev = -(statistic - null)
- al = scales[reduced_ev > np.log(10**(BAYES_K))] # Strong degree of belief
- # al = scales[reduced_ev > 0.4] # Testing
- elif args.stat_method is StatCateg.FREQUENTIST:
- reduced_ev = -2*(statistic - null)
- al = scales[reduced_ev > 2.71] # 90% CL for 1 DOF via Wilks
- if len(al) == 0:
- print 'No points for DIM {0} FRS {1} NULL {2}!'.format(
- dim, solve_ratio(src), null
- )
- print 'Reduced EV {0}'.format(reduced_ev)
- continue
- lim = al[0]
- label = '[{0}, {1}, {2}]'.format(*solve_ratio(src))
- if lim < yranges[0]: yranges[0] = lim
- if lim > yranges[1]: yranges[1] = lim+4
- line = plt.Line2D(
- (dim-0.1, dim+0.1), (lim, lim), lw=3, color=colour[isrc], label=label
- )
- ax.add_line(line)
- if idim == 0: legend_handles.append(line)
- x_offset = isrc*0.05 - 0.05
- ax.annotate(
- s='', xy=(dim+x_offset, lim), xytext=(dim+x_offset, lim+3),
- arrowprops={'arrowstyle': '<-', 'lw': 1.2, 'color':colour[isrc]}
- )
-
- try:
- yranges = (myround(yranges[0], up=True), myround(yranges[1], down=True))
- ax.set_ylim(yranges)
- except: pass
-
- ax.legend(handles=legend_handles, prop=dict(size=8), loc='upper right')
- for ymaj in ax.yaxis.get_majorticklocs():
- ax.axhline(y=ymaj, ls=':', color='gray', alpha=0.4, linewidth=1)
- for xmaj in ax.xaxis.get_majorticklocs():
- ax.axvline(x=xmaj, ls=':', color='gray', alpha=0.4, linewidth=1)
-
- make_dir(outfile)
- for of in outformat:
- print 'Saving plot as {0}'.format(outfile+'.'+of)
- fig.savefig(outfile+'.'+of, bbox_inches='tight', dpi=150)
-
-
def plot_table_sens(data, outfile, outformat, args):
print 'Making TABLE sensitivity plot'
argsc = deepcopy(args)
@@ -375,23 +486,6 @@ def plot_table_sens(data, outfile, outformat, args):
xlims = (-60, -20)
ylims = (0.5, 1.5)
- LV_atmo_90pc_limits = {
- 3: (2E-24, 1E-1),
- 4: (2.7E-28, 3.16E-25),
- 5: (1.5E-32, 1.12E-27),
- 6: (9.1E-37, 2.82E-30),
- 7: (3.6E-41, 1.77E-32),
- 8: (1.4E-45, 1.00E-34)
- }
-
- PS = 8.203e-20 # GeV^{-1}
- planck_scale = {
- 5: PS,
- 6: PS**2,
- 7: PS**3,
- 8: PS**4
- }
-
colour = {0:'red', 1:'blue', 2:'green'}
rgb_co = {0:[1,0,0], 1:[0,0,1], 2:[0.0, 0.5019607843137255, 0.0]}
@@ -404,7 +498,7 @@ def plot_table_sens(data, outfile, outformat, args):
legend_elements = []
for idim, dim in enumerate(dimensions):
- print '== dim', dim
+ print '|||| DIM = {0}'.format(dim)
argsc.dimension = dim
gs0 = gridspec.GridSpecFromSubplotSpec(
len(textures), 1, subplot_spec=gs[idim], hspace=0
@@ -444,8 +538,8 @@ def plot_table_sens(data, outfile, outformat, args):
print '== src', src
argsc.source_ratio = src
- if dim in planck_scale:
- ps = np.log10(planck_scale[dim])
+ if dim in PLANCK_SCALE.iterkeys():
+ ps = np.log10(PLANCK_SCALE[dim])
if ps < xlims[0]:
ax.annotate(
s='', xy=(xlims[0], 1), xytext=(xlims[0]+1, 1),
@@ -462,31 +556,7 @@ def plot_table_sens(data, outfile, outformat, args):
ax.axvline(x=ps, color='purple', alpha=1., linewidth=1.5)
scales, statistic = ma.compress_rows(data[idim][isrc][itex]).T
- try:
- tck, u = splprep([scales, statistic], s=0)
- except:
- return
- sc, st = splev(np.linspace(0, 1, 10000), tck)
- scales_rm = sc[sc >= scales[1]]
- statistic_rm = st[sc >= scales[1]]
-
- min_idx = np.argmin(scales)
- null = statistic[min_idx]
- if args.stat_method is StatCateg.BAYESIAN:
- reduced_ev = -(statistic_rm - null)
- al = scales_rm[reduced_ev > np.log(10**(BAYES_K))]
- elif args.stat_method is StatCateg.FREQUENTIST:
- reduced_ev = -2*(statistic_rm - null)
- al = scales_rm[reduced_ev > 2.71] # 90% CL for 1 DOF via Wilks
- if len(al) == 0:
- print 'No points for DIM {0} FRS {1}!'.format(dim, src)
- continue
- if reduced_ev[-1] < np.log(10**(BAYES_K)) - 0.1:
- print 'Peaked contour does not exclude large scales! For ' \
- 'DIM {0} FRS{1}!'.format(dim, src)
- continue
- lim = al[0]
- print 'limit = {0}'.format(lim)
+ lim = get_limit(scales, statistic, mask_initial=True)
ax.axvline(x=lim, color=colour[isrc], alpha=1., linewidth=1.5)
ax.add_patch(patches.Rectangle(
@@ -503,7 +573,7 @@ def plot_table_sens(data, outfile, outformat, args):
)
if itex == 2:
- LV_lim = np.log10(LV_atmo_90pc_limits[dim])
+ LV_lim = np.log10(LV_ATMO_90PC_LIMITS[dim])
ax.add_patch(patches.Rectangle(
(LV_lim[1], ylim[0]), LV_lim[0]-LV_lim[1], np.diff(ylim),
fill=False, hatch='\\\\'
@@ -521,7 +591,6 @@ def plot_table_sens(data, outfile, outformat, args):
legend_elements.append(
Patch(facecolor='none', hatch='\\\\', edgecolor='k', label='IceCube, Nature.Phy.14,961(2018)')
)
-
legend = first_ax.legend(
handles=legend_elements, prop=dict(size=11), loc='upper left',
title='Excluded regions', framealpha=1., edgecolor='black',
@@ -531,9 +600,8 @@ def plot_table_sens(data, outfile, outformat, args):
plt.setp(legend.get_title(), fontsize='11')
legend.get_frame().set_linestyle('-')
- if show_data: ybound = 0.595
- else: ybound = 0.73
- if args.data is DataType.REAL and show_data:
+ ybound = 0.595
+ if args.data is DataType.REAL:
# fig.text(0.295, 0.684, 'IceCube Preliminary', color='red', fontsize=13,
fig.text(0.278, ybound, r'\bf IceCube Preliminary', color='red', fontsize=13,
ha='center', va='center', zorder=11)
@@ -550,556 +618,12 @@ def plot_table_sens(data, outfile, outformat, args):
fig.savefig(outfile+'.'+of, bbox_inches='tight', dpi=150)
-def plot_sens_fixed_angle(data, outfile, outformat, args):
- print 'Making FIXED_ANGLE sensitivity plot'
-
- colour = {0:'red', 1:'blue', 2:'green', 3:'purple', 4:'orange', 5:'black'}
- xticks = [r'$\mathcal{O}_{e\mu}$', r'$\mathcal{O}_{e\tau}$', r'$\mathcal{O}_{\mu\tau}$']
- argsc = deepcopy(args)
-
- LV_atmo_90pc_limits = {
- 3: (2E-24, 1E-1),
- 4: (2.7E-28, 3.16E-25),
- 5: (1.5E-32, 1.12E-27),
- 6: (9.1E-37, 2.82E-30),
- 7: (3.6E-41, 1.77E-32),
- 8: (1.4E-45, 1.00E-34)
- }
- ylims = {
- 3 : (-28, -22), 4 : (-34, -25), 5 : (-42, -28), 6 : (-48, -33),
- 7 : (-54, -37), 8 : (-61, -40)
- }
-
- for idim in xrange(len(data)):
- dim = args.dimensions[idim]
- print '= dim', dim
- argsc.dimension = dim
-
- # yranges = [np.inf, -np.inf]
- legend_handles = []
-
- fig = plt.figure(figsize=(7, 5))
- ax = fig.add_subplot(111)
- ax.set_xlim(0, len(xticks)+1)
- ax.set_xticklabels([''] + xticks + [''], fontsize=16)
- ax.set_xlabel(r'BSM operator angle', fontsize=16)
- ax.set_ylabel(r'${\mathrm {log}}_{10} \left (\Lambda^{-1}' + \
- get_units(dim) +r'\right )$', fontsize=17)
-
- ax.tick_params(axis='y', labelsize=15)
-
- for isrc in xrange(len(data[idim])):
- src = args.source_ratios[isrc]
- argsc.source_ratio = src
- print '== src', src
-
- for ian in xrange(len(data[idim][isrc])):
- print '=== an', ian
- scales, statistic = data[idim][isrc][ian].T
- tck, u = splprep([scales, statistic], s=0)
- scales, statistic = splev(np.linspace(0, 1, 1000), tck)
- min_idx = np.argmin(scales)
- null = statistic[min_idx]
- if args.stat_method is StatCateg.BAYESIAN:
- reduced_ev = -(statistic - null)
- al = scales[reduced_ev > np.log(10**(BAYES_K))] # Strong degree of belief
- elif args.stat_method is StatCateg.FREQUENTIST:
- reduced_ev = -2*(statistic - null)
- al = scales[reduced_ev > 2.71] # 90% CL for 1 DOF via Wilks
- if len(al) == 0:
- print 'No points for DIM {0} FRS {1}!'.format(dim, src)
- continue
- if reduced_ev[-1] < np.log(10**(BAYES_K)) - 0.1:
- print 'Peaked contour does not exclude large scales! For ' \
- 'DIM {0} FRS{1}!'.format(dim, src)
- continue
- arr_len = 1.5
- lim = al[0]
- print 'limit = {0}'.format(lim)
- label = '{0} : {1} : {2}'.format(*solve_ratio(src))
- # if lim < yranges[0]: yranges[0] = lim-arr_len
- # if lim > yranges[1]: yranges[1] = lim+arr_len+2
- # if lim > yranges[1]: yranges[1] = lim
- xoff = 0.15
- line = plt.Line2D(
- (ian+1-xoff, ian+1+xoff), (lim, lim), lw=2.5, color=colour[isrc], label=label
- )
- ax.add_line(line)
- if len(legend_handles) < isrc+1:
- legend_handles.append(line)
- x_offset = isrc*xoff/2. - xoff/2.
- ax.annotate(
- s='', xy=(ian+1+x_offset, lim+0.02), xytext=(ian+1+x_offset, lim-arr_len),
- arrowprops={'arrowstyle': '<-', 'lw': 1.5, 'color':colour[isrc]}
- )
- if ian == 2:
- lim = np.log10(LV_atmo_90pc_limits[dim][0])
- ax.add_patch(patches.Rectangle(
- (ian+1-xoff, lim), 2*xoff, 100, fill=True,
- facecolor='orange', alpha=0.3, linewidth=1, edgecolor='k'
- ))
- ax.annotate(s='IC atmospheric', xy=(ian+1, lim+0.13),
- color='red', rotation=90, fontsize=7,
- horizontalalignment='center',
- verticalalignment='bottom')
-
- # try:
- # yranges = (myround(yranges[0], up=True), myround(yranges[1], down=True))
- # ax.set_ylim(yranges)
- # except: pass
- ax.set_ylim(ylims[dim])
-
- legend = ax.legend(handles=legend_handles, prop=dict(size=10), loc='lower left',
- title=r'$\nu_e:\nu_\mu:\nu_\tau{\rm\:\:at\:\:source}$',
- framealpha=1., edgecolor='black')
- plt.setp(legend.get_title(), fontsize='10')
- legend.get_frame().set_linestyle('-')
-
- an_text = 'Dimension {0}'.format(dim)
- at = AnchoredText(
- an_text, prop=dict(size=10), frameon=True, loc=2
- )
- at.patch.set_boxstyle("round,pad=0.1,rounding_size=0.5")
- ax.add_artist(at)
-
- fig.text(0.52, 0.8, r'Excluded', color='red', fontsize=16, ha='center',
- va='center', fontweight='bold')
- # fig.text(0.52, 0.76, r'with strong evidence', color='red', fontsize=11,
- # ha='center', va='center')
-
- if args.data is DataType.REAL:
- fig.text(0.77, 0.14, 'IceCube Preliminary', color='red', fontsize=10,
- ha='center', va='center')
- elif args.data in [DataType.ASIMOV, DataType.REALISATION]:
- fig.text(0.77, 0.14, 'IceCube Simulation', color='red', fontsize=10,
- ha='center', va='center')
-
- for ymaj in ax.yaxis.get_majorticklocs():
- ax.axhline(y=ymaj, ls=':', color='gray', alpha=0.2, linewidth=1)
- for xmaj in ax.xaxis.get_majorticklocs():
- ax.axvline(x=xmaj, ls=':', color='gray', alpha=0.2, linewidth=1)
-
- out = outfile + '_DIM{0}'.format(dim)
- make_dir(out)
- for of in outformat:
- print 'Saving plot as {0}'.format(out+'.'+of)
- fig.savefig(out+'.'+of, bbox_inches='tight', dpi=150)
-
-
-def plot_sens_corr_angle(data, outfile, outformat, args):
- print 'Making CORR_ANGLE sensitivity plot'
-
- labels = [r'$sin^2(2\mathcal{O}_{12})$',
- r'$sin^2(2\mathcal{O}_{13})$',
- r'$sin^2(2\mathcal{O}_{23})$']
-
- argsc = deepcopy(args)
- for idim in xrange(len(data)):
- dim = args.dimensions[idim]
- print '= dim', dim
- argsc.dimension = dim
- for isrc in xrange(len(data[idim])):
- src = args.source_ratios[isrc]
- argsc.source_ratio = src
- fig_text = gen_figtext(argsc)
- print '== src', src
- for ian in xrange(len(data[idim][isrc])):
- print '=== an', ian
-
- d = data[idim][isrc][ian].reshape(
- len(data[idim][isrc][ian])**2, 3
- )
-
- fig = plt.figure(figsize=(7, 5))
- ax = fig.add_subplot(111)
- ax.set_ylim(0, 1)
- ax.set_ylabel(labels[ian])
- ax.set_xlabel(r'${\rm log}_{10} \left (\Lambda^{-1}'+get_units(dim)+r'\right )$')
-
- xranges = [np.inf, -np.inf]
- legend_handles = []
-
- y = d[:,0]
- x = d[:,1]
- z = d[:,2]
-
- print 'x', x
- print 'y', y
- print 'z', z
- null_idx = np.argmin(x)
- null = z[null_idx]
- print 'null = {0}, for scale = {1}'.format(null, x[null_idx])
-
- if args.stat_method is StatCateg.BAYESIAN:
- z_r = -(z - null)
- elif args.stat_method is StatCateg.FREQUENTIST:
- z_r = -2*(z - null)
- print 'scale', x
- print 'reduced ev', z_r
-
- pdat = np.array([x, y, z_r, np.ones(x.shape)]).T
- print 'pdat', pdat
- pdat_clean = []
- for d in pdat:
- if not np.any(np.isnan(d)): pdat_clean.append(d)
- pdat = np.vstack(pdat_clean)
- sort_column = 3
- pdat_sorted = pdat[pdat[:,sort_column].argsort()]
- uni, c = np.unique(pdat[:,sort_column], return_counts=True)
- print uni, c
- print len(uni)
- print np.unique(c)
-
- n = len(uni)
- assert len(np.unique(c)) == 1
- c = c[0]
- col_array = []
- for col in pdat_sorted.T:
- col_array.append(col.reshape(n, c))
- col_array = np.stack(col_array)
- sep_arrays = []
- for x_i in xrange(n):
- sep_arrays.append(col_array[:,x_i])
-
- print len(sep_arrays)
- sep_arrays = sep_arrays[0][:3]
- print sep_arrays
-
- if args.stat_method is StatCateg.BAYESIAN:
- reduced_pdat_mask = (sep_arrays[2] > np.log(10**(BAYES_K))) # Strong degree of belief
- elif args.stat_method is StatCateg.FREQUENTIST:
- reduced_pdat_mask = (sep_arrays[2] > 4.61) # 90% CL for 2 DOFS via Wilks
- reduced_pdat = sep_arrays.T[reduced_pdat_mask].T
- print 'reduced_pdat', reduced_pdat
-
- ax.tick_params(axis='x', labelsize=11)
- ax.tick_params(axis='y', labelsize=11)
-
- mini, maxi = np.min(x), np.max(x)
- ax.set_xlim((mini, maxi))
- ax.set_ylim(0, 1)
- ax.grid(b=False)
-
- x_v = reduced_pdat[0].round(decimals=4)
- y_v = reduced_pdat[1].round(decimals=4)
- uniques = np.unique(x_v)
- print 'uniques', uniques
- if len(uniques) == 1: continue
- bw = np.min(np.diff(uniques))
- print 'bw', bw
- print np.diff(uniques)
- uni_x_split = np.split(uniques, np.where(np.diff(uniques) > bw*(1e20))[0] + 1)
- print 'len(uni_x_split)', len(uni_x_split)
- for uni_x in uni_x_split:
- p_x_l, p_y_l = [], []
- p_x_u, p_y_u = [], []
- for uni in uni_x:
- idxes = np.where(x_v == uni)[0]
- ymin, ymax = 1, 0
- for idx in idxes:
- if y_v[idx] < ymin: ymin = y_v[idx]
- if y_v[idx] > ymax: ymax = y_v[idx]
- p_x_l.append(uni)
- p_y_l.append(ymin)
- p_x_u.append(uni)
- p_y_u.append(ymax)
- p_x_l, p_y_l = np.array(p_x_l, dtype=np.float64), np.array(p_y_l, dtype=np.float64)
- p_x_u, p_y_u = np.array(list(reversed(p_x_u)), dtype=np.float64), np.array(list(reversed(p_y_u)), dtype=np.float64)
- p_x = np.hstack([p_x_l, p_x_u])
- p_y = np.hstack([p_y_l, p_y_u])
- p_x = np.r_[p_x, p_x[0]]
- p_y = np.r_[p_y, p_y[0]]
- print 'p_x', p_x
- print 'p_y', p_y
- try:
- tck, u = splprep([p_x, p_y], s=1e-5, per=True)
- xi, yi = splev(np.linspace(0, 1, 1000), tck)
- except:
- xi, yi = p_x, p_y
- ax.fill(xi, yi, 'r', edgecolor='r', linewidth=1)
-
- at = AnchoredText(
- fig_text, prop=dict(size=10), frameon=True, loc=4
- )
- at.patch.set_boxstyle("round,pad=0.1,rounding_size=0.5")
- ax.add_artist(at)
- out = outfile + '_DIM{0}_SRC{1}_AN{2}'.format(dim, isrc, ian)
- make_dir(out)
- for of in outformat:
- print 'Saving plot as {0}'.format(out+'.'+of)
- fig.savefig(out+'.'+of, bbox_inches='tight', dpi=150)
-
-
-def cmap_discretize(cmap, N):
- colors_i = np.concatenate((np.linspace(0, 1., N), (0.,0.,0.,0.)))
- colors_rgba = cmap(colors_i)
- indices = np.linspace(0, 1., N+1)
- cdict = {}
- for ki,key in enumerate(('red','green','blue')):
- cdict[key] = [ (indices[i], colors_rgba[i-1,ki], colors_rgba[i,ki]) for i in xrange(N+1) ]
- # Return colormap object.
- return mpl.colors.LinearSegmentedColormap(cmap.name + "_%d"%N, cdict, 1024)
-
-
-def get_tax(ax, scale, ax_labels):
- ax.set_aspect('equal')
-
- # Boundary and Gridlines
- fig, tax = ternary.figure(ax=ax, scale=scale)
-
- # Draw Boundary and Gridlines
- tax.boundary(linewidth=2.0)
- tax.gridlines(color='grey', multiple=scale/5., linewidth=1.0, alpha=0.4, ls='--')
- tax.gridlines(color='grey', multiple=scale/10., linewidth=0.5, alpha=0.4, ls=':')
-
- # Set Axis labels and Title
- fontsize = 23
- tax.bottom_axis_label(ax_labels[0], fontsize=fontsize+8, position=(0.55, -0.20/2, 0.5), rotation=0)
- tax.right_axis_label(ax_labels[1], fontsize=fontsize+8, offset=0.2, rotation=0)
- tax.left_axis_label(ax_labels[2], fontsize=fontsize+8, offset=0.2, rotation=0)
-
- # Remove default Matplotlib axis
- tax.get_axes().axis('off')
- tax.clear_matplotlib_ticks()
-
- # Set ticks
- ticks = np.linspace(0, 1, 6)
- tax.ticks(ticks=ticks, locations=ticks*scale, axis='blr', linewidth=1,
- offset=0.03, fontsize=fontsize, tick_formats='%.1f')
- tax.ticks()
-
- tax._redraw_labels()
-
- return tax
-
-def triangle_project(frs, llh, outfile, outformat, args, llh_paramset, fig_text):
- print 'Making triangle projection'
- fontsize = 23
-
- def alp(x):
- y = list(x)
- y[-1] = 0.4
- return y
-
- cmap = plt.get_cmap('jet', 10)
- cmap_g = cmap_discretize(
- mpl.colors.LinearSegmentedColormap.from_list(
- "", ["lime", "gold", "darkorange"]),
- 10
- )
- cmap_b = cmap_discretize(
- mpl.colors.LinearSegmentedColormap.from_list(
- "", ["blue", "fuchsia", "darkmagenta"]),
- 10
- )
-
- mean = np.mean(llh)
- sig = np.std(llh)
- max_scale = np.max(llh)
- min_scale = np.min(mean-sig)
- norm = mpl.colors.Normalize(vmin=min_scale, vmax=max_scale)
-
- colour = map(alp, map(cmap, map(norm, llh)))
- # colour = map(alp, map(cmap_g, map(norm, llh)))
- # colour = map(alp, map(cmap_b, map(norm, llh)))
-
- # Figure
- fig = plt.figure(figsize=(8, 8))
- gs = gridspec.GridSpec(1, 2, width_ratios=[40, 1])
- gs.update(hspace=0.3, wspace=0.15)
-
- ax = fig.add_subplot(gs[0])
- tax = get_tax(ax, scale=1)
-
- # Plot
- tax.scatter(frs, marker='o', s=0.1, color=colour)
-
- # Contour TODO(shivesh)
- # tax.plot(contour_68_upper, linewidth=2.3, color='grey', zorder=0, alpha=0.6)
- # tax.plot(contour_68_lower, linewidth=2.3, color='grey', zorder=0, alpha=0.6)
- # tax.plot(contour_90_upper, linewidth=2.3, color='darkgrey', zorder=0, alpha=0.6)
- # tax.plot(contour_90_lower, linewidth=2.3, color='darkgrey', zorder=0, alpha=0.6)
-
- # Lines
- marker_style = dict(
- linestyle=' ', color='darkorange', linewidth=1.2,
- markersize=14, zorder=0
- )
-
- # Colorbar
- ax0 = fig.add_subplot(gs[1])
- cb = mpl.colorbar.ColorbarBase(ax0, cmap=cmap, norm=norm,
- orientation='vertical')
- cb.ax.tick_params(labelsize=fontsize-5)
- cb.set_label(r'$LLH$', fontsize=fontsize+5, labelpad=20,
- horizontalalignment='center')
-
- make_dir(outfile)
- for of in outformat:
- print 'Saving plot as {0}'.format(outfile+'.'+of)
- fig.savefig(outfile+'.'+of, bbox_inches='tight', dpi=150)
-
-
-def heatmap(data, scale, vmin=None, vmax=None, style='triangular'):
- for k, v in data.items():
- data[k] = np.array(v)
- style = style.lower()[0]
- if style not in ["t", "h", 'd']:
- raise ValueError("Heatmap style must be 'triangular', 'dual-triangular', or 'hexagonal'")
-
- vertices_values = polygon_generator(data, scale, style)
-
- vertices = []
- for v, value in vertices_values:
- vertices.append(v)
- return vertices
-
-
-def flavour_contour(frs, ax, nbins, coverage, **kwargs):
- """Plot the flavour contour for a specified coverage."""
- # Histogram in flavour space
- H, b = np.histogramdd(
- (frs[:,0], frs[:,1], frs[:,2]),
- bins=(nbins+1, nbins+1, nbins+1), range=((0, 1), (0, 1), (0, 1))
- )
- H = H / np.sum(H)
-
- # 3D smoothing
- smoothing = 0.05
- H_s = gaussian_filter(H, sigma=smoothing)
-
- # Finding coverage
- H_r = np.ravel(H_s)
- H_rs = np.argsort(H_r)[::-1]
- H_crs = np.cumsum(H_r[H_rs])
- thres = np.searchsorted(H_crs, coverage/100.)
- mask_r = np.zeros(H_r.shape)
- mask_r[H_rs[:thres]] = 1
- mask = mask_r.reshape(H_s.shape)
-
- # Get vertices inside covered region
- binx = np.linspace(0, 1, nbins+1)
- interp_dict = {}
- for i in xrange(len(binx)):
- for j in xrange(len(binx)):
- for k in xrange(len(binx)):
- if mask[i][j][k] == 1:
- interp_dict[(i, j, k)] = H_s[i, j, k]
- vertices = np.array(heatmap(interp_dict, nbins))
- points = vertices.reshape((len(vertices)*3, 2))
-
- # Convex full to find points forming exterior bound
- pc = geometry.MultiPoint(points)
- polygon = pc.convex_hull
- ex_cor = np.array(list(polygon.exterior.coords))
-
- # Join points with a spline
- tck, u = splprep([ex_cor.T[0], ex_cor.T[1]], s=0., per=1, k=1)
- xi, yi = map(np.array, splev(np.linspace(0, 1, 300), tck))
-
- # Spline again to smooth
- tck, u = splprep([xi, yi], s=0.4, per=1, k=3)
- xi, yi = map(np.array, splev(np.linspace(0, 1, 300), tck))
- ev_polygon = np.dstack((xi, yi))[0]
-
- def project_toflavour(p):
- """Convert from cartesian to flavour space."""
- x, y = p
- b = y / (np.sqrt(3)/2.)
- a = x - b/2.
- return [a, b, nbins-a-b]
-
- # Remove points interpolated outside flavour triangle
- f_ev_polygon = np.array(map(project_toflavour, ev_polygon))
- xf, yf, zf = f_ev_polygon.T
- mask = np.array((xf < 0) | (yf < 0) | (zf < 0) | (xf > nbins) |
- (yf > nbins) | (zf > nbins))
- ev_polygon = np.dstack((xi[~mask], yi[~mask]))[0]
-
- # Plot
- ax.plot(
- ev_polygon.T[0], ev_polygon.T[1], label=r'{0}\%'.format(int(coverage)),
- **kwargs
- )
- ax.scatter(points.T[0], points.T[1], marker='o', s=2, alpha=1, zorder=3,
- **kwargs)
-
-def plot_source_ternary(data, outfile, outformat, args):
- """Ternary plot in the source flavour space for each operator texture."""
- r_data = np.full((data.shape[0], data.shape[2], data.shape[1], data.shape[3], data.shape[4]), np.nan)
- for idim in xrange(data.shape[0]):
- for isrc in xrange(data.shape[1]):
- for isce in xrange(data.shape[2]):
- r_data[idim][isce][isrc] = data[idim][isrc][isce]
- r_data = ma.masked_invalid(r_data)
- print r_data.shape, 'r_data.shape'
- nsrcs = int(len(args.source_ratios) / 3)
-
- for idim, dim in enumerate(args.dimensions):
- print '|||| DIM = {0}, {1}'.format(idim, dim)
- for isce in xrange(r_data.shape[1]):
- print '|||| SCEN = {0}'.format(str_enum(MixingScenario(isce+1)))
- fig = plt.figure(figsize=(8, 8))
- ax = fig.add_subplot(111)
- tax = get_tax(ax, scale=nsrcs)
- interp_dict = {}
- for isrc, src in enumerate(args.source_ratios):
- src_sc = tuple(np.array(src)*(nsrcs-1))
- print '|||| SRC = {0}'.format(src)
- scales, statistic = ma.compress_rows(r_data[idim][isce][isrc]).T
- print 'scales', scales
- print 'statistic', statistic
-
- try:
- tck, u = splprep([scales, statistic], s=0)
- except:
- interp_dict[src_sc] = -60
- continue
- # sc, st = splev(np.linspace(0, 1, 10000), tck)
- sc, st = splev(np.linspace(0, 1, 20), tck)
- scales_rm = sc[sc >= scales[1]]
- statistic_rm = st[sc >= scales[1]]
- # scales_rm = sc
- # statistic_rm = st
-
- min_idx = np.argmin(scales)
- null = statistic[min_idx]
- if args.stat_method is StatCateg.BAYESIAN:
- reduced_ev = -(statistic_rm - null)
- print 'reduced_ev', reduced_ev
- al = scales_rm[reduced_ev > np.log(10**(BAYES_K))]
- else:
- assert 0
- if len(al) == 0:
- print 'No points for DIM {0} FRS {1}!'.format(dim, src)
- interp_dict[src_sc] = -60
- continue
- if reduced_ev[-1] < np.log(10**(BAYES_K)) - 0.1:
- print 'Peaked contour does not exclude large scales! For ' \
- 'DIM {0} FRS{1}!'.format(dim, src)
- interp_dict[src_sc] = -60
- continue
- lim = al[0]
- print 'limit = {0}'.format(lim)
-
- interp_dict[src_sc] = lim
- print 'interp_dict', interp_dict
- print
- print 'vertices', heatmap(interp_dict, nsrcs)
- print
- tax.heatmap(interp_dict, scale=nsrcs, vmin=-60, vmax=-30)
- make_dir(outfile)
- for of in outformat:
- print 'Saving plot as {0}'.format(outfile+'_SCEN{0}.'.format(isce)+of)
- fig.savefig(outfile+'_SCEN{0}.'.format(isce)+of, bbox_inches='tight', dpi=150)
- print 'nsrcs', nsrcs
- assert 0
-
-
def plot_x(data, outfile, outformat, args):
"""Limit plot as a function of the source flavour ratio for each operator
texture."""
print 'Making X sensitivity plot'
+ argsc = deepcopy(args)
+
dims = args.dimensions
srcs = args.source_ratios
x_arr = np.array([i[0] for i in srcs])
@@ -1120,72 +644,110 @@ def plot_x(data, outfile, outformat, args):
r_data = ma.masked_invalid(r_data)
print r_data.shape, 'r_data.shape'
+ fig = plt.figure(figsize=(8, 6))
+ gs = gridspec.GridSpec(dims, 1)
+ gs.update(hspace=0.15)
+
+ xlims = (-60, -20)
+ ylims = (0, 1)
+
+ first_ax = None
+ legend_log = []
+ legend_elements = []
+
for idim, dim in enumerate(dims):
- print '|||| DIM = {0}, {1}'.format(idim, dim)
- boundaries = SCALE_BOUNDARIES[dim]
+ print '|||| DIM = {0}'.format(dim)
+ argsc.dimension = dim
+ ax = fig.add_subplot(gs[idim])
- fig = plt.figure(figsize=(4, 4))
- ax = fig.add_subplot(111)
- ax.tick_params(axis='x', labelsize=12)
+ ax.set_xlim(xlims)
+ ax.set_ylim(ylims)
ax.tick_params(axis='y', labelsize=12)
- ax.set_xlabel(r'$x$', fontsize=18)
- ax.set_ylabel(r'${\rm New\:Physics\:Scale}\:[\:{\rm log}_{10} (\Lambda_{d='+str(dim)+r'}^{-1}\:'+get_units(args.dimension)+r')\: ]$', fontsize=12)
- ax.set_xlim(0, 1)
- ax.set_ylim(boundaries)
+ for xmaj in ax.xaxis.get_majorticklocs():
+ ax.axvline(x=xmaj, ls=':', color='gray', alpha=0.2, linewidth=1)
+ ax.get_xaxis().set_visible(False)
+
for itex, tex in enumerate(textures):
print '|||| TEX = {0}'.format(tex)
lims = np.full(len(srcs), np.nan)
+
for isrc, src in enumerate(srcs):
x = src[0]
print '|||| X = {0}'.format(x)
scales, statistic = ma.compress_rows(r_data[idim][itex][isrc]).T
- print 'scales', scales
- print 'statistic', statistic
- max_st = np.max(statistic)
- if args.stat_method is StatCateg.BAYESIAN:
- if (statistic[0] - max_st) > np.log(10**(BAYES_K)):
- raise AssertionError('Discovered LV!')
-
- try:
- tck, u = splprep([scales, statistic], s=0)
- except:
- continue
- sc, st = splev(np.linspace(0, 1, 10000), tck)
- scales_rm = sc[sc >= scales[1]]
- statistic_rm = st[sc >= scales[1]]
-
- min_idx = np.argmin(scales)
- null = statistic[min_idx]
- if args.stat_method is StatCateg.BAYESIAN:
- reduced_ev = -(statistic_rm - null)
- print 'reduced_ev', reduced_ev
- al = scales_rm[reduced_ev > np.log(10**(BAYES_K))]
- else:
- assert 0
- if len(al) == 0:
- print 'No points for DIM {0} X {1}!'.format(dim, x)
- continue
- if reduced_ev[-1] < np.log(10**(BAYES_K)) - 0.1:
- print 'Peaked contour does not exclude large scales! For ' \
- 'DIM {0} X {1}!'.format(dim, x)
- continue
- lim = al[0]
- print 'limit = {0}'.format(lim)
-
- lims[isrc] = lim
+ lims[isrc] = get_limit(scales, statistic, mask_initial=True)
+
lims = ma.masked_invalid(lims)
size = np.sum(~lims.mask)
if size == 0: continue
+
tck, u = splprep([x_arr[~lims.mask], lims[~lims.mask]], s=0, k=1)
- x, y = splev(np.linspace(0, 1, 100), tck)
- ax.scatter(x_arr, lims, marker='o', s=10, alpha=1, zorder=5)
- ax.fill_between(x, y, 0, label=texture_label(tex))
- for ymaj in ax.yaxis.get_majorticklocs():
- ax.axhline(y=ymaj, ls=':', color='gray', alpha=0.3, linewidth=1)
- for xmaj in ax.xaxis.get_majorticklocs():
- ax.axvline(x=xmaj, ls=':', color='gray', alpha=0.3, linewidth=1)
- ax.legend()
- make_dir(outfile)
- for of in outformat:
- print 'Saving plot as {0}'.format(outfile+'_DIM{0}.'.format(dim)+of)
- fig.savefig(outfile+'_DIM{0}.'.format(dim)+of, bbox_inches='tight', dpi=150)
+ y, x = splev(np.linspace(0, 1, 100), tck)
+ ax.scatter(lims, x_arr, marker='o', s=10, alpha=1, zorder=5,
+ color=colour[itex])
+ ax.fill_betweenx(y, x, 0, color=colour[itex], alpha=1.)
+
+ if itex not in legend_log:
+ legend_log.append(itex)
+ label = texture_label(tex)
+ legend_elements.append(
+ Patch(facecolor=rgb_co[isrc]+[0.3],
+ edgecolor=rgb_co[isrc]+[1], label=label)
+ )
+
+ if dim in PLANCK_SCALE.iterkeys():
+ ps = np.log10(PLANCK_SCALE[dim])
+ if ps < xlims[0]:
+ ax.annotate(
+ s='', xy=(xlims[0], 1), xytext=(xlims[0]+1, 1),
+ arrowprops={'arrowstyle': '->, head_length=0.2',
+ 'lw': 1, 'color':'purple'}
+ )
+ elif ps > xlims[1]:
+ ax.annotate(
+ s='', xy=(xlims[1]-1, 1), xytext=(xlims[1], 1),
+ arrowprops={'arrowstyle': '<-, head_length=0.2',
+ 'lw': 1, 'color':'purple'}
+ )
+ else:
+ ax.axvline(x=ps, color='purple', alpha=1., linewidth=1.5)
+
+ # ax.set_ylabel(r'${\rm Source\:Flavor\:Ratio}\:[\:x, \left (1-x\right ), 0\:]$',
+ # fontsize=19)
+
+ ax.get_xaxis().set_visible(True)
+ ax.set_xlabel(r'${\rm New\:Physics\:Scale}\:[\:{\rm log}_{10} (\Lambda^{-1}\:/\:{\rm GeV}^{-d+4})\: ]$',
+ fontsize=19)
+ ax.tick_params(axis='x', labelsize=16)
+
+ purple = [0.5019607843137255, 0.0, 0.5019607843137255]
+ legend_elements.append(
+ Patch(facecolor=purple+[0.7], edgecolor=purple+[1], label='Planck Scale Expectation')
+ )
+ legend_elements.append(
+ Patch(facecolor='none', hatch='\\\\', edgecolor='k', label='IceCube, Nature.Phy.14,961(2018)')
+ )
+ legend = first_ax.legend(
+ handles=legend_elements, prop=dict(size=11), loc='upper left',
+ title='Excluded regions', framealpha=1., edgecolor='black',
+ frameon=True
+ )
+ first_ax.set_zorder(10)
+ plt.setp(legend.get_title(), fontsize='11')
+ legend.get_frame().set_linestyle('-')
+
+ ybound = 0.595
+ if args.data is DataType.REAL:
+ fig.text(0.278, ybound, r'\bf IceCube Preliminary', color='red', fontsize=13,
+ ha='center', va='center', zorder=11)
+ elif args.data is DataType.REALISATION:
+ fig.text(0.278, ybound-0.05, r'\bf IceCube Simulation', color='red', fontsize=13,
+ ha='center', va='center', zorder=11)
+ else:
+ fig.text(0.278, ybound, r'\bf IceCube Simulation', color='red', fontsize=13,
+ ha='center', va='center', zorder=11)
+
+ make_dir(outfile)
+ for of in outformat:
+ print 'Saving plot as {0}'.format(outfile+'_DIM{0}.'.format(dim)+of)
+ fig.savefig(outfile+'_DIM{0}.'.format(dim)+of, bbox_inches='tight', dpi=150)