# 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
  flat_normal_len = int(np.prod(normal_shape))  # 1 if []
  normals = np.reshape(normals, [batch_size, flat_normal_len, 3])
  assert len(tx.shape) in [2, 3]
  assert tx.shape[-1] == 4
  assert tx.shape[-2] == 4
  if len(tx.shape) == 2:
    tx = np.tile(tx[np.newaxis, ...], [batch_size, 1, 1])
  assert tx.shape[0] == batch_size

  normals_invalid = np.all(np.equal(normals, 0.0), axis=-1)
  tx_invt = np.linalg.inv(np.transpose(tx, axes=[0, 2, 1]))
  transformed = batch_apply_4x4(normals, tx_invt)
  transformed[normals_invalid, :] = 0.0
  norm = np.linalg.norm(transformed, axis=-1, keepdims=True)
  log.info('Norm shape, transformed shape: %s %s' %
           (repr(norm.shape), repr(transformed.shape)))
  transformed /= norm + 1e-8
  return np.reshape(transformed, [batch_size] + normal_shape + [3])


def world_xyzn_im_to_pts(world_xyz, world_n):
  """Makes a 10K long XYZN pointcloud from an XYZ image and a normal image."""
  # world im  + world normals -> world points+normals
  is_valid = np.logical_not(np.all(world_xyz == 0.0, axis=-1))
  world_xyzn = np.concatenate([world_xyz, world_n], axis=-1)
  world_xyzn = world_xyzn[is_valid, :]
  world_xyzn = np.reshape(world_xyzn, [-1, 6])
  np.random.shuffle(world_xyzn)
  point_count = world_xyzn.shape[0]
  assert point_count > 0

# 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

  flat_normal_len = int(np.prod(normal_shape))  # 1 if []
  normals = np.reshape(normals, [batch_size, flat_normal_len, 3])
  assert len(tx.shape) in [2, 3]
  assert tx.shape[-1] == 4
  assert tx.shape[-2] == 4
  if len(tx.shape) == 2:
    tx = np.tile(tx[np.newaxis, ...], [batch_size, 1, 1])
  assert tx.shape[0] == batch_size

  normals_invalid = np.all(np.equal(normals, 0.0), axis=-1)
  tx_invt = np.linalg.inv(np.transpose(tx, axes=[0, 2, 1]))
  transformed = batch_apply_4x4(normals, tx_invt)
  transformed[normals_invalid, :] = 0.0
  norm = np.linalg.norm(transformed, axis=-1, keepdims=True)
  log.info('Norm shape, transformed shape: %s %s' %
           (repr(norm.shape), repr(transformed.shape)))
  transformed /= norm + 1e-8
  return np.reshape(transformed, [batch_size] + normal_shape + [3])


def world_xyzn_im_to_pts(world_xyz, world_n):
  """Makes a 10K long XYZN pointcloud from an XYZ image and a normal image."""
  # world im  + world normals -> world points+normals
  is_valid = np.logical_not(np.all(world_xyz == 0.0, axis=-1))
  world_xyzn = np.concatenate([world_xyz, world_n], axis=-1)
  world_xyzn = world_xyzn[is_valid, :]
  world_xyzn = np.reshape(world_xyzn, [-1, 6])
  np.random.shuffle(world_xyzn)
  point_count = world_xyzn.shape[0]
  assert point_count > 0

  log.info('The number of valid samples is: %i' % point_count)