def _make_splines(self, xs, ys): """ Make the splines """ base = splrep(xs, ys, s=0) tcks = { -1: splantider(base, 1), 0: base, 1: splder(base, 1), 2: splder(base, 2), 3: splder(base, 3) } return tcks
def __init__(self, distribution_1, distribution_2=None, n_steps=1000, include_rate=0.5): self.distribution_1 = distribution_1 self.distribution_2 = distribution_2 if distribution_2 is None: self.interval = [distribution_1.min(), distribution_1.max()] else: self.interval = [ min([distribution_1.min(), distribution_2.min()]), max([distribution_1.max(), distribution_2.max()]) ] self.n_steps = n_steps self.include_rate = include_rate self.fraction = np.linspace(self.interval[0], self.interval[-1], n_steps) self.step = self.fraction[1] - self.fraction[0] self.cdf_1 = build_cdf(self.distribution_1) self.cdf_spline_1 = spline_by_distribution(self.cdf_1, self.interval) self.spline_1 = splder(self.cdf_spline_1, 1) self.density_fraction_1 = cdf_fraction(self.spline_1, self.fraction) self.area_1 = full_area(self.density_fraction_1, self.step, None, self.include_rate) # self.scaled_cdf_1 = self.cdf_1 # self.scaled_cdf_1['COUNT'] = self.scaled_cdf_1['COUNT'] / self.area_1 self.scaled_density_fraction_1 = self.density_fraction_1 / self.area_1 if distribution_2 is None: self.cdf_2 = None self.spline_2 = None self.density_fraction_2 = None self.area_2 = None # self.scaled_cdf_2 = None self.scaled_density_fraction_2 = None else: self.cdf_2 = build_cdf(self.distribution_2) self.cdf_spline_2 = spline_by_distribution(self.cdf_2, self.interval) self.spline_2 = splder(self.cdf_spline_2, 1) self.density_fraction_2 = cdf_fraction(self.spline_2, self.fraction) self.area_2 = full_area(self.density_fraction_2, self.step, None, self.include_rate) # self.scaled_cdf_2 = self.cdf_2 # self.scaled_cdf_2['COUNT'] = self.scaled_cdf_2['COUNT'] / self.area_2 self.scaled_density_fraction_2 = self.density_fraction_2 / self.area_2
def plot_free_energy_curves(e_poly, chi_spline, E_samples, q_samples, Ps): fg = plt.figure() ax = fg.add_subplot(111) for e in E_samples: F = free_energy(q_samples, chi_spline, e_poly, e, Ps, False) ax.plot(q_samples, F, '.-', label=r'$E=${0:6.2e}'.format(e)) ax.legend() ax.set_xlabel(r'$Q$') ax.set_ylabel(r'$F(Q;E)(E_\mathrm{H}/a_0^3)$') global now timestamp = now.strftime('%Y%m%d_%H%M%S') pathlib.Path(os.path.join('output', 'free_energy_curves')).mkdir(parents=True, exist_ok=True) fg.savefig( os.path.join('output', 'free_energy_curves', 'free_energy_curves_' + timestamp)) fg = plt.figure() ax = fg.add_subplot(111) chi_prime = splder(chi_spline) for e in E_samples: dF = free_energy_derivative(q_samples, chi_prime, np.polyder(e_poly), e, Ps, False) ax.plot(q_samples, dF, '.-', label=r'$E=${0:6.2e}'.format(e)) ax.legend() ax.set_xlabel(r'$Q$') ax.set_ylabel( r'$\frac{\mathrm{d}F}{\mathrm{d}Q}(Q;E)(E_\mathrm{H}/a_0^3)$') timestamp = now.strftime('%Y%m%d_%H%M%S') pathlib.Path(os.path.join('output', 'dFdQ_curves')).mkdir(parents=True, exist_ok=True) fg.savefig( os.path.join('output', 'dFdQ_curves', 'dFdQ_curves_' + timestamp))
def derivative(self, n=1): """Returns derivative as a spline Arguments: n (int): order of the derivative Returns: Spline: the derivative of the spline with degree - n """ tck = splder(self.tck(), n) return Spline(tck=tck, points=self.points)
def derivative(self, n = 1): """Returns derivative as a spline Arguments: n (int): order of the derivative Returns: Spline: the derivative of the spline with degree - n """ tck = splder(self.tck(), n); return Spline(tck = tck, points = self.points);
def test_splder(self): for b in [self.b, self.b2]: # pad the c array (FITPACK convention) ct = len(b.t) - len(b.c) if ct > 0: b.c = np.r_[b.c, np.zeros((ct,) + b.c.shape[1:])] for n in [1, 2, 3]: bd = splder(b) tck_d = _impl.splder((b.t, b.c, b.k)) assert_allclose(bd.t, tck_d[0], atol=1e-15) assert_allclose(bd.c, tck_d[1], atol=1e-15) assert_equal(bd.k, tck_d[2]) assert_(isinstance(bd, BSpline)) assert_(isinstance(tck_d, tuple)) # back-compat: tck in and out
def correct_tuple_for_nonlin(tuple, nonlin_corr=None, verbose=False, draw=False): """ Compute the non-linearity correction using the 'c1' field, and applies it. Return value: corrected tuple """ t00 = tuple[(tuple['i'] == 0) & (tuple['j'] == 0)] if nonlin_corr == None: if draw: nonlin_corr = eval_nonlin_draw(t00, verbose=verbose) else: nonlin_corr = eval_nonlin(t00, verbose=verbose) amps = np.unique(t00['ext']).astype(int) # sort the tuple by amp, i.e. extension index = tuple['ext'].argsort() stuple = tuple[index] tuple = stuple # release memory ? not sure # find out where each amp starts and ends in the tuple ext = stuple['ext'] diff = ext[1:] - ext[:-1] boundaries = [0] + [i + 1 for i in range(len(diff)) if diff[i] != 0 ] + [len(ext)] amps = np.unique(ext).astype(int) start = [None] * int(amps.max() + 1) end = [None] * int(amps.max() + 1) for k in range(len(boundaries) - 1): b = boundaries[k] amp = int(ext[b]) start[amp] = b end[amp] = boundaries[k + 1] # print amp,start[amp], end[amp], ext[start[amp]],ext[end[amp]-1] # now applyr the nonlinearity correction for amp in amps: tamp = stuple[stuple['ext'] == amp] x = 0.5 * (tamp['mu1'] + tamp['mu2']) iamp = int(amp) s = nonlin_corr[iamp] mu_corr = interp.splev(x, s) # model values dd = interp.splder(s) # model derivative der = interp.splev(x, dd) # model derivative values stuple['mu1'][start[iamp]:end[iamp]] = mu_corr stuple['mu2'][start[iamp]:end[iamp]] = mu_corr stuple['var'][start[iamp]:end[iamp]] *= (der**2) stuple['cov'][start[iamp]:end[iamp]] *= (der**2) return stuple
def corr_spline_interpolation(y1,y2, window_size): y1 = np.array([y1]) y2 = np.array([y2]) corr, delay = corr_no_interpolation(y1,y2, window_size) if window_size%2!=0: window_interp = np.arange(delay-(window_size-1)/2,delay+(window_size-1)/2) else: window_interp = np.arange(delay-(window_size)/2,delay+(window_size)/2-1) tck = interpolate.splrep(window_interp, corr[window_interp], s=0, k=4) dspl = interpolate.splder(tck) delay_spl = interpolate.sproot(dspl, mest = 20) if len(delay_spl) > 1: delay = delay_spl[np.argmax(interpolate.splev(delay_spl, tck, der=0))] else: delay = delay_spl[0] return corr, delay-len(y1[0,:])+1
def corr_spline_interpolation(y1, y2, window_size): y1 = np.array([y1]) y2 = np.array([y2]) corr, delay = corr_no_interpolation(y1, y2, window_size) if window_size % 2 != 0: window_interp = np.arange(delay - (window_size - 1) / 2, delay + (window_size - 1) / 2) else: window_interp = np.arange(delay - (window_size) / 2, delay + (window_size) / 2 - 1) tck = interpolate.splrep(window_interp, corr[window_interp], s=0, k=4) dspl = interpolate.splder(tck) delay_spl = interpolate.sproot(dspl, mest=20) if len(delay_spl) > 1: delay = delay_spl[np.argmax(interpolate.splev(delay_spl, tck, der=0))] else: delay = delay_spl[0] return corr, delay - len(y1[0, :]) + 1
def make_nonlin_plot(filename, knots=20, channel=8): nt = croaks.NTuple.fromfile(filename) cut = (nt['mu1'] < 1.3e5) & (nt['sp1'] < 3.5) & (nt['sp2'] < 3.5) t8 = nt[cut & (nt['ext'] == channel)] dict = {} if knots is not None: dict['knots'] = knots s, x, yclap = fit_nonlin_corr(t8['mu1'], t8['c1'], fullOutput=True, **dict) model = interp.splev(x, s) fig = pl.figure(figsize=(8, 14)) axes = fig.add_subplot(2, 1, 1) pl.plot(x, x / yclap - 1, '.', label='data') pl.plot(x, x / model - 1, '-r', label='model') pl.ticklabel_format(style='sci', axis='x', scilimits=(0, 0)) my_fontsize = 'xx-large' pl.xlabel("$\mu$(ADU)", fontsize=my_fontsize) pl.xticks(fontsize=my_fontsize) pl.yticks(fontsize=my_fontsize) pl.ylabel("$\mu$/diode-1", fontsize=my_fontsize) pl.legend(loc='upper right', fontsize=my_fontsize) fig.add_subplot(2, 1, 2) mu = t8['mu1'] mu_cor = interp.splev(mu, s) dd = interp.splder(s) der = interp.splev(mu, dd) var = 0.5 * t8['var'] var_cor = var * (der**2) pl.plot(mu, var / mu, 'b.', label='before correction') pl.plot(mu_cor, var_cor / mu_cor, 'r.', label='after correction') pl.ticklabel_format(style='sci', axis='x', scilimits=(0, 0)) pl.xlabel("$\mu$ (ADU)", fontsize=my_fontsize) pl.ylabel("$C_{00}/\mu$", fontsize=my_fontsize) pl.xticks(fontsize=my_fontsize) pl.yticks(fontsize=my_fontsize) pl.legend(loc='upper right', fontsize=my_fontsize) pl.tight_layout() fig.show() pl.savefig("nonlin_plot.pdf")
def fit_nonlin_corr(xin, yclapin, knots=20, loop=20, verbose=False, fullOutput=False): """ xin : the data to be "linearized" yclapin : the (hopefully) linear reference returns a spline that can be used for correction uisng "scikit.splev" if full_output==True, returns spline,x,y (presumably to plot) """ # do we need outlier rejection ? # the xin has to be sorted, although the doc does not say it.... index = xin.argsort() x = xin[index] yclap = yclapin[index] chi2_mask = np.isfinite(yclap) # yclap = nan kills the whole thing xx = x yyclap = yclap for i in range(loop): xx = xx[chi2_mask] # first fit the scaled difference between the two channels we are comparing yyclap = yyclap[chi2_mask] length = xx[-1] - xx[0] t = np.linspace(xx[0] + 1e-5 * length, xx[-1] - 1e-5 * length, knots) s = interp.splrep(xx, yyclap, task=-1, t=t) model = interp.splev(xx, s) # model values res = model - yyclap sig = mad(res) res = np.abs(res) if (res > (5 * sig)).sum() > 0: # remove one at a time chi2_mask = np.ones(len(xx)).astype(bool) chi2_mask[np.argmax(res)] = False continue else: break # enforce the fit to got through (0,0) and make sure that 0 is inside # the definition domain of the spline. # print('means yy ',yyclap.mean(),' xx ', xx.mean()) # print ('ymod[0]/xmod[0] ', interp.splev(xx[0],s)/xx[0],xx[0]) old_der = yyclap.mean() / xx.mean() nx = len(xx) fact = 1 nadd = nx / 2 fit_val = interp.splev(xx[0], s) fake_x = np.linspace(-xx[0] * fact, xx[0] * fact, nadd) fake_y = np.linspace(-fit_val * fact, fit_val * fact, nadd) xx = np.hstack((fake_x, xx)) yyclap = np.hstack((fake_y, yyclap)) t = np.linspace(xx[0] + 1e-5 * length, xx[-1] - 1e-5 * length, knots) s = interp.splrep(xx, yyclap, task=-1, t=t[1:-2]) # normalize to "no change" at x->0 der0 = interp.splev(0., s, 1) norm_fact = 1. / der0 # print("n before/after %d/%d"%(nx,len(xx))) norm_fact = yyclap.mean() / xx.mean() # print('comparison old_fact ', old_der, ' new_fact ',norm_fact) yyclap_norm = yyclap / norm_fact # model only the residual to the identity s = interp.splrep(xx, yyclap_norm - xx, task=-1, t=t) model = interp.splev(xx, s) + xx # model values # compute gain residuals mask = (yyclap_norm != 0) print( "der0 = %f, val0 = %f" % (1 + interp.splev(0., interp.splder(s)), interp.splev(0., s)), "nonlin gain residuals : %g" % (model[mask] / yyclap_norm[mask] - 1).std()) if verbose: print("fit_nonlin loops=%d sig=%f res.max = %f" % (i, sig, res.max())) if fullOutput: return s, xx, yyclap_norm return s
def get_pol_vs_e(e_poly, chi_spline, E_samples, Ps, debug, method='TNC', close_prev_figs=True): """ Calculates equilibrium polarization value for various electric field values. Parameters ========== q_energy: array(float) Collective coordinate values corresponding to data in energy variable. Values must be between 0 and 1. energy: array(float) In hartrees. Bulk energy per unit cell for atomic configurations corresponding to q_energy entries. celldims: array(float) In bohr. Dimensions of unit cell. q_chi: array(float) Collective coordinate values corresponding to data in chi variable. Values must be between 0 and 1. chi: array(float) In esu. Electronic contribution to dielectric susceptibility for configurations along path between ferroelectric configurations. E_samples: array(float) In kV/cm. Values of electric field at which equilibrium polarisation value should be calculated. Ps: float In uC/cm^2. Spontaneous polarisation of ferroelectric. method: string Free energy minimization method. See scipy.optimize.minimize documentation. close_prev_figs: boolean If True, previous Matplotlib figures will be closed Returns ======= ret: array(float) The equilibrium polarizations corresponding to values in E_samples. """ global c global barye_on_au global kVpercm_on_statVpercm global uCpercm2_on_statCpercm2 global kilopascal_on_au global now if close_prev_figs: plt.close('all') def wrapped_free_energy(q): return free_energy(q, chi_spline, e_poly, E, Ps, print_fmin_params) def wrapped_free_energy_derivative(q): return free_energy_derivative(q, chi_spline, e_polyder, E, print_fmin_params) q_range = np.linspace(-1.5, 1.5, 100) chi_prime = splder(chi_spline) p_vs_E = [] supercoercive_flags = np.full(E_samples.shape, False) for i, e in enumerate(E_samples): # Find Q where dF/dQ = 0. left_dF = free_energy_derivative(q_range[:-1], chi_prime, np.polyder(e_poly), e, Ps, False) right_df = free_energy_derivative(q_range[1:], chi_prime, np.polyder(e_poly), e, Ps, False) signs = (left_dF * right_df <= 0.) q_idx = np.nonzero(signs)[0] p = q_range[q_idx] * Ps print_string = "E:{0} p:{1}".format(e, str(p)) supercoercive_flags[i] = (len(p) == 1) to_add = np.zeros((len(p), 2)) to_add[:, 0] = p to_add[:, 1] = e p_vs_E += [to_add] all_pol_vs_E = np.concatenate(p_vs_E, axis=0) supercoercive_fields = E_samples[supercoercive_flags] if len(supercoercive_fields) > 2 and (np.any(supercoercive_fields > 0.) and np.any(supercoercive_fields < 0.)): positive_Ec = np.min(supercoercive_fields[supercoercive_fields > 0.]) negative_Ec = np.max(supercoercive_fields[supercoercive_fields < 0.]) print("+Ec={0:.3e}, -Ec={1:.3e}".format(positive_Ec, negative_Ec)) ret = (all_pol_vs_E, positive_Ec, negative_Ec) else: print("Could not calculate coercive field. Consider increasing Emax.") ret = (np.concatenate(p_vs_E, axis=0), None, None) return ret
def drift_fit2D(ev, data, validRange=9): ''' Measures the spectrum drift over all frames and all non-destructive reads. Parameters ---------- ev : Event object data : 4D data frames preclip : Ignore first preclip values of spectrum postclip : Ignore last postclip values of spectrum width : Half-width in pixels used when fitting Gaussian deg : Degree of polynomial fit validRange : Trim spectra by +/- pixels to compute valid region of cross correlation Returns ------- drift : Array of measured drift values model : Array of model drift values History ------- Written by Kevin Stevenson January 2017 ''' #if postclip != None: # postclip = -postclip if ev.n_reads > 2: istart = 1 else: istart = 0 drift = np.zeros((ev.n_files, ev.n_reads-1)) #model = np.zeros((ev.n_files, ev.n_reads-1)) #goodmask = np.zeros((ev.n_files, ev.n_reads-1),dtype=int) for n in range(istart,ev.n_reads-1): ref_data = np.copy(data[-1,n]) ref_data[np.where(np.isnan(ref_data) == True)] = 0 for m in range(ev.n_files): #Trim data to achieve accurate cross correlation without assumptions over interesting region #http://stackoverflow.com/questions/15989384/cross-correlation-of-non-periodic-function-with-numpy fit_data = np.copy(data[m,n,:,validRange:-validRange]) fit_data[np.where(np.isnan(fit_data) == True)] = 0 # Cross correlate, result should be 1D vals = sps.correlate2d(ref_data, fit_data, mode='valid').squeeze() xx_t = range(len(vals)) # Find the B-spline representation spline = spi.splrep(xx_t, vals, k=4) # Compute the spline representation of the derivative deriv = spi.splder(spline) # Find the maximum with a derivative. maximum = spi.sproot(deriv) # Multiple derivatives, take one closest to argmax(vals) if len(maximum) > 1: #print(m,n,maximum,np.argmax(vals)) maximum = maximum[np.argmin(np.abs(maximum-np.argmax(vals)))] drift[m,n] = len(vals)/2 - maximum ''' try: vals = np.correlate(ref_spec, fit_spec, mode='valid') argmax = np.argmax(vals) subvals = vals[argmax-width:argmax+width+1] params, err = g.fitgaussian(subvals/subvals.max(), guess=[width/5., width*1., 1]) drift[n,m,i]= len(vals)/2 - params[1] - argmax + width goodmask[n,m,i] = 1 except: print('Spectrum ' +str(n)+','+str(m)+','+str(i)+' marked as bad.') ''' return drift#, goodmask