Interactive basis plaything#

Allows you to interactively move the basis points (black dots) like in the animation below.

morphing animation

import numpy as np
import bqplot
from bqplot import pyplot as plt
from IPython.display import display
from ipywidgets import Layout
import numpy as np
import pandas as pd
%matplotlib notebook
import sys

try:
    from madminer.utils.morphing import PhysicsMorpher as Morpher
except ImportError:
    sys.path.append('../..')
    from madminer.utils.morphing import PhysicsMorpher as Morpher
    

Settings#

n_bases = 1
n_resolution = 50

Preparation#

morpher = Morpher(parameter_max_power=[4,4],
                  parameter_range=[(-1.,1.), (-1.,1.)])
_ = morpher.find_components(max_overall_power=4)
xi = np.linspace(-1.,1.,n_resolution)
yi = np.linspace(-1.,1.,n_resolution)
xx, yy = np.meshgrid(xi, yi)
xx = xx.reshape((-1,1))
yy = yy.reshape((-1,1))
theta_evaluation = np.hstack([xx, yy])

x_updated = False
y_updated = False

Basis evaluation#

def evaluate_basis(basis=None):
    
    # Optimization
    if basis is None:
        basis = morpher.optimize_basis()

    # Evaluate basis
    squared_weights = []

    for theta in theta_evaluation:
        wi = morpher.calculate_morphing_weights(theta, basis)
        squared_weights.append(np.sum(wi*wi)**0.5)

    squared_weights = np.array(squared_weights).reshape((n_resolution,n_resolution))
    
    return basis, squared_weights

Initial set up#

basis, squared_weights = evaluate_basis(None)

Interactive tool#

def update(change):
    global basis, squared_weights, x_updated, y_updated
    
    variable = change['name']
    values = change['new']
    
    if variable == 'x':
        basis[:,0] = values
        x_updated = True
    elif variable == 'y':
        basis[:,1] = values
        y_updated = True
    
    if x_updated and y_updated:
        basis, squared_weights = evaluate_basis(basis)
        heat.color = np.log(squared_weights) / np.log(10)
        
        x_updated = False
        y_updated = False
x_sc = bqplot.scales.LinearScale(min=-1., max=1.)
y_sc = bqplot.scales.LinearScale(min=-1., max=1.)
c_sc = bqplot.scales.ColorScale(min=0, max=1., scheme='YlOrRd')

heat = bqplot.GridHeatMap(color=np.log(squared_weights) / np.log(10),
                          scales={'row': x_sc, 'column': y_sc, 'color': c_sc},
                          row=yi,
                          column=xi,
                          stroke=None)

scatter = bqplot.Scatter(colors=['black']*len(basis[:,0]),
                         x=basis[:,0],
                         y=basis[:,1],
                         scales={'x': x_sc, 'y': y_sc})

ax_x = bqplot.Axis(scale=x_sc, label='fW')
ax_y = bqplot.Axis(scale=y_sc, orientation='vertical', label='fWW')
ax_c = bqplot.ColorAxis(scale=c_sc,
                        orientation='vertical', 
                        side='right')

fig = bqplot.Figure(marks=[heat, scatter],
                    axes=[ax_x, ax_y, ax_c],
                    layout=Layout(width='600px', height='600px'))

display(fig)

scatter.observe(update, ['y','x'])
scatter.enable_move = True