def plot_ill_dos(hlat,
                 dos_ax=None,
                 cbar_ax=None,
                 alpha=1.0,
                 vmin=None,
                 vmax=None,
                 **kwargs):
    """
    Parameters
    ----------
    dos_ax : axis instance
        Axis on which to plot the Localization-colored DOS
    cbar_ax : axis instance or None
        axis to use for colorbar
    alpha : float
        opacity of the DOS added to the plot
    vmin : float
        minimum value for inverse localization length in colormap
    vmax : float
        maximum value for inverse localization length in colormap
    **kwargs: lepm.plotting.plotting.colored_DOS_plot() keyword arguments
        Excluding fontsize
    """
    # Register cmaps if necessary
    if 'viridis' not in plt.colormaps():
        lecmaps.register_colormaps()

    eigval = hlat.get_eigval(attribute=False)

    # Load or compute localization
    localization = hlat.get_localization(attribute=False)
    ill = localization[:, 2]
    # print 'gcollpfns: localization = ', localization
    # print 'gcollpfns: shape(localization) = ', np.shape(localization)

    # Now overlay the ipr
    if vmin is None:
        print 'setting vmin...'
        vmin = 0.0
    if dos_ax is None:
        print 'dos_ax is None, initializing...'
        fig, dos_ax, cax, cbar = leplt.initialize_colored_DOS_plot(
            eigval,
            'haldane',
            alpha=alpha,
            colorV=ill,
            colormap='viridis',
            linewidth=0,
            cax_label=r'$\lambda^{-1}$',
            vmin=vmin,
            vmax=vmax,
            **kwargs)
    else:
        print 'gcollpfns: calling leplt.colored_DOS_plot...'
        dos_ax, cbar_ax, cbar, n, bins = \
            leplt.colored_DOS_plot(eigval, dos_ax, 'haldane', alpha=alpha, colorV=ill,
                                   cbar_ax=cbar_ax, colormap='viridis', linewidth=0,
                                   vmin=vmin, vmax=vmax, **kwargs)

    return dos_ax, cbar_ax
Ejemplo n.º 2
0
            deltas = np.array(deltas)
            abds = np.array(abds)
            cherns = np.array(cherns)
            if len(abdgrid) == 0:
                deltagrid = deltas
                abdgrid = abds
                cherngrid = cherns
            else:
                deltagrid = np.vstack((deltagrid, deltas))
                abdgrid = np.vstack((abdgrid, abds))
                cherngrid = np.vstack((cherngrid, cherns))

        plt.close('all')
        fig, ax, cax = leplt.initialize_1panel_cbar_cent()
        lecmaps.register_colormaps()
        cmap = 'bbr0'
        # deltagrid.reshape((len(abds), -1))
        # abdgrid.reshape((len(abds), -1))
        # cherngrid.reshape((len(abds), -1))
        # leplt.plot_pcolormesh_scalar(deltagrid, abdgrid, cherngrid, outpath=None, cmap=cmap, vmin=-1.0, vmax=1.0)
        leplt.plot_pcolormesh(deltagrid / np.pi, abdgrid, cherngrid, 100, ax=ax,
                              make_cbar=False, cmap=cmap, vmin=-1.0, vmax=1.0)
        # ax.scatter(deltagrid, abdgrid, c=cherngrid, cmap=cmap, vmin=-1.0, vmax=1.0)
        sm = leplt.empty_scalar_mappable(vmin=-1.0, vmax=1.0, cmap=cmap)
        cb = plt.colorbar(sm, cax=cax, orientation='horizontal')
        cb.set_label(label=r'Chern number, $\nu$', labelpad=-35)
        cb.set_ticks([-1, 0, 1])
        ax.set_xlabel(r'Lattice deformation angle, $\delta/\pi$')
        ax.set_ylabel(r'Inversion symmetry breaking, $\Delta$')
        specstr = '_aol' + sf.float2pstr(lp['aoverl']) + '_Omk' + sf.float2pstr(lp['Omk'])
def plot_projector_singlept_network(hlat,
                                    evxyproj,
                                    fig=None,
                                    ax=None,
                                    cax=None,
                                    cmap='viridis',
                                    save=True,
                                    sz=15,
                                    axis_off=False,
                                    fontsize=10,
                                    **kwargs):
    """Plot a network with each site colored by the magnitude of its projector value relative to a point closest to
    proj_XY.

    Parameters
    ----------
    hlat : HaldaneLattice instance
    evxyproj : 2 x 2*NP complex array
        projector components corresponding to the particle of interest. First row corresponds to x component,
        second to y component
    fig : matplotlib.pyplot figure instance
    ax : axis instance
    cax : colorbar axis instance
    cmap : string specifier for colormap to use
    **kwargs : keyword arguments for leplt.initialize_1panel_cbar_cent()
        Wfig=90, Hfig=None, wsfrac=0.4, hsfrac=None, cbar_pos='above',
                                wcbarfrac=0.06, hcbarfrac=0.05, cbar_label='',
                                vspace=8, hspace=5, tspace=10, fontsize=8

    Returns
    -------

    """
    # make magproj, which has dims 1 x NP
    tmp = np.sqrt(
        np.abs(evxyproj[0]).ravel()**2 + np.abs(evxyproj[1]).ravel()**2)
    magproj = np.array([
        np.sqrt(tmp[2 * ind].ravel()**2 + tmp[2 * ind + 1].ravel()**2)
        for ind in range(int(0.5 * len(tmp)))
    ]).ravel()

    if ax is None:
        fig, ax, cbar_ax_tmp = leplt.initialize_1panel_cbar_cent(**kwargs)
    if cax is None:
        cbar_ax = cbar_ax_tmp
    else:
        cbar_ax = cax

    hlat.lattice.plot_BW_lat(fig=None,
                             ax=ax,
                             save=False,
                             close=False,
                             axis_off=axis_off,
                             title='')
    if cmap not in plt.colormaps():
        lecmaps.register_colormaps()
    colormap = plt.get_cmap(cmap)
    colors = colormap(magproj / np.max(magproj))
    # print 'colors = ', colors
    ax.scatter(hlat.lattice.xy[:, 0],
               hlat.lattice.xy[:, 1],
               s=sz,
               c=colors,
               edgecolors='none',
               zorder=200)
    # create scalar mappable
    norm = matplotlib.colors.Normalize(vmin=0, vmax=1)
    sm = matplotlib.cm.ScalarMappable(cmap=colormap, norm=norm)
    sm._A = []
    cbar = plt.colorbar(sm, cax=cbar_ax, orientation='horizontal')
    cbar.set_ticks([0., 0.5, 1.0])
    cbar_ax.set_title(r'$P_{i0}/P_{00}$', fontsize=fontsize)

    return fig, ax, cbar_ax
def plot_ill_dos_overlay(gcoll,
                         dos_ax=None,
                         cbar_ax=None,
                         alpha=None,
                         vmin=None,
                         vmax=None,
                         **kwargs):
    """
    Parameters
    ----------
    dos_ax : axis instance
        Axis on which to plot the Localization-colored DOS
    **kwargs: lepm.plotting.plotting.colored_DOS_plot() keyword arguments
        Excluding fontsize
    """
    gcoll.ensure_all_eigval()

    # Decide what alpha value to use if not provided (here, 1/N)
    if alpha is None:
        alpha = 1. / float(len(gcoll.gyro_lattices))

    # Register cmaps if necessary
    if 'viridis' not in plt.colormaps():
        cmaps.register_colormaps()

    # Plot the overlays
    for ii in range(len(gcoll.gyro_lattices)):
        if ii % 10 == 0:
            print 'Overlaying ', ii, ' of ', len(gcoll.gyro_lattices)

        eigval = gcoll.gyro_lattices[ii].eigval

        # Load or compute localization
        localization = gcoll.gyro_lattices[ii].get_localization(
            attribute=False)
        ill = np.zeros(len(eigval), dtype=float)
        ill[0:int(len(eigval) * 0.5)] = localization[:, 2][::-1]
        ill[int(len(eigval) * 0.5):len(eigval)] = localization[:, 2]
        print 'ill = ', ill
        # print 'gcollpfns: localization = ', localization
        # print 'gcollpfns: shape(localization) = ', np.shape(localization)

        # Now overlay the ipr
        if vmin is None:
            print 'setting vmin...'
            vmin = 0.0
        if ii == 0 and dos_ax is None:
            print 'dos_ax is None, initializing...'
            fig, dos_ax, cax, cbar = leplt.initialize_colored_DOS_plot(
                eigval,
                'haldane',
                pin=-5000,
                alpha=alpha,
                colorV=ill,
                colormap='viridis',
                linewidth=0,
                cax_label=r'$\lambda^{-1}$',
                vmin=vmin,
                vmax=vmax,
                climbars=False,
                **kwargs)
            print 'cbar_ax = ', cax
            if vmax is None:
                print 'setting vmax...'
                vmax = cbar.get_clim()[1]
        elif ii == 0:
            dos_ax, cbar_ax, cbar, n, bins = \
                leplt.colored_DOS_plot(eigval, dos_ax, 'haldane', pin=-5000, alpha=alpha, colorV=ill,
                                       cbar_ax=cbar_ax, colormap='viridis', linewidth=0,
                                       make_cbar=True, vmin=vmin, vmax=vmax, **kwargs)
            if vmax is None:
                print 'setting vmax...'
                vmax = cbar.get_clim()[1]
        else:
            print 'gcollpfns: calling leplt.colored_DOS_plot...'
            leplt.colored_DOS_plot(eigval,
                                   dos_ax,
                                   'haldane',
                                   pin=-5000,
                                   alpha=alpha,
                                   colorV=ill,
                                   cbar_ax=cbar_ax,
                                   colormap='viridis',
                                   linewidth=0,
                                   make_cbar=False,
                                   vmin=vmin,
                                   vmax=vmax,
                                   **kwargs)

        plt.pause(1)

    return dos_ax, cbar_ax
Ejemplo n.º 5
0
    def plot_ipr_DOS_overlay(self,
                             outdir=None,
                             title=r'$D(\omega)$ for Haldane network',
                             fname='ipr_DOS_overlay',
                             alpha=None,
                             FSFS=12,
                             inverse_PR=True,
                             show=False,
                             close=True,
                             initialize=True,
                             DOS_ax=None,
                             vmin=None,
                             vmax=None,
                             check=False,
                             **kwargs):
        """Plot Inverse Participation Ratio of the Haldane networks and overlay them

        Parameters
        ----------
        close : bool
            Whether to show the figure after plotting
        close : bool
            Whether to close all figure instances at the end
        initialize : bool
            If True or if DOSax is not supplied, creates a new plot for the ipr DOS image
        DOSax : axis instance
            Axis on which to plot the PR DOS, if initialize is False
        **kwargs: most of lepm.plotting.plotting.colored_DOS_plot() keyword arguments
            Excluding pin, alpha, colorV, colormap, linewidth, make_cbar, vmin, vmax
            Includes
        """
        self.ensure_all_eigval()

        # Decide what alpha value to use if not provided (here, 1/N)
        if alpha is None:
            alpha = 1. / float(len(self.haldane_lattices))

        # Register cmaps if necessary
        if 'viridis' not in plt.colormaps(
        ) or 'viridis_r' not in plt.colormaps():
            cmaps.register_colormaps()

        # Plot the overlays
        for ii in range(len(self.haldane_lattices)):
            if ii % 10 == 0:
                print 'Overlaying ', ii, ' of ', len(self.haldane_lattices)

            eigval = self.haldane_lattices[ii].eigval

            # Load ipr
            if self.haldane_lattices[ii].ipr is None:
                # Attempt to load ipr directly
                try:
                    ipr = self.haldane_lattices[ii].load_ipr(attribute=False)
                except:
                    # To calc ipr, load eigvect
                    if self.haldane_lattices[ii].eigvect is None:
                        eigvect = self.haldane_lattices[ii].load_eigvect(
                            attribute=False)
                    else:
                        eigvect = self.haldane_lattices[ii].eigvect
                    ipr = self.haldane_lattices[ii].calc_ipr(eigvect=eigvect,
                                                             attribute=False)

            # Now overlay the ipr
            if vmin is None and inverse_PR:
                print 'setting vmin...'
                vmin = 1.0
            if ii == 0 and initialize and DOS_ax is None:
                if inverse_PR:
                    fig, DOS_ax, cbar_ax, cbar = leplt.initialize_colored_DOS_plot(
                        eigval,
                        'haldane',
                        pin=-5000,
                        alpha=alpha,
                        colorV=ipr,
                        colormap='viridis',
                        fontsize=FSFS,
                        linewidth=0,
                        cax_label=r'$p^{-1}$',
                        vmin=vmin,
                        vmax=vmax,
                        climbars=False,
                        **kwargs)
                    print 'cbar_ax = ', cbar_ax
                    if vmax is None:
                        print 'setting vmax...'
                        vmax = cbar.get_clim()[1]
                else:
                    fig, DOS_ax, cbar_ax, cbar = \
                        leplt.initialize_colored_DOS_plot(eigval, 'haldane', pin=-5000, alpha=alpha,
                                                          colorV=1./ipr, colormap='viridis_r', fontsize=FSFS,
                                                          linewidth=0, cax_label=r'$p$', climbars=False,
                                                          vmin=vmin, vmax=vmax, **kwargs)
                    if vmin is None:
                        print 'setting vmin...'
                        vmin = cbar.get_clim()[0]
                    if vmax is None:
                        print 'setting vmax...'
                        vmax = cbar.get_clim()[1]
            elif ii == 0:
                if inverse_PR:
                    DOS_ax, cbar_ax, cbar, n, bins = \
                        leplt.colored_DOS_plot(eigval, DOS_ax, 'haldane', pin=-5000, alpha=alpha, colorV=ipr,
                                               fontsize=FSFS, colormap='viridis', linewidth=0, make_cbar=True,
                                               vmin=vmin, vmax=vmax, **kwargs)
                    if vmax is None:
                        print 'setting vmax...'
                        vmax = cbar.get_clim()[1]
                else:
                    DOS_ax, cbar_ax, cbar, n, bins = \
                        leplt.colored_DOS_plot(eigval, DOS_ax, 'haldane', pin=-5000, alpha=alpha, colorV=1./ipr,
                                               fontsize=FSFS, colormap='viridis_r', linewidth=0,
                                               make_cbar=True, vmin=vmin, vmax=vmax, **kwargs)
                    if vmin is None:
                        print 'setting vmin...'
                        vmin = cbar.get_clim()[0]
                    if vmax is None:
                        print 'setting vmax...'
                        vmax = cbar.get_clim()[1]
            else:
                if inverse_PR:
                    leplt.colored_DOS_plot(eigval,
                                           DOS_ax,
                                           'haldane',
                                           pin=-5000,
                                           alpha=alpha,
                                           colorV=ipr,
                                           fontsize=FSFS,
                                           colormap='viridis',
                                           linewidth=0,
                                           make_cbar=False,
                                           vmin=vmin,
                                           vmax=vmax,
                                           **kwargs)
                else:
                    leplt.colored_DOS_plot(eigval,
                                           DOS_ax,
                                           'haldane',
                                           pin=-5000,
                                           alpha=alpha,
                                           colorV=1. / ipr,
                                           fontsize=FSFS,
                                           colormap='viridis_r',
                                           linewidth=0,
                                           make_cbar=False,
                                           vmin=vmin,
                                           vmax=vmax,
                                           **kwargs)

            if check:
                plt.pause(1)

        DOS_ax.set_title(title, fontsize=FSFS)
        if outdir is not None:
            print 'saving as ', outdir + fname + '.pkl'
            pl.dump(fig, file(outdir + fname + '.pkl', 'w'))
            plt.savefig(outdir + fname + '.png')
            plt.savefig(outdir + fname + '.pdf')
        if show:
            plt.show()
        if close:
            plt.close('all')
Ejemplo n.º 6
0
    def plot_ipr_DOS_stack(self,
                           outdir=None,
                           title=r'$D(\omega)$ for Haldane network',
                           fname='ipr_DOS_stack',
                           vmin=None,
                           vmax=None,
                           alpha=None,
                           FSFS=12,
                           inverse_PR=True,
                           show=False,
                           close=True,
                           ylabels=None,
                           **kwargs):
        """Plot Inverse Participation Ratio of the Haldane networks (with DOS) and stack them in a column

        Parameters
        ----------
        outdir : str or None
        title : str
        fname : str
        vmin : float or None
        vmax : float or None
        alpha : float or None
        FSFS : int
        inverse_PR : bool
        show : bool
        close : bool
        ylabels : None
        **kwargs: arguments passed to glat.add_ipr_to_ax()
            --> most of lepm.plotting.plotting.colored_DOS_plot() keyword arguments
            Excluding pin, alpha, colorV, colormap, linewidth, make_cbar, vmin, vmax,
        """
        self.ensure_all_eigval()

        # Decide what alpha value to use if not provided (here, 1.)
        if alpha is None:
            alpha = 1.

        # Register cmaps if necessary
        if 'viridis' not in plt.colormaps(
        ) or 'viridis_r' not in plt.colormaps():
            cmaps.register_colormaps()

        fig, ax = plt.subplots(len(self.haldane_lattices),
                               1,
                               sharex=True,
                               sharey=True)

        n_glats = len(self.haldane_lattices)

        # Plot the DOS
        xlabel = ''
        cax = fig.add_axes([0.93, 0.2, 0.02, 0.5])
        for ii in range(n_glats):
            print 'Plotting ', ii, ' of ', len(self.haldane_lattices)
            if ii == n_glats - 1:
                xlabel = 'Oscillation frequency $\omega$'
            if ylabels is None:
                ylabel = ''
            else:
                ylabel = ylabels[ii]
            print 'inverse_PR = ', inverse_PR
            DOSaxis = self.haldane_lattices[ii].add_ipr_to_ax(
                ax[ii],
                alpha=alpha,
                inverse_PR=inverse_PR,
                xlabel=xlabel,
                ylabel=ylabel,
                vmax=vmax,
                vmin=vmin,
                cbar_ax=cax,
                **kwargs)
            ii += 1

        ax[0].set_title(title, fontsize=FSFS)
        ax[0].annotate(r'$D(\omega)$',
                       xy=(.01, .5),
                       xycoords='figure fraction',
                       horizontalalignment='left',
                       verticalalignment='center',
                       fontsize=FSFS,
                       rotation=90)
        if outdir is not None:
            print 'saving as ', outdir + fname + '.pkl'
            pl.dump(fig, file(outdir + fname + '.pkl', 'w'))
            plt.savefig(outdir + fname + '.png')
            plt.savefig(outdir + fname + '.pdf')
        if show:
            plt.show()
        if close:
            plt.close('all')
Ejemplo n.º 7
0
def relax_overdamped_openbc(xy,
                            timesteps,
                            dt,
                            modout=10,
                            outpath=None,
                            save_im=False,
                            clamp_boundary=False):
    """Relax a system with open boundary conditions of particles by a central force, with velocity equal to Force.
    For the interaction, use F=(1-r)rhat for r<1, where r is the distance between particles and rhat is the vector
    between them.

    Parameters
    ----------
    xy
    PV
    timesteps
    dt
    modout
    outpath : str
        the full path, except for the txt extension, to put the output files
    clamp_boundary : bool
        Whether to affix the boundary particles during each relaxation step

    Returns
    -------

    """
    xyo = copy.deepcopy(xy)

    # Save initial positions if outpath is not None
    ii = 0
    time = 0.

    if outpath is not None:
        print 'saving to ', outpath + '{0:06d}'.format(ii)
        header = 'Relaxing (spreading) xy pts generated by gammakick procedure: t={0:0.12e}'.format(time) +\
                 ', dt={0:0.12e}'.format(dt)
        np.savetxt(outpath + '{0:08.3f}'.format(time).replace('.', 'p') +
                   '.txt',
                   xy,
                   header=header)
    if save_im:
        lecmaps.register_colormaps()
        cmap = plt.get_cmap('viridis')

    for ii in (np.arange(timesteps) + 1):
        # Relax for a time dt
        if ii % modout == 0:
            print 'relaxing pts: ii=', ii
        time += dt
        dxy = -spreading_forces_openbc(xyo) * dt

        if clamp_boundary:
            # todo: add code for boundary clamping
            raise RuntimeError('Add code to clamp the boundary here!')

        xyo += dxy

        if np.mod(ii, modout) == 0 and outpath is not None:
            header = 'Relaxing (spreading) xy pts generated by gammakick procedure: t={0:0.12e}'.format(time) + \
                     ', dt={0:0.12e}'.format(dt)
            np.savetxt(outpath + '{0:08.3f}'.format(time).replace('.', 'p') +
                       '.txt',
                       xyo,
                       header=header)
        if save_im:
            plt.scatter(xyo[:, 0],
                        xyo[:, 1],
                        c=cmap(float(ii) / float(timesteps)),
                        edgecolor='none')
    return xyo
Ejemplo n.º 8
0
def relax_overdamped(xy,
                     pv,
                     bbox,
                     timesteps,
                     dt,
                     modout=10,
                     outpath=None,
                     save_im=False):
    """Relax a system of particles by a central force, with velocity equal to Force.
    For the interaction, use F=(1-r)rhat for r<1, where r is the distance between particles and rhat is the vector
    between them.

    Parameters
    ----------
    xy
    PV
    timesteps
    dt
    modout
    outpath : str
        the full path, except for the txt extension, to put the output files

    Returns
    -------

    """
    xyo = copy.deepcopy(xy)

    # Check if the bbox is a rectangle aligned with the xy axes
    isrect = (dh.unique_count(bbox[:, 0])[:, 1] >
              1).all() and (dh.unique_count(bbox[:, 1])[:, 1] > 1).all()
    if isrect:
        minx = np.min(bbox[:, 0])
        maxx = np.max(bbox[:, 0])
        miny = np.min(bbox[:, 1])
        maxy = np.max(bbox[:, 1])
        # Since the bbox is a rectangle, we can assume one element of each of the periodic vectors is zero
        # Form pvx, the distance in x of the periodic vector pointing in the x dir, and similarly for y
        pvx = np.max(np.abs(pv[:, 0]))
        pvy = np.max(np.abs(pv[:, 1]))

    # Save initial positions if outpath is not None
    ii = 0
    time = 0.
    if outpath is not None:
        print 'saving to ', outpath + '{0:06d}'.format(ii)
        header = 'Relaxing (spreading) xy pts generated by gammakick procedure: t={0:0.12e}'.format(time) +\
                 ', dt={0:0.12e}'.format(dt)
        np.savetxt(outpath + '{0:08.3f}'.format(time).replace('.', 'p') +
                   '.txt',
                   xy,
                   header=header)
    if save_im:
        lecmaps.register_colormaps()
        cmap = plt.get_cmap('viridis')

    for ii in (np.arange(timesteps) + 1):
        # Relax for a time dt
        if ii % modout == 0:
            print 'relaxing pts: ii=', ii
        time += dt
        dxy = spreading_forces(xyo, pv) * dt
        xyo += dxy
        if isrect:
            # Since the bbox is a rectangle, we can just move the points outside the bounds back inside
            xyo[xyo[:, 0] < minx, 0] += pvx
            xyo[xyo[:, 1] < miny, 1] += pvy
            xyo[xyo[:, 0] > maxx, 0] -= pvx
            xyo[xyo[:, 1] > maxy, 1] -= pvy
        else:
            # The bbox is a more complicated shape, so we have to use something like matplotlib's inpoly
            bpath = mplpath.Path(bbox)
            outside = not bpath.contains_points(xy)
            raise RuntimeError(
                'Have not included functionality for non-rectangular periodic BCs. Build that here.'
            )

        if np.mod(ii, modout) == 0 and outpath is not None:
            header = 'Relaxing (spreading) xy pts generated by gammakick procedure: t={0:0.12e}'.format(time) + \
                     ', dt={0:0.12e}'.format(dt)
            np.savetxt(outpath + '{0:08.3f}'.format(time).replace('.', 'p') +
                       '.txt',
                       xyo,
                       header=header)

    if save_im:
        # load and plot points
        time = 0.
        for ii in np.arange(timesteps + 1):
            if np.mod(ii, modout) == 0:
                xyo = np.loadtxt(outpath +
                                 '{0:08.3f}'.format(time).replace('.', 'p') +
                                 '.txt')
                plt.scatter(xyo[:, 0],
                            xyo[:, 1],
                            c=cmap(float(ii) / float(timesteps)),
                            edgecolor='none')
            time += dt

        plt.savefig(outpath + 'relaxation_visualization.png')
    return xyo
Ejemplo n.º 9
0
def movie_plot_2D(xy,
                  BL,
                  bs=None,
                  fname='none',
                  title='',
                  NL=[],
                  KL=[],
                  BLNNN=[],
                  NLNNN=[],
                  KLNNN=[],
                  PVx=[],
                  PVy=[],
                  PVxydict={},
                  nljnnn=None,
                  kljnnn=None,
                  klknnn=None,
                  ax=None,
                  fig=None,
                  axcb='auto',
                  cbar_ax=None,
                  cbar_orientation='vertical',
                  xlimv='auto',
                  ylimv='auto',
                  climv=0.1,
                  colorz=True,
                  ptcolor=None,
                  figsize='auto',
                  colorpoly=False,
                  bondcolor=None,
                  colormap='seismic',
                  bgcolor=None,
                  axis_off=False,
                  axis_equal=True,
                  text_topleft=None,
                  lw=-1.,
                  ptsize=10,
                  negative_NNN_arrows=False,
                  show=False,
                  arrow_alpha=1.0,
                  fontsize=8,
                  cax_label='Strain',
                  zorder=0,
                  rasterized=False):
    """Plots (and saves if fname is not 'none') a 2D image of the lattice with colored bonds and particles colored by
    coordination (both optional).

    Parameters
    ----------
    xy : array of dimension nx2
        2D lattice of points (positions x,y)
    BL : array of dimension #bonds x 2
        Each row is a bond and contains indices of connected points
    bs : array of dimension #bonds x 1 or None
        Strain in each bond
    fname : string
        Full path including name of the file (.png, etc), if None, will not save figure
    title : string
        The title of the frame
    NL : NP x NN int array (optional, for speed)
        Specify to speed up computation, if colorz or colorpoly or if periodic boundary conditions
    KL : NP x NN int array (optional, for speed)
        Specify to speed up computation, if colorz or colorpoly or if periodic boundary conditions
    BLNNN :
    NLNNN :
    KLNNN :
    PVx : NP x NN float array (optional, for periodic lattices and speed)
        ijth element of PVx is the x-component of the vector taking NL[i,j] to its image as seen by particle i
        If PVx and PVy are specified, PVxydict need not be specified.
    PVy : NP x NN float array (optional, for periodic lattices and speed)
        ijth element of PVy is the y-component of the vector taking NL[i,j] to its image as seen by particle i
        If PVx and PVy are specified, PVxydict need not be specified.
    PVxydict : dict (optional, for periodic lattices)
        dictionary of periodic bonds (keys) to periodic vectors (values)
    nljnnn : #pts x max(#NNN) int array or None
        nearest neighbor array matching NLNNN and KLNNN. nljnnn[i, j] gives the neighbor of i such that NLNNN[i, j] is
        the next nearest neighbor of i through the particle nljnnn[i, j]
    kljnnn : #pts x max(#NNN) int array or None
        bond array describing periodicity of bonds matching NLNNN and KLNNN. kljnnn[i, j] describes the bond type
        (bulk -> +1, periodic --> -1) of bond connecting i to nljnnn[i, j]
    klknnn : #pts x max(#NNN) int array or None
        bond array describing periodicity of bonds matching NLNNN and KLNNN. klknnn[i, j] describes the bond type
        (bulk -> +1, periodic --> -1) of bond connecting nljnnn[i, j] to NLNNN[i, j]
    ax: matplotlib figure axis instance
        Axis on which to draw the network
    fig: matplotlib figure instance
        Figure on which to draw the network
    axcb: matplotlib colorbar instance
        Colorbar to use for strains in bonds
    cbar_ax : axis instance
        Axis to use for colorbar. If colorbar instance is not already defined, use axcb instead.
    cbar_orientation : str ('horizontal' or 'vertical')
        Orientation of the colorbar
    xlimv: float or tuple of floats
    ylimv: float or tuple of floats
    climv : float or tuple
        Color limit for coloring bonds by bs
    colorz: bool
        whether to color the particles by their coordination number
    ptcolor: string color spec or tuple color spec or None
        color specification for coloring the points, if colorz is False. Default is None (no coloring of points)
    figsize : tuple
        w,h tuple in inches
    colorpoly : bool
        Whether to color in polygons formed by bonds according to the number of sides
    bondcolor : color specification (hexadecimal or RGB)
    colormap : if bondcolor is None, uses bs array to color bonds
    bgcolor : hex format string, rgb color spec, or None
        If not None, sets the bgcolor. Often used is '#d9d9d9'
    axis_off : bool
        Turn off the axis border and canvas
    axis_equal : bool
    text_topleft : str or None
    lw: float
        line width for plotting bonds. If lw == -1, then uses automatic line width to adjust for bond density..
    ptsize: float
        size of points passed to absolute_sizer
    negative_NNN_arrows : bool
        make positive and negative NNN hoppings different color
    show : bool
        whether to show the plot after creating it
    arrow_alpha : float
        opacity of the arrow
    fontsize : int (default=8)
        fontsize for all labels
    cax_label : int (default='Strain')
        Label for the colorbar
    zorder : int
        z placement on axis (higher means bringing network to the front, lower is to the back

    Returns
    ----------
    [ax,axcb] : stuff to clear after plotting

    """
    if fig is None or fig == 'none':
        fig = plt.gcf()
    if ax is None or ax == 'none':
        if figsize == 'auto':
            plt.clf()
        else:
            fig = plt.figure(figsize=figsize)
        ax = plt.axes()

    if bs is None:
        bs = np.zeros_like(BL[:, 0], dtype=float)

    if colormap not in plt.colormaps():
        lecmaps.register_colormaps()

    NP = len(xy)
    if lw == -1:
        if NP < 10000:
            lw = 0.5
            s = leplt.absolute_sizer()
        else:
            lw = (10 / np.sqrt(len(xy)))

    if NL == [] and KL == []:
        if colorz or colorpoly:
            NL, KL = le.BL2NLandKL(BL, NP=NP, NN='min')
            if (BL < 0).any():
                if len(PVxydict) == 0:
                    raise RuntimeError(
                        'PVxydict must be supplied to display_lattice_2D() when periodic BCs exist, '
                        + 'if NL and KL not supplied!')
                else:
                    PVx, PVy = le.PVxydict2PVxPVy(PVxydict, NL, KL)

    if colorz:
        zvals = (KL != 0).sum(1)
        zmed = np.median(zvals)
        # print 'zmed = ', zmed
        under1 = np.logical_and(zvals < zmed - 0.5, zvals > zmed - 1.5)
        over1 = np.logical_and(zvals > zmed + 0.5, zvals < zmed + 1.5)
        Cz = np.zeros((len(xy), 3), dtype=int)
        # far under black // under blue // equal white // over red // far over green
        Cz[under1] = [0. / 255, 50. / 255, 255. / 255]
        Cz[zvals == zmed] = [100. / 255, 100. / 255, 100. / 255]
        Cz[over1] = [255. / 255, 0. / 255, 0. / 255]
        Cz[zvals > zmed + 1.5] = [0. / 255, 255. / 255, 50. / 255]
        # Cz[zvals<zmed-1.5] = [0./255,255./255,150./255] #leave these black

        s = leplt.absolute_sizer()
        sval = min([.005, .12 / np.sqrt(len(xy))])
        sizes = np.zeros(NP, dtype=float)
        sizes[zvals > zmed + 0.5] = sval
        sizes[zvals == zmed] = sval * 0.5
        sizes[zvals < zmed - 0.5] = sval

        # topinds = zvals!=zmed
        ax.scatter(xy[:, 0],
                   xy[:, 1],
                   s=s(sizes),
                   c=Cz,
                   edgecolor='none',
                   zorder=10,
                   rasterized=rasterized)
        ax.axis('equal')
    elif ptcolor is not None and ptcolor != 'none' and ptcolor != '':
        if NP < 10000:
            # if smallish #pts, plot them
            # print 'xy = ', xy
            # plt.plot(xy[:,0],xy[:,1],'k.')
            s = leplt.absolute_sizer()
            ax.scatter(xy[:, 0],
                       xy[:, 1],
                       s=ptsize,
                       alpha=0.5,
                       facecolor=ptcolor,
                       edgecolor='none',
                       rasterized=rasterized)

    if colorpoly:
        # Color the polygons based on # sides
        # First extract polygons. To do that, if there are periodic boundaries, we need to supply as dict
        if PVxydict == {} and len(PVx) > 0:
            PVxydict = le.PVxy2PVxydict(PVx, PVy, NL, KL=KL)

        polygons = le.extract_polygons_lattice(xy,
                                               BL,
                                               NL=NL,
                                               KL=KL,
                                               viewmethod=True,
                                               PVxydict=PVxydict)
        PolyPC = le.polygons2PPC(polygons)
        # number of polygon sides
        Pno = np.array([len(polyg) for polyg in polygons], dtype=int)
        print 'nvis: Pno = ', Pno
        print 'nvis: medPno = ', np.floor(np.median(Pno))
        medPno = np.floor(np.median(Pno))
        uIND = np.where(Pno == medPno - 1)[0]
        mIND = np.where(Pno == medPno)[0]
        oIND = np.where(Pno == medPno + 1)[0]
        loIND = np.where(Pno < medPno - 1.5)[0]
        hiIND = np.where(Pno > medPno + 1.5)[0]
        print ' uIND = ', uIND
        print ' oIND = ', oIND
        print ' loIND = ', loIND
        print ' hiIND = ', hiIND
        if len(uIND) > 0:
            PPCu = [PolyPC[i] for i in uIND]
            pu = PatchCollection(PPCu, color='b', alpha=0.5)
            ax.add_collection(pu)
        if len(mIND) > 0:
            PPCm = [PolyPC[i] for i in mIND]
            pm = PatchCollection(PPCm, color=[0.5, 0.5, 0.5], alpha=0.5)
            ax.add_collection(pm)
        if len(oIND) > 0:
            PPCo = [PolyPC[i] for i in oIND]
            po = PatchCollection(PPCo, color='r', alpha=0.5)
            ax.add_collection(po)
        if len(loIND) > 0:
            PPClo = [PolyPC[i] for i in loIND]
            plo = PatchCollection(PPClo, color='k', alpha=0.5)
            ax.add_collection(plo)
        if len(hiIND) > 0:
            PPChi = [PolyPC[i] for i in hiIND]
            phi = PatchCollection(PPChi, color='g', alpha=0.5)
            ax.add_collection(phi)

    # Efficiently plot many lines in a single set of axes using LineCollection
    # First check if there are periodic bonds
    if BL.size > 0:
        if (BL < 0).any():
            if PVx == [] or PVy == [] or PVx is None or PVy is None:
                raise RuntimeError(
                    'PVx and PVy must be supplied to display_lattice_2D when periodic BCs exist!'
                )
            else:
                # get indices of periodic bonds
                perINDS = np.unique(np.where(BL < 0)[0])
                perBL = np.abs(BL[perINDS])
                # # Check
                # print 'perBL = ', perBL
                # plt.plot(xy[:,0], xy[:,1],'b.')
                # for i in range(len(xy)):
                #     plt.text(xy[i,0]+0.05, xy[i,1],str(i))
                # plt.show()

                # define the normal bonds which are not periodic
                normINDS = np.setdiff1d(np.arange(len(BL)), perINDS)
                BLtmp = BL[normINDS]
                bstmp = bs[normINDS]
                lines = [
                    zip(xy[BLtmp[i, :], 0], xy[BLtmp[i, :], 1])
                    for i in range(len(BLtmp))
                ]

                xy_add = np.zeros((4, 2))
                # Build new strain list bs_out by storing bulk lines first, then recording the strain twice
                # for each periodic bond since the periodic bond is at least two lines in the plot, get bs_out
                # ready for appending
                # bs_out = np.zeros(len(normINDS) + 5 * len(perINDS), dtype=float)
                # bs_out[0:len(normINDS)] = bstmp
                bs_out = bstmp.tolist()

                # Add periodic bond lines to image
                # Note that we have to be careful that a single particle can be connected to another both in the bulk
                # and through a periodic boundary, and perhaps through more than one periodic boundary
                # kk indexes perINDS to determine what the strain of each periodic bond should be
                # draw_perbond_count counts the number of drawn linesegments that are periodic bonds
                kk, draw_perbond_count = 0, 0
                for row in perBL:
                    colA = np.argwhere(NL[row[0]] == row[1]).ravel()
                    colB = np.argwhere(NL[row[1]] == row[0]).ravel()
                    if len(colA) > 1 or len(colB) > 1:
                        # Look for where KL < 0 to pick out just the periodic bond(s) -- ie there
                        # were both bulk and periodic bonds connecting row[0] to row[1]
                        a_klneg = np.argwhere(KL[row[0]] < 0)
                        colA = np.intersect1d(colA, a_klneg)
                        b_klneg = np.argwhere(KL[row[1]] < 0)
                        colB = np.intersect1d(colB, b_klneg)
                        # print 'colA = ', colA
                        # print 'netvis here'
                        # sys.exit()
                        if len(colA) > 1 or len(colB) > 1:
                            # there are multiple periodic bonds connecting one particle to another (in different
                            # directions). Plot each of them.
                            for ii in range(len(colA)):
                                print 'netvis: colA = ', colA
                                print 'netvis: colB = ', colB
                                # columns a and b for this ii index
                                caii, cbii = colA[ii], colB[ii]
                                # add xy points to the network to plot to simulate image particles
                                xy_add[0] = xy[row[0]]
                                xy_add[1] = xy[row[1]] + np.array(
                                    [PVx[row[0], caii], PVy[row[0], caii]])
                                xy_add[2] = xy[row[1]]
                                xy_add[3] = xy[row[0]] + np.array(
                                    [PVx[row[1], cbii], PVy[row[1], cbii]])
                                # Make the lines to draw (dashed lines for this periodic case)
                                lines += zip(xy_add[0:2, 0],
                                             xy_add[0:2, 1]), zip(
                                                 xy_add[2:4, 0], xy_add[2:4,
                                                                        1])
                                bs_out.append(bs[perINDS[kk]])
                                bs_out.append(bs[perINDS[kk]])
                                draw_perbond_count += 1

                            kk += 1
                        else:
                            # print 'row = ', row
                            # print 'NL = ', NL
                            # print 'KL = ', KL
                            # print 'colA, colB = ', colA, colB
                            colA, colB = colA[0], colB[0]
                            xy_add[0] = xy[row[0]]
                            xy_add[1] = xy[row[1]] + np.array(
                                [PVx[row[0], colA], PVy[row[0], colA]])
                            xy_add[2] = xy[row[1]]
                            xy_add[3] = xy[row[0]] + np.array(
                                [PVx[row[1], colB], PVy[row[1], colB]])
                            lines += zip(xy_add[0:2, 0], xy_add[0:2, 1]), zip(
                                xy_add[2:4, 0], xy_add[2:4, 1])
                            # bs_out[2 * kk + len(normINDS)] = bs[perINDS[kk]]
                            # bs_out[2 * kk + 1 + len(normINDS)] = bs[perINDS[kk]]
                            bs_out.append(bs[perINDS[kk]])
                            bs_out.append(bs[perINDS[kk]])
                            draw_perbond_count += 1
                            kk += 1
                    else:
                        colA, colB = colA[0], colB[0]
                        xy_add[0] = xy[row[0]]
                        xy_add[1] = xy[row[1]] + np.array(
                            [PVx[row[0], colA], PVy[row[0], colA]])
                        xy_add[2] = xy[row[1]]
                        xy_add[3] = xy[row[0]] + np.array(
                            [PVx[row[1], colB], PVy[row[1], colB]])
                        lines += zip(xy_add[0:2, 0],
                                     xy_add[0:2,
                                            1]), zip(xy_add[2:4, 0],
                                                     xy_add[2:4, 1])
                        # bs_out[2 * kk + len(normINDS)] = bs[perINDS[kk]]
                        # bs_out[2 * kk + 1 + len(normINDS)] = bs[perINDS[kk]]
                        bs_out.append(bs[perINDS[kk]])
                        bs_out.append(bs[perINDS[kk]])
                        draw_perbond_count += 1
                        kk += 1

                # replace bs by the new bs (bs_out)
                bs = np.array(bs_out)
                # store number of bulk bonds
                nbulk_bonds = len(normINDS)
        else:
            if len(np.shape(BL)) > 1:
                lines = [
                    zip(xy[BL[i, :], 0], xy[BL[i, :], 1])
                    for i in range(np.shape(BL)[0])
                ]
                # store number of bulk bonds
                nbulk_bonds = len(lines)
            else:
                lines = [
                    zip(xy[BL[i][0]], xy[BL[i][1]])
                    for i in range(np.shape(BL)[0])
                ]
                # store number of bulk bonds
                nbulk_bonds = 1

        if isinstance(climv, tuple):
            cmin = climv[0]
            cmax = climv[1]
        elif isinstance(climv, float):
            cmin = -climv
            cmax = climv
        elif climv is None:
            cmin = None
            cmax = None

        if bondcolor is None:
            # draw the periodic bonds as dashed, regular bulk bonds as solid
            line_segments = LineCollection(
                lines[0:nbulk_bonds],  # Make a sequence of x,y pairs
                linewidths=lw,  # could iterate over list
                linestyles='solid',
                cmap=colormap,
                norm=plt.Normalize(vmin=cmin, vmax=cmax),
                zorder=zorder,
                rasterized=rasterized)
            line_segments.set_array(bs[0:nbulk_bonds])
            # draw the periodic bonds as dashed, if there are any
            periodic_lsegs = LineCollection(
                lines[nbulk_bonds:],  # Make a sequence of x,y pairs
                linewidths=lw,  # could iterate over list
                linestyles='dashed',
                cmap=colormap,
                norm=plt.Normalize(vmin=cmin, vmax=cmax),
                zorder=zorder,
                rasterized=rasterized)
            periodic_lsegs.set_array(bs[nbulk_bonds:])
        else:
            line_segments = LineCollection(lines[0:nbulk_bonds],
                                           linewidths=lw,
                                           linestyles='solid',
                                           colors=bondcolor,
                                           zorder=zorder,
                                           rasterized=rasterized)
            # draw the periodic bonds as dashed, if there are any
            periodic_lsegs = LineCollection(lines[nbulk_bonds:],
                                            linewidths=lw,
                                            linestyles='dashed',
                                            colors=bondcolor,
                                            zorder=zorder,
                                            rasterized=rasterized)

        ax.add_collection(line_segments)
        if periodic_lsegs:
            ax.add_collection(periodic_lsegs)
        # If there is only a single bond color, ignore the colorbar specification
        if bondcolor is None or isinstance(bondcolor, np.ndarray):
            if axcb == 'auto':
                if cbar_ax is None:
                    print 'nvis: Instantiating colorbar...'
                    axcb = fig.colorbar(line_segments)
                else:
                    print 'nvis: Using cbar_ax to instantiate colorbar'
                    axcb = fig.colorbar(line_segments,
                                        cax=cbar_ax,
                                        orientation=cbar_orientation)

            if axcb != 'none' and axcb is not None:
                print 'nvis: Creating colorbar...'
                axcb.set_label(cax_label, fontsize=fontsize)
                axcb.set_clim(vmin=cmin, vmax=cmax)
        else:
            # Ignore colorbar axis specification
            axcb = 'none'
    else:
        axcb = 'none'

    if len(BLNNN) > 0:
        # todo: add functionality for periodic NNN connections
        # Efficiently plot many lines in a single set of axes using LineCollection
        lines = [
            zip(xy[BLNNN[i, :], 0], xy[BLNNN[i, :], 1])
            for i in range(len(BLNNN))
        ]
        linesNNN = LineCollection(
            lines,  # Make a sequence of x,y pairs
            linewidths=lw,  # could iterate over list
            linestyles='dashed',
            color='blue',
            zorder=100)
        ax.add_collection(linesNNN, rasterized=rasterized)
    elif len(NLNNN) > 0 and len(KLNNN) > 0:
        factor = 0.8
        if (BL < 0).any():
            print 'nvis: plotting periodic NNN...'
            if nljnnn is None:
                raise RuntimeError(
                    'Must supply nljnnn to plot NNN hoppings/connections')
            for i in range(NP):
                todo = np.where(KLNNN[i, :] > 1e-12)[0]
                for index in todo:
                    kk = NLNNN[i, index]
                    # Ascribe the correct periodic vector based on both PVx[i, NNind] and PVx[NNind, ind]
                    # Note : nljnnn is
                    # nearest neighbor array matching NLNNN and KLNNN. nljnnn[i, j] gives the neighbor of i such that
                    # NLNNN[i, j] is the next nearest neighbor of i through the particle nljnnn[i, j]
                    jj = nljnnn[i, index]
                    if kljnnn[i, index] < 0 or klknnn[i, index] < 0:
                        jind = np.where(NL[i, :] == jj)[0][0]
                        kind = np.where(NL[jj, :] == kk)[0][0]
                        # print 'jj = ', jj
                        # print 'kk = ', kk
                        # print 'jind = ', jind
                        # print 'kind = ', kind
                        # print 'NL[i, :] =', NL[i, :]
                        # print 'NL[jj, :] =', NL[jj, :]
                        # print 'PVx[i, jind] = ', PVx[i, jind]
                        # print 'PVy[i, jind] = ', PVy[i, jind]
                        # print 'PVx[jj, kind] = ', PVx[jj, kind]
                        # print 'PVy[jj, kind] = ', PVy[jj, kind]
                        dx = (xy[kk, 0] + PVx[i, jind] + PVx[jj, kind] -
                              xy[i, 0]) * factor
                        dy = (xy[kk, 1] + PVy[i, jind] + PVy[jj, kind] -
                              xy[i, 1]) * factor
                    else:
                        dx = (xy[kk, 0] - xy[i, 0]) * factor
                        dy = (xy[kk, 1] - xy[i, 1]) * factor
                    ax.arrow(xy[i, 0],
                             xy[i, 1],
                             dx,
                             dy,
                             head_width=0.1,
                             head_length=0.2,
                             fc='b',
                             ec='b',
                             linestyle='dashed')
                    # Check
                    # print 'dx = ', dx
                    # print 'dy = ', dy
                    # for ind in range(NP):
                    #     plt.text(xy[ind, 0]-0.2, xy[ind, 1]-0.2, str(ind))
                    # plt.show()
                    # sys.exit()
        else:
            # amount to offset clockwise nnn arrows
            for i in range(NP):
                todo = np.where(KLNNN[i, :] > 1e-12)[0]

                # Allow for both blue and red arrows (forward/backward), or just blue. If just blue, use no offset and
                # full scale factor
                if negative_NNN_arrows:
                    scalef = 0.3
                else:
                    scalef = 0.8
                offset = np.array([0.0, 0.0])
                for ind in NLNNN[i, todo]:
                    if negative_NNN_arrows:
                        offset = (xy[ind, :] - xy[i, :]) * 0.5
                    ax.arrow(xy[i, 0] + offset[0],
                             xy[i, 1] + offset[1],
                             (xy[ind, 0] - xy[i, 0]) * scalef,
                             (xy[ind, 1] - xy[i, 1]) * scalef,
                             head_width=0.1,
                             head_length=0.2,
                             fc='b',
                             ec='b',
                             alpha=arrow_alpha)

                if negative_NNN_arrows:
                    todo = np.where(KLNNN[i, :] < -1e-12)[0]
                    for ind in NLNNN[i, todo]:
                        offset = (xy[ind, :] - xy[i, :]) * 0.5
                        ax.arrow(xy[i, 0] + offset[0],
                                 xy[i, 1] + offset[1],
                                 (xy[ind, 0] - xy[i, 0]) * 0.3,
                                 (xy[ind, 1] - xy[i, 1]) * 0.3,
                                 head_width=0.1,
                                 head_length=0.2,
                                 fc='r',
                                 ec='r',
                                 alpha=arrow_alpha)

    if bgcolor is not None:
        ax.set_axis_bgcolor(bgcolor)

    # set limits
    ax.axis('scaled')
    if xlimv != 'auto' and xlimv is not None:
        if isinstance(xlimv, tuple):
            ax.set_xlim(xlimv[0], xlimv[1])
        else:
            print 'nvis: setting xlimv'
            ax.set_xlim(-xlimv, xlimv)
    else:
        ax.set_xlim(np.min(xy[:, 0]) - 2.5, np.max(xy[:, 0]) + 2.5)

    if ylimv != 'auto' and ylimv is not None:
        if isinstance(ylimv, tuple):
            print 'nvis: setting ylimv to tuple'
            ax.set_ylim(ylimv[0], ylimv[1])
        else:
            ax.set_ylim(-ylimv, ylimv)
    else:
        print 'nvis: setting', min(xy[:, 1]), max(xy[:, 1])
        ax.set_ylim(np.min(xy[:, 1]) - 2, np.max(xy[:, 1]) + 2)

    if title is not None:
        ax.set_title(title, fontsize=fontsize)
    if text_topleft is not None:
        ax.text(0.05,
                .98,
                text_topleft,
                horizontalalignment='right',
                verticalalignment='top',
                transform=ax.transAxes)
    if axis_off:
        ax.axis('off')

    if fname != 'none' and fname != '' and fname is not None:
        print 'nvis: saving figure: ', fname
        plt.savefig(fname)
    if show:
        plt.show()

    return [ax, axcb]
Ejemplo n.º 10
0
def calc_kitaev_chern_from_evs(xy,
                               eigval,
                               eigvect,
                               cp,
                               pp=None,
                               check=False,
                               contributions=False,
                               verbose=False,
                               vis_exten='.png',
                               contrib_exten='.pdf',
                               delta=2. / 3.):
    """Compute the chern number for a gyro_lattice

    Parameters
    ----------
    xy : NP x 2 float array
        points of the gyro network
    eigval : 2NP x 1 complex array
        Eigenvalues of the system
    eigvect : 2NP x 2NP complex array
        Eigenvectors of the system
    pp : len(gyro_lattice.lattice.xy)*2 x len(gyro_lattice.lattice.xy)*2 complex array (optional)
        projection operator, if already calculated previously. If None, this function calculates this.
    check : bool (optional)
        Display intermediate results
    contributions : bool (optional)
        Compute the contribution of each individual particle to the chern result for the given summation regions
    verbose : bool (optional)
        Print more output on command line
    vis_exten : str ('.png', '.pdf', '.jpg', etc, default = '.png')
        Extension for the plotted output, if cp['save_ims'] == True
    contrib_exten : str ('.png', '.pdf', '.jpg', etc, default = '.pdf')
        Extension for the plotted contributions of each particle, if cp['save_ims'] == True and contributions==True

    Returns
    -------
    chern_finsize : len(cp['ksize_frac_arr']) x 6 complex array
        np.dstack((Nreg1V, ksize_frac_arr, ksize_V, ksys_sizeV, ksys_fracV, nuV))[0]
    params_regs : dict
        For each kitaev region size (ksize), there is a key '{0:0.3f}'.format(ksize) and value pair, of the form
        params_regs['{0:0.3f}'.format(ksize)] = {'reg1': reg1, 'reg2': reg2, 'reg3': reg3,
                                                 'polygon1': polygon1, 'polygon2': polygon2, 'polygon3': polygon3,
                                                 'reg1_xy': reg1_xy, 'reg2_xy': reg2_xy, 'reg3_xy': reg3_xy}
    contribs : dict or None
        If contributions == True, contribs is a dictionary with values storing the contributions to the chern result for
        each particle in reg1, reg2, and reg3. Contribs has keys which are '{0:0.3f}'.format(ksize) for each ksize, and
        each value of contribs['{0:0.3f}'.format(ksize)] is itself a dictionary with keys 'reg1', 'reg2', 'reg3' and
        values as the contributions of each particle, for particles indexed by reg1, 2, 3.
        ie, contribs['{0:0.3f}'.format(ksize)] = {'reg1': cb1, 'reg2': cb2, 'reg3': cb3}
        Here cb1,2,3 are (# particles in region n) x 1 complex arrays -- contributions of each particle in each region
        to the total result (when summed over the other two regions)
    """
    save_ims = cp['save_ims']
    modsave = cp['modsave']
    shape = cp['shape']
    ksize_frac_arr = cp['ksize_frac_arr']
    omegac = cp['omegac']
    if save_ims:
        # Register colormaps
        lecmaps.register_colormaps()
        imagedir = cp['cpmeshfn'] + 'visualization/'
        le.ensure_dir(imagedir)

    NP = len(xy)

    if pp is None:
        print 'Computing projector...'
        pp = calc_projector_from_evs(eigval, eigvect, omegac)

    # Initialize empty region index arrays for speedup by comparing with prev iteration
    reg1 = np.array([])
    reg2 = np.array([])
    reg3 = np.array([])
    nu = 0.0 + 0.0 * 1j
    epskick = 0.001 * np.random.rand(len(xy), 2)

    # Preallocate arrays
    nuV = np.zeros(len(ksize_frac_arr))
    Nreg1V = np.zeros(len(ksize_frac_arr))
    ksize_V = np.zeros(len(ksize_frac_arr))
    ksys_sizeV = np.zeros(len(ksize_frac_arr))
    ksys_fracV = np.zeros(len(ksize_frac_arr))
    params_regs = {}
    if contributions:
        contribs = {}
    else:
        contribs = None

    # Get max(width, height) of network
    maxsz = max(
        np.max(xy[:, 0]) - np.min(xy[:, 0]),
        np.max(xy[:, 1]) - np.min(xy[:, 1]))

    # If we want to look at individual contributions from each gyro, find h first
    if contributions and NP < 800:
        method = '2current'
        print 'constructing 2-current h_ijk...'
        hh = np.einsum('jk,kl,lj->jkl', pp, pp, pp) - np.einsum(
            'jl,lk,kj->jkl', pp, pp, pp)
        # hh = np.zeros((len(pp), len(pp), len(pp)), dtype=complex)
        # for j in range(len(pp)):
        #     for k in range(len(pp)):
        #         for l in range(len(pp)):
        #             hh[j, k, l] = pp[j, k] * pp[k, l] * pp[l, j] - pp[j, l] * pp[l, k] * pp[k, j]
        hh *= 12 * np.pi * 1j
    else:
        method = 'projector'

    jj = 0
    # for each ksize_frac, perform sum
    for kk in range(len(ksize_frac_arr)):
        ksize_frac = ksize_frac_arr[kk]
        ksize = ksize_frac * maxsz
        if verbose:
            print 'ksize = ', ksize

        polygon1, polygon2, polygon3 = kfns.get_kitaev_polygons(
            shape,
            cp['regalph'],
            cp['regbeta'],
            cp['reggamma'],
            ksize,
            delta_pi=delta,
            outerH=cp['outerH'])
        if cp['polyT']:
            polygon1 = np.fliplr(polygon1)
            polygon2_tmp = np.fliplr(polygon3)
            polygon3 = np.fliplr(polygon2)
            polygon2 = polygon2_tmp

        if cp['poly_offset'] != 'none' and cp['poly_offset'] is not None:
            if '/' in cp['poly_offset']:
                splitpo = cp['poly_offset'].split('/')
            else:
                splitpo = cp['poly_offset'].split('_')
            # print 'split_po = ', splitpo
            poly_offset = np.array([float(splitpo[0]), float(splitpo[1])])
            polygon1 += poly_offset
            polygon2 += poly_offset
            polygon3 += poly_offset

        # Save the previous reg1,2,3
        r1old = reg1
        r2old = reg2
        r3old = reg3

        reg1_xy = le.inds_in_polygon(xy + epskick, polygon1)
        reg2_xy = le.inds_in_polygon(xy + epskick, polygon2)
        reg3_xy = le.inds_in_polygon(xy + epskick, polygon3)

        if cp['basis'] == 'XY':
            reg1 = np.sort(np.vstack((2 * reg1_xy, 2 * reg1_xy + 1)).ravel())
            reg2 = np.sort(np.vstack((2 * reg2_xy, 2 * reg2_xy + 1)).ravel())
            reg3 = np.sort(np.vstack((2 * reg3_xy, 2 * reg3_xy + 1)).ravel())
        elif cp['basis'] == 'psi':
            if verbose:
                print 'stacking regions with right-moving selves...'
            reg1 = np.sort(np.vstack((reg1, NP + reg1)).ravel())
            reg2 = np.sort(np.vstack((reg2, NP + reg2)).ravel())
            reg3 = np.sort(np.vstack((reg3, NP + reg3)).ravel())

        if contributions:
            if method == '2current':
                nu, [cb1, cb2,
                     cb3] = kfns.sum_kitaev_with_contributions(reg1,
                                                               reg2,
                                                               reg3,
                                                               r1old,
                                                               r2old,
                                                               r3old,
                                                               hh,
                                                               nu,
                                                               verbose=verbose)
            else:
                nu, [cb1, cb2,
                     cb3] = kfns.sum_kitaev_with_contributions_projector(
                         reg1,
                         reg2,
                         reg3,
                         r1old,
                         r2old,
                         r3old,
                         pp,
                         nu,
                         verbose=verbose)
            contribs['{0:0.3f}'.format(ksize)] = {
                'reg1': cb1,
                'reg2': cb2,
                'reg3': cb3
            }
        else:
            nu = kfns.sum_kitaev_projector(reg1,
                                           reg2,
                                           reg3,
                                           r1old,
                                           r2old,
                                           r3old,
                                           pp,
                                           nu,
                                           verbose=verbose)

        # print 'nu = ', nu
        nuV[kk] = np.real(nu)
        Nreg1V[kk] = len(reg1)
        ksize_V[kk] = ksize
        ksys_sizeV[kk] = len(reg1) + len(reg2) + len(reg3)
        ksys_fracV[kk] = ksys_sizeV[kk] / len(xy)

        # Save regions
        params_regs['{0:0.3f}'.format(ksize)] = {
            'reg1': reg1,
            'reg2': reg2,
            'reg3': reg3,
            'polygon1': polygon1,
            'polygon2': polygon2,
            'polygon3': polygon3,
            'reg1_xy': reg1_xy,
            'reg2_xy': reg2_xy,
            'reg3_xy': reg3_xy
        }
        if save_ims and (kk % modsave == 0 or kk == (len(ksize_frac_arr) - 1)):
            plt.clf()
            filename = 'division_lattice_regions_{0:06d}'.format(
                jj) + vis_exten
            # title = r'Division of lattice: $\nu = ${0:0.3f}'.format(nu.real)
            # Commented out: plot just the regs and the title
            # plot_chern_realspace(gyro_lattice, reg1_xy, reg2_xy, reg3_xy, polygon1, polygon2, polygon3,
            #                     ax=None, outdir=imagedir, filename=filename, title=title, check=check)
            # New way: plot the regs with title plus curve of nu vs ksize
            kfns.plot_chern_realspace_2panel(xy,
                                             ksys_fracV,
                                             nuV,
                                             kk,
                                             reg1_xy,
                                             reg2_xy,
                                             reg3_xy,
                                             polygon1,
                                             polygon2,
                                             polygon3,
                                             outdir=imagedir,
                                             filename=filename,
                                             title='',
                                             check=check)

            if contributions:
                # Save plot of contributions from individual gyroscopes
                plt.clf()
                filename = 'contributions_ksize{0:0.3f}'.format(
                    ksize_frac) + contrib_exten
                kfns.plot_chern_contributions_experiment(xy,
                                                         reg1,
                                                         reg2,
                                                         reg3,
                                                         cb1,
                                                         cb2,
                                                         cb3,
                                                         polygon1,
                                                         polygon2,
                                                         polygon3,
                                                         basis=cp['basis'],
                                                         outdir=imagedir,
                                                         filename=filename)

            jj += 1

    if save_ims:
        movname = cp['cpmeshfn'] + 'visualization'
        imgname = imagedir + 'division_lattice_regions_'
        print 'glob.glob(imgname) = ', glob.glob(imgname + '*')
        print 'len(glob.glob(imgname)[0]) = ', len(glob.glob(imgname + '*'))
        framerate = float(len(glob.glob(imgname + '*'))) / 7.0
        print 'framerate = ', framerate
        subprocess.call([
            './ffmpeg', '-framerate',
            str(framerate), '-i', imgname + '%6d.png', movname + '.mov',
            '-vcodec', 'libx264', '-profile:v', 'main', '-crf', '12',
            '-threads', '0', '-r', '1', '-pix_fmt', 'yuv420p'
        ])

    chern_finsize = np.dstack(
        (Nreg1V, ksize_frac_arr, ksize_V, ksys_sizeV, ksys_fracV, nuV))[0]
    return chern_finsize, params_regs, contribs