# Path: ldif/util/np_util.py
# def batch_np(arr, batch_size):
# def make_coordinate_grid(height, width, is_screen_space, is_homogeneous):
# def make_coordinate_grid_3d(length, height, width, is_screen_space,
#                             is_homogeneous):
# def filter_valid(mask, vals):
# def zero_by_mask(mask, vals, replace_with=0.0):
# def make_mask(im, thresh=0.0):
# def make_pixel_mask(im):
# def thresh_and_radius_to_distance(radius, thresh):
# def plot_rbfs_at_thresh(centers, radii, thresh=0.5):
# def plot_rbfs(centers, radii, scale=10.0):
# def cube_and_render(volume, thresh):
# def sample_surface(quadrics, centers, radii, length, height, width,
#                    renormalize):
# def visualize_prediction(quadrics,
#                          centers,
#                          radii,
#                          renormalize,
#                          thresh=0.0,
#                          input_volumes=None):
# 
# Path: ldif/util/file_util.py
# def readlines(p):
# def readbin(p):
# def writebin(p, s):
# def writetxt(p, s):
# def write_np(path, arr):
# def read_grd(path):
# def read_sif_v1(path, verbose=False):
# def read_lines(p):
# def read_image(p):
# def read_npz(p):
# def read_np(p):
# def read_txt_to_np(p):
# def read_py2_pkl(p):
# def write_mesh(path, mesh):
# def read_mesh(path):
# def read_csv(path):
# def read_normals(path_to_dir, im_count=20, leading='_depth'):
# def write_points(path_ext_optional, points):
# def write_grd(path, volume, world2grid=None):
# def write_depth_image(path, depth_image):


import numpy as np
from ldif.util import np_util
from ldif.util.file_util import log

  Returns:
    Numpy array with shape [..., 3].
  """
  shape_in = arr.shape
  if are_points:
    hom = np.ones_like(arr[..., 0:1], dtype=np.float32)
  else:
    hom = np.zeros_like(arr[..., 0:1], dtype=np.float32)
  assert arr.shape[-1] == 3 + feature_count
  to_tx = np.concatenate([arr[..., :3], hom], axis=-1)
  to_tx = np.reshape(to_tx, [-1, 4])
  transformed = np.matmul(to_tx, m.T)[:, :3]
  if feature_count:
    flat_samples = np.reshape(arr[..., 3:], [-1, feature_count])
    transformed = np.concatenate([transformed, flat_samples], axis=1)
  return np.reshape(transformed, shape_in).astype(np.float32)


def batch_apply_4x4(arrs, ms, are_points=True):
  """Applies a batch of 4x4 matrices to a batch of 3D points/vectors.

  Args:
    arrs: Numpy array with shape [bs, ..., 3].
    ms: Matrix with shape [bs, 4, 4].
    are_points: Boolean. Whether to treat arr as points or vectors.

  Returns:
    Numpy array with shape [bs, ..., 3].
  """

# Path: ldif/util/np_util.py
# def batch_np(arr, batch_size):
# def make_coordinate_grid(height, width, is_screen_space, is_homogeneous):
# def make_coordinate_grid_3d(length, height, width, is_screen_space,
#                             is_homogeneous):
# def filter_valid(mask, vals):
# def zero_by_mask(mask, vals, replace_with=0.0):
# def make_mask(im, thresh=0.0):
# def make_pixel_mask(im):
# def thresh_and_radius_to_distance(radius, thresh):
# def plot_rbfs_at_thresh(centers, radii, thresh=0.5):
# def plot_rbfs(centers, radii, scale=10.0):
# def cube_and_render(volume, thresh):
# def sample_surface(quadrics, centers, radii, length, height, width,
#                    renormalize):
# def visualize_prediction(quadrics,
#                          centers,
#                          radii,
#                          renormalize,
#                          thresh=0.0,
#                          input_volumes=None):
# 
# Path: ldif/util/file_util.py
# def readlines(p):
# def readbin(p):
# def writebin(p, s):
# def writetxt(p, s):
# def write_np(path, arr):
# def read_grd(path):
# def read_sif_v1(path, verbose=False):
# def read_lines(p):
# def read_image(p):
# def read_npz(p):
# def read_np(p):
# def read_txt_to_np(p):
# def read_py2_pkl(p):
# def write_mesh(path, mesh):
# def read_mesh(path):
# def read_csv(path):
# def read_normals(path_to_dir, im_count=20, leading='_depth'):
# def write_points(path_ext_optional, points):
# def write_grd(path, volume, world2grid=None):
# def write_depth_image(path, depth_image):


# Path: ldif/util/geom_util_np.py
import numpy as np
from ldif.util import np_util
from ldif.util.file_util import log


  Returns:
    Numpy array with shape [..., 3].
  """
  shape_in = arr.shape
  if are_points:
    hom = np.ones_like(arr[..., 0:1], dtype=np.float32)
  else:
    hom = np.zeros_like(arr[..., 0:1], dtype=np.float32)
  assert arr.shape[-1] == 3 + feature_count
  to_tx = np.concatenate([arr[..., :3], hom], axis=-1)
  to_tx = np.reshape(to_tx, [-1, 4])
  transformed = np.matmul(to_tx, m.T)[:, :3]
  if feature_count:
    flat_samples = np.reshape(arr[..., 3:], [-1, feature_count])
    transformed = np.concatenate([transformed, flat_samples], axis=1)
  return np.reshape(transformed, shape_in).astype(np.float32)


def batch_apply_4x4(arrs, ms, are_points=True):
  """Applies a batch of 4x4 matrices to a batch of 3D points/vectors.

  Args:
    arrs: Numpy array with shape [bs, ..., 3].
    ms: Matrix with shape [bs, 4, 4].
    are_points: Boolean. Whether to treat arr as points or vectors.

  Returns:
    Numpy array with shape [bs, ..., 3].
  """

  log.info('Input shapes to batch_apply_4x4: %s and %s' %