text:
### Author : Avadesh Meduri
### Date : 27/09/2019
### This is the implementation of the paper "walking control based on step timing Adaption" by Majid Et al.

import numpy as np
from reactive_planners.utils.qp_solver import quadprog_solve_qp

class DcmVrpPlanner:
    def __init__(
        self, l_min, l_max, w_min, w_max, t_min, t_max, v_des, l_p, ht
    ):

        """
        Input:
            l_min : minimum step length in the x direction (in the direction of forward motion)
            l_max : maximum step length in the x direction (in the direction of forward motion)
            w_min : minimum step length in the y direction (in the lateral direction)
            w_max : maximum step lenght in the y direction (in the lateratl direction)
            t_min : minimum step time
            t_max : maximum step time
            v_des : desired average velocity in the x and y ([v_x, v_y]) 2d vector
            l_p : default step width
            ht : average desired height of the com above the ground
        """

        assert np.shape(v_des) == (2,)

        self.l_min = l_min
        self.l_max = l_max
        self.w_min = w_min
        self.w_max = w_max
        self.t_min = t_min
        self.t_max = t_max
        self.v_des = v_des
        self.l_p = l_p
        self.ht = ht

        self.omega = np.sqrt(9.81 / self.ht)
        self.bx_max = self.l_max / (
            np.power(np.e, self.omega * self.t_min) - 1
        )
        self.bx_min = self.l_min / (
            np.power(np.e, self.omega * self.t_max) - 1
        )
        self.by_max_out = (
            self.l_p / (1 + np.power(np.e, self.omega * t_min))
        ) + (
            self.w_max - self.w_min * np.power(np.e, self.omega * self.t_min)
        ) / (
            1 - np.power(np.e, 2 * self.omega * self.t_min)
        )

        self.by_max_in = (
            self.l_p / (1 + np.power(np.e, self.omega * t_min))
        ) + (
            self.w_min - self.w_max * np.power(np.e, self.omega * self.t_min)
        ) / (
            1 - np.power(np.e, 2 * self.omega * self.t_min)
        )

    def compute_nominal_step_values(self, n):

        """
        computes nominal step location and step length at each time step
        input :
            n : 1 if left leg and 2 if right le is in contact
        """

        if self.v_des[0] == 0 or self.v_des[1] == 0:
            B_l = self.t_min
            B_u = self.t_max
        else:
            B_l = np.max(
                [
                    self.l_min / abs(self.v_des[0]),
                    self.w_min / abs(self.v_des[1]),
                    self.t_min,
                ]
            )
            B_u = np.min(
                [
                    self.l_max / abs(self.v_des[0]),
                    self.w_max / abs(self.v_des[1]),
                    self.t_max,
                ]
            )

        t_nom = (B_l + B_u) / 2.0
        l_nom = self.v_des[0] * t_nom
        w_nom = self.v_des[1] * t_nom

        bx_nom = l_nom / (np.power(np.e, self.omega * t_nom) - 1)
        by_nom = (
            np.power(-1, n)
            * (self.l_p / (1 + np.power(np.e, self.omega * t_nom)))
        ) - w_nom / (1 - np.power(np.e, self.omega * t_nom))

        return l_nom, w_nom, t_nom, bx_nom, by_nom

    def compute_dcm_current(self, x, xd):
        """
        computes the current location of the dcm
        input :
            x : center of mass location at current time step
            xd : center of mass velocity of current time step
        """
        self.x = x
        return (xd / self.omega) + x

    def compute_alpha(self, xd_com, v_des):
        """
        computes the current value of alpha. Alpha takes a value of 1 if v_des and
        xd_com are zero. When alpha is one t has to be zero to satisfy complementary constraint.
        Otherwise it takes a value of 0.
        """

        if max(v_des) == 0 and np.square(max(xd_com)) < 0.001:
            print("****************************************")
            return 1
        else:
            return 0

    def compute_adapted_step_locations(self, u, t, n, psi_current, alpha, W):
        """
        computes adapted step location after solving QP
        Input:
            u : the location of the previous step (2d vector) [ux, uy]
            t : time elapsed after the previous step has occured
            n : 1 if left leg and 2 if right le is in contact
            psi_current : current dcm location [psi_x, psi_y]
            W : wieght array 5d
        """

        assert np.shape(u) == (2,)
        assert np.shape(psi_current) == (2,)

        l_nom, w_nom, t_nom, bx_nom, by_nom = self.compute_nominal_step_values(
            n
        )
        t_nom = np.power(
            np.e, self.omega * t_nom
        )  ### take exp as T is considered as e^wt in qp

        P = np.identity(6)  ## quadratic cost matrix
        P[0][0], P[1][1], P[2][2], P[3][3], P[4][4], P[5][5] = W
        q = np.array(
            [
                -W[0] * (l_nom),
                -W[1] * (w_nom),
                -W[2] * t_nom,
                -W[3] * bx_nom,
                -W[4] * by_nom,
                0,
            ]
        )  ##

        G = np.matrix(
            [
                [1, 0, 0, 0, 0, 0],
                [0, 1, 0, 0, 0, 0],
                [-1, 0, 0, 0, 0, 0],
                [0, -1, 0, 0, 0, 0],
                [0, 0, 1, 0, 0, 0],
                [0, 0, -1, 0, 0, 0],
                [0, 0, alpha, 0, 0, 1],
                [0, 0, 0, 1, 0, 0],
                [0, 0, 0, -1, 0, 0],
                [0, 0, 0, 0, 1, 0],
                [0, 0, 0, 0, -1, 0],
            ]
        )

        h = np.array(
            [
                self.l_max,
                self.w_max,
                -1 * (self.l_min),
                -1 * (self.w_min),
                np.power(np.e, self.omega * self.t_max),
                -1 * np.power(np.e, self.omega * self.t_min),
                -alpha,
                self.bx_max,
                -1 * self.bx_min,
                self.by_max_in,
                -1 * self.by_max_out,
            ]
        )

        tmp = [0.0, 0.0]
        tmp[0] = (psi_current[0] - u[0]) * np.power(np.e, -1 * self.omega * t)
        tmp[1] = (psi_current[1] - u[1]) * np.power(np.e, -1 * self.omega * t)
        A = np.matrix(
            [[1, 0, -1 * tmp[0], 1, 0, 0], [0, 1, -1 * tmp[1], 0, 1, 0]]
        )

        b = np.array([0.0, 0.0])

        P = P.astype(float)
        q = q.astype(float)
        G = G.astype(float)
        h = h.astype(float)
        A = A.astype(float)
        b = b.astype(float)

        x_opt = quadprog_solve_qp(P, q, G, h, A, b)
        t_end = np.log(x_opt[2]) / self.omega

        self._quad_params = [P, q, G, h, A, b]
        print("^^^^^^^")
        print(alpha)
        print(x_opt[4])
        return (x_opt[0] + u[0], x_opt[1] + u[1], t_end, x_opt[3], x_opt[4])

    def compute_adapted_step_locations_gurobi(
        self, u, t, n, psi_current, alpha, W
    ):
        """
        computes adapted step location after solving QP
        Input:
            u : the location of the previous step (2d vector) [ux, uy]
            t : time elapsed after the previous step has occured
            n : 1 if left leg and 2 if right le is in contact
            psi_current : current dcm location [psi_x, psi_y]
            W : wieght array 5d
        """
        # Import only when used.
        # from gurobipy import *

        assert np.shape(u) == (2,)
        assert np.shape(psi_current) == (2,)

        l_nom, w_nom, t_nom, bx_nom, by_nom = self.compute_nominal_step_values(
            n
        )

        t_nom = np.power(
            np.e, self.omega * t_nom
        )  ### take exp as T is considered as e^wt in qp

        # creating model

        m = Model("qp")

        ## creating variables
        ut_x = m.addVar(lb=self.l_min, ub=self.l_max, name="ut_x")
        ut_y = m.addVar(lb=self.w_min, ub=self.w_max, name="ut_y")
        t_step = m.addVar(
            lb=np.power(np.e, self.omega * self.t_min),
            ub=np.power(np.e, self.omega * self.t_max),
            name="t_step",
        )
        b_x = m.addVar(lb=self.bx_min, ub=self.bx_max, name="b_x")
        b_y = m.addVar(lb=self.by_max_out, ub=self.by_max_in, name="b_y")

        ### Cost

        c = (
            (W[0] * (ut_x - l_nom) * (ut_x - l_nom))
            + (W[1] * (ut_y - w_nom) * (ut_y - w_nom))
            + (W[2] * (t_step - t_nom) * (t_step - t_nom))
            + (W[3] * (b_x - bx_nom) * (b_x - bx_nom))
            + (W[4] * (b_y - by_nom) * (b_y - by_nom))
        )

        m.setObjective(c)

        ## constraints
        tmp = [0.0, 0.0]
        tmp[0] = (psi_current[0] - u[0]) * np.power(np.e, -1 * self.omega * t)
        tmp[1] = (psi_current[1] - u[1]) * np.power(np.e, -1 * self.omega * t)

        m.addConstr(ut_x == (tmp[0] * t_step) - b_x, "dyn_constr_x")
        m.addConstr(ut_y == (tmp[1] * t_step) - b_y, "dyn_constr_y")

        m.optimize()

        x_opt = m.getVars()

        t_end = np.log(x_opt[2].x) / self.omega

        return (
            x_opt[0].x + u[0],
            x_opt[1].x + u[1],
            t_end,
            x_opt[3].x,
            x_opt[4].x,
        )

    def compute_which_end_effector(
        self, v_des, u_current, u_next, dcm_t, n_current, alpha, W
    ):

        """
        This function decides which end effector leaves the ground next
        """

        x_opt_same_eff = self.compute_adapted_step_locations(
            u_current, 0, n_current, dcm_t, alpha, W
        )
        x_opt_diff_eff = self.compute_adapted_step_locations(
            u_next, 0, n_current + 1, dcm_t, alpha, W
        )

        # print(x_opt_same_eff[0:2], x_opt_diff_eff[0:2])

        if np.linalg.norm(
            np.subtract(x_opt_same_eff[0:2], u_current)
        ) < np.linalg.norm(np.subtract(x_opt_diff_eff[0:2], u_next)):
            n = n_current
        else:
            n = n_current + 1

        return n

    #
    # dcm_vrp_planner.generate_foot_trajectory(x_opt[0:2], u_current_step, u_old, tend_scale * t_end, t, 0.1 , floor_height)

    def generate_foot_trajectory(
        self, u_t_end, u, u_old, t_end, t, z_max, z_ht, ctrl_timestep=0.001
    ):
        """
        This function generates a linear trajectory from the current foot location
        to the desired step location and returns the desired location of the foot
        at the next step.

        Input :
            u_t_end : desried step location
            u : current step location
            u_old : the location of the previous step
            t_end : time duration of the step
            t : current timestep
            z_max : maximum height the foot should reach(will reach at middle of the step time)
            z_ht : the height the robot must be above the ground
            ctrl_timestep : the timestep at which value is recomputed
        """

        x_foot_des_air = np.zeros(3)
        x_foot_des_ground = np.zeros(3)

        ## for impedance the leg length has to be set to zero to move center of mass forward
        if t_end > 0.001:
            x_foot_des_air[0] = u_old[0] + (u_t_end[0] - u_old[0]) * (
                t / t_end
            )
            x_foot_des_air[1] = u_old[1] + (u_t_end[1] - u_old[1]) * (
                t / t_end
            )

            x_foot_des_ground[0] = u[0]
            x_foot_des_ground[1] = u[1]

            x_foot_des_ground[2] = z_ht
            x_foot_des_air[2] = (z_ht) + (z_max) * np.sin(
                (np.pi * t) / (t_end)
            )
        else:
            x_foot_des_air = [u_t_end[0], u_t_end[1], z_ht]
            x_foot_des_ground = [u[0], u[1], z_ht]

        return x_foot_des_air, x_foot_des_ground


text:
from core.simulation import Simulation
import numpy as np
import pandas as pd
from bokeh.plotting import figure, output_file, save
from _datetime import datetime

from service import pid_regler

if __name__ == "__main__":
    pid = pid_regler.PID_regler()
    df = pd.DataFrame(columns=['phi', 'u'])
    #todo: put to toml

    def plot(df):
        TOOLTIPS = [
            ("Name", '$name'),
            ("index", "$index"),
            ("Wert", "$y")]

        p = figure(title="simple line example", x_axis_label='Datapoints', y_axis_label='Data', tooltips=TOOLTIPS)
        p.line(df['phi'].index.values, df['phi'], line_width=2,
               legend_label='phi', name='phi', color="red")
        p.line(df['theta'].index.values, df['theta'], line_width=2,
               legend_label='theta', name='theta', color="green")
        p.line(df['u'].index.values, df['u'], line_width=2,
               legend_label='u', name='u', color="blue")
        output_file("plot.html")
        save(p)

    sim = Simulation()
    result = sim.run()
    sim.set_properties('propulsion/engine/set-running', 1)
    sim.set_properties('fcs/throttle-cmd-norm', 1.0)
    i = 0
    state = ""
    before = datetime.now()
    while result and sim.jsbsim.get_sim_time() <= 50:
        #print(i)
        state = sim.get_state()
        if i%5==0:
            sim.set_properties('fcs/aileron-cmd-norm', pid.innerLoopAileron(np.deg2rad(5), state['phi'], state['p'],
                                                                            sim.jsbsim.get_property_value(
                                                                           'fcs/aileron-cmd-norm')))
            sim.set_properties('fcs/elevator-cmd-norm', pid.innerLoopElevator(np.deg2rad(-10), state['theta'], state['q'],
                                                                              sim.jsbsim.get_property_value(
                                                                             'fcs/elevator-cmd-norm')))
        sim.run()
        #print(np.rad2deg(state['phi']))
        df = df.append({'u': state['u']*0.51444, 'phi': np.rad2deg(state['phi']), 'theta': np.rad2deg(state['theta'])}, ignore_index=True)

        i += 1
    after = datetime.now()
    dt = (after - before)
    print(dt)
    sim.close()
    plot(df)

ext: py

reason: import numpy


text:
from abc import *

import numpy as np

import structure
from infrastructure import Loggable

class EnergyTerm(ABCMeta, Loggable):
    @abstractmethod
    def __init__(self):
        self.logger = Loggable.get_default_logger()

    @abstractmethod
    def E(self, *atoms):
        raise NotImplementedError

class Bond(EnergyTerm):
    def __init__(self, kb, r0):
        EnergyTerm.__init__(self)
        #  kJ / mol nm
        self.kb = kb
        #  nm
        self.r0 = r0

    def E(self, i, j):
        return self.kb * np.power(np.norm(i.r - j.r) - self.r0, 2)

class Angle(EnergyTerm):
    def __init__(self, kb, t0):
        EnergyTerm.__init__(self)
        # kJ / mol rad^2
        self.kb = kb
        # rad
        self.t0 = t0

def E(self, i, j, k):
    return self.kb * np.power(structure.Atom.angle(i, j, k) - self.t0, 2)

class Fourier(EnergyTerm):
    def __init__(self, f):
        EnergyTerm.__init__(self)
        # kJ / mol
        self.f = f

    def E(self, i, j, k, l):
        e = 0.0
        phi = structure.Atom.dihedral(i, j, k, l)

        for i, f in enumerate(self.f):
            # check the actual function definition
            e += f * (1 + np.cos((1 + i) * phi))

        return e

class RyckaertBellemans(EnergyTerm):
    def __init__(self, *c):
        EnergyTerm.__init__(self)
        # kJ / mol
        self.c = c

    def E(self, i, j, k, l):
        e = 0.0

        phi = structure.Atom.dihedral(i, j, k, l)

        for i, c in enumerate(self.c):
            # check the actual function definition
            e += (-1 if i % 2 else 1) * np.pow(np.cos(phi), i + 1)

        return e


text:
# Import numpy and set seed
import numpy as np
np.random.seed(123)

# Use randint() to simulate a dice
np.random.randint(1,7)

# Use randint() again
print(np.random.randint(1,7))
print(np.random.randint(1,7))


text:
# Copyright 2013 National Renewable Energy Laboratory (NREL)
#
#    Licensed under the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.
#
# ++==++==++==++==++==++==++==++==++==++==
import pyDAKOTA

class AnObj(object):
    """ test object to show we can pass an object through our DAKOTA interface """
    def __init__(self):
        self.mynum = 10

def callback(**kwargs):
    """ callback for rosenbrock test case """
    if ('user_data' in kwargs):
        obj = kwargs['user_data']
        print "magic number is ", obj.mynum

    from numpy import array

    num_fns = kwargs['functions']

    x = kwargs['cv']
    ASV = kwargs['asv']

    f0 = x[1]-x[0]*x[0]
    f1 = 1-x[0]

    retval = dict([])

    if (ASV[0] & 1): # **** f:
        f = array([100*f0*f0+f1*f1])
        retval['fns'] = f

    if (ASV[0] & 2): # **** df/dx:
        g = array([[-400*f0*x[0] - 2*f1, 200*f0]])
        retval['fnGrads'] = g

    if (ASV[0] & 4): # **** d^2f/dx^2:
        fx = x[1]-3*x[0]*x[0]

        h = array([ [ [-400*fx + 2, -400*x[0]],
              [-400*x[0],    200     ] ] ]    )
        retval['fnHessians'] = h

    return(retval)

def test_rundak():
    """ run dakota to solve rosenbrock all driven from python """
    __have_mpi__ = False
    if (not __have_mpi__):
        pyDAKOTA.run_dakota("test_dakface.in", 'daktest.out','dakerrors.log',AnObj())
    else:
        from boost.mpi import world
        pyDAKOTA.run_dakota_mpi("test_dakface.in", world, AnObj())
    print "made it back from dakota call"

if __name__=="__main__":
    """ super simple test of connectivity. solves Rosenbrock, no openMDAO.
    requires test_dakface.in to be present """
    test_rundak()

max_stars_repo_name: WISDEM/pyDAKOTA

reason: from numpy


text:
from collections import OrderedDict
import numpy as np

from ..base import (
    validate_input, connectivity_from_array, pcloud_and_lgroup_from_ranges,
    connectivity_from_range, labeller_func)

@labeller_func(group_label='face_ibug_68')
def face_ibug_68_to_face_ibug_68(pcloud):
    r"""
    Apply the IBUG 68-point semantic labels.

    The semantic labels are as follows:

      - jaw
      - left_eyebrow
      - right_eyebrow
      - nose
      - left_eye
      - right_eye
      - mouth

    References
    ----------
    .. [1] http://www.multipie.org/
    .. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
    """
    from menpo.shape import LabelledPointUndirectedGraph

    n_expected_points = 68
    validate_input(pcloud, n_expected_points)

    jaw_indices = np.arange(0, 17)
    lbrow_indices = np.arange(17, 22)
    rbrow_indices = np.arange(22, 27)
    upper_nose_indices = np.arange(27, 31)
    lower_nose_indices = np.arange(31, 36)
    leye_indices = np.arange(36, 42)
    reye_indices = np.arange(42, 48)
    outer_mouth_indices = np.arange(48, 60)
    inner_mouth_indices = np.arange(60, 68)

    jaw_connectivity = connectivity_from_array(jaw_indices)
    lbrow_connectivity = connectivity_from_array(lbrow_indices)
    rbrow_connectivity = connectivity_from_array(rbrow_indices)
    nose_connectivity = np.vstack([
        connectivity_from_array(upper_nose_indices),
        connectivity_from_array(lower_nose_indices)])
    leye_connectivity = connectivity_from_array(leye_indices, close_loop=True)
    reye_connectivity = connectivity_from_array(reye_indices, close_loop=True)
    mouth_connectivity = np.vstack([
        connectivity_from_array(outer_mouth_indices, close_loop=True),
        connectivity_from_array(inner_mouth_indices, close_loop=True)])

    all_connectivity = np.vstack([
        jaw_connectivity, lbrow_connectivity, rbrow_connectivity,
        nose_connectivity, leye_connectivity, reye_connectivity,
        mouth_connectivity
    ])

    mapping = OrderedDict()
    mapping['jaw'] = jaw_indices
    mapping['left_eyebrow'] = lbrow_indices
    mapping['right_eyebrow'] = rbrow_indices
    mapping['nose'] = np.hstack((upper_nose_indices, lower_nose_indices))
    mapping['left_eye'] = leye_indices
    mapping['right_eye'] = reye_indices
    mapping['mouth'] = np.hstack((outer_mouth_indices, inner_mouth_indices))

    new_pcloud = LabelledPointUndirectedGraph.init_from_indices_mapping(
        pcloud.points, all_connectivity, mapping)

    return new_pcloud, mapping

@labeller_func(group_label='face_ibug_68')
def face_ibug_68_mirrored_to_face_ibug_68(pcloud):
    r"""
    Apply the IBUG 68-point semantic labels, on a pointcloud that has been
    mirrored around the vertical axis (flipped around the Y-axis). Thus, on
    the flipped image the jaw etc would be the wrong way around. This
    rectifies that and returns a new PointCloud whereby all the points
    are oriented correctly.

    The semantic labels applied are as follows:

      - jaw
      - left_eyebrow
      - right_eyebrow
      - nose
      - left_eye
      - right_eye
      - mouth

    References
    ----------
    .. [1] http://www.multipie.org/
    .. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
    """
    new_pcloud, old_map = face_ibug_68_to_face_ibug_68(pcloud,
                                                       return_mapping=True)
    lms_map = np.hstack([old_map['jaw'][::-1],
                         old_map['right_eyebrow'][::-1],
                         old_map['left_eyebrow'][::-1],
                         old_map['nose'][:4],
                         old_map['nose'][4:][::-1],
                         np.roll(old_map['right_eye'][::-1], 4),
                         np.roll(old_map['left_eye'][::-1], 4),
                         np.roll(old_map['mouth'][:12][::-1], 7),
                         np.roll(old_map['mouth'][12:][::-1], 5)])
    return new_pcloud.from_vector(pcloud.points[lms_map]), old_map

@labeller_func(group_label='face_ibug_66')
def face_ibug_68_to_face_ibug_66(pcloud):
    r"""
    Apply the IBUG 66-point semantic labels, but ignoring the 2 points
    describing the inner mouth corners).

    The semantic labels applied are as follows:

      - jaw
      - left_eyebrow
      - right_eyebrow
      - nose
      - left_eye
      - right_eye
      - mouth

    References
    ----------
    .. [1] http://www.multipie.org/
    .. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
    """
    from menpo.shape import LabelledPointUndirectedGraph

    n_expected_points = 68
    validate_input(pcloud, n_expected_points)

    jaw_indices = np.arange(0, 17)
    lbrow_indices = np.arange(17, 22)
    rbrow_indices = np.arange(22, 27)
    upper_nose_indices = np.arange(27, 31)
    lower_nose_indices = np.arange(31, 36)
    leye_indices = np.arange(36, 42)
    reye_indices = np.arange(42, 48)
    outer_mouth_indices = np.arange(48, 60)
    inner_mouth_indices = np.hstack((48, np.arange(60, 63),
                                     54, np.arange(63, 66)))

    jaw_connectivity = connectivity_from_array(jaw_indices)
    lbrow_connectivity = connectivity_from_array(lbrow_indices)
    rbrow_connectivity = connectivity_from_array(rbrow_indices)
    nose_connectivity = np.vstack([
        connectivity_from_array(upper_nose_indices),
        connectivity_from_array(lower_nose_indices)])
    leye_connectivity = connectivity_from_array(leye_indices, close_loop=True)
    reye_connectivity = connectivity_from_array(reye_indices, close_loop=True)
    mouth_connectivity = np.vstack([
        connectivity_from_array(outer_mouth_indices, close_loop=True),
        connectivity_from_array(inner_mouth_indices, close_loop=True)])

    all_connectivity = np.vstack([
        jaw_connectivity, lbrow_connectivity, rbrow_connectivity,
        nose_connectivity, leye_connectivity, reye_connectivity,
        mouth_connectivity])

    mapping = OrderedDict()
    mapping['jaw'] = jaw_indices
    mapping['left_eyebrow'] = lbrow_indices
    mapping['right_eyebrow'] = rbrow_indices
    mapping['nose'] = np.hstack([upper_nose_indices, lower_nose_indices])
    mapping['left_eye'] = leye_indices
    mapping['right_eye'] = reye_indices
    mapping['mouth'] = np.hstack([outer_mouth_indices, inner_mouth_indices])

    # Ignore the two inner mouth points
    ind = np.hstack((np.arange(60), np.arange(61, 64), np.arange(65, 68)))
    new_pcloud = LabelledPointUndirectedGraph.init_from_indices_mapping(
        pcloud.points[ind], all_connectivity, mapping)

    return new_pcloud, mapping

@labeller_func(group_label='face_ibug_51')
def face_ibug_68_to_face_ibug_51(pcloud):
    r"""
    Apply the IBUG 51-point semantic labels, but removing the annotations
    corresponding to the jaw region.

    The semantic labels applied are as follows:

      - left_eyebrow
      - right_eyebrow
      - nose
      - left_eye
      - right_eye
      - mouth

    References
    ----------
    .. [1] http://www.multipie.org/
    .. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
    """
    from menpo.shape import LabelledPointUndirectedGraph

    n_expected_points = 68
    validate_input(pcloud, n_expected_points)

    lbrow_indices = np.arange(0, 5)
    rbrow_indices = np.arange(5, 10)
    upper_nose_indices = np.arange(10, 14)
    lower_nose_indices = np.arange(14, 19)
    leye_indices = np.arange(19, 25)
    reye_indices = np.arange(25, 31)
    outer_mouth_indices = np.arange(31, 43)
    inner_mouth_indices = np.arange(43, 51)

    lbrow_connectivity = connectivity_from_array(lbrow_indices)
    rbrow_connectivity = connectivity_from_array(rbrow_indices)
    nose_connectivity = np.vstack([
        connectivity_from_array(upper_nose_indices),
        connectivity_from_array(lower_nose_indices)])
    leye_connectivity = connectivity_from_array(leye_indices, close_loop=True)
    reye_connectivity = connectivity_from_array(reye_indices, close_loop=True)
    mouth_connectivity = np.vstack([
        connectivity_from_array(outer_mouth_indices, close_loop=True),
        connectivity_from_array(inner_mouth_indices, close_loop=True)])

    all_connectivity = np.vstack([
        lbrow_connectivity, rbrow_connectivity, nose_connectivity,
        leye_connectivity, reye_connectivity, mouth_connectivity])

    mapping = OrderedDict()
    mapping['left_eyebrow'] = lbrow_indices
    mapping['right_eyebrow'] = rbrow_indices
    mapping['nose'] = np.hstack([upper_nose_indices, lower_nose_indices])
    mapping['left_eye'] = leye_indices
    mapping['right_eye'] = reye_indices
    mapping['mouth'] = np.hstack([outer_mouth_indices, inner_mouth_indices])

    # Ignore the two inner mouth points
    ind = np.arange(17, 68)
    new_pcloud = LabelledPointUndirectedGraph.init_from_indices_mapping(
        pcloud.points[ind], all_connectivity, mapping)

    return new_pcloud, mapping

@labeller_func(group_label='face_ibug_49')
def face_ibug_49_to_face_ibug_49(pcloud):
    r"""
    Apply the IBUG 49-point semantic labels.

    The semantic labels applied are as follows:

      - left_eyebrow
      - right_eyebrow
      - nose
      - left_eye
      - right_eye
      - mouth

    References
    ----------
    .. [1] http://www.multipie.org/
    .. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
    """
    from menpo.shape import LabelledPointUndirectedGraph

    n_expected_points = 49
    validate_input(pcloud, n_expected_points)

    lbrow_indices = np.arange(0, 5)
    rbrow_indices = np.arange(5, 10)
    upper_nose_indices = np.arange(10, 14)
    lower_nose_indices = np.arange(14, 19)
    leye_indices = np.arange(19, 25)
    reye_indices = np.arange(25, 31)
    outer_mouth_indices = np.arange(31, 43)
    inner_mouth_indices = np.hstack((31, np.arange(43, 46),
                                     37, np.arange(46, 49)))

    lbrow_connectivity = connectivity_from_array(lbrow_indices)
    rbrow_connectivity = connectivity_from_array(rbrow_indices)
    nose_connectivity = np.vstack([
        connectivity_from_array(upper_nose_indices),
        connectivity_from_array(lower_nose_indices)])
    leye_connectivity = connectivity_from_array(leye_indices, close_loop=True)
    reye_connectivity = connectivity_from_array(reye_indices, close_loop=True)
    mouth_connectivity = np.vstack([
        connectivity_from_array(outer_mouth_indices, close_loop=True),
        connectivity_from_array(inner_mouth_indices, close_loop=True)])

    all_connectivity = np.vstack([
        lbrow_connectivity, rbrow_connectivity, nose_connectivity,
        leye_connectivity, reye_connectivity, mouth_connectivity])

    mapping = OrderedDict()
    mapping['left_eyebrow'] = lbrow_indices
    mapping['right_eyebrow'] = rbrow_indices
    mapping['nose'] = np.hstack([upper_nose_indices, lower_nose_indices])
    mapping['left_eye'] = leye_indices
    mapping['right_eye'] = reye_indices
    mapping['mouth'] = np.hstack([outer_mouth_indices, inner_mouth_indices])

    # Ignore the two inner mouth points
    new_pcloud = LabelledPointUndirectedGraph.init_from_indices_mapping(
        pcloud.points, all_connectivity, mapping)

    return new_pcloud, mapping

@labeller_func(group_label='face_ibug_49')
def face_ibug_68_to_face_ibug_49(pcloud):
    r"""
    Apply the IBUG 49-point semantic labels, but removing the annotations
    corresponding to the jaw region and the 2 describing the inner mouth
    corners.

    The semantic labels applied are as follows:

      - left_eyebrow
      - right_eyebrow
      - nose
      - left_eye
      - right_eye
      - mouth

    References
    ----------
    .. [1] http://www.multipie.org/
    .. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
    """
    from menpo.shape import LabelledPointUndirectedGraph

    n_expected_points = 68
    validate_input(pcloud, n_expected_points)

    lbrow_indices = np.arange(0, 5)
    rbrow_indices = np.arange(5, 10)
    upper_nose_indices = np.arange(10, 14)
    lower_nose_indices = np.arange(14, 19)
    leye_indices = np.arange(19, 25)
    reye_indices = np.arange(25, 31)
    outer_mouth_indices = np.arange(31, 43)
    inner_mouth_indices = np.hstack((31, np.arange(43, 46),
                                     37, np.arange(46, 49)))

    lbrow_connectivity = connectivity_from_array(lbrow_indices)
    rbrow_connectivity = connectivity_from_array(rbrow_indices)
    nose_connectivity = np.vstack([
        connectivity_from_array(upper_nose_indices),
        connectivity_from_array(lower_nose_indices)])
    leye_connectivity = connectivity_from_array(leye_indices, close_loop=True)
    reye_connectivity = connectivity_from_array(reye_indices, close_loop=True)
    mouth_connectivity = np.vstack([
        connectivity_from_array(outer_mouth_indices, close_loop=True),
        connectivity_from_array(inner_mouth_indices, close_loop=True)])

    all_connectivity = np.vstack([
        lbrow_connectivity, rbrow_connectivity, nose_connectivity,
        leye_connectivity, reye_connectivity, mouth_connectivity])

    mapping = OrderedDict()
    mapping['left_eyebrow'] = lbrow_indices
    mapping['right_eyebrow'] = rbrow_indices
    mapping['nose'] = np.hstack([upper_nose_indices, lower_nose_indices])
    mapping['left_eye'] = leye_indices
    mapping['right_eye'] = reye_indices
    mapping['mouth'] = np.hstack([outer_mouth_indices, inner_mouth_indices])

    # Ignore the two inner mouth points
    ind = np.hstack((np.arange(17, 60), np.arange(61, 64), np.arange(65, 68)))
    new_pcloud = LabelledPointUndirectedGraph.init_from_indices_mapping(
        pcloud.points[ind], all_connectivity, mapping)

    return new_pcloud, mapping

@labeller_func(group_label='face_ibug_68_trimesh')
def face_ibug_68_to_face_ibug_68_trimesh(pcloud):
    r"""
    Apply the IBUG 68-point semantic labels, with trimesh connectivity.

    The semantic labels applied are as follows:

      - tri

    References
    ----------
    .. [1] http://www.multipie.org/
    .. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
    """
    from menpo.shape import TriMesh

    n_expected_points = 68
    validate_input(pcloud, n_expected_points)

    tri_list = np.array([[47, 29, 28], [44, 43, 23], [38, 20, 21],
                         [47, 28, 42], [49, 61, 60], [40, 41, 37],
                         [37, 19, 20], [28, 40, 39], [38, 21, 39],
                         [36,  1,  0], [48, 59,  4], [49, 60, 48],
                         [67, 59, 60], [13, 53, 14], [61, 51, 62],
                         [57,  8,  7], [52, 51, 33], [61, 67, 60],
                         [52, 63, 51], [66, 56, 57], [35, 30, 29],
                         [53, 52, 35], [37, 36, 17], [18, 37, 17],
                         [37, 38, 40], [38, 37, 20], [19, 37, 18],
                         [38, 39, 40], [28, 29, 40], [41, 36, 37],
                         [27, 39, 21], [41, 31,  1], [30, 32, 31],
                         [33, 51, 50], [33, 30, 34], [31, 40, 29],
                         [36,  0, 17], [31,  2,  1], [31, 41, 40],
                         [ 1, 36, 41], [31, 49,  2], [ 2, 49,  3],
                         [60, 59, 48], [ 3, 49, 48], [31, 32, 50],
                         [48,  4,  3], [59,  5,  4], [58, 67, 66],
                         [ 5, 59, 58], [58, 59, 67], [ 7,  6, 58],
                         [66, 57, 58], [13, 54, 53], [ 7, 58, 57],
                         [ 6,  5, 58], [50, 61, 49], [62, 67, 61],
                         [31, 50, 49], [32, 33, 50], [30, 33, 32],
                         [34, 52, 33], [35, 52, 34], [53, 63, 52],
                         [62, 63, 65], [62, 51, 63], [66, 65, 56],
                         [63, 53, 64], [62, 66, 67], [62, 65, 66],
                         [57, 56,  9], [65, 63, 64], [ 8, 57,  9],
                         [ 9, 56, 10], [10, 56, 11], [11, 56, 55],
                         [11, 55, 12], [56, 65, 55], [55, 64, 54],
                         [55, 65, 64], [55, 54, 12], [64, 53, 54],
                         [12, 54, 13], [45, 46, 44], [35, 34, 30],
                         [14, 53, 35], [15, 46, 45], [27, 28, 39],
                         [27, 42, 28], [35, 29, 47], [30, 31, 29],
                         [15, 35, 46], [15, 14, 35], [43, 22, 23],
                         [27, 21, 22], [24, 44, 23], [44, 47, 43],
                         [43, 47, 42], [46, 35, 47], [26, 45, 44],
                         [46, 47, 44], [25, 44, 24], [25, 26, 44],
                         [16, 15, 45], [16, 45, 26], [22, 42, 43],
                         [50, 51, 61], [27, 22, 42]])
    new_pcloud = TriMesh(pcloud.points, trilist=tri_list)

    mapping = OrderedDict()
    mapping['tri'] = np.arange(new_pcloud.n_points)

    return new_pcloud, mapping

@labeller_func(group_label='face_ibug_66_trimesh')
def face_ibug_68_to_face_ibug_66_trimesh(pcloud):
    r"""
    Apply the IBUG 66-point semantic labels, with trimesh connectivity.

    The semantic labels applied are as follows:

      - tri

    References
    ----------
    .. [1] http://www.multipie.org/
    .. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
    """
    from menpo.shape import TriMesh

    # Apply face_ibug_68_to_face_ibug_66
    new_pcloud = face_ibug_68_to_face_ibug_66(pcloud)

    # This is in terms of the 66 points
    tri_list = np.array([[47, 29, 28], [44, 43, 23], [38, 20, 21],
                         [47, 28, 42], [40, 41, 37], [51, 62, 61],
                         [37, 19, 20], [28, 40, 39], [38, 21, 39],
                         [36,  1,  0],  [48, 59, 4], [49, 60, 48],
                         [13, 53, 14], [60, 51, 61], [51, 51, 62],
                         [52, 51, 33], [49, 50, 60], [57,  7,  8],
                         [64, 56, 57], [35, 30, 29], [52, 62, 53],
                         [53, 52, 35], [37, 36, 17], [18, 37, 17],
                         [37, 38, 40], [38, 37, 20], [19, 37, 18],
                         [38, 39, 40], [28, 29, 40], [41, 36, 37],
                         [27, 39, 21], [41, 31,  1], [30, 32, 31],
                         [33, 51, 50], [33, 30, 34], [31, 40, 29],
                         [36,  0, 17], [31,  2,  1], [31, 41, 40],
                         [ 1, 36, 41], [31, 49,  2], [ 2, 49,  3],
                         [ 3, 49, 48], [31, 32, 50], [62, 53, 54],
                         [48,  4,  3], [59,  5,  4], [58, 65, 64],
                         [ 5, 59, 58], [58, 59, 65], [ 7,  6, 58],
                         [64, 57, 58], [13, 54, 53], [ 7, 58, 57],
                         [ 6,  5, 58], [63, 55, 54], [65, 59, 48],
                         [31, 50, 49], [32, 33, 50], [30, 33, 32],
                         [34, 52, 33], [35, 52, 34], [48, 60, 65],
                         [64, 63, 56], [60, 65, 61], [65, 64, 61],
                         [57, 56,  9], [ 8, 57,  9], [64, 63, 61],
                         [ 9, 56, 10], [10, 56, 11], [11, 56, 55],
                         [11, 55, 12], [56, 63, 55], [51, 52, 62],
                         [55, 54, 12], [63, 54, 62], [61, 62, 63],
                         [12, 54, 13], [45, 46, 44], [35, 34, 30],
                         [14, 53, 35], [15, 46, 45], [27, 28, 39],
                         [27, 42, 28], [35, 29, 47], [30, 31, 29],
                         [15, 35, 46], [15, 14, 35], [43, 22, 23],
                         [27, 21, 22], [24, 44, 23], [44, 47, 43],
                         [43, 47, 42], [46, 35, 47], [26, 45, 44],
                         [46, 47, 44], [25, 44, 24], [25, 26, 44],
                         [16, 15, 45], [16, 45, 26], [22, 42, 43],
                         [50, 60, 51], [27, 22, 42]])

    new_pcloud = TriMesh(new_pcloud.points, trilist=tri_list, copy=False)

    mapping = OrderedDict()
    mapping['tri'] = np.arange(new_pcloud.n_points)

    return new_pcloud, mapping

@labeller_func(group_label='face_ibug_51_trimesh')
def face_ibug_68_to_face_ibug_51_trimesh(pcloud):
    r"""
    Apply the IBUG 51-point semantic labels, with trimesh connectivity..

    The semantic labels applied are as follows:

      - tri

    References
    ----------
    .. [1] http://www.multipie.org/
    .. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
    """
    from menpo.shape import TriMesh

    # Apply face_ibug_68_to_face_ibug_51
    new_pcloud = face_ibug_68_to_face_ibug_51(pcloud)

    # This is in terms of the 51 points
    tri_list = np.array([[30, 12, 11], [27, 26,  6], [21,  3,  4],
                         [30, 11, 25], [32, 44, 43], [23, 24, 20],
                         [20,  2,  3], [11, 23, 22], [21,  4, 22],
                         [32, 43, 31], [50, 42, 43], [44, 34, 45],
                         [35, 34, 16], [44, 50, 43], [35, 46, 34],
                         [49, 39, 40], [18, 13, 12], [36, 35, 18],
                         [20, 19,  0], [ 1, 20,  0], [20, 21, 23],
                         [21, 20,  3], [ 2, 20,  1], [21, 22, 23],
                         [11, 12, 23], [24, 19, 20], [10, 22,  4],
                         [13, 15, 14], [16, 34, 33], [16, 13, 17],
                         [14, 23, 12], [14, 24, 23], [43, 42, 31],
                         [14, 15, 33], [41, 50, 49], [41, 42, 50],
                         [49, 40, 41], [33, 44, 32], [45, 50, 44],
                         [14, 33, 32], [15, 16, 33], [13, 16, 15],
                         [17, 35, 16], [18, 35, 17], [36, 46, 35],
                         [45, 46, 48], [45, 34, 46], [49, 48, 39],
                         [46, 36, 47], [45, 49, 50], [45, 48, 49],
                         [48, 46, 47], [39, 48, 38], [38, 47, 37],
                         [38, 48, 47], [47, 36, 37], [28, 29, 27],
                         [18, 17, 13], [10, 11, 22], [10, 25, 11],
                         [18, 12, 30], [13, 14, 12], [26,  5,  6],
                         [10,  4,  5], [ 7, 27,  6], [27, 30, 26],
                         [26, 30, 25], [29, 18, 30], [ 9, 28, 27],
                         [29, 30, 27], [ 8, 27,  7], [ 8,  9, 27],
                         [ 5, 25, 26], [33, 34, 44], [10,  5, 25]])

    new_pcloud = TriMesh(new_pcloud.points, trilist=tri_list, copy=False)

    mapping = OrderedDict()
    mapping['tri'] = np.arange(new_pcloud.n_points)

    return new_pcloud, mapping

@labeller_func(group_label='face_ibug_49_trimesh')
def face_ibug_68_to_face_ibug_49_trimesh(pcloud):
    r"""
    Apply the IBUG 49-point semantic labels, with trimesh connectivity.

    The semantic labels applied are as follows:

      - tri

    References
    ----------
    .. [1] http://www.multipie.org/
    .. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
    """
    from menpo.shape import TriMesh

    # Apply face_ibug_68_to_face_ibug_49
    new_pcloud = face_ibug_68_to_face_ibug_49(pcloud)

    # This is in terms of the 49 points
    tri_list = np.array([[47, 29, 28], [44, 43, 23], [38, 20, 21],
                         [47, 28, 42], [40, 41, 37], [51, 62, 61],
                         [37, 19, 20], [28, 40, 39], [38, 21, 39],
                         [36,  1,  0],  [48, 59, 4], [49, 60, 48],
                         [13, 53, 14], [60, 51, 61], [51, 51, 62],
                         [52, 51, 33], [49, 50, 60], [57,  7,  8],
                         [64, 56, 57], [35, 30, 29], [52, 62, 53],
                         [53, 52, 35], [37, 36, 17], [18, 37, 17],
                         [37, 38, 40], [38, 37, 20], [19, 37, 18],
                         [38, 39, 40], [28, 29, 40], [41, 36, 37],
                         [27, 39, 21], [41, 31,  1], [30, 32, 31],
                         [33, 51, 50], [33, 30, 34], [31, 40, 29],
                         [36,  0, 17], [31,  2,  1], [31, 41, 40],
                         [ 1, 36, 41], [31, 49,  2], [ 2, 49,  3],
                         [ 3, 49, 48], [31, 32, 50], [62, 53, 54],
                         [48,  4,  3], [59,  5,  4], [58, 65, 64],
                         [ 5, 59, 58], [58, 59, 65], [ 7,  6, 58],
                         [64, 57, 58], [13, 54, 53], [ 7, 58, 57],
                         [ 6,  5, 58], [63, 55, 54], [65, 59, 48],
                         [31, 50, 49], [32, 33, 50], [30, 33, 32],
                         [34, 52, 33], [35, 52, 34], [48, 60, 65],
                         [64, 63, 56], [60, 65, 61], [65, 64, 61],
                         [57, 56,  9], [ 8, 57,  9], [64, 63, 61],
                         [ 9, 56, 10], [10, 56, 11], [11, 56, 55],
                         [11, 55, 12], [56, 63, 55], [51, 52, 62],
                         [55, 54, 12], [63, 54, 62], [61, 62, 63],
                         [12, 54, 13], [45, 46, 44], [35, 34, 30],
                         [14, 53, 35], [15, 46, 45], [27, 28, 39],
                         [27, 42, 28], [35, 29, 47], [30, 31, 29],
                         [15, 35, 46], [15, 14, 35], [43, 22, 23],
                         [27, 21, 22], [24, 44, 23], [44, 47, 43],
                         [43, 47, 42], [46, 35, 47], [26, 45, 44],
                         [46, 47, 44], [25, 44, 24], [25, 26, 44],
                         [16, 15, 45], [16, 45, 26], [22, 42, 43],
                         [50, 60, 51], [27, 22, 42]])

    new_pcloud = TriMesh(new_pcloud.points, trilist=tri_list, copy=False)

    mapping = OrderedDict()
    mapping['tri'] = np.arange(new_pcloud.n_points)

    return new_pcloud, mapping

@labeller_func(group_label='face_ibug_65')
def face_ibug_68_to_face_ibug_65(pcloud):
    r"""
    Apply the IBUG 68 point semantic labels, but ignore the 3 points that are
    coincident for a closed mouth (bottom of the inner mouth).

    The semantic labels applied are as follows:

      - jaw
      - left_eyebrow
      - right_eyebrow
      - nose
      - left_eye
      - right_eye
      - mouth

    References
    ----------
    .. [1] http://www.multipie.org/
    .. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
    """
    from menpo.shape import LabelledPointUndirectedGraph

    # Apply face_ibug_68_to_face_ibug_68
    new_pcloud, mapping = face_ibug_68_to_face_ibug_68(pcloud,
                                                       return_mapping=True)

    # The coincident points are considered the final 3 landmarks (bottom of
    # the inner mouth points). We remove all the edges for the inner mouth
    # which are the last 8.
    edges = new_pcloud.edges[:-8]
    # Re-add the inner mouth without the bottom 3 points
    edges = np.vstack([edges,
                       connectivity_from_range((60, 65), close_loop=True)])

    # Luckily, OrderedDict maintains the original ordering despite updates
    outer_mouth_indices = np.arange(48, 60)
    inner_mouth_indices = np.arange(60, 65)
    mapping['mouth'] = np.hstack([outer_mouth_indices, inner_mouth_indices])

    new_pcloud = LabelledPointUndirectedGraph.init_from_indices_mapping(
        new_pcloud.points[:-3], edges, mapping)

    return new_pcloud, mapping

@labeller_func(group_label='face_imm_58')
def face_imm_58_to_face_imm_58(pcloud):
    r"""
    Apply the 58-point semantic labels from the IMM dataset.

    The semantic labels applied are as follows:

      - jaw
      - left_eye
      - right_eye
      - left_eyebrow
      - right_eyebrow
      - mouth
      - nose

    References
    ----------
    .. [1] http://www2.imm.dtu.dk/~aam/
    """
    n_expected_points = 58
    validate_input(pcloud, n_expected_points)

    labels = OrderedDict([
        ('jaw', (0, 13, False)),
        ('left_eye', (13, 21, True)),
        ('right_eye', (21, 29, True)),
        ('left _eyebrow', (29, 34, False)),
        ('right_eyebrow', (34, 39, False)),
        ('mouth', (39, 47, True)),
        ('nose', (47, 58, False))
    ])
    return pcloud_and_lgroup_from_ranges(pcloud, labels)

@labeller_func(group_label='face_lfpw_29')
def face_lfpw_29_to_face_lfpw_29(pcloud):
    r"""
    Apply the 29-point semantic labels from the original LFPW dataset.

    The semantic labels applied are as follows:

      - chin
      - left_eye
      - right_eye
      - left_eyebrow
      - right_eyebrow
      - mouth
      - nose

    References
    ----------
    .. [1] http://homes.cs.washington.edu/~neeraj/databases/lfpw/
    """
    from menpo.shape import LabelledPointUndirectedGraph

    n_expected_points = 29
    validate_input(pcloud, n_expected_points)

    chin_indices = np.array([28])
    outer_leye_indices = np.array([8, 12, 10, 13])
    pupil_leye_indices = np.array([16])
    outer_reye_indices = np.array([11, 14, 9, 15])
    pupil_reye_indices = np.array([17])
    lbrow_indices = np.array([0, 4, 2, 5])
    rbrow_indices = np.array([3, 6, 1, 7])
    outer_mouth_indices = np.array([22, 24, 23, 27])
    inner_mouth_indices = np.array([22, 25, 23, 26])
    nose_indices = np.array([18, 20, 19, 21])

    chin_connectivity = connectivity_from_array(chin_indices, close_loop=True)
    leye_connectivity = connectivity_from_array(outer_leye_indices,
                                                close_loop=True)
    reye_connectivity = connectivity_from_array(outer_reye_indices,
                                                close_loop=True)
    lbrow_connectivity = connectivity_from_array(lbrow_indices,
                                                 close_loop=True)
    rbrow_connectivity = connectivity_from_array(rbrow_indices,
                                                 close_loop=True)
    mouth_connectivity = np.vstack([
        connectivity_from_array(outer_mouth_indices, close_loop=True),
        connectivity_from_array(inner_mouth_indices, close_loop=True)])
    nose_connectivity = connectivity_from_array(nose_indices, close_loop=True)

    all_connectivity = np.vstack([
        chin_connectivity, leye_connectivity, reye_connectivity,
        lbrow_connectivity, rbrow_connectivity, mouth_connectivity,
        nose_connectivity])

    mapping = OrderedDict()
    mapping['chin'] = chin_indices
    mapping['left_eye'] = np.hstack((outer_leye_indices, pupil_leye_indices))
    mapping['right_eye'] = np.hstack((outer_reye_indices, pupil_reye_indices))
    mapping['left_eyebrow'] = lbrow_indices
    mapping['right_eyebrow'] = rbrow_indices
    mapping['mouth'] = np.hstack((outer_mouth_indices, inner_mouth_indices))
    mapping['nose'] = nose_indices

    new_pcloud = LabelledPointUndirectedGraph.init_from_indices_mapping(
        pcloud.points, all_connectivity, mapping)

    return new_pcloud, mapping

def _build_upper_eyelid():
    top_indices = np.arange(0, 7)
    middle_indices = np.arange(12, 17)
    upper_eyelid_indices = np.hstack((top_indices, middle_indices))

    upper_eyelid_connectivity = list(zip(top_indices, top_indices[1:]))
    upper_eyelid_connectivity += [(0, 12)]
    upper_eyelid_connectivity += list(zip(middle_indices, middle_indices[1:]))
    upper_eyelid_connectivity += [(16, 6)]

    return upper_eyelid_indices, upper_eyelid_connectivity

@labeller_func(group_label='eye_ibug_open_38')
def eye_ibug_open_38_to_eye_ibug_open_38(pcloud):
    r"""
    Apply the IBUG 38-point open eye semantic labels.

    The semantic labels applied are as follows:

      - upper_eyelid
      - lower_eyelid
      - iris
      - pupil
      - sclera
    """
    from menpo.shape import LabelledPointUndirectedGraph

    n_expected_points = 38
    validate_input(pcloud, n_expected_points)

    upper_el_indices, upper_el_connectivity = _build_upper_eyelid()

    iris_range = (22, 30)
    pupil_range = (30, 38)
    sclera_top = np.arange(12, 17)
    sclera_bottom = np.arange(17, 22)
    sclera_indices = np.hstack((0, sclera_top, 6, sclera_bottom))
    lower_el_top = np.arange(17, 22)
    lower_el_bottom = np.arange(7, 12)
    lower_el_indices = np.hstack((6, lower_el_top, 0, lower_el_bottom))

    iris_connectivity = connectivity_from_range(iris_range, close_loop=True)
    pupil_connectivity = connectivity_from_range(pupil_range, close_loop=True)

    sclera_connectivity = list(zip(sclera_top, sclera_top[1:]))
    sclera_connectivity += [(0, 21)]
    sclera_connectivity += list(zip(sclera_bottom, sclera_bottom[1:]))
    sclera_connectivity += [(6, 17)]

    lower_el_connectivity = list(zip(lower_el_top, lower_el_top[1:]))
    lower_el_connectivity += [(6, 7)]
    lower_el_connectivity += list(zip(lower_el_bottom, lower_el_bottom[1:]))
    lower_el_connectivity += [(11, 0)]

    all_connectivity = np.asarray(upper_el_connectivity +
                                  lower_el_connectivity +
                                  iris_connectivity.tolist() +
                                  pupil_connectivity.tolist() +
                                  sclera_connectivity)

    mapping = OrderedDict()
    mapping['upper_eyelid'] = upper_el_indices
    mapping['lower_eyelid'] = lower_el_indices
    mapping['pupil'] = np.arange(*pupil_range)
    mapping['iris'] = np.arange(*iris_range)
    mapping['sclera'] = sclera_indices

    new_pcloud = LabelledPointUndirectedGraph.init_from_indices_mapping(
        pcloud.points, all_connectivity, mapping)

    return new_pcloud, mapping

@labeller_func(group_label='eye_ibug_close_17')
def eye_ibug_close_17_to_eye_ibug_close_17(pcloud):
    r"""
    Apply the IBUG 17-point close eye semantic labels.

    The semantic labels applied are as follows:

      - upper_eyelid
      - lower_eyelid
    """
    from menpo.shape import LabelledPointUndirectedGraph

    n_expected_points = 17
    validate_input(pcloud, n_expected_points)

    upper_indices, upper_connectivity = _build_upper_eyelid()

    middle_indices = np.arange(12, 17)
    bottom_indices = np.arange(6, 12)
    lower_indices = np.hstack((bottom_indices, 0, middle_indices))
    lower_connectivity = list(zip(bottom_indices, bottom_indices[1:]))
    lower_connectivity += [(0, 12)]
    lower_connectivity += list(zip(middle_indices, middle_indices[1:]))
    lower_connectivity += [(11, 0)]

    all_connectivity = np.asarray(upper_connectivity + lower_connectivity)

    mapping = OrderedDict()
    mapping['upper_eyelid'] = upper_indices
    mapping['lower_eyelid'] = lower_indices

    new_pcloud = LabelledPointUndirectedGraph.init_from_indices_mapping(
        pcloud.points, all_connectivity, mapping)

    return new_pcloud, mapping

@labeller_func(group_label='eye_ibug_open_38_trimesh')
def eye_ibug_open_38_to_eye_ibug_open_38_trimesh(pcloud):
    r"""
    Apply the IBUG 38-point open eye semantic labels, with trimesh connectivity.

    The semantic labels applied are as follows:

      - tri
    """
    from menpo.shape import TriMesh

    n_expected_points = 38
    validate_input(pcloud, n_expected_points)

    tri_list = np.array([[29, 36, 28], [22, 13, 23], [12,  1,  2],
                         [29, 30, 37], [13,  3, 14], [13, 12,  2],
                         [19,  8,  9], [25, 33, 24], [36, 37, 33],
                         [24, 32, 31], [33, 37, 31], [35, 34, 27],
                         [35, 36, 33], [ 3, 13,  2], [14, 24, 23],
                         [33, 32, 24], [15, 25, 14], [25, 26, 34],
                         [22, 30, 29], [31, 37, 30], [24, 31, 23],
                         [32, 33, 31], [22, 12, 13], [ 0,  1, 12],
                         [14, 23, 13], [31, 30, 23], [28, 19, 20],
                         [21, 11,  0], [12, 21,  0], [20, 11, 21],
                         [20, 10, 11], [21, 29, 20], [21, 12, 22],
                         [30, 22, 23], [29, 21, 22], [27, 19, 28],
                         [29, 37, 36], [29, 28, 20], [36, 35, 28],
                         [20, 19, 10], [10, 19,  9], [28, 35, 27],
                         [19, 19,  8], [17, 16,  6], [18,  7,  8],
                         [25, 34, 33], [18, 27, 17], [18, 19, 27],
                         [18, 17,  7], [27, 26, 17], [17,  6,  7],
                         [14, 25, 24], [34, 35, 33], [17, 26, 16],
                         [27, 34, 26], [ 3, 15, 14], [15, 26, 25],
                         [ 4, 15,  3], [16, 26, 15], [16,  4,  5],
                         [16, 15,  4], [16,  5,  6], [8, 18, 19]])

    new_pcloud = TriMesh(pcloud.points, trilist=tri_list, copy=False)

    mapping = OrderedDict()
    mapping['tri'] = np.arange(new_pcloud.n_points)

    return new_pcloud, mapping

@labeller_func(group_label='eye_ibug_close_17_trimesh')
def eye_ibug_close_17_to_eye_ibug_close_17_trimesh(pcloud):
    r"""
    Apply the IBUG 17-point close eye semantic labels, with trimesh
    connectivity.

    The semantic labels applied are as follows:

      - tri
    """
    from menpo.shape import TriMesh

    n_expected_points = 17
    validate_input(pcloud, n_expected_points)

    tri_list = np.array([[10, 11, 13], [ 3, 13,  2], [ 4, 14,  3],
                         [15,  5, 16], [12, 11,  0], [13, 14, 10],
                         [13, 12,  2], [14, 13,  3], [ 0,  1, 12],
                         [ 2, 12,  1], [13, 11, 12], [ 9, 10, 14],
                         [15,  9, 14], [ 7,  8, 15], [ 5,  6, 16],
                         [15, 14,  4], [ 7, 15, 16], [ 8,  9, 15],
                         [15,  4,  5], [16,  6,  7]])

    new_pcloud = TriMesh(pcloud.points, trilist=tri_list, copy=False)

    mapping = OrderedDict()
    mapping['tri'] = np.arange(new_pcloud.n_points)

    return new_pcloud, mapping

@labeller_func(group_label='tongue_ibug_19')
def tongue_ibug_19_to_tongue_ibug_19(pcloud):
    r"""
    Apply the IBUG 19-point tongue semantic labels.

    The semantic labels applied are as follows:

      - outline
      - bisector
    """
    n_expected_points = 19
    validate_input(pcloud, n_expected_points)

    labels = OrderedDict([
        ('outline', (0, 13, False)),
        ('bisector', (13, 19, False))
    ])
    return pcloud_and_lgroup_from_ranges(pcloud, labels)

max_stars_repo_name: yutiansut/menpo

max_issues_repo_name: yutiansut/menpo

max_forks_repo_name: yutiansut/menpo