def despot1_cost_function(
        combine=np.sum,
        cov=True,
        L=np.atleast_1d([1.0]),
        spgr=None,
        t1=np.array([1.0]),
        m0=np.array([1.0]),
        wrt_in=('t1', 'm0'),
):
    # Use default values if not specified
    if spgr is not None:
        spgr_theta = spgr.get('theta', np.atleast_1d([np.pi/4]))
        spgr_nex = spgr.get('nex', np.atleast_1d([1.0]))
        spgr_tr = spgr.get('tr', np.atleast_1d(tr))
        # Remove values with small NEX, these tend to cause inversion errors as they are essentially a row of 0s
        # Can be omitted if regularization in calc_crlb is used instead.
        spgr_nex, (spgr_theta, spgr_tr) = remove_small_nex(spgr_nex, (spgr_theta, spgr_tr))

    # Estimating T1 and M0, calculate Jacobian for each sample tissue
    Js = sort_jacobians(SPGR.jacobian(
        spgr_theta,
        spgr_tr,
        t1[:, newaxis],
        m0[:, newaxis],
        wrt_in=wrt_in,
    ))
    noise_variance = 1.0/spgr_nex
    try:
        crlb = np.array([calc_crlb(J, noise_variance) for J in Js])
    except spla.LinAlgError:
        print 'CRLB Error'
        print Js.shape
        print Js[0].shape
        raise
    if combine is None:
        # Bypass to return all the lower bound variances
        return crlb

    true_values = np.broadcast_arrays(*[locals()[tissue_param] for tissue_param in wrt_in])
    true_values = np.vstack(true_values).T
    if cov:
        # Minimize coefficient of variation
        return combine((L*crlb/true_values).sum(axis=0))
    else:
        # Maximize T1NR = minimize the negative
        return combine((-L*true_values/crlb).sum(axis=0))
def diffusion_cost_function(
    combine=np.sum,
    cov=True,
    L=np.atleast_1d([1.0]),
    diffusion=None,
    D=np.array([1.0]),
    m0=np.array([1.0]),
    wrt_in=("D", "m0"),
    regularization=1e-6,
):
    # Use default values if not specified
    if diffusion is not None:
        b = diffusion.get("b", np.atleast_1d([np.pi / 4]))
        nex = diffusion.get("nex", np.atleast_1d([1.0]))
        # Remove values with small NEX, these tend to cause inversion errors as they are essentially a row of 0s
        nex, (b,) = remove_small_nex(nex, (b,))

    # Estimating T1 and M0, calculate Jacobian for each sample tissue
    Js = sort_jacobians(Diffusion.jacobian(b, D[:, newaxis], m0[:, newaxis], wrt_in=wrt_in))
    noise_variance = 1.0 / nex
    try:
        crlb = np.array([calc_crlb(J, noise_variance, regularization=regularization) for J in Js])
    except spla.LinAlgError:
        print "CRLB Error"
        print Js.shape
        print Js[0].shape
        raise
    if combine is None:
        # Bypass to return all the lower bound variances
        return crlb

    true_values = np.broadcast_arrays(*[locals()[tissue_param] for tissue_param in wrt_in])
    true_values = np.vstack(true_values).T
    if cov:
        return combine((L * crlb / true_values).sum(axis=0))
    else:
        return combine((-L * true_values / crlb).sum(axis=0))