
def products(data):
    from functools import reduce
    return reduce(lambda x,y:x*y,data)

def rotate_points_along_z(points, angle):
    import numpy as np
    """
    Args:
        points: (N, 3 + C)
        angle: angle along z-axis, angle increases x ==> y
    Returns:
    """
    cosa = np.cos(angle)
    sina = np.sin(angle)
    zeros=0.0
    ones=1.0
    rot_matrix = np.array(
        [cosa,  sina, zeros,
        -sina, cosa, zeros,
        zeros, zeros, ones]
    ).reshape(3, 3)
    points_rot = np.dot(points[..., 0:3], rot_matrix)
    points_rot = np.concatenate((points_rot, points[..., 3:]), axis=-1)
    return points_rot

def rotate_points2d(points, angle):
    import torch
    """
    Args:
        points: (B, N, 2)
        angle: (B), angle along z-axis, angle increases x ==> y
    Returns:

    """
    cosa = torch.cos(angle)
    sina = torch.sin(angle)
    zeros = angle.new_zeros(points.shape[0])
    ones = angle.new_ones(points.shape[0])
    rot_matrix = torch.stack((
        cosa,  sina,
        -sina, cosa,
    ), dim=1).view(-1, 2, 2).float()
    points_rot = torch.matmul(points[:, :, 0:2], rot_matrix)
    points_rot = torch.cat((points_rot, points[:, :, 2:]), dim=-1)
    return points_rot

def quat2euler(quat):
    from scipy.spatial.transform import Rotation as R
    r = R.from_quat(quat)
    return r.as_euler('xyz', degrees=False)