import numpy as np
import matplotlib.pyplot as plt
import copy
import sys
import lepm.data_handling as dh
'''
'''
[docs]def periodicstrip(kx, bands, ax=None, colorgaps=False, gaps=None, gapthres=4, de=0.1, eps_exx=0.01, lw0=0.1, lw1=1.0,
upcolor="#55a254", downcolor="#c042c8", ingap_thres=0.1):
"""
Parameters
----------
kx
bands
colorgaps : bool
gaps : #gaps x 2 float array or None
gapthres : float or int
threshold number of curves in each bin to consider it a gap
lw0 : float
Line width for non-edge mode states
lw1 : float
Line width for edge mode states
upcolor : color specifier
downcolor : color specifier
Returns
-------
"""
# Instantiate axis if needed
if ax is None:
ax = plt.gca()
# Make sure we're using the right axis of 'bands'
if np.shape(bands)[1] != len(kx):
bands = bands.T
if colorgaps:
gaps = estimate_gaps_from_bands(bands, gapthres, de)
ind = 0
for band in bands:
ax.plot(kx, band, 'k-', lw=lw0)
# Color based on presence of gaps
if colorgaps and (frac_band_in_range(band, gaps) > ingap_thres).any():
# The above checks that a substantial part of the band is in the gap (more than ingap_thres)
for gap in gaps:
ingap = np.where(np.logical_and(band > gap[0], band < gap[1]))[0]
if len(ingap) > 2:
# For each contiguous range of indices, find where slope is up or down and color accordingly
segments = dh.consecutive(ingap, stepsize=1)
for segment in segments:
print 'segment = ', segment
# Find where slope is positive
kseg = kx[segment]
bseg = band[segment]
up = np.where(np.diff(bseg) > 0)[0]
down = np.where(np.diff(bseg) < 0)[0]
# Include endpoints that are missed by diff, except if they run out of range
up = np.setdiff1d(np.unique(np.hstack((up + 1, up))), np.array([-1, len(segment)]))
down = np.setdiff1d(np.unique(np.hstack((down + 1, down))), np.array([-1, len(segment)]))
upsegs = dh.consecutive(up, stepsize=1)
downsegs = dh.consecutive(down, stepsize=1)
# For each up or down portion, get contiguous segment
if len(upsegs[0]) > 0:
print 'upsegs = ', upsegs
for upseg in upsegs:
# Here we set a minimum length of the curve that must exist in the gap,
# not just a couple pts
if len(upseg) > 2:
ax.plot(kseg[upseg], bseg[upseg], color=upcolor, lw=lw1)
if len(downsegs[0]) > 0:
print 'downsegs = ', downsegs
for downseg in downsegs:
# Here we set a minimum length of the curve that must exist in the gap,
# not just a couple pts
if len(upseg) > 2:
ax.plot(kseg[downseg], bseg[downseg], color=downcolor, lw=lw1)
# User gradients to find line crossings
# grad = np.gradient(np.gradient(band))
# if (np.abs(grad) > eps_exx).any():
# # This is an edgemode since it intersects with another band (Normal eigvals repel, but here there is
# # a singularity at the crossing)
# # Plot the positive part as upcolor, other part as downcolor
# dips = np.where(grad < - eps_exx)[0]
# peaks = np.where(grad > eps_exx)[0]
# # make a list of all the singularities
# sings = np.hstack((dips, peaks))
# print 'dips = ', dips
# print 'peaks = ', peaks
#
# start = 0
# for sing in sings:
# # is the first singularity a dip or a peak
# if sing in dips:
# ax.plot(kx[start:sing + 1], band[start:sing + 1], color=downcolor, lw=lw1)
# elif sing in peaks:
# ax.plot(kx[start:sing + 1], band[start:sing + 1], color=upcolor, lw=lw1)
# start = sing
#
# if start in dips:
# ax.plot(kx[start:], band[start:], color=upcolor, lw=lw1)
# else:
# ax.plot(kx[start:], band[start:], color=downcolor, lw=lw1)
return ax
[docs]def band_in_range(band, gaps):
"""Check if a band lives in an energy range, such as a gap
Parameters
----------
band : N x 1 float array
A list of energies for different k's
gaps : #ranges x 2 float array
The ranges of energy values to look in
Returns
-------
ingap : bool
Whether the band is in each gap
"""
ingap = []
for gap in gaps:
if np.logical_and((band > gap[0]).any(), (band < gap[1]).any()):
ingap.append(True)
else:
ingap.append(False)
return np.array(ingap)
[docs]def frac_band_in_range(band, gaps):
"""Measure how much of a band is in each gap
Parameters
----------
band : N x 1 float array
A list of energies for different k's
gaps : #ranges x 2 float array
The ranges of energy values to look in
Returns
-------
ingap : float
how much of the band is in any gap
"""
ingap = []
for gap in gaps:
ingap.append(float(len(np.where(np.logical_and(band > gap[0], band < gap[1]))[0])) / float(len(gap)))
return np.array(ingap)
[docs]def estimate_gaps_from_bands(bands, gapthres, de):
"""
Returns
-------
"""
erange = np.arange(np.min(bands.ravel()), np.max(bands.ravel()), de)
# Get gaps where DOS falls below thres
ii = 0
density = np.array([len(np.unique(np.where(np.logical_and(bands > erange[ii], bands < erange[ii + 1]))[0]))
for ii in range(len(erange) - 1)])
# Check
# plt.plot(np.arange(len(density)), density, 'b.-')
# plt.show()
# Look for contiguous energy ranges
wheregap = np.where(density < gapthres)[0]
edgemarkers = np.where(np.abs(np.diff(wheregap)) > 1)[0]
print 'edgemarkers = ', edgemarkers
print 'erange[wheregap[edgemarkers]] = ', erange[wheregap[edgemarkers]]
inds = wheregap[edgemarkers].tolist() + (wheregap[edgemarkers + 1]).tolist()
inds.append(wheregap[0])
inds.append(wheregap[len(wheregap) - 1])
print 'inds = ', inds
inds = np.sort(np.array(inds).ravel())
print 'inds = ', inds
gaps = (erange[inds]).reshape(2, -1)
gaps[:, 1] += de
print 'gaps = ', gaps
return gaps
if __name__ == '__main__':
gap_finder = False
color_disp = True
if gap_finder:
NN = 1000
bands = np.random.rand(NN)
bands[bands > 0.5] += 0.2
bands[bands > 1.0] += 0.5
plt.hist(bands, bins=100)
gapthres = 2
de = 0.02
gaps = estimate_gaps_from_bands(bands, gapthres, de)
for gap in gaps:
plt.plot([gap[0], gap[0]], [0, np.sqrt(NN)], 'r--')
plt.plot([gap[1], gap[1]], [0, np.sqrt(NN)], 'g--')
print 'gaps = ', gaps
plt.show()
if color_disp:
import pickle
import glob
geom = 'kagome'
fnbase = '/Users/npmitchell/Dropbox/Soft_Matter/PAPER/gyro_disorder_paper/figure_drafts/' + \
'data_for_figs/kagome_fig/' + geom + '/'
print 'loading kspace chern from: ' + fnbase + '*strip_dispserion.pkl'
globfn = glob.glob(fnbase + '*strip_dispersion.pkl')
print 'globfn = ', globfn
with open(globfn[0], "rb") as fn:
dat_dict = pickle.load(fn)
# Unpack the dictionary
kx = dat_dict['kx']
bands = dat_dict['bands']
# Keep only the bands above omega = 0
bands = np.array(bands)
# bands_out = None
# for band in bands:
# if bands_out is None:
# bands_out = band
# else:
# bands_out = np.dstack()
# keep = []
# for band in bands:
# if (band > 0).all():
# keep.append(ii)
keep = np.unique(np.where((bands > 0))[1])
bands = bands[:, keep]
# Plot the dispersion
stripax = periodicstrip(kx, bands, ax=None, colorgaps=True, de=0.05)
plt.show()
sys.exit()