From 9b6a64329d7f25ca21e64fec7064965d7a1bbc8e Mon Sep 17 00:00:00 2001 From: gcassella Date: Sat, 30 Jul 2022 12:43:01 +0100 Subject: [PATCH 1/2] Docconvert rest -> google --- src/koala/chern_number.py | 32 +++-- src/koala/example_graphs.py | 141 ++++++++++---------- src/koala/flux_finder/flux_finder.py | 57 ++++---- src/koala/flux_finder/pathfinding.py | 61 ++++----- src/koala/graph_color.py | 8 +- src/koala/graph_utils.py | 105 +++++++-------- src/koala/hamiltonian.py | 55 ++++---- src/koala/lattice.py | 190 +++++++++++++++------------ src/koala/phase_diagrams.py | 5 +- src/koala/phase_space.py | 49 +++---- src/koala/plotting.py | 166 +++++++++++------------ src/koala/voronization.py | 26 ++-- src/koala/weaire_thorpe.py | 3 +- 13 files changed, 466 insertions(+), 432 deletions(-) diff --git a/src/koala/chern_number.py b/src/koala/chern_number.py index 0e977a6..c9c7be8 100644 --- a/src/koala/chern_number.py +++ b/src/koala/chern_number.py @@ -5,14 +5,17 @@ def crosshair_marker(lattice: Lattice, projector: np.ndarray, crosshair_position: np.ndarray): """Generate the crosshair marker for a lattice and Hamiltonian - :param lattice: the lattice on which the Hamiltonian is placed - :type lattice: Lattice - :param projector: A projectro onto a set of occupied states - :type projector: np.ndarray - :param crosshair_position: the position of the crosshair in the bulk - :type crosshair_position: np.ndarray - :return: an array giving the marker value at every point in the system - :rtype: np.ndarray + Args: + lattice (Lattice): the lattice on which the Hamiltonian is + placed + projector (np.ndarray): A projectro onto a set of occupied + states + crosshair_position (np.ndarray): the position of the crosshair + in the bulk + + Returns: + np.ndarray: an array giving the marker value at every point in + the system """ @@ -28,12 +31,13 @@ def crosshair_marker(lattice: Lattice, projector: np.ndarray, crosshair_position def chern_marker(lattice: Lattice, projector: np.ndarray): """generate the Chern marker for the system - :param lattice: the lattice - :type lattice: Lattice - :param projector: a projector onto a set of occupied states - :type projector: np.ndarray - :return: the Chern marker value for each point in the system - :rtype: np.ndarray + Args: + lattice (Lattice): the lattice + projector (np.ndarray): a projector onto a set of occupied + states + + Returns: + np.ndarray: the Chern marker value for each point in the system """ positions = lattice.vertices.positions diff --git a/src/koala/example_graphs.py b/src/koala/example_graphs.py index 07bd7d7..91cd7f6 100644 --- a/src/koala/example_graphs.py +++ b/src/koala/example_graphs.py @@ -38,8 +38,7 @@ def tri_square_pent(): def tutte_graph(): - """ - Returns a tutte graph, a cubic graph with no Hamiltonian cycle, but is three-colorable. + """Returns a tutte graph, a cubic graph with no Hamiltonian cycle, but is three-colorable. Returns: vertices: np.array shape (nvertices, ndim) - A list of the positions of all the vertices that make up the graph @@ -182,12 +181,14 @@ def tutte_graph(): def n_ladder(n_sites: int, wobble=False): """Produces a strip-ladder type graph - good for testing if things work in strip geometry - :param n_sites: number of sites in the x-direction - :type n_sites: int - :param wobble: adds a sin wobble to the ladder shape - for testing if plaquettes come out that shouldnt be there, defaults to False - :type wobble: bool, optional - :return: a lattice for the ladder system - :rtype: Lattice + Args: + n_sites (int): number of sites in the x-direction + wobble (bool, optional): adds a sin wobble to the ladder shape - + for testing if plaquettes come out that shouldnt be there, + defaults to False + + Returns: + Lattice: a lattice for the ladder system """ x_positions = np.linspace(0.05, 0.95, n_sites) @@ -222,8 +223,8 @@ def n_ladder(n_sites: int, wobble=False): def multi_graph() -> Lattice: """Returns a graph with multiple edges between the same two sites - :return: A multiple-y connected graph - :rtype: Lattice + Returns: + Lattice: A multiple-y connected graph """ return Lattice( vertices=np.array([[0.5, 0.7], [0.5, 0.3]]), @@ -235,8 +236,8 @@ def multi_graph() -> Lattice: def bridge_graph(): """gives a simple example of a graph with a bridge - somethiing that could mess up the plaquette finder (but shouldnt any more!) - :return: A simple lattice with a bridge - :rtype: Lattice + Returns: + Lattice: A simple lattice with a bridge """ vertices = np.array( [[0.1, 0.2], [0.1, 0.8], [0.4, 0.5], [0.6, 0.5], [0.9, 0.8], [0.9, 0.2]] @@ -255,12 +256,15 @@ def generate_honeycomb(n_horizontal_cells: int, return_coloring=False) -> Lattic """Generates a regular honeycomb lattice with n_horizonta_cells number of cells in the x-direction, and a similar amount in the y direction but slightly fudged to fir a square system - :param n_horizontal_cells: number of cells wide you want the lattice - :type n_horizontal_cells: int - :param return_coloring: if True also returns a regular kitaev-style coloring for all the edges, defaults to False - :type return_coloring: bool, optional - :return: a lattice or a lattice and a coloring - :rtype: Lattice, np.ndarray (optional) + Args: + n_horizontal_cells (int): number of cells wide you want the + lattice + return_coloring (bool, optional): if True also returns a regular + kitaev-style coloring for all the edges, defaults to False + + Returns: + Lattice, np.ndarray (optional): a lattice or a lattice and a + coloring """ # define a basic unit cell with four sites @@ -382,10 +386,11 @@ def next_direction(n_horizontal, n_vertical, n, shift): def generate_hex_square_oct(n_cells: int) -> Lattice: """Generates a lattice containing squares, hexagons and octagons - :param n_cells: Number of unit cells in the x or y directions - :type n_cells: int - :return: the lattice object for this system - :rtype: Lattice + Args: + n_cells (int): Number of unit cells in the x or y directions + + Returns: + Lattice: the lattice object for this system """ site_coordinates = np.array( @@ -457,12 +462,16 @@ def next_direction(cells, n, shift): def generate_tri_non(n_cells, return_coloring=False): """generate a lattice of nonagons and triangles - :param n_cells: system dimensions. If an int is passed then the system is n_cells x n_cells. If an iterable is passed the system is n_cells[0] x n_cells[1] - :type n_cells: int or iter[int] - :param return_coloring: optional arg to return a coloring of the edges, defaults to False - :type return_coloring: bool, optional - :return: the lattice and optionally a coloring - :rtype: Lattice or Lattice, np.ndarray + Args: + n_cells (int or iter[int]): system dimensions. If an int is + passed then the system is n_cells x n_cells. If an iterable + is passed the system is n_cells[0] x n_cells[1] + return_coloring (bool, optional): optional arg to return a + coloring of the edges, defaults to False + + Returns: + Lattice or Lattice, np.ndarray: the lattice and optionally a + coloring """ unit_points = np.array([[0.4, 0.1], [0.1, 0.4], [0.4, 0.4], [0.6, 0.6]]) @@ -493,14 +502,11 @@ def generate_tri_non(n_cells, return_coloring=False): def _next_cell_number(n_horizontal, n_vertical, n, shift): """gives you the index of the next unit cell in the list of all unit cells - :param n_horizontal: number unit cells in x direction - :type n_horizontal: int - :param n_vertical: number of unit cells in y direction - :type n_vertical: int - :param n: what index you are currently at - :type n: int - :param shift: whoch way you want to shift to - :type shift: list + Args: + n_horizontal (int): number unit cells in x direction + n_vertical (int): number of unit cells in y direction + n (int): what index you are currently at + shift (list): whoch way you want to shift to """ y = n // n_horizontal new_y = (y + shift[1]) % n_vertical @@ -513,14 +519,11 @@ def _next_cell_number(n_horizontal, n_vertical, n, shift): def _crossing(n_x, n_y, n, shift): """tells you if the shift crosses PBC in the x or why direction - :param n_x: system size in x - :type n_x: int - :param n_y: system_size in y - :type n_y: int - :param n: what index you are currently at - :type n: int - :param shift: whoch way you want to shift to - :type shift: list + Args: + n_x (int): system size in x + n_y (int): system_size in y + n (int): what index you are currently at + shift (list): whoch way you want to shift to """ x = n % n_x @@ -545,18 +548,18 @@ def tile_unit_cell( ) -> Lattice: """given a description of a unit cell, this tiles it to make a full lattice - :param unit_points: coordinates of points in the unit cell - :type unit_points: np.ndarray - :param unit_edges: indices of edges in unit cell - :type unit_edges: np.ndarray - :param unit_crossing: whether the edges cross to the next unit cell in x and y direction - :type unit_crossing: np.ndarray - :param unit_cell_dimensions: size of unit cell - :type unit_cell_dimensions: np.ndarray - :param n_xy: number of tilings you want. if this is iterable then assume it has the form [nx, ny]. If an int then we assume we want [n,n] - :type n_xy: int or list - :return: the final lattice - :rtype: Lattice + Args: + unit_points (np.ndarray): coordinates of points in the unit cell + unit_edges (np.ndarray): indices of edges in unit cell + unit_crossing (np.ndarray): whether the edges cross to the next + unit cell in x and y direction + unit_cell_dimensions (np.ndarray): size of unit cell + n_xy (int or list): number of tilings you want. if this is + iterable then assume it has the form [nx, ny]. If an int + then we assume we want [n,n] + + Returns: + Lattice: the final lattice """ try: @@ -606,11 +609,14 @@ def tile_unit_cell( def single_plaquette(n_sides: int) -> Lattice: """Makes a graph consisting of a single plaquette with n_sides sides - :param n_sides: how many sides the polygon should have - :type n_sides: int - :raises Exception: n_sides must be >2 - :return: a lattice containing a single polygon - :rtype: Lattice + Args: + n_sides (int): how many sides the polygon should have + + Raises: + Exception: n_sides must be >2 + + Returns: + Lattice: a lattice containing a single polygon """ if n_sides < 3: @@ -656,14 +662,13 @@ def make_amorphous( ): """Makes an amorphous lattice with L**2 plaquettes - :param L: The lattice will have L**2 plaquettes - :type L: int + Args: + L (int): The lattice will have L**2 plaquettes + return_points (bool): if True returns Lattice, coloring, ground + state ujk, original_random_points - :param return_points: if True returns Lattice, coloring, ground state ujk, original_random_points - :type return_points: bool - - :return: Lattice, coloring, ground state ujk - :rtype: Lattice + Returns: + Lattice: Lattice, coloring, ground state ujk """ if rng is None: rng = np.random.default_rng() diff --git a/src/koala/flux_finder/flux_finder.py b/src/koala/flux_finder/flux_finder.py index 6371f9d..508d4f0 100644 --- a/src/koala/flux_finder/flux_finder.py +++ b/src/koala/flux_finder/flux_finder.py @@ -4,17 +4,16 @@ from .pathfinding import straight_line_length, periodic_straight_line_length, path_between_plaquettes def fluxes_from_bonds(l, bonds, real = True) -> np.ndarray: - """ - Given a lattice l and a set of bonds = +/-1 defined on the edges of the lattice, calculate the fluxes. + """Given a lattice l and a set of bonds = +/-1 defined on the edges of the lattice, calculate the fluxes. The fluxes are defined on each plaquette as the the product of each bond in the direction, with the sign fliped otherwise. - :param l: The lattice. - :type l: Lattice - :param bonds: The bond variables +1 or -1 - :type bonds: np.ndarray - :return: fluxes - :rtype: np.ndarray + Args: + l (Lattice): The lattice. + bonds (np.ndarray): The bond variables +1 or -1 + + Returns: + np.ndarray: fluxes """ fluxes = np.zeros(len(l.plaquettes), dtype = 'int') if real else np.zeros(len(l.plaquettes), dtype = 'complex') @@ -36,11 +35,12 @@ def fluxes_from_bonds(l, bonds, real = True) -> np.ndarray: def fluxes_to_labels(fluxes: np.ndarray) -> np.ndarray: """Remaps fluxes from the set {1,-1} to labels in the form {0,1} for plotting. - :param fluxes: Fluxes in the format +1 or -1 - :type fluxes: np.ndarray - :return: labels in [0,1] - :rtype: np.ndarray - """ + Args: + fluxes (np.ndarray): Fluxes in the format +1 or -1 + + Returns: + np.ndarray: labels in [0,1] + """ return ((1 - fluxes)//2).astype(np.int8) def _random_bonds(l : Lattice) -> np.ndarray: @@ -61,8 +61,7 @@ def _greedy_plaquette_pairing(plaquettes, distance_func): return np.array(pairs) def _flip_adjacent_fluxes(l : Lattice, bonds : np.ndarray, fluxes : np.ndarray): - """ - See docs for find_flux_sector, this helper method implements step 2) + """See docs for find_flux_sector, this helper method implements step 2) which is that it looks for adjacent -1 fluxes and flips their edges """ for edge_index, (p_a, p_b) in enumerate(l.edges.adjacent_plaquettes): @@ -82,9 +81,7 @@ def _flip_adjacent_fluxes(l : Lattice, bonds : np.ndarray, fluxes : np.ndarray): return bonds, fluxes def _flip_isolated_fluxes(l : Lattice, bonds : np.ndarray, fluxes : np.ndarray): - """ - See docs for find_flux_sector, this helper method implements step 3-5) - """ + """See docs for find_flux_sector, this helper method implements step 3-5)""" indices_to_flip = np.where(fluxes == -1)[0] def pos(p): return l.plaquettes[p].center @@ -102,16 +99,15 @@ def distance_func(a,b): return straight_line_length(pos(a), pos(b)) def find_flux_sector(l: Lattice, target_flux_sector : np.ndarray = None, initial_bond_guess : np.ndarray = None, ): - """ - Find a bond configuration that produces the given flux sector for the lattice l. - + """Find a bond configuration that produces the given flux sector for the lattice l. + The high level method is: 1) Figure out which fluxes need to flip using fluxes_to_flip = target_flux_sector / initial_flux_sector 2) Look for any adjacent -1 fluxes in fluxes_to_flip that can be anhilated by just flipping 1 edge. 3) Pair the remaining fluxes off into close-ish pairs 4) Use A* to find a path between each pair. 5) Flip all the edges along each path. - + Where: A bond configuration is an assignment of +/-1 to each bond. A flux sector is an assignment of +/-1 to even plaquette and +/-i to odd plaquettes. @@ -145,14 +141,15 @@ def find_flux_sector(l: Lattice, target_flux_sector : np.ndarray = None, def n_to_ujk_flipped(n: int, ujk: np.ndarray, min_spanning_set: np.ndarray): """given an integer n in the 0 - 2^(number of edges in spanning tree), this code flips the edges of ujk in the spanning tree in the combination given by the binary representation of n. Useful for exhaustively searching over the entire flux space of a lattice. - :param n: number determining the flip configuration - :type n: int - :param ujk: the edge signs of the wholelattice - :type ujk: np.ndarray( ±1 ) - :param min_spanning_set: an array containing a minimum set of edges that form a plaquete-spanning tree on the system - :type min_spanning_set: np.ndarray( int ) - :return: a flipped set of ujk - :rtype: np.ndarray( ±1 ) + Args: + n (int): number determining the flip configuration + ujk (np.ndarray( ±1 )): the edge signs of the wholelattice + min_spanning_set (np.ndarray( int )): an array containing a + minimum set of edges that form a plaquete-spanning tree on + the system + + Returns: + np.ndarray( ±1 ): a flipped set of ujk """ n_in_tree = len(min_spanning_set) str_format = '0' + str(n_in_tree) + 'b' diff --git a/src/koala/flux_finder/pathfinding.py b/src/koala/flux_finder/pathfinding.py index 40342aa..d286f85 100644 --- a/src/koala/flux_finder/pathfinding.py +++ b/src/koala/flux_finder/pathfinding.py @@ -77,21 +77,22 @@ def path_between_plaquettes(l : Lattice, start : int, goal : int, If early_stopping = True it's probably still pretty short but it stops as soon as it finds a path. The heuristic function must give a lower bound on the distance, it could be swapped out for a periodic one for instance. - :param l: The lattice to pathfind on. - :type l: Lattice - :param start: The index of the plaquette to start from. - :type start: int - :param goal: The index of the plaquette to go to. - :type goal: int - :param heuristic: The distance metric (and periodicity) to use, defaults to straight_line_length - :type heuristic: function - :param early_stopping: If True, return as soon as a path is found, defaults to True - :type early_stopping: bool, optional - :param maxits: How many iterations to do before giving up, defaults to 1000 - :type maxits: int, optional - :return: plaquettes, edges, lists of plaquettes visited by a path and the indices of the edges used to get there. - :rtype: Tuple[array, array] - """ + Args: + l (Lattice): The lattice to pathfind on. + start (int): The index of the plaquette to start from. + goal (int): The index of the plaquette to go to. + heuristic (function): The distance metric (and periodicity) to + use, defaults to straight_line_length + early_stopping (bool, optional): If True, return as soon as a + path is found, defaults to True + maxits (int, optional): How many iterations to do before giving + up, defaults to 1000 + + Returns: + Tuple[array, array]: plaquettes, edges, lists of plaquettes + visited by a path and the indices of the edges used to get + there. + """ # all information about the graph is stored in the adjacency(a) and heuristic(a,b) functions def adjacency(a): return adjacent_plaquettes(l, a) def pos(p): return l.plaquettes[p].center @@ -112,21 +113,21 @@ def path_between_vertices(l : Lattice, start : int, goal : int, If early_stopping = True it's probably still pretty short but it stops as soon as it finds a path. The heuristic function must give a lower bound on the distance, it could be swapped out for a periodic one for instance. - :param l: The lattice to pathfind on. - :type l: Lattice - :param start: The index of the vertex to start from. - :type start: int - :param goal: The index of the vertex to go to. - :type goal: int - :param heuristic: The distance metric (and periodicity) to use, defaults to straight_line_length - :type heuristic: function - :param early_stopping: If True, return as soon as a path is found, defaults to True - :type early_stopping: bool, optional - :param maxits: How many iterations to do before giving up, defaults to 1000 - :type maxits: int, optional - :return: vertices, edges, lists of vertices visited by a path and the indices of the edges used to get there. - :rtype: Tuple[array, array] - """ + Args: + l (Lattice): The lattice to pathfind on. + start (int): The index of the vertex to start from. + goal (int): The index of the vertex to go to. + heuristic (function): The distance metric (and periodicity) to + use, defaults to straight_line_length + early_stopping (bool, optional): If True, return as soon as a + path is found, defaults to True + maxits (int, optional): How many iterations to do before giving + up, defaults to 1000 + + Returns: + Tuple[array, array]: vertices, edges, lists of vertices visited + by a path and the indices of the edges used to get there. + """ def adjacency(a): return adjacent_vertices(l, a) def pos(a): return l.vertices.positions[a] diff --git a/src/koala/graph_color.py b/src/koala/graph_color.py index 224f7e9..e97f99d 100644 --- a/src/koala/graph_color.py +++ b/src/koala/graph_color.py @@ -58,7 +58,7 @@ def vertex_color(adjacency: np.ndarray, n_colors:int = 4, all_solutions = False): """Return a coloring of the vertices using n_colors. - Note the code assumes that all vertices actually appear in the adjacency list + Note the code assumes that all vertices actually appear in the adjacency list because it calculates n_vertices = np.max(adjacency) + 1 Args: @@ -183,9 +183,9 @@ def color_lattice(lattice: Lattice): """Return an asignment of one of 3 labels to each lattice edge such that mp edges with the same label meet at a vertex. If such a coloring cannot be found raises a ValueError. - :param Lattice: The lattice to color. - :type Lattice: lattice - """ + Args: + Lattice (lattice): The lattice to color. + """ #fix the coloring to be clockwise about vertex 0 fixed = enumerate(clockwise_edges_about(vertex_i = 0, g=lattice)) solveable, solution = edge_color(lattice, n_colors = 3, fixed = fixed) diff --git a/src/koala/graph_utils.py b/src/koala/graph_utils.py index 6043dd2..0268947 100644 --- a/src/koala/graph_utils.py +++ b/src/koala/graph_utils.py @@ -8,16 +8,17 @@ def plaquette_spanning_tree(lattice: Lattice, shortest_edges_only = True): """Given a lattice this returns a list of edges that form a spanning tree over all the plaquettes (aka a spanning tree of the dual lattice!) - The optional argument shortest_edge_only automatically sorts the edges to ensure that only the shortest connections are used - (which is kind of a fudgey way of stopping the algorithm from picking edges that connect over the periodic boundaries). If you're hungry for + The optional argument shortest_edge_only automatically sorts the edges to ensure that only the shortest connections are used + (which is kind of a fudgey way of stopping the algorithm from picking edges that connect over the periodic boundaries). If you're hungry for speed you might want to turn it off. The algorith is basically prim's algorithm - so it should run in linear time. - :param lattice: the lattice you want the tree on - :type lattice: Lattice - :param shortest_edges_only: do you want a minimum spanning tree - distance wise, defaults to True - :type shortest_edges_only: bool, optional - :return: a list of the edges that form the tree - :rtype: np.ndarray + Args: + lattice (Lattice): the lattice you want the tree on + shortest_edges_only (bool, optional): do you want a minimum + spanning tree - distance wise, defaults to True + + Returns: + np.ndarray: a list of the edges that form the tree """ plaquettes_in = np.full(lattice.n_plaquettes, -1) edges_in = np.full(lattice.n_plaquettes-1, -1) @@ -80,17 +81,16 @@ def find_plaq_distance(edge): # FIXME: change function signature to take lattice object instead of adjacency list def vertex_neighbours(lattice, vertex_i): - """ - Return the neighbouring nodes of a point + """Return the neighbouring nodes of a point Args: vertex_i: int the index into vertices of the node we want the neighbours of adjacency: (M, 2) A list of pairs of vertices representing edges Returns: vertex_indices: (k), the indices into vertices of the neighbours - edge_indices: (k), the indices into adjacency of the edges that link vertex_i to its neighbours - - Note that previous version of this function broke the expectation that edge_indices[i] is the edge that links + edge_indices: (k), the indices into adjacency of the edges that link vertex_i to its neighbours + + Note that previous version of this function broke the expectation that edge_indices[i] is the edge that links vertex_i to vertex_indices[i], make sure to preserve this property. """ adjacency = lattice.edges.indices @@ -108,15 +108,16 @@ def vertex_neighbours(lattice, vertex_i): return vertex_indices, edge_indices def edge_neighbours(lattice, edge_i): - """ - Return the neighbouring edges of an edge (the edges connected to the same nodes as this edge) - - :param lattice: The lattice - :type lattice: Lattice - :param edge_i: the index of the edge we want the neighbours of - :type edge_i: integer - :return: edge_indices: (k), the indices into adjacency of the edges that link vertex_i to its neighbours - :rtype: np.ndarray (k,) + """Return the neighbouring edges of an edge (the edges connected to the same nodes as this edge) + + Args: + lattice (Lattice): The lattice + edge_i (integer): the index of the edge we want the neighbours + of + + Returns: + np.ndarray (k,): edge_indices: (k), the indices into adjacency + of the edges that link vertex_i to its neighbours """ edge = lattice.edges.indices[edge_i] v1 = edge[0] @@ -126,15 +127,14 @@ def edge_neighbours(lattice, edge_i): return np.where(mask)[0] def clockwise_about(vertex_i : int, g : Lattice) -> np.ndarray: - """ - Finds the vertices/edges that border vertex_i, order them clockwise starting from the positive x axis + """Finds the vertices/edges that border vertex_i, order them clockwise starting from the positive x axis and returns those indices in order. Args: vertex_i (int): int the index into g.vertices.positions of the node we want to use. Generally use 0 g (Lattice): a graph object with keys vertices, adjacency, adjacency_crossing Returns: - ordered_edge_indices: np.ndarray (n_neighbours_of_vertex_i) ordered indices of the edges. + ordered_edge_indices: np.ndarray (n_neighbours_of_vertex_i) ordered indices of the edges. """ #get the edges and vertices around vertex 0 vertex_indices, edge_indices = vertex_neighbours(g, vertex_i) @@ -149,28 +149,26 @@ def clockwise_about(vertex_i : int, g : Lattice) -> np.ndarray: return ordered_vertex_indices, ordered_edge_indices def clockwise_edges_about(vertex_i : int, g : Lattice) -> np.ndarray: - """ - Finds the edges that border vertex_i, orders them clockwise starting from the positive x axis + """Finds the edges that border vertex_i, orders them clockwise starting from the positive x axis and returns those indices in order. Use this to break the degeneracy of graph coloring. Args: vertex_i (int): int the index into g.vertices.positions of the node we want to use. Generally use 0 g (Lattice): a graph object with keys vertices, adjacency, adjacency_crossing Returns: - ordered_edge_indices: np.ndarray (n_neighbours_of_vertex_i) ordered indices of the edges. + ordered_edge_indices: np.ndarray (n_neighbours_of_vertex_i) ordered indices of the edges. """ return clockwise_about(vertex_i, g)[1] def get_edge_vectors(vertex_i : int, edge_indices : np.ndarray, l : Lattice) -> np.ndarray: - """ - Get the vector starting from vertex_i along edge_i, taking into account boundary conditions + """Get the vector starting from vertex_i along edge_i, taking into account boundary conditions Args: vertex_i (int): the index of the vertex edge_i (int): the index of the edge lattice (Lattice): the lattice to use Returns: - np.ndarray (2,): + np.ndarray (2,): """ #this is a bit nontrivial, g.adjacency_crossing tells us if the edge crossed into another unit cell but #it is directional, hence we need to check for each edge if vertex_i was the first of second vertex stored @@ -187,13 +185,14 @@ def adjacent_plaquettes(l : Lattice, p_index : int) -> Tuple[np.ndarray, np.ndar """For a given lattice, compute the plaquettes that share an edge with lattice.plaquettes[p_index] and the shared edge. Returns a list of plaquettes indices and a matching list of edge indices. - :param l: The lattice. - :type l: Lattice - :param p_index: The index of the plaquette to find the neighbours of. - :type p_index: int - :return: (plaque_indices, edge_indices) - :rtype: Tuple[np.ndarray, np.ndarray] - """ + Args: + l (Lattice): The lattice. + p_index (int): The index of the plaquette to find the neighbours + of. + + Returns: + Tuple[np.ndarray, np.ndarray]: (plaque_indices, edge_indices) + """ p = l.plaquettes[p_index] edges = p.edges neighbouring_plaquettes = l.edges.adjacent_plaquettes[edges] @@ -221,14 +220,15 @@ def rotate(vector, angle): def edge_crossing_that_minimises_length(start, end): """Given two points in the unit plane, return the edge crossing = [-1/0/+1, -1/0/+1,] that minimises the length of the edge between them. - + :param: start: The start point of the edge :type: np.ndarray shape (2,) :param: end: The start point of the edge :type: np.ndarray shape (2,) - :return: The edge crossing that minimises the length of the edge. - :rtype: np.ndarray shape (2,) + Returns: + np.ndarray shape (2,): The edge crossing that minimises the + length of the edge. """ if np.linalg.norm(start - end, ord = 2) < 0.5: return np.array([0,0]) crossings = np.array(list(itertools.product([-1,0,1], repeat = 2))) @@ -236,17 +236,16 @@ def edge_crossing_that_minimises_length(start, end): return crossings[np.argmin(lengths)] def make_dual(lattice, subset = slice(None, None)): - """ - Given a lattice and a subset of its edge, contruct the dual lattice + """Given a lattice and a subset of its edge, contruct the dual lattice and return it as a new Lattice object. - :param lattice: The lattice to make the dual of. - :type lattice: Lattice - :param subset: The edges to include in the dual. - :type subset: slice, boolean array, or integer indices. + Args: + lattice (Lattice): The lattice to make the dual of. + subset (slice, boolean array, or integer indices.): The edges to + include in the dual. - :return: The dual lattice. - :rtype: Lattice + Returns: + Lattice: The dual lattice. """ subset = np.arange(lattice.n_edges, dtype = int)[subset] st_edges = np.array([lattice.edges.adjacent_plaquettes[i] for i in subset]) @@ -261,8 +260,7 @@ def plaquette_index_to_center(i): return lattice.plaquettes[i].center from scipy.sparse import csgraph def sparse_adjacency(lattice: Lattice): - """ - Create a sparse (dok_matrix) adjacency matrix from a Lattice object. + """Create a sparse (dok_matrix) adjacency matrix from a Lattice object. Useful to use a Lattice object as input to a scipy.sparse.csgraph routine. """ adj = sparse.dok_matrix((lattice.n_vertices, lattice.n_vertices)) @@ -271,8 +269,7 @@ def sparse_adjacency(lattice: Lattice): return adj def edge_to_index_mapper(lattice: Lattice): - """ - This returns a map where k = map[i,j] tells you the index k of an edge (i,j) + """This returns a map where k = map[i,j] tells you the index k of an edge (i,j) The order of (i,j) or (j,i) doesn't matter. Useful to convert back from the output of a scipy.sparse.csgraph routine. """ @@ -288,7 +285,7 @@ def adjacency_to_edgelist(adj): def minimum_spanning_tree(lattice : Lattice): """" - Use scipy.sparse.csgraph.minimum_spanning_tree to find a + Use scipy.sparse.csgraph.minimum_spanning_tree to find a minimum spanning tree of the given lattice. """ adjacency = sparse_adjacency(lattice) diff --git a/src/koala/hamiltonian.py b/src/koala/hamiltonian.py index e2864b4..c5670c4 100644 --- a/src/koala/hamiltonian.py +++ b/src/koala/hamiltonian.py @@ -5,16 +5,16 @@ def bisect_lattice(l: Lattice, solution: npt.NDArray[np.integer], along: int = 0) -> npt.NDArray[np.integer]: """Generate a new lattice with vertex indices permuted such that the first nvert/2 entries are in sublattice A and the rest are in sublattice B, according to the given coloring `solution` - - :param l: Non-bisected lattice - :type l: Lattice - :param solution: Edge coloring of `l` - :type solution: npt.NDArray[np.integer] Shape (nedges,) - :param along: Bond type along which to dimerize the system - :type along: int - :return: Bisected lattice - :rtype: Lattice - """ + + Args: + l (Lattice): Non-bisected lattice + solution (npt.NDArray[np.integer] Shape (nedges,)): Edge coloring + of `l` + along (int): Bond type along which to dimerize the system + + Returns: + Lattice: Bisected lattice + """ # Label each vertex in lattice g as belonging to A or B sublattice, according to the coloring # given by solution. By default, the first entry in solution will define the flavor of bond along # which the lattice is 'dimerized' to form the sublattices. @@ -37,17 +37,19 @@ def generate_majorana_hamiltonian(l: Lattice, coloring: npt.NDArray, ujk: npt.ND to the vertex indices in the Lattice object. This is the quadratic Majorana Hamiltonian of eqn (13) in Kitaev's paper. - :param l: Lattice to construct Hamiltonian on, from which nearest bond-sharing vertices are determined - :type l: Lattice - :param coloring: Edge coloring of `l` - :type coloring: npt.NDArray[np.integer] Shape (lattice.n_edges,) - :param J: Coupling parameter for Kitaev model, defaults to 1.0 - :type J: npt.NDArray[np.floating] or float - :param ujk: Link variables, with value +1 or -1 + Args: + l (Lattice): Lattice to construct Hamiltonian on, from which + nearest bond-sharing vertices are determined + coloring (npt.NDArray[np.integer] Shape (lattice.n_edges,)): Edge + coloring of `l` + J (npt.NDArray[np.floating] or float): Coupling parameter for + Kitaev model, defaults to 1.0 + ujk: Link variables, with value +1 or -1 - :return: Quadratic Majorana Hamiltonian matrix representation in Majorana basis - :rtype: npt.NDArray - """ + Returns: + npt.NDArray: Quadratic Majorana Hamiltonian matrix representation + in Majorana basis + """ ham = np.zeros((l.n_vertices, l.n_vertices)) Js = J[coloring] if coloring is not None else J[0] hoppings = 2*Js*ujk @@ -64,11 +66,14 @@ def majorana_to_fermion_ham(majorana_ham: npt.NDArray[np.complexfloating]) -> np will be dictated by the sublattice layout of the Majoranas. Elements of the A(B) sublattice correspond to the first(second) half of the Majorana indices. - :param majorana_ham: (nvert,nvert) matrix representation of Hamiltonian in Majorana basis - :type majorana_ham: npt.NDArray[np.complexfloating] - :return: (nvert,nvert) matrix representation of Hamiltonian in Fermion basis - :rtype: npt.NDArray[np.complexfloating] - """ + Args: + majorana_ham (npt.NDArray[np.complexfloating]): (nvert,nvert) + matrix representation of Hamiltonian in Majorana basis + + Returns: + npt.NDArray[np.complexfloating]: (nvert,nvert) matrix + representation of Hamiltonian in Fermion basis + """ sublat_size = majorana_ham.shape[0] // 2 F = -1.0j*majorana_ham[:sublat_size, :sublat_size] D = -1*-1.0j*majorana_ham[sublat_size:, sublat_size:] diff --git a/src/koala/lattice.py b/src/koala/lattice.py index edfd614..dc4fda6 100644 --- a/src/koala/lattice.py +++ b/src/koala/lattice.py @@ -13,19 +13,23 @@ class LatticeException(Exception): class Plaquette: """Represents a single plaquette in a lattice. Not a list since plaquettes can have varying size. - :param vertices: Indices correspondng to the vertices that border the plaquette. These are always organised to start from the lowest index and then go clockwise around the plaquette - :type vertices: np.ndarray[int] (n_sides) - :param edges: Indices correspondng to the edges that border the plaquette. These are arranged to start from the lowest indexed vertex and progress clockwise. - :type edges: np.ndarray[int] (n_sides) - :param directions: Valued +1,-1 depending on whether the i'th edge points clockwise/anticlockwise around the plaquette - :type directions: np.ndarray[int] (n_sides) - :param centers: Coordinates of the center of the plaquette - :type centers: np.ndarray[float] (2) - :param n_sides: Number of sides to the plaquette - :type n_sides: int - :param adjacent_plaquettes: Indices of all the plaquettes that share an edge with this one, ordered in the same order as the plaquette edges - :type adjacent_plaquettes: np.ndarray[int] (n_sides) - + Args: + vertices (np.ndarray[int] (n_sides)): Indices correspondng to + the vertices that border the plaquette. These are always + organised to start from the lowest index and then go + clockwise around the plaquette + edges (np.ndarray[int] (n_sides)): Indices correspondng to the + edges that border the plaquette. These are arranged to start + from the lowest indexed vertex and progress clockwise. + directions (np.ndarray[int] (n_sides)): Valued +1,-1 depending + on whether the i'th edge points clockwise/anticlockwise + around the plaquette + centers (np.ndarray[float] (2)): Coordinates of the center of + the plaquette + n_sides (int): Number of sides to the plaquette + adjacent_plaquettes (np.ndarray[int] (n_sides)): Indices of all + the plaquettes that share an edge with this one, ordered in + the same order as the plaquette edges """ vertices: np.ndarray edges: np.ndarray @@ -37,17 +41,18 @@ class Plaquette: @dataclass(frozen=True) class Edges: - """ - Represents the list of edges in the lattice - - :param indices: Indices of points connected by each edge. - :type indices: np.ndarray[int] (nedges, 2) - :param vectors: Vectors pointing along each edge - :type vectors: np.ndarray[float] (nedges, 2) - :param crossing: Tells you whether the edge crosses the boundary conditions, and if so, in which direction. One value for x-direction and one for y-direction - :type crossing: np.ndarray[int] (nedges, 2) - :param adjacent_plaquettes: Lists the indices of every plaquette that touches each edge - :type adjacent_plaquettes: np.ndarray[int] (nedges, 2) + """Represents the list of edges in the lattice + + Args: + indices (np.ndarray[int] (nedges, 2)): Indices of points + connected by each edge. + vectors (np.ndarray[float] (nedges, 2)): Vectors pointing along + each edge + crossing (np.ndarray[int] (nedges, 2)): Tells you whether the + edge crosses the boundary conditions, and if so, in which + direction. One value for x-direction and one for y-direction + adjacent_plaquettes (np.ndarray[int] (nedges, 2)): Lists the + indices of every plaquette that touches each edge """ indices: np.ndarray @@ -67,15 +72,16 @@ def adjacent_plaquettes(self) -> np.ndarray: @dataclass(frozen=True) class Vertices: - """ - Represents a list of vertices in the lattice - - :param positions: List of the positions of every vertex - :type positions: np.ndarray[float] (nvertices, 2) - :param adjacent_edges: Lists the indices of every edge that connects to that vertex. Listed in clockwise order from the lowest index - :type adjacent_edges: list[np.ndarray] (nvertices, n_edges_per_vertex) - :param adjacent_plaquettes: Lists the indices of every plaquette that touches the vertex - :type adjacent_plaquettes: np.ndarray[int] (nvertices, 3) + """Represents a list of vertices in the lattice + + Args: + positions (np.ndarray[float] (nvertices, 2)): List of the + positions of every vertex + adjacent_edges (list[np.ndarray] (nvertices, n_edges_per_vertex)): + Lists the indices of every edge that connects to that + vertex. Listed in clockwise order from the lowest index + adjacent_plaquettes (np.ndarray[int] (nvertices, 3)): Lists the + indices of every plaquette that touches the vertex """ positions: np.ndarray @@ -94,16 +100,19 @@ def adjacent_plaquettes(self) -> np.ndarray: class Lattice(object): """Data structure containing information about a lattice consisting of vertices in real space connected by undirected edges. - :param vertices: Data structure containing vertex positions, and the edges/plaquettes touching each vertex - :type vertices: Vertices - :param edges: Data structure containing indices of vertices comprising each edge, the spatial displacement vectors - corresponding to those edges, flags for edges which cross the system boundary in periodic Lattices, and the plaquettes - touching each edge. - :type edges: Edges - :param plaquettes: All of the polygons (aka plaquettes) comprising the lattice, specifying their constituent vertices, edges, - winding directions, and centers. - :type plaquettes: list[Plaquette] - """ + Args: + vertices (Vertices): Data structure containing vertex positions, + and the edges/plaquettes touching each vertex + edges (Edges): Data structure containing indices of vertices + comprising each edge, the spatial displacement vectors + corresponding to those edges, flags for edges which cross + the system boundary in periodic Lattices, and the plaquettes + touching each edge. + plaquettes (list[Plaquette]): All of the polygons (aka + plaquettes) comprising the lattice, specifying their + constituent vertices, edges, winding directions, and + centers. + """ def __init__( self, vertices: npt.NDArray[np.floating], @@ -113,15 +122,18 @@ def __init__( ): """Constructor for Lattices - :param vertices: Spatial locations of lattice vertices - :type vertices: npt.NDArray[np.floating] Shape (nverts, 2) - :param edge_indices: Indices corresponding to the vertices which each edge connects - :type edge_indices: npt.NDArray[np.integer] Shape (nedges, 2) - :param edge_crossing: Flags describing which boundaries of the system each edge crosses in periodic boundary conditions. + Args: + vertices (npt.NDArray[np.floating] Shape (nverts, 2)): + Spatial locations of lattice vertices + edge_indices (npt.NDArray[np.integer] Shape (nedges, 2)): + Indices corresponding to the vertices which each edge + connects + edge_crossing (npt.NDArray[np.integer] Shape (nedges, 2)): + Flags describing which boundaries of the system each + edge crosses in periodic boundary conditions. Each entry in the final axis corresponds to a spatial dimension, 1(-1) denotes an edge crossing a boundary in the positive (negative) direction along that dimension. 0 corresponds to no boundary crossing. - :type edge_crossing: npt.NDArray[np.integer] Shape (nedges, 2) - """ + """ # calculate the vector corresponding to each edge edge_vectors = (vertices[edge_indices][:, 1] - @@ -231,17 +243,21 @@ def _sorted_vertex_adjacent_edges( vertex_positions, edge_indices, edge_vectors): - """Gives you an array where the i'th row contains the indices of the edges that connect to the i'th vertex. + """Gives you an array where the i'th row contains the indices of the edges that connect to the i'th vertex. The edges are always organised in clockwise order starting from 12:00, which will be handy later ;) - :param vertex_positions: List of the positions of every vertex - :type vertex_positions: np.ndarray[float] (nvertices, 2) - :param edge_indices: Indices of points connected by each edge. - :type edge_indices: np.ndarray[int] (nedges, 2) - :param edge_vectors: Vectors pointing along each edge - :type edge_vectors: np.ndarray[float] (nedges, 2) - :return: List containing the indices of the edges that connect to each point, ordered clockwise around the point. - :rtype: list[int] (nvertices, nedges_per_vertex) + Args: + vertex_positions (np.ndarray[float] (nvertices, 2)): List of the + positions of every vertex + edge_indices (np.ndarray[int] (nedges, 2)): Indices of points + connected by each edge. + edge_vectors (np.ndarray[float] (nedges, 2)): Vectors pointing + along each edge + + Returns: + list[int] (nvertices, nedges_per_vertex): List containing the + indices of the edges that connect to each point, ordered + clockwise around the point. """ # sorts these lists to make sure that they always are ordered clockwise from 12:00 like on a clock face @@ -275,17 +291,18 @@ def _find_plaquette( starting_edge: int, starting_direction: int, l: Lattice): - """Given a single edge, and a direction, this code finds the plaquette corresponding to starting in that + """Given a single edge, and a direction, this code finds the plaquette corresponding to starting in that direction and only taking left turns. This means plaquettes are ordered anticlockwise - which amounts to going round each vertex clockwise. - :param starting_edge: Index of the edge where you start - :type starting_edge: int - :param starting_direction: Direction to take the first step. +1 means the same direction as the edge, -1 means opposite - :type starting_direction: int (+1 or -1) - :param l: Lattice to be searched for the plaquette - :type l: Lattice - :return: A plaquette object representing the found plaquette - :rtype: Plaquette + Args: + starting_edge (int): Index of the edge where you start + starting_direction (int (+1 or -1)): Direction to take the first + step. +1 means the same direction as the edge, -1 means + opposite + l (Lattice): Lattice to be searched for the plaquette + + Returns: + Plaquette: A plaquette object representing the found plaquette """ edge_indices = l.edges.indices @@ -377,10 +394,11 @@ def _find_plaquette( def _find_all_plaquettes(l: Lattice): """Construct a list of Plaquette objects, representing all of the polygons in the lattice. - :param l: Lattice whose plaquettes are to be found - :type l: Lattice - :return: List of all plaquettes in the lattice - :rtype: list[Plaquette] + Args: + l (Lattice): Lattice whose plaquettes are to be found + + Returns: + list[Plaquette]: List of all plaquettes in the lattice """ edge_indices = l.edges.indices @@ -415,12 +433,13 @@ def permute_vertices(l: Lattice, ordering: npt.NDArray[np.integer]) -> Lattice: """Create a new lattice with the vertex indices rearranged according to ordering, such that new_l.vertices[i] = l.vertices[ordering[i]]. - :param l: Original lattice to have vertices reordered - :type l: Lattice - :param ordering: Permutation of vertex ordering, i = ordering[i'] - :type ordering: npt.NDArray[np.integer] - :return: New lattice object with permuted vertex indices - :rtype: Lattice + Args: + l (Lattice): Original lattice to have vertices reordered + ordering (npt.NDArray[np.integer]): Permutation of vertex + ordering, i = ordering[i'] + + Returns: + Lattice: New lattice object with permuted vertex indices """ original_verts = l.vertices original_edges = l.edges @@ -445,13 +464,14 @@ def permute_vertices(l: Lattice, ordering: npt.NDArray[np.integer]) -> Lattice: def cut_boundaries(l: Lattice, boundary_to_cut: list = [True,True]) -> Lattice: """Removes the x and/or y boundary edges of the lattice. - :param l: The lattice to cut. - :type l: Lattice - :param boundary_to_cut: whether to cut the x or y boundaries, defaults to [True,True] - :type boundary_to_cut: list[Bool], optional - :return: A new lattice with boundaries cut. - :rtype: Lattice - """ + Args: + l (Lattice): The lattice to cut. + boundary_to_cut (list[Bool], optional): whether to cut the x or + y boundaries, defaults to [True,True] + + Returns: + Lattice: A new lattice with boundaries cut. + """ vertices = l.vertices.positions edges = l.edges.indices crossing = l.edges.crossing diff --git a/src/koala/phase_diagrams.py b/src/koala/phase_diagrams.py index 7f64788..c749b40 100644 --- a/src/koala/phase_diagrams.py +++ b/src/koala/phase_diagrams.py @@ -29,11 +29,10 @@ def function(Js): return some data def get_non_symmetric_triangular_sampling_points(samples = 10): - """ - Usage: + """Usage: sampling_points, triangulation = pd.get_non_symmetric_triangular_sampling_points(samples = 20) data = f(sampling_points) - + ax.triplot(triangulation, 'ko-', markersize = 1) #to plots the points where samples were taken ax.tricontourf(triangulation, data) #to plot the data """ diff --git a/src/koala/phase_space.py b/src/koala/phase_space.py index e2ea518..89d209e 100644 --- a/src/koala/phase_space.py +++ b/src/koala/phase_space.py @@ -5,16 +5,15 @@ def k_hamiltonian_generator(lattice:Lattice, coloring:np.ndarray, ujk: np.ndarray, J: np.ndarray): """Generates a bloch Hamiltonian for a translational system with the unit cell given by lattice for a given k value - :param lattice: The lattice object defining the unit cell - :type lattice: lattice - :param coloring: a coloring for the lattice (if None then you just use J[0]) - :type coloring: np.ndarray - :param J: the J-values for the x y and z bonds - :type J: np.ndarray - :param ujk: the edges that define the flux sector - :type ujk: np.ndarray - :return: a function that describes the Hamiltonian for a gven k - :rtype: function + Args: + lattice (lattice): The lattice object defining the unit cell + coloring (np.ndarray): a coloring for the lattice (if None then + you just use J[0]) + J (np.ndarray): the J-values for the x y and z bonds + ujk (np.ndarray): the edges that define the flux sector + + Returns: + function: a function that describes the Hamiltonian for a gven k """ j_vals = J[coloring] if coloring is not None else J[0] @@ -41,14 +40,15 @@ def k_hamiltonian(k: np.ndarray): def analyse_hk(Hk, k_num: int, return_all_results = False) -> tuple: """Given a k-dependent Hamiltonian, this code samples over k-space to find the energy of the ground state and tells you the gap size - :param Hk: K-dependent Hamiltonian - :type Hk: function - :param k_num: number of k states in the x and y direction that you want to sample - :type k_num: int - :param return_all_results: If true, return the energies over all of phase space - :type return_all_results: Bool - :return: the ground state energy per site, gap size - :rtype: tuple + Args: + Hk (function): K-dependent Hamiltonian + k_num (int): number of k states in the x and y direction that + you want to sample + return_all_results (Bool): If true, return the energies over all + of phase space + + Returns: + tuple: the ground state energy per site, gap size """ k_values = np.arange(k_num)*2*np.pi/k_num @@ -79,12 +79,13 @@ def analyse_hk(Hk, k_num: int, return_all_results = False) -> tuple: def gap_over_phase_space(Hk, k_num: int, return_k_values = False) -> tuple: """given a k-dependent hamiltonian, returns an array of the gap size over a k-lattice - :param Hk: k dependent hamiltonian - :type Hk: function - :param k_num: number of k states in the x and y direction that you want to sample - :type k_num: int - :return: - :rtype: np.ndarray + Args: + Hk (function): k dependent hamiltonian + k_num (int): number of k states in the x and y direction that + you want to sample + + Returns: + np.ndarray """ k_values = np.arange(k_num)*2*np.pi/k_num diff --git a/src/koala/plotting.py b/src/koala/plotting.py index de2c284..9702abe 100644 --- a/src/koala/plotting.py +++ b/src/koala/plotting.py @@ -32,16 +32,17 @@ def plot_vertices( You can use this to, for instance, plot some of the vertices as triangles and some as squares. - :param lattice: The lattice to use. - :type lattice: Lattice - :param labels: int or array of ints specifying the colors, defaults to 0. May be the same size as the vertices or of the subset. - :type labels: np.ndarray, optional - :param color_scheme: List or array of colors, defaults to ['black', ] - :type color_scheme: np.ndarray, optional - :param subset: An array of indices, boolean array or slice that selects which elements to plot, defaults to plotting all. - :type subset: np.ndarray, optional - :param ax: The axis to plot on, defaults to plt.gca() - :type subset: axis, optional + Args: + lattice (Lattice): The lattice to use. + labels (np.ndarray, optional): int or array of ints specifying + the colors, defaults to 0. May be the same size as the + vertices or of the subset. + color_scheme (np.ndarray, optional): List or array of colors, + defaults to ['black', ] + subset (axis, optional): An array of indices, boolean array or + slice that selects which elements to plot, defaults to + plotting all. + ax: The axis to plot on, defaults to plt.gca() """ labels, colors, color_scheme, subset, ax, transform = _process_plot_args( lattice, ax, labels, color_scheme, subset, lattice.n_vertices, kwargs @@ -68,26 +69,26 @@ def plot_edges( arrow_head_length=None, **kwargs, ): - """ - Plot the edges of a lattice with optional arrows. + """Plot the edges of a lattice with optional arrows. This uses matplotlib.collections.LineColection under the hood and you may pass in any keyword to be passed along to it. Note that arrays for alpha or linestyle don't currently work since they would have to be tiled correctly, and are not currently. If directions is not none, arrows are plotted from the first vertex to the second unless direction[i] == -1 - :param lattice: The lattice to use. - :type lattice: Lattice - :param labels: int or array of ints specifying the colors, defaults to 0. May be the same size as the vertices or of the subset. - :type labels: np.ndarray, optional - :param color_scheme: List or array of colors, defaults to ['black', ] - :type color_scheme: np.ndarray, optional - :param subset: An array of indices, boolean array or slice that selects which elements to plot, defaults to plotting all. - :type subset: np.ndarray, optional - :param directions: An array of arrow directions +/-1, defaults to None. - :type directions: np.ndarray, optional - :param ax: The axis to plot on, defaults to plt.gca() - :type subset: axis, optional + Args: + lattice (Lattice): The lattice to use. + labels (np.ndarray, optional): int or array of ints specifying + the colors, defaults to 0. May be the same size as the + vertices or of the subset. + color_scheme (np.ndarray, optional): List or array of colors, + defaults to ['black', ] + subset (axis, optional): An array of indices, boolean array or + slice that selects which elements to plot, defaults to + plotting all. + directions (np.ndarray, optional): An array of arrow directions + +/-1, defaults to None. + ax: The axis to plot on, defaults to plt.gca() """ labels, colors, color_scheme, subset, ax, transform = _process_plot_args( lattice, ax, labels, color_scheme, subset, lattice.n_edges, kwargs @@ -144,23 +145,23 @@ def plot_plaquettes( ax=None, **kwargs, ): - """ - Plot the plaquettes of a lattice. + """Plot the plaquettes of a lattice. This uses matplotlib.collections.PolyColection under the hood and you may pass in any keyword to be passed along to it. Note that currently the calls are done per plaquette so you can't for instance have multiple alpha values. Adding a color argument overides the color_scheme and labels. - :param lattice: The lattice to use. - :type lattice: Lattice - :param labels: int or array of ints specifying the colors, defaults to 0. May be the same size as the vertices or of the subset. - :type labels: np.ndarray, optional - :param color_scheme: List or array of colors, defaults to ['black', ] - :type color_scheme: np.ndarray, optional - :param subset: An array of indices, boolean array or slice that selects which elements to plot, defaults to plotting all. - :type subset: np.ndarray, optional - :param ax: The axis to plot on, defaults to plt.gca() - :type subset: axis, optional + Args: + lattice (Lattice): The lattice to use. + labels (np.ndarray, optional): int or array of ints specifying + the colors, defaults to 0. May be the same size as the + vertices or of the subset. + color_scheme (np.ndarray, optional): List or array of colors, + defaults to ['black', ] + subset (axis, optional): An array of indices, boolean array or + slice that selects which elements to plot, defaults to + plotting all. + ax: The axis to plot on, defaults to plt.gca() """ labels, colors, color_scheme, subset, ax, transform = _process_plot_args( @@ -210,15 +211,15 @@ def plot_plaquettes( def plot_dual(lattice, subset=slice(None, None), **kwargs): """Given a lattice, plot the edges in it's dual or a subset of them, other args are passed through to plot_edges. - :param lattice: The lattice to use. - :type lattice: Lattice - :param subset: a subset of edges to plot, defaults to all. - :type subset: slice, boolean array or indices, optional - :param ax: the ax to plot to, defaults to None - :type ax: axis, optional + Args: + lattice (Lattice): The lattice to use. + subset (slice, boolean array or indices, optional): a subset of + edges to plot, defaults to all. + ax (axis, optional): the ax to plot to, defaults to None - :return: The dual lattice represented as a second Lattice object. - :rtype: Lattice + Returns: + Lattice: The dual lattice represented as a second Lattice + object. """ st_as_lattice = graph_utils.make_dual(lattice, subset) plot_edges(st_as_lattice, **kwargs) @@ -298,8 +299,7 @@ def _scale_nicely(lattice, ax): def _process_plot_args(lattice, ax, labels, color_scheme, subset, N, kwargs): - """ - Deals with housekeeping operations common to all plotting functions. + """Deals with housekeeping operations common to all plotting functions. Specifically: Broadcast single values to be the size of the lattice. Allow labels to refer to either the whole lattice or the subset. @@ -333,9 +333,7 @@ def _process_plot_args(lattice, ax, labels, color_scheme, subset, N, kwargs): def plot_vertex_indices(g, ax=None, offset=0.01, **kwargs): - """ - Plot the indices of the vertices on a graph - """ + """Plot the indices of the vertices on a graph""" if ax is None: ax = plt.gca() for i, v in enumerate(g.vertices.positions): @@ -344,9 +342,7 @@ def plot_vertex_indices(g, ax=None, offset=0.01, **kwargs): # TODO: Make this work with edges that cross the boundaries def plot_edge_indices(g, ax=None, offset=0.01): - """ - Plot the indices of the edges on a graph - """ + """Plot the indices of the edges on a graph""" if ax is None: ax = plt.gca() for i, e in enumerate(g.edges.indices): @@ -356,9 +352,7 @@ def plot_edge_indices(g, ax=None, offset=0.01): def plot_plaquette_indices(l, ax=None, **kwargs): - """ - Plot the indices of the vertices on a graph - """ + """Plot the indices of the vertices on a graph""" if ax is None: ax = plt.gca() for i, p in enumerate(l.plaquettes): @@ -374,7 +368,8 @@ def plot_plaquette_indices(l, ax=None, **kwargs): def deprecated(func): """This is a decorator which can be used to mark functions as deprecated. It will result in a warning being emitted - when the function is used.""" + when the function is used. + """ @functools.wraps(func) def new_func(*args, **kwargs): @@ -430,10 +425,14 @@ def _lines_cross_unit_cell(lines: np.ndarray) -> np.ndarray: Returns: np.ndarray: out[i] == 1 if line[i] is fully inside the unit cell - :param lines: : Represents lines by pairs of points - :type lines: np.ndarray shape (n_lines, 2, 2) - :return: cross[i] is true is the corresponding line crossed any of the 4 boundaries of the unit cell - :rtype: np.ndarray shape (n_lines,) + Args: + lines (np.ndarray shape (n_lines, 2, 2)): : Represents lines by + pairs of points + + Returns: + np.ndarray shape (n_lines,): cross[i] is true is the + corresponding line crossed any of the 4 boundaries of the unit + cell """ start, end = ( lines[:, 0, None, :], @@ -651,8 +650,7 @@ def to_points(xv, yv): def plot_degeneracy_breaking(vertex_i, g, ax=None): - """ - Companion function to graph_utils.clockwise_edges_about, + """Companion function to graph_utils.clockwise_edges_about, plots the edges on an axis with labelled angles and the positive x axis as a dotted line """ if ax is None: @@ -692,17 +690,20 @@ def plot_degeneracy_breaking(vertex_i, g, ax=None): def _lines_cross_any_cell_boundary(lines: np.ndarray) -> np.ndarray: - """ - Used in plot_plaquettes to determine which plaquettes need to be plotted multiple times. + """Used in plot_plaquettes to determine which plaquettes need to be plotted multiple times. Similar to the above, but tells you if the line cross y=0,1 and x=0,1 at any point rather than just the unit cell. - :param lines: : Represents lines by pairs of points - :type lines: np.ndarray shape (n_lines, 2, 2) - :param which: If True output information about which lines were crossed, defaults to False - :type which: bool, optional - :return: If which is false, cross[i] is true is the corresponding line crossed any of the 4 boundaries of the unit cell, + Args: + lines (np.ndarray shape (n_lines, 2, 2)): : Represents lines by + pairs of points + which (bool, optional): If True output information about which + lines were crossed, defaults to False + + Returns: + np.ndarray shape (n_lines,) or (n_lines, 2, 2) if which is True: + If which is false, cross[i] is true is the corresponding line + crossed any of the 4 boundaries of the unit cell, if which is true, cross[i] = ((x=0, y=0), (x=1, y=1)) where each entry if true if line[i] crossed the corresponding boundary. - :rtype: np.ndarray shape (n_lines,) or (n_lines, 2, 2) if which is True """ start, end = ( lines[:, 0, None, :], @@ -731,20 +732,21 @@ def cross_product_2d(a, b): def line_intersection(lines, lines2, abs_tolerance=1e-14, full_output=False): - """ - Generic Line to line intersection function - - :param lines: The first set of lines, with shape [n_lines, 2, 2] where lines[i, 0, :] is the first point of the ith line - :type line: np.ndarray + """Generic Line to line intersection function - :param lines2: The second set of lines to intersect with. Shape [n_lines2, 2, 2] - :type line2: np.ndarray - - :param abs_tolerance: The absolute floating point tolerance to use for the parallel and colinear special cases. - :type abs_tolerance: float + Args: + lines: The first set of lines, with shape [n_lines, 2, 2] where + lines[i, 0, :] is the first point of the ith line + line (np.ndarray) + lines2: The second set of lines to intersect with. Shape + [n_lines2, 2, 2] + line2 (np.ndarray) + abs_tolerance (float): The absolute floating point tolerance to + use for the parallel and colinear special cases. - :return: intersection, boolean array shape [n_lines, n_lines2] - :rtype: np.ndarray + Returns: + np.ndarray: intersection, boolean array shape [n_lines, + n_lines2] """ s1 = lines[:, 0, :][:, None] diff --git a/src/koala/voronization.py b/src/koala/voronization.py index f623e6d..8017768 100644 --- a/src/koala/voronization.py +++ b/src/koala/voronization.py @@ -15,8 +15,7 @@ def points_near_unit_image(vor, idx): - """ - Find the vertex in unit cell near the image of the vertex with index + """Find the vertex in unit cell near the image of the vertex with index idx. Assumes a voronoi diagram vor generated from a point set in a 3x3 replicated geometry spanning [-1, 2]. """ @@ -61,15 +60,20 @@ def generate_lattice( """Generate a `Lattice` object with periodic boundary conditions from an initial set of points ``original_points`` whose voronoi diagram constitute the vertices and edges of the lattice. - :param original_points: Points used to generating lattice voronoi diagram - :type original_points: npt.NDArray[np.floating] - :param debug_plot: Output intermediate debugging plots to check PBC logic, defaults to False - :type debug_plot: bool, optional - :param shift_vertices: If True, shift all the vertices to the center of the delaunay triangle they sit in - stops any vertices getting too close together and makes things a bit neater - :type shift_vertices: bool, optional - :return: Lattice object containing information about vertices, edges, and - :rtype: Lattice object - """ + Args: + original_points (npt.NDArray[np.floating]): Points used to + generating lattice voronoi diagram + debug_plot (bool, optional): Output intermediate debugging plots + to check PBC logic, defaults to False + shift_vertices (bool, optional): If True, shift all the vertices + to the center of the delaunay triangle they sit in - stops + any vertices getting too close together and makes things a + bit neater + + Returns: + Lattice object: Lattice object containing information about + vertices, edges, and + """ padding = 1 if original_points.shape[0] > 10 else 2 #how many layers to add, 1 -> 3x3, 2 -> 5x5 etc. #Create periodic boundary conditions by replicating the point set across 3x3 unit cells points = generate_point_array(original_points, padding) diff --git a/src/koala/weaire_thorpe.py b/src/koala/weaire_thorpe.py index e2b0698..1fa0859 100644 --- a/src/koala/weaire_thorpe.py +++ b/src/koala/weaire_thorpe.py @@ -11,8 +11,7 @@ def normalised(a): return a / np.linalg.norm(a) def vertices_to_triangles(g, edge_labels, triangle_size = 0.05): - """ - Map every vertex to a triangle. + """Map every vertex to a triangle. The original vertex labeled by i get mapped to vertices 3*i, 3*i + 1, 3*i + 2 Where the mapping with those three is determined by the edge coloring which allows us to connect the right vertices of neighbouring triangles together. From 22d4c00f939e5a331dc36fa2a1c0f4d1250ee2ad Mon Sep 17 00:00:00 2001 From: gcassella Date: Sat, 30 Jul 2022 12:48:51 +0100 Subject: [PATCH 2/2] Add Google style pylintrc --- pylintrc | 427 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 427 insertions(+) create mode 100644 pylintrc diff --git a/pylintrc b/pylintrc new file mode 100644 index 0000000..cf4d01c --- /dev/null +++ b/pylintrc @@ -0,0 +1,427 @@ +# This Pylint rcfile contains a best-effort configuration to uphold the +# best-practices and style described in the Google Python style guide: +# https://google.github.io/styleguide/pyguide.html +# +# Its canonical open-source location is: +# https://google.github.io/styleguide/pylintrc + +[MASTER] + +# Add files or directories to the denylist. They should be base names, not +# paths. +ignore=third_party + +# Add files or directories matching the regex patterns to the denylist. The +# regex matches against base names, not paths. +ignore-patterns= + +# Pickle collected data for later comparisons. +persistent=no + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + +# Use multiple processes to speed up Pylint. +jobs=4 + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +#enable= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +disable=abstract-method, + apply-builtin, + arguments-differ, + attribute-defined-outside-init, + backtick, + bad-option-value, + basestring-builtin, + buffer-builtin, + c-extension-no-member, + consider-using-enumerate, + cmp-builtin, + cmp-method, + coerce-builtin, + coerce-method, + delslice-method, + div-method, + duplicate-code, + eq-without-hash, + execfile-builtin, + file-builtin, + filter-builtin-not-iterating, + fixme, + getslice-method, + global-statement, + hex-method, + idiv-method, + implicit-str-concat-in-sequence, + import-error, + import-self, + import-star-module-level, + inconsistent-return-statements, + input-builtin, + intern-builtin, + invalid-str-codec, + locally-disabled, + long-builtin, + long-suffix, + map-builtin-not-iterating, + misplaced-comparison-constant, + missing-function-docstring, + metaclass-assignment, + next-method-called, + next-method-defined, + no-absolute-import, + no-else-break, + no-else-continue, + no-else-raise, + no-else-return, + no-init, # added + no-member, + no-name-in-module, + no-self-use, + nonzero-method, + oct-method, + old-division, + old-ne-operator, + old-octal-literal, + old-raise-syntax, + parameter-unpacking, + print-statement, + raising-string, + range-builtin-not-iterating, + raw_input-builtin, + rdiv-method, + reduce-builtin, + relative-import, + reload-builtin, + round-builtin, + setslice-method, + signature-differs, + standarderror-builtin, + suppressed-message, + sys-max-int, + too-few-public-methods, + too-many-ancestors, + too-many-arguments, + too-many-boolean-expressions, + too-many-branches, + too-many-instance-attributes, + too-many-locals, + too-many-nested-blocks, + too-many-public-methods, + too-many-return-statements, + too-many-statements, + trailing-newlines, + unichr-builtin, + unicode-builtin, + unnecessary-pass, + unpacking-in-except, + useless-else-on-loop, + useless-object-inheritance, + useless-suppression, + using-cmp-argument, + wrong-import-order, + xrange-builtin, + zip-builtin-not-iterating, + + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html. You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Tells whether to display a full report or only the messages +reports=no + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + + +[BASIC] + +# Good variable names which should always be accepted, separated by a comma +good-names=main,_ + +# Bad variable names which should always be refused, separated by a comma +bad-names= + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +property-classes=abc.abstractproperty,cached_property.cached_property,cached_property.threaded_cached_property,cached_property.cached_property_with_ttl,cached_property.threaded_cached_property_with_ttl + +# Regular expression matching correct function names +function-rgx=^(?:(?PsetUp|tearDown|setUpModule|tearDownModule)|(?P_?[A-Z][a-zA-Z0-9]*)|(?P_?[a-z][a-z0-9_]*))$ + +# Regular expression matching correct variable names +variable-rgx=^[a-z][a-z0-9_]*$ + +# Regular expression matching correct constant names +const-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$ + +# Regular expression matching correct attribute names +attr-rgx=^_{0,2}[a-z][a-z0-9_]*$ + +# Regular expression matching correct argument names +argument-rgx=^[a-z][a-z0-9_]*$ + +# Regular expression matching correct class attribute names +class-attribute-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$ + +# Regular expression matching correct inline iteration names +inlinevar-rgx=^[a-z][a-z0-9_]*$ + +# Regular expression matching correct class names +class-rgx=^_?[A-Z][a-zA-Z0-9]*$ + +# Regular expression matching correct module names +module-rgx=^(_?[a-z][a-z0-9_]*|__init__)$ + +# Regular expression matching correct method names +method-rgx=(?x)^(?:(?P_[a-z0-9_]+__|runTest|setUp|tearDown|setUpTestCase|tearDownTestCase|setupSelf|tearDownClass|setUpClass|(test|assert)_*[A-Z0-9][a-zA-Z0-9_]*|next)|(?P_{0,2}[A-Z][a-zA-Z0-9_]*)|(?P_{0,2}[a-z][a-z0-9_]*))$ + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=(__.*__|main|test.*|.*test|.*Test)$ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=10 + + +[TYPECHECK] + +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators=contextlib.contextmanager,contextlib2.contextmanager + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis. It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= + +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=optparse.Values,thread._local,_thread._local + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=80 + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=(?x)( + ^\s*(\#\ )??$| + ^\s*(from\s+\S+\s+)?import\s+.+$| + ^.*pytype:\sdisable=.*$| + ^.*(\#\s*)type:\s.*$| + ^\s*""".*$| + ^.*pylint:\sdisable=.*$) + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=yes + +# Maximum number of lines in a module +max-module-lines=99999 + +indent-string=' ' + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=TODO + + +[STRING] + +# This flag controls whether inconsistent-quotes generates a warning when the +# character used as a quote delimiter is used inconsistently within a module. +check-quote-consistency=yes + + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=^\*{0,2}(_$|unused_|dummy_) + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_,_cb + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules=six,six.moves,past.builtins,future.builtins,functools + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging,absl.logging,tensorflow.io.logging + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + + +[SPELLING] + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub, + TERMIOS, + Bastion, + rexec, + sets + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant, absl + +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__, + __new__, + setUp + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict, + _fields, + _replace, + _source, + _make + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls, + class_ + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=StandardError, + Exception, + BaseException \ No newline at end of file