<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Minimum Variance Cluster Analysis
We are going to use a minimum variance criterion with the
Jensen-Shannon divergence to coarse-grain the quad well
dataset.
Step1:  Get the dataset
Step2:  Define a regular spatial clusterer
Step3:  Plot our MSM energies
Step4:  Make a model with out macrostating to get linkage information
Step5:  Use mvca.linkage to get a scipy linkage object
Step6:  Use mvca.elbow_distance to get the objective function change with agglomeration
Step7:  Plot some macrostate models
<ASSISTANT_TASK:>
Python Code:
from msmbuilder.example_datasets import QuadWell
from msmbuilder.msm import MarkovStateModel
from msmbuilder.lumping import MVCA
import numpy as np
import scipy.cluster.hierarchy
import matplotlib.pyplot as plt
% matplotlib inline
Explanation: Minimum Variance Cluster Analysis
We are going to use a minimum variance criterion with the
Jensen-Shannon divergence to coarse-grain the quad well
dataset.
End of explanation
q = QuadWell(random_state=998).get()
ds = q['trajectories']
Explanation: Get the dataset
End of explanation
def regular_spatial_clustering(ds, n_bins=20, halfwidth=np.pi):
    new_ds = []
    for t in ds:
        new_t = []
        for i, f in enumerate(t):
            width = 2*halfwidth
            temp = f + halfwidth
            reg = np.floor(n_bins*temp/width)
            new_t.append(int(reg))
        new_ds.append(np.array(new_t))
    return new_ds
halfwidth = max(np.abs([max(np.abs(f)) for f in ds]))[0]
assignments = regular_spatial_clustering(ds, halfwidth=halfwidth)
msm_mdl = MarkovStateModel()
msm_mdl.fit(assignments)
Explanation: Define a regular spatial clusterer
End of explanation
def get_centers(n_bins=20, halfwidth=np.pi):
    centers = []
    tot = 2*halfwidth
    interval = tot/n_bins
    for i in range(n_bins):
        c = (i+1)*interval - interval/2. - halfwidth
        centers.append(c)
    return(centers)
ccs = get_centers(halfwidth=halfwidth)
nrgs = [-0.6*np.log(p) for p in msm_mdl.populations_]
m,s,b = plt.stem(ccs, nrgs, 'deepskyblue', bottom=-1)
for i in s:
    i.set_linewidth(8)
    
potential = lambda x: 4 * (x ** 8 + 0.8 * np.exp(-80 * x ** 2) + 0.2 * np.exp(
            -80 * (x - 0.5) ** 2) +
                    0.5 * np.exp(-40 * (x + 0.5) ** 2))
exes = np.linspace(-np.pi,np.pi,1000)
whys = potential(exes)
plt.plot(exes, whys, linewidth=2, color='k')
    
plt.xlim([-halfwidth, halfwidth])
plt.ylim([0,4])
Explanation: Plot our MSM energies
End of explanation
mvca = MVCA.from_msm(msm_mdl, n_macrostates=None, get_linkage=True)
Explanation: Make a model with out macrostating to get linkage information
End of explanation
scipy.cluster.hierarchy.dendrogram(mvca.linkage,
                                   color_threshold=1.1,
                                   no_labels=True)
plt.show()
Explanation: Use mvca.linkage to get a scipy linkage object
End of explanation
for i in range(19):
    s = str(i+1)
    plt.scatter([i+1], mvca.elbow_data[i], color='k', marker=r'$%s$'%(i+1),
            s=60*(np.floor((i+1)/10)+1)) # so numbers are approximately the same size
plt.xlabel('Number of macrostates')
plt.xticks([])
plt.show()
Explanation: Use mvca.elbow_distance to get the objective function change with agglomeration
End of explanation
color_list = ['deepskyblue', 'hotpink', 'turquoise', 'indigo', 'gold',
              'olivedrab', 'orangered', 'whitesmoke']
def plot_macrostates(n_macrostates=4):
    mvca_mdl = MVCA.from_msm(msm_mdl, n_macrostates=n_macrostates)
    for i, _ in enumerate(mvca_mdl.microstate_mapping_):
        m,s,b = plt.stem([ccs[i]], [nrgs[i]],
                     color_list[mvca_mdl.microstate_mapping_[i]],
                     markerfmt=' ', bottom=-1)
        for i in s:
            i.set_linewidth(5)
    plt.plot(exes, whys, color='black', linewidth=1.5)
    plt.ylim([0,4])
    plt.xlim([-halfwidth,halfwidth])
plt.subplots(nrows=2, ncols=3, figsize=(12,6))
for i in range(6):
    plt.subplot(2,3,i+1)
    plot_macrostates(n_macrostates=i+2)
    plt.title('%i macrostates'%(i+2))
    
plt.tight_layout()
Explanation: Plot some macrostate models
End of explanation
<END_TASK>