Orders the entries (their coordinates) in a phase diagram plot according
    to the user specified ordering.
    Ordering should be given as ['Up', 'Left', 'Right'], where Up,
    Left and Right are the names of the entries in the upper, left and right
    corners of the triangle respectively.

    Args:
        lines: list of list of coordinates for lines in the PD.
        stable_entries: {coordinate : entry} for each stable node in the
            phase diagram. (Each coordinate can only have one stable phase)
        unstable_entries: {entry: coordinates} for all unstable nodes in the
            phase diagram.
        ordering: Ordering of the phase diagram, given as a list ['Up',
            'Left','Right']

    Returns:
        (newlines, newstable_entries, newunstable_entries):
        - newlines is a list of list of coordinates for lines in the PD.
        - newstable_entries is a {coordinate : entry} for each stable node
        in the phase diagram. (Each coordinate can only have one
        stable phase)
        - newunstable_entries is a {entry: coordinates} for all unstable
        nodes in the phase diagram.

def order_phase_diagram(lines, stable_entries, unstable_entries, ordering):
    """
    Orders the entries (their coordinates) in a phase diagram plot according
    to the user specified ordering.
    Ordering should be given as ['Up', 'Left', 'Right'], where Up,
    Left and Right are the names of the entries in the upper, left and right
    corners of the triangle respectively.

    Args:
        lines: list of list of coordinates for lines in the PD.
        stable_entries: {coordinate : entry} for each stable node in the
            phase diagram. (Each coordinate can only have one stable phase)
        unstable_entries: {entry: coordinates} for all unstable nodes in the
            phase diagram.
        ordering: Ordering of the phase diagram, given as a list ['Up',
            'Left','Right']

    Returns:
        (newlines, newstable_entries, newunstable_entries):
        - newlines is a list of list of coordinates for lines in the PD.
        - newstable_entries is a {coordinate : entry} for each stable node
        in the phase diagram. (Each coordinate can only have one
        stable phase)
        - newunstable_entries is a {entry: coordinates} for all unstable
        nodes in the phase diagram.
    """
    yup = -1000.0
    xleft = 1000.0
    xright = -1000.0

    for coord in stable_entries:
        if coord[0] > xright:
            xright = coord[0]
            nameright = stable_entries[coord].name
        if coord[0] < xleft:
            xleft = coord[0]
            nameleft = stable_entries[coord].name
        if coord[1] > yup:
            yup = coord[1]
            nameup = stable_entries[coord].name

    if (not nameup in ordering) or (not nameright in ordering) or \
            (not nameleft in ordering):
        raise ValueError(
            'Error in ordering_phase_diagram : \n"{up}", "{left}" and "{'
            'right}"'
            ' should be in ordering : {ord}'.format(up=nameup, left=nameleft,
                                                    right=nameright,
                                                    ord=ordering))

    cc = np.array([0.5, np.sqrt(3.0) / 6.0], np.float)

    if nameup == ordering[0]:
        if nameleft == ordering[1]:
            # The coordinates were already in the user ordering
            return lines, stable_entries, unstable_entries
        else:
            newlines = [[np.array(1.0 - x), y] for x, y in lines]
            newstable_entries = {(1.0 - c[0], c[1]): entry
                                 for c, entry in stable_entries.items()}
            newunstable_entries = {entry: (1.0 - c[0], c[1])
                                   for entry, c in
                                   unstable_entries.items()}
            return newlines, newstable_entries, newunstable_entries
    elif nameup == ordering[1]:
        if nameleft == ordering[2]:
            c120 = np.cos(2.0 * np.pi / 3.0)
            s120 = np.sin(2.0 * np.pi / 3.0)
            newlines = []
            for x, y in lines:
                newx = np.zeros_like(x)
                newy = np.zeros_like(y)
                for ii, xx in enumerate(x):
                    newx[ii] = c120 * (xx - cc[0]) - s120 * (y[ii] - cc[1]) + \
                               cc[0]
                    newy[ii] = s120 * (xx - cc[0]) + c120 * (y[ii] - cc[1]) + \
                               cc[1]
                newlines.append([newx, newy])
            newstable_entries = {
                (c120 * (c[0] - cc[0]) - s120 * (c[1] - cc[1]) + cc[0],
                 s120 * (c[0] - cc[0]) + c120 * (c[1] - cc[1]) + cc[1]): entry
                for c, entry in stable_entries.items()}
            newunstable_entries = {
                entry: (c120 * (c[0] - cc[0]) - s120 * (c[1] - cc[1]) + cc[0],
                        s120 * (c[0] - cc[0]) + c120 * (c[1] - cc[1]) + cc[1])
                for entry, c in unstable_entries.items()}
            return newlines, newstable_entries, newunstable_entries
        else:
            c120 = np.cos(2.0 * np.pi / 3.0)
            s120 = np.sin(2.0 * np.pi / 3.0)
            newlines = []
            for x, y in lines:
                newx = np.zeros_like(x)
                newy = np.zeros_like(y)
                for ii, xx in enumerate(x):
                    newx[ii] = -c120 * (xx - 1.0) - s120 * y[ii] + 1.0
                    newy[ii] = -s120 * (xx - 1.0) + c120 * y[ii]
                newlines.append([newx, newy])
            newstable_entries = {(-c120 * (c[0] - 1.0) - s120 * c[1] + 1.0,
                                  -s120 * (c[0] - 1.0) + c120 * c[1]): entry
                                 for c, entry in stable_entries.items()}
            newunstable_entries = {
                entry: (-c120 * (c[0] - 1.0) - s120 * c[1] + 1.0,
                        -s120 * (c[0] - 1.0) + c120 * c[1])
                for entry, c in unstable_entries.items()}
            return newlines, newstable_entries, newunstable_entries
    elif nameup == ordering[2]:
        if nameleft == ordering[0]:
            c240 = np.cos(4.0 * np.pi / 3.0)
            s240 = np.sin(4.0 * np.pi / 3.0)
            newlines = []
            for x, y in lines:
                newx = np.zeros_like(x)
                newy = np.zeros_like(y)
                for ii, xx in enumerate(x):
                    newx[ii] = c240 * (xx - cc[0]) - s240 * (y[ii] - cc[1]) + \
                               cc[0]
                    newy[ii] = s240 * (xx - cc[0]) + c240 * (y[ii] - cc[1]) + \
                               cc[1]
                newlines.append([newx, newy])
            newstable_entries = {
                (c240 * (c[0] - cc[0]) - s240 * (c[1] - cc[1]) + cc[0],
                 s240 * (c[0] - cc[0]) + c240 * (c[1] - cc[1]) + cc[1]): entry
                for c, entry in stable_entries.items()}
            newunstable_entries = {
                entry: (c240 * (c[0] - cc[0]) - s240 * (c[1] - cc[1]) + cc[0],
                        s240 * (c[0] - cc[0]) + c240 * (c[1] - cc[1]) + cc[1])
                for entry, c in unstable_entries.items()}
            return newlines, newstable_entries, newunstable_entries
        else:
            c240 = np.cos(4.0 * np.pi / 3.0)
            s240 = np.sin(4.0 * np.pi / 3.0)
            newlines = []
            for x, y in lines:
                newx = np.zeros_like(x)
                newy = np.zeros_like(y)
                for ii, xx in enumerate(x):
                    newx[ii] = -c240 * xx - s240 * y[ii]
                    newy[ii] = -s240 * xx + c240 * y[ii]
                newlines.append([newx, newy])
            newstable_entries = {(-c240 * c[0] - s240 * c[1],
                                  -s240 * c[0] + c240 * c[1]): entry
                                 for c, entry in stable_entries.items()}
            newunstable_entries = {entry: (-c240 * c[0] - s240 * c[1],
                                           -s240 * c[0] + c240 * c[1])
                                   for entry, c in unstable_entries.items()}
            return newlines, newstable_entries, newunstable_entries