def calc_magevecs(eigvect): """Compute the magnitude of the second half of all eigenvectors, by norming their x and y components in quad NOTE: This is the same function as in gyro_lattice_functions.py, copied for imoprt convenience. Parameters ---------- eigvect : 2*N x 2*N complex array eigenvectors of the matrix, sorted by order of imaginary components of eigvals Eigvect is stored as NModes x NP*2 array, with x and y components alternating, like: x0, y0, x1, y1, ... xNP, yNP. Returns ------- magevecs : #particles x #particles float array The magnitude of the upper half of eigenvectors at each site. magevecs[i, j] is the magnitude of the i+NP normal mode at site j. """ from lepm.gyro_lattice_functions import calc_magevecs return calc_magevecs(eigvect)
def fit_eigvect_edge_boundaries(xy_inner, inner_boundary_inner, eigvect, PVxydict, eigval=None, locutoffd=None, hicutoffd=None, check=False, interp_n=None): """Fit the (edge) excitations of a gyro lattice to exponential decay, using Delta = lim_x->infty 1/x ln(psi(x)), computing x as the distance of each site to the edge of the network Parameters ---------- xy_inner : NP x 2 float array positions of particles in 2D inner_boundary_inner : tuple of two int arrays Each boundary of the periodic strip as an ordered int array that indexes mglat.xy_inner, not mglat.xy eigvect : NP x NP complex array eigenvectors of the system PVxydict : dict eigval : NP x 1 complex array, required only if check==True eigenvalues of the system locutoffd : float low-end cutoff distance for fitting exponential hicutoffd : float hi-end cutoff distance for fitting exponential check : bool show intermediate steps Returns ------- fits : NP x 6 float array (ie, int(len(eigval)*0.5) x 7 float array) fit details: A, K, uncertainty_A, covariance_AK, uncertainty_K, topbottom topbottom is an int indicator of whether the excitation is fit to a state localized to the top (0) or bottom (1) """ raise RuntimeError('Check that boundaries index xy_inner, not xy') if check: try: # consider only half of eigvals halfeval = eigval[int(len(eigval) * 0.5):] except IndexError: raise RuntimeError( "If kwarg 'check' is True, must supply eigval to fit_eigvect_to_exponential_edge()" ) # convert eigvect to magnitude of eigenvectors len_halfevec = len(eigvect[int(len(eigvect) * 0.5):]) # Take absolute value of excitations for magnitudes magevec = calc_magevecs(eigvect) # Get minimum distance for each particle, taking care to handle the interpolation of the boundary # Supplied 'boundary' must be a tuple, as the sample is periodic in one dimension # here boundary is a tuple of (usually two) boundaries, as if for periodic strip or openBC annulus dist_tup = le.distance_from_boundaries(xy_inner, inner_boundary_inner, PVxydict, interp_n=interp_n) # print 'dist_tup = ', dist_tup # Fit the eigvals given distances of each particle from edge fits = np.zeros((len_halfevec, 6), dtype=float) for ii in range(len_halfevec): if ii % 100 == 1: print 'glfns: eval #', str(ii), '/', len_halfevec # First try to fit to the top boundary jj = 0 for dist in dist_tup: # Use cutoff distances if provided inds = np.argsort(dist) if hicutoffd is not None and locutoffd is not None: inds = inds[np.logical_and(dist[inds] > locutoffd, dist[inds] < hicutoffd)] elif hicutoffd is not None: inds = inds[dist[inds] < hicutoffd] elif locutoffd is not None: inds = inds[dist[inds] > locutoffd] mags = magevec[ii][inds] dists = dist[inds] # Check if exponential is possible # kstest_exponential(magevec[ii], dist, bins=int(np.max(dist))) # possibly_exp = possibly_exponential(dists, mags) # if possibly_exp: # Fit to an exponential y=A*exp(K*t) using linear method. # METHOD 1 # bin_means, bin_edges, bin_number = scistat.binned_statistic(dists, mags, bins=int(cutoffd)) # A, K, cov = fit_exp_linear(binc, bin_means) A, K, cov = fit_exp_linear(dists, mags) if jj == 0: fits[ii, 0] = A fits[ii, 1] = K fits[ii, 2] = cov[0, 0] fits[ii, 3] = cov[0, 1] fits[ii, 4] = cov[1, 1] fits[ii, 5] = 0 else: # Check if fit is better than fitting to other boundary A, K, cov = fit_exp_linear(dists, mags) better_fit_negative = cov[1, 1] < fits[ii, 4] and K < 0. if better_fit_negative or K < fits[ii, 1]: # This fit is better than previous, so update fits array fits[ii, 0] = A fits[ii, 1] = K fits[ii, 2] = cov[0, 0] fits[ii, 3] = cov[0, 1] fits[ii, 4] = cov[1, 1] fits[ii, 5] = 1 # Check if fits better to a constant value, which is the case if exponential growth # print 'fits[ii, 4] = ', fits[ii, 4] # print 'variance = ', variance if fits[ii, 1] > 0: fits[ii, 0] = np.mean(mags) fits[ii, 1] = 0. fits[ii, 2] = np.var(mags) fits[ii, 3] = 0. fits[ii, 4] = 0. fits[ii, 5] = 2 # check the result if check: K = fits[ii, 1] A = fits[ii, 0] if abs(K) > 0.05: plt.clf() plt.semilogy(dists, mags, 'b.-') plt.semilogy(dists, A * np.exp(K * dists), 'r-') Astr = ' A = {0:0.5f}'.format( A) + r'$\pm$' + '{0:0.5f}'.format( np.sqrt(fits[ii, 2])) Kstr = ' K = {0:0.5f}'.format( K) + r'$\pm$' + '{0:0.5f}'.format( np.sqrt(fits[ii, 4])) plt.title(r'$\omega = $' + str(eigval[ii]) + Astr + Kstr) plt.pause(0.1) jj += 1 # Inspect localization parameter K (exponent in exp(K * r) if check: plt.plot(np.real(halfeval), fits[:, 1]) plt.show() return fits
def fit_eigvect_to_exponential_edge(xy_inner, inner_boundary_inner, eigvect, eigval=None, locutoffd=None, hicutoffd=None, check=False, interp_n=None): """Fit the (edge) excitations of a gyro lattice to exponential decay, using Delta = lim_x->infty 1/x ln(psi(x)), computing x as the distance of each site to the edge of the network Parameters ---------- xy_inner : NP x 2 float array positions of particles in 2D inner_boundary_inner : M x 1 int array the indices of xy_inner that mark the boundary sites eigvect : 2*NP x 2*NP complex array eigenvectors of the system eigval : 2*NP x 1 complex array eigenvalues of the system locutoffd : float low-end cutoff distance for fitting exponential hicutoffd : float hi-end cutoff distance for fitting exponential check : bool show intermediate steps interp_n : int The number of interpolation points along each boundary linesegment Returns ------- fits : NP x 5 float array (ie, int(len(eigval)*0.5) x 7 float array) fit details: A, K, uncertainty_A, covariance_AK, uncertainty_K """ # convert eigvect to magnitude of eigenvectors, consider only half of eigvals halflength = int(len(eigvect) * 0.5) if check: try: halfeval = eigval[halflength:] except IndexError: raise RuntimeError( "If kwarg 'check' is True, must supply eigval to fit_eigvect_to_exponential_edge()" ) halfevec = eigvect[halflength:] # Contract x and y component of each evect so that len(halfevec[ii]) = NP magevec = calc_magevecs(eigvect) # Get minimum distance for each particle, taking care to handle the interpolation of the boundary dist = le.distance_from_boundary(xy_inner, inner_boundary_inner, interp_n=interp_n) print 'mglfnslocz: np.shape(eigvect) = ', np.shape(eigvect) print 'mglfnslocz: np.shape(xy_inner) = ', np.shape(xy_inner) print 'mglfnslocz: np.shape(dist) = ', np.shape(dist) # Fit the eigvals given distances of each particle from edge fits = np.zeros((halflength, 5), dtype=float) for ii in range(halflength): if ii % 100 == 1: print 'glfns: eval #', str(ii), '/', halflength # Check it inds = np.argsort(dist) if hicutoffd is not None: inds = inds[dist[inds] < hicutoffd] if locutoffd is not None: inds = inds[dist[inds] > locutoffd] print 'mglatfnslocz: np.shape(magevec) = ', np.shape(magevec) print 'mglatfnslocz: np.shape(magevec[ii]) = ', np.shape(magevec[ii]) print 'mglatfnslocz: np.shape(inds) = ', np.shape(inds) mags = magevec[ii][inds] dists = dist[inds] # Check if exponential is possible # kstest_exponential(magevec[ii], dist, bins=int(np.max(dist))) # possibly_exp = possibly_exponential(dists, mags) # if possibly_exp: # Fit to an exponential y=A*exp(K*t) using linear method. # METHOD 1 # bin_means, bin_edges, bin_number = scistat.binned_statistic(dists, mags, bins=int(cutoffd)) # A, K, cov = fit_exp_linear(binc, bin_means) A, K, cov = fit_exp_linear(dists, mags) fits[ii, 0] = A fits[ii, 1] = K fits[ii, 2] = cov[0, 0] fits[ii, 3] = cov[0, 1] fits[ii, 4] = cov[1, 1] # check the result if check: if np.abs(K) > 0.1: plt.clf() plt.plot(dists, mags, 'b.-') plt.plot(dists, A * np.exp(K * dists), 'r-') Astr = ' A = {0:0.5f}'.format( A) + r'$\pm$' + '{0:0.5f}'.format(np.sqrt(fits[ii, 2])) Kstr = ' K = {0:0.5f}'.format( K) + r'$\pm$' + '{0:0.5f}'.format(np.sqrt(fits[ii, 4])) plt.title(r'$\omega = $' + str(halfeval[ii]) + Astr + Kstr) plt.pause(0.1) # Inspect localization parameter K (exponent in exp(K * r) if check: plt.plot(np.imag(halfeval), fits[:, 1]) plt.show() return fits
def fit_eigvect_to_exponential_1dperiodic(xy_inner, eigval, eigvect, LL, locutoffd=None, hicutoffd=None, check=False): """Fit the excitations of a gyro lattice to exponential decay, using Delta = lim_x->infty 1/x ln(psi(x)) Parameters ---------- xy : NP x 2 float array positions of particles in 2D eigval : 2*NP x 1 complex array eigenvalues of the system eigvect : 2*NP x 2*NP complex array eigenvectors of the system LL : float width of the periodic system in 2d locutoffd : float low-end cutoff distance for fitting exponential hicutoffd : float hi-end cutoff distance for fitting exponential check : bool show intermediate steps Returns ------- fits : NP x 7 float array (ie, int(len(eigval)*0.5) x 7 float array) fit details: x_center, y_center, A, K, uncertainty_A, covariance_AK, uncertainty_K """ # convert eigvect to magnitude of eigenvectors, consider only half of eigvals halfeval = eigval[int(len(eigval) * 0.5):] halfevec = eigvect[int(len(eigval) * 0.5):] # Contract x and y component of each evect so that len(halfevec[ii]) = NP magevec = calc_magevecs(eigvect) # find COM for each eigvect fits = np.zeros((len(halfeval), 7), dtype=float) for ii in range(len(halfeval)): if ii % 100 == 1: print 'glfns: eval #', str(ii), '/', len(halfeval) # le.plot_real_matrix(magevec, show=True) # print 'ii = ', ii # print 'np.shape(magevec[ii]) = ', np.shape(magevec[ii]) # print 'np.min(magevec[ii]) = ', np.min(magevec[ii]) # print 'np.max(magevec[ii]) = ', np.max(magevec[ii]) com = le.com_periodicstrip(xy_inner, LL, masses=magevec[ii]) fits[ii, 0:2] = com # print 'com =', com # Get minimum distance for each particle, taking care to get minimum across periodic BCs dist = le.distancex_periodicstrip(xy_inner, com, LL) # Check it inds = np.argsort(dist) if hicutoffd is not None: inds = inds[dist[inds] < hicutoffd] if locutoffd is not None: inds = inds[dist[inds] > locutoffd] mags = magevec[ii][inds] dists = dist[inds] # Check if exponential is possible # kstest_exponential(magevec[ii], dist, bins=int(np.max(dist))) # possibly_exp = possibly_exponential(dists, mags) # if possibly_exp: # Fit to an exponential y=A*exp(K*t) using linear method. # METHOD 1 # bin_means, bin_edges, bin_number = scistat.binned_statistic(dists, mags, bins=int(cutoffd)) # A, K, cov = fit_exp_linear(binc, bin_means) A, K, cov = fit_exp_linear(dists, mags) fits[ii, 2] = A fits[ii, 3] = K fits[ii, 4] = cov[0, 0] fits[ii, 5] = cov[0, 1] fits[ii, 6] = cov[1, 1] # check the result if check: if np.abs(K) > 0.1: plt.clf() plt.plot(dists, mags, 'b.-') plt.plot(dists, A * np.exp(K * dists), 'r-') Astr = ' A = {0:0.5f}'.format( A) + r'$\pm$' + '{0:0.5f}'.format(np.sqrt(fits[ii, 4])) Kstr = ' K = {0:0.5f}'.format( K) + r'$\pm$' + '{0:0.5f}'.format(np.sqrt(fits[ii, 6])) plt.title(r'$\omega = $' + str(halfeval[ii]) + Astr + Kstr) plt.show() # check that including all in magevec makes no difference com = le.com_periodicstrip(xy, LL, magevec[ii], check=True) com = le.com_periodicstrip(xy_inner, LL, magevec[ii], check=True) # if np.imag(halfeval[ii]) > 3.7: # # plt.show() # pass # else: # plt.pause(0.0001) # pass # Inspect localization parameter K (exponent in exp(K * r) if check: plt.plot(np.imag(halfeval), fits[:, 3]) plt.show() return fits
def bottommiddletop_excitation(xy, eigvect, below=None, above=None, top=None, bottom=None, check=False, checkdir=None): """Determine if excitation is weighted toward top, middle or bottom: which chunk has the most excitation: 0-bottom, 0.5-middle, 1.0-top Returns ------- tmb : (#eigval*0.5) x 1 float array 0 for bottom, 0.5 for middle, 1.0 for top """ if above is None: if top is None: top = np.max(xy[:, 1]) if bottom is None: bottom = np.min(xy[:, 1]) above = (top - bottom) * 2. / 3. + bottom if below is None: if top is None: top = np.max(xy[:, 1]) if bottom is None: bottom = np.min(xy[:, 1]) below = (top - bottom) / 3. + bottom magevec = calc_magevecs(eigvect) # etop is the energy in the top third of the system, similar for ebot and emid # Note that each of etop ebot and emid should have lengths of #particles etop = np.sum(magevec[:, xy[:, 1] > above], axis=1) ebot = np.sum(magevec[:, xy[:, 1] < below], axis=1) emid = np.sum(magevec[:, np.logical_and(xy[:, 1] > below, xy[:, 1] < above)], axis=1) # Prepare ebot, emid, etop, indicator (0, 0.5, 1) as columns tmb = np.dstack((ebot, emid, etop, 0.5 * np.ones_like(xy[:, 0])))[0] tops = np.logical_and(etop > emid, etop > ebot) bots = np.logical_and(ebot > emid, ebot > etop) print 'bots = ', bots tmb[tops, 3] = 1.0 tmb[bots, 3] = 0.0 if check: # plot excitation magnitude, excitation, and result import lepm.plotting.plotting as leplt import lepm.dataio as dio fig, ax, cax = leplt.initialize_2panel_1cbar_centy() for (mag, kk) in zip(magevec, np.arange(len(xy[:, 0]))): ax[0].plot(xy[:, 1], mag, 'b.') ylims = ax[0].get_ylim() ax[0].plot([below, below], ylims, 'k--') ax[0].plot([above, above], ylims, 'k--') ax[0].set_title('tmb = {0:0.1f}'.format(tmb[kk])) ax[1].scatter(xy[:, 0], xy[:, 1], s=mag * 250) ax[1].set_ylim(np.min(xy[:, 1]), np.max(xy[:, 1])) ax[1].set_xlim(np.min(xy[:, 0]), np.max(xy[:, 0])) if checkdir is not None: plt.savefig( dio.prepdir(checkdir) + 'magevec_{0:06d}'.format(kk) + '.png') else: plt.pause(1) ax[0].cla() ax[1].cla() return tmb