Ejemplo n.º 1
0
def fit_gaussian(spectra, f_ppm, lb=2.6, ub=3.6):
    """
   Fit a gaussian function to the difference spectra to be used for estimation
   of the GABA peak.
   
   Parameters
   ----------
   spectra : array of shape (n_transients, n_points)
      Typically the difference of the on/off spectra in each transient.

   f_ppm : array

   lb, ub : floats
      In ppm, the range over which optimization is bounded
   
   """
    idx = ut.make_idx(f_ppm, lb, ub)
    # We are only going to look at the interval between lb and ub
    n_points = idx.stop - idx.start
    n_params = 5
    fit_func = ut.gaussian
    # Set the bounds for the optimization
    bounds = [
        (lb, ub),  # peak location
        (0, None),  # sigma
        (0, None),  # amp
        (None, None),  # offset
        (None, None)  # drift
    ]

    model = np.empty((spectra.shape[0], n_points))
    signal = np.empty((spectra.shape[0], n_points))
    params = np.empty((spectra.shape[0], n_params))
    for ii, xx in enumerate(spectra):
        # We fit to the real spectrum:
        signal[ii] = np.real(xx[idx])
        # Use the signal for a rough estimate of the parameters for
        # initialization :
        max_idx = np.argmax(signal[ii])
        max_sig = np.max(signal[ii])
        initial_f0 = f_ppm[idx][max_idx]
        half_max_idx = np.argmin(np.abs(signal[ii] - max_sig / 2))
        # We estimate sigma as the hwhm:
        initial_sigma = np.abs(initial_f0 - f_ppm[idx][half_max_idx])
        initial_off = np.min(signal[ii])
        initial_drift = 0
        initial_amp = max_sig

        initial = (initial_f0, initial_sigma, initial_amp, initial_off,
                   initial_drift)

        params[ii], _ = lsq.leastsqbound(mopt.err_func,
                                         initial,
                                         args=(f_ppm[idx], np.real(signal[ii]),
                                               fit_func),
                                         bounds=bounds)

        model[ii] = fit_func(f_ppm[idx], *params[ii])

    return model, signal, params
Ejemplo n.º 2
0
def _do_two_gaussian_fit(freqs, signal, bounds=None):
    """
   Helper function for the two gaussian fit
   """
    initial = _two_func_initializer(freqs, signal)
    # Edit out the ones we want in the order we want them:
    initial = (initial[0], initial[1], initial[6], initial[7], initial[2],
               initial[3], initial[10], initial[11])

    # We want to preferntially weight the error on estimating the height of the
    # individual peaks, so we formulate an error-weighting function based on
    # these peaks, which is simply a two-gaussian bumpety-bump:
    w = (ut.gaussian(freqs, initial[0], 0.075, 1, 0, 0) +
         ut.gaussian(freqs, initial[1], 0.075, 1, 0, 0))

    # Further, we want to also optimize on the individual gaussians error, to
    # restrict the fit space a bit more. For this purpose, we will pass a list
    # of gaussians with indices into the parameter list, so that we can do
    # that (see mopt.err_func for the mechanics).
    func_list = [[
        ut.gaussian, [0, 2, 4, 6, 7],
        ut.gaussian(freqs, initial[0], 0.075, 1, 0, 0)
    ],
                 [
                     ut.gaussian, [1, 3, 5, 6, 7],
                     ut.gaussian(freqs, initial[1], 0.075, 1, 0, 0)
                 ]]

    params, _ = lsq.leastsqbound(mopt.err_func,
                                 initial,
                                 args=(freqs, np.real(signal), ut.two_gaussian,
                                       w, func_list),
                                 bounds=bounds)

    return params
Ejemplo n.º 3
0
def _do_lorentzian_fit(freqs, signal, bounds=None):
    """

   Helper function, so that Lorentzian fit can be generalized to different
   frequency scales (Hz and ppm).
   
   """
    # Use the signal for a rough estimate of the parameters for initialization:
    max_idx = np.argmax(np.real(signal))
    max_sig = np.max(np.real(signal))
    initial_f0 = freqs[max_idx]
    half_max_idx = np.argmin(np.abs(np.real(signal) - max_sig / 2))
    initial_hwhm = np.abs(initial_f0 - freqs[half_max_idx])
    # Everything should be treated as real, except for the phase!
    initial_ph = np.angle(signal[signal.shape[-1] / 2.])

    initial_off = np.min(np.real(signal))
    initial_drift = 0
    initial_a = (np.sum(
        np.real(signal)[max_idx:max_idx + np.abs(half_max_idx) * 2])) * 2

    initial = (initial_f0, initial_a, initial_hwhm, initial_ph, initial_off,
               initial_drift)

    params, _ = lsq.leastsqbound(mopt.err_func,
                                 initial,
                                 args=(freqs, np.real(signal), ut.lorentzian),
                                 bounds=bounds)
    return params
Ejemplo n.º 4
0
def _do_two_gaussian_fit(freqs, signal, bounds=None):
   """
   Helper function for the two gaussian fit
   """
   initial = _two_func_initializer(freqs, signal)
   # Edit out the ones we want in the order we want them: 
   initial = (initial[0], initial[1],
              initial[6], initial[7],
              initial[2], initial[3],
              initial[10], initial[11])

   # We want to preferntially weight the error on estimating the height of the
   # individual peaks, so we formulate an error-weighting function based on
   # these peaks, which is simply a two-gaussian bumpety-bump:
   w = (ut.gaussian(freqs, initial[0], 0.075, 1, 0, 0) +
        ut.gaussian(freqs, initial[1], 0.075, 1, 0, 0))

   # Further, we want to also optimize on the individual gaussians error, to
   # restrict the fit space a bit more. For this purpose, we will pass a list
   # of gaussians with indices into the parameter list, so that we can do
   # that (see mopt.err_func for the mechanics).
   func_list = [[ut.gaussian, [0,2,4,6,7],
                 ut.gaussian(freqs, initial[0], 0.075, 1, 0, 0)],
                [ut.gaussian, [1,3,5,6,7],
                 ut.gaussian(freqs, initial[1], 0.075, 1, 0, 0)]]

   params, _ = lsq.leastsqbound(mopt.err_func, initial,
                                args=(freqs, np.real(signal),
                                ut.two_gaussian, w, func_list),
                                bounds=bounds)

   return params
Ejemplo n.º 5
0
def _do_lorentzian_fit(freqs, signal, bounds=None):
   """

   Helper function, so that Lorentzian fit can be generalized to different
   frequency scales (Hz and ppm).
   
   """
   # Use the signal for a rough estimate of the parameters for initialization:
   max_idx = np.argmax(np.real(signal))
   max_sig = np.max(np.real(signal))
   initial_f0 = freqs[max_idx]
   half_max_idx = np.argmin(np.abs(np.real(signal) - max_sig/2))
   initial_hwhm = np.abs(initial_f0 - freqs[half_max_idx])
   # Everything should be treated as real, except for the phase!
   initial_ph = np.angle(signal[signal.shape[-1]/2.])

   initial_off = np.min(np.real(signal))
   initial_drift = 0
   initial_a = (np.sum(np.real(signal)[max_idx:max_idx +
                              np.abs(half_max_idx)*2]) ) * 2

   initial = (initial_f0,
              initial_a,
              initial_hwhm,
              initial_ph,
              initial_off,
              initial_drift)

   params, _ = lsq.leastsqbound(mopt.err_func, initial,
                                args=(freqs, np.real(signal), ut.lorentzian),
                                bounds=bounds)
   return params
Ejemplo n.º 6
0
def fit_gaussian(spectra, f_ppm, lb=2.6, ub=3.6):
   """
   Fit a gaussian function to the difference spectra to be used for estimation
   of the GABA peak.
   
   Parameters
   ----------
   spectra : array of shape (n_transients, n_points)
      Typically the difference of the on/off spectra in each transient.

   f_ppm : array

   lb, ub: floats
      In ppm, the range over which optimization is bounded
   
   """
   idx = ut.make_idx(f_ppm, lb, ub)
   # We are only going to look at the interval between lb and ub
   n_points = idx.stop - idx.start
   n_params = 5
   fit_func = ut.gaussian
   # Set the bounds for the optimization
   bounds = [(lb,ub), # peak location
             (0,None), # sigma
             (0,None), # amp
             (None, None), # offset
             (None, None)  # drift
             ]

   model = np.empty((spectra.shape[0], n_points))
   signal = np.empty((spectra.shape[0], n_points))
   params = np.empty((spectra.shape[0], n_params))
   for ii, xx in enumerate(spectra):
      # We fit to the real spectrum:
      signal[ii] = np.real(xx[idx])
      # Use the signal for a rough estimate of the parameters for
      # initialization :
      max_idx = np.argmax(signal[ii])
      max_sig = np.max(signal[ii])
      initial_f0 = f_ppm[idx][max_idx]
      half_max_idx = np.argmin(np.abs(signal[ii] - max_sig/2))
      # We estimate sigma as the hwhm:
      initial_sigma = np.abs(initial_f0 - f_ppm[idx][half_max_idx])
      initial_off = np.min(signal[ii])
      initial_drift = 0
      initial_amp = max_sig
      
      initial = (initial_f0,
                 initial_sigma,
                 initial_amp,
                 initial_off,
                 initial_drift)
      
      params[ii], _ = lsq.leastsqbound(mopt.err_func,
                                       initial,
                                       args=(f_ppm[idx],
                                             np.real(signal[ii]),
                                             fit_func), bounds=bounds)

      model[ii] = fit_func(f_ppm[idx], *params[ii])
   
   return model, signal, params