def fit_limbs(self):
        for limb in LIMBS:
            data = self.data
            lengths = self.lengths
            A = np.array(data[limb[0]])
            B = np.array(data[limb[1]])
            C = np.array(data[limb[2]])
            Y = normalize_rows(B - A)
            X = normalize_rows(C - A)
            Yn = normalize_rows(Y - np.sum((X * Y), axis=-1, keepdims=True) * X)
            a = ((C - A) * X).sum(-1)
            b = ((B - A) * X).sum(-1)
            c = ((B - A) * Yn).sum(-1)
            # will be dog slow for now
            temp = {}
            temp["start"] = []
            temp["mid"] = []
            temp["end"] = []
            L1 = self.lengths[(limb[0], limb[1])]
            L2 = self.lengths[(limb[1], limb[2])]
            L = len(A)
            for i in xrange(L):
                S, M, E = triangle_min(L1, L2, a[i], b[i], c[i])
                temp["start"].append(S)
                temp["mid"].append([M[0], M[1]])
                temp["end"].append([E[0], E[1]])
            temp["start"] = np.array(temp["start"])
            temp["end"] = np.array(temp["end"])
            temp["mid"] = np.array(temp["mid"])

            self.data[limb[0]] = A + (temp["start"].T[0]).reshape(L, 1) * X + (temp["start"].T[1]).reshape(L, 1) * Yn
            self.data[limb[1]] = A + (temp["mid"].T[0]).reshape(L, 1) * X + (temp["mid"].T[1]).reshape(L, 1) * Yn
            self.data[limb[2]] = A + (temp["end"].T[0]).reshape(L, 1) * X + (temp["end"].T[1]).reshape(L, 1) * Yn
 def smooth(self, q):
     """Implement double exponential smoothing on generated timeseries."""
     """Copying most of MS code. Probably painfully slow in Python because
     it is not vectorized."""
     filt = np.zeros(q.shape)
     trend = np.zeros(q.shape)
     
     filt[0] = q[0]
     trend[0] = np.array([1.0, 0.0, 0.0, 0.0])
     
     filt[1] = slerp(q[0], filt[0], 0.5)
     diff_started = rotation_between(filt[1], filt[0])
     trend[1] = slerp(trend[0], diff_started, self.correction)
         
     for i in range(2, len(q)):
         diff_jitter = rotation_between(q[i], filt[i-1])
         diff_val_jitter = np.abs(quaternion_angle(diff_jitter))
         if diff_val_jitter <= self.jitter_radius:
             filt[i] = slerp(filt[i-1], q[i], diff_val_jitter/self.jitter_radius)
         else:
             filt[i] = q[i]
         filt[i] = normalize_rows(slerp(filt[i], prod(filt[i-1], trend[i-1]), self.smoothing))
         diff_jitter = rotation_between(filt[i], filt[i-1])
         trend[i] = normalize_rows(slerp(trend[i-1], diff_jitter, self.correction))
     
     return np.array(filt)
    def __init__(self, data=None):
        if data is None:
            with open("DataFiles/master/master.json", "rb") as file:
                data = json.load(file)
        self.coords = data
        try:
            self.kin = data['kin']
            self.qual = data['qual']
        except KeyError:
            self.kin = data
        for hinge in HINGES:
            self.kin[hinge + 'Angle'] = angle_handlers.z_angle(data=self.kin,
                                                             bone=[hinge],
                                                             method='kin')

            normal_fore_limb = None
            normal_upper_limb = None
            ball_bone = None
            for seg in data_model.KIN_SEGMENTS:
                bone = data_model.KIN_SEGMENTS[seg]
                add = None
                if hinge == bone[0]:
                    add = 'PostLength'
                    normal_fore_limb = normalize_rows(np.array(self.kin[bone[1]]) - np.array(self.kin[bone[0]]))
                if hinge == bone[1]:
                    add = 'PreLength'
                    normal_upper_limb = normalize_rows(np.array(self.kin[bone[1]]) - np.array(self.kin[bone[0]]))
                    ball_bone = bone[0]
                if add is not None:
                    self.kin[hinge + add] = correctors.limb_length(limb=bone, data=self.kin)

            z = normal_upper_limb
            x = normalize_rows(normal_fore_limb - np.dot((normal_fore_limb * normal_upper_limb).sum(-1).T, normal_upper_limb))
            y = np.cross(z,x)
            self.kin[ball_bone + "Axis"] = z
            self.kin[ball_bone + "Normal"] = y
        newlabels = []
        for label in data_model.KIN_LABELS:
            if label not in HINGES and label not in BALLS:
                newlabels.append(label)
            elif label in HINGES:
                newlabels.append(label+'Angle')
                newlabels.append(label+'PostLength')
                newlabels.append(label+'PreLength')
            elif label in BALLS:
                newlabels.append(label+'Axis')
                newlabels.append(label+'Normal')
        self.newkin = {label: self.kin[label] for label in newlabels}
def axis_mover(z):
    u = normalize_rows(np.column_stack((-1.0 * z.T[1], -1.0 * z.T[0])))
    alpha = np.arccos(z.T[2])
    if len(z.shape) == 1:
        x = np.cos(0.5 * alpha)
        w = 0.0
    else:
        x = np.cos(0.5 * alpha) * np.ones((z.shape[0],))
        w = np.zeros((z.shape[0],))
    return join_parts((x, np.sin(0.5 * alpha) * u.T[0], np.sin(0.5 * alpha) * u.T[1], w))
 def __init__(self, name, limits=[0, 0], direction=np.array((0.01, 0, 1)), axial=0, sign=1.0):
     self.name = name
     self.limits = limits
     #  approx: equation for cone ax^2 + bz^2 >= y^2 constraining motion; outside certain cone.
     self.direction = normalize_rows(
         direction
     )  # point on 2-sphere giving (initial) direction of child relative to parent
     # self.phi = 0 # rotation around x
     # self.theta = 0 # rotation around z
     self.axial = axial  # rotation around bone axis
     self.sign = sign
 def greedy_fit_point(self, point, filter=True):  # point should be made of numpy arrays....
     new_point = sg_filter_data(point) if filter else point
     fitted_point = dict()
     fitted_point["HipCenter"] = new_point["HipCenter"]
     visited = ["HipCenter"]
     change = 1
     while change > 0:
         length = len(visited)
         for edge in data_model.KIN_TREE:
             if edge[0] in visited and edge[1] not in visited:
                 edge_length = self.lengths[edge]
                 dir = normalize_rows(np.array(new_point[edge[1]]) - np.array(fitted_point[edge[0]]))
                 fitted_point[edge[1]] = fitted_point[edge[0]] + edge_length * dir
                 visited.append(edge[1])
             # print edge[1]
         change = len(visited) - length
     # other_keys = [label for label in new_point if label not in data_model.KIN_TREE]
     # for label in other_keys:
     #    fitted_point[label] = new_point[label]
     return fitted_point
    def ingest_data(self, data, modeled=True, length_fit=False):
        self.BM = BodyModel(data)
        if length_fit:
            self.BM.fit()
        self.data = data
        if modeled:
            n = normalize_data({'kin': self.BM.data})['kin']
            X = np.column_stack((n[key] for key in KL))
            self.model_data = normalize_rows(X)

        times = self.data['Time']
        newtimes = np.linspace(times[0], times[-1], 1000)

        self.times = times
        self.newtimes = newtimes

        floor = self.floor if self.floor else 0.5 * (np.mean(self.data['FootRight'].T[2]) + np.mean(self.data['FootLeft'].T[2]))
        #if (floor == None): floor = 0.5 * (np.mean(self.data['FootRight'].T[2]) + np.mean(self.data['FootLeft'].T[2]))
        vl = VL(self.BM.data, floor=floor)
        modeled_vl = vl + VLm(self.model_data) if modeled else vl
        subsampled_vl = UnivariateSpline(times, modeled_vl, s=0)(newtimes)
        self.smoothed_VL = UnivariateSpline(newtimes, sav_gol.savgol_filter(subsampled_vl, 31, 3), s=0) # smooth pretty hard to stop wobbling, overest?

        hl = HL(self.BM.data)
        modeled_hl = hl + HLm(self.model_data) if modeled else hl
        subsampled_hl = UnivariateSpline(times, modeled_hl, s=0)(newtimes)
        self.smoothed_HL = UnivariateSpline(newtimes, sav_gol.savgol_filter(subsampled_hl, 31, 3), s=0) # smooth pretty hard to stop wobbling, overest?

        aa = AA(self.BM.data)
        modeled_aa = aa + AAm(self.model_data) if modeled else aa
        subsampled_aa = UnivariateSpline(times, modeled_aa, s=0)(newtimes)
        self.smoothed_AA = UnivariateSpline(newtimes, sav_gol.savgol_filter(subsampled_aa, 31, 3), s=0) # smooth pretty hard to stop wobbling, overest?

        self.find_F()
        # self.find_origins()
        # self.find_ends()
        self.find_V()
        self.find_H()
        self.find_D()
        self.find_A()
def canonical(q):
    z = conjugate(q, np.array([0.0, 0.0, 0.0, 1.0])).T[1:].T
    z = normalize_rows(z)
    return axis_mover(z)
def quaternion_angle(a):
    b = normalize_rows(a)
    return 2.0 * np.arccos((b.T)[2].T)
def normalize_data(data, center_floor = False):
    """Assume that data is aligned (so qual and kin have best fit)"""

    qual_present = hasattr(data, 'qual')

    k = data['kin']
    kn = dict()

    if qual_present:
        q = data['qual']
        qn = dict()

    center = center_of_mass(k)
    if center_floor:
        center *= np.array((1,1,0))

    # first translate center of mass to the origin
    for key in k.keys():
        if key in data_model.KIN_LABELS:
            kn[key] = np.array(k[key]) - center
        else:
            kn[key] = k[key]
    if qual_present:
        for key in q.keys():
            if len(q[key][0]) == 3:
                qn[key] = np.array(q[key]) - center
            else:
                qn[key] = q[key]

    # coordinate system to use: z axis, hip orientation vector (suitably
    # gram schmidted) --  call this x, whatever is necessary to make right-handed system -- y

    hr = kn['HipRight']
    hl = kn['HipLeft']
    n = normalize_rows(np.cross(hl, hr))
    x = normalize_rows(n - n * np.array([0,0,1]))
    y = normalize_rows(np.cross(np.array([0,0,1]), x))

    outk = {}
    if qual_present:
        outq = {}

    for key in kn.keys():
        if key in data_model.KIN_LABELS:
            outk[key] = np.column_stack(((kn[key] * x).sum(-1), (kn[key] * y).sum(-1), kn[key].T[2]))
        else:
            outk[key] = k[key]

    if qual_present:
        for key in qn.keys():
            if len(q[key][0]) == 3:
                outq[key] = np.column_stack(((qn[key] * x).sum(-1), (qn[key] * y).sum(-1), qn[key].T[2]))
            elif key != 'Time' and key != 'HipCenterQ':
                outq[key] = q[key]
            elif key == 'HipCenterQ':
                theta = np.arccos(x.T[0])
                s = np.cos(0.5 * theta)
                t = np.sin(0.5 * theta)
                outq[key] = quaternions.conjugate(np.column_stack([s, np.zeros(len(s)), np.zeros(len(s)), t]), np.array(q[key]))

    # try:
    #     outk['Time'] = k['Time']
    # except KeyError:
    #     pass
    if qual_present:
        try:
            outq['Time'] = q['Time']
        except KeyError:
            pass

    if qual_present:
        return {'unnormalized_kin': k, 'unnormalized_qual': q, 'kin': outk, 'qual': outq}
    else:
        return {'unnormalized_kin': k, 'kin': outk}
def proj(a,b):
    c = normalize_rows(b)
    return np.dot((a * c).sum(-1), c)